d4df81e37494dc52d75f3f5c8f3c107dacff0f2b
9 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
| e56cb3b210 |
feat(checklists): t-paliad-225 Slice C frontend — Geteilte Vorlagen tab + outdated-template badge
m/paliad#61 Slice C frontend pass. Discovery (Geteilte Vorlagen): - New 4th tab on /checklists between "Meine Vorlagen" and "Vorhandene Instanzen". Filters the merged catalog response to authored entries not owned by the caller (firm-visible OR globally-promoted OR share-recipient). Tab state round-trips via ?tab=gallery. - Regime filter pills (UPC / DE / EPA / OTHER) operate independently from the main Vorlagen tab. - Cards show regime badge, item count, author line, visibility chip. - Self-filter relies on /api/me email match — loadMe() fires once on page boot and is idempotent. Versioning UI on /checklists/instances/{id}: - "Vorlage aktualisiert" badge appears when the instance's template_version is known AND lags the live template version (only for authored templates; static templates never bump). Shows "v{from} → v{to}" delta. - "Änderungen anzeigen" button opens a diff modal that compares the instance's template_snapshot against the live template body. Item-level grouping by (section title, item label). Surfaces added / removed / changed items with localised section labels. Empty state when only metadata changed. i18n: 13 new keys per language (DE + EN) under checklisten.tab.gallery, checklisten.gallery.*, checklisten.filter.other, and checklisten.instance.{outdated,diff}.*. Total 2666 keys. Build hygiene: bun run build clean; i18n scan clean. Go build/vet/test + TestBootSmoke ./cmd/server/ all green. |
|||
| 7a1fd81d23 |
feat(checklists): t-paliad-225 Slice A frontend — Meine Vorlagen + authoring wizard
m/paliad#61 Slice A frontend pass. Pages: - /checklists gets a third tab "Meine Vorlagen" between Vorlagen and Vorhandene Instanzen — lists owned authored templates with regime badge, visibility chip, Bearbeiten / Löschen actions, "Neue Vorlage" CTA. Tab state round-trips via ?tab=mine. - /checklists/new and /checklists/{slug}/edit serve a shared bundle (checklists-author.html). Client reads location.pathname to decide create vs edit mode; edit mode prefills from /api/checklists/templates/mine. Wizard: - Metadata form (title, description, regime UPC/DE/EPA/OTHER, court, reference, deadline, language de/en, visibility private/firm). - Repeating section + item editor — add/remove sections, add/remove items per section, label + optional note + optional rule per item. - Single-language authoring (lang column on paliad.checklists). The catalog read layer mirrors the title/description onto both DE and EN sides so the existing bilingual frontend renders without a special case for authored entries. - Save POSTs (create) or PATCHes (edit) the template; visibility flip on edit goes through its own endpoint so the audit row captures the transition. Merged catalog: - /api/checklists now returns the merged list (static + DB visible); the Summary shape gained origin / visibility / owner_email / owner_display_name fields. i18n: 55 new keys per language (110 total) under checklisten.tab.mine.*, checklisten.mine.*, checklisten.author.*, checklisten.detail.* (Bearbeiten/Löschen labels for Slice B). i18n codegen total: 2621 keys. Build hygiene: bun run build clean, go build clean, go vet clean, go test ./internal/... + ./cmd/server/ all green. |
|||
|
|
ba2408eb51 |
feat(paliadin/inline-widget): t-paliad-161 Slice C — floating button + slide-out drawer
The inline Paliadin chat surface — reachable from every authenticated
page, replacing the standalone /paliadin route as the primary entry
point. The standalone page survives as the dedicated full-screen mode
(the drawer's "↗ fullscreen" action links to it).
Components:
- frontend/src/components/PaliadinWidget.tsx — emits the floating
trigger button (bottom-right, lime ✨, owner-revealed by JS), a
scrim, and the right-edge slide-out drawer with header (reset /
fullscreen / close), context chip, message stream, empty-state
starter list, and textarea+send form. Loads /assets/paliadin-widget.js.
- frontend/src/client/paliadin-widget.ts — runtime. /api/me probe
reveals the trigger when caller matches PaliadinOwnerEmail (with
optional is_paliadin_owner flag fast-path); Cmd+J / Ctrl+J shortcut
toggles open/close (Cmd+K stays reserved for global search per
client/search.ts). Uses computePaliadinContext() (Slice B) per send
so route + entity + selection flow into every turn. SSE consumer
writes assistant bubbles; localStorage persists per-session history.
- frontend/src/client/paliadin-starters.ts — per-route starter prompt
registry. 14 routes covered (dashboard, projects.*, deadlines.*,
appointments.*, agenda, events, inbox, tools.*, glossary, courts) +
a _default fallback. Bilingual (DE/EN); prompts ending in `: ` seed
the textarea for the user to finish; fully-formed prompts auto-send.
- 39 authenticated TSX pages get a `<PaliadinWidget />` element after
`<Footer />` via a mechanical pass. paliadin.tsx (the standalone)
is intentionally excluded — its dedicated UI is the widget's
fullscreen escape hatch, not a place to overlay another widget.
- frontend/build.ts registers the new bundle.
- frontend/src/styles/global.css gains ~280 lines of widget CSS
(trigger / scrim / drawer / header / context-chip / messages /
bubbles / starters / form / send-btn) using only existing tokens.
Mobile (≤640px): drawer goes full-screen; trigger lifts above
bottom-nav slots.
- 11 new i18n keys × 2 langs = 22 entries under paliadin.widget.*.
Visibility predicate (paliadin-context.shouldSendContext) hides the
widget on /paliadin, /login, /onboarding. Owner-only gate stays on
PaliadinOwnerEmail.
Build clean: i18n 1955 → 1966 keys, IIFE-wrapped 218KB bundle, go test
green.
Refs: docs/design-paliadin-inline-2026-05-08.md §3, §5.
|
||
|
|
df321acb63 |
feat(t-paliad-097): clickable checklist references + Vorhandene Instanzen tab
Two related checklist UX gaps:
1. Checklist events in a project's Verlauf tab were unclickable — and
nothing in the project_events row carried the originating instance ID.
Add an `insertProjectEventWithMeta` helper, write
{"checklist_instance_id": <uuid>} as project_events.metadata for
checklist_created / _renamed / _linked / _unlinked / _reset (skipped
for _deleted — instance is gone). Surface metadata on
/api/projects/{id}/events and on dashboard recent_activity. The
Verlauf renderer wraps the title in <a href="/checklists/instances/{id}">
when metadata.checklist_instance_id is present, and the dashboard's
activity feed deep-links the project ref to the instance directly for
checklist_* events. Existing rows (metadata `{}`) stay non-clickable —
no migration backfill needed.
2. /checklists previously demanded a template pick before any existing
instance was reachable. Add a tab nav (Vorlagen / Vorhandene Instanzen)
using the existing entity-tab pattern. New endpoint
GET /api/checklist-instances and ChecklistInstanceService.ListAllVisible
return every visible instance across templates + projects, joined with
project ref/title and sorted by created_at DESC. Rows show template,
instance name (linked), project link (or "Persönlich"), progress bar,
and created date. URL state (?tab=instances) keeps the active tab
shareable. EN + DE i18n covered for tab labels and column headers.
Also adds event.title.checklist_* localizations for the Verlauf header
that translateEvent looks up.
|
||
|
|
b21dacf15c |
feat(t-paliad-063): adopt HLC brand palette across paliad
Replace ad-hoc lime/forest-green system with the official 4-color HLC palette. Lime + midnight are the primary pair; cyan + cream supporting. Tokens - :root now exposes --hlc-lime, --hlc-midnight, --hlc-cyan, --hlc-cream plus channel-token siblings (--hlc-*-rgb) so tints can be expressed as rgb(var(--hlc-*-rgb) / a) without hex literals. - --color-bg → cream, --color-text/--color-hero-bg → midnight, --color-accent → lime, --color-accent-dark → midnight (foreground on lime; passes WCAG AA where #fff failed). - New --sidebar-* tokens for the dark sidebar surface. Sweep (frontend/src/styles/global.css) - Replaced every hard-coded #c6f41c / #65a30d / #84cc16 / #b8e616 / #4d7c0f / #1a2e1a / #1a1a2e / #1a2e05 with the matching var(...). - rgba(101,163,13,a) and rgba(198,244,28,a) collapsed to rgb(var(--hlc-lime-rgb) / a). - text-on-lime now uses var(--color-accent-dark) instead of #fff; btn-danger keeps white on red. Sidebar reskin (cronus's audit, F-30) - Background: midnight; text: cream (muted via cream-channel alpha); active/hover: lime. Border + hover use cream-channel alphas so no rgba hex creep on the dark surface. Brand assets - manifest.json theme_color → lime, background_color → cream. - icon.svg / icon-maskable.svg base recoloured to lime + midnight glyph. - 32× <meta name="theme-color"> across pages updated to #BFF355. - Email templates (base.html, invitation.html) lime accent updated; mail_service_test.go expectation tracks the new hex. Deferred / out of scope - PNG icons under public/icons/ are baked artefacts; regen left to the next deploy. - Categorical chip colours (office tints, traffic-light red/amber/green, termin-type hues) are functional, not brand, and deliberately untouched. - Dark mode is not in scope. Verified - bun run build clean. - go build ./... clean; mail render tests pass. - Visual sweep at 1280×900 against frontend/dist via Playwright on /, /login, /dashboard, /projects, /agenda, /team, /fristenrechner, /glossary — sidebar midnight + lime active, cream page bg, white cards, midnight text on lime CTAs. Supersedes audit findings F-14, F-30, F-31. |
||
|
|
8921830f43 |
feat(pwa): app-shell phase 2 — manifest + icons + service worker + install prompt (t-paliad-042)
Ship the installability bits that t-paliad-041 deferred so iOS / Android users can add Paliad to their home screen. What landed: - frontend/public/manifest.json — name=Paliad, theme_color #65a30d (lime), display=standalone, scope=/, start_url=/dashboard, four icon entries (192/512 × any/maskable). Served from /manifest.json with the spec-mandated application/manifest+json content type (servePWAManifest in internal/handlers/pwa.go). - frontend/public/icons/ — lime "p" logo rendered to 192/512 PNGs in both "any" and maskable variants (maskable variant has extra safe-zone padding), 180×180 apple-touch-icon, 32×32 favicon. SVG sources kept under frontend/icons-src/ for regeneration via rsvg-convert. - frontend/public/sw.js — minimal cache-first for /assets/* and /icons/*, network-first for /api/*, network passthrough for everything else. CACHE_VERSION + activate-clean lets us bump and purge cleanly. Served from /sw.js so its scope can claim /; Service-Worker-Allowed: / header set, no-cache on the SW file itself so updates take effect on next load. - frontend/src/components/PWAHead.tsx — head fragment (manifest link, apple-touch-icon, favicon, app-name metas, <script src="/assets/app.js" defer>). Added to all 30 page TSX files via mechanical insertion. - frontend/src/client/app.ts — universal client bundle loaded on every page. Three jobs: register the service worker, init the BottomNav (icarus flagged that bottom-nav.ts was written but never wired into the build — m reproduced the broken [+] Anlegen and Menü buttons in prod), and surface the install banner. - frontend/src/client/pwa-install.ts — install banner UI. Two flows: beforeinstallprompt for Chromium/Android (deferred → CTA → prompt), one-time iOS Safari hint pointing at the share sheet. Both dismissals persist in localStorage (paliad-install-dismissed / -ios-shown). - frontend/src/styles/global.css — banner styles, sits above BottomNav on mobile and pinned bottom-right on desktop, lime-on-white card with the brand "p" mark. - frontend/build.ts — copies frontend/public → dist verbatim so the manifest, icons, and SW land at the application root. Verification before merge: - bun run build clean, go build/vet/test clean. - Local server smoke: curl -sI confirmed manifest.json (200, application/manifest+json), all icon files (200, image/png), sw.js (200, Service-Worker-Allowed: /), app.js (200, text/javascript). - Playwright at 390×844: Chrome fired beforeinstallprompt, the banner rendered with "Paliad installieren" + "Installieren" CTA in German, dismiss persisted across reload via localStorage. Manifest validated in-browser (name/short_name/start_url/display/scope all correct, all four icon URLs returned 200). - The InvalidStateError on serviceWorker.register() seen in the MCP Playwright profile is a known headless flag; SW registration works in real Chrome / Safari on localhost and HTTPS production. Out of scope: push notifications, runtime offline mode (SW intentionally stays minimal — cache shell + assets, network passthrough for everything else). |
||
|
|
3f0c26fd3a |
feat(frontend): PWA mobile BottomNav + Quick-Add sheet (t-paliad-041)
Phone-first bottom navigation per pwa-baseline.md. Renders only at <768px; tablets and desktop are unchanged. Slots: Start / Projekte / [+] Anlegen / Agenda / Menü. - Center [+] opens a slide-up <dialog> sheet with three rows: Frist, Termin, Projekt. Native showModal() + ::backdrop, ESC and backdrop-tap dismiss, transform-based slide-up transition. - Right Menü slot reuses the existing Sidebar mobile drawer via a new exported toggleMobileSidebar() (DRY with the legacy hamburger handler). - Agenda slot carries a red-dot badge: count = today + overdue pending deadlines (live via /api/deadlines/summary, refreshed every 60s). Pulse animation when overdue > 0 — m: "Due is the latest we can do, OVERDUE is a catastrophy." - visualViewport resize watcher hides the bar when the on-screen keyboard opens (>100px height shrink) so it doesn't cover form fields. - safe-area-inset-bottom padding on the bar; main padding-bottom adjusts on phones so the last row stays above the bar. PWA shell groundwork (defers manifest/SW/install-prompt to follow-ups): - viewport-fit=cover on every page (required for safe-area to register) - theme-color #65a30d (lime), apple-mobile-web-app-capable, status-bar style — all 30 page heads updated in one sweep. Backend: deadline_service.SummaryCounts gains a `today` bucket so the Agenda badge can distinguish "due today" from "this week" without a new endpoint. Files added: frontend/src/components/BottomNav.tsx frontend/src/client/bottom-nav.ts Verified visually via headless chromium at 375x812, 800x600, 1280x800: phone shows BottomNav (5 slots, lime [+] elevated), tablet shows the existing hamburger only, desktop sidebar untouched. go build/vet/test and bun run build all clean. |
||
|
|
01de3f736b |
fix: update all script src references from German to English filenames
knuth's rename changed TS/TSX filenames but left <script src> tags pointing at old German JS names (akten-neu.js, fristen.js, termine.js, glossar.js, einstellungen.js, gerichte.js, checklisten.js). These 404'd in production. |
||
|
|
caf319e7ee |
refactor(rename): frontend TSX + client TS files, fetch URLs, nav hrefs
t-paliad-025 Phase 3 — frontend rename pass:
File renames (git mv, preserving history):
frontend/src/
akten.tsx → projects.tsx
akten-neu.tsx → projects-new.tsx
akten-detail.tsx → projects-detail.tsx
fristen.tsx → deadlines.tsx
fristen-neu.tsx → deadlines-new.tsx
fristen-detail.tsx → deadlines-detail.tsx
fristen-kalender.tsx → deadlines-calendar.tsx
termine.tsx → appointments.tsx
termine-neu.tsx → appointments-new.tsx
termine-detail.tsx → appointments-detail.tsx
termine-kalender.tsx → appointments-calendar.tsx
einstellungen.tsx → settings.tsx
checklisten*.tsx → checklists*.tsx
gerichte.tsx → courts.tsx
glossar.tsx → glossary.tsx
frontend/src/client/ — same renames, plus notizen.ts → notes.ts.
Render exports renamed (renderAkten → renderProjects, renderFristen →
renderDeadlines, …). build.ts rewired to new names.
Client-side changes:
* fetch() API paths: /api/projekte → /api/projects, /api/fristen →
/api/deadlines, /api/termine → /api/appointments, /api/notizen →
/api/notes, /api/gerichte → /api/courts, /api/glossar → /api/glossary,
/api/dezernate → /api/departments, /api/parteien → /api/parties,
/api/checklisten → /api/checklists. Legacy /api/akten aliases removed.
* Navigation href/template strings: /akten → /projects, /fristen →
/deadlines, /termine → /appointments, /einstellungen → /settings,
/notizen → /notes, /checklisten → /checklists, /gerichte → /courts,
/glossar → /glossary. Nested paths /neu → /new, /verlauf → /events,
/kinder → /children, /kalender → /calendar, /dokumente → /documents.
* Interface names in client TS: Frist → Deadline, Termin → Appointment,
Notiz → Note, Partei → Party, Akte → Project, ProjektMini → ProjectMini,
Dezernat → Department, DezernatMitglied → DepartmentMember.
* JSON wire-format keys follow backend: projekt_id → project_id, akte_id
→ project_id, frist_id → deadline_id, termin_id → appointment_id,
akten_event_id → project_event_id, dezernat_id → department_id,
termin_type → appointment_type.
Go handlers (projects_pages.go, deadlines_pages.go, appointments_pages.go,
checklists.go, courts.go, glossary.go) serve the correctly-named HTML
files from dist/.
Kept German (user-facing i18n + product names):
* i18n keys/strings (src/client/i18n.ts) — DE labels and their keys
* Product names: fristenrechner, kostenrechner, gebuehrentabellen
Build verified: go build / vet / test clean; bun run build clean;
dist/ contains all 26 English-named HTML pages.
|