feat(web): the side panel's headline and lane ledger (#40) - #63
Merged
Conversation
The instructor's dashboard beside the graph: a headline and a lane ledger that lists every lane, always, in a fixed order, so a lane's numbers are in the same place on every beat of all four days and can be read aloud without hunting. Both slots are built once per dataset in the same topology pass as the canvas and thereafter mutated only by class and text content. No innerHTML after build, in any slot -- a slot rebuilt from a string loses its handles, and the handle is what makes a row and its lane demonstrably the same object. Three of the panel's apparent content shapes were never components. The cut's certifying lane list and the interdicted subset are subsets of the lanes, so they are row states on the one ledger row -- .in-cut, .removed, .violating, .on-path, .hot -- never separate DOM that could disagree with it. The struck and violation counts are counted from the very flags that class those rows. Throughput and cut capacity are not: they are solver scalars the server computed, and re-deriving either here would put two numbers that must be equal on the dashboard by two different routes. The ledger shows every lane always, with hot rows marked, rather than filtering to the cold ones. Filtering reflows on every keypress and empties itself on the pristine network, where an empty hot set means every lane is hot. Showing everything gives the ledger the job it needed anyway: it is the printed key to the canvas. Row-state colour is a low-chroma left-edge tick whose width is reserved transparently from the first paint -- a border that appeared would move the row's text sideways on the beat it appeared. The table is laid out `fixed` for the same reason: an auto table re-measures its columns from their content, so a two-digit flow becoming three-digit would shift every column on a beat that changed nothing else. Clicking a row pins that lane hot until the next beat or R. That is the whole of what a pointer may do here: duplicate a keyboard jump, or produce transient emphasis no later state depends on. R ships alongside it because the rule is that a pointer may never reach a state the keyboard cannot. tests/test_web_assets.py gains four checks: no asset writes markup as a string; every row state is both painted and computed; every row state has a tick token; and the ticks are strictly less saturated than every categorical role on the canvas -- a relationship rather than a value, since the palette is expected to be retuned against the real projector. Closes #40
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #40.
The instructor's dashboard beside the graph: a headline and a lane ledger that lists every lane, always, in a fixed order, so a lane's numbers are in the same place on every beat of all four days and can be read aloud without hunting.
What's here
.removed,.in-cut,.violating,.on-path,.hotas classes on that one row. No separate DOM for any lane subset.Rclears it.Both slots are built once per dataset in the same topology pass as the canvas and thereafter mutated only by class and text content. No
innerHTMLafter build, in any slot — a slot rebuilt from a string loses its handles, and the handle is what makes a row and its lane demonstrably the same object.Decisions worth reading
state.cutandmarks.inCutfrom one/maxflowresponse.fixed— an auto table re-measures its columns from their content, so a two-digit flow becoming three-digit would shift every column on a beat that changed nothing else.Rships alongside the click rather than after it.Known follow-ups
Rclears the pin, but "until the next beat" cannot be honoured until the beat engine (The beat engine, keyboard controls and layer catalog #41) lands.clearPin()documents that the beat mutator must call it.removedandhotecho a colour that exists today. The stylesheet flags them for re-derivation.Verification
tests/test_web_assets.pygains four checks, written before the implementation:innerHTMLand friends);state.js;--panel-tick-*token;Full suite: 294 passed. No JavaScript test runner is introduced; the frontend stays verified from Python or not at all.
🤖 Generated with Claude Code