Files
IT-Nexus/nexus-scanner/internal/web/templates/layout.html

146 lines
7.4 KiB
HTML

{{define "layout"}}
<!DOCTYPE html>
<html lang="de" data-theme="light">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{.Title}} — Nexus Scanner</title>
<link rel="stylesheet" href="/static/style.css">
<script>
(function(){
var t = localStorage.getItem('nx-theme') || 'light';
document.documentElement.setAttribute('data-theme', t);
})();
</script>
<script src="https://unpkg.com/htmx.org@1.9.12" defer></script>
</head>
<body>
<div class="app">
<!-- Sidebar -->
<aside class="sidebar">
<div class="sidebar-brand">
<div class="brand-mark">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round">
<path d="M22 12h-4l-3 9L9 3l-3 9H2"/>
</svg>
</div>
<div>
<div class="brand-name">Nexus Scanner</div>
<div class="brand-sub">{{.SiteID}} · {{.Addr}}</div>
</div>
</div>
<div class="sidebar-section">Scanner</div>
<nav>
<a href="/dashboard" class="nav-item{{if eq .Page "dashboard"}} active{{end}}">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="7" height="9" rx="1.5"/><rect x="14" y="3" width="7" height="5" rx="1.5"/><rect x="14" y="12" width="7" height="9" rx="1.5"/><rect x="3" y="16" width="7" height="5" rx="1.5"/></svg>
<span>Übersicht</span>
</a>
<a href="/assets" class="nav-item{{if eq .Page "assets"}} active{{end}}">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="16" rx="2"/><path d="M3 9h18M9 9v11"/></svg>
<span>Geräte</span>
<span class="nav-badge">{{.HostCount}}</span>
</a>
<a href="/modules" class="nav-item{{if eq .Page "modules"}} active{{end}}">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="7" height="7" rx="1.5"/><rect x="14" y="3" width="7" height="7" rx="1.5"/><rect x="3" y="14" width="7" height="7" rx="1.5"/><rect x="14" y="14" width="7" height="7" rx="1.5"/></svg>
<span>Module</span>
</a>
<a href="/snmp" class="nav-item{{if eq .Page "snmp"}} active{{end}}">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"/></svg>
<span>SNMP</span>
</a>
<a href="/monitoring" class="nav-item{{if eq .Page "monitoring"}} active{{end}}">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/></svg>
<span>Monitoring</span>
{{if .Scanning}}<span class="nav-dot"></span>{{end}}
</a>
<a href="/ad" class="nav-item{{if eq .Page "ad"}} active{{end}}">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75"/></svg>
<span>Active Directory</span>
</a>
<a href="/logs" class="nav-item{{if eq .Page "logs"}} active{{end}}">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="M4 6h16M4 12h16M4 18h10"/></svg>
<span>Logs</span>
<span class="nav-dot"></span>
</a>
</nav>
<div class="sidebar-section">System</div>
<nav>
<a href="/settings" class="nav-item{{if eq .Page "settings"}} active{{end}}">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"/></svg>
<span>Einstellungen</span>
</a>
<button class="nav-item" onclick="toggleTheme()">
<svg id="theme-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"/></svg>
<span id="theme-label">Dunkler Modus</span>
</button>
</nav>
<div class="sidebar-footer">
<div class="avatar">A</div>
<div style="flex:1;min-width:0;">
<div class="user-name">Administrator</div>
<div class="user-sub">Eingeloggt</div>
</div>
<a href="/logout" class="icon-btn" title="Abmelden">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4M16 17l5-5-5-5M21 12H9"/></svg>
</a>
</div>
</aside>
<!-- Main -->
<div class="main">
<header class="topbar">
<div class="breadcrumb">
<span>Nexus Scanner</span>
<span class="breadcrumb-sep">/</span>
<span class="breadcrumb-current">{{.Title}}</span>
</div>
<div class="topbar-actions">
{{if .Scanning}}
<div class="status-pill scanning"><span class="dot teal" style="animation:dotpulse 1.6s ease-out infinite;"></span> Scan läuft…</div>
{{else}}
<div class="status-pill online"><span class="dot green"></span> Online · {{.SiteID}}</div>
{{end}}
<a href="/logout" class="icon-btn" title="Abmelden">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4M16 17l5-5-5-5M21 12H9"/></svg>
</a>
</div>
</header>
<main class="content">
{{template "content" .}}
</main>
</div>
</div>
<script>
function toggleTheme() {
var cur = document.documentElement.getAttribute('data-theme') || 'light';
var next = cur === 'dark' ? 'light' : 'dark';
document.documentElement.setAttribute('data-theme', next);
localStorage.setItem('nx-theme', next);
updateThemeUI(next);
}
function updateThemeUI(t) {
var icon = document.getElementById('theme-icon');
var label = document.getElementById('theme-label');
if (!icon || !label) return;
if (t === 'dark') {
icon.innerHTML = '<circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"/>';
label.textContent = 'Heller Modus';
} else {
icon.innerHTML = '<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/>';
label.textContent = 'Dunkler Modus';
}
}
(function(){
updateThemeUI(document.documentElement.getAttribute('data-theme') || 'light');
})();
</script>
</body>
</html>
{{end}}