- api.ts: add GeschichteType, JourneyItem, GeschichteSummary schemas;
remove documentId param from list endpoint; change list response to
GeschichteSummary[]; add type + items to Geschichte; remove documents field
- GeschichteEditor: remove DocumentMultiSelect + documentIds from payload
(journey items are managed via the future Lesereisen editor, not here)
- GET /geschichten page: remove documentId filter from server load + URL logic
- geschichten/new: remove documentId pre-population from server load
- geschichten/[id]: replace g.documents with g.items (document-backed JourneyItems)
- geschichten/new + [id]/edit: remove documentIds from submit payload type
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Senior-author persona requires 44px minimum touch targets on every
interactive control. The /geschichten filter row had three pills
(All / chip / + Person wählen) at h-9 (36px), missing the rule that
the toolbar already follows. Bumped all three to h-11.
Test added in page.svelte.spec.ts asserts the className contains
h-11 on every pill variant.
Addresses Leonie's iteration-3 concern #6 on PR #382.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The /geschichten list page now renders one removable chip per active
person filter and lets users add more via the existing typeahead. The
URL uses repeated ?personId= params (matching the documents tag
filter), which the regenerated API client passes straight through to
the backend's new array-bound endpoint. New translation keys cover the
chip remove aria-label, the AND hint shown while picking, and the
multi-person empty state.
Adds a module docstring at the top of extractText.ts spelling out that this
is text extraction, not XSS sanitisation, and that callers must rely on
safeHtml() (DOMPurify) for security. Adds a Vitest test block with classic
XSS-shaped payloads (<script>, <svg/onload>, <iframe srcdoc>, javascript:
href) asserting that no markup is re-emitted, even though the module is
explicitly not a sanitiser.
Updates the two callers (/geschichten index, GeschichtenCard) to import
from the new path. The collapse-whitespace pass also makes the regex
fallback's output saner for excerpt rendering.
Closes Nora's review B1 on PR #382.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- /geschichten — published-stories index with filter pills + "+ Neue Geschichte"
for BLOG_WRITERs; supports ?personId and ?documentId pre-filtering
- /geschichten/[id] — reader detail with sanitised {@html} body, person and
document chip sections, BLOG_WRITER edit/delete with confirm dialog
- /geschichten/new — editor with optional ?personId and ?documentId pre-fill
(silent ignore on unknown IDs to avoid leaking entity existence)
- /geschichten/[id]/edit — editor populated from existing story; BLOG_WRITE
guard redirects readers to the detail page
All routes load via createApiClient(fetch) with !response.ok error handling
following the project pattern; PATCH/DELETE go through raw fetch which the
Vite dev proxy / Caddy production proxy authenticates via cookie.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>