/* Atlus — Settings app */ (function () { 'use strict'; let container = null; let contentEl = null; let activeSection = 'general'; const SECTIONS = [ { id: 'general', label: 'General' }, { id: 'network', label: 'Network' }, { id: 'services', label: 'Services' }, { id: 'about', label: 'About' }, ]; async function loadSection(section) { activeSection = section; // Update nav container.querySelectorAll('.settings-nav-item').forEach(item => { item.classList.toggle('active', item.dataset.section === section); }); if (section === 'general') await renderGeneral(); else if (section === 'network') await renderNetwork(); else if (section === 'services') await renderServicesConfig(); else if (section === 'about') await renderAbout(); } async function renderGeneral() { const res = await Atlus.apiFetch('/api/settings'); const cfg = await res.json(); const sysRes = await Atlus.apiFetch('/api/settings/system'); const sys = await sysRes.json(); contentEl.innerHTML = `
General
SYSTEM
Hostname
System network name
Timezone
System timezone
DISPLAY
Stats refresh interval
Seconds between stat updates
Session timeout
Minutes before auto-logout
`; contentEl.querySelector('#saveGeneral').addEventListener('click', async () => { const hostname = contentEl.querySelector('#setHostname').value.trim(); const timezone = contentEl.querySelector('#setTimezone').value.trim(); const interval = parseInt(contentEl.querySelector('#setStatsInterval').value); const timeout = parseInt(contentEl.querySelector('#setSessionTimeout').value); // Update hostname if changed if (hostname && hostname !== sys.hostname) { await Atlus.apiFetch('/api/settings/hostname', { method: 'POST', body: { hostname }, }); } // Update timezone if changed if (timezone && timezone !== 'System default') { await Atlus.apiFetch('/api/settings/timezone', { method: 'POST', body: { timezone }, }); } // Update config await Atlus.apiFetch('/api/settings', { method: 'PUT', body: { stats_interval_seconds: interval, session_timeout_minutes: timeout, timezone: timezone === 'System default' ? null : timezone, }, }); alert('Settings saved.'); }); } async function renderNetwork() { const res = await Atlus.apiFetch('/api/stats'); const data = await res.json(); let html = '
Network
'; const ifaces = data.network.interfaces; for (const [name, info] of Object.entries(ifaces)) { html += `
${name.toUpperCase()}
Status
${info.up ? 'Up' : 'Down'}
IPv4
${info.ipv4 || '--'}
IPv6
${info.ipv6 || '--'}
`; } contentEl.innerHTML = html; } async function renderServicesConfig() { const cfgRes = await Atlus.apiFetch('/api/settings'); const cfg = await cfgRes.json(); const panelServices = cfg.panel_services || []; contentEl.innerHTML = `
Panel Services
PINNED TO RIGHT PANEL
Comma-separated list of systemd unit names to show in the right panel.
`; contentEl.querySelector('#saveServices').addEventListener('click', async () => { const raw = contentEl.querySelector('#setPanelServices').value; const units = raw.split(',').map(s => s.trim()).filter(Boolean); await Atlus.apiFetch('/api/settings', { method: 'PUT', body: { panel_services: units }, }); alert('Panel services updated.'); }); } async function renderAbout() { const res = await Atlus.apiFetch('/api/settings/system'); const sys = await res.json(); contentEl.innerHTML = `
About
A
ATLUS v0.1.0
Hostname
${sys.hostname}
Operating System
${sys.os}
Kernel
${sys.kernel}
Architecture
${sys.arch}
Python
${sys.python}
Licensed under GPL-3.0
`; } Atlus.registerApp('settings', { title: 'Settings', init(el) { container = el; container.classList.add('app-settings'); // Nav const nav = document.createElement('div'); nav.className = 'settings-nav'; SECTIONS.forEach(s => { const item = document.createElement('button'); item.className = 'settings-nav-item' + (s.id === activeSection ? ' active' : ''); item.dataset.section = s.id; item.textContent = s.label; item.addEventListener('click', () => loadSection(s.id)); nav.appendChild(item); }); container.appendChild(nav); // Content contentEl = document.createElement('div'); contentEl.className = 'settings-content'; container.appendChild(contentEl); loadSection(activeSection); }, destroy() { container = null; contentEl = null; activeSection = 'general'; }, }); })();