Carry who saves and whether the card is new with each card save #258

Merged
Grandiras merged 1 commit from fix-card-save-state into main 2026-10-04 17:40:30 +00:00
Owner

A card's saves queue (save on leave, #242), so a save can run after its dialog has closed or another dialog has opened. Both pages read who is writing, and whether the card is new, from their own state at that moment:

  • Calendar: SaveCard used _modalViewer, which CloseModal resets to BoardViewer.None. A save still queued when the dialog closed was refused, and the edit was lost. This is a likely cause of the occasional "a dated card… cleared" failure in calendar.spec.js.
  • Board: SaveCard used _modalIsNew. With a new card's dialog open by the time an older save ran, it would have created a copy of the card instead of updating it. It also used _viewer, which a board switch changes, since the router reuses the page.

CardModalSaveArgs now carries IsNew and Viewer as they were when the edit was made, and both pages use those.

Verified: tools/verify.sh (600 unit tests); full e2e on an isolated stack, 162/162.

🤖 Generated with Claude Code

A card's saves queue (save on leave, #242), so a save can run after its dialog has closed or another dialog has opened. Both pages read who is writing, and whether the card is new, from their own state at that moment: - **Calendar:** `SaveCard` used `_modalViewer`, which `CloseModal` resets to `BoardViewer.None`. A save still queued when the dialog closed was refused, and the edit was lost. This is a likely cause of the occasional "a dated card… cleared" failure in `calendar.spec.js`. - **Board:** `SaveCard` used `_modalIsNew`. With a new card's dialog open by the time an older save ran, it would have created a copy of the card instead of updating it. It also used `_viewer`, which a board switch changes, since the router reuses the page. `CardModalSaveArgs` now carries `IsNew` and `Viewer` as they were when the edit was made, and both pages use those. Verified: `tools/verify.sh` (600 unit tests); full e2e on an isolated stack, 162/162. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Carry who saves and whether the card is new with each card save
All checks were successful
CI / build (pull_request) Successful in 40s
a2b47bcfc7
A card's saves queue, so one can run after its dialog has closed or another
has opened. The pages read that from their own state at save time: the
calendar's closed dialog had reset its viewer, so the save was refused and
lost, and a board with a new card's dialog open would have created a copy of
the card instead of updating it. CardModalSaveArgs now carries IsNew and the
Viewer as they were when the edit was made.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Collaborator

🤖 Reviewing this PR — the review will link the full session transcript.

📜 Live transcript — updating every ~5 minutes while the review runs.

🤖 Reviewing this PR — the review will link the full session transcript. <!-- opencode-run:review --> 📜 [Live transcript](https://git.grandiras.net/Grandiras/opencode-bot/src/branch/opencode-logs/transcripts/Grandiras/Ponente/pr-258/run-2026-10-04T17-37-19-109Z.md) — updating every ~5 minutes while the review runs.
Collaborator

🤖 Reviewing this PR — follow along in the action run; the reply will link the full session transcript.

📜 Live transcript — updating every ~5 minutes while the task runs.

🤖 Reviewing this PR — follow along in [the action run](https://git.grandiras.net/Grandiras/claude-bot/actions/runs/711); the reply will link the full session transcript. <!-- claude-run:pr_review --> 📜 [Live transcript](https://git.grandiras.net/Grandiras/claude-bot/src/branch/claude-logs/transcripts/Grandiras/Ponente/pr-258/run-711.md) — updating every ~5 minutes while the task runs.
claude-reviewer left a comment

✅ Verdict: approve — no blocking issues found.

The change is correct and small. CardModalSaveArgs now carries IsNew and Viewer, and both pages read them in place of the page-level _modalIsNew, _viewer and _modalViewer.

  • Constructor calls: the record is constructed in only two places, both in CardModal.razor, and both are updated. CardModal.Viewer exists (line 270).
  • isNew value: the autosave path passes false and the create path passes true. That matches what _modalIsNew meant before.
  • Docs: docs/ui.md is updated with the reason.

Two remarks:

  • Changelog: the fix is member-visible (lost calendar edits), but no Changelog.Unreleased line is added. If you judge it a bug fix not worth a note, that is fine.
  • Tests: there is no regression test for the queued save after close. The PR says the full e2e suite passed 162/162, but I did not run it.

🧠 claude-sonnet-5-5 · ⏱ 0m 7s · 3 turns · tokens: 12.7k in / 600 out (+36.6k cache-read)
📜 Full session transcript

✅ **Verdict: approve** — no blocking issues found. The change is correct and small. `CardModalSaveArgs` now carries `IsNew` and `Viewer`, and both pages read them in place of the page-level `_modalIsNew`, `_viewer` and `_modalViewer`. - **Constructor calls:** the record is constructed in only two places, both in `CardModal.razor`, and both are updated. `CardModal.Viewer` exists (line 270). - **`isNew` value:** the autosave path passes `false` and the create path passes `true`. That matches what `_modalIsNew` meant before. - **Docs:** `docs/ui.md` is updated with the reason. Two remarks: - **Changelog:** the fix is member-visible (lost calendar edits), but no `Changelog.Unreleased` line is added. If you judge it a bug fix not worth a note, that is fine. - **Tests:** there is no regression test for the queued save after close. The PR says the full e2e suite passed 162/162, but I did not run it. --- 🧠 claude-sonnet-5-5 · ⏱ 0m 7s · 3 turns · tokens: 12.7k in / 600 out (+36.6k cache-read) 📜 [Full session transcript](https://git.grandiras.net/Grandiras/claude-bot/src/branch/claude-logs/transcripts/Grandiras/Ponente/pr-258/run-711.md) <!-- claude-verdict:approve --> <!-- claude-reviewed-head:a2b47bcfc754942db46c20920d1ead70d0e67720 -->
opencode-reviewer left a comment

✅ Verdict: approve — no blocking issues found.

Good to merge. The fix is correct and complete: CardModalSaveArgs now carries IsNew and Viewer as captured at the moment the edit was committed, and since SaveAfter chains each queued save with the args captured at its commit, a save running after CloseModal reset _modalViewer (Calendar) or after a board switch changed _viewer/_modalIsNew (BoardPage) no longer reads stale page state. Both pages now consume args.Viewer/args.IsNew consistently; the record's only instantiation sites are the two in CardModal.razor, so nothing else breaks. Minor note (not a blocker): BoardPage.MoveCardToBoard still reads _viewer at handler time rather than carrying it in CardModalMoveArgs — that path is interactive (the dialog is open when the user clicks move), so it isn't affected by the queued-save race, but it could be worth aligning if that ever changes.


⏱ 1m 36s · 10 steps · $0.0111 · tokens: 46.8k in / 1.2k out (+70.5k cache-read) · Go: 5h 9% · wk 16% · mo 90%
📜 Full session transcript

✅ **Verdict: approve** — no blocking issues found. Good to merge. The fix is correct and complete: `CardModalSaveArgs` now carries `IsNew` and `Viewer` as captured at the moment the edit was committed, and since `SaveAfter` chains each queued save with the args captured at its commit, a save running after `CloseModal` reset `_modalViewer` (Calendar) or after a board switch changed `_viewer`/`_modalIsNew` (BoardPage) no longer reads stale page state. Both pages now consume `args.Viewer`/`args.IsNew` consistently; the record's only instantiation sites are the two in `CardModal.razor`, so nothing else breaks. Minor note (not a blocker): `BoardPage.MoveCardToBoard` still reads `_viewer` at handler time rather than carrying it in `CardModalMoveArgs` — that path is interactive (the dialog is open when the user clicks move), so it isn't affected by the queued-save race, but it could be worth aligning if that ever changes. --- ⏱ 1m 36s · 10 steps · $0.0111 · tokens: 46.8k in / 1.2k out (+70.5k cache-read) · Go: 5h 9% · wk 16% · mo 90% 📜 [Full session transcript](https://git.grandiras.net/Grandiras/opencode-bot/src/branch/opencode-logs/transcripts/Grandiras/Ponente/pr-258/run-2026-10-04T17-37-19-109Z.md) <!-- opencode-reviewed-head:a2b47bcfc754942db46c20920d1ead70d0e67720 --> <!-- opencode-verdict:approve -->
Grandiras deleted branch fix-card-save-state 2026-10-04 17:40:31 +00:00
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
5 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Grandiras/Ponente!258
No description provided.