overflow:hidden bleibt 300ms nach loadIncidentDetail aktiv, damit
die verzögerten GridStack resizeTileToContent-Operationen keinen
Scroll zum Faktencheck ausloesen koennen.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Statt den Scroll nach unten mit Timeouts zurueckzukaempfen, wird
overflow:hidden auf main-content gesetzt bevor das Rendering startet.
Nach Abschluss wird scrollTop=0 gesetzt und overflow wiederhergestellt.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Scroll-Reset erfolgt nun an 4 Zeitpunkten um sicherzustellen, dass
der Hauptbereich nach oben scrollt, auch wenn GridStack oder andere
asynchrone Rendering-Operationen den Scroll verschieben.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1. Modal (Anlegen/Bearbeiten) schliesst nur noch ueber den X-Button,
nicht mehr durch Klick auf den dunklen Hintergrund
2. Beim Anklicken einer Lage in der Sidebar scrollt der Hauptbereich
nach oben statt zum Faktencheck-Bereich
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Neue Tabelle user_excluded_domains für benutzerspezifische Ausschlüsse
- Domain-Ausschlüsse wirken nur für den jeweiligen User, nicht org-weit
- user_id wird durch die gesamte Pipeline geschleust (Orchestrator → Researcher → RSS-Parser)
- Grundquellen (is_global) können nicht mehr bearbeitet/gelöscht werden im Frontend
- Grundquelle-Badge bei globalen Quellen statt Edit/Delete-Buttons
- Filter Von mir ausgeschlossen im Quellen-Modal
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- geoparsing.py: Komplett-Rewrite (spaCy NER + Nominatim -> Haiku + geonamescache)
- orchestrator.py: incident_context an geoparse_articles, category in INSERT
- incidents.py: incident_context aus DB laden und an Geoparsing uebergeben
- public_api.py: Locations aggregiert im Lagebild-Endpoint
- components.js: response-Kategorie neben retaliation (beide akzeptiert)
- requirements.txt: spaCy und geopy entfernt
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
parseUTC() hängte blind ein 'Z' (UTC) an alle Timestamps, aber
die DB speichert Lokalzeit (Europe/Berlin). Bei CET (UTC+1) wurden
alle Zeiten 1 Stunde zu spät angezeigt.
Neue Logik: Timestamps mit 'Z' oder '+' werden direkt geparst.
Timestamps ohne Zeitzonen-Info werden als Europe/Berlin interpretiert
mit korrektem Offset (auch bei Sommer-/Winterzeit-Wechsel).
Betrifft: Refresh-Verlauf, Artikel-Zeitstempel, Snapshots, Lagebild-Stand
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Ursache: Server sendete started_at als Lokalzeit (Europe/Berlin),
aber der Client interpretierte es als UTC via parseUTC().
Bei UTC+1 lag die Startzeit dadurch 1 Stunde in der Zukunft.
- orchestrator.py: started_at in WebSocket-Nachrichten als echtes UTC
(ISO 8601 mit Z-Suffix) senden, DB-Timestamps bleiben Lokalzeit
- components.js: elapsed auf min. 0 clampen als Sicherheitsnetz
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Alle toLocaleTimeString/toLocaleDateString-Aufrufe und
getHours/getMinutes-Zugriffe verwenden jetzt fix die
Zeitzone Europe/Berlin statt der Browser-Zeitzone.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Klick auf Email öffnet Dropdown mit Organisation und Lizenzinfo
- Org-Name und Lizenz-Badge nicht mehr direkt sichtbar im Header
- Dropdown schliesst bei Klick ausserhalb
- Barrierefreie ARIA-Attribute
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Frontend-Dateien auf Zustand vor i18n zurückgesetzt.
lang.js entfernt, CSP bereinigt. Backend-Umlaut-Fix bleibt erhalten.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix gray map on EN: always use tile.openstreetmap.de (org has rate limits)
- Add A11yManager._updateLabels() for live language switch of accessibility panel
- Add NotificationCenter._updateLabels() for notification panel translation
- Replace all remaining hardcoded de-DE locales with dynamic locale switch
- Translate sidebar stats, source discovery toasts, session expiry warning
- Translate source form hints, type labels, article progress counter
- Add 15+ new translation keys for missing strings
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add LangManager with 270+ translation keys, anti-flicker lang detection
- Replace all hardcoded German strings in app.js, components.js, dashboard.html, index.html
- Dynamic getter properties for fact-check labels, category badges
- Language-aware map tiles (DE/EN OSM servers), CSP updated for tile.openstreetmap.org
- Lang switcher in header bar and login page
- Locale-aware date formatting, translateApiError for backend messages
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Provides full German/English translation support for the OSINT dashboard
with anti-flicker init, DOM hydration via data-i18n attributes, placeholder
replacement, API error translation, and locale-aware map tile URLs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- tile.openstreetmap.de statt OSM/CartoDB: deutsche Ortsnamen
- Graue Vierecke behoben (Subdomain 'd' existierte nicht bei OSM)
- Gleiche helle Karte in Dark und Light Mode
- CSP img-src auf neuen Tile-Server aktualisiert
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Boulevard als Kategorie in HTML-Dropdowns, JS-Labels und Pydantic-Validierung
- create_source: URL-Duplikat-Prüfung (409 Conflict bei existierender URL)
- create_source + update_source: Domain via _DOMAIN_ALIASES normalisieren
- System-Quellen (auto-entdeckt) sind jetzt von allen Nutzern editierbar
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- {r} (Retina-Platzhalter) wurde nicht ersetzt und blieb literal in URL
- subdomains: 'abcd' explizit fuer CartoDB gesetzt
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Leaflet JS/CSS + MarkerCluster lokal in /static/vendor/ (kein CDN)
- Marker-Images lokal gehostet
- Container-Hoehe wird per JS berechnet falls gridstack 0px liefert
- gridstack karte-Item: display flex auf item-content
- Kein CDN-Abhaengigkeit mehr fuer Kartenfeature
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- map-card: position absolute + inset 0 (zuverlaessig in gridstack)
- map-container: min-height 0 statt 200px (flex-Item braucht das)
- map-empty: position absolute statt flex-basiert
- invalidateSize mit mehreren Retries (100/300/800ms)
- Bounds werden nach invalidateSize erneut gesetzt
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- SRI integrity-Hashes von Leaflet CDN-Links entfernt (verursachen
stille Blockierung wenn Hash nicht passt)
- renderMap() prueft ob L verfuegbar ist und merkt sich Locations
- retryPendingMap() rendert nachtraeglich wenn Leaflet spaeter bereit ist
- 2s Retry-Timer nach init() als Fallback
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Endpunkt startet async Background-Task statt synchron zu warten
- Batch-Verarbeitung (50 Artikel pro Batch)
- Neuer Status-Endpunkt GET /incidents/{id}/geoparse-status
- Frontend pollt alle 3s und zeigt Fortschritt im Button (z.B. "150/427 Artikel...")
- Kein Timeout-Problem mehr bei grossen Lagen
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Neues Geoparsing-Modul (spaCy NER + geonamescache/Nominatim)
- article_locations-Tabelle mit Migration
- Pipeline-Integration nach Artikel-Speicherung
- API-Endpunkt GET /incidents/{id}/locations
- Leaflet.js + MarkerCluster im Dashboard-Grid
- Theme-aware Kartenkacheln (CartoDB dark / OSM light)
- Gold-Akzent MarkerCluster, Popup mit Artikelliste
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Die Toggle-Switches im Lage-Modal (Anlegen/Bearbeiten) waren nicht
mit den API-Endpunkten verbunden. Jetzt werden die Subscription-
Einstellungen korrekt geladen, gespeichert und zurueckgesetzt.
- api.js: getSubscription() und updateSubscription() hinzugefuegt
- app.js: handleFormSubmit() speichert Subscription nach Create/Edit
- app.js: handleEdit() laedt bestehende Subscription beim Oeffnen
- app.js: openModal() setzt Checkboxen im Create-Modus zurueck