Loading…
Reference in a new issue
No description provided.
Delete branch "build/lane1-you"
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?
Lane 1's last PR (#727, series item 5: HOME-5 Profile, HOME-6 Notifications, HOME-7 Plan & billing). Frontend and a small backend change; the last of the lane's six.
Profile, one page in sections (
/profile, IS-366, D21): You (the sign-in name, display name, pronouns with three chips, IS-229, time zone), When you can play (weekly times with their own Save, time away with its own Add, SH-139/SH-142), Notifications, Connected accounts (Discord in its three states, other accounts, the post-link banner), Calendar (the feed with Copy, a new link and turning it off behind their confirms), and Your data and leaving (export first; the typed-name delete; the owner-blocked state naming the campaigns to hand on). The sections are in the Contents as Profile's sub-list, the one in view current. Its own duplicate header goes; the frame has the bar. Saving and Saved areSaveState; a failed save is an inline error with the drawing's own sentence, becauseSaveState's failure words promise a local copy that a page with Save buttons does not keep.Notifications as a grid (
/profile/notificationsand the section, D48, IS-361): a row per category with the kit's words, "Always" in Quest Board, an Email column only when the instance sends mail, a Discord DM column only when it can work, mutes per campaign with "Muted since". New library componentNotifyGrid; each cell is named by the two headings it sits under, so a reader hears "Sessions Email" rather than five controls all called "Email".Backend for the grid: a
recapscategory (kinds:summary_ready), with migrationb8c9d0e1f2a3moving the carried-over recap opt-in rows from(sessions, email)to(recaps, email)and the recap email's gate andPATCH /api/me {recap_email_opt_in}following; calendar invites as a mail-only row in the grid backed byusers.calendar_invite_opt_in;muted_aton mutes. Discord DM is listed as unavailable ("Discord DMs arrive with a later release.") until lane 10 delivers it, and the delivery task skips that channel before claiming its at-most-once row, so nothing is marked delivered that never went out.Plan & billing (
/profile/plan, D49, D71, IS-362 to IS-376): #642's phase 1, the entitlements interface with the self-hosted provider.GET /api/me/plananswers{"hosted": false}on a self-hosted instance, which is every real instance today, and then the account menu's entry, the sheet's entry and the page are absent. When a hosted provider exists, the page renders the contract: slots and what they cost, the failed-payment banner with the grace date, the credits meter, used this month, what things cost, and the four dialogs (buy in blocks, a first slot, add a slot with the new monthly total, remove a slot choosing which campaign stays active); paying goes to the provider's page and the return states come from?return=. Prices are read once from Admin's plan pricing key (IS-398), never typed twice. The three write endpoints answer 501 on a self-hosted instance. Verified by rendering every state headless with the API faked (eighteen stills, desktop and phone) since no real instance can show it yet.The journeys found two faults, fixed here: the phone's Contents sheet stayed open over the page a row had just opened (the sheet now closes when the frame routes a chrome link); and J0 asserted Dana had no pronouns by design, which the seed now sets and J0 asserts positively.
Coverage (
lane1b.py): every drawn and replaced placement on HOME-5, HOME-6 and HOME-7, with SH-128 and SH-132 replaced and SH-133 moved into the grid. Tests: frontend 1,233 (Profile 25, Notifications 8, Plan 18, NotifyGrid 5, the frame 7 more); backend 3,817 (tests/test_plan.py24 new; notifications and recap email extended); journeys 21 passed in the three projects,/profileand/profile/notificationsclean under the strict gate. Lint, ruff and the build clean.🤖 Generated with Claude Code