From f69fa1b95ef17926077d140ab6486ddaf3ed99f6 Mon Sep 17 00:00:00 2001 From: Claude Code Date: Fri, 22 May 2026 13:37:44 +0000 Subject: [PATCH] feat(sources): Quellenuebersicht der Lage nach Typ filterbar Die Quellenuebersicht innerhalb einer Lage zeigt jetzt Filter-Chips (Alle / Web / Telegram / X) und blendet die Quellen-Boxen nach Quellentyp ein und aus. Die Chips erscheinen nur, wenn neben Web auch Telegram- oder X-Quellen vorkommen. - sources-summary-Endpoint liefert pro Quelle einen source_type, abgeleitet aus dem source-Praefix (X: / Telegram: / sonst Web) - Filter-Chips und data-type in renderSourceOverviewFromSummary - App.filterSourceOverview blendet die Boxen nach Typ - Chip-Styles in style.css Co-Authored-By: Claude Opus 4.7 (1M context) --- src/routers/incidents.py | 8 ++++++++ src/static/css/style.css | 33 +++++++++++++++++++++++++++++++++ src/static/dashboard.html | 6 +++--- src/static/js/app.js | 20 ++++++++++++++++++++ src/static/js/components.js | 23 ++++++++++++++++++++++- 5 files changed, 86 insertions(+), 4 deletions(-) diff --git a/src/routers/incidents.py b/src/routers/incidents.py index 9debb69..921538b 100644 --- a/src/routers/incidents.py +++ b/src/routers/incidents.py @@ -507,6 +507,14 @@ async def get_articles_sources_summary( d = dict(r) langs = (d.pop("languages") or "de").split(",") d["languages"] = sorted({(l or "de").strip() for l in langs if l is not None}) + # Quellentyp aus dem source-Praefix ableiten (fuer den Typ-Filter der Quellenuebersicht) + src = d.get("source") or "" + if src.startswith("X: "): + d["source_type"] = "x" + elif src.startswith("Telegram: "): + d["source_type"] = "telegram" + else: + d["source_type"] = "web" sources.append(d) # Sprach-Verteilung gesamt cursor = await db.execute( diff --git a/src/static/css/style.css b/src/static/css/style.css index 38862cd..236d9de 100644 --- a/src/static/css/style.css +++ b/src/static/css/style.css @@ -1715,6 +1715,39 @@ a.dev-source-pill:hover { color: var(--text-primary); } +.source-type-filter-chips { + display: flex; + flex-wrap: wrap; + gap: var(--sp-xs); + margin: var(--sp-sm) 0 var(--sp-xs); +} + +.source-type-filter-chip { + font: inherit; + font-size: 11px; + padding: 3px 10px; + border-radius: var(--radius); + border: 1px solid var(--border); + background: var(--bg-secondary); + color: var(--text-secondary); + cursor: pointer; +} + +.source-type-filter-chip:hover { + border-color: var(--accent); + color: var(--text-primary); +} + +.source-type-filter-chip.active { + background: var(--accent); + border-color: var(--accent); + color: #fff; +} + +.source-type-filter-chip.active strong { + color: #fff; +} + .source-overview-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); diff --git a/src/static/dashboard.html b/src/static/dashboard.html index cd5c270..229e9b9 100644 --- a/src/static/dashboard.html +++ b/src/static/dashboard.html @@ -13,7 +13,7 @@ - +