feat(public-mood): Stimmungs-Kachel aus Foren-Quellen
Eigene Pipeline-Stufe nach factcheck, vor summary, die Foren-Artikel (media_type='forum') zu einer Themen-Zusammenfassung verarbeitet. Wird als separate Dashboard-Kachel "Öffentliche Stimmung" angezeigt — getrennt von Lagebild und Faktencheck, damit anonyme Forenposts nicht mit belegter Faktenlage verwechselt werden. - DB-Migration: incidents.public_mood (TEXT) + public_mood_updated_at (TS). - pipeline_tracker: neuer Pipeline-Step "public_mood" (DE/EN-Labels). - analyzer.generate_public_mood: Haiku-Call der Foren-Beitraege pro Quelle gruppiert und 3-6 thematische Bullets erzeugt, mit expliziter Quellen- Herkunft pro Bullet. Bei zu duennem Material gibt's keinen Output. - orchestrator: neuer Schritt zwischen Factcheck und Summary. Laedt alle Foren-Artikel der Lage (via JOIN auf sources), uebergibt sie an den Stimmungs-Agent, speichert den Markdown-Text in incidents.public_mood. - Topic-Filter (analyzer.filter_relevant_articles) markiert Foren-Quellen mit [FORUM]-Tag und bekommt im Prompt die Regel, Foren-Artikel weicher zu bewerten (Lage-Keyword im Titel reicht). Sie sollen in der Stimmungs- Kachel landen, nicht voreilig verworfen werden. - IncidentResponse-Modell: public_mood/public_mood_updated_at ergaenzt. - Frontend: neuer Tab "Öffentliche Stimmung" (nur sichtbar wenn Inhalt da), eigene Kachel mit Warn-Hinweis "keine Faktenlage". UI.renderPublicMood als einfacher Bullet-Renderer. - dashboard.html Cache-Buster fuer components.js + app.js gebumpt. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Dieser Commit ist enthalten in:
@@ -1131,6 +1131,26 @@ const App = {
|
||||
: '';
|
||||
}
|
||||
|
||||
// Öffentliche Stimmung (Foren-Kachel): Tab + Inhalt nur einblenden,
|
||||
// wenn fuer diese Lage tatsaechlich Stimmungs-Text vorhanden ist.
|
||||
const stimmungTabBtn = document.getElementById('tab-btn-stimmung');
|
||||
const stimmungText = document.getElementById('stimmung-text');
|
||||
const stimmungTs = document.getElementById('stimmung-timestamp');
|
||||
const moodText = (incident.public_mood || '').trim();
|
||||
if (moodText && stimmungTabBtn) {
|
||||
stimmungTabBtn.style.display = '';
|
||||
if (stimmungText) stimmungText.innerHTML = UI.renderPublicMood(moodText);
|
||||
if (stimmungTs && incident.public_mood_updated_at) {
|
||||
const mUpd = parseUTC(incident.public_mood_updated_at);
|
||||
if (mUpd) {
|
||||
stimmungTs.textContent = `Stand: ${mUpd.toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric', timeZone: TIMEZONE })} ${mUpd.toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit', timeZone: TIMEZONE })} Uhr`;
|
||||
}
|
||||
}
|
||||
} else if (stimmungTabBtn) {
|
||||
stimmungTabBtn.style.display = 'none';
|
||||
if (stimmungText) stimmungText.innerHTML = '';
|
||||
}
|
||||
|
||||
{ const _e = document.getElementById('meta-refresh-mode'); if (_e) {
|
||||
if (incident.refresh_mode === 'auto' && incident.refresh_start_time) {
|
||||
const intervalText = App._formatInterval(incident.refresh_interval);
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren