Commit Graph

5 Commits

Author SHA1 Message Date
Dotty Dotter
4c989ea443 fix(tour, csp): media-src für Tour-Audio + Tour global außer Administration
Zwei Bugs:

1) Audio kam nicht durch — die Content-Security-Policy hatte kein
   media-src und fiel auf default-src 'self' zurück. data:- (silent-WAV
   zum Element-Unlock) und blob:-URLs (ElevenLabs-MP3-Cache) wurden
   geblockt. Browser-Fehlermeldung im Console: „Loading media from
   ‚data:audio/wav;base64,…' violates the following Content Security
   Policy directive". Fix: ``media-src 'self' data: blob:;`` ergänzt.

2) Tour war nur auf Startseite + Antrag-Detail eingebunden. User-Wunsch:
   auf jeder Page außer Administration. Lösung: Tour-Engine-Include in
   v2/base.html, mit ``{% if v2_active_nav not in [admin_*] %}``-Guard.
   Pages ohne eigene ``window.GWOE_TOUR_STEPS`` bekommen einen Fallback
   mit drei Stationen (Logo+Konzept, Topbar, Sidebar).

   Topbar-Tour-Link sichtbar wenn ``window.gwoeTourStart`` existiert
   (Engine geladen) — nicht mehr abhängig von Page-eigenen Steps.

Aufräumen: redundante Tour-Includes aus durchsuchen.html und
antrag_detail.html entfernt — die Engine kommt jetzt nur einmal aus
base.html.
2026-05-09 08:43:35 +02:00
Dotty Dotter
e397ae5028 fix(tour, nav): Audio-Auto-Play entsperren + Daten-Nav für alle sichtbar
Drei zusammenhängende UI-Bugs:

1) Audio kam nicht — Browser-Auto-Play-Block. ``new Audio(blobUrl).play()``
   nach einem await zählt nicht mehr als User-Gesture; Safari/Chrome
   kassieren mit NotAllowedError. Fix: persistentes <audio>-Element wird
   einmal beim Tour-Start (im Click-Handler, synchron) mit einer
   1×1-silent-WAV entsperrt. Folgende src-Updates spielen ohne Block.

2) Tour-Bubble „Weiter"-Button sah 90er aus — der lokale CSS-Override
   ``.gwoe-tour-bubble .v3-action-btn.primary`` hat den modernen
   pill-shaped Style ausgehebelt. Override entfernt; nutzt jetzt das
   globale ``.v3-action-btn.primary`` (teal-solid, runde Ecken,
   weicher Drop-Shadow).

3) Tour erzählt anonymen User:innen über „Auswertungen" und
   „Stimmverhalten", die in der linken Nav für Anonyme nicht sichtbar
   waren. Aggregierte Daten sind öffentlich — Daten-Nav-Gruppe jetzt für
   alle sichtbar (Auswertungen, Stimmverhalten, Aktuelle Themen,
   Export-API, Atom-Feed). Persönliche Items (Merkliste, Abos, Neuer
   Antrag, Batch) bleiben eingeloggt. Cluster + Landtag-Suche bleiben
   eingeloggt/admin (Backend-Routen sind ohnehin require_auth).
2026-05-09 08:07:27 +02:00
Dotty Dotter
6ec05d2b86 feat(tour): ElevenLabs-Voice für die Tour (#185 Phase 2)
Audio-Backend:
- ``app/tour_audio.py`` ruft ElevenLabs-TTS mit voice_id=Domi
  (AZnzlk1XvdvUeBnXmlld) und model=eleven_multilingual_v2. ENV-konfiguriert
  via ``ELEVENLABS_API_KEY``, ``ELEVENLABS_VOICE_ID``, ``ELEVENLABS_MODEL_ID``.
- Voice-Settings: stability 0.55, similarity_boost 0.7 (warm, klar, natürlich).
- Caching: SHA-256(text|voice|model) → ``data/tour_audio/<hash>.mp3``.
  Folgeabrufe gehen aus dem Datei-Cache, kein API-Quota-Verbrauch.

Endpoint: ``GET /api/tour/voice?text=...`` rate-limited 30/min,
liefert audio/mpeg mit Cache-Control 30 Tage. Bei fehlendem
API-Key 503 — Frontend fällt dann auf ``speechSynthesis`` zurück
(Browser-eingebaute Stimme).

Frontend (tour.html):
- ``speak()`` versucht erst Server-Audio (ElevenLabs), bei 503/Fehler
  Fallback auf Web Speech API.
- Session-Cache via Blob-URL: Vor/Zurück-Navigation in der Tour zieht
  nicht jedes Mal eine neue Network-Roundtrip.
- ``stopSpeak()`` stoppt beide Audio-Pfade sauber.

Konfiguration für dev: ``ELEVENLABS_API_KEY`` und (optional)
``ELEVENLABS_VOICE_ID`` in ``/opt/gwoe-antragspruefer-dev/.env`` setzen,
dann Container restart.
2026-05-09 03:17:06 +02:00
Dotty Dotter
e31ee1ad07 feat(tour): Welcome-Banner + Tour auf Startseite, Logo-Klick zur Startseite
Drei zusammenhängende UI-Bausteine:

1) Tour-Engine ist jetzt page-agnostisch — sie liest die Stationen aus
   ``window.GWOE_TOUR_STEPS`` (pro Page hinterlegt), nicht mehr aus einem
   eingebauten Konstanten. Tour-Komponente wird per ``{% include %}``
   eingehängt; das Page-Template definiert vorher seine eigenen Steps.
   Antrag-Detail-Tour wurde entsprechend in das eigene Template gezogen.

2) Startseite (v2/screens/durchsuchen.html): „Du bist neu hier?"-Banner
   oben mit zwei Buttons — „🧭 Tour starten" und „Nein, danke". Banner
   bleibt sichtbar, bis explizit weggeklickt wird (localStorage-Flag),
   oder die Tour gestartet wird. Fünf Stationen für die Startseite:
   Marken-Block, Suche, Score-Filter + Sortierung, Antrags-Liste,
   linke Navigation.

3) Logo-Klick führt jetzt zur Startseite — sowohl in v2/base.html als
   auch in components/appshell.html. ``v2-brand`` und ``v2-brand-sub``
   sind in einen ``<a href="/">`` mit Hover-Highlight gewickelt
   (``.v2-brand-link``).

Phase 2 (ElevenLabs-Voice) ist der nächste Schritt — bisher läuft das
Audio über die Web Speech API.
2026-05-09 02:47:04 +02:00
Dotty Dotter
1c74cb8801 feat(antrag-detail): geführte Tour mit Sprachausgabe (#185 Phase 1)
Schaltfläche „🧭 Tour" in der userrow neben „Merken". Klick öffnet ein
Spotlight-Overlay mit vier Stationen, ermächtigend statt vereinfachend
formuliert:

1. Die Gemeinwohl-Note (was die Zahl 0–10 sagt, was die Empfehlung ist)
2. Die GWÖ-Matrix (5 Werte × 5 Berührungsgruppen, Farbcodierung)
3. Programm-Treue pro Fraktion (Score + Belege)
4. Stimmverhalten + Marker (Heuchelei ⚠ und Opportunismus !)

Audio: Web Speech API (Browser-eingebaute Stimme), de-DE, möglichst
weibliche Stimme. „Stimme an / aus"-Toggle in der Bubble. Bei
ESC oder Klick auf Overlay-Hintergrund: Tour-Ende, Audio stoppt.

Phase 2 (separate Iteration) wird das Audio-Backend gegen ElevenLabs
tauschen — Tour-Skript + UI bleiben gleich, nur ``speak()`` ruft dann
einen Server-Endpoint, der eine vorgenerierte und gecachte MP3 liefert.

Komponente in ``app/templates/v3/components/tour.html``, included am
Ende von antrag_detail.html. CSS inline in der Komponente (1 ``<style>``-
Block, keine ``style=""``-Attribute — Anti-Regression-Wache aus #184
respektiert).
2026-05-09 02:39:01 +02:00