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>
Dieser Commit ist enthalten in:
2026-04-20 00:07:46 +02:00
Ursprung a302790777
Commit 0d6ad8ea90
5 geänderte Dateien mit 118 neuen und 22 gelöschten Zeilen

Datei anzeigen

@@ -78,6 +78,11 @@ class DescriptionEnhanceRequest(BaseModel):
class IncidentResponse(BaseModel):
"""Vollstaendige Lage-Details (fuer GET /incidents/{id}).
Enthaelt summary + latest_developments, aber NICHT mehr sources_json —
das wird separat per GET /incidents/{id}/sources geladen (Lazy-Load).
"""
id: int
title: str
description: Optional[str]
@@ -90,7 +95,6 @@ class IncidentResponse(BaseModel):
visibility: str = "public"
summary: Optional[str]
latest_developments: Optional[str] = None
sources_json: Optional[str] = None
international_sources: bool = True
include_telegram: bool = False
created_by: int
@@ -101,6 +105,35 @@ class IncidentResponse(BaseModel):
source_count: int = 0
class IncidentListItem(BaseModel):
"""Schlankes Sidebar-Item (fuer GET /incidents).
Enthaelt, was Sidebar und Edit-Dialog brauchen — kein summary,
kein sources_json. Statt summary-Volltext ein ``has_summary``-Bit,
damit das Frontend "erster Refresh"-Zustand erkennen kann.
description bleibt drin (kurz, vom Edit-Modal direkt genutzt).
"""
id: int
title: str
description: Optional[str] = None
type: str
status: str
refresh_mode: str
refresh_interval: int
refresh_start_time: Optional[str] = None
retention_days: int
visibility: str = "public"
international_sources: bool = True
include_telegram: bool = False
created_by: int
created_by_username: str = ""
created_at: str
updated_at: str
article_count: int = 0
source_count: int = 0
has_summary: bool = False
# Sources (Quellenverwaltung)