Rechte Sidebar + Monitor-Feed nur Naturkatastrophen

SIDEBAR (neu):
- Aufklappbare Uebersicht aller aktiven Datenpunkte rechts
- Suchfeld filtert alle Eintraege
- Sektionen: OSINT Monitor, Katastrophen (auffaecherbar)
- Flug/Schiff/Satelliten als Zaehler
- Klick auf Eintrag fliegt zur Position
- Ein-/ausklappbar per Pfeil-Button am rechten Rand

MONITOR-FEED FIX:
- Nur Lage 45 (Naturkatastrophen international) wird abgefragt
- Keine anderen Lagen mehr im Globe sichtbar
Dieser Commit ist enthalten in:
Claude Dev
2026-03-24 13:29:43 +01:00
Ursprung 27516b1a8a
Commit 65a30e0d06
5 geänderte Dateien mit 347 neuen und 2 gelöschten Zeilen

Datei anzeigen

@@ -82,6 +82,7 @@ const Globe = {
this._toggleLabels(true);
if (typeof VisualModes !== 'undefined') VisualModes.init();
if (typeof Sidebar !== 'undefined') Sidebar.init();
document.getElementById('bottom-stats').textContent = 'Globe initialisiert — Lade Daten...';
},

171
static/js/ui/sidebar.js Normale Datei
Datei anzeigen

@@ -0,0 +1,171 @@
/**
* Rechte Sidebar: Uebersicht aller aktiven Datenpunkte mit Suche.
*/
const Sidebar = {
_open: true,
_searchTerm: '',
init() {
var self = this;
var toggle = document.getElementById('sidebar-toggle');
var search = document.getElementById('sidebar-search');
if (toggle) toggle.addEventListener('click', function() { self.toggle(); });
if (search) search.addEventListener('input', function() {
self._searchTerm = this.value.toLowerCase();
self.update();
});
// Periodisch aktualisieren
setInterval(function() { self.update(); }, 5000);
},
toggle() {
this._open = !this._open;
var panel = document.getElementById('sidebar-right');
var toggle = document.getElementById('sidebar-toggle');
if (panel) panel.classList.toggle('collapsed', !this._open);
if (toggle) toggle.innerHTML = this._open
? '<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2"><polyline points="9 18 15 12 9 6"/></svg>'
: '<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2"><polyline points="15 18 9 12 15 6"/></svg>';
},
update() {
var container = document.getElementById('sidebar-content');
if (!container) return;
var html = '';
var term = this._searchTerm;
// Monitor OSINT
if (typeof MonitorLayer !== 'undefined' && MonitorLayer._data.length) {
html += this._renderSection('monitor', 'OSINT Monitor', MonitorLayer._data, function(f) {
var p = f.properties;
return {
name: p.name || '?',
sub: (p.incident_title || '') + (p.article_count > 1 ? ' (' + p.article_count + ' Artikel)' : ''),
color: { primary: '#ff2222', secondary: '#ff8800', tertiary: '#4499ff', mentioned: '#888' }[p.category] || '#888',
lat: f.geometry.coordinates[1],
lon: f.geometry.coordinates[0],
};
}, term);
}
// Katastrophen
if (typeof DisastersLayer !== 'undefined' && DisastersLayer._dataSource && DisastersLayer._count > 0) {
var entities = DisastersLayer._dataSource.entities.values;
var items = [];
for (var i = 0; i < entities.length; i++) {
var e = entities[i];
var name = e.name || (e._name && e._name.getValue ? e._name.getValue() : '');
if (!name && e.description) {
var match = e.description.getValue().match(/<strong[^>]*>([^<]+)<\/strong>/);
if (match) name = match[1];
}
var pos = e.position ? e.position.getValue(Cesium.JulianDate.now()) : null;
var carto = pos ? Cesium.Cartographic.fromCartesian(pos) : null;
items.push({
name: name || 'Ereignis',
sub: '',
color: '#ff4400',
lat: carto ? Cesium.Math.toDegrees(carto.latitude) : 0,
lon: carto ? Cesium.Math.toDegrees(carto.longitude) : 0,
entity: e,
});
}
html += this._renderEntitySection('disasters', 'Katastrophen + Erdbeben', items, term);
}
// Flugverkehr (nur count, keine Liste — zu viele)
if (typeof FlightsLayer !== 'undefined' && FlightsLayer._count > 0) {
html += this._renderCountSection('flights', 'Flugverkehr', FlightsLayer._count, '#00ff88');
}
// Schiffsverkehr
if (typeof ShipsLayer !== 'undefined' && ShipsLayer._count > 0) {
html += this._renderCountSection('ships', 'Schiffsverkehr', ShipsLayer._count, '#4499ff');
}
// Satelliten
if (typeof SatellitesLayer !== 'undefined' && SatellitesLayer._count > 0) {
html += this._renderCountSection('satellites', 'Satelliten', SatellitesLayer._count, '#ff4444');
}
if (!html) {
html = '<div class="sb-empty">Keine Layer aktiv</div>';
}
container.innerHTML = html;
this._attachListeners();
},
_renderSection(id, title, features, mapFn, term) {
var items = features.map(mapFn).filter(function(item) {
if (!term) return true;
return (item.name + ' ' + item.sub).toLowerCase().indexOf(term) >= 0;
});
if (!items.length) return '';
return '<div class="sb-section" id="sb-' + id + '">' +
'<div class="sb-header" onclick="Sidebar._toggleSection(\'' + id + '\')">' +
'<span class="sb-chevron" id="sb-chev-' + id + '">&#9662;</span>' +
'<span class="sb-title">' + title + '</span>' +
'<span class="sb-badge">' + items.length + '</span></div>' +
'<div class="sb-list" id="sb-list-' + id + '">' +
items.slice(0, 100).map(function(item) {
return '<div class="sb-item" onclick="Sidebar._flyTo(' + item.lat + ',' + item.lon + ')" title="' + item.name + '">' +
'<span class="sb-dot" style="background:' + item.color + '"></span>' +
'<div class="sb-item-text"><div class="sb-item-name">' + item.name + '</div>' +
(item.sub ? '<div class="sb-item-sub">' + item.sub + '</div>' : '') +
'</div></div>';
}).join('') +
(items.length > 100 ? '<div class="sb-more">+ ' + (items.length - 100) + ' weitere</div>' : '') +
'</div></div>';
},
_renderEntitySection(id, title, items, term) {
if (term) {
items = items.filter(function(item) { return item.name.toLowerCase().indexOf(term) >= 0; });
}
if (!items.length) return '';
return '<div class="sb-section" id="sb-' + id + '">' +
'<div class="sb-header" onclick="Sidebar._toggleSection(\'' + id + '\')">' +
'<span class="sb-chevron" id="sb-chev-' + id + '">&#9662;</span>' +
'<span class="sb-title">' + title + '</span>' +
'<span class="sb-badge">' + items.length + '</span></div>' +
'<div class="sb-list" id="sb-list-' + id + '">' +
items.slice(0, 100).map(function(item, idx) {
return '<div class="sb-item" onclick="Sidebar._flyTo(' + item.lat + ',' + item.lon + ')" title="' + item.name + '">' +
'<span class="sb-dot" style="background:' + item.color + '"></span>' +
'<div class="sb-item-text"><div class="sb-item-name">' + item.name + '</div></div></div>';
}).join('') +
'</div></div>';
},
_renderCountSection(id, title, count, color) {
return '<div class="sb-section">' +
'<div class="sb-header sb-header-count">' +
'<span class="sb-dot" style="background:' + color + '"></span>' +
'<span class="sb-title">' + title + '</span>' +
'<span class="sb-badge">' + count.toLocaleString('de-DE') + '</span></div></div>';
},
_toggleSection(id) {
var list = document.getElementById('sb-list-' + id);
var chev = document.getElementById('sb-chev-' + id);
if (list) {
var open = list.style.display !== 'none';
list.style.display = open ? 'none' : 'block';
if (chev) chev.style.transform = open ? 'rotate(-90deg)' : '';
}
},
_flyTo(lat, lon) {
if (typeof Globe !== 'undefined' && Globe.viewer) {
Globe.viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(lon, lat, 800000),
duration: 1.5,
});
}
},
_attachListeners() {
// Wird nach jedem Update aufgerufen
},
};