Surfaces client-reported playback failures from /api/admin/playback-errors
in a new admin tab. Tabs: Unresolved (default) / Resolved. Each row
shows track + artist + album, error kind badge, who hit it, when,
optional client-supplied detail, and the absolute file path so the
operator can grep the library mount without leaving the page.
Per-row actions (RowActionsMenu):
- Resolve (primary) — modal with Fixed / Ignored dropdown for the
"no further action taken" cases.
- Copy — JSON payload to clipboard with track_id / file_path / kind
/ detail / reporter / client_id / occurred_at. Matches the
operator's "logs with a copy-out function" ask.
- Delete file (danger, modal-confirm) — uses the existing
/api/admin/quarantine/{track_id}/delete-file endpoint AND
auto-stamps resolution='deleted' so a single click closes both
the file and the inbox row.
Deferred to a follow-up: Hide (the existing quarantine flow is
per-user-flag, not a true library-hide), and Re-request via Lidarr
(needs album MBID join — not in the current ListAdminPlaybackErrors
projection).
Also: admin tab list grows from five to six; AdminTabs.test.ts
updated.
This commit is contained in:
@@ -3,6 +3,7 @@ import { api } from './client';
|
||||
import { qk } from './queries';
|
||||
import type {
|
||||
ActionResult,
|
||||
AdminPlaybackError,
|
||||
AdminQuarantineRow,
|
||||
LidarrConfig,
|
||||
LidarrMetadataProfile,
|
||||
@@ -11,7 +12,8 @@ import type {
|
||||
LidarrRequest,
|
||||
LidarrRequestStatus,
|
||||
LidarrRootFolder,
|
||||
LidarrTestResult
|
||||
LidarrTestResult,
|
||||
PlaybackErrorResolution
|
||||
} from './types';
|
||||
|
||||
// Admin Lidarr config -----------------------------------------------------
|
||||
@@ -174,6 +176,34 @@ export function createQuarantineActionsQuery(limit: number = 50) {
|
||||
});
|
||||
}
|
||||
|
||||
// Admin playback errors ---------------------------------------------------
|
||||
|
||||
export async function listAdminPlaybackErrors(
|
||||
resolved: boolean = false
|
||||
): Promise<AdminPlaybackError[]> {
|
||||
return api.get<AdminPlaybackError[]>(
|
||||
`/api/admin/playback-errors?resolved=${resolved}`
|
||||
);
|
||||
}
|
||||
|
||||
export async function resolvePlaybackError(
|
||||
id: string,
|
||||
resolution: PlaybackErrorResolution
|
||||
): Promise<{ id: string }> {
|
||||
return api.post<{ id: string }>(
|
||||
`/api/admin/playback-errors/${id}/resolve`,
|
||||
{ resolution }
|
||||
);
|
||||
}
|
||||
|
||||
export function createAdminPlaybackErrorsQuery(resolved: boolean = false) {
|
||||
return createQuery({
|
||||
queryKey: qk.adminPlaybackErrors(resolved),
|
||||
queryFn: () => listAdminPlaybackErrors(resolved),
|
||||
staleTime: 30_000
|
||||
});
|
||||
}
|
||||
|
||||
// Admin cover art ---------------------------------------------------------
|
||||
|
||||
export type RefetchAlbumCoverResponse = {
|
||||
|
||||
Reference in New Issue
Block a user