History panel + undo in the editor #49

Closed
opened 2026-07-21 04:17:02 +00:00 by steve · 0 comments
Owner

Design: DESIGN.md

Context

#48 makes every change revertible; this makes that reachable. The bar to clear: after the agent rearranges a bed, undoing it should take one obvious click, not a hunt through a menu.

Scope

  • History panel in the garden editor: change sets newest-first — who, when, summary, a count of what moved ("3 plops added, 1 bed moved"), and a badge distinguishing agent changes from hand edits. Paginate or lazy-load; a season of edits is a long list.
  • Undo on each entry → POST /change-sets/:id/revert, then invalidate the /full query so the canvas redraws. A reverted change set is marked as such in the list, and the revert appears as its own entry (it is one) rather than making the original disappear.
  • Conflict handling: a 409 names the entities that couldn't be cleanly reverted because they changed afterwards. Say which ones and what happened to the rest — "2 of 3 changes undone; the north bed was edited since and was left alone" — not a generic failure toast.
  • Inline undo on the agent turn itself (see #57): the result of a turn carries an Undo affordance so the common case never involves opening the panel at all. One implementation shared between here and #57, not two.
  • Note honestly in the panel that deleting a garden is not covered by history (see #48).

Layout note

The editor's right rail is already the inspector; #53 wants journal access and #57 wants a chat panel. Four things competing for one rail is the actual design problem, and this issue is where it gets settled — the later issues follow whatever is decided here rather than each bolting on its own chrome. A tabbed rail (Inspector / History / Journal / Chat) is the obvious candidate; a bottom drawer for history is the other.

Constraints to hold whatever wins: selecting an object still lands you in the inspector without a click, and the canvas keeps enough width to be worth watching while the agent edits it.

Out of scope

  • Diff visualisation (showing before/after geometry on the canvas). Nice, not necessary.
  • Restoring a deleted garden.

Key files

web/src/pages/GardenEditorPage.tsx · web/src/editor/ · web/src/lib/ (a new history.ts data layer alongside gardens.ts/objects.ts)

Dependencies

Blocked by #48. Owns the rail-layout decision that #53 and #57 depend on.

Acceptance criteria

  • Move a bed, open History, undo it: the bed returns to its previous position and the canvas reflects it without a manual refresh.
  • The undo itself appears in the list and can be undone.
  • Edit an object, then try to undo an older change set that touched it: the partial result and the reason are both stated in the UI.
  • The panel is usable on a phone (the editor is expected to work there).
Design: [DESIGN.md](https://gitea.stevedudenhoeffer.com/steve/pansy/src/branch/main/DESIGN.md) ## Context #48 makes every change revertible; this makes that reachable. The bar to clear: after the agent rearranges a bed, undoing it should take one obvious click, not a hunt through a menu. ## Scope - [ ] History panel in the garden editor: change sets newest-first — who, when, summary, a count of what moved ("3 plops added, 1 bed moved"), and a badge distinguishing **agent** changes from hand edits. Paginate or lazy-load; a season of edits is a long list. - [ ] **Undo** on each entry → `POST /change-sets/:id/revert`, then invalidate the `/full` query so the canvas redraws. A reverted change set is marked as such in the list, and the revert appears as its own entry (it is one) rather than making the original disappear. - [ ] Conflict handling: a `409` names the entities that couldn't be cleanly reverted because they changed afterwards. Say which ones and what happened to the rest — "2 of 3 changes undone; the north bed was edited since and was left alone" — not a generic failure toast. - [ ] Inline undo on the agent turn itself (see #57): the result of a turn carries an Undo affordance so the common case never involves opening the panel at all. One implementation shared between here and #57, not two. - [ ] Note honestly in the panel that deleting a garden is not covered by history (see #48). ## Layout note The editor's right rail is already the inspector; #53 wants journal access and #57 wants a chat panel. **Four things competing for one rail is the actual design problem, and this issue is where it gets settled** — the later issues follow whatever is decided here rather than each bolting on its own chrome. A tabbed rail (Inspector / History / Journal / Chat) is the obvious candidate; a bottom drawer for history is the other. Constraints to hold whatever wins: selecting an object still lands you in the inspector without a click, and the canvas keeps enough width to be worth watching while the agent edits it. ## Out of scope - Diff visualisation (showing before/after geometry on the canvas). Nice, not necessary. - Restoring a deleted garden. ## Key files `web/src/pages/GardenEditorPage.tsx` · `web/src/editor/` · `web/src/lib/` (a new `history.ts` data layer alongside `gardens.ts`/`objects.ts`) ## Dependencies Blocked by #48. Owns the rail-layout decision that #53 and #57 depend on. ## Acceptance criteria - Move a bed, open History, undo it: the bed returns to its previous position and the canvas reflects it without a manual refresh. - The undo itself appears in the list and can be undone. - Edit an object, then try to undo an older change set that touched it: the partial result and the reason are both stated in the UI. - The panel is usable on a phone (the editor is expected to work there).
steve added the frontendpolish labels 2026-07-21 04:17:02 +00:00
steve closed this issue 2026-07-21 05:23:25 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: steve/pansy#49