Restore editor history after reload

This commit is contained in:
2026-07-25 21:45:58 +02:00
parent c45afd0981
commit 4b47bc2bcc
10 changed files with 275 additions and 423 deletions
+11 -11
View File
@@ -122,14 +122,15 @@ Cross-section device moves show confirmation-required feedback before drop. The
## Undo/Redo
Undo/redo wraps editor operations as command objects and reloads the tree after
each command. Existing Circuit and device-row cell edits plus standalone
insert/delete actions execute persistent project commands; their toolbar
undo/redo calls the project-wide server history. New entities receive stable
UUIDs before insertion, and deletion undo restores those same ids. Device-row
moves and circuit reorders also use persistent project commands. Applying a
sorted view across multiple sections is atomic and occupies one history step.
Explicit renumbering uses a collision-safe persistent project command and one
Editor operations execute persistent project commands and reload the tree after
each command. On initial load and every reload, the editor reads undo/redo
eligibility from the project-wide server history and verifies that tree and
history belong to the same project revision. Undo/redo therefore remains
available after a page refresh. New entities receive stable UUIDs before
insertion, and deletion undo restores those same ids. Device-row moves and
circuit reorders also use persistent project commands. Applying a sorted view
across multiple sections is atomic and occupies one history step. Explicit
renumbering uses a collision-safe persistent project command and one
project-history step.
Covered operations include:
@@ -141,6 +142,5 @@ Covered operations include:
- renumber and identifier update flows
- apply sorted order
Current limitations:
- the visible editor stack is still session-local and is empty after reload
The toolbar currently exposes availability through its Undo/Redo buttons. A
browsable revision timeline and named restore points are separate future work.
@@ -2,11 +2,10 @@
- All currently supported Circuit and CircuitDeviceRow editor writes use
persistent project commands and project-wide toolbar undo/redo, including
moves, atomic multi-section reorders and explicit renumbering. The editor's
visible stack is still session-local and empty after reload.
- Server-side project revisions and persistent undo/redo eligibility exist for
the command types documented in `circuit-list-editor-api.md`; visible history
reconstruction is not complete.
moves, atomic multi-section reorders and explicit renumbering. Undo/redo
eligibility is restored from server history after a page reload.
- There is no browsable revision timeline yet; the editor currently exposes
only the next eligible Undo/Redo actions.
- Named logical project snapshots and restore are not implemented yet.
- No Revit/CSV/IFCGUID import and export workflow is implemented yet.
- Persistence currently targets local SQLite; PostgreSQL is an architectural option, not an implemented runtime.
+7 -5
View File
@@ -62,9 +62,10 @@ liegt über einen Host-Mount außerhalb des Containers.
6. Das Frontend lädt den Circuit-Tree neu und stellt Auswahl beziehungsweise
Viewport soweit möglich wieder her.
Der sichtbare React-Historiestapel ist während des schrittweisen Cutovers noch
sitzungslokal. Das Datenmodell besitzt
einen projektbezogenen Revisionszähler sowie getrennte Revision-/Change-Set-
Der Editor besitzt keinen sitzungslokalen Undo-/Redo-Stapel mehr. Beim initialen
Laden und nach jedem Tree-Reload liest er den persistenten History-Status und
gleicht dessen Revision mit `currentRevision` des Trees ab. Das Datenmodell
besitzt einen projektbezogenen Revisionszähler sowie getrennte Revision-/Change-Set-
Tabellen. Ein getestetes Repository kann diese Historienmetadaten optimistisch
und atomar fortschreiben. Vorwärts- und Rückwärtskommandos besitzen einen
versionierten, JSON-sicheren Umschlag; Typ und Payload können dadurch nach
@@ -94,8 +95,9 @@ dazu `currentRevision`; Undo/Redo für diese Aktionen läuft über die projektwe
Serverhistorie. Direkte Feld-PATCH-, Struktur-POST-, Move-, Circuit- und
Gerätezeilen-DELETE-Endpunkte sind entfernt. Gerätezeilen-Moves,
Stromkreis-Reorders und die explizite Neunummerierung im Grid verwenden die
persistenten Kommandos. Der sichtbare Undo-/Redo-Stack wird nach einem Reload
noch nicht aus der Serverhistorie rekonstruiert.
persistenten Kommandos. Die Toolbar leitet ihre Undo-/Redo-Verfügbarkeit direkt
aus den serverseitigen Stack-Tiefen ab, sodass ein Reload die Bedienbarkeit
nicht unterbricht.
`circuit-device-row.move` verschiebt oder sortiert eine oder mehrere Zeilen
zwischen vorhandenen Stromkreisen derselben Liste. Erwartete und neue
Stromkreis-/Sortierpositionen machen Forward und Inverse deterministisch;
@@ -60,7 +60,9 @@ Full event sourcing is not required. Current normalized tables remain the primar
- After a page reload, the client requests the current revision and eligible history actions.
- Commands include an expected project revision. A stale command is rejected instead of silently overwriting a newer project state.
The current session-local frontend command stack is transitional. Editor modularization must separate command descriptions from React callbacks so commands can later be sent to and reconstructed by the server.
The circuit-list editor uses the server state directly for operation
eligibility. React callbacks only initiate forward commands and provide
best-effort selection hints after the tree reload.
## Snapshot Storage
@@ -210,6 +212,9 @@ Completed foundation:
- the editor's explicit renumber action uses this command; obsolete direct
renumber and identifier-restore routes plus their transaction adapter are
removed
- the circuit-list editor loads project-wide undo/redo eligibility together
with the tree, retries revision mismatches and keeps Undo/Redo available after
page reloads without a session-local command stack
- `project-device.sync-rows` records synchronization, disconnect and reconnect
as one atomic multi-row operation; complete expected/target sync snapshots
protect local values, links and override metadata against silent stale writes
@@ -219,11 +224,9 @@ Completed foundation:
ids; delete undo restores links only from complete unchanged disconnected-row
snapshots in the same transaction
Remaining constraints before completing persistent history:
Remaining constraints before completing project version history:
- reconstruct the visible frontend history state after reload; Circuit and
CircuitDeviceRow operations plus ProjectDevice operations already use
persistent commands and project-wide undo
- add a browsable revision timeline plus named logical snapshots and restore
- extend project-scoped commands only when further project mutations are
deliberately added to history; the generic versioned envelope is complete
- do not model IFCGUID as an overloaded circuit equipment identifier
+5 -4
View File
@@ -358,8 +358,8 @@ Tasks:
- [x] add immutable append-only server-side change-set storage with versioned
forward/inverse payloads
- [x] add optimistic checks when appending a revision
- route domain writes and history records through one shared transaction
- define concrete serializable domain command descriptions and executors
- [x] route supported domain writes and history records through one shared transaction
- [x] define concrete serializable domain command descriptions and executors
outside React
- [x] persist undo/redo eligibility on the server
- [x] expose public command, undo and redo endpoints for the first supported
@@ -435,8 +435,9 @@ Circuit/CircuitDeviceRow field/insert/delete actions, device-row moves and
circuit reorders in the circuit-list editor are connected to this history
boundary. Applying sorted order across multiple sections is one atomic command.
Explicit renumbering is connected to the same persistent boundary. The
editor's visible undo/redo stack remains session-local and is not reconstructed
after reload.
editor reads the persistent undo/redo stack depths on initial load and after
every tree reload. Tree and history revisions are reconciled before the state
is exposed, so the toolbar remains usable after a page refresh.
Acceptance criteria: