Web dashboard step 3: overview, runs and articles pages
Fill in the dashboard read pages of the web dashboard plan (§9): the overview card set (last run from report_json, budget today per provider, ratings this week, unrated picks with the rating widget, jobs summary, config-on-disk warnings), the runs list and run detail (funnel, admission mix, preference state, timings, provider usage, warnings, top feeds, config diff against the previous non-dry run, near misses, and the candidates table with allow-listed filters/sorts and per-row signals), and the articles list and article detail (assessments including provider rejections, run history, neighbours and interests, embedding metadata, rating events, and the text explain). Dynamic list queries go through AssertSqlSafe with SQL built only from constants and allow-listed fragments; every user value is bound. Adds the shared signals-table, candidate-row and pager partials, a CSS block and the data-filter table behaviour in app.js, plus the step 3 handoff. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NHyYupFdBiR4VfoUM7NjSM
This commit is contained in:
@@ -57,3 +57,36 @@ thead { position:sticky; top:0; background:var(--bg); }
|
||||
.rating-prompt { margin-right:.25rem; }
|
||||
.rating-note { flex-basis:100%; }
|
||||
@media (max-width:40rem) { .masthead { font-size:1.55rem; } .kv { display:block; } }
|
||||
/* step 3: dashboard reads (overview, runs, articles) */
|
||||
.dashboard h1 { font-size:1.5rem; margin:.5rem 0; }
|
||||
.dashboard h1 a { color:inherit; }
|
||||
.dashboard h2 { font-size:1.1rem; margin:1.75rem 0 .5rem; }
|
||||
.dashboard h3 { font-size:1rem; margin:.5rem 0; }
|
||||
.dashboard table td { vertical-align:top; }
|
||||
.cards { display:grid; grid-template-columns:repeat(auto-fit,minmax(20rem,1fr)); gap:1rem; margin:1rem 0; }
|
||||
.card { border:1px solid var(--rule); padding:.75rem 1rem; min-width:0; }
|
||||
.card h2 { margin-top:0; }
|
||||
.block { white-space:pre-wrap; overflow-wrap:anywhere; font:.85rem/1.4 ui-monospace,SFMono-Regular,Menlo,monospace; margin:.5rem 0; }
|
||||
.muted { color:var(--muted); }
|
||||
.num { text-align:right; font-variant-numeric:tabular-nums; white-space:nowrap; }
|
||||
.filters { display:flex; flex-wrap:wrap; gap:.5rem 1rem; align-items:end; margin:1rem 0; }
|
||||
.filters label { font-size:.85rem; }
|
||||
.filters input,.filters select { padding:.3rem; font-size:.9rem; }
|
||||
.run-nav { display:flex; flex-wrap:wrap; gap:1.5rem; margin:.5rem 0 1rem; }
|
||||
.funnel-cell { min-width:12rem; width:40%; }
|
||||
.funnel svg { display:block; }
|
||||
.funnel-table .reasons { color:var(--muted); font-size:.8rem; }
|
||||
.badge.reason,.badge.running,.badge.requested { color:var(--muted); }
|
||||
.badge.ok { color:var(--loved); } .badge.degraded { color:var(--good); } .badge.failed,.badge.dry_run { color:var(--down); }
|
||||
.pager { display:flex; flex-wrap:wrap; gap:1rem; margin:1rem 0; align-items:center; }
|
||||
details.signals summary { cursor:pointer; }
|
||||
details.signals summary a { display:inline; }
|
||||
.signals-body { margin:.5rem 0 .5rem 1rem; font-size:.85rem; }
|
||||
.signals-body table { width:auto; }
|
||||
.signals-body tr.muted td { color:var(--muted); }
|
||||
details.explain { margin:1rem 0; }
|
||||
.diff .before { color:var(--down); } .diff .after { color:var(--loved); }
|
||||
.picks,.jobs,.warnings { list-style:none; padding:0; }
|
||||
.picks li { border-bottom:1px solid var(--rule); padding:.5rem 0; }
|
||||
.budget meter { width:60%; max-width:14rem; height:.8rem; vertical-align:middle; margin-right:.5rem; }
|
||||
.table-filter { margin:.5rem 0; padding:.3rem; width:20rem; max-width:100%; }
|
||||
|
||||
Reference in New Issue
Block a user