Topbar auf globalen Prüf-Timer reduziert, Aktionen+Beschreibung über Tabellen, sortierbare Listen
- Topbar zeigt rechts jetzt ausschließlich den "Nächste Prüfung"-Countdown, konsistent auf jeder Seite (auch anonymes Dashboard) statt nur auf dem Dashboard. Neuer Context-Processor inject_check_timer()/get_last_run_at() liefert last_run/interval global, ohne dass jede Route das selbst berechnen muss. - "+ Neu ..."-Buttons (Devices, Switches, Zugangsdaten, Benutzer, Gruppen) aus der Topbar entfernt und stattdessen in einen .section-head direkt über der jeweiligen Tabelle verschoben, zusammen mit einer kurzen Beschreibung der Seite (bisher nur bei Zugangsdaten/Gruppen vorhanden, jetzt auch bei Geräte/Switche/Benutzer). - Live-Log: eigene lokale Timer-Pill entfernt (redundant zum globalen Timer), "Aktualisieren"-Button in denselben section-head verschoben. Dashboard: Suchfeld aus der Topbar in den Seiteninhalt verschoben, lokale Timer-Anzeige entfernt (übernimmt die globale Topbar-Pill), Reload-bei- Intervallende-Logik bleibt als separater, unsichtbarer Scheduler erhalten. - Neue generische Tabellen-Sortierung (app.js: initSortableTables): Klick auf eine Spaltenüberschrift mit data-sort-key sortiert die Zeilen anhand von data-sort-<key>-Attributen. Unterstützt auch Akkordeon-Tabellen mit mehreren <tbody> (Gruppen: Haupt- + Detail-Zeile bleiben als Einheit zusammen, die virtuelle "Admin"-Zeile bleibt über data-sort-pinned immer oben). Angewendet auf Geräte, Switche, Zugangsdaten, Benutzer, Gruppen. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -2,15 +2,13 @@
|
||||
{% set active_page = "index" %}
|
||||
{% block page_title %}Dashboard{% endblock %}
|
||||
{% block page_sub %}<div class="topbar-sub">{{ device_count }} Geräte{{ " im Bestand" if current_user.is_authenticated else "" }}</div>{% endblock %}
|
||||
{% block topbar_right %}
|
||||
<div class="search-input" style="min-width:180px;">
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="search-input" style="max-width:320px; margin-bottom:18px;">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><circle cx="11" cy="11" r="7"/><path d="M21 21l-4.3-4.3"/></svg>
|
||||
<input type="text" id="tileSearch" placeholder="Gerät suchen…">
|
||||
</div>
|
||||
<span class="timer-pill"><span class="dot"></span><span id="dashboard-timer">Nächste Prüfung in --s</span></span>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="stat-row">
|
||||
<div class="stat-card">
|
||||
@@ -169,28 +167,27 @@
|
||||
{% block scripts %}
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
const intervalMinutes = {{ interval | int }};
|
||||
const intervalMinutes = {{ global_check_interval | int }};
|
||||
const intervalMilliseconds = intervalMinutes * 60 * 1000;
|
||||
const isAuthenticated = {{ "true" if current_user.is_authenticated else "false" }};
|
||||
// Vom Server ermittelter Zeitpunkt des letzten echten Prüf-Durchlaufs
|
||||
// (aus dem Logfile) — damit startet der Countdown nicht bei jedem
|
||||
// Seitenaufruf wieder von vorn, sondern zeigt die tatsächlich
|
||||
// verbleibende Zeit bis zur nächsten Prüfung durch poe.sh.
|
||||
const lastRunAt = {{ last_run_epoch_ms | tojson }};
|
||||
// verbleibende Zeit bis zur nächsten Prüfung durch poe.sh. Der
|
||||
// sichtbare Countdown selbst läuft global in der Topbar (app.js); hier
|
||||
// wird nur überwacht, wann ein neuer Durchlauf fertig ist, um die
|
||||
// Dashboard-Kacheln dann automatisch neu zu laden.
|
||||
const lastRunAt = {{ global_last_run_epoch_ms | tojson }};
|
||||
let lastUpdateTime = lastRunAt || Date.now();
|
||||
|
||||
function updateTimer() {
|
||||
function checkForReload() {
|
||||
const now = Date.now();
|
||||
const elapsed = now - lastUpdateTime;
|
||||
const remainingMs = intervalMilliseconds - (elapsed % intervalMilliseconds);
|
||||
const remainingSec = Math.ceil(remainingMs / 1000);
|
||||
const el = document.getElementById("dashboard-timer");
|
||||
if (el) el.innerText = `Nächste Prüfung in ${remainingSec}s`;
|
||||
if (remainingSec <= 1) window.location.reload();
|
||||
if (Math.ceil(remainingMs / 1000) <= 1) window.location.reload();
|
||||
}
|
||||
|
||||
setInterval(updateTimer, 1000);
|
||||
updateTimer();
|
||||
if (intervalMilliseconds) setInterval(checkForReload, 1000);
|
||||
|
||||
// Suchfilter über alle Abschnitte hinweg; Abschnitt wird komplett
|
||||
// ausgeblendet, wenn keine seiner Kacheln mehr passt.
|
||||
|
||||
Reference in New Issue
Block a user