import { type JSX, Show } from "solid-js"; import { fmtDuration } from "../../format"; import { isFetching, lastTickAt, lastTickError, statusResource } from "../../state"; import { EVENT_STATE_ORDER } from "../../types"; // Ported verbatim from Header.tsx (dissolved). function relativeAgo(ms: number): string { const seconds = Math.max(0, (Date.now() - ms) / 1000); if (seconds < 5) return "just now"; return `${fmtDuration(seconds)} ago`; } const STATE_TONE: Record = { queued: "var(--color-info)", running: "var(--color-warn)", done: "var(--color-ok)", failed: "var(--color-err)", skipped: "var(--color-ink-300)", }; export function Vitals(): JSX.Element { const runtime = () => statusResource()?.runtime; // issue_event_counts ?? event_counts — preserves the Stats.tsx accessor + title. const counts = (): Record => { const status = statusResource(); if (!status) return { queued: 0, running: 0, done: 0, failed: 0, skipped: 0 }; return status.issue_event_counts ?? status.event_counts; }; // Match the pipeline derivation: running_events and the inflight snapshot overlap // (the worker pool keys inflight by `issue_key || delivery_id`), so union by // that same key instead of summing lengths — otherwise one live job counts as two. const runningTotal = (): number => { const s = statusResource(); if (!s) return 0; const keys = new Set(s.running_events.map((e) => e.issue_key ?? e.delivery_id)); for (const key of s.inflight) keys.add(key); return keys.size; }; const failedCount = (): number => counts().failed ?? 0; const allowlist = (): string => { const list = runtime()?.repo_allowlist; return list && list.length ? list.join(", ") : "(none)"; }; const syncTone = (): string => { if (lastTickError()) return "err"; if (isFetching()) return "warn"; return "ok"; }; const syncText = (): string => { if (lastTickError()) return lastTickError()!; if (isFetching()) return "syncing…"; return `synced ${relativeAgo(lastTickAt())}`; }; return (
{/* health / sync */}
{syncText()}} > {syncText()}
{/* big running / failed */}
running 0 ? " running-nonzero" : "" }`} > {runningTotal()}
failed 0 ? " failed-nonzero" : "" }`} > {failedCount()}
{/* 5 state counts (compact 2-col) */}
{EVENT_STATE_ORDER.map((state) => (
{state} {counts()[state] ?? 0}
))}
{/* runtime meta */}
); } interface RuntimeRowProps { label: string; value?: string; mono?: boolean; title?: string; } function RuntimeRow(props: RuntimeRowProps): JSX.Element { return (
{props.label} {props.value ?? "—"}
); }