Fix provisioning detail breadcrumbs (Refs #84)

This commit is contained in:
2026-10-09 11:43:07 -04:00
parent 43c1a32065
commit c443ffa0dc
+4 -11
View File
@@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { safeReturnHref, returnLabel, contextHref } from '$lib/navigation-context.js'; import { contextHref } from '$lib/navigation-context.js';
import { onDestroy, onMount, untrack } from 'svelte'; import { onDestroy, onMount, untrack } from 'svelte';
import { page } from '$app/stores'; import { page } from '$app/stores';
import type { PageData } from './$types'; import type { PageData } from './$types';
@@ -9,7 +9,7 @@
import { serverTitle } from '$ui/server-labels.js'; import { serverTitle } from '$ui/server-labels.js';
import { createProvisioningRefresh, type ProvisioningRefreshState } from '$ui/provisioning-refresh.js'; import { createProvisioningRefresh, type ProvisioningRefreshState } from '$ui/provisioning-refresh.js';
import { confirmAction } from '$ui/confirm.js'; import { confirmAction } from '$ui/confirm.js';
import { elapsedTime, isProvisioningDetail, provisioningOutcome, provisioningRequester, provisioningReturn } from '$ui/provisioning-presentation.js'; import { elapsedTime, isProvisioningDetail, provisioningOutcome, provisioningRequester } from '$ui/provisioning-presentation.js';
import SectionHeader from '$ui/components/primitives/SectionHeader.svelte'; import SectionHeader from '$ui/components/primitives/SectionHeader.svelte';
import Breadcrumbs from '$ui/components/primitives/Breadcrumbs.svelte'; import Breadcrumbs from '$ui/components/primitives/Breadcrumbs.svelte';
import StatusBadge from '$ui/components/primitives/StatusBadge.svelte'; import StatusBadge from '$ui/components/primitives/StatusBadge.svelte';
@@ -43,13 +43,6 @@
const finishedAt = $derived(timestampISO(deployment?.finished_at)); const finishedAt = $derived(timestampISO(deployment?.finished_at));
const canOverride = $derived(data.user?.role === 'admin' && detail?.canOverrideSafety); const canOverride = $derived(data.user?.role === 'admin' && detail?.canOverrideSafety);
const outcome = $derived(detail ? provisioningOutcome(detail) : null); const outcome = $derived(detail ? provisioningOutcome(detail) : null);
const returnTo = $derived.by(() => {
const requested = $page.url.searchParams.get('returnTo');
if (requested) { const href = safeReturnHref(requested, '/provisioning'); return { href, label: returnLabel(href) }; }
if (detail?.collection) return { href: `/collections/launches/${encodeURIComponent(detail.collection.id)}`, label: `Back to ${detail.collection.name}` };
if (detail?.sources.length === 1 && detail.sources[0].href) return { href: detail.sources[0].href, label: `Back to ${detail.sources[0].label}` };
return provisioningReturn(null);
});
const serverHref = $derived(deployment && deployment.server_exists && !deployment.server_deleted_at ? `/servers/${encodeURIComponent(deployment.server)}` : null); const serverHref = $derived(deployment && deployment.server_exists && !deployment.server_deleted_at ? `/servers/${encodeURIComponent(deployment.server)}` : null);
const recipeStatus = $derived(detail?.progress?.recipeStatus ?? null); const recipeStatus = $derived(detail?.progress?.recipeStatus ?? null);
const recipeHeading = $derived(recipeStatus === 'queued' ? 'Setup captured when queued' : recipeStatus === 'attempted' ? 'Files selected for this attempt' : 'Recorded launch files'); const recipeHeading = $derived(recipeStatus === 'queued' ? 'Setup captured when queued' : recipeStatus === 'attempted' ? 'Files selected for this attempt' : 'Recorded launch files');
@@ -103,7 +96,7 @@
<div class="page"> <div class="page">
<SectionHeader title={deployment ? `${actionLabels[deployment.action]} · ${serverTitle(deployment.server)}` : 'Provisioning operation'} subtitle={deployment?.server}> <SectionHeader title={deployment ? `${actionLabels[deployment.action]} · ${serverTitle(deployment.server)}` : 'Provisioning operation'} subtitle={deployment?.server}>
{#snippet crumbs()}<Breadcrumbs items={[{ label: 'Activity', href: '/activity' }, { label: 'Operation' }]} />{/snippet} {#snippet crumbs()}<Breadcrumbs items={[{ label: 'Provisioning', href: '/provisioning' }, { label: 'Operation' }]} />{/snippet}
{#snippet actions()}{#if serverHref}<Button href={serverHref}>View server</Button>{/if}{/snippet} {#snippet actions()}{#if serverHref}<Button href={serverHref}>View server</Button>{/if}{/snippet}
</SectionHeader> </SectionHeader>
{#if deployment && outcome} {#if deployment && outcome}
@@ -118,7 +111,7 @@
{/if} {/if}
<div class="identity-row"> <div class="identity-row">
{#if deployment}<div class="operation-id"><span>Operation</span><CopyValue value={deployment.id} label="operation ID" /></div>{/if} {#if deployment}<div class="operation-id"><span>Operation</span><CopyValue value={deployment.id} label="operation ID" /></div>{/if}
<div class="identity-links"><a href={returnTo.href}>← {returnTo.label}</a><Button size="sm" variant="ghost" onclick={copyLink}>Copy link</Button>{#if copyStatus}<span role="status">{copyStatus}</span>{/if}</div> <div class="identity-links"><Button size="sm" variant="ghost" onclick={copyLink}>Copy link</Button>{#if copyStatus}<span role="status">{copyStatus}</span>{/if}</div>
</div> </div>
<Freshness updatedAt={view.refreshedAt ? Date.parse(view.refreshedAt) : null} error={view.loadError ? 'Operation updates interrupted.' : ''} intervalLabel="Updates every 5 seconds" onRetry={() => void controller.forceRefresh()} retryDisabled={view.refreshing || !!view.busy} /> <Freshness updatedAt={view.refreshedAt ? Date.parse(view.refreshedAt) : null} error={view.loadError ? 'Operation updates interrupted.' : ''} intervalLabel="Updates every 5 seconds" onRetry={() => void controller.forceRefresh()} retryDisabled={view.refreshing || !!view.busy} />