fix: undo closing a widget (#40) #48

Merged
pitfriedrich merged 1 commits from ai/issue-40-undo-closing-a-widget into main 2026-07-28 21:30:54 +00:00
Collaborator

Problem

Closing a widget was instant and destructive: GridStackItem.close() detached the item and there was no way back short of a full layout reset (which also throws away every other widget's placement).

Fix

  • GridStackItem.CloseEvent now carries the item's Position (id, x, y, w, h), captured right before removeFromParent() — after detach the grid no longer reports it.
  • DashboardView wires every widget's close listener once, on first add (addWidgetToGrid), to offerUndo: for a client-initiated close (isFromClient()), it shows a Notification toast with an "Undo" button that re-adds the very same GridStackItem instance at its captured position, so it keeps its exact gs-id/size/position rather than the grid's next free slot.
  • Programmatic closes (GridStackItem#close(), e.g. duplicate cleanup) have fromClient == false and are skipped — no toast.
  • Translations added for the toast copy (gridstack.closed, gridstack.undo) in de/en/es.

Tests

  • DashboardViewTest: toast shown on close, undo restores position/id, repeated close→undo→close still offers undo, programmatic close shows no toast.
  • New WidgetUndoClosePlaywrightTest (e2e): close → undo → exact grid slot restored, in a real browser.
  • ./mvnw test: 73/73 green.

Closes #40

## Problem Closing a widget was instant and destructive: `GridStackItem.close()` detached the item and there was no way back short of a full layout reset (which also throws away every other widget's placement). ## Fix - `GridStackItem.CloseEvent` now carries the item's `Position` (id, x, y, w, h), captured right before `removeFromParent()` — after detach the grid no longer reports it. - `DashboardView` wires every widget's close listener once, on first add (`addWidgetToGrid`), to `offerUndo`: for a client-initiated close (`isFromClient()`), it shows a `Notification` toast with an "Undo" button that re-adds the very same `GridStackItem` instance at its captured position, so it keeps its exact `gs-id`/size/position rather than the grid's next free slot. - Programmatic closes (`GridStackItem#close()`, e.g. duplicate cleanup) have `fromClient == false` and are skipped — no toast. - Translations added for the toast copy (`gridstack.closed`, `gridstack.undo`) in `de`/`en`/`es`. ## Tests - `DashboardViewTest`: toast shown on close, undo restores position/id, repeated close→undo→close still offers undo, programmatic close shows no toast. - New `WidgetUndoClosePlaywrightTest` (e2e): close → undo → exact grid slot restored, in a real browser. - `./mvnw test`: 73/73 green. Closes #40
claude-bot added 1 commit 2026-07-28 21:25:34 +00:00
fix: undo closing a widget (#40)
CI / build-and-test (pull_request) Successful in 2m19s
4878a7fc06
Closing a widget was instant and destructive - one misclick on the X
lost its size and position. Close now shows a toast with an undo
button that re-adds the very same widget at its captured gs-x/y/w/h,
keeping its gs-id. Programmatic close() (fromClient=false) is skipped.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HGRChzremwYCUctf2qMrQz
pitfriedrich merged commit 114f00523b into main 2026-07-28 21:30:54 +00:00
pitfriedrich deleted branch ai/issue-40-undo-closing-a-widget 2026-07-28 21:30:54 +00:00
Sign in to join this conversation.