Die Bausteinspalte mischte vier Dinge in einem Kartenlayout. Ergebnisse zum Anschauen, Erzeuger zum Starten, ein Artefakt ohne Erzeuger und reine Aktionen. In jeder Karte lagen Öffnen und Neurechnen wenige Pixel auseinander, beide mit demselben Kreispfeil-Symbol. Dazu kamen sechs Stellen, an denen ein Lauf beginnen konnte, verteilt über zwei Spalten. Jetzt drei getrennte Bereiche. Oben wird gearbeitet, in der Mitte werden Ergebnisse angesehen, unten stehen die Fall-Aktionen. Gearbeitet wird über genau einen Knopf, dessen Beschriftung sich am Zustand ausrichtet. Beim leeren Fall Lauf starten, bei einer Recherche Recherche starten, bei veralteten Ergebnissen Jetzt aktualisieren, sonst Erneut durchlaufen, während eines abbrechbaren Laufs Abbrechen. Darüber steht, was gerade zu tun ist, etwa die Zahl der neuen Artikel seit dem letzten Bericht. Darunter die vier Schritte als Kette mit Zustand. Sie starten nichts, Aufklappen erklärt nur, was ein Schritt tut. Damit fällt auch eine Kostenfalle weg. Ein einzeln gestartetes Sammeln buchte denselben Satz wie der komplette Lauf, wer danach Lagebild und Faktencheck einzeln nachzog, zahlte 69 statt 45 Credits, ohne dass die Oberfläche darauf hinwies. Benannt wird ab jetzt das Ergebnis statt des Erzeugers. Artikel holen, Lagebild schreiben, Fakten prüfen, Orte erkennen. Bei Recherche-Lagen heißt der zweite Schritt Recherchebericht schreiben. Die Wörter Baustein, Geoparsing und Analyse verschwinden aus der Oberfläche. Weiter entfernt sind die Karte Netzwerkanalyse, solange es den Baustein im Server nicht gibt, der Sammeln-Knopf aus der Quellenspalte und die Wahl Nur Quellen sammeln im Startdialog. Der Server behält seine Schnittstelle für einzelne Bausteine. Die Anzeige eines so gestarteten Laufs bleibt erhalten, er kann aus der klassischen Ansicht kommen. Ein solcher Lauf wird beim Abbruch auch als der Schritt abgebrochen, der wirklich läuft, nicht pauschal als kompletter Lauf. 51 tote CSS-Regeln entfernt. Prüfungen ohne Browser, 59 neue Fälle für die Lauf-Anzeige plus 12 in der Strukturprüfung, die festhalten, dass es im ganzen Dokument genau ein Element gibt, das einen Lauf starten kann. Die Anzeige der Credits am Knopf kommt später, sie ist bewusst nicht Teil dieser Änderung. Cache-Buster auf 20260802c. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
969 Zeilen
77 KiB
HTML
969 Zeilen
77 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="de">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<script>(function(){var t=localStorage.getItem('osint_theme');if(t)document.documentElement.setAttribute('data-theme',t);try{var a=JSON.parse(localStorage.getItem('osint_a11y')||'{}');Object.keys(a).forEach(function(k){if(a[k])document.documentElement.setAttribute('data-a11y-'+k,'true');});}catch(e){}})()</script>
|
|
<link rel="icon" type="image/svg+xml" href="/static/favicon.svg">
|
|
<link rel="apple-touch-icon" href="/static/favicon.svg">
|
|
<title>AegisSight Monitor</title>
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap" rel="stylesheet">
|
|
<link rel="stylesheet" href="/static/vendor/leaflet.css">
|
|
<link rel="stylesheet" href="/static/vendor/MarkerCluster.css">
|
|
<link rel="stylesheet" href="/static/vendor/MarkerCluster.Default.css">
|
|
<link rel="stylesheet" href="/static/css/style.css?v=20260802c">
|
|
<style>
|
|
/* Export Modal Radio */
|
|
.export-radio { display:flex; align-items:center; gap:10px; padding:8px 12px; cursor:pointer; border-radius:var(--radius-sm); transition:background 0.15s; border:1px solid transparent; margin-bottom:4px; }
|
|
.export-radio:hover { background:var(--bg-secondary); }
|
|
.export-radio input[type="radio"] { accent-color:var(--accent); width:16px; height:16px; cursor:pointer; flex-shrink:0; }
|
|
.export-radio input[type="radio"]:checked ~ span:first-of-type { color:var(--accent); font-weight:600; }
|
|
.export-radio span:first-of-type { font-size:13px; }
|
|
.export-radio-desc { font-size:11px; color:var(--text-tertiary); margin-left:auto; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<a href="#main-content" class="skip-link">Zum Hauptinhalt springen</a>
|
|
<div class="dashboard">
|
|
<!-- Header -->
|
|
<header class="header">
|
|
<div class="header-left">
|
|
<div class="header-logo">Aegis<span>Sight</span> Monitor</div>
|
|
<h1 class="sr-only">AegisSight Monitor Dashboard</h1>
|
|
</div>
|
|
<div class="header-right">
|
|
<div class="theme-switch" id="theme-toggle" onclick="ThemeManager.toggle()" role="switch" aria-checked="true" aria-label="Dark Mode" title="Theme wechseln">
|
|
<span class="theme-switch-icon theme-switch-sun">☀︎</span>
|
|
<div class="theme-switch-track">
|
|
<div class="theme-switch-knob"></div>
|
|
</div>
|
|
<span class="theme-switch-icon theme-switch-moon">☽</span>
|
|
</div>
|
|
<div class="header-user-info">
|
|
<button class="header-user-btn" id="header-user-btn" aria-expanded="false" aria-haspopup="true">
|
|
<span class="header-user" id="header-user"></span>
|
|
<span class="header-user-chevron" aria-hidden="true">▾</span>
|
|
</button>
|
|
<div class="header-user-dropdown" id="header-user-dropdown" role="menu">
|
|
<div class="header-dropdown-row">
|
|
<span class="header-dropdown-label">Organisation</span>
|
|
<span class="header-dropdown-value" id="header-org-name">-</span>
|
|
</div>
|
|
<!-- Global Admin: Org-Switcher (herausnehmbar) -->
|
|
<div id="org-switcher-section" class="org-switcher-section" style="display: none;">
|
|
<div class="credits-divider"></div>
|
|
<label class="org-switcher-label" for="org-switcher-select">Wechseln zu:</label>
|
|
<select id="org-switcher-select" class="org-switcher-select"></select>
|
|
</div>
|
|
<div class="header-dropdown-row">
|
|
<span class="header-dropdown-label">Lizenz</span>
|
|
<span class="header-dropdown-value" id="header-license-info">-</span>
|
|
</div>
|
|
<div id="credits-section" class="credits-section" style="display: none;">
|
|
<div class="credits-divider"></div>
|
|
<div class="credits-label" id="credits-label" data-i18n="credits.label">Credits</div>
|
|
<div class="credits-bar-container">
|
|
<div id="credits-bar" class="credits-bar"></div>
|
|
</div>
|
|
<div class="credits-info">
|
|
<span><span id="credits-remaining">0</span> <span data-i18n="credits.of">von</span> <span id="credits-total">0</span></span>
|
|
<span class="credits-percent" id="credits-percent"></span>
|
|
</div>
|
|
</div>
|
|
<div class="credits-divider"></div>
|
|
<button class="header-dropdown-action" type="button" onclick="AIDisclaimer && AIDisclaimer.show()">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg>
|
|
<span>Über KI-Inhalte</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="header-license-warning" id="header-license-warning"></div>
|
|
<a href="/studio" class="btn btn-secondary btn-small" id="studio-link" style="display:none;" title="Experimentelle Studio-Ansicht">Studio</a>
|
|
<button class="btn btn-secondary btn-small" id="logout-btn" data-i18n="header.logout">Abmelden</button>
|
|
</div>
|
|
</header>
|
|
|
|
<!-- Sidebar -->
|
|
<nav class="sidebar" aria-label="Seitenleiste">
|
|
<div class="sidebar-section">
|
|
<button class="btn btn-primary btn-full btn-small" id="new-incident-btn" style="margin-bottom:6px;" data-i18n="header.new_incident">+ Neuer Fall</button>
|
|
</div>
|
|
|
|
<div class="sidebar-filter">
|
|
<button class="sidebar-filter-btn active" data-filter="all" onclick="App.setSidebarFilter('all')" aria-pressed="true" data-i18n="filter.all">Alle</button>
|
|
<button class="sidebar-filter-btn" data-filter="mine" onclick="App.setSidebarFilter('mine')" aria-pressed="false" data-i18n="filter.own">Eigene</button>
|
|
</div>
|
|
|
|
<div class="sidebar-section">
|
|
<h2 class="sidebar-section-title collapsible" onclick="App.toggleSidebarSection('active-incidents')" role="button" tabindex="0" aria-expanded="true">
|
|
<span class="sidebar-chevron" id="chevron-active-incidents" aria-hidden="true">▾</span>
|
|
<span data-i18n="sidebar.live_monitoring">Live-Monitoring</span>
|
|
<span class="sidebar-section-count" id="count-active-incidents"></span>
|
|
</h2>
|
|
<div id="active-incidents" aria-live="polite"></div>
|
|
</div>
|
|
|
|
<div class="sidebar-section">
|
|
<h2 class="sidebar-section-title collapsible" onclick="App.toggleSidebarSection('active-research')" role="button" tabindex="0" aria-expanded="true">
|
|
<span class="sidebar-chevron" id="chevron-active-research" aria-hidden="true">▾</span>
|
|
<span data-i18n="sidebar.research">Recherchen</span>
|
|
<span class="sidebar-section-count" id="count-active-research"></span>
|
|
</h2>
|
|
<div id="active-research" aria-live="polite"></div>
|
|
</div>
|
|
|
|
|
|
<div class="sidebar-section">
|
|
<h2 class="sidebar-section-title collapsible" onclick="App.toggleSidebarSection('archived-incidents')" role="button" tabindex="0" aria-expanded="false">
|
|
<span class="sidebar-chevron" id="chevron-archived-incidents" aria-hidden="true">▾</span>
|
|
<span data-i18n="sidebar.archive">Archiv</span>
|
|
<span class="sidebar-section-count" id="count-archived-incidents"></span>
|
|
</h2>
|
|
<div id="archived-incidents" aria-live="polite" style="display:none;"></div>
|
|
</div>
|
|
<!-- Sammelaktionen. Der erste Klick schaltet den Auswahlmodus ein,
|
|
erst dann erscheinen die Haken in der Lagenliste. -->
|
|
<div class="sidebar-bulk" id="sidebar-bulk-tools">
|
|
<button class="btn btn-secondary btn-small sidebar-bulk-btn" onclick="App.startBulkMode('archive')" title="Mehrere Lagen archivieren oder wieder aktivieren" data-i18n-attr="title:sidebar.bulk_archive_title">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect width="20" height="5" x="2" y="3" rx="1"/><path d="M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8"/><path d="M10 12h4"/></svg>
|
|
<span data-i18n="action.archive">Archivieren</span>
|
|
</button>
|
|
<button class="btn btn-secondary btn-small sidebar-bulk-btn danger" onclick="App.startBulkMode('delete')" title="Mehrere Lagen löschen" data-i18n-attr="title:sidebar.bulk_delete_title">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 6h18"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/><line x1="10" x2="10" y1="11" y2="17"/><line x1="14" x2="14" y1="11" y2="17"/></svg>
|
|
<span data-i18n="action.delete">Löschen</span>
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Auswahlmodus. Hier wird die Sammelaktion bestätigt oder verworfen. -->
|
|
<div class="sidebar-bulk sidebar-bulk-active" id="sidebar-bulk-bar" hidden>
|
|
<div class="sidebar-bulk-count" id="sidebar-bulk-count" aria-live="polite"></div>
|
|
<label class="sidebar-bulk-all">
|
|
<input type="checkbox" id="sidebar-bulk-all" onchange="App.selectAllVisible(this.checked)">
|
|
<span data-i18n="sidebar.bulk_all">Alle sichtbaren</span>
|
|
</label>
|
|
<div class="sidebar-bulk-actions">
|
|
<button class="btn btn-secondary btn-small sidebar-bulk-btn" id="sidebar-bulk-archive" onclick="App.bulkStatus('archived')">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect width="20" height="5" x="2" y="3" rx="1"/><path d="M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8"/><path d="M10 12h4"/></svg>
|
|
<span>Archivieren</span>
|
|
</button>
|
|
<button class="btn btn-secondary btn-small sidebar-bulk-btn" id="sidebar-bulk-activate" onclick="App.bulkStatus('active')">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect width="20" height="5" x="2" y="3" rx="1"/><path d="M4 8v11a2 2 0 0 0 2 2h2"/><path d="M20 8v11a2 2 0 0 1-2 2h-2"/><path d="m9 15 3-3 3 3"/><path d="M12 12v9"/></svg>
|
|
<span>Aktivieren</span>
|
|
</button>
|
|
<button class="btn btn-secondary btn-small sidebar-bulk-btn danger" id="sidebar-bulk-delete" onclick="App.bulkDelete()">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 6h18"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/><line x1="10" x2="10" y1="11" y2="17"/><line x1="14" x2="14" y1="11" y2="17"/></svg>
|
|
<span>Löschen</span>
|
|
</button>
|
|
<button class="btn btn-secondary btn-small sidebar-bulk-btn ghost" onclick="App.endBulkMode()" title="Auswahl verwerfen">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>
|
|
<span data-i18n="action.cancel">Abbrechen</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="sidebar-sources-link">
|
|
<button class="btn btn-secondary btn-full btn-small" onclick="App.openSourceManagement()" title="Quellen verwalten" data-i18n-attr="title:sidebar.manage_sources_title">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M3 5v14c0 1.66 4.03 3 9 3s9-1.34 9-3V5"/><path d="M3 12c0 1.66 4.03 3 9 3s9-1.34 9-3"/></svg>
|
|
<span data-i18n="sidebar.sources">Quellen</span>
|
|
</button>
|
|
<button class="btn btn-secondary btn-full btn-small sidebar-feedback-btn" onclick="App.openFeedback()" title="Feedback senden" data-i18n-attr="title:sidebar.feedback_title">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect width="20" height="16" x="2" y="4" rx="2"/><path d="m22 7-10 5L2 7"/></svg>
|
|
<span data-i18n="sidebar.feedback">Feedback</span>
|
|
</button>
|
|
<!-- Tutorial-Einstieg temporaer deaktiviert (Ueberarbeitung) - reaktivieren durch Entfernen der Kommentarzeichen:
|
|
<button class="btn btn-secondary btn-full btn-small" onclick="Tutorial.start()" title="Interaktiven Rundgang starten">Rundgang starten</button>
|
|
-->
|
|
<div class="sidebar-stats-mini">
|
|
<span id="stat-sources-count">0 Quellen</span> · <span id="stat-articles-count">0 Artikel</span>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
|
|
<!-- Main Content -->
|
|
<main class="main-content" id="main-content">
|
|
<div class="empty-state" id="empty-state">
|
|
<div class="empty-state-icon">☉</div>
|
|
<div class="empty-state-title" data-i18n="empty.no_incident_title">Kein Vorfall ausgewählt</div>
|
|
<div class="empty-state-text" data-i18n="empty.no_incident_text">Erstelle einen neuen Fall oder wähle einen bestehenden aus der Seitenleiste.</div>
|
|
</div>
|
|
|
|
|
|
<!-- Netzwerkanalyse View (hidden by default) -->
|
|
|
|
|
|
<!-- Lagebild (hidden by default) -->
|
|
<div id="incident-view" style="display:none;">
|
|
<!-- Header Strip -->
|
|
<div class="incident-header-strip" id="incident-header-strip">
|
|
<div class="incident-header-row0">
|
|
<span class="incident-type-badge" id="incident-type-badge"></span>
|
|
<span class="auto-refresh-indicator" id="meta-refresh-mode"></span>
|
|
</div>
|
|
<div class="incident-header-row1">
|
|
<div class="incident-header-left">
|
|
<h2 class="incident-header-title" id="incident-title"></h2>
|
|
<span class="incident-ai-badge" id="incident-ai-badge" hidden></span>
|
|
</div>
|
|
<div class="incident-header-actions">
|
|
<button class="btn btn-primary btn-small" id="refresh-btn" data-i18n="action.refresh">Aktualisieren</button>
|
|
<button class="btn btn-secondary btn-small" id="edit-incident-btn" data-i18n="action.edit">Bearbeiten</button>
|
|
<button class="btn btn-secondary btn-small" onclick="App.openExportModal()" data-i18n="action.export">Bericht exportieren</button>
|
|
<button class="btn btn-secondary btn-small" id="archive-incident-btn" title="Diese Lage archivieren"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect width="20" height="5" x="2" y="3" rx="1"/><path d="M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8"/><path d="M10 12h4"/></svg><span data-i18n="action.archive">Archivieren</span></button>
|
|
<button class="btn btn-danger btn-small" id="delete-incident-btn" title="Diese Lage löschen"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 6h18"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/><line x1="10" x2="10" y1="11" y2="17"/><line x1="14" x2="14" y1="11" y2="17"/></svg><span data-i18n="action.delete">Löschen</span></button>
|
|
</div>
|
|
</div>
|
|
<div class="incident-header-row2">
|
|
<div class="incident-header-row2-left">
|
|
<span class="incident-creator-badge">von <strong id="incident-creator"></strong></span>
|
|
<span class="intl-badge" id="intl-badge"></span>
|
|
<span id="incident-description" class="incident-description-text"></span>
|
|
</div>
|
|
<div class="incident-header-row2-right">
|
|
<div class="summary-meta" id="summary-meta">
|
|
<span id="meta-updated" class="meta-updated-link" role="button" tabindex="0" onclick="App.toggleRefreshHistory()" onkeydown="if(event.key==='Enter')App.toggleRefreshHistory()"></span>
|
|
</div>
|
|
<div class="refresh-history-popover" id="refresh-history-popover" style="display:none;">
|
|
<div class="refresh-history-header">
|
|
<span class="refresh-history-title">Refresh-Verlauf</span>
|
|
<button class="refresh-history-close" onclick="App.closeRefreshHistory()">×</button>
|
|
</div>
|
|
<div class="refresh-history-list" id="refresh-history-list">
|
|
<div style="padding:12px;color:var(--text-disabled);font-size:12px;">Lade...</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Minimierte Fortschrittsanzeige -->
|
|
<div class="progress-mini" id="progress-mini" style="display:none;" onclick="App.openProgressPopup()">
|
|
<span class="progress-mini-dot"></span>
|
|
<span class="progress-mini-text" id="progress-mini-text">Läuft...</span>
|
|
<span class="progress-mini-timer" id="progress-mini-timer"></span>
|
|
</div>
|
|
|
|
<!-- Tab-Navigation -->
|
|
<div class="tab-nav" id="tab-nav" style="display:none;">
|
|
<button class="tab-btn active" data-tab="zusammenfassung" data-i18n="tab.latest_developments">Neueste Entwicklungen</button>
|
|
<button class="tab-btn" data-tab="lagebild" data-i18n="tab.summary">Lagebild</button>
|
|
<button class="tab-btn" data-tab="timeline" data-i18n="tab.timeline">Ereignis-Timeline</button>
|
|
<button class="tab-btn" data-tab="karte" data-i18n="tab.map">Geografische Verteilung</button>
|
|
<button class="tab-btn" data-tab="faktencheck" data-i18n="tab.factcheck">Faktencheck</button>
|
|
<button class="tab-btn" data-tab="stimmung" data-i18n="tab.public_mood" id="tab-btn-stimmung" style="display:none;">Öffentliche Stimmung</button>
|
|
<button class="tab-btn" data-tab="pipeline" data-i18n="tab.pipeline">Analysepipeline</button>
|
|
<button class="tab-btn" data-tab="quellen" data-i18n="tab.sources_overview">Quellenübersicht</button>
|
|
</div>
|
|
|
|
<!-- Tab-Panels -->
|
|
<div class="tab-panels">
|
|
<div class="tab-panel active" id="panel-zusammenfassung">
|
|
<div class="card" id="zusammenfassung-card">
|
|
<div class="card-header">
|
|
<div class="card-title">Zusammenfassung</div>
|
|
</div>
|
|
<div id="zusammenfassung-content">
|
|
<div id="zusammenfassung-text" class="summary-text" style="padding:8px 16px;"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="tab-panel" id="panel-lagebild">
|
|
<div class="card incident-analysis-summary">
|
|
<div class="card-header">
|
|
<div class="card-title" data-i18n="card.summary">Lagebild</div>
|
|
<span class="lagebild-timestamp" id="lagebild-timestamp"></span>
|
|
</div>
|
|
<div id="summary-content">
|
|
<div id="summary-text" class="summary-text"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="tab-panel" id="panel-timeline">
|
|
<div class="card timeline-card">
|
|
<div class="card-header">
|
|
<div class="card-title" data-i18n="card.timeline">Ereignis-Timeline</div>
|
|
<div class="ht-controls">
|
|
<div class="ht-filter-group">
|
|
<button class="ht-filter-btn active" data-filter="all" onclick="App.setTimelineFilter('all')" aria-pressed="true">Alle</button>
|
|
<button class="ht-filter-btn" data-filter="articles" onclick="App.setTimelineFilter('articles')" aria-pressed="false">Meldungen</button>
|
|
<button class="ht-filter-btn" data-filter="snapshots" onclick="App.setTimelineFilter('snapshots')" aria-pressed="false">Lageberichte</button>
|
|
</div>
|
|
<span class="ht-count" id="article-count"></span>
|
|
<div class="ht-range-group">
|
|
<button class="ht-range-btn" data-range="24h" onclick="App.setTimelineRange('24h')" aria-pressed="false">24h</button>
|
|
<button class="ht-range-btn" data-range="7d" onclick="App.setTimelineRange('7d')" aria-pressed="false">7T</button>
|
|
<button class="ht-range-btn active" data-range="all" onclick="App.setTimelineRange('all')" aria-pressed="true">Alles</button>
|
|
</div>
|
|
<label for="timeline-search" class="sr-only">Timeline durchsuchen</label>
|
|
<input type="text" id="timeline-search" class="timeline-filter-input" placeholder="Suche..." oninput="App.debouncedRerenderTimeline()">
|
|
</div>
|
|
</div>
|
|
<div id="timeline" class="ht-timeline-container">
|
|
<div class="ht-empty">Noch keine Meldungen</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="tab-panel" id="panel-karte">
|
|
<div class="card map-card">
|
|
<div class="card-header">
|
|
<div class="card-title" data-i18n="card.map">Geografische Verteilung</div>
|
|
<span class="map-stats" id="map-stats"></span>
|
|
<div class="card-header-actions">
|
|
<button class="btn btn-secondary btn-small" id="geoparse-btn" onclick="App.triggerGeoparse()" title="Orte aus Artikeln einlesen" data-i18n="map.import_locations" data-i18n-attr="title:map.import_locations_title">Orte einlesen</button>
|
|
</div>
|
|
</div>
|
|
<div class="map-container" id="map-container">
|
|
<div class="map-empty" id="map-empty" data-i18n="map.empty">Keine Orte erkannt</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="tab-panel" id="panel-faktencheck">
|
|
<div class="card incident-analysis-factcheck" id="factcheck-card">
|
|
<div class="card-header">
|
|
<div class="card-title"><span data-i18n="tab.factcheck">Faktencheck</span> <span class="info-icon" data-tooltip="Gesichert/Bestätigt = durch mehrere unabhängige Quellen belegt. Unbestätigt/Ungeprüft = noch nicht ausreichend verifiziert. Widerlegt/Umstritten = Quellen widersprechen sich."><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg></span></div>
|
|
<div class="fc-filter-bar" id="fc-filters"></div>
|
|
</div>
|
|
<div class="factcheck-list" id="factcheck-list">
|
|
<div class="empty-state" style="padding:20px;">
|
|
<div class="empty-state-text">Noch keine Fakten geprüft</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="tab-panel" id="panel-stimmung">
|
|
<div class="card incident-analysis-stimmung" id="stimmung-card">
|
|
<div class="card-header">
|
|
<div class="card-title">
|
|
<span data-i18n="card.public_mood">Öffentliche Stimmung</span>
|
|
<span class="info-icon" data-tooltip="Themen und Bruchlinien aus Foren-Quellen (z.B. 5ch, Hatena, Note). KEINE Faktenlage - reines Stimmungsmaterial. Beitraege sind anonym und koennen Trolling enthalten."><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg></span>
|
|
</div>
|
|
<span class="stimmung-timestamp" id="stimmung-timestamp"></span>
|
|
</div>
|
|
<div id="stimmung-content">
|
|
<div id="stimmung-text" class="summary-text" style="padding:8px 16px;"></div>
|
|
<div style="padding:0 16px 16px; font-size:11px; color:var(--text-disabled); border-top:1px solid var(--border); margin-top:8px; padding-top:8px;">
|
|
Hinweis: Forenbeiträge sind anonyme Online-Stimmungen, keine Faktenlage. Sie fließen nicht in den Faktencheck ein.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="tab-panel" id="panel-pipeline">
|
|
<div class="card pipeline-card" id="pipeline-card">
|
|
<div class="card-header">
|
|
<div class="card-title" data-i18n="card.pipeline">Analysepipeline</div>
|
|
<span class="pipeline-header-meta" id="pipeline-header-meta"></span>
|
|
</div>
|
|
<div class="pipeline-body">
|
|
<div class="pipeline-stage" id="pipeline-stage" aria-label="Analysepipeline-Visualisierung">
|
|
<div class="pipeline-empty" id="pipeline-empty" data-i18n="pipeline.empty">Noch nie aktualisiert. Starte den ersten Refresh.</div>
|
|
</div>
|
|
<aside class="pipeline-sidenote" id="pipeline-sidenote" hidden>
|
|
Recherche-Lagen werden mehrfach evaluiert, um das Bild Schritt für Schritt aufzubauen.
|
|
</aside>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="tab-panel" id="panel-quellen">
|
|
<div class="card source-overview-card">
|
|
<div class="card-header">
|
|
<div class="card-title" data-i18n="card.sources_overview">Quellenübersicht</div>
|
|
<span class="source-overview-header-stats" id="source-overview-header-stats"></span>
|
|
</div>
|
|
<div id="source-overview-content"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
</div>
|
|
|
|
<!-- Modal: Neue Lage -->
|
|
<div class="modal-overlay" id="modal-new" role="dialog" aria-modal="true" aria-labelledby="modal-new-title">
|
|
<div class="modal">
|
|
<div class="modal-header">
|
|
<div class="modal-title" id="modal-new-title" data-i18n="modal.new_incident.title2">Neuen Fall anlegen</div>
|
|
<button class="modal-close" onclick="closeModal('modal-new')" aria-label="Schließen" data-i18n-attr="aria-label:aria.close">×</button>
|
|
</div>
|
|
<form id="new-incident-form">
|
|
<div class="modal-body">
|
|
<div class="form-group">
|
|
<label for="inc-type" data-i18n="modal.field.type">Art der Lage</label>
|
|
<select id="inc-type" onchange="toggleTypeDefaults()">
|
|
<option value="adhoc" data-i18n="modal.option.type_adhoc">Live-Monitoring : Ereignis beobachten</option>
|
|
<option value="research" data-i18n="modal.option.type_research">Recherche : Thema analysieren</option>
|
|
</select>
|
|
<div class="form-hint" id="type-hint" data-i18n="modal.hint.type_adhoc">
|
|
Durchsucht laufend hunderte Nachrichtenquellen nach neuen Meldungen. Empfohlen: Automatische Aktualisierung.
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="inc-title" data-i18n="modal.new_incident.title_field">Titel des Vorfalls</label>
|
|
<input type="text" id="inc-title" required aria-required="true" placeholder="z.B. Explosion in Madrid" data-i18n-attr="placeholder:modal.placeholder.title">
|
|
</div>
|
|
<div class="form-group">
|
|
<div class="description-label-row">
|
|
<label for="inc-description"><span data-i18n="modal.new_incident.description">Beschreibung / Kontext</span> <span class="info-icon tooltip-below" id="description-info-icon" data-tooltip="Beschreibe den Vorfall möglichst genau: Was ist passiert? Wo? Wer ist beteiligt? Je präziser, desto bessere Ergebnisse."><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg></span></label>
|
|
<button type="button" class="btn btn-secondary btn-small" id="btn-enhance-description" onclick="App.generateDescription()" disabled>
|
|
<span id="enhance-btn-text" data-i18n="modal.new_incident.enhance">Beschreibung generieren</span>
|
|
<span id="enhance-spinner" class="spinner-inline" style="display:none;"></span>
|
|
</button>
|
|
</div>
|
|
<textarea id="inc-description" placeholder="Weitere Details zum Vorfall (optional)" data-i18n-attr="placeholder:modal.placeholder.description"></textarea>
|
|
|
|
</div>
|
|
<div class="form-group">
|
|
<label data-i18n="modal.field.sources">Quellen</label>
|
|
<div class="toggle-group">
|
|
<label class="toggle-label">
|
|
<input type="checkbox" id="inc-international">
|
|
<span class="toggle-switch"></span>
|
|
<span class="toggle-text"><span data-i18n="modal.toggle.international">Internationale Quellen einbeziehen</span> <span class="info-icon tooltip-below" data-tooltip="Aktiviert: Sucht auch in englischsprachigen und internationalen Medien. Deaktiviert (Standard): Nur deutschsprachige Quellen - empfohlen für DACH-Lagen."><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg></span></span>
|
|
</label>
|
|
</div>
|
|
<div class="toggle-group" style="margin-top: 8px;">
|
|
<label class="toggle-label">
|
|
<input type="checkbox" id="inc-telegram">
|
|
<span class="toggle-switch"></span>
|
|
<span class="toggle-text"><span data-i18n="modal.toggle.telegram">Telegram-Kanäle einbeziehen</span> <span class="info-icon tooltip-below" data-tooltip="Bezieht OSINT-relevante Telegram-Kanäle als zusätzliche Quelle ein. Kann die Aktualität erhöhen, aber auch unbestätigte Informationen liefern."><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg></span></span>
|
|
</label>
|
|
</div>
|
|
<div class="toggle-group" style="margin-top: 8px;">
|
|
<label class="toggle-label">
|
|
<input type="checkbox" id="inc-x">
|
|
<span class="toggle-switch"></span>
|
|
<span class="toggle-text"><span data-i18n="modal.toggle.x">X (Twitter) einbeziehen</span> <span class="info-icon tooltip-below" data-tooltip="Bezieht Posts konfigurierter X-Accounts (Twitter) als zusätzliche Quelle ein. Kann die Aktualität erhöhen, aber auch unbestätigte Informationen liefern."><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg></span></span>
|
|
</label>
|
|
</div> </div>
|
|
<div class="form-group">
|
|
<label><span data-i18n="modal.new_incident.visibility">Sichtbarkeit</span> <span class="info-icon tooltip-below" data-tooltip="Öffentlich: Alle Nutzer der Organisation sehen diese Lage. Privat: Nur für dich sichtbar."><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg></span></label>
|
|
<div class="toggle-group">
|
|
<label class="toggle-label">
|
|
<input type="checkbox" id="inc-visibility" checked>
|
|
<span class="toggle-switch"></span>
|
|
<span class="toggle-text" id="visibility-text" data-i18n="modal.toggle.visibility_public_text">Öffentlich : für alle Nutzer sichtbar</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="inc-ai-backend"><span data-i18n="modal.field.ai_backend">KI-Verarbeitung</span> <span class="info-icon tooltip-below" data-tooltip="Steuert, wo die KI-Verarbeitung dieser Lage stattfindet. Standard: es gilt die Vorgabe der Organisation. Anthropic: heutiger Weg mit eingebauter Websuche. EU: Verarbeitung ueber AWS Bedrock in Frankfurt, Recherche ueber den europaeischen Suchindex staan. Prompts und Suchanfragen verlassen den europaeischen Rechtsraum nicht."><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg></span></label>
|
|
<select id="inc-ai-backend">
|
|
<option value="" data-i18n="modal.option.ai_backend_default">Standard (Vorgabe der Organisation)</option>
|
|
<option value="cli" data-i18n="modal.option.ai_backend_cli">Anthropic (heutiger Weg)</option>
|
|
<option value="bedrock" data-i18n="modal.option.ai_backend_eu">EU (Frankfurt, DSGVO-Fassung)</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="inc-refresh-mode" data-i18n="modal.field.refresh">Aktualisierung</label>
|
|
<select id="inc-refresh-mode" onchange="toggleRefreshInterval()">
|
|
<option value="manual" data-i18n="modal.option.manual">Manuell</option>
|
|
<option value="auto" data-i18n="modal.option.auto">Automatisch</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group conditional-field" id="refresh-interval-field">
|
|
<label for="inc-refresh-value" data-i18n="modal.field.interval">Intervall</label>
|
|
<div class="interval-input-group">
|
|
<input type="number" id="inc-refresh-value" min="30" value="30">
|
|
<select id="inc-refresh-unit" onchange="updateIntervalMin()">
|
|
<option value="1" selected data-i18n="modal.unit.minutes">Minuten</option>
|
|
<option value="60" data-i18n="modal.unit.hours">Stunden</option>
|
|
<option value="1440" data-i18n="modal.unit.days">Tage</option>
|
|
<option value="10080" data-i18n="modal.unit.weeks">Wochen</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-hint" id="interval-min-hint" style="display:none;"></div>
|
|
</div>
|
|
<div class="form-group conditional-field" id="refresh-starttime-field">
|
|
<label for="inc-refresh-starttime"><span data-i18n="modal.field.start_time">Erste Aktualisierung um</span> <span class="info-icon tooltip-below" data-tooltip="Legt den Startzeitpunkt fest. Danach wird im eingestellten Intervall aktualisiert."><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg></span></label>
|
|
<input type="time" id="inc-refresh-starttime" value="07:00" required>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="inc-retention"><span data-i18n="modal.field.retention">Aufbewahrung (Tage)</span> <span class="info-icon tooltip-below" data-tooltip="Nach Ablauf wird die Lage automatisch archiviert. 0 = unbegrenzt aufbewahren."><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg></span></label>
|
|
<input type="number" id="inc-retention" min="0" max="999" value="30" placeholder="0 = Unbegrenzt" data-i18n-attr="placeholder:modal.placeholder.retention">
|
|
</div>
|
|
<div class="form-group" style="margin-top: 8px;">
|
|
<label data-i18n="modal.field.notifications">E-Mail-Benachrichtigungen</label>
|
|
<div class="form-hint" style="margin-bottom: 8px;" data-i18n="modal.hint.notifications">Per E-Mail benachrichtigen bei:</div>
|
|
<div class="toggle-group">
|
|
<label class="toggle-label">
|
|
<input type="checkbox" id="inc-notify-summary">
|
|
<span class="toggle-switch"></span>
|
|
<span class="toggle-text" data-i18n="modal.notify.summary">Neues Lagebild</span>
|
|
</label>
|
|
</div>
|
|
<div class="toggle-group" style="margin-top: 8px;">
|
|
<label class="toggle-label">
|
|
<input type="checkbox" id="inc-notify-new-articles">
|
|
<span class="toggle-switch"></span>
|
|
<span class="toggle-text" data-i18n="modal.notify.new_articles">Neue Artikel</span>
|
|
</label>
|
|
</div>
|
|
<div class="toggle-group" style="margin-top: 8px;">
|
|
<label class="toggle-label">
|
|
<input type="checkbox" id="inc-notify-status-change">
|
|
<span class="toggle-switch"></span>
|
|
<span class="toggle-text" data-i18n="modal.notify.status_change">Statusänderung Faktencheck</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" onclick="closeModal('modal-new')" data-i18n="common.cancel">Abbrechen</button>
|
|
<button type="submit" class="btn btn-primary" id="modal-new-submit" data-i18n="modal.new_incident.submit">Lage anlegen</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal: Quellenverwaltung -->
|
|
<div class="modal-overlay" id="modal-sources" role="dialog" aria-modal="true" aria-labelledby="modal-sources-title">
|
|
<div class="modal modal-wide">
|
|
<div class="modal-header">
|
|
<div class="modal-title" id="modal-sources-title" data-i18n="sources_modal.title">Quellenverwaltung</div>
|
|
<button class="modal-close" onclick="closeModal('modal-sources')" aria-label="Schließen" data-i18n-attr="aria-label:aria.close">×</button>
|
|
</div>
|
|
<div class="modal-body sources-modal-body">
|
|
<!-- Stats-Leiste -->
|
|
<div class="sources-stats-bar" id="sources-stats-bar"></div>
|
|
|
|
<!-- Toolbar -->
|
|
<div class="sources-toolbar">
|
|
<div class="sources-filters">
|
|
<label for="sources-filter-type" class="sr-only" data-i18n="sources_modal.filter.type">Quellentyp filtern</label>
|
|
<select id="sources-filter-type" class="timeline-filter-select" onchange="App.filterSources()">
|
|
<option value="" data-i18n="sources_modal.filter.type_all">Alle Typen</option>
|
|
<option value="rss_feed">RSS-Feed</option>
|
|
<option value="web_source">Web-Quelle</option>
|
|
<option value="telegram_channel">Telegram</option>
|
|
<option value="x_account">X (Twitter)</option>
|
|
<option value="podcast_feed">Podcast</option>
|
|
<option value="excluded">Von mir ausgeschlossen</option>
|
|
</select>
|
|
<label for="sources-filter-category" class="sr-only" data-i18n="sources_modal.filter.category">Kategorie filtern</label>
|
|
<select id="sources-filter-category" class="timeline-filter-select" onchange="App.filterSources()">
|
|
<option value="" data-i18n="sources_modal.filter.category_all">Alle Kategorien</option>
|
|
<option value="nachrichtenagentur">Nachrichtenagentur</option>
|
|
<option value="oeffentlich-rechtlich">Öffentlich-Rechtlich</option>
|
|
<option value="qualitaetszeitung">Qualitätszeitung</option>
|
|
<option value="behoerde">Behörde</option>
|
|
<option value="fachmedien">Fachmedien</option>
|
|
<option value="think-tank">Think Tank</option>
|
|
<option value="international">International</option>
|
|
<option value="regional">Regional</option>
|
|
<option value="boulevard">Boulevard</option>
|
|
<option value="sonstige">Sonstige</option>
|
|
</select>
|
|
<label for="sources-filter-political" class="sr-only" data-i18n="sources_modal.filter.political">Politische Ausrichtung filtern</label>
|
|
<select id="sources-filter-political" class="timeline-filter-select" onchange="App.filterSources()">
|
|
<option value="" data-i18n="sources_modal.filter.political_all">Alle Ausrichtungen</option>
|
|
<option value="links_extrem">Links (extrem)</option>
|
|
<option value="links">Links</option>
|
|
<option value="mitte_links">Mitte-Links</option>
|
|
<option value="liberal">Liberal</option>
|
|
<option value="mitte">Mitte</option>
|
|
<option value="konservativ">Konservativ</option>
|
|
<option value="mitte_rechts">Mitte-Rechts</option>
|
|
<option value="rechts">Rechts</option>
|
|
<option value="rechts_extrem">Rechts (extrem)</option>
|
|
<option value="na">Nicht eingeordnet</option>
|
|
</select>
|
|
<label for="sources-filter-mediatype" class="sr-only" data-i18n="sources_modal.filter.mediatype">Medientyp filtern</label>
|
|
<select id="sources-filter-mediatype" class="timeline-filter-select" onchange="App.filterSources()">
|
|
<option value="" data-i18n="sources_modal.filter.mediatype_all">Alle Medientypen</option>
|
|
<option value="tageszeitung">Tageszeitung</option>
|
|
<option value="wochenzeitung">Wochenzeitung</option>
|
|
<option value="magazin">Magazin</option>
|
|
<option value="tv_sender">TV-Sender</option>
|
|
<option value="radio">Radio</option>
|
|
<option value="oeffentlich_rechtlich">Öffentlich-Rechtlich</option>
|
|
<option value="nachrichtenagentur">Nachrichtenagentur</option>
|
|
<option value="online_only">Online-only</option>
|
|
<option value="blog">Blog</option>
|
|
<option value="telegram_kanal">Telegram-Kanal</option>
|
|
<option value="telegram_bot">Telegram-Bot</option>
|
|
<option value="podcast">Podcast</option>
|
|
<option value="social_media">Social Media</option>
|
|
<option value="imageboard">Imageboard</option>
|
|
<option value="think_tank">Think Tank</option>
|
|
<option value="ngo">NGO</option>
|
|
<option value="behoerde">Behörde</option>
|
|
<option value="staatsmedium">Staatsmedium</option>
|
|
<option value="fachmedium">Fachmedium</option>
|
|
<option value="sonstige">Sonstige</option>
|
|
</select>
|
|
<label for="sources-filter-reliability" class="sr-only" data-i18n="sources_modal.filter.reliability">Glaubwürdigkeit filtern</label>
|
|
<select id="sources-filter-reliability" class="timeline-filter-select" onchange="App.filterSources()">
|
|
<option value="" data-i18n="sources_modal.filter.reliability_all">Alle Glaubwürdigkeiten</option>
|
|
<option value="sehr_hoch">Sehr hoch</option>
|
|
<option value="hoch">Hoch</option>
|
|
<option value="gemischt">Gemischt</option>
|
|
<option value="niedrig">Niedrig</option>
|
|
<option value="sehr_niedrig">Sehr niedrig</option>
|
|
<option value="na">Nicht eingeordnet</option>
|
|
</select>
|
|
<label for="sources-filter-extern" class="sr-only" data-i18n="sources_modal.filter.extern">Externe Reputation filtern</label>
|
|
<select id="sources-filter-extern" class="timeline-filter-select" onchange="App.filterSources()">
|
|
<option value="" data-i18n="sources_modal.filter.extern_all">Externe Reputation: alle</option>
|
|
<option value="ifcn">IFCN-Faktenchecker</option>
|
|
<option value="eu_disinfo">EU-Desinfo gelistet</option>
|
|
</select>
|
|
<label for="sources-filter-alignment" class="sr-only" data-i18n="sources_modal.filter.alignment">Geopolitische Nähe filtern</label>
|
|
<select id="sources-filter-alignment" class="timeline-filter-select" onchange="App.filterSources()">
|
|
<option value="" data-i18n="sources_modal.filter.alignment_all">Alle Nähen</option>
|
|
<option value="prorussisch">Prorussisch</option>
|
|
<option value="proiranisch">Proiranisch</option>
|
|
<option value="prowestlich">Prowestlich</option>
|
|
<option value="proukrainisch">Proukrainisch</option>
|
|
<option value="prochinesisch">Prochinesisch</option>
|
|
<option value="projapanisch">Projapanisch</option>
|
|
<option value="proisraelisch">Proisraelisch</option>
|
|
<option value="propalaestinensisch">Propalästinensisch</option>
|
|
<option value="protuerkisch">Protürkisch</option>
|
|
<option value="panarabisch">Panarabisch</option>
|
|
<option value="neutral">Neutral</option>
|
|
<option value="sonstige">Sonstige</option>
|
|
</select>
|
|
<label for="sources-search" class="sr-only" data-i18n="sources_modal.search">Quellen durchsuchen</label>
|
|
<input type="text" id="sources-search" class="timeline-filter-input sources-search-input" placeholder="Suche..." oninput="App.filterSources()" data-i18n-attr="placeholder:sources_modal.search_placeholder">
|
|
</div>
|
|
<div class="sources-toolbar-actions">
|
|
<button class="btn btn-secondary btn-small" onclick="App.openPdfUpload()" style="margin-right:8px;">+ PDF hochladen</button>
|
|
<button class="btn btn-primary btn-small" onclick="App.toggleSourceForm()" data-i18n="sources_modal.add_source">+ Quelle</button>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<!-- Inline-Formular: Quelle hinzufügen (ein-/ausklappbar) -->
|
|
<div class="sources-add-form" id="sources-add-form" style="display:none;">
|
|
<div class="sources-form-row">
|
|
<div class="form-group flex-1">
|
|
<label for="src-discover-url" data-i18n="sources_modal.form.url_label">URL oder Domain</label>
|
|
<input type="text" id="src-discover-url" placeholder="z.B. netzpolitik.org oder t.me/kanalname" data-i18n-attr="placeholder:sources_modal.form.url_placeholder">
|
|
</div>
|
|
<button class="btn btn-secondary btn-small" id="src-discover-btn" onclick="App.discoverSource()" data-i18n="sources_modal.form.discover">Erkennen</button>
|
|
</div>
|
|
|
|
<!-- Ergebnis-Anzeige (nach Discovery) -->
|
|
<div id="src-discovery-result" class="sources-discovery-result" style="display:none;">
|
|
<div class="sources-add-form-grid">
|
|
<div class="form-group">
|
|
<label for="src-name">Name</label>
|
|
<input type="text" id="src-name" placeholder="Wird erkannt..." data-i18n-attr="placeholder:sources_modal.form.name_placeholder">
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="src-category" data-i18n="sources_modal.form.category">Kategorie</label>
|
|
<select id="src-category">
|
|
<option value="nachrichtenagentur">Nachrichtenagentur</option>
|
|
<option value="oeffentlich-rechtlich">Öffentlich-Rechtlich</option>
|
|
<option value="qualitaetszeitung">Qualitätszeitung</option>
|
|
<option value="behoerde">Behörde</option>
|
|
<option value="fachmedien">Fachmedien</option>
|
|
<option value="think-tank">Think Tank</option>
|
|
<option value="international">International</option>
|
|
<option value="regional">Regional</option>
|
|
<option value="boulevard">Boulevard</option>
|
|
<option value="sonstige" selected>Sonstige</option>
|
|
<option value="ukraine-russland-krieg">Ukraine-Russland-Krieg</option>
|
|
<option value="irankonflikt">Irankonflikt</option>
|
|
<option value="osint-international">OSINT International</option>
|
|
<option value="extremismus-deutschland">Extremismus Deutschland</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label data-i18n="sources_modal.form.type">Typ</label>
|
|
<input type="text" id="src-type-display" class="input-readonly" readonly>
|
|
<select id="src-type-select" style="display:none">
|
|
<option value="rss_feed">RSS-Feed</option>
|
|
<option value="web_source">Web-Quelle</option>
|
|
<option value="telegram_channel">Telegram-Kanal</option>
|
|
<option value="x_account">X-Account</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group" id="src-rss-url-group">
|
|
<label data-i18n="sources_modal.form.rss_url">RSS-Feed URL</label>
|
|
<input type="text" id="src-rss-url" class="input-readonly" readonly>
|
|
</div>
|
|
<div class="form-group">
|
|
<label data-i18n="sources_modal.form.domain">Domain</label>
|
|
<input type="text" id="src-domain" class="input-readonly" readonly>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="src-notes" data-i18n="sources_modal.form.notes">Notizen</label>
|
|
<input type="text" id="src-notes" placeholder="Optional" data-i18n-attr="placeholder:sources_modal.form.notes_placeholder">
|
|
</div>
|
|
</div>
|
|
<div class="sources-discovery-actions">
|
|
<button class="btn btn-primary btn-small" onclick="App.saveSource()" data-i18n="common.save">Speichern</button>
|
|
<button class="btn btn-secondary btn-small" onclick="App.toggleSourceForm(false)" data-i18n="common.cancel">Abbrechen</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Quellen-Liste (gruppiert) -->
|
|
<div class="sources-list" id="sources-list">
|
|
<div class="empty-state-text" style="padding:var(--sp-3xl);text-align:center;" data-i18n="sources_modal.list.loading">Lade Quellen...</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal: PDF als Quelle hochladen -->
|
|
<div class="modal-overlay" id="modal-pdf-upload" role="dialog" aria-modal="true" aria-labelledby="modal-pdf-upload-title">
|
|
<div class="modal">
|
|
<div class="modal-header">
|
|
<div class="modal-title" id="modal-pdf-upload-title">PDF als Quelle hochladen</div>
|
|
<button class="modal-close" onclick="closeModal('modal-pdf-upload')" aria-label="Schliessen">×</button>
|
|
</div>
|
|
<form id="pdf-upload-form" enctype="multipart/form-data">
|
|
<div class="modal-body">
|
|
<p class="text-secondary" style="margin-top:0;">
|
|
Die PDF wird gespeichert und im Hintergrund verarbeitet: Text wird extrahiert (OCR-Fallback fuer gescannte Dokumente) und nach Deutsch und Englisch uebersetzt. Sie erscheint danach in Ihrer Quellenliste.
|
|
</p>
|
|
<div class="form-group">
|
|
<label for="pdf-upload-file">PDF-Datei (max. 50 MB)</label>
|
|
<input type="file" id="pdf-upload-file" accept="application/pdf,.pdf" required>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="pdf-upload-name">Anzeige-Name (optional)</label>
|
|
<input type="text" id="pdf-upload-name" maxlength="200" placeholder="leer = Dateiname">
|
|
</div>
|
|
<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;">
|
|
<div class="form-group">
|
|
<label for="pdf-upload-category">Kategorie</label>
|
|
<select id="pdf-upload-category">
|
|
<option value="sonstige" selected>Sonstige</option>
|
|
<option value="behoerde">Behoerde</option>
|
|
<option value="think-tank">Think-Tank</option>
|
|
<option value="fachmedien">Fachmedien</option>
|
|
<option value="international">International</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="pdf-upload-language">Sprache (optional)</label>
|
|
<input type="text" id="pdf-upload-language" placeholder="z.B. Deutsch, Englisch">
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="pdf-upload-notes">Notizen</label>
|
|
<input type="text" id="pdf-upload-notes" placeholder="Optional">
|
|
</div>
|
|
<div id="pdf-upload-error" class="error-msg" style="display:none"></div>
|
|
<div id="pdf-upload-progress" class="text-secondary" style="display:none;margin-top:8px;">Laedt hoch …</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" onclick="closeModal('modal-pdf-upload')">Abbrechen</button>
|
|
<button type="submit" class="btn btn-primary" id="pdf-upload-submit">Hochladen</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal: Content-Viewer (wiederverwendbar für Lagebild, Faktencheck, Quellenübersicht, Timeline) -->
|
|
<div class="modal-overlay" id="modal-content-viewer" role="dialog" aria-modal="true" aria-labelledby="content-viewer-title">
|
|
<div class="modal modal-content-viewer">
|
|
<div class="modal-header">
|
|
<div class="modal-title" id="content-viewer-title"></div>
|
|
<div class="modal-header-extra" id="content-viewer-header-extra"></div>
|
|
<button class="modal-close" onclick="closeModal('modal-content-viewer')" aria-label="Schließen">×</button>
|
|
</div>
|
|
<div class="modal-body" id="content-viewer-body"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal: Feedback -->
|
|
<div class="modal-overlay" id="modal-feedback" role="dialog" aria-modal="true" aria-labelledby="modal-feedback-title">
|
|
<div class="modal">
|
|
<div class="modal-header">
|
|
<div class="modal-title" id="modal-feedback-title">Feedback senden</div>
|
|
<button class="modal-close" onclick="closeModal('modal-feedback')" aria-label="Schließen">×</button>
|
|
</div>
|
|
<form id="feedback-form">
|
|
<div class="modal-body">
|
|
<div class="form-group">
|
|
<label for="fb-category">Kategorie</label>
|
|
<select id="fb-category">
|
|
<option value="bug">Fehlerbericht</option>
|
|
<option value="feature">Feature-Wunsch</option>
|
|
<option value="question">Frage</option>
|
|
<option value="other">Sonstiges</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="fb-message">Nachricht</label>
|
|
<textarea id="fb-message" required aria-required="true" minlength="10" maxlength="5000" rows="6" placeholder="Beschreibe dein Anliegen (mind. 10 Zeichen)..."></textarea>
|
|
<div class="form-hint"><span id="fb-char-count">0</span> / 5.000 Zeichen</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="fb-files">Bilder anhaengen (optional)</label>
|
|
<input type="file" id="fb-files" accept="image/jpeg,image/png" multiple style="font-size:13px;">
|
|
<div class="form-hint">Max. 3 Bilder (JPEG/PNG, je max. 5 MB)</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" onclick="closeModal('modal-feedback')">Abbrechen</button>
|
|
<button type="submit" class="btn btn-primary" id="fb-submit-btn">Absenden</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Chat-Assistent Widget -->
|
|
<button class="chat-toggle-btn" id="chat-toggle-btn" title="Chat-Assistent" aria-label="Chat-Assistent oeffnen" data-i18n-attr="title:chat.toggle_title,aria-label:chat.toggle_aria">
|
|
<svg viewBox="0 0 24 24"><path d="M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 14H5.2L4 17.2V4h16v12z"/></svg>
|
|
</button>
|
|
<div class="chat-window" id="chat-window">
|
|
<div class="chat-header">
|
|
<span class="chat-header-title" data-i18n="chat.title">AegisSight Assistent</span>
|
|
<div class="chat-header-actions">
|
|
<button class="chat-header-btn chat-reset-btn" id="chat-reset-btn" title="Neuer Chat" aria-label="Neuen Chat starten" style="display:none" data-i18n-attr="title:chat.new_title,aria-label:chat.new_aria">
|
|
<svg viewBox="0 0 24 24" width="15" height="15"><path d="M17.65 6.35A7.958 7.958 0 0012 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08A5.99 5.99 0 0112 18c-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z" fill="currentColor"/></svg>
|
|
</button>
|
|
<button class="chat-header-btn" id="chat-fullscreen-btn" title="Vollbild" aria-label="Vollbild umschalten" data-i18n-attr="title:chat.fullscreen_title,aria-label:chat.fullscreen_aria">
|
|
<svg viewBox="0 0 24 24" width="15" height="15"><path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z" fill="currentColor"/></svg>
|
|
</button>
|
|
<button class="chat-header-btn chat-header-close" id="chat-close-btn" title="Schließen" aria-label="Chat schließen" data-i18n-attr="title:chat.close_title,aria-label:chat.close_aria">×</button>
|
|
</div>
|
|
</div>
|
|
<div class="chat-messages" id="chat-messages"></div>
|
|
<form class="chat-input-area" id="chat-form" autocomplete="off">
|
|
<textarea id="chat-input" rows="1" placeholder="Frage stellen..." maxlength="2000" data-i18n-attr="placeholder:chat.input_placeholder"></textarea>
|
|
<button type="submit" class="chat-send-btn" title="Senden" aria-label="Nachricht senden" data-i18n-attr="title:chat.send_title,aria-label:chat.send_aria">
|
|
<svg viewBox="0 0 24 24"><path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"/></svg>
|
|
</button>
|
|
</form>
|
|
</div>
|
|
|
|
|
|
<!-- Modal: Neue Netzwerkanalyse -->
|
|
<!-- Tutorial -->
|
|
<div class="tutorial-overlay" id="tutorial-overlay">
|
|
<div class="tutorial-spotlight" id="tutorial-spotlight"></div>
|
|
</div>
|
|
<div class="tutorial-bubble" id="tutorial-bubble"></div>
|
|
<div class="tutorial-cursor" id="tutorial-cursor"></div>
|
|
|
|
<!-- Toast Container -->
|
|
<div class="toast-container" id="toast-container" aria-live="polite" aria-atomic="true"></div>
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/d3@7/dist/d3.min.js"></script>
|
|
<script src="/static/vendor/leaflet.js"></script>
|
|
<script src="/static/vendor/leaflet.markercluster.js"></script>
|
|
<script src="/static/js/i18n.js?v=20260513a"></script>
|
|
<script src="/static/js/api.js?v=20260725b"></script>
|
|
<script src="/static/js/ws.js?v=20260316b"></script>
|
|
<script src="/static/js/components.js?v=20260802c"></script>
|
|
<script src="/static/js/layout.js?v=20260513f"></script>
|
|
<script src="/static/js/pipeline.js?v=20260513d"></script>
|
|
<script src="/static/js/a11y.js?v=20260725a"></script>
|
|
<script src="/static/js/app.js?v=20260802c"></script>
|
|
<script src="/static/js/cluster-data.js?v=20260322f"></script>
|
|
<script src="/static/js/tutorial.js?v=20260316z"></script>
|
|
<script src="/static/js/chat.js?v=20260514e"></script>
|
|
<script>document.addEventListener("DOMContentLoaded",function(){Chat.init();/* Tutorial.init() wird in App.init() nach Sprachwahl aufgerufen, damit es bei englischen Orgs unterdrueckt werden kann */});</script>
|
|
|
|
<!-- Map Fullscreen Overlay -->
|
|
<div class="map-fullscreen-overlay" id="map-fullscreen-overlay">
|
|
<div class="map-fullscreen-header">
|
|
<div class="map-fullscreen-title" data-i18n="card.map">Geografische Verteilung</div>
|
|
<span class="map-stats map-fullscreen-stats" id="map-fullscreen-stats"></span>
|
|
<button class="btn btn-secondary btn-small" onclick="UI.toggleMapFullscreen()" title="Vollbild beenden" aria-label="Vollbild beenden">
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 14 10 14 10 20"/><polyline points="20 10 14 10 14 4"/><line x1="14" y1="10" x2="21" y2="3"/><line x1="3" y1="21" x2="10" y2="14"/></svg>
|
|
</button>
|
|
</div>
|
|
<div class="map-fullscreen-container" id="map-fullscreen-container"></div>
|
|
</div>
|
|
|
|
|
|
|
|
<!-- Export Modal -->
|
|
<div class="modal-overlay" id="modal-export" role="dialog" aria-modal="true">
|
|
<div class="modal" style="max-width:420px;">
|
|
<div class="modal-header">
|
|
<h3 data-i18n="modal.export.title">Bericht exportieren</h3>
|
|
<button class="modal-close" onclick="closeModal('modal-export')" aria-label="Schließen" data-i18n-attr="aria-label:aria.close">×</button>
|
|
</div>
|
|
<div class="modal-body" style="padding:20px;">
|
|
<div style="margin-bottom:16px;">
|
|
<label style="font-size:11px;text-transform:uppercase;letter-spacing:1px;color:var(--text-secondary);display:block;margin-bottom:8px;" data-i18n="export.sections">Bereiche</label>
|
|
<label class="export-radio"><input type="checkbox" name="export-section" value="zusammenfassung" checked><span data-i18n="export.section.summary">Zusammenfassung</span></label>
|
|
<label class="export-radio"><input type="checkbox" name="export-section" value="bericht" checked><span data-i18n="export.section.report">Recherchebericht / Lagebild</span></label>
|
|
<label class="export-radio"><input type="checkbox" name="export-section" value="faktencheck" checked><span data-i18n="export.section.factcheck">Faktencheck</span></label>
|
|
<label class="export-radio"><input type="checkbox" name="export-section" value="quellen" checked><span data-i18n="export.section.sources">Quellen</span></label>
|
|
</div>
|
|
<div style="margin-bottom:16px;">
|
|
<label style="font-size:11px;text-transform:uppercase;letter-spacing:1px;color:var(--text-secondary);display:block;margin-bottom:8px;" data-i18n="export.format">Format</label>
|
|
<label class="export-radio"><input type="radio" name="export-format" value="pdf" checked><span>PDF</span></label>
|
|
<label class="export-radio"><input type="radio" name="export-format" value="docx"><span data-i18n="export.format.docx">Word (DOCX)</span></label>
|
|
</div>
|
|
<div style="margin-bottom:16px;">
|
|
<label style="font-size:11px;text-transform:uppercase;letter-spacing:1px;color:var(--text-secondary);display:block;margin-bottom:8px;" data-i18n="export.branding">Branding</label>
|
|
<label class="export-radio"><input type="radio" name="export-branding" value="on" checked><span data-i18n="export.branding.on">Mit AegisSight-Branding</span></label>
|
|
<label class="export-radio"><input type="radio" name="export-branding" value="off"><span data-i18n="export.branding.off">Ohne Firmen-Branding</span></label>
|
|
</div>
|
|
<div style="margin-bottom:0;">
|
|
<label for="export-ersteller" style="font-size:11px;text-transform:uppercase;letter-spacing:1px;color:var(--text-secondary);display:block;margin-bottom:8px;">Ersteller</label>
|
|
<input type="text" id="export-ersteller" maxlength="120" placeholder="Name des Erstellers (optional)" style="width:100%;box-sizing:border-box;">
|
|
<div style="font-size:11px;color:var(--text-secondary);margin-top:6px;">Leer lassen, dann wird automatisch der Lage-Ersteller verwendet.</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer" style="padding:12px 20px;display:flex;justify-content:flex-end;gap:8px;border-top:1px solid var(--border);">
|
|
<button class="btn btn-secondary" onclick="closeModal('modal-export')" data-i18n="common.cancel">Abbrechen</button>
|
|
<button class="btn btn-primary" id="export-submit-btn" onclick="App.submitExport()" data-i18n="export.submit">Exportieren</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<!-- Fortschritts-Popup -->
|
|
<div class="progress-overlay" id="progress-overlay" style="display:none;">
|
|
<div class="progress-popup" id="progress-popup">
|
|
<div class="progress-popup-header">
|
|
<span class="progress-popup-title" id="progress-popup-title" data-i18n="progress.title.refresh">Aktualisierung läuft</span>
|
|
<span class="progress-popup-timer" id="progress-popup-timer"></span>
|
|
<button class="progress-popup-minimize" id="progress-popup-minimize" style="display:none;" onclick="App.minimizeProgress()" title="Minimieren">−</button>
|
|
</div>
|
|
<div class="progress-popup-body">
|
|
<div class="progress-popup-pass" id="progress-popup-pass" style="display:none;"></div>
|
|
<div class="pipeline-mini" id="progress-pipeline-mini" aria-label="Analyseschritte"></div>
|
|
<div class="progress-checklist" id="progress-checklist" style="display:none;">
|
|
<div class="progress-check-item" data-step="queued">
|
|
<span class="progress-check-icon">○</span>
|
|
<span class="progress-check-label" data-i18n="progress.title.queued">In Warteschlange</span>
|
|
<span class="progress-check-detail"></span>
|
|
</div>
|
|
<div class="progress-check-item" data-step="researching">
|
|
<span class="progress-check-icon">○</span>
|
|
<span class="progress-check-label" data-i18n="progress.check.researching">Quellen werden durchsucht</span>
|
|
<span class="progress-check-detail"></span>
|
|
</div>
|
|
<div class="progress-check-item" data-step="analyzing">
|
|
<span class="progress-check-icon">○</span>
|
|
<span class="progress-check-label" data-i18n="progress.check.analyzing">Meldungen werden analysiert</span>
|
|
<span class="progress-check-detail"></span>
|
|
</div>
|
|
<div class="progress-check-item" data-step="factchecking">
|
|
<span class="progress-check-icon">○</span>
|
|
<span class="progress-check-label" data-i18n="progress.factcheck_running">Faktencheck läuft</span>
|
|
<span class="progress-check-detail"></span>
|
|
</div>
|
|
</div>
|
|
<div class="progress-complete-summary" id="progress-complete-summary" style="display:none;"></div>
|
|
</div>
|
|
<div class="progress-popup-footer">
|
|
<button class="progress-cancel-btn" id="progress-cancel-btn" onclick="App.cancelRefresh()">Abbrechen</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="/static/js/update-system.js"></script>
|
|
<script src="/static/js/ai-disclaimer.js"></script>
|
|
</body>
|
|
</html>
|