- DocumentMetadataDrawer: 3-column grid (≥1024px), single-column mobile
Shows document date, location, status, person cards, tag chips
Person names link to /persons/{id}, tags link to filtered search
Empty states for missing persons/tags, receiver cap with expand button
- DocumentTopBar: "Details" toggle button with animated SVG chevron
44×44px tap target, aria-expanded, Svelte slide transition
Semantic color tokens for dark mode compatibility
- Remove DocumentBottomPanel from document detail page
Bottom panel replaced by topbar drawer for metadata access
Simplify +page.server.ts (remove comments loading)
Update page.server.spec.ts for new load signature
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Keys for #175: doc_details_toggle, section headings, field labels, empty states
Keys for #176: transcription mode, block editing, save states, comments, drawing hints
Error codes: TRANSCRIPTION_BLOCK_NOT_FOUND, TRANSCRIPTION_BLOCK_CONFLICT
All three languages: de, en, es
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
TranscriptionBlock entity with @Version optimistic locking
TranscriptionBlockVersion for edit history
TranscriptionService facade: CRUD, reorder, version history
TranscriptionBlockController: REST endpoints under /api/documents/{docId}/transcription-blocks
DTOs: Create, Update, Reorder
ErrorCode: TRANSCRIPTION_BLOCK_NOT_FOUND, TRANSCRIPTION_BLOCK_CONFLICT
DocumentComment: add block_id field for block-level comment threads
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
V18: transcription_blocks table with optimistic locking version column
V19: transcription_block_versions for edit history capture
V20: add block_id FK to document_comments for block-level threads
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Three final UI/UX specs for the collaborative transcription system:
- expandable-metadata-header-spec: labeled "Details" toggle with drawer
- annotation-transcription-final-spec: annotation-backed transcription with block-level comment threads
- transcription-read-mode-final-spec: clean split read mode with flowing prose and scroll sync
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove overflow-hidden from the main flex row — the inner min-w-0 flex-1
overflow-hidden title container already handles truncation. Add relative z-10
to the topbar wrapper so it stacks above the pdf viewer. Pill is now hidden
below md (matching the chip row) and shows +N at md, +N weitere at lg+.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Accent bar, h-12/h-14 responsive height, 44×44px back link touch target
- PersonChipRow with sender→receivers chips, overflow pill button at ≥768px
- DocumentStatusChip dot-only at ≥768px
- Edit/annotate/download actions with annotateMode wiring
- AnnotateHintStrip below main row when annotateMode active
- status field added to Doc type
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
On small screens the upload zone now appears above recent docs.
lg:order-last keeps it visually on the right at desktop width.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Restructures the dashboard to a lg:grid-cols-[1fr_300px] split:
- Left column: DashboardRecentDocuments (with stats footnote)
- Right column: DropZone (canWrite) + DashboardNeedsMetadata (flex-1)
Adds showRightColumn guard (canWrite || incompleteDocs.length > 0) so
read-only users with a complete archive never see an empty 300px ghost
column. DashboardMentions is removed from the page; the file is kept.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds stats?: StatsDTO | null prop; renders a quiet footnote showing total
document and person counts. Guards on stats?.totalDocuments != null so
zero is shown but the footnote is absent when stats fails. Adds
min-h-[44px] to doc rows for WCAG 2.5.5 touch target compliance.
Adds dashboard_stats_documents/persons i18n keys in de/en/es.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Removes /api/notifications from the dashboard widget fetches and replaces
it with /api/stats so the page no longer needs to own notification data.
Returns stats: StatsDTO | null (null on failure) instead of mentions.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Six categories of breakage:
1. date.ts — add formatGermanDateInput(raw: string): string as a pure
function covering both digit-stream auto-dot and manual-dot-with-padding
modes. Refactor handleGermanDateInput to delegate to it. Fixes 16 failures
in date.spec.ts where the function was imported but didn't exist.
2. Admin layout specs (groups/tags/users) — $effect fires on initial mount
with manualCollapse=false, so the spy captured 'false' before the click's
effect ran. Fix: move spy setup after render(), add await setTimeout(0) to
flush Svelte effects before asserting.
3. DashboardMentions — component now renders a persistent
"Benachrichtigungsverlauf ansehen" link, making getByRole('link') strict-
mode violations. Fix: scope link queries to the actor name, and check
absence of the actor link (not all links) in the no-documentId test.
4. Conversations page — empty-state copy changed from "Wählen Sie zwei
Personen aus" to "Korrespondenz durchsuchen". Update the test.
5. Login page — AuthHeader adds a second aria-label="Familienarchiv" link.
Use .first() to avoid strict-mode violation.
6. Persons page — alias is rendered with German quotation marks „…" not
straight quotes "…". Update the test string.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The password-reset E2E test was using button[type="submit"].last() to target
the password change button on the profile page. The profile page has two submit
buttons with identical text, so .last() is layout-order-dependent and breaks
if the form order ever changes.
Add data-testid="submit-password" to PasswordChangeForm and use getByTestId()
in the test.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>