Add operation flows and activity logs for betas and campaigns
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
<script lang="ts">
|
||||
import type { ActivityEvent, OperationStep } from '$lib/operation-flow.js';
|
||||
let { steps, events, active = false }: { steps: OperationStep[]; events: ActivityEvent[]; active?: boolean } = $props();
|
||||
</script>
|
||||
|
||||
<section>
|
||||
<h2>Operation flow</h2>
|
||||
<ol class="flow">
|
||||
{#each steps as step, index}
|
||||
<li class={step.state} aria-current={step.state === 'current' ? 'step' : undefined}>
|
||||
<span>{index + 1}</span>{step.label}
|
||||
<span class="sr-only">({step.state})</span>
|
||||
</li>
|
||||
{/each}
|
||||
</ol>
|
||||
</section>
|
||||
<section>
|
||||
<div class="top"><h2>Activity</h2>{#if active}<span class="muted">Updates automatically</span>{/if}</div>
|
||||
{#if events.length}
|
||||
<ol class="timeline">
|
||||
{#each events as event (event.id)}
|
||||
<li><time datetime={event.created_at}>{new Date(event.created_at).toLocaleString()}</time><p>{event.message}</p></li>
|
||||
{/each}
|
||||
</ol>
|
||||
{:else}
|
||||
<p class="muted">This operation predates detailed activity tracking. Its recorded status and timestamps are shown on this page.</p>
|
||||
{/if}
|
||||
</section>
|
||||
|
||||
<style>
|
||||
section { display: grid; gap: 16px; }
|
||||
h2 { font-size: 18px; margin: 0; }
|
||||
.top { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
|
||||
time, .muted { color: var(--text-secondary); font-size: 13px; }
|
||||
p { margin: 0; line-height: 1.6; }
|
||||
.flow { display: flex; flex-wrap: wrap; gap: 12px; padding: 0; margin: 0; list-style: none; }
|
||||
.flow li { display: flex; align-items: center; gap: 10px; background: var(--surface); border-radius: 8px; padding: 12px; font-size: 13px; border: 1px solid var(--border-subtle); color: var(--text-secondary); }
|
||||
.flow span { color: var(--accent-primary-hover); font-family: var(--font-mono); }
|
||||
.flow .done { color: var(--text-primary); }
|
||||
.flow .current { color: var(--text-primary); border-color: var(--accent-primary); }
|
||||
.flow .failed { color: var(--state-danger); border-color: var(--state-danger); }
|
||||
.timeline { list-style: none; padding: 0 0 0 18px; margin: 0; border-left: 2px solid var(--border-strong); }
|
||||
.timeline li { position: relative; padding: 0 0 24px 12px; overflow-wrap: anywhere; }
|
||||
.timeline li::before { content: ''; position: absolute; left: -24px; top: 5px; width: 10px; height: 10px; border-radius: 50%; background: var(--accent-primary); }
|
||||
.timeline p { margin-top: 6px; }
|
||||
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
|
||||
</style>
|
||||
Reference in New Issue
Block a user