Complete workflow navigation and document page groups
This commit is contained in:
@@ -291,7 +291,7 @@
|
||||
<BackLink fallback={basePath} />
|
||||
|
||||
{#if scopeComplete}<div class="scope-complete" role="status"><strong>Scope saved.</strong> {scopeComplete.composed ? `Intended configuration may change on ${scopeComplete.count} eligible servers.` : scopeComplete.detached ? `Inventory tracking detached on ${scopeComplete.detached} servers; live files remain.` : `${scopeComplete.count} servers are in the old or new scope.`} Maintenance detects resulting drift and rebuilds eligible servers when automation is enabled. <a href={scopeComplete.href}>View drift recovery →</a></div>{/if}
|
||||
{#if latestVersion}<Card padding="lg"><div class="release-summary"><div><h2>Latest {artifactVersionLabel(latestVersion)}</h2><StatusBadge state={latestVersion.id === a.current_version_id ? 'promoted' : latestVersion.state} /><p>{latestVersion.notes || 'No version notes provided.'}</p></div>{#if runningBetaId !== null}<Button variant="primary" href={contextHref(`/betas/${runningBetaId}`, $page.url)}>View active beta</Button>{:else if latestVersion.id !== a.current_version_id}<Button variant="primary" href={betaSelectionHref([{ scriptId: id, versionId: latestVersion.id }])}>Test latest version</Button>{:else}<span class="dim">Latest version is promoted</span>{/if}</div></Card>{/if}
|
||||
{#if latestVersion}<Card padding="lg"><div class="release-summary"><div><h2>Latest {artifactVersionLabel(latestVersion)}</h2><StatusBadge state={latestVersion.id === a.current_version_id ? 'promoted' : latestVersion.state} /><p>{latestVersion.notes || 'No version notes provided.'}</p></div>{#if runningBetaId !== null}<Button variant="primary" href={contextHref(`/betas/${runningBetaId}`, $page.url)}>View active beta</Button>{:else if latestVersion.id !== a.current_version_id}<Button variant="primary" href={contextHref(betaSelectionHref([{ scriptId: id, versionId: latestVersion.id }]), $page.url)}>Test latest version</Button>{:else}<span class="dim">Latest version is promoted</span>{/if}</div></Card>{/if}
|
||||
|
||||
{#if runningBetaId}
|
||||
<div class="warn-banner">
|
||||
@@ -382,7 +382,7 @@
|
||||
<Badge variant="online" size="sm">Promoted</Badge>
|
||||
{:else}
|
||||
<StatusBadge state={v.state} size="sm" />
|
||||
{#if runningBetaId === null}<Button size="sm" href={betaSelectionHref([{scriptId:id,versionId:v.id}])}>Test version</Button>{/if}
|
||||
{#if runningBetaId === null}<Button size="sm" href={contextHref(betaSelectionHref([{scriptId:id,versionId:v.id}]), $page.url)}>Test version</Button>{/if}
|
||||
{/if}
|
||||
<details class="version-technical"><summary>File details</summary><span>SHA-256: {v.sha256}</span><span>Size: {v.size.toLocaleString()} bytes</span></details>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { contextHref, safeReturnHref } from '$lib/navigation-context.js';
|
||||
import BackLink from '$ui/components/BackLink.svelte';
|
||||
import Breadcrumbs from '$ui/components/primitives/Breadcrumbs.svelte';
|
||||
import { timeFormat } from '$ui/stores/time-zone.js';
|
||||
import { onMount, tick } from 'svelte';
|
||||
import { beforeNavigate, goto } from '$app/navigation';
|
||||
@@ -167,14 +171,16 @@
|
||||
const response=await fetch('/api/betas',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({scripts:picks.map(p=>({scriptId:p.scriptId,scriptVersionId:p.versionId})),servers:[...pickedServers],testPlan:parseBetaPlan(testPlan),notes:betaLabel.trim()||undefined,waitForHealth:true,waitForMatch:false})}), body=await response.json();
|
||||
if(!response.ok||!body.ok)throw new Error(body.error??'Could not start beta. Review the selected versions and servers.');
|
||||
draftReady=false;try{localStorage.removeItem(betaDraftKey);}catch{}allowLeave=true;
|
||||
await goto(`/betas/${body.result.betaId}`);
|
||||
await goto(contextHref(`/betas/${body.result.betaId}`, safeReturnHref($page.url.searchParams.get('returnTo'), '/betas')));
|
||||
}catch(error){flash=(error as Error).message;}finally{openingBeta=false;}
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:head><title>New beta | Electric Cherry</title></svelte:head>
|
||||
<div class="page">
|
||||
<SectionHeader title="New beta" subtitle="Choose exact file versions and test servers, then review before starting.">{#snippet actions()}<Button href="/betas" variant="ghost">Back to betas</Button>{/snippet}</SectionHeader>
|
||||
<Breadcrumbs items={[{ label: 'Betas', href: '/betas' }, { label: 'New beta' }]} />
|
||||
<BackLink fallback="/betas" />
|
||||
<SectionHeader title="New beta" subtitle="Choose exact file versions and test servers, then review before starting." />
|
||||
{#if flash}<div class="ui-error" role="alert">{flash}{#if !scripts.length}<Button size="sm" onclick={()=>initialize()}>Retry</Button>{/if}</div>{/if}
|
||||
{#if $fleetError}<div class="ui-error" role="alert">{$fleetError}<Button size="sm" onclick={() => refreshFleet(true)}>Retry servers</Button></div>{/if}
|
||||
{#if notice}<p role="status" class="notice">{notice}</p>{/if}
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
interface Detail {
|
||||
deployment: {
|
||||
id: string; action: string; started_at: string;
|
||||
finished_at: string | null; triggered_by: string | null;
|
||||
finished_at: string | null; triggered_by: string | null; beta_id?: number | null;
|
||||
};
|
||||
servers: ServerRow[];
|
||||
files: FileRow[];
|
||||
@@ -149,6 +149,7 @@
|
||||
</section>
|
||||
|
||||
{#if detail.watchdogIncidentId}<p class="watchdog-source">Started by Maintenance · <a href={contextHref(`/maintenance/${encodeURIComponent(detail.watchdogIncidentId)}`, $page.url)}>View incident and recovery history</a></p>{/if}
|
||||
{#if detail.deployment.beta_id}<p class="watchdog-source">Started from <a href={contextHref(`/betas/${detail.deployment.beta_id}`, $page.url)}>Beta #{detail.deployment.beta_id}</a> · Review its files, checks, and test servers.</p>{/if}
|
||||
|
||||
{#if detail.servers.some(server => !server.server_deleted_at && ['held', 'manual'].includes(server.restart_state))}
|
||||
<div><Button onclick={resume} loading={resuming} disabled={resuming}>Resume when empty</Button><p>Apply held changes and restart after the safety checks pass.</p></div>
|
||||
|
||||
Reference in New Issue
Block a user