feat(tour): seitenspezifische Touren für jede Public/Auth-Page

Bisher hatten nur Startseite und Antrag-Detail eigene Touren — die
Fallback-Tour (Logo+Topbar+Sidebar) war für jede andere Page identisch.
User-Wunsch: pro Menüpunkt eigene Tour, die diese Page funktional
erklärt.

Pro Page 3-5 Stationen mit konkreten Selektoren auf die Hauptbereiche:
- Quellen: Volltextsuche, Treffer-Liste, Programm-Karten
- Methodik: TOC, GWÖ-Matrix, Pipeline
- Auswertungen: Tabs (4 Sichten), Filter, Visualisierung
- Stimmverhalten: Stimm-Index, Heuchelei-Quote, Cross-BL — eigene
  Variante via {% if v2_active_nav == 'stimmverhalten' %}, da
  Stimmverhalten dasselbe Template wie Auswertungen nutzt
- Tags: Tag-Wolke, gefilterte Treffer
- Merkliste: Liste, Empty-State
- Neuer Antrag: BL-Wahl, Drucksachen-Eingabe, Modell, Submit
- Abos: Filter, aktive Abos
- Atom-Feed: Filter, Feed-URL
- Landtag-Suche: BL, Suchbegriff, Treffer + Bewertung anstoßen
- Aktuelle Themen: Top-News, Cluster+Zeitreihe, PM-Generator

Texte ermächtigend formuliert (was-wofür-wie), nicht oberflächlich.
Selektoren mit Fallback-Liste (komma-separiert), damit Templates ohne
exakte Klassennamen die Station trotzdem zeigen können.
This commit is contained in:
Dotty Dotter 2026-05-09 09:03:59 +02:00
parent 722156cff6
commit bf6201eb00
10 changed files with 168 additions and 0 deletions

View File

@ -87,6 +87,19 @@
{% block body_scripts %} {% block body_scripts %}
<script> <script>
window.GWOE_TOUR_STEPS = [
{ selector: 'h1',
title: 'E-Mail-Abos',
text: 'Hier richtest du dir Benachrichtigungen ein — eine kurze Mail pro Tag mit den neuen Bewertungen, die zu deinen Filterkriterien passen.' },
{ selector: 'form, .v2-kasten:not(:has(.abos-list)), select[name="bundesland"]',
title: 'Filter setzen',
text: 'Du kannst nach Bundesland und Partei filtern. Eine leere Auswahl heißt „alle". Die Mail kommt nur, wenn neue Bewertungen die Kriterien erfüllen — keine Leer-Mails.' },
{ selector: '.abos-list, ul.abo-list, [id*="abo-list"]',
title: 'Aktive Abos',
text: 'Deine eingestellten Abos siehst du hier. Mit dem Button daneben kannst du jedes Abo wieder aufheben.' },
];
</script>
<script>
async function aboLoad() { async function aboLoad() {
var listEl = document.getElementById('abo-list'); var listEl = document.getElementById('abo-list');
try { try {

View File

@ -256,6 +256,22 @@
{% block body_scripts %} {% block body_scripts %}
<script> <script>
window.GWOE_TOUR_STEPS = [
{ selector: 'h1',
title: 'Aktuelle Themen — News × Anträge × PM',
text: 'Diese Seite verbindet drei Datenquellen: aktuelle politische Nachrichten (Tagesschau + Bundestag-RSS), inhaltlich passende Anträge aus unserer DB und einen LLM-gestützten Pressemitteilungs-Generator. So findest du, welche Anträge gerade thematisch in der Debatte sind.' },
{ selector: '.at-news, [class*="news-list"], .v2-kasten:has(.at-news)',
title: 'Top-News',
text: 'Aktuelle Nachrichten, gewichtet nach Relevanz für unser Themenfeld. Pro News siehst du verlinkte Anträge — ein Klick führt zur Detail-Bewertung.' },
{ selector: '.at-cluster, [class*="cluster"], .at-zeitreihe',
title: 'Themen-Cluster + Zeitreihe',
text: 'Wo häufen sich Themen? Wann hat eine Story Fahrt aufgenommen? Cluster gruppieren News inhaltlich, die Zeitreihe zeigt das Volumen pro Tag.' },
{ selector: '.at-pm, button[onclick*="generate"], [class*="presse"]',
title: 'Pressemitteilungs-Entwurf',
text: 'Aus einer News + einem passenden Antrag generiert das LLM einen PM-Entwurf — als kompakte Pressemitteilung oder Mastodon/Threads-Thread. Praktisch für Mandatsträger:innen, die schnell auf eine Story reagieren wollen.' },
];
</script>
<script>
let _atZeitreiheChart = null; let _atZeitreiheChart = null;
let _atActiveTab = 'news'; let _atActiveTab = 'news';
let _atSingleDate = null; // YYYY-MM-DD wenn aus Chart geklickt let _atSingleDate = null; // YYYY-MM-DD wenn aus Chart geklickt

View File

@ -419,6 +419,39 @@ table.modal-table th { background: var(--ecg-bg-subtle); font-weight: 700; }
{% block body_scripts %} {% block body_scripts %}
<script> <script>
{% if v2_active_nav == 'stimmverhalten' %}
window.GWOE_TOUR_STEPS = [
{ selector: 'h1',
title: 'Stimmverhalten × Gemeinwohl',
text: 'Diese Sicht verbindet zwei Datenquellen: Wer hat im Plenum wie abgestimmt — und wie passt das zum eigenen Wahlprogramm der Fraktion? Heuchelei (NEIN trotz passendem Programm) und Opportunismus (JA trotz Mismatch) werden hier sichtbar.' },
{ selector: '#tab-stimm-index, .panel-stimmverhalten, [class*="stimm"]',
title: 'Stimm-Index pro Fraktion',
text: 'Pro Fraktion: Anteil der Stimmen, die zum eigenen Wahlprogramm passen. Höher heißt: Fraktion stimmt konsistent mit ihrem Programm. Niedriger heißt: Bruch zwischen Versprechen und Stimme.' },
{ selector: '#tab-heuchelei, [class*="heuchelei"]',
title: 'Heuchelei-Quote',
text: 'Anträge, bei denen eine Fraktion mit NEIN gestimmt hat, obwohl der Antrag inhaltlich exakt zum eigenen Wahlprogramm passt (Wahlprogramm-Score ≥ 7/10). Klick auf eine Bar öffnet die Drucksachen-Liste.' },
{ selector: '.matrix-axis, [class*="cross-bl"]',
title: 'Cross-BL und Wert-Aufschlüsselung',
text: 'Zwei tiefere Sichten: gleiche Fraktion in mehreren Bundesländern (zeigt regionale Drift) und Stimm-Index pro GWÖ-Wert (Würde, Solidarität, Nachhaltigkeit, Gerechtigkeit, Demokratie).' },
];
{% else %}
window.GWOE_TOUR_STEPS = [
{ selector: 'h1',
title: 'Auswertungen — Aggregate über alle Anträge',
text: 'Hier siehst du Muster, die in einem einzelnen Antrag nicht sichtbar wären: Welche Bundesländer bringen viele kommunal-orientierte Anträge? Welche Parteien schneiden im Schnitt wie ab? Wie verteilen sich die Themen über die Wahlperiode?' },
{ selector: '.tabs, [role="tablist"], .v2-tabs',
title: 'Vier Sichten',
text: 'Bundesland-Partei-Matrix · Themen-Verteilung · Score-Histogramm · Stimmverhalten. Jede Sicht beantwortet eine andere Frage. Klick auf einen Tab wechselt die Ansicht.' },
{ selector: '.v2-kasten.outline-blue, .v2-toolbar',
title: 'Filter',
text: 'Bundesland und Wahlperiode filtern alle Sichten zusammen — Top-Bar, der globale BL-Selector wirkt sich auch hier aus. Die Diagramme reagieren live.' },
{ selector: 'table.gwoe-matrix, [class*="chart"], .matrix-grid',
title: 'Visualisierung',
text: 'Heatmaps und Bar-Charts zeigen Aggregate. Klick auf eine Zelle / Bar führt meist zu den dahinterliegenden Anträgen — Detail-Drilldown statt nur Statistik.' },
];
{% endif %}
</script>
<script>
let _tabLoaded = { 'bl-partei': false, 'themen': false, 'stimmverhalten': false, 'histogram': false }; let _tabLoaded = { 'bl-partei': false, 'themen': false, 'stimmverhalten': false, 'histogram': false };
let _histChart = null; let _histChart = null;
let _svCharts = { index: null, heuchelei: null, empfehlung: null, crossBl: null, zeitreihe: null }; let _svCharts = { index: null, heuchelei: null, empfehlung: null, crossBl: null, zeitreihe: null };

View File

@ -84,6 +84,19 @@
{% block body_scripts %} {% block body_scripts %}
<script> <script>
window.GWOE_TOUR_STEPS = [
{ selector: 'h1',
title: 'Atom-Feed',
text: 'Wenn du lieber per RSS/Atom-Reader auf dem Laufenden bleibst statt per E-Mail: Hier kannst du dir den Feed konfigurieren — Filter wie bei den Abos, Ausgabe als Atom-XML.' },
{ selector: '.v2-kasten:first-of-type, form',
title: 'Filter wählen',
text: 'Bundesland und Partei einstellen, dann gibt der Feed nur Anträge zurück, die zu deinen Kriterien passen. Leer heißt „alle".' },
{ selector: '#feed-url, input[type="url"], code',
title: 'Feed-URL kopieren',
text: 'Die generierte URL trägst du in deinen Reader ein (Feedly, Inoreader, NetNewsWire, etc.). Aktualisiert sich automatisch, wenn neue Bewertungen rein kommen.' },
];
</script>
<script>
function feedUpdate() { function feedUpdate() {
var bl = document.getElementById('feed-bl').value; var bl = document.getElementById('feed-bl').value;
var part = document.getElementById('feed-partei').value.trim(); var part = document.getElementById('feed-partei').value.trim();

View File

@ -197,6 +197,22 @@
{% block body_scripts %} {% block body_scripts %}
<script> <script>
window.GWOE_TOUR_STEPS = [
{ selector: 'h1',
title: 'Landtag-Suche',
text: 'Hier suchst du Anträge live in den Landtags-Portalen — auch solche, die das Tool noch nicht bewertet hat. Praktisch, wenn du eine bestimmte Drucksache aus den Nachrichten direkt aufrufen willst.' },
{ selector: 'select[name="bundesland"], #bl-select',
title: 'Bundesland',
text: 'In welchem Parlament suchen? Bundestag oder einer der 16 Landtage. Das Tool reicht die Suche an die jeweilige Quell-API durch.' },
{ selector: 'input[type="search"], input[name="q"], #q',
title: 'Suchbegriff',
text: 'Stichwort oder Drucksachen-Nummer. Die Live-Suche im Landtag bringt typischerweise mehr Treffer als die interne Datenbank, weil sie den ganzen offiziellen Bestand sieht.' },
{ selector: '#results, .v2-result-row',
title: 'Treffer + Bewertung anstoßen',
text: 'Pro Treffer siehst du, ob er bereits bewertet ist. Falls nicht, kannst du mit einem Klick die Analyse starten — das LLM prüft dann diesen Antrag.' },
];
</script>
<script>
/* Bekannte Assessments aus der DB laden, um „Bereits bewertet"-Status zu zeigen */ /* Bekannte Assessments aus der DB laden, um „Bereits bewertet"-Status zu zeigen */
var lsCheckedIds = new Set(); var lsCheckedIds = new Set();
(function () { (function () {

View File

@ -69,6 +69,19 @@
{% block body_scripts %} {% block body_scripts %}
<script> <script>
window.GWOE_TOUR_STEPS = [
{ selector: 'h1',
title: 'Merkliste — deine gespeicherten Anträge',
text: 'Auf jeder Antrag-Detail-Seite kannst du oben den „Merken"-Stern klicken. Hier sammeln sich diese Einträge — pro Konto persistent gespeichert, nicht mehr nur lokal im Browser.' },
{ selector: '#merkliste-results, .merkliste-entry',
title: 'Eintragsliste',
text: 'Pro Antrag siehst du Drucksachen-Nummer, Titel, Score und das Datum, an dem du ihn gemerkt hast. Klick auf den Titel öffnet das Detail. Das ✕ rechts entfernt einen Eintrag.' },
{ selector: '#merkliste-empty, #merkliste-login-hint',
title: 'Noch leer?',
text: 'Wenn du noch keine Einträge hast, gehe zur Antrags-Übersicht und klick bei einem Antrag auf den Stern. Solltest du Einträge aus der alten Merkliste-Variante haben, bietet das Tool dir einmalig den Import an.' },
];
</script>
<script>
(async function () { (async function () {
var loadingEl = document.getElementById('merkliste-loading'); var loadingEl = document.getElementById('merkliste-loading');
var loginEl = document.getElementById('merkliste-login-hint'); var loginEl = document.getElementById('merkliste-login-hint');

View File

@ -650,6 +650,22 @@
{% block body_scripts %} {% block body_scripts %}
<script> <script>
window.GWOE_TOUR_STEPS = [
{ selector: 'h1',
title: 'Methodik — wie wir bewerten',
text: 'Hier ist alles offen dokumentiert: das GWÖ-Wertegerüst, was unser Werkzeug daraus macht, wie die Analyse-Pipeline läuft. Keine Black-Box — du kannst jeden Schritt nachvollziehen.' },
{ selector: '.meth-toc, nav.meth-toc',
title: 'Inhaltsverzeichnis',
text: 'Springpunkte zu den einzelnen Abschnitten: Was ist die GWÖ, was macht der Antragsprüfer, die Matrix 2.0, die Pipeline, Datenquellen.' },
{ selector: '#matrix, .gwoe-matrix-grid',
title: 'Die GWÖ-Matrix 2.0',
text: 'Das interaktive Raster der Bewertung: fünf Werte (Würde, Solidarität, Nachhaltigkeit, Gerechtigkeit, Demokratie) × fünf Berührungsgruppen. Klick auf eine Zelle zeigt die Detail-Erklärung.' },
{ selector: '#pipeline',
title: 'Analyse-Pipeline',
text: 'Von der Drucksache zum Score: Wie das LLM den Text einordnet, wie wir Halluzinationen ausschließen, wie Zitate aus Wahlprogrammen verifiziert werden.' },
];
</script>
<script>
const fieldInfo = { const fieldInfo = {
"A1": { label: "Grundrechtsschutz in der Lieferkette", text: "<p><strong>Praxis:</strong> Wenn die öffentliche Hand Büromöbel, IT-Geräte oder Dienstkleidung beschafft: Unter welchen Bedingungen wurden diese hergestellt? Werden Lieferant:innen verpflichtet, Arbeitsschutzstandards und Menschenrechte einzuhalten?</p><p><strong>Theorie:</strong> Die GWÖ versteht Menschenwürde als unteilbar und kettenübergreifend. Das Feld A1 operationalisiert den Zusammenhang zwischen kommunaler Beschaffung und globalem Menschenrechtsschutz.</p>" }, "A1": { label: "Grundrechtsschutz in der Lieferkette", text: "<p><strong>Praxis:</strong> Wenn die öffentliche Hand Büromöbel, IT-Geräte oder Dienstkleidung beschafft: Unter welchen Bedingungen wurden diese hergestellt? Werden Lieferant:innen verpflichtet, Arbeitsschutzstandards und Menschenrechte einzuhalten?</p><p><strong>Theorie:</strong> Die GWÖ versteht Menschenwürde als unteilbar und kettenübergreifend. Das Feld A1 operationalisiert den Zusammenhang zwischen kommunaler Beschaffung und globalem Menschenrechtsschutz.</p>" },
"A2": { label: "Nutzen für die Gemeinde", text: "<p><strong>Praxis:</strong> Beauftragt die Kommune den Betrieb aus dem Ort — oder den billigsten Konzern aus dem Ausland? Bleiben Steuergelder in der Region?</p><p><strong>Theorie:</strong> Solidarität beginnt in der Nachbarschaft. Die GWÖ misst, ob die Beschaffungspolitik aktiv zur regionalen Wertschöpfung beiträgt.</p>" }, "A2": { label: "Nutzen für die Gemeinde", text: "<p><strong>Praxis:</strong> Beauftragt die Kommune den Betrieb aus dem Ort — oder den billigsten Konzern aus dem Ausland? Bleiben Steuergelder in der Region?</p><p><strong>Theorie:</strong> Solidarität beginnt in der Nachbarschaft. Die GWÖ misst, ob die Beschaffungspolitik aktiv zur regionalen Wertschöpfung beiträgt.</p>" },

View File

@ -124,6 +124,25 @@
{% block body_scripts %} {% block body_scripts %}
<script> <script>
window.GWOE_TOUR_STEPS = [
{ selector: 'h1',
title: 'Neuer Antrag prüfen',
text: 'Hier kannst du einen Antrag aus einem deutschen Parlament neu durch das LLM laufen lassen — falls er noch nicht in der Datenbank ist oder du eine aktualisierte Bewertung willst.' },
{ selector: 'select[name="bundesland"], #bundesland',
title: 'Bundesland wählen',
text: 'Aus welchem Parlament kommt der Antrag? Bundestag oder einer der 16 Landtage. Jeder hat sein eigenes Drucksachen-Format und seine eigenen Wahlprogramme.' },
{ selector: 'input[name="drucksache"], #drucksache',
title: 'Drucksachen-Nummer',
text: 'Format z.B. 18/12345 — die offizielle Aktennummer. Das Tool sucht den Antrag bei der jeweiligen Landtags-/Bundestags-Quelle und lädt das PDF.' },
{ selector: 'select[name="model"], #model, .model-select',
title: 'LLM-Modell',
text: 'Welches Modell soll bewerten? Standard ist qwen-plus (gutes Verhältnis Qualität/Kosten). Du kannst auf qwen-max wechseln für sensiblere Bewertung — kostet aber mehr.' },
{ selector: 'button[type="submit"], .v2-chip.primary',
title: 'Analyse starten',
text: 'Klick startet die Pipeline: Antrag laden → LLM-Call → Citation-Verifikation → DB-Speicherung. Dauert je nach Antragslänge 3090 Sekunden.' },
];
</script>
<script>
async function startAnalyse(e) { async function startAnalyse(e) {
e.preventDefault(); e.preventDefault();
const btn = document.getElementById('neu-btn'); const btn = document.getElementById('neu-btn');

View File

@ -297,6 +297,22 @@
{% block body_scripts %} {% block body_scripts %}
<script> <script>
window.GWOE_TOUR_STEPS = [
{ selector: 'h1',
title: 'Quellen — was hier liegt',
text: 'Diese Seite listet alle Wahl- und Grundsatzprogramme der Parteien, gegen die der GWÖ-Antragsprüfer Anträge bewertet. Aktuell sind das 287 Programme — historisch und aktuell, von Bundestag bis Bundesländer.' },
{ selector: '#quellen-q, .gwoe-search-form',
title: 'Volltextsuche',
text: 'Hier findest du Stellen in den Programmen — semantisch durchsuchbar. Wortunscharf: Endungen sind egal, verwandte Begriffe werden ebenfalls gefunden. Filter „nur aktuelle Programme" oder „auch historische" daneben.' },
{ selector: '.search-results, #search-results',
title: 'Treffer',
text: 'Pro Treffer siehst du das Programm, die Seitenzahl, einen Snippet-Auszug und einen Direkt-Link ins PDF mit gelb hervorgehobener Stelle.' },
{ selector: '.prog-card, .v2-kasten.outline-blue',
title: 'Programm-Karten',
text: 'Unten gruppiert nach Bundesland alle Programme als Karten — mit Direktlink zum PDF und Hinweis ob das Programm semantisch indiziert ist.' },
];
</script>
<script>
async function indexAll() { async function indexAll() {
const statusEl = document.getElementById('index-status'); const statusEl = document.getElementById('index-status');
statusEl.textContent = 'Indexierung gestartet …'; statusEl.textContent = 'Indexierung gestartet …';

View File

@ -88,6 +88,19 @@
{% block body_scripts %} {% block body_scripts %}
<script> <script>
window.GWOE_TOUR_STEPS = [
{ selector: 'h1',
title: 'Tags — Themen-Übersicht',
text: 'Diese Seite zeigt alle Themen, die das Tool in den Anträgen erkannt hat — als Wolke. Größere Tags bedeuten häufigere Themen.' },
{ selector: '.tag-cloud, #tag-cloud, .v2-toolbar',
title: 'Tag-Wolke',
text: 'Klick auf einen Tag filtert die Antrags-Liste unten — du kannst auch mehrere kombinieren. So findest du z.B. alle Anträge zu „Klimaschutz" und „Verkehr" gleichzeitig.' },
{ selector: '#v2-results',
title: 'Gefilterte Treffer',
text: 'Unten erscheinen alle Anträge zu den gewählten Themen, sortiert nach Score. Klick auf eine Karte öffnet die ausführliche Bewertung.' },
];
</script>
<script>
let _allItems = []; let _allItems = [];
let _selectedTags = new Set(); let _selectedTags = new Set();