Dashboard: GridStack durch Tab-Navigation ersetzen

Der Monitor-Dashboard zeigte bisher alle sechs Kacheln gleichzeitig in
einem GridStack-Layout (Drag/Resize, je Kachel eigenes Scrolling). Nutzer-
wunsch: Analog zur Lagebild-Seite nur ein Tab-Panel gleichzeitig, maximiert
auf volle Breite, Seiten-Scroll statt interne Scrollbars.

Aenderungen:
- dashboard.html: Layout-Toolbar + grid-stack-Wrapper entfernt; neue tab-nav
  mit 6 Buttons + tab-panels mit 6 Panels. GridStack CDN-Links raus.
- layout.js: GridStack-Init/toggleTile/reset komplett entfernt. Neu:
  switchTab(tabId) + restoreTabFor(incidentId) mit localStorage-Persistenz
  pro Lage osint_tab_id. applyTypeLabels fuer adhoc vs. research. Legacy-
  Methoden sind No-Op-Stubs.
- app.js: renderIncidentDetail ruft LayoutManager.restoreTabFor und
  applyTypeLabels auf. openContentModal-Trigger aus Card-Titeln raus.
  Tile-Resize-Bloecke fuer Quellen und Timeline entfernt.
- components.js: Telegram-Pills bekommen Suffix Telegram-Link, wenn die
  URL auf t.me verweist.
- style.css: grid-stack/layout-toggle Klassen raus; neue tab-nav/tab-btn/
  tab-panel Klassen. Internes Scrolling entfernt. map-container 600px.

Alte osint_layout-Eintraege werden ignoriert.
Dieser Commit ist enthalten in:
claude-dev
2026-04-18 22:34:36 +00:00
Ursprung 3b9e9e25c2
Commit e15ed0c21e
5 geänderte Dateien mit 206 neuen und 571 gelöschten Zeilen

Datei anzeigen

@@ -335,7 +335,7 @@ const UI = {
if (state.isFirst) {
overlay.classList.add('blocking');
// Apply blur to grid
const grid = document.querySelector('.grid-stack');
const grid = document.querySelector('.tab-panels');
if (grid) grid.classList.add('blurred');
} else {
overlay.classList.remove('blocking');
@@ -465,7 +465,7 @@ const UI = {
if (incidentId === App.currentIncidentId) {
// Remove blur
const grid = document.querySelector('.grid-stack');
const grid = document.querySelector('.tab-panels');
if (grid) grid.classList.remove('blurred');
const overlay = document.getElementById('progress-overlay');
@@ -559,7 +559,7 @@ const UI = {
if (!incidentId) incidentId = App.currentIncidentId;
// Remove blur
const grid = document.querySelector('.grid-stack');
const grid = document.querySelector('.tab-panels');
if (grid) grid.classList.remove('blurred');
if (incidentId === App.currentIncidentId) {
@@ -787,11 +787,15 @@ const UI = {
const buildPill = (src, fallbackName) => {
const displayName = src ? (src.name || fallbackName) : fallbackName;
const esc = this.escape(displayName);
const url = (src && src.url) || '';
const isTelegram = /^https?:\/\/t\.me\//i.test(url);
const label = isTelegram ? displayName + ' (Telegram-Link)' : displayName;
const esc = this.escape(label);
const titleEsc = this.escape(displayName);
if (src && src.url) {
return `<a href="${this.escape(src.url)}" target="_blank" rel="noopener" class="dev-source-pill" title="${esc}">${esc}</a>`;
return `<a href="${this.escape(src.url)}" target="_blank" rel="noopener" class="dev-source-pill" title="${titleEsc}">${esc}</a>`;
}
return `<span class="dev-source-pill" title="${esc}">${esc}</span>`;
return `<span class="dev-source-pill" title="${titleEsc}">${esc}</span>`;
};
const cards = bulletLines.map(line => {