feat(board): the boards read as a timeline - #956
Merged
Conversation
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.
What this does
/boardis an island page. Top to bottom: an island header, the timeline of every board, theboard band, the identity block, the seats, the closing band. The Vuetify
TopBanneris gone, andso is the wall of grey toggles behind it.
name — composed from its number in Roman numerals where none is recorded — and the academic year
beneath it. The board in office is marked In office, a board elected and not yet sitting
Candidate. The lit stretch ends on the board being read.
?board=<number>, so a board is linkable and theback button walks back through the years. Absent a board in the url the page opens on the board
in office; a url naming a board nobody recorded falls through to it rather than to a blank page.
the number set large in Roman numerals at the lower left and shaved by the lower cut, with a
scrim under the numeral only rather than over the photograph. A board with no photograph keeps
the band and its height, filled with its own colour and the numeral centred — boards I to IV have
none and board X has none yet, so that is the normal case for half the history.
BOARD IX · 2025-2026, then the name, then the cheer in the displayface and the accent, then the description in body text.
BoardMemberRow, ordered withseatsInOrderand named with thenickname in place (
seatTitlein the adapter already did that). Seats read as expandable rows #931 replaces the rows.Where the in-office rule went
src/domains/boards/standing.ts, beside the other reading rules, importing nothing:isCandidate(board, on?)— the term opens later than today.boardInOffice(boards, on?)— the board whose term contains today; where none does, the newestboard that is not a candidate answers instead. Null where there are no boards, or where every
board recorded has yet to begin. A board with no readable start date is passed over.
standingOf(board, boards, on?)—"in office" | "candidate" | "past", read against the wholeline, because being in office is a fact about the line rather than about one board's dates.
tests/unit/domains/boards/standing.test.tsreads it against the real seeded terms, which is wherethe awkward shapes live: board IX runs to 16 September and board X opens on the 17th, so the tidy
"1 September to 31 August" fixture never meets either case.
boardAxis.tsturns boards into thetimeline's stops and
boardInRoute.tsreads?board=; both are unit-tested too. The page asks; itworks nothing out.
Stopin the shared island gains an optionalmark— a word marking one stop out from the line.What the word is stays with whoever draws the strip, so the esports timeline is unchanged.
The two things #930's comment recorded
ImagePicker's contract. Nothing in this ticket picks a picture — the dialogs are A board is edited on the page #932 andA seat is edited on the page #933 — so no
FileTypeis reached for anywhere new. The wiring the comment points at is intact:storeBoardPhotoandstoreSeatPortraitare exported from the boards adapter asPictureStoreand are what those dialogs bind to
store.boardName(Board IV). Theadapter's
boardTitleis gone and its digits went with its last caller, as a local helper inBoardManager.vue, which The board editor leaves the management area #934 deletes.Copy — DRAFT, awaiting your approval
Both of these need redlining. Quoted exactly as committed.
Island header
Closing band (
src/domains/boards/island/boardCall.ts)Two smaller strings, same standing:
No boards are recorded yet.andNo seats are recorded on this board yet.(the second is what board X shows today).Three judgement calls worth a look
Board IV. The two acceptance criteria read against each other — "each stop shows the board'sname, composed from its number where it has none" and "a blank name, cheer or description renders
nothing rather than a placeholder" — and this is the reading that satisfies both: a stop may not
be blank, and a heading repeating the eyebrow that has just said
BOARD IVis the placeholder.photoand does not fall back toimage. The old page drewasset(board.image), but the band's contract is aPicturewith a width ladder, and an assetpath has neither a width nor a rendition — so a fallback could not satisfy "a large photograph
does not cost a reader the page". Every seeded board with a photograph carries both fields, so
nothing loses its picture. Seat portraits keep the fallback, because that row takes a bare
url: stored picture first, then the assets directory, until The asset file names go #935.
candidatecolumn, which holds a copy of the name andwhich nothing reads. The word is the one the ticket asked for and the standing is derived rather
than stored, so nothing is ambiguous in the code — but if the column outlives A board is edited on the page #932 it may be worth
renaming one of the two.
Accent
Every board draws the association's blue today, because no board has a colour recorded. The page
reads one value into the lit stretch of the timeline, the band, the bare band's fill and the cheer,
so a colour appearing on a board needs no further change. It is made readable rather than used raw:
--accent-inkmixes the accent towards--color-chalk, which is near-white in the dark half andnear-black in the light one, with the heavier hand in light — so a pale historical colour drops onto
the pale ground instead of vanishing into it. Declared on the element that carries
--accent, sincea custom property built out of another is substituted where it is declared.
island.cssnow scanspages/Board.vueanddomains/boards, without which none of the page'sTailwind exists.
Verification
yarn typecheckyarn lint --max-warnings=0yarn test:unityarn test:e2e --grep "board"yarn test:e2e(full)The three full-run failures are all
page.gototiming out at 5s in one worker window(
navigation-links×2,home-competitive-games×1); the mobile-chrome copies of the same testspassed in the same run. Re-run in isolation:
yarn test:e2e tests/e2e/navigation-links.spec.ts tests/e2e/home-competitive-games.spec.ts→ exit 0, 18 passed. Runner starvation, not this change.New end-to-end coverage: the stops and their marks, choosing a board and the url following, the back
button, the Roman numerals, the band with and without a photograph (including which copy a phone
actually fetches), the candidate board appearing without being focused, a blank cheer, description
and name rendering nothing, the seat order and the nicknames, and the three blocks stacked on a
phone. The
board managerhalf ofboards.spec.tsis untouched and still passes — #934 removes it.Closes #930
Diff breakdown —
█added░removed, scaled to the largest row.