From 2df2fa1cfa48ba08117a491652f8aa11eb760407 Mon Sep 17 00:00:00 2001 From: claude-dev Date: Sat, 25 Jul 2026 18:23:27 +0000 Subject: [PATCH] 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 --- src/routers/audit.py | 33 +++++++++----- src/static/css/style.css | 43 +++++++++++++++++++ src/static/dashboard.html | 51 ++++------------------ src/static/js/app.js | 30 +++++++++++++ src/static/js/audit.js | 79 +++++++++++++++++----------------- src/static/js/aufgaben.js | 90 +++++++++++++++++++++++++++++++++------ src/static/js/sources.js | 75 ++++++++++++++++++-------------- 7 files changed, 263 insertions(+), 138 deletions(-) diff --git a/src/routers/audit.py b/src/routers/audit.py index d7ed9f4..e651d7f 100644 --- a/src/routers/audit.py +++ b/src/routers/audit.py @@ -2,7 +2,7 @@ import json import logging from typing import Optional -from fastapi import APIRouter, Depends +from fastapi import APIRouter, Depends, HTTPException from auth import get_current_admin from database import db_dependency import aiosqlite @@ -25,7 +25,7 @@ async def list_audit( action: Optional[str] = None, resource_type: Optional[str] = None, resource_id: Optional[int] = None, - admin_id: Optional[int] = None, + admin_id: Optional[str] = None, from_ts: Optional[str] = None, to_ts: Optional[str] = None, limit: int = 200, @@ -33,7 +33,11 @@ async def list_audit( admin: dict = Depends(get_current_admin), db: aiosqlite.Connection = Depends(db_dependency), ): - """Audit-Log-Eintraege auflisten mit Filter + Pagination.""" + """Audit-Log-Eintraege auflisten mit Filter + Pagination. + + action, resource_type und admin_id akzeptieren kommagetrennte Mehrfachwerte + (Checkbox-Filter im Frontend), ein Einzelwert funktioniert weiterhin. + """ if limit < 1 or limit > 1000: limit = 200 if offset < 0: @@ -42,17 +46,26 @@ async def list_audit( where = [] params = [] if action: - where.append("action = ?") - params.append(action) + vals = [v.strip() for v in action.split(",") if v.strip()] + if vals: + where.append(f"action IN ({','.join('?' for _ in vals)})") + params.extend(vals) if resource_type: - where.append("resource_type = ?") - params.append(resource_type) + vals = [v.strip() for v in resource_type.split(",") if v.strip()] + if vals: + where.append(f"resource_type IN ({','.join('?' for _ in vals)})") + params.extend(vals) if resource_id is not None: where.append("resource_id = ?") params.append(resource_id) - if admin_id is not None: - where.append("admin_id = ?") - params.append(admin_id) + if admin_id: + try: + ids = [int(v) for v in admin_id.split(",") if v.strip()] + except ValueError: + raise HTTPException(status_code=422, detail="admin_id muss eine Zahl oder kommagetrennte Zahlen sein") + if ids: + where.append(f"admin_id IN ({','.join('?' for _ in ids)})") + params.extend(ids) if from_ts: where.append("ts >= ?") params.append(from_ts) diff --git a/src/static/css/style.css b/src/static/css/style.css index db7b9fc..ef7cee6 100644 --- a/src/static/css/style.css +++ b/src/static/css/style.css @@ -928,6 +928,49 @@ input[type="date"].filter-select { padding: 6px 10px; } .health-run-item { display: inline-flex; align-items: center; gap: 8px; } .health-run-item #healthRunInfo { font-size: 12px; } +/* Checkbox-Filterleisten (Standard fuer alle Filter im Portal) */ +.filter-bar { + display: flex; + flex-direction: column; + gap: 4px; + padding: 10px 14px; + margin-bottom: 14px; + background: var(--bg-secondary); + border: 1px solid var(--border); + border-radius: 8px; +} +.filter-group { + display: flex; + align-items: baseline; + gap: 4px 10px; + flex-wrap: wrap; +} +.filter-group-label { + font-size: 11px; + font-weight: 600; + color: var(--text-secondary); + text-transform: uppercase; + letter-spacing: 0.4px; + min-width: 92px; + cursor: default; +} +.filter-check { + display: inline-flex; + align-items: center; + gap: 5px; + font-size: 13px; + cursor: pointer; + padding: 2px 7px; + border-radius: 6px; + user-select: none; +} +.filter-check:hover { background: var(--bg-tertiary); } +.filter-check input { + accent-color: var(--accent); + cursor: pointer; + margin: 0; +} + /* Checkbox-Spalte: nur sichtbar bei Herkunfts-Filter "Kundenquellen" */ .select-col { display: none; } table.show-select .select-col { display: table-cell; } diff --git a/src/static/dashboard.html b/src/static/dashboard.html index 5f80542..67a0bf7 100644 --- a/src/static/dashboard.html +++ b/src/static/dashboard.html @@ -6,7 +6,7 @@ AegisSight Monitor-Verwaltung - +