feat(web/m7-353): admin cover-refetch UI (per-album + bulk)
Adds cover_art_source to AlbumRef, two admin API helpers (refetchAlbumCover, refetchMissingCovers), a per-album retry button gated on is_admin in the album detail page, and a bulk-refetch section in the admin overview. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
import { Play, Shuffle } from 'lucide-svelte';
|
||||
import { page } from '$app/state';
|
||||
import { createAlbumQuery } from '$lib/api/queries';
|
||||
import { qk } from '$lib/api/queries';
|
||||
import { pageTitle } from '$lib/branding';
|
||||
import TrackRow from '$lib/components/TrackRow.svelte';
|
||||
import LibrarySkeleton from '$lib/components/LibrarySkeleton.svelte';
|
||||
@@ -12,6 +13,9 @@
|
||||
import { FALLBACK_COVER } from '$lib/media/covers';
|
||||
import type { ApiError } from '$lib/api/client';
|
||||
import { playQueue } from '$lib/player/store.svelte';
|
||||
import { user } from '$lib/auth/store.svelte';
|
||||
import { refetchAlbumCover } from '$lib/api/admin';
|
||||
import { useQueryClient } from '@tanstack/svelte-query';
|
||||
|
||||
const id = $derived(page.params.id ?? '');
|
||||
const queryStore = $derived(createAlbumQuery(id));
|
||||
@@ -58,6 +62,27 @@
|
||||
isStartingPlay = false;
|
||||
}
|
||||
}
|
||||
|
||||
const queryClient = useQueryClient();
|
||||
let refetching = $state(false);
|
||||
let refetchError = $state<string | null>(null);
|
||||
|
||||
const isAdmin = $derived(user.value?.is_admin === true);
|
||||
|
||||
async function onRefetchCover() {
|
||||
const data = query.data;
|
||||
if (!data || refetching) return;
|
||||
refetching = true;
|
||||
refetchError = null;
|
||||
try {
|
||||
await refetchAlbumCover(data.id);
|
||||
await queryClient.invalidateQueries({ queryKey: qk.album(data.id) });
|
||||
} catch (e) {
|
||||
refetchError = (e as { code?: string })?.code ?? 'refetch failed';
|
||||
} finally {
|
||||
refetching = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
@@ -127,6 +152,21 @@
|
||||
<Shuffle size={16} strokeWidth={1.5} />
|
||||
Shuffle
|
||||
</button>
|
||||
{#if isAdmin}
|
||||
<button
|
||||
type="button"
|
||||
onclick={onRefetchCover}
|
||||
disabled={refetching}
|
||||
aria-label={`Refetch cover for ${album.title}`}
|
||||
title={album.cover_art_source === 'none' ? 'No cover found previously — try again' : 'Refetch from MusicBrainz'}
|
||||
class="flex items-center gap-2 rounded-md border border-border bg-surface px-3 py-2 text-sm font-medium text-text-secondary hover:border-accent disabled:opacity-50"
|
||||
>
|
||||
Refetch cover
|
||||
</button>
|
||||
{/if}
|
||||
{#if refetchError}
|
||||
<span class="text-sm text-oxblood">{refetchError}</span>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
Reference in New Issue
Block a user