Lage-Auswahl im Header + dynamischer Monitor-Feed

Dropdown in der Top-Leiste zeigt alle oeffentlichen Lagen.
[L] = Live-Monitoring, [R] = Recherche.
Immer nur eine Lage aktiv. Bei Auswahl:
- OSINT Monitor Layer zeigt nur Daten dieser Lage
- Klick auf Katastrophen zeigt Summary dieser Lage
- Sidebar zeigt Punkte dieser Lage
Ohne Auswahl: kein Monitor-Overlay.
Dieser Commit ist enthalten in:
Claude Dev
2026-03-24 13:30:52 +01:00
Ursprung 65a30e0d06
Commit 0944b12e2d
5 geänderte Dateien mit 98 neuen und 4 gelöschten Zeilen

Datei anzeigen

@@ -412,3 +412,24 @@ html, body { height: 100%; overflow: hidden; background: var(--bg-primary); colo
font-size: 11px;
color: var(--text-dim);
}
/* === Lage-Selector === */
.header-lage { display: flex; align-items: center; }
.lage-select {
background: rgba(255,255,255,0.05);
border: 1px solid var(--border);
border-radius: 4px;
color: var(--accent);
font-family: var(--font-mono);
font-size: 11px;
padding: 4px 8px;
cursor: pointer;
max-width: 300px;
outline: none;
}
.lage-select:hover { border-color: var(--accent); }
.lage-select option {
background: var(--bg-primary);
color: var(--text);
}

Datei anzeigen

@@ -34,7 +34,7 @@
</svg>
<span class="header-title">AegisSight Globe</span>
</div>
<div class="header-stats" id="header-stats"></div>
<div class="header-lage"><select id="lage-select" class="lage-select" onchange="Globe._onLageChange(this.value)"><option value="">-- Lage waehlen --</option></select></div><div class="header-stats" id="header-stats"></div>
<div class="header-actions">
<button class="header-btn" id="btn-fullscreen" title="Vollbild">
<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2"><polyline points="15 3 21 3 21 9"/><polyline points="9 21 3 21 3 15"/><line x1="21" y1="3" x2="14" y2="10"/><line x1="3" y1="21" x2="10" y2="14"/></svg>

Datei anzeigen

@@ -5,6 +5,7 @@ const Globe = {
viewer: null,
layers: {},
_statsInterval: null,
_currentLageId: null,
_labelsLayer: null,
init() {
@@ -83,6 +84,7 @@ const Globe = {
this._toggleLabels(true);
if (typeof VisualModes !== 'undefined') VisualModes.init();
if (typeof Sidebar !== 'undefined') Sidebar.init();
this._loadLagen();
document.getElementById('bottom-stats').textContent = 'Globe initialisiert — Lade Daten...';
},
@@ -107,6 +109,35 @@ const Globe = {
}
},
_loadLagen() {
var select = document.getElementById('lage-select');
if (!select) return;
fetch('/api/monitor-incidents')
.then(function(r) { return r.json(); })
.then(function(lagen) {
var html = '<option value="">-- Lage waehlen --</option>';
(lagen || []).forEach(function(l) {
var typeLabel = l.type === 'research' ? '[R] ' : '[L] ';
html += '<option value="' + l.id + '">' + typeLabel + l.title + '</option>';
});
select.innerHTML = html;
})
.catch(function() {});
},
_onLageChange(lageId) {
this._currentLageId = lageId ? parseInt(lageId) : null;
// Monitor-Layer aktualisieren wenn aktiv
if (typeof MonitorLayer !== 'undefined' && MonitorLayer._points) {
MonitorLayer._data = [];
MonitorLayer._incidents = [];
MonitorLayer._render();
if (lageId) MonitorLayer._fetchForLage(lageId);
}
// Sidebar aktualisieren
if (typeof Sidebar !== 'undefined') Sidebar.update();
},
_setupLayerToggles() {
var toggles = {
'layer-monitor': function(on) { on ? MonitorLayer.start(Globe.viewer) : MonitorLayer.stop(); },

Datei anzeigen

@@ -120,13 +120,34 @@ const MonitorLayer = {
});
},
_fetchForLage(lageId) {
var self = this;
var loadEl = document.getElementById('loading-monitor');
var statusEl = document.getElementById('status-monitor');
if (loadEl) loadEl.classList.add('active');
if (statusEl) { statusEl.textContent = 'Lade Lage-Daten...'; statusEl.classList.add('active'); }
fetch('/api/monitor-feed?incident_id=' + lageId)
.then(function(r) { return r.json(); })
.then(function(data) {
self._data = data.features || [];
self._incidents = data.incidents || [];
self._count = self._data.length;
self._render();
var title = self._incidents.length ? self._incidents[0].title : '';
if (statusEl) statusEl.textContent = self._count + ' Orte' + (title ? ' (' + title + ')' : '');
})
.catch(function(e) { console.warn('Monitor error:', e); if (statusEl) statusEl.textContent = 'Fehler'; })
.finally(function() { if (loadEl) loadEl.classList.remove('active'); setTimeout(function() { if (statusEl) statusEl.classList.remove('active'); }, 8000); });
},
_fetch() {
var self = this;
var loadEl = document.getElementById('loading-monitor');
var statusEl = document.getElementById('status-monitor');
if (loadEl) loadEl.classList.add('active');
if (statusEl) { statusEl.textContent = 'Lade Monitor-Daten...'; statusEl.classList.add('active'); }
fetch('/api/monitor-feed')
var lageId = (typeof Globe !== 'undefined' && Globe._currentLageId) ? Globe._currentLageId : '';
fetch('/api/monitor-feed' + (lageId ? '?incident_id=' + lageId : ''))
.then(function(r) { return r.json(); })
.then(function(data) {
self._data = data.features || [];