Skip to content

Make the public board work for a visitor, and look like a status board - #7

Merged
tschm merged 1 commit into
mainfrom
fix/public-drilldown-links
Aug 29, 2026
Merged

Make the public board work for a visitor, and look like a status board#7
tschm merged 1 commit into
mainfrom
fix/public-drilldown-links

Conversation

@tschm

@tschm tschm commented Aug 29, 2026

Copy link
Copy Markdown
Member

The bug

Clicking any tile on the public dashboard sent the visitor to a login page.

The drill-down links pointed at /d/jq-fleet-public/…?viewPanel=N — an authenticated route. A public dashboard is served from /public-dashboards/<token>, a path that doesn't exist when the file is generated.

Making the links relative didn't help either: Grafana's router resolves ?viewPanel=N against the app root, so a click landed on /. Verified in a browser with no session:

tile href:    ?viewPanel=107&from=now-1h&to=now
after click:  http://localhost:3000/?viewPanel=107...
still public: False

The fix

The detail can't be reached by clicking, so it's no longer hidden behind one. Every data link is stripped and the collapsed rows are expanded — the tables are just on the page. A visitor had no way to know a tile was clickable anyway.

Expanding those rows meant rebuilding the layout. A row's freed children all carry the same y, and the previous repack read them as one side-by-side band — it packed full-width tables to x=24, 48, 72, off the right of the 24-column grid. Panels now carry an explicit band and the grid is rebuilt from that.

check-dashboard.py caught both the overlap and the overflow, which is exactly what it was added for.

And a status-board restyle

The private board is something you interrogate; this one is something you glance at:

  • one dominant verdict — every red workflow, drifted repo and failing PR summed, reading ALL CLEAR at zero
  • a row of plain counters — repos, open PRs, open issues
  • a row of lit status blocks — CI red, behind template, PRs red

Colour does real work: every lit panel means good or bad, and the counters that mean neither stay unlit, because 37 open issues is workload, not a fault. Data age is lit, since stale data invalidates everything above it.

One thing worth keeping: textMode stays "value". "value_and_name" prints the raw PromQL beside each number — the series has no name so Grafana falls back to the expression — which is not something to publish.

Verified

Rendered through a real public-dashboard link in a fresh browser context with no session: no login redirect, 0 "No data" panels, no raw PromQL visible, no private repos, nothing about any laptop.

🤖 Generated with Claude Code

Clicking any tile on the public dashboard took the visitor to a login page.
The drill-down links pointed at /d/jq-fleet-public/...?viewPanel=N, which is an
authenticated route; a public dashboard is served from /public-dashboards/
<token>, a path that does not exist when this file is generated. Making the
links relative did not help either - Grafana's router resolves "?viewPanel=N"
against the app root and lands on "/".

Since the detail cannot be reached by clicking, it is no longer hidden behind a
click: every data link is stripped and the collapsed rows are expanded, so the
tables are simply on the page. A visitor had no way to know a tile was
clickable anyway.

Expanding those rows meant rebuilding the layout, because a row's freed
children all carry the same y and the previous repack read them as one
side-by-side band - it packed full-width tables to x=24, 48 and 72, off the
right of the grid. Panels now carry an explicit band and the grid is rebuilt
from that. check-dashboard.py caught both the overlap and the overflow.

The public copy is also restyled as something you glance at rather than
interrogate: one dominant verdict that reads ALL CLEAR at zero, a row of plain
counters, and a row of lit status blocks. Colour does real work - every lit
panel means good or bad, and the counters that mean neither stay unlit, because
37 open issues is workload, not a fault. Data age is lit, since stale data
invalidates everything above it.

textMode stays "value": "value_and_name" prints the raw PromQL beside each
number, because the series has no name and Grafana falls back to the
expression - not something to publish.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@tschm
tschm merged commit 3389d0d into main Aug 29, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant