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:
@@ -0,0 +1,33 @@
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
|
||||
vi.mock('./client', () => ({
|
||||
api: {
|
||||
get: vi.fn(),
|
||||
post: vi.fn(),
|
||||
put: vi.fn(),
|
||||
del: vi.fn()
|
||||
}
|
||||
}));
|
||||
|
||||
import { refetchAlbumCover, refetchMissingCovers } from './admin';
|
||||
import { api } from './client';
|
||||
|
||||
describe('admin covers API', () => {
|
||||
beforeEach(() => vi.clearAllMocks());
|
||||
|
||||
it('refetchAlbumCover POSTs to the correct path', async () => {
|
||||
(api.post as unknown as ReturnType<typeof vi.fn>).mockResolvedValueOnce({
|
||||
album_id: 'a1', cover_art_path: '/x.jpg', cover_art_source: 'mbcaa'
|
||||
});
|
||||
const got = await refetchAlbumCover('a1');
|
||||
expect(api.post).toHaveBeenCalledWith('/api/admin/albums/a1/cover/refetch', {});
|
||||
expect(got.cover_art_source).toBe('mbcaa');
|
||||
});
|
||||
|
||||
it('refetchMissingCovers POSTs to the bulk endpoint', async () => {
|
||||
(api.post as unknown as ReturnType<typeof vi.fn>).mockResolvedValueOnce({ queued: 7 });
|
||||
const got = await refetchMissingCovers();
|
||||
expect(api.post).toHaveBeenCalledWith('/api/admin/covers/refetch-missing', {});
|
||||
expect(got.queued).toBe(7);
|
||||
});
|
||||
});
|
||||
@@ -161,3 +161,23 @@ export function createQuarantineActionsQuery(limit: number = 50) {
|
||||
staleTime: 60_000
|
||||
});
|
||||
}
|
||||
|
||||
// Admin cover art ---------------------------------------------------------
|
||||
|
||||
export type RefetchAlbumCoverResponse = {
|
||||
album_id: string;
|
||||
cover_art_path: string | null;
|
||||
cover_art_source: string | null;
|
||||
};
|
||||
|
||||
export async function refetchAlbumCover(albumId: string): Promise<RefetchAlbumCoverResponse> {
|
||||
return api.post<RefetchAlbumCoverResponse>(`/api/admin/albums/${albumId}/cover/refetch`, {});
|
||||
}
|
||||
|
||||
export type RefetchMissingResponse = {
|
||||
queued: number;
|
||||
};
|
||||
|
||||
export async function refetchMissingCovers(): Promise<RefetchMissingResponse> {
|
||||
return api.post<RefetchMissingResponse>('/api/admin/covers/refetch-missing', {});
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ export type AlbumRef = {
|
||||
track_count: number;
|
||||
duration_sec: number;
|
||||
cover_url: string;
|
||||
cover_art_source: string | null;
|
||||
};
|
||||
|
||||
export type TrackRef = {
|
||||
|
||||
Reference in New Issue
Block a user