diff --git a/app/static/v2/v2.css b/app/static/v2/v2.css index 73e3438..b5872fc 100644 --- a/app/static/v2/v2.css +++ b/app/static/v2/v2.css @@ -819,6 +819,18 @@ body.v2 ul.v2-manual ul li::before { body.v2 .v2-main { padding: 16px 12px; } + /* Topbar darf auf Mobile umbrechen, sonst pusht das Auth-Widget + + Bundesland-Selector + Theme-Toggle die rechte Kante ueber 390 px. */ + body.v2 .v2-topbar { + flex-wrap: wrap; + height: auto; + min-height: 32px; + row-gap: 4px; + padding: 4px 12px; + } + body.v2 .v2-topbar > * { + max-height: none; + } .v2-sidebar { display: none; diff --git a/app/templates/v2/base.html b/app/templates/v2/base.html index 85f0938..1e6ff37 100644 --- a/app/templates/v2/base.html +++ b/app/templates/v2/base.html @@ -79,7 +79,6 @@
- {{ icon("arrow-square-out", 13) }} Klassische Ansicht {{ icon("info", 13) }} Methodik {{ icon("book-open", 13) }} Quellen diff --git a/app/templates/v2/screens/tags.html b/app/templates/v2/screens/tags.html index dd57e5c..2a6beba 100644 --- a/app/templates/v2/screens/tags.html +++ b/app/templates/v2/screens/tags.html @@ -37,6 +37,20 @@ font-size: 10px; } .tag-pill.active .tag-count { opacity: 0.9; } +/* Tags, die mit aktuellen Filtern zu 0 Treffern führen würden, werden + ausgegraut. Klickbar bleiben sie (User kann „falsche" Auswahl zurück- + nehmen), aber visuell deutlich entwertet. */ +.tag-pill.disabled { + opacity: 0.35; + background: var(--ecg-bg-subtle); + border-style: dashed; + color: var(--ecg-text-muted); +} +.tag-pill.disabled:hover { + background: var(--ecg-bg-subtle); + border-color: var(--ecg-text-muted); + color: var(--ecg-text-muted); +} {% endblock %} @@ -116,12 +130,42 @@ function toggleTag(btn, tag) { btn.classList.add('active'); } renderFiltered(); + updateTagAvailability(); } function clearFilters() { _selectedTags.clear(); document.querySelectorAll('.tag-pill.active').forEach(b => b.classList.remove('active')); renderFiltered(); + updateTagAvailability(); +} + +/* Items, die zu den aktuellen aktiven Filtern passen. + Wird sowohl fuer die Ergebnis-Liste als auch fuer Tag-Greying genutzt. */ +function currentFilteredItems() { + if (!_selectedTags.size) return _allItems.slice(); + return _allItems.filter(a => { + const tags = new Set(a.themen || []); + return Array.from(_selectedTags).every(t => tags.has(t)); + }); +} + +/* Pro Tag-Pill pruefen: wuerde Hinzufuegen dieses Tags die Ergebnisliste + auf 0 reduzieren? Wenn ja → ausgrauen. Aktive Tags werden nicht + ausgegraut (sonst kann man sie nicht mehr abwaehlen). */ +function updateTagAvailability() { + const base = currentFilteredItems(); + document.querySelectorAll('.tag-cloud .tag-pill').forEach(btn => { + const tag = btn.dataset.tag; + if (!tag) return; + if (_selectedTags.has(tag)) { + btn.classList.remove('disabled'); + return; + } + // Wuerde Hinzufuegen dieses Tags die Liste leer machen? + const wouldHave = base.some(a => (a.themen || []).includes(tag)); + btn.classList.toggle('disabled', !wouldHave); + }); } function renderFiltered() { @@ -140,10 +184,7 @@ function renderFiltered() { `${t}` ).join(' '); - const filtered = _allItems.filter(a => { - const tags = new Set(a.themen || []); - return Array.from(_selectedTags).every(t => tags.has(t)); - }); + const filtered = currentFilteredItems(); if (!filtered.length) { resultsEl.innerHTML = '

Keine Ergebnisse

Die Filterauswahl liefert keine Treffer.

'; @@ -151,19 +192,25 @@ function renderFiltered() { } resultsEl.innerHTML = filtered.map(a => { - const score = (typeof a.gwoe_score === 'number') ? a.gwoe_score.toFixed(1) : '—'; + /* API-Felder: title (englisch), gwoe_score oder gwoeScore. Vorher + wurde a.titel (deutsch) gelesen — gibt's nicht → Fallback auf + Drucksache, was dann wie ein leeres Resultat aussieht. */ + const score = (typeof a.gwoe_score === 'number') ? a.gwoe_score.toFixed(1) + : (typeof a.gwoeScore === 'number') ? a.gwoeScore.toFixed(1) + : '—'; const bl = a.bundesland || ''; const fraktion = (a.fraktionen || []).join(', '); - const title = a.titel || a.drucksache; + const title = a.title || a.titel || a.drucksache; + const escAttr = (s) => String(s).replace(/[&<>"']/g, c => ({'&':'&','<':'<','>':'>','"':'"',"'":'''})[c]); return `
- ${bl} - ${a.drucksache} - ${fraktion ? `${fraktion}` : ''} + ${escAttr(bl)} + ${escAttr(a.drucksache)} + ${fraktion ? `${escAttr(fraktion)}` : ''}
-
${title}
+
${escAttr(title)}
Score ${score}