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:
@@ -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
171
static/js/ui/sidebar.js
Normale Datei
@@ -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 + '">▾</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 + '">▾</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
|
||||
},
|
||||
};
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren