From 6298c7d21c6ab443250cb2e6397c5d214607e2fb Mon Sep 17 00:00:00 2001 From: MechaCat02 Date: Sun, 7 Jun 2026 21:07:36 +0200 Subject: [PATCH] fix(dashboard): F-U-009 add download link + copy-id button per file row MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Listing showed name/content-type/size/created/id; only mutation was Delete. No download link, no copy-id button (the UUID was rendered unclickable), no preview, no metadata refresh. Operators had to use the admin API directly. - Add api.files.downloadUrl(slug, collection, id) helper that builds the admin GET URL. The anchor uses HTML `download` so the browser saves with the original filename. - Add a ⧉ copy-id button next to the UUID column using navigator.clipboard.writeText. Silently no-ops where the browser doesn't expose clipboard (plain-http LAN). - Preview / metadata-refresh are deferred to a UI overhaul. AUDIT.md anchor: F-U-009 (partial — download + copy; preview deferred). Co-Authored-By: Claude Opus 4.7 (1M context) --- dashboard/src/lib/api.ts | 6 ++++- .../src/routes/apps/[slug]/files/+page.svelte | 25 ++++++++++++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/dashboard/src/lib/api.ts b/dashboard/src/lib/api.ts index 770f609..0be7376 100644 --- a/dashboard/src/lib/api.ts +++ b/dashboard/src/lib/api.ts @@ -907,7 +907,11 @@ export const api = { adminRequest( `/api/v1/admin/apps/${encodeURIComponent(idOrSlug)}/files/${encodeURIComponent(collection)}/${fileId}`, { method: 'DELETE' } - ) + ), + /// F-U-009: build the admin download URL. GET returns the file + /// bytes inline; the browser handles content-disposition. + downloadUrl: (idOrSlug: string, collection: string, fileId: string): string => + `/api/v1/admin/apps/${encodeURIComponent(idOrSlug)}/files/${encodeURIComponent(collection)}/${fileId}` }, secrets: { diff --git a/dashboard/src/routes/apps/[slug]/files/+page.svelte b/dashboard/src/routes/apps/[slug]/files/+page.svelte index 0a37797..352e4dc 100644 --- a/dashboard/src/routes/apps/[slug]/files/+page.svelte +++ b/dashboard/src/routes/apps/[slug]/files/+page.svelte @@ -91,6 +91,12 @@ return new Date(iso).toLocaleString(); } + // F-U-009: best-effort clipboard copy; silently no-ops where the + // browser doesn't expose navigator.clipboard (e.g. plain-http LAN). + function copyToClipboard(text: string) { + void navigator.clipboard?.writeText(text); + } + function fmtSize(bytes: number): string { if (bytes < 1024) return `${bytes} B`; if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`; @@ -180,8 +186,25 @@ {f.content_type} {fmtSize(f.size)} {fmtTime(f.created_at)} - {f.id} + + {f.id} + + + + Download +