Commit Graph

4 Commits

Author SHA1 Message Date
mAi
085e672dd5 refactor(dashboard): cache via internal/cache.TTLCache
Phase 5b slice B. dashboardCache deleted. The Server's dashboard field
is now `*cache.TTLCache[*dashboardPayload]` constructed via
`cache.NewTTL[*dashboardPayload](dashboardCacheTTL)`. All call sites
renamed:

- s.dashboard.get(k)         → s.dashboard.Get(k)
- s.dashboard.set(k, p)      → s.dashboard.Set(k, p)
- s.dashboard.invalidate(k)  → s.dashboard.Invalidate(k)
- s.dashboard.invalidateAll  → s.dashboard.InvalidateAll
  (across web/dashboard.go, web/server.go, web/caldav.go,
   web/links.go, web/gitea_writeback.go)

The 64-line dashboardCache struct + methods are gone; the dashboard
file shrinks by ~63 lines. TTL constant lifted out to
`dashboardCacheTTL = 60 * time.Second` so the const lives next to its
semantics rather than a magic-number literal in New().

All web/dashboard_*test.go pass unmodified.

Task: t-projax-5b-cache
2026-05-22 00:25:13 +02:00
mAi
4e919babed refactor(timeline): consume internal/aggregate/
Phase 5a slice B. Replace web/timeline.go's hand-rolled fan-out + day
grouping with calls into the aggregator package.

- web/timeline.go: collectTimelineTodos + collectTimelineEvents +
  in-line day grouping deleted. buildTimeline now calls
  aggregator.Todos/Events/Docs/Creations, decorates each typed row
  with the template-friendly TimelineRow shape (PER, StartLabel,
  DurationHint), then hands rows to aggregate.BuildTimelineDays for
  sorting + sticky-pill markers + far-future fade.
- web/timeline.go: TimelineRow / TimelineDay are now type aliases for
  the aggregate package's versions (Phase 5a slice A introduced them
  with the same flat-field layout the templates already address).
- web/server.go: new Server.Aggregator() factory builds a fresh
  *aggregate.Aggregator wired to the server's current CalDAV/Gitea
  deps (so main.go can install those after web.New without a re-init
  hook).
- web/{gitea,dashboard,gitea_writeback,gitea_test}.go: issueCache
  methods capitalised (Get/Set/Invalidate) so the aggregator's
  IssueCache interface accepts *web.issueCache directly. No behaviour
  change.

All web/timeline_*test.go pass unmodified — the refactor preserves
output shape and template field paths.

Task: t-projax-5a-aggregator
2026-05-22 00:05:14 +02:00
mAi
5dcacff520 feat(phase 4b): dark/light theme toggle + file-upload permanently out-of-scope
## Slice A — explicit dark/light toggle

projax now ships with two palettes and a 1y cookie to remember the choice.
Dark is the new default; ☀ button in the header nav flips to light and
writes projax_theme=light. Server reads the cookie via themeFromRequest(r)
and injects Theme + ThemeColor into every template via the centralised
render(w, r, …) path, so first paint never flashes the wrong theme. Inline
JS in layout.tmpl handles the toggle without a server roundtrip.

Every panel colour now lives in a CSS variable under
:root[data-theme=dark|light]; the only hardcoded hex values left are
inside those two :root blocks. A future palette tweak is one edit, not
30 selectors. Graph node colours, kind-badges, highlights and warn/ok/bad
all have parallel dark/light values picked for contrast.

Standalone SVG download bakes the light palette inline because the
downloaded asset has no parent :root providing vars — m's existing
snapshots stay print-friendly regardless of his current cookie.

Login page keeps its embedded dark CSS — it's the gateway, intentionally
always dark.

Tests: TestThemeDefaultIsDark, TestThemeCookieRoundTrips,
TestThemeCookieUnknownFallsBackToDark, TestThemeTogglePagesShareSameTheme,
TestThemeToggleScriptPresent, TestThemeColorMetaHelper. Full suite green.

## Slice B — file-upload permanently out of scope (m, 2026-05-17)

docs/design.md moves "File uploads / in-projax storage" from the §3c
parked list to a permanent "Out of scope (decided 2026-05-17)" clause
with the rationale: PER is the cross-reference index, not the file
system. docs/standards/per.md gains the same explicit clause so future
shifts working from the PER standard see the constraint where they
look. Memory note filed so future workers don't re-propose multipart
uploads, attachments tables, or documents buckets.

## docs/design.md §13 Theming

Documents the toggle approach, cookie semantics, palette table, the
standalone-SVG carve-out, the login-page exception, and the 4b
out-of-scope (prefers-color-scheme detection, per-page overrides,
transitions on swap).
2026-05-17 18:14:08 +02:00
mAi
5a56ad91e5 feat(phase 3h gitea writeback): close/reopen/comment/create from projax
- gitea pkg: CloseIssue, ReopenIssue, CreateIssue, AddComment + ErrForbidden
  classification on 401/403. Client.do sets Content-Type on non-empty bodies.
- web handler: POST /i/{path}/issues/{close|reopen|comment|create}
  - authorisation guard: repo form value must match a gitea-repo item_link
    on the target item (rejects form-crafted writes to unrelated repos)
  - HTMX re-renders issues_section partial after each action
  - busts gitea per-repo cache (open + closed-recent) and dashboard 60s TTL
- templates: ✓ close button + reopen + collapsible comment box on every
  issue row; "+ new issue" disclosure per repo
- design.md §6 retitled "Phase 2.d read; 3h writeback" with auth/perm
  semantics + parked list
- 5 unit tests in gitea/, 5 integration tests in web/ covering happy paths
  + 403 → inline banner fallback
2026-05-15 19:22:11 +02:00