feat: add session undo and redo
Continuous Integration / lint-and-test (push) Successful in 14s
Continuous Integration / docker-build-and-push (push) Successful in 34s

This commit is contained in:
Lucas Winther committed 2026-09-30 01:33:29 +02:00
1 parent d38584396b
commit 804f32c5fb
9 files changed
+411 -14

No files matched your search

@@ -0,0 +1,31 @@
# Session undo and redo
The owner needs to reverse an accidental saved edit without reconstructing a
budget from an export. History lasts for the current page session only; a reload
starts with the saved dataset and empty history.
## Behavior
- Every successful, changed `mutate` produces one undo step. Unchanged edits
produce none. The last 50 prior datasets are retained.
- Undo and redo restore complete datasets, including IDs and dated rules, by
writing through the store's existing serialization queue. A failed write
changes neither the displayed dataset nor either history stack.
- A new successful edit after undo clears redo. A failed edit leaves redo
available.
- Import and reset are destructive whole-dataset operations. Their existing
backup-first flow remains mandatory. On success they clear both history
stacks; on failure they leave history intact. Neither can be undone with the
session controls.
- The header offers Undo and Redo buttons. Ctrl/Cmd+Z undoes and
Ctrl/Cmd+Shift+Z or Ctrl/Cmd+Y redoes when focus is outside an editable
control. Native text editing shortcuts remain native.
- A failed undo or redo shows its persistence error near the controls.
## Implementation boundary
History belongs to `src/store/snapshot.ts`, where edits already serialize and
only become visible after persistence succeeds. The UI reads stable capability
state from the same store and invokes its methods; no domain or dataset schema
change is needed. History is deliberately memory-only, so exports contain only
the current dataset and IndexedDB needs no upgrade.