From c09c2a49b9805981cbed986753691e0732c37972 Mon Sep 17 00:00:00 2001 From: claude-dev Date: Sun, 2 Aug 2026 12:19:52 +0000 Subject: [PATCH] feat(ui): Sammelaktionen auch in der klassischen Ansicht, mit Lucide-Icons Im Studio lassen sich mehrere Faelle auf einmal archivieren oder loeschen, in der klassischen Ansicht ging das nur einzeln ueber die Aktionsleiste. Wer dort zehn alte Lagen wegraeumen wollte, musste jede einzeln oeffnen. Die Seitenleiste bekommt deshalb dieselbe Bedienung wie das Studio. Unten stehen zwei Knoepfe, Archivieren und Loeschen. Der erste Klick schaltet den Auswahlmodus ein, erst dann erscheinen Haken in der Lagenliste, an Stelle des Statuspunktes. Ein Klick auf eine Zeile waehlt dann aus, statt die Lage zu oeffnen. Bestaetigt wird in der Leiste darunter, die mitzaehlt und nur anbietet, was zur Auswahl passt. Sind nur aktive Lagen gewaehlt, erscheint kein Aktivieren-Knopf, im Loeschmodus keiner der beiden anderen. "Alle sichtbaren" beruecksichtigt den Filter der Seitenleiste, waehlt also bei aktivem Eigene-Filter nur die eigenen Lagen aus. Das Loeschen fragt vorher nach und nennt Titel und Artikelzahl, weil es nicht rueckgaengig zu machen ist. Die Aktionen laufen nacheinander ueber die normalen Endpunkte, damit deren Rechtepruefung greift, und Fehlschlaege werden mit Nummer gemeldet statt still verschluckt. War die offene Lage dabei, springt die Ansicht zurueck. Dazu Lucide-Icons fuer Archivieren, Aktivieren, Loeschen und Abbrechen, in beiden Ansichten. Im Studio setzte _renderBulkBar die Beschriftung bisher ueber textContent des Knopfes, was das Icon bei jedem Neuzeichnen entfernt haette. Die Beschriftung liegt jetzt in einer eigenen span. Cache-Buster auf 20260802a, sonst laden Browser die alten Skripte weiter. Neu sind 34 Pruefungen, sie laufen ohne Browser gegen ein DOM-Double. Co-Authored-By: Claude Opus 5 (1M context) --- src/static/css/studio.css | 5 + src/static/css/style.css | 100 +++++++++++++++ src/static/dashboard.html | 50 +++++++- src/static/i18n/de.json | 4 + src/static/i18n/en.json | 4 + src/static/js/app.js | 147 ++++++++++++++++++++++ src/static/js/components.js | 15 ++- src/static/js/studio.js | 12 +- src/static/studio.html | 20 +-- tests/test_sammelaktionen.js | 237 +++++++++++++++++++++++++++++++++++ 10 files changed, 574 insertions(+), 20 deletions(-) create mode 100644 tests/test_sammelaktionen.js diff --git a/src/static/css/studio.css b/src/static/css/studio.css index 22f7a8b..632d82e 100644 --- a/src/static/css/studio.css +++ b/src/static/css/studio.css @@ -383,6 +383,10 @@ .btn-bulk { flex: 1; min-width: 84px; + display: inline-flex; + align-items: center; + justify-content: center; + gap: 6px; padding: 6px 10px; border-radius: var(--radius-md, 6px); border: 1px solid var(--border); @@ -394,6 +398,7 @@ cursor: pointer; transition: border-color .15s, background .15s, color .15s; } +.btn-bulk svg { flex-shrink: 0; } .btn-bulk:hover { border-color: var(--accent); color: var(--accent); } .btn-bulk[hidden] { display: none; } .btn-bulk.danger { color: var(--danger, #EF4444); } diff --git a/src/static/css/style.css b/src/static/css/style.css index 483b3ef..90c3cc9 100644 --- a/src/static/css/style.css +++ b/src/static/css/style.css @@ -3277,6 +3277,106 @@ body.first-refresh-blocking .header { } /* Sidebar Sources Link */ +/* === Sammelaktionen in der Seitenleiste ============================== */ +/* Zwei Zustaende. Normal stehen dort nur die beiden Startknoepfe, im + Auswahlmodus die Bestaetigungsleiste. Beides sitzt ueber dem Fussbereich + mit Quellen und Feedback. */ +.sidebar-bulk { + padding: var(--sp-md) var(--sp-xl) 0; + display: flex; + gap: var(--sp-md); +} + +.sidebar-bulk[hidden] { + display: none; +} + +.sidebar-bulk-btn { + flex: 1; + min-height: 32px; + font-size: 12px; + font-weight: 500; + padding: 0 var(--sp-md); +} + +.sidebar-bulk-btn svg { + flex-shrink: 0; +} + +.sidebar-bulk-btn.danger { + color: var(--error); +} + +.sidebar-bulk-btn.danger:hover:not(:disabled) { + background: var(--tint-error); + border-color: var(--error); +} + +.sidebar-bulk-btn.ghost { + color: var(--text-tertiary); +} + +.sidebar-bulk-btn[hidden] { + display: none; +} + +/* Bestaetigungsleiste: untereinander, damit die Zaehlung lesbar bleibt */ +.sidebar-bulk-active { + flex-direction: column; + align-items: stretch; + gap: var(--sp-md); + padding-bottom: var(--sp-md); + border-top: 1px solid var(--accent); + padding-top: var(--sp-md); +} + +.sidebar-bulk-count { + font-size: 12px; + font-weight: 600; + color: var(--text-secondary); +} + +.sidebar-bulk-all { + display: flex; + align-items: center; + gap: var(--sp-md); + font-size: 12px; + color: var(--text-tertiary); + cursor: pointer; +} + +.sidebar-bulk-all input { + accent-color: var(--accent); + cursor: pointer; +} + +.sidebar-bulk-actions { + display: flex; + flex-wrap: wrap; + gap: var(--sp-md); +} + +/* Haken in der Lagenliste, nur im Auswahlmodus sichtbar */ +.incident-check { + display: flex; + align-items: center; + flex-shrink: 0; + cursor: pointer; +} + +.incident-check input { + accent-color: var(--accent); + cursor: pointer; + margin: 0; +} + +/* Ausgewaehlte Lage: vollstaendig umlaufender Rahmen, kein einseitiger Streifen */ +.incident-item.picked { + outline: 2px solid var(--accent); + outline-offset: -2px; + border-radius: var(--radius); +} + .sidebar-sources-link { padding: var(--sp-lg) var(--sp-xl); border-top: 1px solid var(--border); diff --git a/src/static/dashboard.html b/src/static/dashboard.html index c4112f9..040d3f2 100644 --- a/src/static/dashboard.html +++ b/src/static/dashboard.html @@ -13,7 +13,7 @@ - +