Improve operational UX, recovery flows, and action safety
Implement the approved UX review across Fleet, Betas, Library, deployments, and Settings. Add reviewed promotion and reconciliation plans, atomic queued-removal cancellation, recoverable beta drafts and launch inputs, accessible controls, and mobile improvements. Validated with 473 tests, a clean typecheck, production build, and isolated desktop/mobile browser walkthroughs. Include the review and implementation coverage notes.
This commit is contained in:
@@ -31,5 +31,9 @@ export async function GET({ params }: { params: { id: string } }) {
|
||||
const servers = listBetaServers(id);
|
||||
|
||||
const events = db().prepare('SELECT id, created_at, message FROM beta_events WHERE beta_id = ? ORDER BY id').all(id);
|
||||
return json({ beta, scripts, servers, events, test: testView(id) });
|
||||
const rollout = db().prepare("SELECT id FROM deployments WHERE beta_id = ? AND action = 'promote' ORDER BY started_at DESC LIMIT 1").get(id) as { id: string } | undefined;
|
||||
const promotion = rollout ? { ...rollout,
|
||||
pending: (db().prepare("SELECT COUNT(*) n FROM deployment_servers WHERE deployment_id = ? AND restart_state NOT IN ('done','failed','cancelled')").get(rollout.id) as { n: number }).n,
|
||||
failed: (db().prepare("SELECT COUNT(*) n FROM deployment_servers WHERE deployment_id = ? AND restart_state = 'failed'").get(rollout.id) as { n: number }).n } : null;
|
||||
return json({ beta, scripts, servers, events, test: testView(id), promotion });
|
||||
}
|
||||
|
||||
@@ -1,16 +1,28 @@
|
||||
import { json } from '@sveltejs/kit';
|
||||
import { promoteBeta, BetaError } from '$lib/server/fleet/beta.js';
|
||||
import { promoteBeta, previewBetaPromotion, BetaError } from '$lib/server/fleet/beta.js';
|
||||
|
||||
function parseId(raw: string): number | null {
|
||||
const n = Number.parseInt(raw, 10);
|
||||
return Number.isFinite(n) ? n : null;
|
||||
}
|
||||
|
||||
export async function POST({ params }: { params: { id: string } }) {
|
||||
export async function GET({ params }: { params: { id: string } }) {
|
||||
const id = parseId(params.id);
|
||||
if (id === null) return json({ ok: false, error: 'Invalid beta ID.' }, { status: 400 });
|
||||
try { return json({ preview: previewBetaPromotion(id) }, { headers: { 'Cache-Control': 'no-store' } }); }
|
||||
catch (err) {
|
||||
if (err instanceof BetaError) return json({ error: err.message }, { status: 409 });
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST({ params, request }: { params: { id: string }; request: Request }) {
|
||||
const id = parseId(params.id);
|
||||
if (id === null) return json({ ok: false, error: 'bad id' }, { status: 400 });
|
||||
const body = await request.json().catch(() => null);
|
||||
if (typeof body?.previewToken !== 'string') return json({ ok: false, error: 'Review promotion targets before confirming.' }, { status: 400 });
|
||||
try {
|
||||
const result = await promoteBeta(id);
|
||||
const result = await promoteBeta(id, body.previewToken);
|
||||
return json({ ok: true, result });
|
||||
} catch (err) {
|
||||
if (err instanceof BetaError) {
|
||||
|
||||
Reference in New Issue
Block a user