Lane 3: the new-session form and the recurring series (#729, CAMP-3, CAMP-4) #774
Loading…
Reference in a new issue
No description provided.
Delete branch "build/lane3-sessionform"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The thing a GM does more than anything else, and the rule that saves them doing it.
How this PR was built, because it matters for how you read it
Two delegates died mid-task on the same API safeguard, both times on the model's own reasoning and never on anything in the code. Neither produced a report. The work was preserved as it stood — twice — and I verified it myself rather than receiving a row-by-row account. So: the checks below are mine and were actually run, but there is no delegate narrative behind them, and the review is correspondingly the code's rather than a summary's. The two WIP commits are in the history and say exactly that.
A page, not a dialog
CA-123is classified replaced for this reason: the drawing opens New session as a page of its own, and Cancel there is the way back./campaigns/:id/sessions/new— the form./sessions/:id/edit— the same form editing one (SE-011,SE-012). Its own address rather than the campaign's, because a session is reached from its own page.Neither is a Contents entry; both are reached from the list, This week's checklist, and a session.
Two clock rules that are not the same rule
This is the part to read, and the build got it right — including a step past the brief.
D17 governs displaying an instant:
whenTextformats in the reader's own zone with its abbreviation and takes no zone parameter.CA-137is not that. A recurrence rule is a wall clock in a named zone — "8:00 PM, in the campaign's time, CDT, whatever the clocks do" — and putting it through the reader's zone would turn a schedule into a timestamp and make the series drift an hour twice a year.components/seriesText.jskeeps the two apart by construction, and its file note says so. Two details worth calling out:zoneShortLabelfalls back to the reader's zone, so a rule in no named zone would otherwise render "8:00 PM BST" and assert something untrue of it — which is the exact confusionCA-137exists to prevent. That one is not in the drawing; it is a consequence of the drawing taken seriously.The sessions a series makes are instants, and those go through
whenTextlike everything else.The series moves to where its sessions are
IS-368puts "Manage the series" on the Sessions list and under the title of any session it made, soSeriesManageris removed from the old campaign page — it is not a section anybody goes looking for, it is the reason the next two evenings are already on the board. That is the one edit toCampaignDetail.jsxin this PR, and it is a deletion.The read it needs is
GET /api/series/{id}/sessions, added in #765 precisely for this:CA-154's "Change which sessions?" turns on which occurrences were individually rescheduled, becauseupdate_series'sfuture_allwill not touch those.No session numbering
#760is not this PR. Nothing here invents a number: where the drawing reads "Session 15", the build reads the session's title.grepforsession_numberin the new files returns nothing.Checks
eslint src0 errors, 227 warnings — seven fewer than main's 234, from the old page's deleted section.vite buildgreen.coverage/lane2.py→{'drawn': 99, 'replaced': 7, 'deferred': 1, 'elsewhere': 11} total 118 — unclassified: none.coverage/lane2c.py→{'drawn': 65, 'elsewhere': 27, 'replaced': 10, 'behaviour': 5} total 107 — unclassified: none.A render check is running separately and its result will be added as a comment. The CSS carries evidence that one was done during the build —
.qb-series__under-title .nb'swhite-space: nowrapexists because the separators were seen stranding at line ends and "Manage the series" coming apart across two — but I have not personally looked at these pages, and I would rather say so than imply otherwise. Each.nbis a short phrase, so the line wraps between phrases and never inside one; that is by inspection, not by eye.🤖 Generated with Claude Code
The render check: clean, and measured rather than eyeballed
Sixteen renders of the built app — the new-session form, the edit form, the sessions list with the series card collapsed, and the same list with it expanded (
?series=…, which exercisesSeriesEdit's whole field set) — each at desktop and phone width, in both themes. All sixteen looked at.No layout faults. No overflow, no mid-word wrap, no horizontal scroll, nothing overlapping or outside its card, nothing invisible in either theme.
.slist__rule("Ninety Miles of Fog · every other Monday") wraps cleanly onto a second line at 390px without colliding with the chip below it.Two things about how it was checked matter more than the result.
The phone-width shots this project has been taking are not evidence
Headless Edge on Windows clamps the viewport to a 492px floor — below ~500 it clamps to 492, above it you get
request − 24— and then saves the PNG at the requested width. A--window-size=390"phone" shot is therefore a crop of a 492px render, and a crop and a real overflow look identical: text truncated at the right edge, "Pencil i[t in]", a search box cut off. That is a manufactured fault, and this run reproduced it before catching it.The repo's own notes already knew about the clamp and concluded that ~492px was the narrowest honest render available. It isn't. Put the page in an iframe — a wrapper page whose own window is requested comfortably wide, holding
<iframe style="width:390px">. The iframe is laid out in CSS pixels by the parent document, so the clamp does not reach it, and the page inside genuinely lays out at 390.Then prove it from inside the iframe's own document rather than trusting the picture:
scrollWidth > clientWidthis horizontal overflow, measured. Every page above returns390 === 390. That is a better test than looking at a screenshot in any case.A stale build nearly got reported as a pass
The scratchpad already held a
dist/and a set of screenshots from the first delegate's interrupted attempt. Checking their timestamps against the git log showed that build predated the commit that wroteSessionForm.jsxat all — they were pictures of a page that did not yet exist. Discarded and everything rebuilt from5a1dfb3. Worth saying because "screenshots exist" is not the same as "this code was rendered", and the two are indistinguishable without checking.Two things deliberately not covered
SeriesUnderTitlein its real home. The.nbnon-breaking-phrase CSS exists for the 320px left rail onSessionDetail.jsx, which is a large legacy page with ~10 further API dependencies; standing it up was out of proportion to a render check of two other pages. The sibling mechanism — the sameruleLine()text beside a title in the sessions list — was checked and wraps cleanly, and the CSS structurally does what it claims: each phrase is an atomic span, so wrapping only ever happens between phrases, never inside one and never stranding a bare "·". Confident, but not photographed.Nothing under
webapp/was modified by the check; the fixture server and shot helper stayed in the scratchpad.🤖 Generated with Claude Code