Verfahrensablauf URL state: hybrid model — filter chips in URL, scenario inputs in localStorage #137

Open
opened 2026-05-26 15:45:46 +00:00 by mAi · 0 comments
Collaborator

Direction (m, 2026-05-26 17:45)

m picked option C — hybrid:

  • URL holds the filter chips that define which timeline kind the user is looking at — paste-able, shareable, refresh-resistant.
  • localStorage holds the per-session scenario inputs — the noisy parts that nobody else needs to see in a URL.

Concrete split

URL params (keep / add)

key description
proceeding proceeding type (upc.inf.cfi, upc.apl.unified, etc.) — VERIFY currently in URL; if not, add it
side claimant / defendant / undefined
target appeal_target for upc.apl.unified (endentscheidung / kostenentscheidung / anordnung / schadensbemessung / bucheinsicht)
trigger_date YYYY-MM-DD of the anchor event — currently NOT in URL, refresh loses it. Add it.

localStorage (move out of URL where currently there)

localStorage key prefix: paliad.verfahrensablauf.scenario.*

key currently
event_choices URL (?event_choices=…) — long, verbose, not really shareable. Move to localStorage.
court picker (court_id) URL — keep also in localStorage as fallback; URL still wins if explicitly set.
CCR / amend / CCI flags URL — same treatment as court_id.
show_hidden URL (?show_hidden=1) — Move to localStorage (it's per-user UX preference, not scenario state).
notes-show / durations-show toggles already localStorage (paliad.fristen.notes-show, paliad.verfahrensablauf.durations-show) — keep as-is.

Removed (already gone)

  • ?appellant= — removed in #132 (Berufung tile refactor). Worker must NOT reintroduce.

Behavior contract

  1. On page load: hydrate URL first → then fill any remaining state from localStorage. URL wins on conflict.
  2. On filter change (chip selectors, trigger date): update URL (history.replaceState). NO localStorage write for these — URL is the source of truth.
  3. On scenario change (event_choices, court, flags, show_hidden): update localStorage. NO URL write.
  4. Shared link from colleague: opens the URL, sees the same proceeding + side + target + trigger date. Their own event_choices / court / flags don't leak in; they fill those locally.
  5. Refresh: URL hydrates filter chips; localStorage restores last-used scenario inputs.
  6. Project-driven side-fill chip ("Aus Akte: …") still works — when a project is open, the project's our_side overrides whatever's in URL/localStorage, same as today.

Files

  • frontend/src/client/verfahrensablauf.ts — the URL helpers (getSide, setSide, getAppealTarget, setAppealTarget, getEventChoices, setEventChoices, getShowHidden, setShowHidden, currentProceeding). Refactor: URL helpers stay for the 4 chip params + trigger_date; new localStorage helpers for the rest. Make sure the existing initPerspectiveControls + load-time hydration honour the new contract.
  • frontend/src/verfahrensablauf.tsx — verify the <input type=date> and <select> widgets carry their values from the right source on render.
  • frontend/src/client/views/verfahrensablauf-core.ts — if the renderer reads URL params directly, route through the helpers instead.

Acceptance

  1. Refresh on https://paliad.de/tools/verfahrensablauf?proceeding=upc.inf.cfi&side=defendant&trigger_date=2026-05-26&target=endentscheidung → form fully restored (proceeding chip selected, side picked, date filled, target chip lit).
  2. Pick a court / toggle a CCR flag / show hidden → URL does NOT grow. localStorage gains a paliad.verfahrensablauf.scenario.* entry.
  3. Open the same URL in a private window → identical proceeding/side/target/date, but no scenario state (court empty, no event_choices, show_hidden=false). Each user's scenario state stays local.
  4. Project-driven side-fill chip from ?project=<id> still overrides as today.
  5. bun run build + go test ./... clean. Add a small frontend test (verfahrensablauf-core.test.ts already exists) covering the URL→localStorage hydration order.

Sequencing

This task is BLOCKED until #136 (t-paliad-307, diesel) lands — diesel is touching frontend/src/client/verfahrensablauf.ts for the side-filter bug and would conflict with this refactor. Head will dispatch a worker once #136 is merged.

Anti-patterns

  • DON'T undo #132 (no ?appellant= resurrection).
  • DON'T put trigger_date in localStorage — it goes in the URL because a shared link must reproduce the same dated timeline.
  • DON'T deviate from the URL→localStorage hydration ORDER — URL must win.
## Direction (m, 2026-05-26 17:45) m picked option **C** — hybrid: - **URL holds** the filter chips that define *which timeline kind* the user is looking at — paste-able, shareable, refresh-resistant. - **localStorage holds** the per-session scenario inputs — the noisy parts that nobody else needs to see in a URL. ## Concrete split ### URL params (keep / add) | key | description | |---|---| | `proceeding` | proceeding type (`upc.inf.cfi`, `upc.apl.unified`, etc.) — *VERIFY currently in URL; if not, add it* | | `side` | claimant / defendant / undefined | | `target` | appeal_target for `upc.apl.unified` (endentscheidung / kostenentscheidung / anordnung / schadensbemessung / bucheinsicht) | | `trigger_date` | YYYY-MM-DD of the anchor event — currently NOT in URL, refresh loses it. **Add it.** | ### localStorage (move out of URL where currently there) localStorage key prefix: `paliad.verfahrensablauf.scenario.*` | key | currently | |---|---| | `event_choices` | URL (`?event_choices=…`) — long, verbose, not really shareable. **Move to localStorage**. | | court picker (`court_id`) | URL — keep also in localStorage as fallback; URL still wins if explicitly set. | | CCR / amend / CCI flags | URL — same treatment as court_id. | | `show_hidden` | URL (`?show_hidden=1`) — **Move to localStorage** (it's per-user UX preference, not scenario state). | | notes-show / durations-show toggles | already localStorage (`paliad.fristen.notes-show`, `paliad.verfahrensablauf.durations-show`) — keep as-is. | ### Removed (already gone) - `?appellant=` — removed in #132 (Berufung tile refactor). Worker must NOT reintroduce. ## Behavior contract 1. **On page load**: hydrate URL first → then fill any remaining state from localStorage. URL wins on conflict. 2. **On filter change** (chip selectors, trigger date): update URL (`history.replaceState`). NO localStorage write for these — URL is the source of truth. 3. **On scenario change** (event_choices, court, flags, show_hidden): update localStorage. NO URL write. 4. **Shared link from colleague**: opens the URL, sees the same proceeding + side + target + trigger date. Their own `event_choices` / court / flags don't leak in; they fill those locally. 5. **Refresh**: URL hydrates filter chips; localStorage restores last-used scenario inputs. 6. **Project-driven side-fill chip** ("Aus Akte: …") still works — when a project is open, the project's `our_side` overrides whatever's in URL/localStorage, same as today. ## Files - `frontend/src/client/verfahrensablauf.ts` — the URL helpers (`getSide`, `setSide`, `getAppealTarget`, `setAppealTarget`, `getEventChoices`, `setEventChoices`, `getShowHidden`, `setShowHidden`, `currentProceeding`). Refactor: URL helpers stay for the 4 chip params + trigger_date; new localStorage helpers for the rest. Make sure the existing `initPerspectiveControls` + load-time hydration honour the new contract. - `frontend/src/verfahrensablauf.tsx` — verify the `<input type=date>` and `<select>` widgets carry their values from the right source on render. - `frontend/src/client/views/verfahrensablauf-core.ts` — if the renderer reads URL params directly, route through the helpers instead. ## Acceptance 1. Refresh on https://paliad.de/tools/verfahrensablauf?proceeding=upc.inf.cfi&side=defendant&trigger_date=2026-05-26&target=endentscheidung → form fully restored (proceeding chip selected, side picked, date filled, target chip lit). 2. Pick a court / toggle a CCR flag / show hidden → URL does NOT grow. localStorage gains a `paliad.verfahrensablauf.scenario.*` entry. 3. Open the same URL in a private window → identical proceeding/side/target/date, but no scenario state (court empty, no event_choices, show_hidden=false). Each user's scenario state stays local. 4. Project-driven side-fill chip from `?project=<id>` still overrides as today. 5. `bun run build` + `go test ./...` clean. Add a small frontend test (verfahrensablauf-core.test.ts already exists) covering the URL→localStorage hydration order. ## Sequencing **This task is BLOCKED until #136 (t-paliad-307, diesel) lands** — diesel is touching `frontend/src/client/verfahrensablauf.ts` for the side-filter bug and would conflict with this refactor. Head will dispatch a worker once #136 is merged. ## Anti-patterns - DON'T undo #132 (no `?appellant=` resurrection). - DON'T put trigger_date in localStorage — it goes in the URL because a shared link must reproduce the same dated timeline. - DON'T deviate from the URL→localStorage hydration ORDER — URL must win.
mAi self-assigned this 2026-05-26 15:45:46 +00:00
mAi added the
done
label 2026-05-26 16:46:40 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: m/paliad#137
No description provided.