From 4254acf0b8bb60050c99746183bbd409c939d52b Mon Sep 17 00:00:00 2001 From: Chris Busillo Date: Sat, 6 Jun 2026 13:15:26 -0400 Subject: [PATCH] Render top routes progressively --- frontend/src/lib/api/placeholders.ts | 60 +++++++++++++++++++ .../workstation/HomeWorkbenchView.svelte | 16 +++-- frontend/src/routes/+page.svelte | 40 +------------ frontend/src/routes/completed/+page.svelte | 7 +-- frontend/src/routes/folders/+page.svelte | 25 +++++--- frontend/src/routes/ops/+page.svelte | 12 ++-- frontend/src/routes/settings/+page.svelte | 33 +++++++++- frontend/src/routes/settings/+page.ts | 30 ---------- 8 files changed, 123 insertions(+), 100 deletions(-) create mode 100644 frontend/src/lib/api/placeholders.ts delete mode 100644 frontend/src/routes/settings/+page.ts diff --git a/frontend/src/lib/api/placeholders.ts b/frontend/src/lib/api/placeholders.ts new file mode 100644 index 0000000..5fad80e --- /dev/null +++ b/frontend/src/lib/api/placeholders.ts @@ -0,0 +1,60 @@ +import type { + CompletedPayload, + DashboardFoldersPayload, + DashboardSummaryPayload, + HostsPayload, + QueueLane +} from './types'; + +const emptyQueueLane: QueueLane = { + running: [], + queued: [], + pending_review: [], + running_count: 0, + queued_count: 0, + pending_review_count: 0 +}; + +export const initialDashboard: DashboardSummaryPayload = { + folders_preview: [], + library_colors: {}, + scan_job: null, + calibration_queue: { + sample: emptyQueueLane, + full: emptyQueueLane, + active_count: 0 + }, + encode_queue: { + running_count: 0, + queued_count: 0, + running: [], + queued: [], + state: { is_paused: false, stop_requested: false, scheduler_summary: 'loading' } + }, + catalog_empty: false, + folder_cache_key: 'loading', + metric_support: { vmaf: false, xpsnr: false, ssim: false }, + metric_status_copy: 'loading' +}; + +export const initialFoldersPayload: DashboardFoldersPayload = { + folders: [], + series_folders: [], + folder_cache_key: 'loading', + catalog_empty: false +}; + +export const initialHosts: HostsPayload = { compact: true, hosts: [] }; + +export const initialCompleted: CompletedPayload = { + folders: [], + completed_count: 0, + folders_with_backups_count: 0, + archive_cleanup: { + archive_root: '', + file_count: 0, + total_size_bytes: 0, + has_cleanup: false + }, + history: [] +}; diff --git a/frontend/src/lib/components/workstation/HomeWorkbenchView.svelte b/frontend/src/lib/components/workstation/HomeWorkbenchView.svelte index 368244a..7bdfdc0 100644 --- a/frontend/src/lib/components/workstation/HomeWorkbenchView.svelte +++ b/frontend/src/lib/components/workstation/HomeWorkbenchView.svelte @@ -184,20 +184,22 @@ isFolderIndex ? `Matching ${folderScopeLabel.toLowerCase()}` : 'Workflow lanes' ); const visibleScopeSummary = $derived( - foldersPending && !isFolderIndex - ? 'Loading work folders' + foldersPending + ? isFolderIndex + ? `Loading ${folderScopeLabel.toLowerCase()}` + : 'Loading work folders' : `${visibleFolders.length.toLocaleString('en-US')} / ${folders.length.toLocaleString( 'en-US' )} ${isFolderIndex ? folderScopeLabel.toLowerCase() : 'folders'}` ); const visibleFoldersCopy = $derived( - foldersPending && !isFolderIndex ? 'loading' : visibleFolders.length.toLocaleString('en-US') + foldersPending ? 'loading' : visibleFolders.length.toLocaleString('en-US') ); const visiblePendingCopy = $derived( - foldersPending && !isFolderIndex ? 'loading' : visiblePendingItems.toLocaleString('en-US') + foldersPending ? 'loading' : visiblePendingItems.toLocaleString('en-US') ); const visibleReclaimCopy = $derived( - foldersPending && !isFolderIndex ? 'loading' : formatBytes(visibleProjectedReclaim) + foldersPending ? 'loading' : formatBytes(visibleProjectedReclaim) ); type LibraryOption = { @@ -742,7 +744,9 @@ {/each} {:else if foldersPending} - Loading folder worklist... + + {isFolderIndex ? 'Loading folder index...' : 'Loading folder worklist...'} + {:else} diff --git a/frontend/src/routes/+page.svelte b/frontend/src/routes/+page.svelte index 539e7ef..dae1294 100644 --- a/frontend/src/routes/+page.svelte +++ b/frontend/src/routes/+page.svelte @@ -1,6 +1,7 @@ @@ -34,8 +37,12 @@ Mediaforce Folders -{#if dashboard && foldersPayload && hosts} - -{:else} - -{/if} + diff --git a/frontend/src/routes/ops/+page.svelte b/frontend/src/routes/ops/+page.svelte index c901b23..de9ddf8 100644 --- a/frontend/src/routes/ops/+page.svelte +++ b/frontend/src/routes/ops/+page.svelte @@ -1,12 +1,12 @@ Mediaforce Settings - + diff --git a/frontend/src/routes/settings/+page.ts b/frontend/src/routes/settings/+page.ts deleted file mode 100644 index 454b68a..0000000 --- a/frontend/src/routes/settings/+page.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { fetchJson } from '$lib/api/client'; -import type { HostsPayload, SettingsPayload } from '$lib/api/types'; - -type SettledPayload = { data: T; error: null } | { data: null; error: string }; - -function errorMessage(error: unknown): string { - return error instanceof Error ? error.message : 'Request failed.'; -} - -async function settle(promise: Promise): Promise> { - try { - return { data: await promise, error: null }; - } catch (error) { - return { data: null, error: errorMessage(error) }; - } -} - -export async function load({ fetch }: { fetch: typeof window.fetch }) { - const [settings, hosts] = await Promise.all([ - settle(fetchJson('/api/settings?include_archive_cleanup=0', fetch)), - settle(fetchJson('/api/hosts?compact=1', fetch)) - ]); - const loadError = [settings.error, hosts.error].filter(Boolean).join(' · ') || null; - - return { - settings: settings.data, - hosts: hosts.data, - loadError - }; -}