Add a general calendar as an addition to board-specific calendars #85

Closed
opened 2026-08-14 15:58:25 +00:00 by Grandiras · 2 comments
Owner

So basically a user-specific calendar...

So basically a user-specific calendar...
Collaborator

🤖 On it — follow along in the action run; the reply will link the full session transcript.

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

🤖 On it — follow along in [the action run](https://git.grandiras.net/Grandiras/claude-bot/actions/runs/227); the reply will link the full session transcript. 📜 [Live transcript](https://git.grandiras.net/Grandiras/claude-bot/src/branch/claude-logs/transcripts/Grandiras/Ponente/issue-85/run-227.md) — updating every ~5 minutes while the task runs.
Collaborator

Pushed to claude/issue-85.

What it is

/calendar/all — the calendar you already have, over every board you can see rather than one. The switcher in the header offers it, but only inside the calendar section: a board is a place cards live, so "all boards" is a sensible thing to read by date and no kind of thing to put a card on, and there is no /board/all.

It's the same component, not a second one — the month grid, timeline, swipe, entrance and card dialog are all shared. The scope only decides which cards are loaded, what the legend stands for, and what the .ics links ask for.

The decisions worth arguing with

  • The category is the board, not the tag. Tags are per board, so five boards' worth are five vocabularies that don't line up — two boards each having a "Bug" would be two chips with one name and two lanes. So the legend lists boards, the timeline lanes by board (CalendarTimeline.BoardLanes), and the legend is still the filter. Tags stay the axis on a board's own calendar, unchanged.
  • A board's colour is derived from its id (BoardPalette), not stored. A board has no colour anywhere else in the app, so a column plus an admin control for one view would be a lot of schema for a hint. Two boards can therefore share a colour and nothing prevents it — the legend, the lane and every chip's tooltip name the board, and the name is also rendered on the chips that have a second line for it (day sheet, phone agenda) but never in a day cell, whose chips are one line by design.
  • The board query on both .ics endpoints carries the scope (CalendarScope): absent = the default board (every old link still means what it meant), all = every board you can see, 3,7 = exactly those, which is what the board filter writes. all stays dynamic where a list doesn't — "all my boards" and "these three" are different standing instructions when a fourth arrives. A named board that has gone 404s the whole feed rather than being silently dropped from it, and an unreadable value 404s too.
  • The card dialog offers the card's own board's tags — SetCardTagsAsync drops another board's ids, so anything else would be a picker of ticks that do nothing.
  • Both subscribe/secret lines get all-boards wording; cal.all.* keys in en and de.

Also fixed (pre-existing, found by the new tests)

/admin/boards could 500 on load: ReloadAsync published _boards before _edits was filled, and ComponentBase renders after the first await in OnInitializedAsync — so a slow second query made _edits[board.Id] a KeyNotFoundException out of the prerender. Both are now assigned after every query returns.

Verified

  • dotnet build Ponente.sln clean (no new warnings); dotnet test 191 passed — including 26 new ones: CalendarScopeTests (query parsing/round-trip, strict refusal), board lanes in CalendarTimelineTests, BoardFilter.MatchesBoard, and the all-boards X-WR-CALNAME in en/de. The en/de key-parity test covers the new strings.
  • New tests/e2e/calendar-all.spec.js (4 tests) run against the real compose stack in this container — cards from both boards on the page and only one board's on a board's own calendar, board lanes in the timeline, the switcher offering/naming/leaving it (and not offering it in the board section), the legend narrowing by board with the export link following, and /calendar.ics?board=all|<id>|garbage → 200/200/404. Green three consecutive runs.
  • The pre-existing calendar.spec.js / boards.spec.js failures in this environment are timing flakes, not regressions: I rebuilt the stack from main with my changes stashed and got the same or more failures (boards 6 vs 5, calendar 11 vs 9), all of them clicks landing before the Blazor circuit is up in cleanup helpers I didn't touch.

CLAUDE.md has a new "The general calendar: every board at once" section under the calendar chapter, plus pointers from the routes paragraph and the .ics one.

Compare: https://git.grandiras.net/Grandiras/Ponente/compare/main...claude/issue-85


⏱ 55m 38s · 189 turns · tokens: 290.1k in / 101.4k out (+38804.5k cache-read)
📜 Full session transcript
→ Opened PR: #88

Pushed to `claude/issue-85`. ## What it is **`/calendar/all`** — the calendar you already have, over **every board you can see** rather than one. The switcher in the header offers it, but only inside the calendar section: a board is a place cards live, so "all boards" is a sensible thing to read *by date* and no kind of thing to put a card on, and there is no `/board/all`. It's the **same component**, not a second one — the month grid, timeline, swipe, entrance and card dialog are all shared. The scope only decides which cards are loaded, what the legend stands for, and what the `.ics` links ask for. ## The decisions worth arguing with - **The category is the board, not the tag.** Tags are per board, so five boards' worth are five vocabularies that don't line up — two boards each having a "Bug" would be two chips with one name and two lanes. So the legend lists boards, the timeline lanes by board (`CalendarTimeline.BoardLanes`), and *the legend is still the filter*. Tags stay the axis on a board's own calendar, unchanged. - **A board's colour is derived from its id** (`BoardPalette`), not stored. A board has no colour anywhere else in the app, so a column plus an admin control for one view would be a lot of schema for a hint. Two boards can therefore share a colour and nothing prevents it — the legend, the lane and every chip's tooltip *name* the board, and the name is also rendered on the chips that have a second line for it (day sheet, phone agenda) but never in a day cell, whose chips are one line by design. - **The `board` query on both `.ics` endpoints carries the scope** (`CalendarScope`): absent = the default board (every old link still means what it meant), `all` = every board you can see, `3,7` = exactly those, which is what the board filter writes. `all` stays dynamic where a list doesn't — "all my boards" and "these three" are different standing instructions when a fourth arrives. A *named* board that has gone 404s the whole feed rather than being silently dropped from it, and an unreadable value 404s too. - The card dialog offers the card's **own** board's tags — `SetCardTagsAsync` drops another board's ids, so anything else would be a picker of ticks that do nothing. - Both subscribe/secret lines get all-boards wording; `cal.all.*` keys in en and de. ## Also fixed (pre-existing, found by the new tests) `/admin/boards` could 500 on load: `ReloadAsync` published `_boards` before `_edits` was filled, and `ComponentBase` renders after the first `await` in `OnInitializedAsync` — so a slow second query made `_edits[board.Id]` a `KeyNotFoundException` out of the prerender. Both are now assigned after every query returns. ## Verified - `dotnet build Ponente.sln` clean (no new warnings); `dotnet test` **191 passed** — including 26 new ones: `CalendarScopeTests` (query parsing/round-trip, strict refusal), board lanes in `CalendarTimelineTests`, `BoardFilter.MatchesBoard`, and the all-boards `X-WR-CALNAME` in en/de. The en/de key-parity test covers the new strings. - New **`tests/e2e/calendar-all.spec.js`** (4 tests) run against the real compose stack in this container — cards from both boards on the page and only one board's on a board's own calendar, board lanes in the timeline, the switcher offering/naming/leaving it (and *not* offering it in the board section), the legend narrowing by board with the export link following, and `/calendar.ics?board=all|<id>|garbage` → 200/200/404. Green three consecutive runs. - The pre-existing `calendar.spec.js` / `boards.spec.js` failures in this environment are timing flakes, not regressions: I rebuilt the stack from `main` with my changes stashed and got the *same or more* failures (boards 6 vs 5, calendar 11 vs 9), all of them clicks landing before the Blazor circuit is up in cleanup helpers I didn't touch. `CLAUDE.md` has a new **"The general calendar: every board at once"** section under the calendar chapter, plus pointers from the routes paragraph and the `.ics` one. Compare: https://git.grandiras.net/Grandiras/Ponente/compare/main...claude/issue-85 --- ⏱ 55m 38s · 189 turns · tokens: 290.1k in / 101.4k out (+38804.5k cache-read) 📜 [Full session transcript](https://git.grandiras.net/Grandiras/claude-bot/src/branch/claude-logs/transcripts/Grandiras/Ponente/issue-85/run-227.md) → Opened PR: https://git.grandiras.net/Grandiras/Ponente/pulls/88
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
2 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#85
No description provided.