MeshDD-Bot/static/js/app.js
ppfeiffer f2aa69333d feat: v0.7.1 - Hell-Theme als Standard
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 18:49:46 +01:00

123 lines
5.1 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// MeshDD-Bot Shared page module
// Provides: initPage(), escapeHtml(), applyTheme()
// ── Sidebar definition ────────────────────────────────────────
const _SIDEBAR_LINKS = [
{ href: '/', icon: 'bi-speedometer2', label: 'Dashboard', admin: false },
{ href: '/scheduler', icon: 'bi-clock-history', label: 'Scheduler', admin: true },
{ href: '/map', icon: 'bi-map', label: 'Karte', admin: false },
{ href: '/packets', icon: 'bi-reception-4', label: 'Pakete', admin: false },
{ href: '/settings', icon: 'bi-gear', label: 'Einstellungen',admin: true },
{ href: '/admin', icon: 'bi-people', label: 'Benutzer', admin: true },
];
function _injectSidebar() {
const sidebar = document.getElementById('sidebar');
if (!sidebar) return;
const currentPath = window.location.pathname;
sidebar.innerHTML = '<nav class="sidebar-nav">' +
_SIDEBAR_LINKS.map(link => {
const active = currentPath === link.href ? ' active' : '';
const adm = link.admin ? ' sidebar-admin' : '';
return `<a href="${link.href}" class="sidebar-link${active}${adm}">` +
`<i class="bi ${link.icon}"></i><span>${link.label}</span></a>`;
}).join('') +
'</nav>';
}
// ── Navbar ────────────────────────────────────────────────────
function _updateNavbar(user) {
const userMenu = document.getElementById('userMenu');
const loginBtn = document.getElementById('loginBtn');
const userName = document.getElementById('userName');
if (user) {
if (userName) userName.textContent = user.name;
if (userMenu) userMenu.classList.remove('d-none');
if (loginBtn) loginBtn.classList.add('d-none');
} else {
if (userMenu) userMenu.classList.add('d-none');
if (loginBtn) loginBtn.classList.remove('d-none');
}
}
function _updateSidebar(user) {
const isAdmin = user && user.role === 'admin';
document.querySelectorAll('.sidebar-admin').forEach(el => {
el.style.display = isAdmin ? '' : 'none';
});
}
// ── Theme ─────────────────────────────────────────────────────
function applyTheme(theme) {
document.documentElement.setAttribute('data-bs-theme', theme);
const icon = document.getElementById('themeIcon');
if (icon) icon.className = theme === 'dark' ? 'bi bi-sun-fill' : 'bi bi-moon-fill';
localStorage.setItem('theme', theme);
document.dispatchEvent(new CustomEvent('themechange', { detail: { theme } }));
}
function _setupTheme() {
applyTheme(localStorage.getItem('theme') || 'light');
const btn = document.getElementById('themeToggle');
if (btn) {
btn.addEventListener('click', () => {
const current = document.documentElement.getAttribute('data-bs-theme');
applyTheme(current === 'dark' ? 'light' : 'dark');
});
}
}
// ── Sidebar toggle (mobile) ───────────────────────────────────
function _setupSidebarToggle() {
const toggle = document.getElementById('sidebarToggle');
const sidebar = document.getElementById('sidebar');
const backdrop = document.getElementById('sidebarBackdrop');
if (toggle && sidebar) toggle.addEventListener('click', () => sidebar.classList.toggle('open'));
if (backdrop && sidebar) backdrop.addEventListener('click', () => sidebar.classList.remove('open'));
}
// ── Utilities ─────────────────────────────────────────────────
function escapeHtml(str) {
if (!str) return '';
const div = document.createElement('div');
div.textContent = str;
return div.innerHTML;
}
// ── Public init ───────────────────────────────────────────────
function _injectFooter(version) {
const footer = document.getElementById('pageFooter');
if (!footer) return;
const now = new Date();
const mm = String(now.getMonth() + 1).padStart(2, '0');
const yyyy = now.getFullYear();
const ver = version ? ` · v${version}` : '';
footer.textContent = `© MeshDD / PPfeiffer${ver} · ${mm}/${yyyy}`;
}
function initPage({ onAuth = null } = {}) {
_injectSidebar();
_setupTheme();
fetch('/api/auth/me')
.then(r => r.ok ? r.json() : null)
.then(user => {
_updateNavbar(user);
_updateSidebar(user);
_setupSidebarToggle();
if (onAuth) onAuth(user);
});
const vl = document.getElementById('versionLabel');
fetch('/api/stats')
.then(r => r.ok ? r.json() : null)
.then(d => {
if (d?.version && vl) vl.textContent = `v${d.version}`;
_injectFooter(d?.version);
});
}