SCRUM-249 — AdminUI service detail charts¶
Plan ref: UI-4 (docs/11-admin-plane-plan.md). Stacked on SCRUM-248. Reads the
Dashboard series endpoint from SCRUM-236.
What exists¶
| Piece | Notes |
|---|---|
Route /dashboard/services/:name |
viewer; breadcrumb "Overview / |
| Range picker | 15m · 1h · 6h · 24h · 7d in the URL (?range=6h, optional ?to=), so a link reproduces the view; back button works |
| Charts | Traffic by status class, Latency p50/p95/p99, Error ratio, CPU, Memory, Go runtime (goroutines, heap in use, GC pause max as three small charts — the units cannot share an axis); each fetched concurrently, a failed one shows its own error + retry; "showing the last 7 days" when the server clamped |
TimeSeriesChart.vue |
uPlot 1.6.32 (new dependency, lockfile hand-merged to avoid unrelated churn); nulls are gaps; colours from new --ds-chart-1..6 tokens (light/dark), re-read on theme change; setData on updates; debounced ResizeObserver; y-axis sized to its longest label; legend below the canvas |
| Polling | every 30 s for ranges ≤ 6 h, paused on hidden tabs; none for 24 h / 7 d |
| Mock | series for every template and range, honouring the 1500-point cap and clamped |
How to verify¶
cd services/adminui
npm ci
npm run typecheck && npm run lint && npm run format:check && npx vitest run && npm run build
npx playwright test
Results at time of writing¶
- typecheck, lint, prettier, vitest (273 tests), build: pass; Playwright 10/10 incl. the card → detail navigation, range in the URL surviving a reload, and the 1500 × 4 latency chart's first render ≈ 319 ms (budget 500 ms).
- Screenshots checked in light and dark at 1440 px.
How it was built¶
DeepSeek run scoped (Landlock) to services/adminui (846 s, ~70k output tokens,
reasoning effort low); Claude installed uPlot beforehand. Claude review
(screenshots): every chart's legend was clipped by a fixed-height container (Traffic
showed three of its four series) and y-axis labels such as "0.70%" were cut at the
panel edge; the container now grows with the legend and the axis is sized to its
labels.