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) <noreply@anthropic.com>
Dieser Commit ist enthalten in:
claude-dev
2026-08-02 12:19:52 +00:00
Ursprung e440ef93d1
Commit c09c2a49b9
10 geänderte Dateien mit 574 neuen und 20 gelöschten Zeilen

Datei anzeigen

@@ -13,7 +13,7 @@
<link rel="stylesheet" href="/static/vendor/leaflet.css">
<link rel="stylesheet" href="/static/vendor/MarkerCluster.css">
<link rel="stylesheet" href="/static/vendor/MarkerCluster.Default.css">
<link rel="stylesheet" href="/static/css/style.css?v=20260723a">
<link rel="stylesheet" href="/static/css/style.css?v=20260802a">
<style>
/* Export Modal Radio */
.export-radio { display:flex; align-items:center; gap:10px; padding:8px 12px; cursor:pointer; border-radius:var(--radius-sm); transition:background 0.15s; border:1px solid transparent; margin-bottom:4px; }
@@ -123,6 +123,46 @@
</h2>
<div id="archived-incidents" aria-live="polite" style="display:none;"></div>
</div>
<!-- Sammelaktionen. Der erste Klick schaltet den Auswahlmodus ein,
erst dann erscheinen die Haken in der Lagenliste. -->
<div class="sidebar-bulk" id="sidebar-bulk-tools">
<button class="btn btn-secondary btn-small sidebar-bulk-btn" onclick="App.startBulkMode('archive')" title="Mehrere Lagen archivieren oder wieder aktivieren" data-i18n-attr="title:sidebar.bulk_archive_title">
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect width="20" height="5" x="2" y="3" rx="1"/><path d="M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8"/><path d="M10 12h4"/></svg>
<span data-i18n="action.archive">Archivieren</span>
</button>
<button class="btn btn-secondary btn-small sidebar-bulk-btn danger" onclick="App.startBulkMode('delete')" title="Mehrere Lagen löschen" data-i18n-attr="title:sidebar.bulk_delete_title">
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 6h18"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/><line x1="10" x2="10" y1="11" y2="17"/><line x1="14" x2="14" y1="11" y2="17"/></svg>
<span data-i18n="action.delete">Löschen</span>
</button>
</div>
<!-- Auswahlmodus. Hier wird die Sammelaktion bestätigt oder verworfen. -->
<div class="sidebar-bulk sidebar-bulk-active" id="sidebar-bulk-bar" hidden>
<div class="sidebar-bulk-count" id="sidebar-bulk-count" aria-live="polite"></div>
<label class="sidebar-bulk-all">
<input type="checkbox" id="sidebar-bulk-all" onchange="App.selectAllVisible(this.checked)">
<span data-i18n="sidebar.bulk_all">Alle sichtbaren</span>
</label>
<div class="sidebar-bulk-actions">
<button class="btn btn-secondary btn-small sidebar-bulk-btn" id="sidebar-bulk-archive" onclick="App.bulkStatus('archived')">
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect width="20" height="5" x="2" y="3" rx="1"/><path d="M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8"/><path d="M10 12h4"/></svg>
<span>Archivieren</span>
</button>
<button class="btn btn-secondary btn-small sidebar-bulk-btn" id="sidebar-bulk-activate" onclick="App.bulkStatus('active')">
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect width="20" height="5" x="2" y="3" rx="1"/><path d="M4 8v11a2 2 0 0 0 2 2h2"/><path d="M20 8v11a2 2 0 0 1-2 2h-2"/><path d="m9 15 3-3 3 3"/><path d="M12 12v9"/></svg>
<span>Aktivieren</span>
</button>
<button class="btn btn-secondary btn-small sidebar-bulk-btn danger" id="sidebar-bulk-delete" onclick="App.bulkDelete()">
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 6h18"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/><line x1="10" x2="10" y1="11" y2="17"/><line x1="14" x2="14" y1="11" y2="17"/></svg>
<span>Löschen</span>
</button>
<button class="btn btn-secondary btn-small sidebar-bulk-btn ghost" onclick="App.endBulkMode()" title="Auswahl verwerfen">
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>
<span data-i18n="action.cancel">Abbrechen</span>
</button>
</div>
</div>
<div class="sidebar-sources-link">
<button class="btn btn-secondary btn-full btn-small" onclick="App.openSourceManagement()" title="Quellen verwalten" data-i18n-attr="title:sidebar.manage_sources_title">
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M3 5v14c0 1.66 4.03 3 9 3s9-1.34 9-3V5"/><path d="M3 12c0 1.66 4.03 3 9 3s9-1.34 9-3"/></svg>
@@ -170,8 +210,8 @@
<button class="btn btn-primary btn-small" id="refresh-btn" data-i18n="action.refresh">Aktualisieren</button>
<button class="btn btn-secondary btn-small" id="edit-incident-btn" data-i18n="action.edit">Bearbeiten</button>
<button class="btn btn-secondary btn-small" onclick="App.openExportModal()" data-i18n="action.export">Bericht exportieren</button>
<button class="btn btn-secondary btn-small" id="archive-incident-btn" data-i18n="action.archive">Archivieren</button>
<button class="btn btn-danger btn-small" id="delete-incident-btn" data-i18n="action.delete">Löschen</button>
<button class="btn btn-secondary btn-small" id="archive-incident-btn" title="Diese Lage archivieren"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect width="20" height="5" x="2" y="3" rx="1"/><path d="M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8"/><path d="M10 12h4"/></svg><span data-i18n="action.archive">Archivieren</span></button>
<button class="btn btn-danger btn-small" id="delete-incident-btn" title="Diese Lage löschen"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 6h18"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/><line x1="10" x2="10" y1="11" y2="17"/><line x1="14" x2="14" y1="11" y2="17"/></svg><span data-i18n="action.delete">Löschen</span></button>
</div>
</div>
<div class="incident-header-row2">
@@ -818,11 +858,11 @@
<script src="/static/js/i18n.js?v=20260513a"></script>
<script src="/static/js/api.js?v=20260725b"></script>
<script src="/static/js/ws.js?v=20260316b"></script>
<script src="/static/js/components.js?v=20260731a"></script>
<script src="/static/js/components.js?v=20260802a"></script>
<script src="/static/js/layout.js?v=20260513f"></script>
<script src="/static/js/pipeline.js?v=20260513d"></script>
<script src="/static/js/a11y.js?v=20260725a"></script>
<script src="/static/js/app.js?v=20260731a"></script>
<script src="/static/js/app.js?v=20260802a"></script>
<script src="/static/js/cluster-data.js?v=20260322f"></script>
<script src="/static/js/tutorial.js?v=20260316z"></script>
<script src="/static/js/chat.js?v=20260514e"></script>