Audit-Log, Import/Export, eigenes Profil & anpassbare Navigation
- Änderungslog: audit_log-Tabelle + last_modified_by/at an Devices und Switches; log_action()/touch_record() in allen Verwaltungsrouten (Devices, Switches, Zugangsdaten, Benutzer, Gruppen, Settings) verdrahtet. Neue Admin-Seite "Änderungslog" unter /logs/aenderungen. PoE-Neustarts werden bewusst nicht geloggt. - Verschlüsseltes Import/Export für Devices/Switches/Zugangsdaten unter Settings, passphrasenbasiert (PBKDF2 + Fernet), für Umzug auf neue Umgebungen. Referenziert Zugangsdaten/Switche über Name/Hostname statt interner ID für stabilen Re-Import. - Eigenes Profil: Klick auf den Namen in der Sidebar öffnet ein Modal zum Ändern von Vor-/Nachname, eigenem Passwort (mit Prüfung des aktuellen Passworts) und Profilbild-Upload (Anzeige in Sidebar + Änderungslog). - Anpassbare Navigation: Reihenfolge der Sidebar-Punkte ist unter Settings per Auf-/Ab-Buttons konfigurierbar (settings.nav_order); "Devices"/ "Users"/"Settings" umbenannt zu "Geräte"/"Benutzer"/"Einstellungen"; "Live-Log" und "Änderungslog" zu aufklappbarer "Logs"-Gruppe zusammengefasst. Jeder Benutzer sieht weiterhin nur, wofür er berechtigt ist. - create_db.py mit allen Schema-Erweiterungen synchronisiert (audit_log, last_modified_by/at, avatar_filename) für Frischinstallationen. - venv-Umgebung im WSL neu aufgesetzt (war fälschlich unter dem Erstellungspfad venv-linux verankert und daher nicht aktivierbar). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -168,6 +168,60 @@ button { font-family: inherit; }
|
||||
margin: 10px 8px;
|
||||
}
|
||||
|
||||
/* Nav-Gruppe mit Untermenü (z.B. "Logs" -> Live-Log / Änderungslog) */
|
||||
.nav-group-toggle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
width: 100%;
|
||||
padding: 10px 12px;
|
||||
border: none;
|
||||
background: none;
|
||||
color: var(--text-dim);
|
||||
font-weight: 550;
|
||||
font-size: 13.5px;
|
||||
font-family: inherit;
|
||||
border-radius: var(--radius-sm);
|
||||
cursor: pointer;
|
||||
transition: background 0.15s ease, color 0.15s ease;
|
||||
}
|
||||
.nav-group-toggle svg { width: 18px; height: 18px; flex-shrink: 0; opacity: 0.85; }
|
||||
.nav-group-toggle:hover { background: var(--bg-card-hover); color: var(--text); }
|
||||
.nav-group-toggle .nav-chevron { margin-left: auto; width: 14px; height: 14px; transition: transform 0.15s ease; opacity: 0.6; }
|
||||
.nav-group.expanded .nav-group-toggle .nav-chevron { transform: rotate(90deg); }
|
||||
.nav-group.active-group .nav-group-toggle { color: var(--accent-strong); }
|
||||
.nav-group-children {
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
padding-left: 30px;
|
||||
margin-top: 2px;
|
||||
}
|
||||
.nav-group.expanded .nav-group-children { display: flex; }
|
||||
.nav-group-children .nav-item { font-size: 13px; padding: 8px 12px; }
|
||||
|
||||
/* Navbar-Reihenfolge (Settings) */
|
||||
.nav-order-list {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.nav-order-list li {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 8px 12px;
|
||||
background: var(--bg-card);
|
||||
border: 1px solid var(--border-soft);
|
||||
border-radius: var(--radius-sm);
|
||||
font-size: 13.5px;
|
||||
font-weight: 550;
|
||||
}
|
||||
.nav-order-list .nav-order-actions { display: flex; gap: 4px; }
|
||||
.nav-order-list .icon-btn { width: 28px; height: 28px; }
|
||||
|
||||
.sidebar-footer {
|
||||
padding: 14px 12px 18px;
|
||||
border-top: 1px solid var(--border-soft);
|
||||
@@ -421,6 +475,25 @@ button { font-family: inherit; }
|
||||
.pill.disabled { background: var(--muted-dim); color: var(--muted); }
|
||||
.pill.admin { background: var(--accent-dim); color: var(--accent-strong); }
|
||||
.pill.user { background: var(--muted-dim); color: var(--text-dim); }
|
||||
.pill.action-pill { background: var(--muted-dim); color: var(--text-dim); }
|
||||
.pill.action-pill::before { display: none; }
|
||||
.pill.action-pill svg { width: 13px; height: 13px; }
|
||||
|
||||
.avatar-sm {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
background: var(--muted-dim);
|
||||
color: var(--text-dim);
|
||||
font-size: 11.5px;
|
||||
font-weight: 700;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.avatar-placeholder { text-transform: uppercase; }
|
||||
|
||||
.timer-pill {
|
||||
display: inline-flex;
|
||||
@@ -503,6 +576,7 @@ button { font-family: inherit; }
|
||||
.device-card[data-status="online"]::before { background: var(--success); }
|
||||
.device-card[data-status="offline"]::before { background: var(--danger); }
|
||||
.device-card[data-status="unbekannt"]::before { background: var(--warning); }
|
||||
.device-card[data-status="disabled"]::before { background: var(--muted); }
|
||||
|
||||
.device-card .dc-top {
|
||||
display: flex;
|
||||
@@ -521,6 +595,7 @@ button { font-family: inherit; }
|
||||
}
|
||||
.device-card[data-status="online"] .dc-icon { background: var(--success-dim); color: var(--success); }
|
||||
.device-card[data-status="offline"] .dc-icon { background: var(--danger-dim); color: var(--danger); }
|
||||
.device-card[data-status="disabled"] .dc-icon { background: var(--muted-dim); color: var(--muted); }
|
||||
.device-card .dc-icon svg { width: 17px; height: 17px; }
|
||||
|
||||
.device-card .dc-name {
|
||||
|
||||
@@ -206,6 +206,15 @@
|
||||
} catch (e) { /* noop */ }
|
||||
}
|
||||
|
||||
/* Nav-Gruppen mit Untermenü (z.B. "Logs") auf-/zuklappen */
|
||||
function initNavGroups() {
|
||||
document.querySelectorAll("[data-nav-group-toggle]").forEach((btn) => {
|
||||
btn.addEventListener("click", () => {
|
||||
btn.closest("[data-nav-group]").classList.toggle("expanded");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/* ---------------- Init ---------------- */
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
@@ -214,6 +223,7 @@
|
||||
initModals();
|
||||
initConfirmables();
|
||||
initFlashedMessages();
|
||||
initNavGroups();
|
||||
document.querySelectorAll("[data-theme-toggle]").forEach((btn) => btn.addEventListener("click", toggleTheme));
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user