Commit Graph

498 Commits

Author SHA1 Message Date
Marcel
f68c892170 fix(chronik): sentinel-based title split + drop duplicate comment preview
Two PR #288 blockers from Felix and Leonie:

Felix: verbText.indexOf(docTitle) broke when the title was empty (indexOf
returned 0, the before/after slices both emptied) or when the title
substring-matched any word in the compiled Paraglide message (e.g. "Brief"
appearing inside a translated verb). Swap to a sentinel approach: interpolate
{doc} with U+0001, then split the compiled text on that sentinel — robust
regardless of title content or translator sentence order. Two new red tests
lock the invariant: empty title still renders the row link; short titles
that could substring-match render exactly once as a single chronik-doc-title
span.

Leonie: the comment variant rendered „{documentTitle}" as a placeholder,
which made the row show the same title twice — once as the underlined link,
once as the italic "preview quote" — implying the comment was quoting
itself. Replace with an italic ellipsis „…". A new red test asserts the
preview no longer contains the document title text verbatim.

While here, add a SECURITY comment next to the TODO so the next person who
wires item.commentPreview knows the backend must truncate/strip server-side
and the frontend must use {text}, never {@html} (Nora, issue #285 #3552).

Part of #285, address PR #288 review.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 20:38:10 +02:00
Marcel
58ea2f827a fix(chronik): split Für-dich row markup — Dismiss is sibling of link, not nested
HTML5 forbids interactive content (<button>, <a>, <input>...) as descendants
of <a>. The original <a href=…><button>✓</button></a> markup triggered two
concrete bugs flagged by Felix, Nora, and Leonie in PR #288 review:

- Browsers inconsistently route the nested click: on some engines the
  stopPropagation() still bubbles, and the user navigates into the document
  instead of dismissing.
- The senior audience (60+) tap-selects with a slight drag, and the OS
  treats the interaction as anchor vs. button inconsistently — a
  reproducible usability failure Leonie has seen in testing before.

Refactor to the Option-C layout from issue #285 comment #3573: outer <li>
flex container, <a> wrapping avatar + body + time, <button> as a sibling.
Independent focus stops, invalid-HTML gone, no behavioural regression.

A new spec locks the invariant: `dismiss.closest('a')` must be null.

Part of #285, address PR #288 review.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 20:38:10 +02:00
Marcel
93c80671e2 fix(notifications): retarget bell dropdown footer to /chronik
The "Alle anzeigen" link at the bottom of the notification dropdown now
points to /chronik with the new "Zur Chronik →" label key, matching the
unified activity page introduced in #285.

Part of #285.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 20:38:10 +02:00
Marcel
81f86474b6 fix(dashboard): retarget feed footer to /chronik + render rollup rows
- "Alle anzeigen" link now goes to /chronik (was /documents — the dead-end
  bug called out in #285).
- Rollup rows (count > 1) render a primary-colored count badge plus a
  compound timestamp line: "14. Apr. · 14:02–14:32" (en-dash U+2013).
- Singleton rows render the existing "14. Apr. 2026" date line.
- BLOCK_REVIEWED now has a verb mapping (re-using the annotation verb until
  the spec pins a distinct copy).
- Three new spec cases: rollup count badge + en-dash range, no badge on
  singletons, /chronik link assertion.

Part of #285.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 20:38:10 +02:00
Marcel
e36c9382fc feat(chronik): add six Chronik page components + co-located specs (40 tests)
All under src/lib/components/chronik/:

- ChronikRow.svelte — single orchestrator for four variants (comment / for-you /
  rollup / simple), discriminated via $derived. Outer <a> wraps avatar + body +
  time; document title is a styled <span> (no nested anchors). Rollup shows
  count badge + en-dash time range; for-you gets accent left border + @ marker
  hidden below sm:.
- ChronikTimeline.svelte — buckets items by day using bucketByDay() and renders
  Heute/Gestern/Diese Woche/Älter section headers with <span> trailing rule.
- ChronikFuerDichBox.svelte — unread mentions card with inbox-zero variant,
  per-row Dismiss button (prevents bubbling, calls onMarkRead), aria-live count
  badge, and a .fade-in class gated by prefers-reduced-motion.
- ChronikFilterPills.svelte — role=radiogroup with 5 pills, ArrowLeft/Right
  keyboard navigation wrapping across the group, single tabstop via dynamic
  tabindex.
- ChronikEmptyState.svelte — three variants (first-run / filter-empty /
  inbox-zero) sharing a centered-column layout.
- ChronikErrorCard.svelte — warning card with retry button, optional custom
  message override.

Verbs map to chronik_singleton_* / chronik_rollup_* per AuditKind so no ICU
pluralization is needed. Comment preview is a TODO placeholder (currently the
document title) pending a backend preview DTO follow-up.

All 40 unit tests green. No type-check or lint errors in these files.

Part of #285.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 20:38:10 +02:00
Marcel
f13b2a984e fix(notifications): retarget NotificationItem import to singleton store
Left over from the hook→singleton refactor — NotificationDropdown still
imported from the deleted $lib/hooks path.

Part of #285.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 20:38:10 +02:00
Marcel
5fc39b0371 refactor(notifications): convert per-component stream hook to module-level singleton
Replaces the per-component createNotificationStream() factory with a shared
$lib/stores/notifications.svelte.ts singleton. Ref-counted init()/destroy()
ensures one EventSource per tab no matter how many consumers mount
simultaneously.

Motivation: the /chronik "Für dich" box (#285) needs the same live-arrival
stream that NotificationBell already consumes. Two factories would open two
SSE connections per tab — this refactor avoids the silent regression before
it ships.

- New: src/lib/stores/notifications.svelte.ts (module state, refcount)
- New: src/lib/stores/notifications.svelte.spec.ts (proves single EventSource
  across multiple consumers + ref-counted teardown)
- Deleted: src/lib/hooks/useNotificationStream.svelte.ts (factory)
- Deleted: src/lib/hooks/__tests__/useNotificationStream.svelte.test.ts
- NotificationBell now imports the singleton

Part of #285.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 20:38:10 +02:00
Marcel
eb3a54b19c fix(document-row): align contributor circles with progress ring
The ProgressRing renders SVG + percentage label as a flex column (~52px
total). With items-center, the contributor circles aligned to the middle
of the full block, placing them 8px below the ring center. Changed to
items-start on the container and wrapped ContributorStack in h-9 (36px =
SVG height) flex items-center so both circles center at the same 18px.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 11:29:33 +02:00
Marcel
4e1d0b1cf0 chore: merge main into feat/issue-281-documents-page
Some checks failed
CI / Unit & Component Tests (pull_request) Failing after 2m39s
CI / OCR Service Tests (pull_request) Successful in 29s
CI / Backend Unit Tests (pull_request) Failing after 2m50s
CI / Unit & Component Tests (push) Failing after 2m31s
CI / OCR Service Tests (push) Successful in 31s
CI / Backend Unit Tests (push) Failing after 2m52s
Resolved 9 conflicts:
- AuditLogQueryRepository/Service: keep HEAD (findRecentContributorsForDocuments)
- ContributorStack: merge main key fix + text-[10px] with HEAD safeColor + aria
- DashboardResumeStrip: merge main text-[10px] with HEAD safeColor
- +page.server/svelte + tests: keep HEAD (pure dashboard, no isDashboard)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 08:54:17 +02:00
Marcel
55ce696428 fix(dashboard): fix ContributorStack each-block key and add accessible avatar labels
- Replace (actor.name ?? actor.initials + i) with (actor.initials + '-' + actor.color)
  to fix operator-precedence bug that made keys order-dependent when name is null
- Add role="img" + aria-label={actor.name ?? actor.initials} so screen readers
  and touch users can access contributor names

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 07:45:16 +02:00
Marcel
3ede42503a fix(dashboard): i18n, a11y, security, and type-safety fixes from PR review
- Use @RequiredArgsConstructor in AuditLogQueryService; remove unused import
- Add 401/403 tests for /activity endpoint
- Add getPulseStats and findContributorsPerDocument integration tests
- Use m.pulse_headline/pulse_you in FamilyPulse; composite avatar keys
- Replace hover:text-accent with hover:text-ink in ActivityFeed (WCAG AA)
- Localise "Alle →" link with feed_show_all key + aria-label
- Gate DropZone behind {#if data.canWrite}
- Export DashboardResumeDTO, DashboardPulseDTO, ActivityFeedItemDTO from api.ts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 07:45:16 +02:00
Marcel
117044aad9 docs(spec): add /documents page design spec with mobile breakpoints
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 07:45:16 +02:00
Marcel
eac025dec1 feat(dashboard): show block count instead of page numbers in resume strip
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 07:45:16 +02:00
Marcel
7506f8743a fix(dashboard): defensive null guard in ContributorStack; fix spec makeDoc factories 2026-04-20 07:45:16 +02:00
Marcel
520cca58b8 feat(dashboard): show contributor pill stack on each mission control queue item
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 07:45:16 +02:00
Marcel
4bd1ebfd1e feat(dashboard): add ContributorStack component for mission control pill stacks
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 07:45:16 +02:00
Marcel
5a98edac86 feat(dashboard): complete frontend redesign for Issue #271
- +layout.svelte: Upload button in header (authenticated users only)
- +page.server.ts: call /api/dashboard/resume, /pulse, /activity;
  remove deprecated /api/documents/incomplete and /recent-activity
- +page.svelte: 2-col grid layout (main + 320px sidebar), greeting,
  DashboardFamilyPulse + DashboardActivityFeed in sidebar
- DashboardResumeStrip: refactored to use server data (resumeDoc prop),
  SVG thumbnail, progress bar with aria-*, empty state, CTA
- DashboardFamilyPulse: new component — weekly stats from audit_log
- DashboardActivityFeed: new component — activity feed with "für dich" badge
- Update specs for new data shapes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 07:45:16 +02:00
Marcel
da2ece986a fix(documents): WCAG text-size and API error pattern fixes
Some checks failed
CI / Unit & Component Tests (pull_request) Failing after 2m37s
CI / OCR Service Tests (pull_request) Successful in 29s
CI / Unit & Component Tests (push) Failing after 2m44s
CI / OCR Service Tests (push) Successful in 38s
CI / Backend Unit Tests (push) Failing after 2m45s
CI / Backend Unit Tests (pull_request) Failing after 2m45s
- DashboardResumeStrip: text-[10px] → text-xs on collaborator initials (WCAG 1.4.4)
- documents/+page.server.ts: use !result.response.ok per CLAUDE.md; keep narrow try/catch for network-level failures only

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 01:17:04 +02:00
Marcel
f2bed92176 fix(review): cycle 3 — a11y, CSS injection, domain boundary
Some checks failed
CI / Unit & Component Tests (push) Failing after 2m44s
CI / OCR Service Tests (push) Successful in 34s
CI / Unit & Component Tests (pull_request) Failing after 2m33s
CI / OCR Service Tests (pull_request) Successful in 35s
CI / Backend Unit Tests (push) Failing after 2m56s
CI / Backend Unit Tests (pull_request) Failing after 2m48s
- DocumentRow: add data-testid="search-snippet"; sanitize tag.color with safeTagColor()
- ContributorStack: add role="img" aria-label to overflow "…" badge
- DocumentList: year header text-[10px] → text-xs (WCAG 1.4.4 minimum 12px)
- DashboardResumeStrip: sanitize collab.color with safeColor()
- Extract TranscriptionBlockQueryService to fix cross-domain repository access in DocumentService
- Update unit test mocks to use TranscriptionBlockQueryService

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 01:03:06 +02:00
Marcel
7f23e88b69 fix(documents): address review cycle 2 — a11y, CSS injection, debounce tests
Some checks failed
CI / Unit & Component Tests (pull_request) Failing after 2m33s
CI / OCR Service Tests (pull_request) Successful in 38s
CI / Unit & Component Tests (push) Failing after 2m40s
CI / OCR Service Tests (push) Successful in 36s
CI / Backend Unit Tests (push) Failing after 2m54s
CI / Backend Unit Tests (pull_request) Failing after 2m58s
- ContributorStack: text-xs for WCAG 1.4.4 (was text-[10px]), safeColor()
  validation to block CSS injection via actor.color, role="img" aria-label
  on empty placeholder, {#each} keyed by index
- ContributorStack spec: update empty-state assertion to getByRole('img')
- DocumentRow spec: add stopPropagation regression test for tag click
- documents/page.svelte.spec.ts: new — debounce, URL building, initial state

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 00:40:48 +02:00
Marcel
dc349947ef fix(a11y): add aria-hidden to decorative SVG and use text-xs for WCAG 12px minimum
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 00:24:36 +02:00
Marcel
80e10e1755 fix(docs): stop tag click propagation to prevent parent anchor navigation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 00:23:48 +02:00
Marcel
3707d34c62 test(docs): add DocumentRow unit tests — title, snippet, tags, sender, progress ring
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 00:23:08 +02:00
Marcel
648aa2a742 feat(frontend): add DocumentRow component with two-column layout, highlights, progress, contributors
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 23:44:31 +02:00
Marcel
ae0e3b271d feat(frontend): add ProgressRing component — SVG progress arc with percentage label
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 23:34:30 +02:00
Marcel
eeca30e7a6 feat(frontend): add --header-height, bump initials to text-[10px], update nav to /documents
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 23:24:46 +02:00
Marcel
5246638014 fix(dashboard): fix ContributorStack each-block key and add accessible avatar labels
- Replace (actor.name ?? actor.initials + i) with (actor.initials + '-' + actor.color)
  to fix operator-precedence bug that made keys order-dependent when name is null
- Add role="img" + aria-label={actor.name ?? actor.initials} so screen readers
  and touch users can access contributor names

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 22:28:00 +02:00
Marcel
2bb08b6877 fix(dashboard): i18n, a11y, security, and type-safety fixes from PR review
- Use @RequiredArgsConstructor in AuditLogQueryService; remove unused import
- Add 401/403 tests for /activity endpoint
- Add getPulseStats and findContributorsPerDocument integration tests
- Use m.pulse_headline/pulse_you in FamilyPulse; composite avatar keys
- Replace hover:text-accent with hover:text-ink in ActivityFeed (WCAG AA)
- Localise "Alle →" link with feed_show_all key + aria-label
- Gate DropZone behind {#if data.canWrite}
- Export DashboardResumeDTO, DashboardPulseDTO, ActivityFeedItemDTO from api.ts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 21:43:16 +02:00
Marcel
148710f2ed docs(spec): add /documents page design spec with mobile breakpoints
Some checks failed
CI / Unit & Component Tests (push) Failing after 2m35s
CI / OCR Service Tests (push) Successful in 27s
CI / Backend Unit Tests (push) Failing after 1m26s
CI / OCR Service Tests (pull_request) Successful in 31s
CI / Backend Unit Tests (pull_request) Failing after 1m28s
CI / Unit & Component Tests (pull_request) Failing after 2m33s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 21:39:56 +02:00
Marcel
18e321b1e6 feat(dashboard): show block count instead of page numbers in resume strip
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 21:32:13 +02:00
Marcel
64c5b40eae fix(dashboard): defensive null guard in ContributorStack; fix spec makeDoc factories 2026-04-19 19:22:52 +02:00
Marcel
0c65d5d748 feat(dashboard): show contributor pill stack on each mission control queue item
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 19:10:16 +02:00
Marcel
031f6ea29a feat(dashboard): add ContributorStack component for mission control pill stacks
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 19:06:46 +02:00
Marcel
10dbce1c70 feat(dashboard): complete frontend redesign for Issue #271
Some checks failed
CI / OCR Service Tests (push) Successful in 29s
CI / Backend Unit Tests (push) Failing after 1m21s
CI / Unit & Component Tests (push) Failing after 2m37s
CI / Unit & Component Tests (pull_request) Failing after 2m27s
CI / OCR Service Tests (pull_request) Successful in 30s
CI / Backend Unit Tests (pull_request) Failing after 1m21s
- +layout.svelte: Upload button in header (authenticated users only)
- +page.server.ts: call /api/dashboard/resume, /pulse, /activity;
  remove deprecated /api/documents/incomplete and /recent-activity
- +page.svelte: 2-col grid layout (main + 320px sidebar), greeting,
  DashboardFamilyPulse + DashboardActivityFeed in sidebar
- DashboardResumeStrip: refactored to use server data (resumeDoc prop),
  SVG thumbnail, progress bar with aria-*, empty state, CTA
- DashboardFamilyPulse: new component — weekly stats from audit_log
- DashboardActivityFeed: new component — activity feed with "für dich" badge
- Update specs for new data shapes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 17:44:08 +02:00
Marcel
fced33e033 fix(forms): correct required/optional field markers and divider placement
Some checks failed
CI / Backend Unit Tests (push) Has been cancelled
CI / Unit & Component Tests (push) Has been cancelled
CI / OCR Service Tests (push) Has been cancelled
- Add * to Datum and Absender labels (both are required fields)
- Add required prop to PersonTypeahead to show * in its label
- Move "Optional" divider in DescriptionSection to after Titel (the only
  required field), so Tags and Inhalt appear below the divider where they belong

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 23:36:31 +02:00
Marcel
a7a5123839 refactor(types): use generated Document type for doc prop in DocumentEditLayout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 23:36:31 +02:00
Marcel
d31ea12086 feat(upload): validate MIME type and size on file replace in DocumentEditLayout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 23:36:31 +02:00
Marcel
b0ea5f5552 feat(i18n): extract hardcoded strings in DocumentEditLayout to i18n keys
Adds label_required_fields to all three locales. Fixes "Datei ersetzen"
toolbar colors to use semantic ink tokens (readable in both light and dark
pdf-bg themes).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 23:36:31 +02:00
Marcel
8225bd660b feat(upload): replace Unicode arrow with SVG icon in UploadZone
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 23:36:31 +02:00
Marcel
fcc4c4665c feat(edit): unify edit page with enrich split-panel layout
Extract DocumentEditLayout shared component for the PDF+form split-panel
UI, replacing the old scrolling layout on /documents/[id]/edit with the
same fixed-panel structure used by /enrich/[id]. Removes TranscriptionSection
and FileSectionEdit from the edit page; file upload/replace is now handled
by the shared layout. Delete SaveBar and FileSectionEdit as dead code.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 23:36:31 +02:00
Marcel
9bad9e807b fix(i18n): replace hardcoded strings with Paraglide message keys
- error_file_upload_failed key used in enrich upload handler
- label_optional key added (de/en/es) and used in DescriptionSection divider

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 23:36:31 +02:00
Marcel
91500c4cf1 fix(a11y): bump Optional divider label to text-xs minimum (WCAG 1.4.4)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 23:36:31 +02:00
Marcel
f7ed154e4d fix(a11y): bump progress bar text to text-xs minimum, add motion-safe to upload animation
- text-[9px]/text-[10px] in required-fields bar raised to text-xs (12px),
  meeting the project minimum for the 60+ audience (WCAG 1.4.4)
- Upload animation now uses motion-safe: prefix so it stops for users
  with prefers-reduced-motion set (WCAG 2.1 SC 2.3.3)
- Strengthened UploadZone tests: onCancel uses [role=status] button
  selector instead of first-button heuristic; added positive file
  selection test (valid PDF calls onFile), file-too-large test, and
  MIME rejection now also asserts the error message is visible

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 23:36:31 +02:00
Marcel
f0bdcf334b feat(frontend): add UploadZone component for PLACEHOLDER document file upload
Presentational component with idle/uploading/error states, drag-and-drop,
client-side MIME type + 50 MB size validation, accessible touch targets (44px),
aria-live region, and indeterminate progress animation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 23:36:31 +02:00
Marcel
c62bf9085c feat(frontend): reorder DescriptionSection fields, expose currentTitle bindable, add Optional divider
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>
2026-04-18 23:36:31 +02:00
Marcel
047b7c71ff feat(frontend): reorder WhoWhenSection grid, expose dateIso bindable, add autofocus
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>
2026-04-18 23:36:31 +02:00
Marcel
1d9990715d feat(frontend): add autofocus prop to PersonTypeahead forwarded to text input
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 23:36:31 +02:00
Marcel
cea1234400 feat(ocr): move training cards from system page to OCR overview page
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>
2026-04-18 10:52:23 +02:00
Marcel
9ff498a194 feat(training-history): hide person/type columns for segmentation context
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>
2026-04-18 10:39:18 +02:00
Marcel
da0a7e9194 fix(frontend): increase dismiss button touch target to 44×44px (WCAG 2.5.5)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 21:50:05 +02:00