Commit Graph

666 Commits

Author SHA1 Message Date
Marcel
0b57717586 feat(parser): normalize dot-compressed names in split()
Inserts spaces after dots when the cleaned name has no spaces but
contains dots, so the existing last-space fallback handles names
like "E.Rockstroh" and "Dr.Fr.Zarncke" correctly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 17:34:56 +02:00
Marcel
59475efbcb feat(parser): support // as multi-person separator in parseReceivers
Pre-splits input on "//" before existing logic so each segment is
processed independently through the full pipeline (und/u splitting,
last-name distribution, etc.).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 17:33:55 +02:00
Marcel
f435f2441c fix(model): add @JsonIgnore on PersonNameAlias.person to prevent LazyInitializationException
Some checks failed
CI / Unit & Component Tests (pull_request) Failing after 1s
CI / Backend Unit Tests (pull_request) Failing after 1s
CI / Unit & Component Tests (push) Failing after 3s
CI / Backend Unit Tests (push) Failing after 1s
Jackson tried to serialize the lazy Person proxy when returning
alias list, causing a "no session" error. The back-reference is
only needed for JPA navigation, not for API responses.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 16:31:39 +02:00
Marcel
e204ed89b6 fix(ui): switch alias operations from client fetch to form actions
Some checks failed
CI / Unit & Component Tests (push) Failing after 1s
CI / Backend Unit Tests (push) Failing after 2s
CI / Unit & Component Tests (pull_request) Failing after 1s
CI / Backend Unit Tests (pull_request) Failing after 1s
Replaces raw client-side fetch with SvelteKit form actions
(addAlias, removeAlias) using the server-side API client for
proper auth handling. 10 new component tests for NameHistoryEditCard.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 16:05:56 +02:00
Marcel
036843bf8f fix(ui): use mt-6 on save bar to match card spacing
Some checks failed
CI / Unit & Component Tests (push) Failing after 3s
CI / Backend Unit Tests (push) Failing after 2s
CI / Unit & Component Tests (pull_request) Failing after 2s
CI / Backend Unit Tests (pull_request) Failing after 1s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 16:01:43 +02:00
Marcel
9027f60760 fix(ui): use card-style save bar with mt-4 instead of full-bleed
Some checks failed
CI / Unit & Component Tests (push) Failing after 3s
CI / Backend Unit Tests (push) Failing after 1s
CI / Unit & Component Tests (pull_request) Failing after 1s
CI / Backend Unit Tests (pull_request) Failing after 1s
Removes -mx-4 negative margin and switches to the card pattern
(rounded border, shadow-sm, mt-4) so the save bar matches the
width of the other cards on the edit page.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 15:59:55 +02:00
Marcel
0f5eebec29 fix(ui): move save bar to end of edit page after alias and danger zone
Some checks failed
CI / Unit & Component Tests (push) Failing after 2s
CI / Backend Unit Tests (push) Failing after 1s
CI / Unit & Component Tests (pull_request) Failing after 1s
CI / Backend Unit Tests (pull_request) Failing after 1s
Uses HTML form attribute to associate the submit button with the
person-edit-form from outside the form tag. Page now reads:
Personendaten -> Namensverlauf -> Danger zone -> Save bar.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 15:59:05 +02:00
Marcel
f0eb3a76be test(ui): add component tests for NameHistoryCard
Some checks failed
CI / Unit & Component Tests (push) Failing after 3s
CI / Backend Unit Tests (push) Failing after 1s
CI / Unit & Component Tests (pull_request) Failing after 2s
CI / Backend Unit Tests (pull_request) Failing after 2s
Verifies alias rendering, empty state, firstName fallback,
and type label display. 5 browser-based Svelte tests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 13:43:09 +02:00
Marcel
6d837c518c fix(a11y): include alias name in delete button aria-label
Screen readers now announce which alias is being deleted, e.g.
"Entfernen de Gruyter" instead of just "Entfernen".

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 13:42:08 +02:00
Marcel
97646a31df fix(ui): always show Namensverlauf card on detail page
Removes the {#if} guard so the card with empty state message is
always visible for feature discoverability.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 13:41:19 +02:00
Marcel
cfb3260e0e fix(api): add input validation to PersonNameAliasDTO
Adds @NotBlank @Size(max=255) on lastName, @NotNull on type,
@Valid on controller parameter. Blank/null input now returns
400 instead of reaching the DB constraint. 2 new controller tests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 13:40:43 +02:00
Marcel
59f593280b fix(test): update person detail loader tests for 4th aliases API call
Some checks failed
CI / Unit & Component Tests (push) Failing after 2s
CI / Backend Unit Tests (push) Failing after 1s
CI / Unit & Component Tests (pull_request) Failing after 1s
CI / Backend Unit Tests (pull_request) Failing after 2s
Adds mock for the new GET /api/persons/{id}/aliases call added
in the parallel Promise.all.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 13:35:19 +02:00
Marcel
b910517690 feat(ui): add alias management to person edit page
NameHistoryEditCard with add form (type dropdown + name fields),
delete with confirmation modal, and IDOR-safe client-side fetch
calls. Placed between Personendaten and DangerZone cards.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 13:31:41 +02:00
Marcel
002ee1010a feat(ui): add Namensverlauf read-only card to person detail page
Shows historical name aliases in the left column with type labels
and firstName fallback. Fetches aliases in parallel with other data.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 13:31:07 +02:00
Marcel
9e13208ccd chore(api): regenerate TypeScript API types with alias endpoints
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 13:24:03 +02:00
Marcel
f396e079a5 feat(i18n): add alias type labels and section strings for de/en/es
Adds 16 new keys per language: alias type labels (BIRTH, WIDOWED,
DIVORCED, OTHER), section heading, empty state, add form labels,
delete confirmation, and ALIAS_NOT_FOUND error code.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 13:21:21 +02:00
Marcel
90c9ac9357 feat(search): extend document text search to match alias last names
Adds sender alias LEFT JOIN and receiver alias EXISTS subquery to
DocumentSpecifications.hasText(). Uses entity-graph navigation via
Person.nameAliases (@OneToMany) to avoid a separate DB roundtrip
while respecting domain boundaries. 2 new integration tests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 13:18:31 +02:00
Marcel
db61d6b77f feat(search): extend person search to include alias last names
Adds LEFT JOIN to person_name_aliases in both searchByName (JPQL)
and searchWithDocumentCount (native SQL). Uses DISTINCT/GROUP BY
to prevent duplicate results. 4 new integration tests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 13:12:54 +02:00
Marcel
a1d63bbc42 feat(api): add GET/POST/DELETE /api/persons/{id}/aliases endpoints
GET returns aliases (no permission required), POST requires
WRITE_ALL, DELETE requires WRITE_ALL. 5 new controller tests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 13:09:58 +02:00
Marcel
0fc568dd9f feat(service): add alias CRUD methods to PersonService
getAliases (sorted by sort_order), addAlias (auto-incrementing
sort_order), removeAlias (with IDOR protection verifying alias
belongs to the given person). All TDD with 7 new unit tests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 13:07:14 +02:00
Marcel
765cbfbaaf feat(model): add PersonNameAlias entity, type enum, repository, DTO
Introduces the alias domain model: entity with @ManyToOne to Person,
@OneToMany on Person for JPA graph navigation, repository with
sort_order queries, input DTO, and ALIAS_NOT_FOUND error code.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 13:04:38 +02:00
Marcel
22fe9600a1 feat(migration): V21 add person_name_aliases table with pg_trgm indexes
Creates the alias table for historical name changes (marriage,
widowhood, etc.) and adds GIN trigram indexes on both the new
alias table and the existing persons table for substring search.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 13:02:51 +02:00
Marcel
b5ec4ebc0c refactor(ui): rename shadowed m parameter to newMode
Some checks failed
CI / Unit & Component Tests (pull_request) Failing after 1s
CI / Backend Unit Tests (pull_request) Failing after 3s
CI / Unit & Component Tests (push) Failing after 3s
CI / Backend Unit Tests (push) Failing after 2s
Avoids shadowing the Paraglide m import in the onModeChange callback.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 11:58:54 +02:00
Marcel
10fdaf7d00 refactor(ui): use CSS variable for turquoise in flash animations
Replaces hardcoded rgba(0,199,177,...) with color-mix using
var(--color-turquoise) for dark mode compatibility.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 11:58:04 +02:00
Marcel
e01ef56c48 fix(i18n): use getLocale() for date formatting in panel header
Replaces hardcoded 'de-DE' with the active Paraglide locale so
dates render in the user's language.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 11:56:23 +02:00
Marcel
b01a9ef406 refactor(ui): use bg-turquoise/10 token for paragraph hover
Replaces hardcoded rgba value with the project's turquoise color
token for dark mode compatibility.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 11:54:57 +02:00
Marcel
e31b73303e fix(ui): bump paragraph hover opacity from 6% to 10%
Improves visibility of the clickability affordance on uncalibrated
displays and for senior users.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 11:53:17 +02:00
Marcel
9d9d19ceb5 fix(a11y): increase segmented toggle height on mobile to 36px
Uses h-9 (36px) on mobile, h-7 (28px) on desktop for better tap
targets on small screens.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 11:51:56 +02:00
Marcel
0a5c82cd0e fix(a11y): increase panel close button touch target to 44px
Changes h-8 w-8 (32px) to h-11 w-11 (44px) to meet project's
minimum touch target standard.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 11:50:32 +02:00
Marcel
1b063d4e4b test(ui): add tests for 0 blocks and lastEditedAt on PanelHeader
Verifies blockCount=0 shows "0 Abschnitte" and that a provided
lastEditedAt value renders a formatted date containing the year.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 11:46:53 +02:00
Marcel
b312878b3f test(ui): add annotation-flash class tests for AnnotationLayer
Verifies flashAnnotationId applies and removes the annotation-flash
CSS class correctly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 11:45:23 +02:00
Marcel
90120ca8e8 test(ui): add flash-highlight class tests for TranscriptionReadView
Verifies highlightBlockId applies and removes the flash-highlight
CSS class correctly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 11:44:01 +02:00
Marcel
4d5b8b4ead feat(ui): add collapsible PDF strip and abbreviated labels on mobile
Some checks failed
CI / Unit & Component Tests (push) Failing after 2s
CI / Backend Unit Tests (push) Failing after 2s
CI / Unit & Component Tests (pull_request) Failing after 3s
CI / Backend Unit Tests (pull_request) Failing after 1s
PDF viewer collapses to 70px on mobile in read mode, expandable to
50vh. Toggle button with chevron. Paragraph tap auto-expands strip.
Mode toggle abbreviates to "Bearb." on small screens.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 11:30:36 +02:00
Marcel
10cecb01f5 feat(a11y): respect prefers-reduced-motion for scroll-sync
Uses scrollIntoView behavior 'instant' instead of 'smooth', skips
CSS animations (static highlight instead), and extends timeout to
2s for reduced-motion users.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 11:27:01 +02:00
Marcel
81b14e5026 feat(ui): add bidirectional scroll-sync with flash animations
Paragraph click flashes the PDF annotation outline (1.5s fade).
Annotation click highlights the paragraph with a background flash.
Both directions scroll the target into view.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 11:25:23 +02:00
Marcel
e089192d7a feat(ui): wire panelMode state with read/edit view switching
Adds TranscriptionPanelHeader and TranscriptionReadView to the
document detail page. Default mode is 'read' when blocks exist,
'edit' otherwise. Annotations dimmed in read mode.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 11:21:15 +02:00
Marcel
306eef2e95 feat(ui): add TranscriptionReadView for flowing prose display
Renders transcription blocks as readable text with [unleserlich]/[...]
markers styled as italic muted text. Supports click-to-sync and
flash highlight for scroll-sync feedback.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 11:14:53 +02:00
Marcel
7d98081390 feat(ui): add TranscriptionPanelHeader with mode toggle and status
Segmented Lesen/Bearbeiten control, block count, last-edited date,
and close button. Lesen disabled when no blocks exist.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 11:10:39 +02:00
Marcel
d070ae2612 feat(annotation): add dimmed prop to AnnotationLayer
Hides block number badges and disables hover/active visual feedback
when dimmed=true. Click handlers remain active for scroll-sync.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 11:07:23 +02:00
Marcel
3279342ea7 feat(util): add splitByMarkers for [unleserlich] and [...] text splitting
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 11:00:23 +02:00
Marcel
f38c384268 feat(types): add updatedAt to TranscriptionBlockData
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 10:58:34 +02:00
Marcel
a94df4b225 feat(i18n): add read mode translation keys for de/en/es
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 10:57:47 +02:00
Marcel
53b318f7ad fix(ui): add py-8 to results state matching document search page
Some checks failed
CI / Unit & Component Tests (pull_request) Failing after 2s
CI / Backend Unit Tests (pull_request) Failing after 1s
CI / Unit & Component Tests (push) Failing after 3s
CI / Backend Unit Tests (push) Failing after 2s
Aligns the top/bottom padding of the Briefwechsel results view with
the document search page wrapper (both py-8).

Refs: #179

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 08:52:44 +02:00
Marcel
001e875f31 fix(ui): use De Gruyter long arrows for swap button and timeline entries
Some checks failed
CI / Unit & Component Tests (push) Failing after 2s
CI / Backend Unit Tests (push) Failing after 1s
CI / Unit & Component Tests (pull_request) Failing after 1s
CI / Backend Unit Tests (pull_request) Failing after 1s
Swap button: stack right/left arrows vertically at h-3.5 for a
compact look. Timeline: replace → ← text with Long-Arrow icons on
each letter entry and the distribution bar summary.

Refs: #179

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 08:50:58 +02:00
Marcel
06709e7458 fix(ui): remove disabled look from receiver typeahead when empty
Some checks failed
CI / Unit & Component Tests (push) Failing after 3s
CI / Backend Unit Tests (push) Failing after 1s
CI / Unit & Component Tests (pull_request) Failing after 1s
CI / Backend Unit Tests (pull_request) Failing after 2s
Remove border-dashed and bg-canvas conditional styles so the
receiver input matches the sender input styling. The placeholder
"Alle Korrespondenten" already communicates the optional state.

Refs: #179

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 08:46:36 +02:00
Marcel
7fed057e59 fix(ui): prevent hero flicker when clearing sender input
Some checks failed
CI / Unit & Component Tests (pull_request) Failing after 2s
CI / Backend Unit Tests (pull_request) Failing after 2s
CI / Unit & Component Tests (push) Failing after 5s
CI / Backend Unit Tests (push) Failing after 5s
Only navigate (applyFilters) when a person is actually selected, not
when the sender input is cleared. Combined with showHero checking
data.filters.senderId, the user stays in the search bar view after
clearing — no jump back to the hero.

Refs: #179

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 22:56:44 +02:00
Marcel
a3edf9d7b4 fix(ui): date input placeholders show format TT.MM.JJJJ instead of label
Some checks failed
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Failing after 1m20s
CI / Backend Unit Tests (pull_request) Failing after 1m49s
Remove custom placeholder props so DateInput falls back to its default
format hint (TT.MM.JJJJ / DD.MM.YYYY / DD.MM.AAAA) instead of
repeating the label text above.

Refs: #179

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 22:47:28 +02:00
Marcel
708d02a1f7 fix(ui): unify date inputs — use DateInput component on both pages
Some checks failed
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Failing after 1m16s
CI / Backend Unit Tests (pull_request) Failing after 2m23s
Replace native <input type="date"> on the document search page with
the custom DateInput component (German dd.mm.yyyy format with auto-dot
insertion). Align both pages' date input styling: add rounded-md,
border, bg-surface, px-3, text-ink, placeholder color, and focus ring
to match all other inputs in the card.

Refs: #179

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 22:46:29 +02:00
Marcel
2e943b7f91 fix(ui): De Gruyter long arrows on both sort buttons, rotate swap icon 90°
Some checks failed
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Failing after 1m21s
CI / Backend Unit Tests (pull_request) Failing after 2m30s
Replace ↑↓ text with Long-Arrow-Up/Down-MD.svg on the document search
SortDropdown and the Briefwechsel sort button. Rotate the swap button
SVG 90° so arrows point left/right matching the horizontal person
field layout.

Refs: #179

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 22:43:45 +02:00
Marcel
b4a9e678c6 fix(ui): use De Gruyter long arrow icons for sort direction
Some checks failed
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Failing after 1m24s
CI / Backend Unit Tests (pull_request) Failing after 2m28s
Replace tiny ↑↓ text with Long-Arrow-Up/Down-MD.svg icons from the
brand icon set for better visibility and consistency.

Refs: #179

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 22:37:50 +02:00