feat(board): a seat is filled in on the page it is read on - #968
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
A board member fills in a seat from the page a visitor reads it on. A pencil on a row opens
that seat; a plus at the end of the stack adds one.
One dialog per seat carries everything a seat is: the name it stands under, the nickname the
history knows it by, the role in the board's own words, the portrait uploaded, the account it
belongs to, the stretch it was served and the blurb. Plus Remove, which asks first.
The parts that are about the real data
name is the seat's own and an account is something a seat may additionally have. Detaching
leaves the seat standing under its own name, and the spec asserts exactly that.
answer "was on the board that year", so the dates are pre-filled from the board and then
editable: a mid-year handover is recorded truthfully rather than credited as a full year.
Cancelling leaves the seat exactly as it was, portrait included — asserted by comparing the
plate's
srcacross a cancelled dialog that had already uploaded a replacement.{error}rather than throwing, so theadapter grew
addSeatOrReason,saveSeatOrReason,linkSeatMemberOrReasonanddropSeatOrReasonbeside the existing four — the same shape feat(board): a board can be edited and added on the boards page #962 gavesaveBoardOrReason.The old signatures stay as thin wrappers, so
BoardManageris untouched until The board editor leaves the management area #934 removes it.IslandPicker, not Vuetify's, and the portraitwith
ImagePickerbound tostoreSeatPortrait.How the pencil reaches the page without a cross-domain import
src/components/island/SeatRows.vuemay not know about boards (frontend ADR-001), so it doesnot. It takes a
mayEditboolean and anaddLabel, and emitsedit(id)andadd()— the samecontract
TimelineandBannerSlicesalready have.Board.vueowns the dialog, decides who maysee a pencil, and turns a row id back into the seat it read. The pencil is positioned over the
row rather than nested inside it, because the row head is itself a button wherever a blurb was
written and a button inside a button is not markup — which also kept the diff off the existing
markup's indentation.
It is hidden until the row is approached (and simply stands where there is no pointer to hover
with), following the strip's own rule. Nothing here is a guard: a visitor is offered no pencil at
all, and a refused request is still refused.
On #962
useMayEditBoardsis #962's file and this imports it rather than carrying a second copy. #962merged before this was pushed, so the rebase absorbed it and the file does not appear in this
diff at all.
The e2e board mocks are now stateful on both sides: #962 made a board's own fields stateful, and
this lands a seat write on the board's
members, so a page that reads again is answered the waythe api would.
boardHoldingdeliberately looks at the raw fixtures andboardsMaderather thanat
boardsNow(), which composes a copy per board — a seat pushed onto a copy's list would reachthe board, and a seat removed from one would not.
Verification
All from
services/frontend, run against the rebased tree, exit codes checked rather thangrepped summaries.
vue-tsc --noEmit -p tsconfig.typecheck.jsoneslint --fix --max-warnings 0 src tests scripts …vitest run --coverage— 138 files, 1017 testsvite buildplaywright test --grep "board"— 130 passedplaywright test(full)New coverage: 5 unit tests on
SeatRows(a visitor is offered nothing; a pencil per row namedfor its seat; which seat a press reports; the one way in at the end) and 13 e2e tests in
board-seat-edit.spec.ts— adding a seat, each field round-tripping, the nickname recorded apartfrom the name, a portrait uploaded and previewed before saving, an account linked and detached,
the dates pre-filled and changed, removal asking first and naming the blurb it takes,
cancellation changing nothing, a refusal reported, and a visitor seeing none of it.
The full run had one failure —
email-manager.spec.ts"stats panel shows delivery ratepercentage", a lone
page.goto5000ms timeout. That is the documented runner-starvationsignature (8 workers on 4 vCPUs), in a spec this branch does not touch; the whole file re-ran in
isolation 44/44 green, exit 0.
The e2e runs were driven by starting
vite preview(4173) andvite dev(4174) by hand andletting Playwright reuse them, so the wrapper's coverage-conversion step was skipped. No
yarn installwas run andpackage.json,yarn.lockand.yarnare untouched.The OpenAPI client was not regenerated: every field this needs —
nickname,portrait,displayName,role,startDate,endDate,descriptionand the link endpoint — alreadyexists.
Closes #933
Diff breakdown —
█added░removed, scaled to the largest row.