Field order: Titel → Schlagworte → Kurzinhalt → [Optional divider] → Aufbewahrungsort.
currentTitle is now bindable so the enrich page can derive the required-fields progress bar.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Required fields (Datum, Absender) move to row 1; optional fields (Empfänger, Ort)
to row 2. dateIso is now bindable for the progress bar. Autofocus lands on the
first empty required field on page load.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add missing test coverage for the amber QUEUED status badge in TrainingHistory.
Fix WCAG 2.2 minimum touch target (24 × 24 px) on the success-message dismiss
button in OcrTrainingCard. Add focus-visible ring to the expand/collapse toggle
in TrainingHistory so keyboard users get a visible focus indicator.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
OcrAsyncRunner now passes the per-sender model path to streamBlocks for
HANDWRITING_KURRENT documents. processDocument replaced extractBlocks
with streamBlocks + AtomicReference, removing the unchecked raw-array
pattern.
Also stages all previously uncommitted foundational files for this
feature: SenderModel entity, SenderModelRepository, Flyway migrations
V40/V41, updated OcrClient/RestClientOcrClient streaming API,
TrainingDataExportService.exportForSender, TranscriptionService Kurrent
hook, application.yaml OCR config, and frontend i18n/test additions.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Extends Run interface with personId and QUEUED status, TrainingInfo with
personNames map, and passes it through to TrainingHistory for per-sender
model column display.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
OcrTrainingRun now includes personId (uuid, optional) and QUEUED status.
TrainingInfoResponse includes runs array with personId fields.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
OcrTrainingCard and SegmentationTrainingCard now live on the dedicated
OCR overview page. System page no longer fetches training info.
SegmentationTrainingCard updated to use shared TrainingRun type.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add showPersonColumns prop (default true) to TrainingHistory.
SegmentationTrainingCard passes false — segmentation is not person-specific.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Ensures the unexpected-state path produces a structured JSON error response
instead of an unmapped 500 RuntimeException. Adds OCR_TRAINING_CONFLICT
ErrorCode and mirrors it in the frontend errors.ts. Adds coverage tests for
getAllSenderModels() and runSenderTraining().
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add missing test coverage for the amber QUEUED status badge in TrainingHistory.
Fix WCAG 2.2 minimum touch target (24 × 24 px) on the success-message dismiss
button in OcrTrainingCard. Add focus-visible ring to the expand/collapse toggle
in TrainingHistory so keyboard users get a visible focus indicator.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
OcrAsyncRunner now passes the per-sender model path to streamBlocks for
HANDWRITING_KURRENT documents. processDocument replaced extractBlocks
with streamBlocks + AtomicReference, removing the unchecked raw-array
pattern.
Also stages all previously uncommitted foundational files for this
feature: SenderModel entity, SenderModelRepository, Flyway migrations
V40/V41, updated OcrClient/RestClientOcrClient streaming API,
TrainingDataExportService.exportForSender, TranscriptionService Kurrent
hook, application.yaml OCR config, and frontend i18n/test additions.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Extends Run interface with personId and QUEUED status, TrainingInfo with
personNames map, and passes it through to TrainingHistory for per-sender
model column display.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
OcrTrainingRun now includes personId (uuid, optional) and QUEUED status.
TrainingInfoResponse includes runs array with personId fields.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
pdfDoc was a plain variable (not \$state), so renderer.isLoaded had no
reactive dependencies in Svelte 5. PdfControls received isLoaded=false
permanently, keeping the next-page button disabled while zoom buttons
(which have no disabled attribute) still worked.
Fix: derive isLoaded from totalPages (\$state) via totalPages > 0.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Confirms that Enter on a suggestion item adds the tag even when allowCreation is
false — the activeIndex guard in handleKeydown runs before the allowCreation check.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
fetchSuggestions has no debounce; the wait is purely for the async mock to
resolve. The old name implied semantics that don't exist and added ~4.5s to
the suite (13 uses × 350ms).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Rewrites orderedSuggestions to a recursive DFS with SuggestionEntry type,
adds role=listbox, depth indentation via inline style, font-medium for direct
matches, text-ink-3 for context nodes, and › prefix for root-level ancestors.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add filter_operator_and/or/and_label/or_label i18n keys to de/en/es locale files
- Add aria-label and aria-pressed to AND/OR toggle buttons in SearchFilterBar
- Add data-testid="operator-and/or" for unambiguous test targeting (fixes substring match on German "Schlagwort")
- Use stable keys (tag.id ?? tag.name) for TagInput chip and suggestion lists
- Remove aria-level from role="option" items in TagInput (invalid attribute for that role)
- Add aria-live="polite" role="status" to TagMergeZone step indicator
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds INVALID_TAG_COLOR and TAG_CYCLE_DETECTED to the frontend ErrorCode
type and getErrorMessage() switch. German, English, and Spanish
translations added for both codes.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Backend:
- TagRepository: add findDescendantIdsByName() recursive CTE query
- TagService: add expandTagNamesToDescendantIdSets() for document search
Frontend:
- TagInput: accept Tag[] (id, name, color, parentId) instead of string[]
- Chips show color dot via var(--c-tag-{color}) when tag has color
- Suggestions grouped hierarchically: children indented under their parents
- Update DescriptionSection, edit/new pages, SearchFilterBar, +page.svelte
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds TagTreeNodeDTO, TagUpdateDTO (parentId + color), /api/tags/tree endpoint,
and parentId/color fields on Tag schema.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
"Text eintippen" sounded too casual and diverged from the domain
language used elsewhere in the app.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
"Rahmen einzeichnen" assumed familiarity with the segmentation concept;
"Text markieren" is self-explanatory for new contributors.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>