New web/ SPA (React 18 + Vite 5 + TypeScript + React Flow + dagre, all pinned, no CDN). Dark, three-pane layout: summary top bar, filterable task list, center auto-laid pipeline map, and a right drawer showing a selected task's history through each node (timeline with timestamps/duration/cost + Q&A/verdicts/plan). Map nodes color by live state, loop-backs render dashed, clicking a node filters the list, selecting a task highlights its path. Polls /api/state every 4s; topology fetched once. dist/ is gitignored (built on the Mac, rsynced).
42 lines
1.5 KiB
TypeScript
42 lines
1.5 KiB
TypeScript
import type { StateResponse } from "../api";
|
||
|
||
interface Props {
|
||
state: StateResponse | null;
|
||
connected: boolean;
|
||
generatedAt: string | null;
|
||
}
|
||
|
||
const CHIPS: Array<{ key: keyof StateResponse["summary"]; label: string; cls: string }> =
|
||
[
|
||
{ key: "active", label: "Active", cls: "active" },
|
||
{ key: "waiting", label: "Awaiting human", cls: "waiting" },
|
||
{ key: "parked", label: "Parked", cls: "parked" },
|
||
{ key: "open_questions", label: "Open questions", cls: "open" },
|
||
{ key: "total", label: "Total", cls: "total" },
|
||
];
|
||
|
||
// Top status bar: summary chips, a connection/health dot, and the snapshot clock.
|
||
export function TopBar({ state, connected, generatedAt }: Props) {
|
||
const summary = state?.summary;
|
||
return (
|
||
<header className="topbar" role="banner">
|
||
<div className="brand">
|
||
<span className="brand-dot" aria-hidden />
|
||
<span className="brand-name">agent-team</span>
|
||
<span className="brand-sub">pipeline</span>
|
||
</div>
|
||
<div className="chips" role="list">
|
||
{CHIPS.map((c) => (
|
||
<div className={`chip chip-${c.cls}`} role="listitem" key={c.key}>
|
||
<span className="chip-num">{summary ? summary[c.key] : "–"}</span>
|
||
<span className="chip-lbl">{c.label}</span>
|
||
</div>
|
||
))}
|
||
</div>
|
||
<div className="health" title={connected ? "live" : "disconnected"}>
|
||
<span className={`health-dot ${connected ? "ok" : "down"}`} aria-hidden />
|
||
<span className="health-clock">{generatedAt ?? "—"}</span>
|
||
</div>
|
||
</header>
|
||
);
|
||
}
|