fix(timeline): track form dirtiness via change callbacks, not an $effect
Some checks failed
CI / Unit & Component Tests (pull_request) Failing after 4m17s
CI / OCR Service Tests (pull_request) Successful in 24s
CI / Backend Unit Tests (pull_request) Successful in 5m23s
CI / fail2ban Regex (pull_request) Successful in 47s
CI / Semgrep Security Scan (pull_request) Successful in 26s
CI / Compose Bucket Idempotency (pull_request) Successful in 1m8s
SDD Gate / RTM Check (pull_request) Successful in 16s
SDD Gate / Contract Validate (pull_request) Successful in 25s
SDD Gate / Constitution Impact (pull_request) Successful in 17s

The round-2 dirty-guard used an $effect that both read and wrote its `dirtyArmed`
$state, so the self-write re-triggered the effect and `dirty` flipped true on
mount — the beforeNavigate confirm then fired on every navigation away from an
untouched form (caught by the round-3 clean-agent review + the Svelte autofixer,
which flags assigning state inside $effect).

Replace it with the component's existing idiomatic pattern: DatePrecisionField,
PersonMultiSelect, and DocumentMultiSelect each gain an optional `onchange`
callback fired on a real user edit, and EventForm passes `markDirty` to all
three. Now date/precision/end-date and picker add/remove mark the form dirty
exactly like title/type/description already did — no effect, no mount-timing
trap. The new props are optional, so the other consumers (WhoWhenSection, the
document forms) are unaffected. Svelte autofixer: clean.

Addresses PR #832 review (round-3 clean-agent concern).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-06-14 00:55:34 +02:00
parent 0862d43ba3
commit 6150fc7be5
4 changed files with 26 additions and 18 deletions

View File

@@ -15,6 +15,8 @@ interface Props {
emptyLabel?: string;
/** id of the search input so a <label for=...> can be associated. */
inputId?: string;
/** Called when the selection changes (add/remove) — lets a parent track dirtiness. */
onchange?: () => void;
}
let {
@@ -22,7 +24,8 @@ let {
placeholder = m.geschichte_editor_search_document(),
hiddenInputName = 'documentIds',
emptyLabel = undefined,
inputId = undefined
inputId = undefined,
onchange = undefined
}: Props = $props();
let searchTerm = $state('');
@@ -54,10 +57,12 @@ function selectDocument(doc: DocumentOption) {
selectedDocuments = [...selectedDocuments, doc];
searchTerm = '';
picker.close();
onchange?.();
}
function removeDocument(id: string | undefined) {
selectedDocuments = selectedDocuments.filter((d) => d.id !== id);
onchange?.();
}
</script>