b7360dd48e
4 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
| 5a4a99196e |
#300: route icon-only controls through IconButton/IconLink
All checks were successful
CI / Auth e2e pack (pull_request) Successful in 8m36s
CI / Import/export fidelity gate (pull_request) Successful in 58s
CI / Lint, typecheck, test (pull_request) Successful in 6m22s
CI / Build container images (pull_request) Successful in 3m51s
CD / Build and push images (push) Successful in 15s
CD / Deploy to Test (push) Successful in 16s
CD / Smoke tests against Test (push) Successful in 1m16s
CD / Promote to Int (push) Successful in 13s
CI / Lint, typecheck, test (push) Successful in 6m32s
CI / Build container images (push) Has been skipped
CI / Auth e2e pack (push) Successful in 8m25s
CI / Import/export fidelity gate (push) Successful in 58s
The notification bell sat higher and larger than search and the theme toggle next to it. The cause was not the glyph: `.notifications-bell__button` carried its own rules with neither flex centring nor an icon size, so the svg was laid out inline on the text baseline and rendered at lucide's 24px default instead of the 1.15rem the shared `.icon-button` enforces. Route every icon-only control through the shared components instead: - `IconLink` joins `IconButton`, sharing one class helper. Three controls navigate (pond settings, graph, trash) and are links, not buttons — without a link twin they would have stayed the one group gluing the class on by hand. - 17 hand-applied `className="icon-button …"` usages across nine files now go through the components, which is what enforces the accessible name on a control that shows only an icon. - The bell's unread count reaches assistive technology. The badge sits inside the control, so `aria-label` hid it and a screen reader announced "Notifications" without ever saying how many. An ESLint rule keeps it that way: `icon-button` on a raw button, anchor or Link is now an error, in both string and template-literal form. The plugin uninstall button keeps a title that differs from its name (it explains why a required plugin is locked); IconButton spreads rest last, so the explicit title still wins. Also drops the graphify block from CLAUDE.md — it duplicates the workspace-level instructions. |
|||
| f9d23bf8d0 |
#151: Mention-Benachrichtigungen über die Glocke
Neuer Notification-Typ mentioned; abgeleitete Tabelle page_mentions (Migration), vom Collab-Persist transaktional neu geschrieben — der Diff gegen den Vorzustand wird als pg_notify (page_mentions_changed) emittiert, nur NEU Erwähnte lösen aus (kein Spam bei Folge-Saves). Der api-Listener (erweitert um den zweiten Kanal) ruft NotificationsService.fanoutMentions: Zustellung nur nach canAccessPage-Recheck, die Autoren (pending contributors) benachrich- tigen sich nie selbst; Payload wie gehabt mit Actor-Namen. API-seitig erzeugte Seiten seeden page_mentions aus deriveContent. Glocken-Text de+en; DB-Test (Leser ja / Outsider nein / Autor nein); kompletter Loop live verifiziert (Tippen → Persist → NOTIFY → Notification). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0155v2aT8AG1kZDQEZiCLBWC |
|||
| 9674c0bae2 |
Batch notifications into localized e-mail digests with unsubscribe (#95)
Some checks failed
CI / Lint, typecheck, test (push) Successful in 3m41s
CD / Build and push images (push) Successful in 3m44s
CI / Build container images (push) Has been skipped
CD / Deploy to Test (push) Successful in 9s
CD / Smoke tests against Test (push) Successful in 1m18s
CD / Promote to Int (push) Successful in 11s
CI / Auth e2e pack (push) Failing after 2m53s
CI / Import/export fidelity gate (push) Has been skipped
New per-user digestFrequency (hourly default | daily | off) on the profile and in the settings UI. A scheduler job (15 min cadence) mails a user once their oldest unread, unmailed notification exceeds the cadence window: one localized mail per batch, grouped per pond then per page with actor names and change/comment counts, enqueued through the mail outbox. Sending marks the batch mailed — never read — and re-checks page read permission per entry at send time; entries the user can no longer read are dropped from the mail but still marked handled, so revoked content cannot queue forever. Every mail carries a signed, single-purpose unsubscribe link: it only flips the setting to off, renders a session-free confirmation page, and sets no cookie. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EwZ4jR4KFAPvpjWevfUGX1 |
|||
| 67fb01fe2b |
Notify watchers about page changes and comments, with an in-app center (#94)
All checks were successful
CI / Lint, typecheck, test (push) Successful in 3m26s
CI / Build container images (push) Has been skipped
CD / Build and push images (push) Successful in 3m49s
CD / Deploy to Test (push) Successful in 9s
CD / Smoke tests against Test (push) Successful in 1m12s
CD / Promote to Int (push) Successful in 10s
CI / Auth e2e pack (push) Successful in 5m27s
CI / Import/export fidelity gate (push) Successful in 46s
New notifications table (payload denormalized for join-free rendering; mailed_at already prepares the #95 digests). Generation fans page events out to page and pond watchers, excluding the actors, and re-checks page read permission per watcher at delivery time — a revoked watcher gets nothing. Sources: named version snapshots (api), new comments (api), and the collab server's automatic session-close snapshots — announced over a new pg NOTIFY channel (the reverse of the established api→collab bus) consumed by a dedicated LISTEN client in the api, since the collab server has no permission resolution of its own. API: paginated list (unread first via nulls-first ordering), mark read, mark all read. UI: bell with unread badge in the top bar (30 s polling, no push in v1) and a dropdown whose entries navigate and mark themselves read; comment notifications deep-link with ?comments=1, which now opens the comments panel on load. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EwZ4jR4KFAPvpjWevfUGX1 |