# Dashboard-Verbesserungen – Übersicht (v0.06.02 – v0.06.07) Alle Änderungen wurden in der Session vom 2026-02-17 durchgeführt. --- ## Prio 1 – Shared `app.js` Modul (v0.06.02) **Problem:** ~360 doppelte Zeilen identischer Boilerplate-Code in allen 6 JS-Dateien (`applyTheme`, `updateNavbar`, `updateSidebar`, `escapeHtml`, Sidebar-HTML). **Lösung:** `static/js/app.js` als gemeinsames Modul: - `initPage({ onAuth })` – Auth-Check, Navbar, Sidebar, Theme, Toggle in einem Aufruf - `applyTheme(theme)` – setzt `data-bs-theme`, Icon, LocalStorage + dispatcht `themechange` CustomEvent - `escapeHtml(str)` – XSS-sichere HTML-Escape-Funktion - Sidebar wird dynamisch per `innerHTML` injiziert; aktiver Link über `window.location.pathname` **Dateien:** `static/js/app.js` (neu), alle 5 Seiten-JS-Dateien bereinigt --- ## Prio 2 – WebSocket Auth-Fix (v0.06.02) **Problem:** `initial_messages` und `new_message` WS-Events wurden an alle Clients gesendet, auch nicht eingeloggte. **Lösung:** `meshbot/webserver.py`: - `WebSocketManager` bekommt `auth_clients: set` zusätzlich zu `clients` - `broadcast_auth()` sendet nur an authentifizierte Clients - `_ws_handler`: eingeloggte User werden zu `auth_clients` hinzugefügt; `initial_messages` nur für diese - Bot nutzt `broadcast_auth("new_message", ...)` statt `broadcast` --- ## Prio 3 – Bot-Uptime & Meshtastic-Status (v0.06.04) **Problem:** Uptime nur per `?uptime`-Kommando abrufbar; kein Indikator ob Bot mit Meshtastic verbunden. **Lösung:** - `meshbot/bot.py`: `_connected`-Flag, `pubsub`-Subscription auf `meshtastic.connection.lost`, `get_uptime()`, `_broadcast_bot_status()` - `meshbot/webserver.py`: `_api_stats` liefert `uptime` + `bot_connected`; WS sendet `bot_status`-Event - Dashboard: 4. Info-Box "Uptime", zweiter Status-Dot `#meshDot` / `#meshText` in der Navbar --- ## Prio 4 – Dark Mode Kartentiles (v0.06.05) **Problem:** OpenStreetMap-Kacheln sind immer hell – passt nicht zum Dark Theme. **Lösung:** - `app.js:applyTheme()` dispatcht `themechange` CustomEvent auf `document` - `map.js`: `getTileLayer(theme)` liefert CartoDB Dark Matter (dark) oder OSM (light); `setMapTheme()` tauscht Layer live - `dashboard.js`: Node-Detail-Modal-Karte reagiert ebenfalls auf `themechange` **Dark-Tile-URL:** `https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png` --- ## Prio 5 – Charts (v0.06.05) **Bibliothek:** Chart.js 4.4.4 (CDN in `index.html`) **3 neue Charts im Dashboard:** | Chart | Typ | Datenquelle | |-------|-----|-------------| | Kanal-Anfragen | Doughnut | `stats.channel_breakdown` (WS) | | Hop-Verteilung | Balken | `nodes`-Objekt (client-seitig) | | Hardware Top 5 | Horizontalbalken | `nodes`-Objekt (client-seitig) | **Besonderheiten:** - Charts reagieren via `themechange`-Event auf Dark/Light-Wechsel (`Chart.defaults.color`) - `initCharts()` beim Seitenstart, `updateChannelChart()` bei `stats_update`, `updateNodeCharts()` bei `renderNodes()` --- ## Prio 6 – Nodes-Tabelle Interaktivität (v0.06.05) **Neue Features in `dashboard.js` + `index.html`:** - **Suchfeld** `#nodeSearch`: filtert `long_name`, `short_name`, `hw_model`, `node_id` - **Online-Filter** `#btnOnlineOnly`: zeigt nur Nodes mit `last_seen < 15 min` - **Sortierung**: Klick auf `` sortiert auf-/absteigend, Icon-Feedback per `bi-sort-down` / `bi-sort-up` - Standardsortierung: `last_seen` absteigend --- ## Prio 7 – Nachrichten Kanalfilter (v0.06.06) **Neue Features in `dashboard.js` + `index.html`:** - Filter-Buttons im Nachrichten-Card-Header: „Alle" + ein Button pro Kanal - Buttons werden aus dem `channels`-Objekt dynamisch befüllt (nach Kanalindex sortiert) - Jedes `.msg-item` erhält `data-channel`-Attribut - `applyMsgFilter()` setzt/entfernt `d-none` auf Basis des aktiven Filters - Neue Nachrichten werden sofort gefiltert; `initial_messages` werden nach dem Laden gefiltert - `bar.onclick` statt `addEventListener` verhindert Listener-Akkumulation bei Channel-Updates --- ## Extra – Tabler 1.4.0 Admin-Theme (v0.06.07) **Motivation:** Eleganteres, professionelleres Erscheinungsbild. **Änderungen:** - Bootstrap CSS/JS in allen 6 HTML-Dateien ersetzt durch `@tabler/core@1.4.0` (bündelt Bootstrap intern) - `` auf allen Seiten für subpixel-glattes Inter-Font-Rendering - `static/css/style.css` komplett überarbeitet: | Bereich | Vorher | Nachher | |---------|--------|---------| | Font | System-Font | Inter (via Tabler automatisch) | | Sidebar-Links | Linker Rand-Indikator | Rounded Highlight (Tabler-Stil) | | Cards | Kein Schatten | Subtiler Box-Shadow | | Info-Boxen | Statisch | Hover-Animation (translateY + Shadow) | | Status-Dot | Einfacher Glow | Pulsierender Keyframe-Ring | | Navbar | Nur Border | Shadow + Tabler-Variablen | | Navbar-Höhe | 46 px | 48 px | | Sidebar-Breite | 200 px | 210 px | **Tabler CSS-Variablen** (`--tblr-*`) mit Bootstrap-Fallback (`var(--tblr-x, var(--bs-x))`) für maximale Kompatibilität. --- ## Noch offen | # | Feature | Aufwand | |---|---------|---------| | Prio 8 | `/api/stats/history` – Backend + Zeitverlauf-Liniendiagramm (Nachrichten/Stunde) | mittel | | Klein | Favicon auf allen Seiten | sehr klein | | Klein | Nachrichten >24h: Datum statt nur Uhrzeit | sehr klein | | Klein | Channel-Breakdown Fallback-Text wenn leer | sehr klein | | Klein | CLAUDE.md Versionsfeld aktualisieren | sehr klein | | Klein | Scheduler: „Nächster Lauf"-Zeitstempel | mittel |