Commit graph

92 Commits

Autor SHA1 Nachricht Datum
3a346ba2ec Analysepipeline: Visualisierung der Refresh-Schritte
Neuer Tab "Analysepipeline" zwischen Faktencheck und Quellenuebersicht.
Zeigt 9 Verarbeitungsschritte als n8n-artige Blockkette: Quellen sichten,
Nachrichten sammeln, Doppeltes filtern, Relevanz bewerten, Orte erkennen,
Lagebild verfassen, Fakten pruefen, Qualitaetscheck, Benachrichtigen.

- Backend: refresh_pipeline_steps-Tabelle persistiert pro Refresh+Pass die
  Status- und Zahlen-Werte. pipeline_tracker.py kapselt Start/Done/Skip/Error
  inkl. WebSocket-Broadcast (Event-Typ pipeline_step). 9 Hooks im Orchestrator
  speisen die Anzeige.
- API: GET /api/incidents/{id}/pipeline liefert Definition + letzten Stand
  (Zahlen aus letztem Refresh, Multi-Pass-Konsolidierung).
- Frontend: pipeline.js rendert Vollbild-Blockkette mit pulsierendem Glow am
  aktiven Block, animierten Pfeilen bei Datenfluss, Haekchen am fertigen Block.
  Hover-Tooltip mit Erklaerung in Nutzersprache, Klick oeffnet Detail-Popup.
  Bei Research-Lagen leuchtet ein Schleifen-Pfeil pro Mehrfach-Durchlauf auf.
  Mini-Variante (nur Icons) im Refresh-Progress-Popup.
- CSS: Light/Dark-Theme-fest, dezenter Circuit-Hintergrund (5% Opacity),
  Mobile-vertikale Stapelung unter 900px, prefers-reduced-motion respektiert.
- Uebersprungene Schritte (z.B. Geoparsing ohne neue Artikel) werden
  ausgeblendet, brandneue Lagen ohne Refresh zeigen Hinweis.

Tooltips bewusst in normaler Sprache ohne Internas (keine Modellnamen,
keine Toolnamen, keine Phasen-Labels).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 13:53:44 +02:00
Claude Code
e3fe7fac85 fix(blur): Refresh-Blur stabilisieren und Header mit-blurren
Problem: Beim Anlegen einer neuen Lage verschwand der Blur-Effekt auf dem
Hintergrund-Inhalt sobald das Browserfenster in der Groesse veraendert wurde.
Zudem blieb der Lagen-Titel im Header offen sichtbar, waehrend der Inhalt
darunter geblurrt war — der wechselnde Titel war also klar lesbar.

Ursache:
- Blur lag auf .tab-panels und parallel auf .tab-panel — zwei verschachtelte
  Composite-Layer, die bei jedem Reflow neu berechnet werden.
- transition: filter 0.4s ease auf .tab-panel — bei Resize lief die Transition
  oft rueckwaerts oder pausierte, was den Blur visuell verschwinden liess.
- .incident-header-strip lag ausserhalb von .tab-panels und war dadurch nie
  geblurrt (Titel/Aktionen/Beschreibung blieben offen sichtbar).

Aenderungen:
- Blur-Anker hochgezogen auf #incident-view (Klasse refresh-blurred), so dass
  Header und Tab-Panels gemeinsam unscharf werden.
- Nur noch eine Filter-Ebene (filter: blur(8px)).
- Transition entfernt — Blur soll schlagartig kommen und gehen, kein
  lesbarer Zwischenzustand beim Reflow.
- will-change: filter; transform: translateZ(0); — erzwingt einen persistenten
  GPU-Composite-Layer, der bei Window-Resize stabil bleibt.

Headless-Tests bestaetigen: alte Variante 89.8% Pixel-Stabilitaet ueber 6
Resize-Zyklen mit Content-Mutation, neue Variante 97.0% (Rest = Content-Diff).
2026-04-30 22:40:51 +00:00
Claude Code
059395393c Fix: rAF-Sicherheitsnetz fuer Blur zentral in _showPopupProgress
Vorheriger Fix in selectIncident griff nicht beim handleRefresh-Pfad
(manueller Aktualisieren-Klick), weil dieser direkt UI.showProgress aufruft
ohne selectIncident zu durchlaufen. Damit blieb eine Lage, deren erster
Refresh per Klick angestossen wurde, unblurred.

rAF mit add("blurred") jetzt direkt in _showPopupProgress (components.js),
sobald state.isFirst gesetzt ist. Damit greift der Blur in jedem Pfad, der
durch _showPopupProgress laeuft — selectIncident, handleRefresh,
handleStatusUpdate (WebSocket), Initial-Restore.

Der zentrale rAF in selectIncident ist redundant und wieder entfernt.
Der _willReBlur-Skip von remove("blurred") in selectIncident bleibt
erhalten — verhindert ueberfluessiges remove+add im selben Tick.

cache-bust components.js auf v=20260427a, app.js auf v=20260427c.
2026-04-27 20:52:39 +00:00
Claude Code
14d1062583 Fix: Blur greift bei jedem ersten Durchlauf der ausgewaehlten Lage
Vorheriger Patch hatte den rAF nur im Create-Flow gesetzt. Damit funktionierte
zwar das Anlegen, aber das Auswaehlen einer existierenden Lage, deren erste
Recherche gerade laeuft (oder nach einem manuellen ersten Refresh), blieb
unblurred.

Loesung: rAF mit add("blurred") jetzt zentral in selectIncident, sobald der
Progress-State isFirst=true und nicht minimiert ist. Damit greift der Blur
in allen Pfaden (Anlegen, manueller Refresh, Auswahl einer laufenden Lage,
Wechsel zwischen Faellen, Initial-Load via savedId).

Der zusaetzliche rAF in createIncident von 2ee90a4 ist damit redundant und
wieder entfernt — der zentrale Hook in selectIncident deckt den Fall mit ab.

cache-bust app.js auf v=20260427b.
2026-04-27 19:43:18 +00:00
Claude Code
2ee90a4b3b Fix: Blur greift sofort beim Anlegen einer neuen Lage
Im Create-Flow wurde .blurred in selectIncident() erst entfernt und gleich
darauf via _showPopupProgress wieder gesetzt. CSS filter:blur greift in der
Kombination (frischer isFirst-State + selectIncident im selben Tick + viel
vorausgehende DOM-Manipulation durch Modal-Close + renderSidebar) nicht
zuverlaessig im selben Frame — der Fall war bis zum Wegklicken/Zurueckklicken
unblurred.

selectIncident: remove("blurred") wird uebersprungen, wenn der zustaendige
Progress-State isFirst=true und nicht minimiert ist (Blur soll bestehen
bleiben statt remove+add im selben Tick).

createIncident: zusaetzlich requestAnimationFrame mit grid.classList.add im
naechsten Frame, falls der Browser den ersten add-Aufruf in selectIncident
nicht visuell uebernommen hat. Doppeltes Setzen ist idempotent.

dashboard.html: cache-bust app.js auf v=20260427a.
2026-04-27 19:29:00 +00:00
claude-dev
5d5ec7c924 Block B: ClaudeCliError + differenzierte HTTP-Status + Rate-Limit-Retry
- Neue Exception-Klasse ClaudeCliError(error_type, message) in claude_client.py
  mit Kategorien rate_limit / auth_error / timeout / cli_error.
- _classify_cli_error() als geteilter Klassifikator (Keywords fuer Rate-Limit
  und Auth-Fehler wie "does not have access", "login again").
- call_claude() erkennt jetzt auch is_error=true im JSON bei returncode=0
  (Hauptursache des Ausfalls vom 22.04.: CLI liefert "Your organization
  does not have access" mit is_error=true statt Exit-Code).
- Orchestrator: ClaudeCliError mit rate_limit/timeout als transient behandelt
  (3 Retries mit Backoff 0s/120s/300s). auth_error/cli_error brechen sofort
  ab ohne Retry. Behebt den bestehenden Bug, dass Rate-Limit-Fehler gar nicht
  retried wurden.
- routers/incidents.py Enhance-Endpoint: ClaudeCliError wird auf
  503 (auth_error) / 429 (rate_limit) gemappt, TimeoutError auf 504.
- routers/chat.py _call_claude_chat(): wirft jetzt ClaudeCliError statt
  generischem RuntimeError. Chat-Endpoint mappt auth_error auf 503.
- Frontend: neue ApiError-Klasse in api.js mit status+detail.
  generateDescription() in app.js zeigt differenzierte Toasts nach
  HTTP-Status (503/429/504/403).
- dashboard.html: Cache-Bust api.js + app.js auf v=20260423a
2026-04-23 17:54:13 +00:00
claude-dev
efae707fa9 Fix: Blur + Aktions-Lock beim Anlegen eines Falls sofort aktiv
Beim Create-Flow wurde selectIncident() aufgerufen, BEVOR der Fall
als refreshend markiert wurde. Dadurch entfernte selectIncident den
'.blurred'-Zustand des Tab-Containers und rief _lockActionsIfFirst(false)
auf — der Fallinhalt war zwischen Oeffnen und Eintreffen der ersten
WebSocket-Statusnachricht kurzzeitig klickbar und unblurred.

Jetzt wird der Refresh-Status und ein Initial-State mit isFirst=true
schon VOR selectIncident gesetzt. selectIncident erkennt isRefreshing
und ruft _showPopupProgress + _lockActionsIfFirst(true) mit dem
bestehenden State auf — Blur und Lock greifen sofort.
2026-04-21 14:02:52 +00:00
0d6ad8ea90 Incident-Response: sources_json nur noch via Lazy-Endpunkt, Sidebar schlank
Backend:
- IncidentResponse: sources_json-Feld entfernt (Detail-GET liefert es
  nicht mehr mit).
- Neues Schema IncidentListItem fuer GET /incidents (Sidebar):
  Ohne summary, ohne sources_json. Ein has_summary-Bit fuer
  Erster-Refresh-Erkennung, description bleibt fuer das Edit-Modal.
- list_incidents selektiert nur die noetigen Spalten (kein SELECT *)
  — spart bei grossen Lagen Speicher + Serialisierung.
- Neuer Endpunkt GET /incidents/{id}/sources liefert geparstes
  Sources-Array fuer Zitate-Lookups (Lazy).

Frontend:
- api.js: getIncidentSources(id).
- app.js: loadIncidentDetail laedt /sources parallel, speichert Array
  in _currentSources. Alle renderSummary/Zusammenfassung/
  LatestDevelopments-Aufrufe bekommen jetzt _currentSources statt
  incident.sources_json. inc.summary-Checks -> inc.has_summary.
- components.js: _parseSources(input) akzeptiert Array ODER String
  (Rueckwaertskompatibilitaet). renderZusammenfassung, renderSummary,
  renderLatestDevelopments nutzen den Helper.

Hintergrund: Die Sidebar-Liste lieferte bei 17 Lagen 1,23 MB
(Iran allein 386 KB wegen sources_json + summary). Detail-Endpunkt
lieferte sources_json (324 KB bei Iran) bei jedem Oeffnen mit.
Beides jetzt radikal kleiner — die 324 KB Sources gibt's nur
einmalig auf Anfrage.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 00:07:46 +02:00
9a43dffa6c Articles: Paginierung, Timeline-Buckets, Sources-Summary-Endpunkt
Backend:
- GET /{id}/articles paginiert jetzt per limit/offset (Default 500,
  Max 1000) und unterstuetzt optionalen search-Parameter (LIKE ueber
  headline/source/content). Response-Shape: {total, articles}.
- Neuer Endpunkt GET /{id}/articles/sources-summary liefert pro Quelle
  {source, article_count, languages} sowie language_counts gesamt —
  serverseitige Aggregation, unabhaengig von Artikel-Paginierung.
- Neuer Endpunkt GET /{id}/articles/timeline-buckets?granularity=hour|day|week|month
  aggregiert Artikel + Snapshot-Counts pro Zeitbucket (fuer spaetere
  Timeline-Zaehler ueber die volle Historie).
- database.py: Index idx_articles_incident_collected auf
  (incident_id, collected_at DESC) fuer schnelleres ORDER BY + Pagination.

Frontend:
- api.js: getArticles({limit, offset, search}),
  getArticlesSourcesSummary(), getArticlesTimelineBuckets().
- app.js: loadIncidentDetail laedt erste Seite (500 Artikel), startet
  _loadSourcesSummary parallel und zieht restliche Artikel
  batchweise (500er Bloecke) im Hintergrund nach, bis _currentArticlesTotal
  erreicht ist. rerenderTimeline nach jedem Batch.
- components.js: renderSourceOverviewFromSummary(data) rendert aus
  Aggregat-Daten (ersetzt clientseitige Zaehlung ueber geladene Artikel).

Hintergrund: /articles lieferte bei der Iran-Lage 22 MB (17.286 Artikel
mit SELECT *). Die Erstantwort sinkt auf ~650 KB (500 Artikel), weitere
werden progressiv im Hintergrund nachgeladen. Quellenuebersicht zeigt
dank Aggregat-Endpunkt sofort alle Quellen + Sprachen komplett.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 23:46:40 +02:00
194790899c Snapshots: Liste ohne Volltext, Lazy-Load + serverseitige Suche
Backend:
- GET /{id}/snapshots liefert nur noch schlanke Shape (Metadaten +
  SUBSTR(summary,1,300) AS summary_preview), kein Volltext, kein sources_json.
- Neuer Endpunkt GET /{id}/snapshots/{snapshot_id} fuer Volltext-Lazy-Load.
- Neuer Endpunkt GET /{id}/snapshots/search?q=... fuer serverseitige
  Volltextsuche ueber alle Snapshots einer Lage.

Frontend:
- api.js: getSnapshot() und searchSnapshots() ergaenzt.
- app.js: _snapshotFullCache, Volltext wird beim Aufklappen eines
  Snapshot-Eintrags per lazyLoadSnapshotDetail() nachgeladen und gecacht.
- Suche ueber Snapshots filtert weiterhin clientseitig ueber summary_preview.

Hintergrund: Bei grossen Lagen (Iran-Lage: 347 Snapshots) fiel die
Snapshots-Listenantwort mit Volltext-Summaries auf ~54 MB. Die Liste
faellt damit auf ~150 KB; Volltexte werden nur on-demand geladen.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 23:42:08 +02:00
claude-dev
e15ed0c21e Dashboard: GridStack durch Tab-Navigation ersetzen
Der Monitor-Dashboard zeigte bisher alle sechs Kacheln gleichzeitig in
einem GridStack-Layout (Drag/Resize, je Kachel eigenes Scrolling). Nutzer-
wunsch: Analog zur Lagebild-Seite nur ein Tab-Panel gleichzeitig, maximiert
auf volle Breite, Seiten-Scroll statt interne Scrollbars.

Aenderungen:
- dashboard.html: Layout-Toolbar + grid-stack-Wrapper entfernt; neue tab-nav
  mit 6 Buttons + tab-panels mit 6 Panels. GridStack CDN-Links raus.
- layout.js: GridStack-Init/toggleTile/reset komplett entfernt. Neu:
  switchTab(tabId) + restoreTabFor(incidentId) mit localStorage-Persistenz
  pro Lage osint_tab_id. applyTypeLabels fuer adhoc vs. research. Legacy-
  Methoden sind No-Op-Stubs.
- app.js: renderIncidentDetail ruft LayoutManager.restoreTabFor und
  applyTypeLabels auf. openContentModal-Trigger aus Card-Titeln raus.
  Tile-Resize-Bloecke fuer Quellen und Timeline entfernt.
- components.js: Telegram-Pills bekommen Suffix Telegram-Link, wenn die
  URL auf t.me verweist.
- style.css: grid-stack/layout-toggle Klassen raus; neue tab-nav/tab-btn/
  tab-panel Klassen. Internes Scrolling entfernt. map-container 600px.

Alte osint_layout-Eintraege werden ignoriert.
2026-04-18 22:34:36 +00:00
claude-dev
2ae8b9a341 Live-Monitoring: Neueste Entwicklungen als Karten mit Quellen-Pills
Der Bullet-Render fuer Live-Monitoring (adhoc) zeigt nun pro Eintrag eine
Karte mit klickbaren Quellen-Pills (Quellname statt nur [N]) im Header und
dezentem Zeitstempel rechts oben. Der Ereignistext steht darunter ohne
Inline-Citations. Bias-Markierung (pro-RU, staatsnah) als kleines Suffix.

Recherchen behalten den bisherigen renderZusammenfassung-Render unveraendert.
2026-04-18 19:53:21 +00:00
claude-dev
d6c541cb95 Neueste Entwicklungen: Kachel fuer adhoc-Lagen
- DB-Migration: Spalte latest_developments (TEXT) in incidents
- Analyzer: neuer Prompt LATEST_DEVELOPMENTS_PROMPT_TEMPLATE und
  Methode generate_latest_developments() liefert chronologische
  Bullet-Liste (max. 8, neueste oben, Zeitstempel DD.MM. HH:MM)
- Orchestrator: nach Analyse+Faktencheck ein Extra-Schritt nur fuer
  incident_type=adhoc, der die neue Kachel fortschreibt
- Analyzer-Prompts (Erst- und inkrementell): erzeugen KEINE
  Zusammenfassung-Sektion mehr im Lagebild (vermeidet Duplikat mit
  der neuen Kachel)
- models.IncidentResponse um latest_developments erweitert
- Frontend: Rendering der Kachel in app.js
2026-04-18 11:47:10 +00:00
claude-dev
acfc74ffe7 Standard-Opus auf claude-opus-4-7 festlegen (statt CLI-Default) 2026-04-16 22:19:26 +00:00
claude-dev
509165484e Zusammenfassung-Kachel: Quellenverweise als klickbare Links
renderZusammenfassung bekommt jetzt sourcesJson und rendert
[1], [2] etc. als klickbare Links -- identisch zu renderSummary.
2026-04-11 22:34:04 +00:00
claude-dev
c59ba4f4af Zusammenfassung als eigene Dashboard-Kachel
Research-Lagen: ZUSAMMENFASSUNG-Sektion wird aus dem Bericht
extrahiert und in eigener Kachel oberhalb des Recherchberichts
angezeigt. Der Recherchebericht zeigt den Rest ohne Dopplung.

- Neue Kachel mit gs-id="zusammenfassung" im GridStack
- Toggle-Button in der Layout-Leiste
- extractZusammenfassung() und renderZusammenfassung() in UI
- Adhoc/Live-Lagen: Kachel wird automatisch ausgeblendet
- Export nutzt weiterhin _extract_zusammenfassung() aus dem Backend
2026-04-11 21:12:28 +00:00
claude-dev
fa12d4cfd6 Export: Zusammenfassung-Sektion, Checkbox-Auswahl, neue Reihenfolge
Research-Briefings:
- Neue Sektion ZUSAMMENFASSUNG mit Bullet-Points als erstes Element
- UEBERBLICK entfernt, durch ZUSAMMENFASSUNG ersetzt
- Inkrementelles Briefing ebenfalls angepasst

Export-System:
- Zusammenfassung wird direkt aus dem Bericht extrahiert (kein
  separater KI-Aufruf mehr fuer Research-Lagen)
- Reihenfolge: Zusammenfassung > Recherchebericht > Faktencheck > Quellen > Timeline
- Sections-basiert statt scope-basiert (rueckwaertskompatibel)
- Checkbox-Dialog statt Radio-Buttons im Frontend
- Bereiche: Zusammenfassung, Recherchebericht, Faktencheck, Quellen, Timeline, Karte
- PDF und DOCX Templates angepasst
- Backend akzeptiert sections-Parameter (kommagetrennt)
2026-04-11 20:56:04 +00:00
claude-dev
89cc920bdc Warteschlange: Positionen nach Cancel/Error/Complete neu nummerieren
Wenn ein Fall aus der Queue entfernt wird (Cancel, Fehler, Abschluss),
bleiben die #-Nummern der verbleibenden Eintraege jetzt nicht mehr
stecken. _reindexQueuePositions() sortiert nach alter Position und
nummeriert sequentiell neu (#1, #2, ...).

Aufgerufen in: handleRefreshCancelled, handleRefreshError,
handleRefreshComplete.
2026-04-11 19:50:59 +00:00
claude-dev
f2469093ee Revert "Feature: Analyse-Anweisungen (Direktiven) fuer Tabellen und Zusammenfassung"
This reverts commit e0bcd85d90.
2026-04-10 19:34:25 +00:00
claude-dev
e0bcd85d90 Feature: Analyse-Anweisungen (Direktiven) fuer Tabellen und Zusammenfassung
Nutzer koennen per Klick auf Chips Anweisungen zur Beschreibung
hinzufuegen: Zusammenfassung, Vergleichstabelle, Zeitverlauf,
Pro/Contra oder eigene Tabellen. Format: [TABELLE: ...] und
[ZUSAMMENFASSUNG]. Mehrere Anweisungen moeglich. Analyzer-Prompts
beachten diese Anweisungen verbindlich. Beschreibung-generieren
bewahrt bestehende Direktiven.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 18:37:04 +00:00
Claude Dev
9aa80b4aec Lagenwechsel: Popup/Mini-Status pro Lage korrekt wiederherstellen
Beim Zurueckwechseln auf eine laufende Lage wird der gespeicherte
State (minimized/offen) direkt aus _progressState wiederhergestellt.
War das Popup offen -> offen. War es minimiert -> Mini-Bar.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 20:57:51 +02:00
Claude Dev
fb0c47eee4 Fix: Abbrechen-Dialog, Overlay-Stacking, Queue-Cancel
1. Confirm-Dialog z-index ueber Progress-Popup (10000 > 9000)
2. Progress-Popup wird ausgeblendet waehrend Confirm-Dialog offen
3. Kein dunkler-werdendes Overlay bei mehrfachem Abbrechen-Klick
4. Abbrechen funktioniert jetzt auch fuer Lagen in der Warteschlange
   (werden direkt aus der Queue entfernt statt auf Start zu warten)
5. Cancel-Status wird im Popup-Titel angezeigt

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 20:50:30 +02:00
Claude Dev
990ece1346 Fix: Sidebar-Status bei Fehler und Abbruch korrekt aufraumen
handleRefreshError und handleRefreshCancelled haben den Sidebar-
Refresh-Status (Gold-Rand, Spinner-Text) nicht entfernt. Dadurch
blieben Lagen faeelschlicherweise als laufend markiert.

Jetzt wird bei Error/Cancel: _removeSidebarRefreshStatus() aufgerufen,
_progressState geloescht, und Sidebar neu gerendert.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 20:48:24 +02:00
Claude Dev
3811229ad9 Ctrl+Shift+R: Refresh-Status korrekt wiederherstellen
API /incidents/refreshing gibt jetzt auch queued IDs mit Position
und den aktuell laufenden Task zurueck.

Frontend nutzt started_at aus der API fuer Timer-Wiederherstellung.
Queued Lagen werden mit korrekter Position wiederhergestellt.
Aktiv laufender Task wird als researching angezeigt statt queued.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 20:40:33 +02:00
Claude Dev
762d8dbc1a Sidebar: Refresh-Status fuer ALLE Lagen korrekt anzeigen
Progress-State wird jetzt fuer alle refreshenden Lagen angelegt,
nicht nur fuer die aktuell ausgewaehlte. Sidebar-Update passiert
vor dem Early-Return fuer nicht-aktuelle Lagen.

Bei WebSocket-Reconnect (auch nach Ctrl+Shift+R) wird der State
fuer bereits laufende Refreshes korrekt wiederhergestellt.

Sidebar-Cleanup bei Refresh-Abschluss fuer alle Lagen.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 20:36:16 +02:00
Claude Dev
244cc56bde Sidebar: Refresh-Status direkt im HTML gerendert statt dynamisch
renderIncidentItem() baut den Refresh-Status (Gold-Rand, Spinner,
Statustext, Warteschlange-Position) direkt ins HTML ein. Ueberlebt
jetzt renderSidebar()-Aufrufe bei Lagenwechsel und Aktualisierungen.

Sidebar wird nach jedem WebSocket-Status-Update neu gerendert,
damit der Status fuer ALLE Lagen immer sichtbar bleibt.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 20:32:37 +02:00
Claude Dev
97ecde87c2 Fortschritt: Auto-Minimize, Action-Lock, Queue-Anzeige in Sidebar
1. Aktualisierungen starten minimiert (Mini-Bar), Popup nur per Klick.
   Verhindert Ueberlagerung von Bearbeiten/Export-Buttons.
2. Erster Durchlauf: Bearbeiten/Export/Archivieren/Loeschen gesperrt,
   nur Abbrechen moeglich.
3. Sidebar: Warteschlange-Lagen zeigen Position (#1, #2...) mit
   eigenem visuellen Stil (gedimmt, pulsierender Dot).
4. Sidebar-Status (Recherchiert/Analysiert/Faktencheck) wird fuer
   ALLE laufenden Lagen angezeigt, nicht nur die aktuelle.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 20:21:52 +02:00
Claude Dev
3f88d00b8c Fortschrittsanzeige: Popup mit Checkboxen, Blur, Pro-Lage-Timer
Ladebalken ersetzt durch zentriertes Popup-Fenster mit Checkbox-Checkliste
(Warteschlange, Recherche, Analyse, Faktencheck) und Echtzeit-Timer.

Erster Durchlauf: Popup nicht wegklickbar, Blur-Effekt auf Kacheln.
Aktualisierung: Popup minimierbar zu kompakter Status-Leiste.
Timer laeuft pro Lage im Hintergrund weiter bei Lagenwechsel.
Gesamtzeit wird am Ende im Abschluss-Popup angezeigt.

Sidebar: Animierter Gold-Rand und Fortschrittstext (Recherchiert/
Analysiert/Faktencheck) unter dem Lage-Namen bei laufendem Refresh.

Zusaetzlicher Cancel-Checkpoint im Orchestrator nach Uebersetzung.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 20:08:59 +02:00
Claude Dev
678b72e7ff fix: Dropdown bleibt offen beim Klick auf Org-Switcher
stopPropagation auf dem Dropdown-Container verhindert, dass der
globale Click-Listener das Menue schliesst wenn man den Org-Switcher
bedient.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 22:35:43 +02:00
Claude Dev
c22ae854fe feat: Global-Admin Org-Switcher fuer info@aegis-sight.de
Ermoeglicht dem Global Admin (is_global_admin Flag) zwischen
Organisationen zu wechseln. Neue Endpoints: GET /api/auth/organizations,
POST /api/auth/switch-org. Org-Dropdown im Header-Menue, nur fuer
Global Admin sichtbar. Komplett herausnehmbar (Flag + Code-Bloecke).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 22:25:41 +02:00
Claude Dev
d3e8c0adc7 feat: Slot-basierter Auto-Refresh mit konfigurierbarer Startzeit
Auto-Refresh nutzt jetzt eine feste Anker-Uhrzeit (refresh_start_time) statt
reinem Intervall-basiertem Driften. Verpasste Slots werden max. 1x aufgeholt.
Bestehendes Intervall-Verhalten bleibt als Fallback erhalten (ohne Startzeit).

Migration: Bestehende Auto-Lagen erhalten 07:00 als Startzeit.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 13:14:34 +02:00
Claude Dev
cb851ee72d fix: Textarea-Höhe beim Öffnen von Neuer Fall zurücksetzen 2026-03-28 00:58:14 +01:00
Claude Dev
34a173b27b fix: Textarea Auto-Resize + Emdashes entfernt
Beschreibungs-Textarea waechst automatisch mit dem Inhalt (min 80px).
Greift beim Tippen, nach Beschreibung generieren und im Edit-Modus.
Emdashes (U+2014) durch Doppelpunkte ersetzt.
2026-03-28 00:51:02 +01:00
Claude Dev
779678fbcb fix: Beschreibung generieren Button korrekt enabled/disabled
Button wird beim Bearbeiten einer Lage korrekt aktiviert (Titel per
JS gesetzt loest kein input-Event aus). Im Create-Modus explizit
disabled nach form.reset().
2026-03-28 00:39:01 +01:00
Claude Dev
0780901b61 fix: Button zeigt Wird generiert... statt nur Spinner 2026-03-27 23:58:14 +01:00
Claude Dev
ca2059aca0 fix: Beschreibungs-Hinweis als Info-Icon Tooltip statt form-hint
Hinweistext zur guten Beschreibung erscheint jetzt als Tooltip am
i-Icon neben dem Label, konsistent mit allen anderen Formularfeldern.
Tooltip-Text wechselt weiterhin je nach Typ (Live/Recherche).
2026-03-27 23:50:09 +01:00
Claude Dev
11d0aadc57 fix: Beschreibung generieren — AbortController, Readonly, Gold-Styling
- Textarea readonly + visuell gedimmt während Generierung läuft
- AbortController bricht Request ab wenn Modal geschlossen wird
- Stern-Icon entfernt, Button-Text in Gold (Akzentfarbe)
- api.js _request() unterstützt externen AbortSignal
2026-03-27 23:46:44 +01:00
Claude Dev
6913c1e683 feat: Beschreibung generieren Button im Neuer-Fall-Modal
KI-gestütztes Prompt Enhancement: Button generiert per Haiku aus dem
Titel eine strukturierte Beschreibung. Unterscheidet zwischen
Live-Monitoring (kompakte Vorfallsbeschreibung) und Recherche
(strukturiertes Briefing mit Schwerpunkten und Suchbegriffen).

- Neuer Endpoint POST /api/incidents/enhance-description
- Button erscheint für beide Lage-Typen, aktiv ab 3 Zeichen Titel
- Info-Hinweis wechselt je nach Typ mit Beispiel
- Spinner-Animation während der Generierung
2026-03-27 23:31:05 +01:00
Claude Dev
a5ef9bbfbf fix: Refresh-Button zeigt Warteschlangen-Status statt Fehlermeldung
Bei Klick auf Aktualisieren bleibt der Progress-Indikator aktiv,
auch wenn die Recherche in der Warteschlange landet. Statt einer
Warning-Meldung wird eine Info-Meldung angezeigt. Erneutes Klicken
bestaetigt, dass die Aktualisierung bereits in Bearbeitung ist.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 22:13:01 +01:00
Claude Dev
d0f99f4e5b Export: Klassifizierung (offen/dienstgebrauch/vertraulich) komplett entfernt 2026-03-25 23:50:57 +01:00
Claude Dev
93948cbc4c Fix: Verwaiste _pdfLabel Referenz entfernt 2026-03-25 01:34:00 +01:00
Claude Dev
f7deafd14a Export-System: PDF/Word mit Executive Summary, Deckblatt, Klassifizierung
- Neuer report_generator.py: WeasyPrint (PDF) + python-docx (Word)
- 3 Stufen: Executive Summary (KI-generiert), Lagebericht, Vollständiger Bericht
- 3 Klassifizierungsstufen: Offen, Nur für den Dienstgebrauch, Vertraulich
- Deckblatt mit AegisSight Logo, Titel, Typ, Klassifizierung
- Executive Summary: Claude Haiku verdichtet Lagebild auf 3-5 Kernpunkte
- Jinja2 HTML-Template für PDF (A4-optimiert)
- Alte Exporte entfernt (Markdown, JSON, Browser-Print)
- Neues Export-Modal im Dashboard (Umfang/Format/Stufe)
2026-03-25 01:28:47 +01:00
Claude Dev
138fdd8594 Cleanup: Alle Netzwerkanalyse-Reste vollständig entfernt
- 7 JS/CSS-Dateien gelöscht (api_network, app_network, network-graph, network-cluster, cluster-data, network.css, network-cluster.css)
- 2 Backend-Dateien gelöscht (routers/network_analysis.py, models_network.py)
- dashboard.html: Modal Neue Netzwerkanalyse entfernt
- app.js: 15 Netzwerk-Referenzen + kaputte Blöcke bereinigt
- DB-Schema CREATE TABLEs bleiben (geteilte DB mit Netzwerkanalyse-App)
2026-03-25 01:00:03 +01:00
Claude Dev
d274ec237b Fix: Fehler beim Laden wenn Kacheln ausgeblendet sind
_applyLayout entfernte Widgets ohne die Card-Elemente vorher zu parken.
Beim Wiederherstellen eines Layouts mit versteckten Kacheln (z.B. Timeline)
gingen die DOM-Elemente verloren, was zu null-Referenz-Fehlern fuehrte.

Fixes:
- layout.js: Cards in tile-parking retten bevor Widget entfernt wird
- app.js: Null-Guards in rerenderTimeline und _updateTimelineCount
2026-03-24 07:34:56 +01:00
Claude Dev
c7d7bbbb18 Kachel-Label dynamisch: Recherchebericht bei Recherche-Lagen, Lagebild bei Live-Monitoring
Betrifft: Card-Title, Layout-Toggle, PDF-Export, Benachrichtigungs-Toggle.
Bei Typ research wird ueberall Recherchebericht angezeigt statt Lagebild.
2026-03-24 07:29:14 +01:00
Claude Dev
17088e588f fix: Credits-Dropdown linksbündig, Balken-Track sichtbar, Prozentzahl rechts, kein Fettdruck, mehr Abstand 2026-03-18 00:08:20 +01:00
Claude Dev
7bfa1d29cf feat: Credits-System mit Verbrauchsanzeige im User-Dropdown
- DB-Migration: credits_total/credits_used/cost_per_credit auf licenses, token_usage_monthly Tabelle
- Orchestrator: Monatliche Token-Aggregation + Credits-Abzug nach Refresh
- Auth: Credits-Daten im /me Endpoint + Bugfix fehlende Klammer in get()
- Frontend: Credits-Balken im User-Dropdown mit Farbwechsel

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 23:53:19 +01:00
Claude Dev
4b9ed6439a fix: PDF-Export verbessert - Seitenraender, kein Abschneiden, klickbare Links
- @page margins 18mm/15mm fuer korrekte Seitenraender
- Header kompakt: Titel + Lagebild direkt auf Seite 1 (keine leere Seite)
- Citations/Quellenverweise als klickbare unterstrichene Links im PDF
- break-inside:avoid statt page-break-inside fuer korrekte Seitenumbrueche
- Kartenexport entfernt (nicht sinnvoll als PDF)
- Schriftgroessen leicht reduziert fuer bessere Platznutzung
2026-03-17 10:34:38 +01:00
Claude Dev
0b3fbb1efc feat: PDF-Export mit Kachel-Auswahl und hellem Drucklayout
- Neuer PDF-Export-Dialog mit Checkboxen: Lagebild, Quellen, Faktencheck, Karte, Timeline
- Helles, schlichtes Drucklayout (weiss, Serifenlos, A4-optimiert)
- Oeffnet neues Fenster mit sauberem HTML fuer Drucken/PDF-Speichern
- Ersetzt alte window.print() Funktion die das dunkle Theme exportierte
- Quellenübersicht als Tabelle + Artikelliste mit Links
- Faktencheck mit farbcodierten Status-Badges
2026-03-17 10:29:01 +01:00
Claude Dev
742f49467e fix: saveSource() liest source_type wieder aus _discoveredData statt Select
Stellt das Original-Verhalten wieder her: Der Typ wird aus den
Auto-Discovery-Daten gelesen, nicht aus dem versteckten Select-Element.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 23:55:42 +01:00