feat(ui): alle Filter als Checkbox-Gruppen statt Dropdowns + Aufgaben-Filter

- Neuer wiederverwendbarer Helper renderFilterGroup (app.js) + filter-bar-CSS.
  Mehrfachauswahl per Checkbox, nichts angehakt = alle, Gold-Akzent.
- Quellenliste: Herkunft/Typ/Status/Kategorie/Sprache als Checkbox-Leiste
  unter der Action-Bar. Checkbox-Spalte + Bulk-Promote erscheinen, wenn der
  Herkunfts-Filter ausschliesslich auf Kundenquellen steht.
- Aufgaben ist jetzt filterbar: Vorschlagstyp und Prioritaet fuer die
  Vorschlags-Tabelle, Konfidenz-Stufen (ab 85, 70 bis 85, 50 bis 70,
  unter 50 Prozent) fuer die Klassifikations-Karten. Das alte
  Mindest-Konfidenz-Dropdown entfaellt, die Queue laedt einmal komplett
  und filtert clientseitig.
- Audit-Log: Aktion/Ressource/Admin als Checkbox-Gruppen, Backend
  akzeptiert dafuer kommagetrennte Mehrfachwerte (IN-Filter,
  Einzelwert bleibt kompatibel). Ressourcen-ID und Datumsfelder bleiben
  Eingabefelder.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Dieser Commit ist enthalten in:
claude-dev
2026-07-25 18:23:27 +00:00
Ursprung 14e766173c
Commit 2df2fa1cfa
7 geänderte Dateien mit 263 neuen und 138 gelöschten Zeilen

Datei anzeigen

@@ -1375,6 +1375,36 @@ function populateSelect(el, items, allLabel) {
if (current && items.some(it => it.key === current)) el.value = current;
}
// Checkbox-Filtergruppe (Standard für alle Filter im Portal, statt Dropdowns).
// selected ist ein Set mit den angehakten Keys. Nichts angehakt = keine
// Einschränkung. onChange wird nach jedem Toggle aufgerufen.
function renderFilterGroup(container, title, items, selected, onChange) {
if (!container) return;
const wrap = document.createElement("div");
wrap.className = "filter-group";
const lbl = document.createElement("span");
lbl.className = "filter-group-label";
lbl.textContent = title;
lbl.title = "Nichts angehakt = alle";
wrap.appendChild(lbl);
(items || []).forEach((it) => {
const label = document.createElement("label");
label.className = "filter-check";
const cb = document.createElement("input");
cb.type = "checkbox";
cb.checked = selected.has(it.key);
cb.addEventListener("change", () => {
if (cb.checked) selected.add(it.key);
else selected.delete(it.key);
onChange();
});
label.appendChild(cb);
label.appendChild(document.createTextNode(it.label));
wrap.appendChild(label);
});
container.appendChild(wrap);
}
document.addEventListener("DOMContentLoaded", () => {
// Beim Page-Load Meta einmalig laden (asynchron, blockiert nicht)
if (window.API && (localStorage.getItem("token") || window.location.pathname === "/dashboard")) {