fix(web): the standings do not belong under a node
Reported: the board was still rendering beneath the node route. It was a fourth place spelling out "is this the standings?" by hand — the board's own render condition, which I missed when extracting `isStandings` for the other three. That predicate now has one definition and four callers: the section nav, the window selector, the canonicalising redirect, and the board. Grepped for survivors; there are none. Worth recording how both node-route bugs were found, because it is the same lesson twice in one feature: the route parsed, the page existed, every gate was green, and only opening the page in a browser showed that the address bar threw it away the first time and that thirty mining rows sat under it the second. Checked: `/quantus/node/<peer>` renders one panel, no `.two-col`, no board rows. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Jp6a8EDar9ueEhAxzep4V5
This commit is contained in:
15
CLAUDE.md
15
CLAUDE.md
@@ -402,13 +402,16 @@ nobody: a node visible on the official telemetry site was invisible here. The
|
||||
`/:chain/node` index and `/:chain/node/:peer` route have no entry condition,
|
||||
and the miner panel now links to them rather than being the only way in.
|
||||
|
||||
**"Is this the standings?" is one function, not three.** `isStandings` in
|
||||
`lib/routes.ts`. Adding the node section updated the copies in `SectionNav` and
|
||||
`windowApplies` and missed the canonicalising redirect in `App`, which judged
|
||||
**"Is this the standings?" is one function, not four.** `isStandings` in
|
||||
`lib/routes.ts`. Adding the node section had to update the section nav, the
|
||||
window selector, the canonicalising redirect and the board's own render
|
||||
condition — and the first pass caught two of them. The redirect judged
|
||||
`/quantus/node/<peer>` to be the standings and replaced it with
|
||||
`/quantus/3600-blocks` — the route parsed, the page existed, and the address bar
|
||||
threw it away before it rendered. A new section still has to be added to the
|
||||
predicate; it now has one place to be added to.
|
||||
`/quantus/3600-blocks`, and the render condition left thirty unrelated mining
|
||||
rows under the node. Both were reported rather than caught: the route parsed,
|
||||
the page existed, the build was green, and only opening it showed either. A new
|
||||
section still has to be added to the predicate; it now has one place to be added
|
||||
to.
|
||||
|
||||
**Telemetry hardware is the node's word, reached by inference.** A miner is
|
||||
joined to a node through the same first-reporter voting that produces its
|
||||
|
||||
@@ -269,39 +269,39 @@ export default function App() {
|
||||
)}
|
||||
{route.index === 'node' && chain && <NodesIndex chain={chain} />}
|
||||
|
||||
{!route.account &&
|
||||
!route.miner &&
|
||||
!route.block &&
|
||||
route.runtime === null &&
|
||||
route.call === null &&
|
||||
route.event === null &&
|
||||
route.index === null && (
|
||||
<div className="two-col">
|
||||
<section className="panel">
|
||||
<div className="panel-head">
|
||||
<h2 className="panel-title">The Standings</h2>
|
||||
<span className="eyebrow">
|
||||
last {activeWindow.blocks.toLocaleString('en-US')} blocks ·{' '}
|
||||
{measuredSpan(state.windowSeconds, activeWindow.blocks, interval)}
|
||||
{pinned.length > 0 && ` · ${pinned.length} marked yours`}
|
||||
</span>
|
||||
</div>
|
||||
<Leaderboard rows={state.leaderboard} chain={chain} ready={state.ready} />
|
||||
</section>
|
||||
{/* The standings and the live ticker belong to the standings route and
|
||||
nowhere else. A page that names one subject has that subject as its
|
||||
whole subject; leaving thirty unrelated mining rows underneath is the
|
||||
site failing to notice which page it is on. This was the fourth place
|
||||
spelling out "is this the standings?" by hand — and the one that kept
|
||||
showing the board under a node. */}
|
||||
{isStandings(route) && (
|
||||
<div className="two-col">
|
||||
<section className="panel">
|
||||
<div className="panel-head">
|
||||
<h2 className="panel-title">The Standings</h2>
|
||||
<span className="eyebrow">
|
||||
last {activeWindow.blocks.toLocaleString('en-US')} blocks ·{' '}
|
||||
{measuredSpan(state.windowSeconds, activeWindow.blocks, interval)}
|
||||
{pinned.length > 0 && ` · ${pinned.length} marked yours`}
|
||||
</span>
|
||||
</div>
|
||||
<Leaderboard rows={state.leaderboard} chain={chain} ready={state.ready} />
|
||||
</section>
|
||||
|
||||
<section className="panel">
|
||||
<div className="panel-head">
|
||||
<h2 className="panel-title">Live Blocks</h2>
|
||||
<span className="eyebrow">
|
||||
{state.summary?.block_interval_seconds
|
||||
? `${seconds(state.summary.block_interval_seconds)} apart`
|
||||
: 'measuring'}
|
||||
</span>
|
||||
</div>
|
||||
<BlockTicker blocks={state.blocks} chain={chain} />
|
||||
</section>
|
||||
</div>
|
||||
)}
|
||||
<section className="panel">
|
||||
<div className="panel-head">
|
||||
<h2 className="panel-title">Live Blocks</h2>
|
||||
<span className="eyebrow">
|
||||
{state.summary?.block_interval_seconds
|
||||
? `${seconds(state.summary.block_interval_seconds)} apart`
|
||||
: 'measuring'}
|
||||
</span>
|
||||
</div>
|
||||
<BlockTicker blocks={state.blocks} chain={chain} />
|
||||
</section>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<footer className="footer">
|
||||
<span>
|
||||
|
||||
Reference in New Issue
Block a user