Commit Graph
3 Commits
Author SHA1 Message Date
ki a465912b55 BUG-06: Auto-Pack Undo via Snapshot + actionable Toast
Auto-Pack rief vorher layout_mod.pack() auf und schickte einen
simplen success-Toast. Wer aus Versehen klickte, hatte alle
manuellen Positionen verloren — kein Undo, kein Recovery.

Fix:
- packAll() speichert layoutItems als JSON-Snapshot in einer
  local closure (vor dem pack-Call).
- Nach erfolgreichem Pack: toast() bekommt einen 4. Parameter
  action={label, onClick}.
- Neues toast()-Feature: action-Button im Toast, clickbar trotz
  dismiss-on-click. Klick ruft onClick und dismissed den Toast.
- Bei Undo-Klick: POST /api/layout mit den snapshot-Items →
  Server restored → renderGrid() → 'Layout wiederhergestellt'.
- Modal-Text weist auf die 10s Undo-Möglichkeit hin.

Vorteile:
- Versehentlicher Klick auf Auto-Pack ist recoverable.
- Kein sessionStorage-Bloat, kein Multi-Tab-Konflikt
  (Closure-Variable statt global Storage).
- Toast-Pattern ist jetzt generisch — andere Aktionen
  (z.B. 'Snapshot wiederherstellen' aus Sidebar) können
  denselben Mechanismus nutzen.

Beweis: tests/test_autopack_undo.js (8/8 grün)
  1. Snapshot (JSON.stringify(layoutItems)) wird erstellt
  2. Toast mit action={label:'Rückgängig'}
  3. Undo ruft POST /api/layout mit snapshot-Items
  4. Modal-Body erwähnt 'rückgängig'
  5. CSS .toast-action Klasse vorhanden
  6. toast() unterstützt 4-Args (action-Parameter)
  7. Action-Button Click ruft onClick + dismiss
  8. .toast-action hat pointer-events:auto

Live-Test: GET /?demo=1 → 200, 90847 bytes
  toast-action: 6 occurrences (CSS + JS)
  Rückgängig: 1 mention
  JSON.stringify(layoutItems): 1

Closes #8
2026-08-29 17:44:58 +04:00
ki 6059748f9b Add BUG-04 test suite + .gitignore for .venv/
Re-holt die Tests vom BUG-04-Branch in diesen Branch, damit CI/Runs
vollständig sind. .gitignore ergänzt um .venv/ und tests/__pycache__/.
2026-08-29 17:43:02 +04:00
ki 9f705ad7e4 BUG-03: Span-Geometrie im Initial-Render (grid-column/grid-row direkt setzen)
Initial-Render hatte keine Span-Geometrie:
  renderGrid() hing Items in die Origin-Cell mit width:100% height:100%.
  Ein 2x2-Item sah damit aus wie eine 1x1-Box mit Mini-Inhalt.

Resize-Code (in BUG-01/02-Branch, applySize) setzte zwar korrekt
grid-column/row per JS — aber nur WÄHREND Resize. Initial war's kaputt.

Fix:
- renderGrid() hängt Items jetzt direkt in den Grid-Container (cont),
  nicht mehr in die Origin-Cell.
- style.gridColumn = '${it.x + 1} / span ${it.w}' setzt die CSS-Span-Geometrie
  direkt im Inline-Style.
- Origin-Cell bekommt nur noch die 'occupied'-Klasse (für die Optik).
- DOM-Baum: Items sind Geschwister der Cells → keine DOM-Kollision mehr,
  Drag-Events auf Nachbar-Cells werden nicht vom Item verschluckt.

Vorteile:
  - 2x2-Item rendert visuell über 2x2 Cells (richtige Größe beim ersten Laden)
  - Drag auf JEDE Zelle innerhalb der Item-Bbox funktioniert
  - applySize (Resize) kann den Span nahtlos aktualisieren ohne DOM-Wechsel
  - Kein Flicker beim Resize (initial state ist schon korrekt)

Beweis: tests/test_span_geometry.js (8/8 grün)
  1. gridColumn wird per JS gesetzt
  2. gridRow wird per JS gesetzt
  3. Item wird in Container (cont) gehängt
  4. Item wird NICHT mehr in Origin-Cell gehängt
  5. Origin-Cell bekommt 'occupied' Klasse
  6. gridColumn Format: <x+1> / span <w>
  7. Keine width:100% im Item-CSS-Block
  8. CSS-Kommentar erwähnt BUG-03

Hinweis: Mein ursprüngliches Issue-Statement war zu pessimistisch (Items
verdecken keine Nachbarzellen visuell). Sie saßen nur 1x1 in der
Origin-Cell. Dennoch ist der Fix substantiell: Initial-Render zeigt jetzt
korrekte Größe, und zukünftige Resize-Codes können sich auf den Span
verlassen ohne DOM-Mutation.

Closes #5
2026-08-29 17:42:49 +04:00