Persist dashboard layout server-side, not only in localStorage #22
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
GridStackLayout.setStorageKey(...)persists drag/resize state to browserlocalStorage(seefrontend/components/grid-stack.ts). That means the layout is:There is a second, subtler gap: only positions are persisted, not which widgets exist. Once widgets are closable (#14) and addable (widget registry issue), restoring positions alone is not enough — the restore silently skips saved nodes whose
gs-idno longer exists in the DOM, and a widget added at runtime is gone after reload.Proposal
DashboardLayoutStoreabstraction persisting, per user/session, a list of(widgetTypeId, itemId, x, y, w, h).GridStackLayout.addLayoutChangeListener, which already deliversList<GridStackItem.Position>server-side.localStorageas a fast path or drop it — but do not let the two disagree; pick one source of truth.clearStorage().Acceptance criteria
Depends on
Widget registry (needs a widget type id to rebuild from, not just a position).
Scope
Medium to large. Coordinate with the registry issue; doing them together may be cleaner than sequentially.
Needs human — blocked, not fixing via autofix.
Checked the stated dependency first: the widget registry (
WidgetRegistry/WidgetDefinition) already exists and widgets are already closable/addable at runtime, so that part of the "depends on" note is resolved.The remaining scope is still too large/unclear for autofix:
User, no login). The issue suggests starting with a "session- or file-backed" store, but the acceptance criteria require the layout to "survive a reload in a different browser / after clearing site data" — a session (cookie-bound) or a single shared file (global, not per-user) can't satisfy that without picking an actual identity model first. That's a product decision, not an implementation detail.DashboardLayoutStoreabstraction,DashboardViewrebuilt to construct from stored(widgetTypeId, itemId, x, y, w, h)instead of the hardcoded default widgets, persistence wired into every mutation path (drag/resize viaaddLayoutChangeListener,addWidget, widget close, KPI tiles),resetLayout()reworked to clear the server store and rebuild the default widget set (today it only clears clientlocalStorageand relies on the DOM's existinggs-*attributes), plus a new Playwright e2e for the reload round-trip per the acceptance criteria. That's comfortably over the ~200-line diff guideline for a single autofix pass.Recommend scoping this as a human-planned feature: decide the identity model first (even a placeholder single-user store would need an explicit choice), then split "store abstraction + wiring" from "reset semantics" from "e2e coverage" if it's still too big for one PR.