async function loadDashboard() {
const res = await apiFetch('/api/dashboard');
if (!res) return;
const d = await res.json();
// Service status cards with restart buttons
function setDaemon(id, service, running) {
document.getElementById(id).innerHTML =
`
${running ? 'Running' : 'Stopped'}
`;
document.getElementById(id).style.display = 'flex';
document.getElementById(id).style.alignItems = 'center';
}
setDaemon('statusSmbd', 'smbd', d.status.smbd);
setDaemon('statusNfsd', 'nfsd', d.status.nfsd);
setDaemon('statusApache2', 'apache2', d.status.apache2);
// Disk bar
if (d.disk && !d.disk.error) {
const p = d.disk.percent;
const bar = document.getElementById('diskBar');
bar.style.width = p + '%';
bar.style.background = p > 90 ? 'var(--red)' : p > 75 ? 'var(--yellow)' : 'var(--accent)';
document.getElementById('diskLabel').textContent =
`${d.disk.used_gb} GB / ${d.disk.total_gb} GB — ${d.disk.free_gb} GB free`;
} else if (d.disk?.error) {
document.getElementById('diskLabel').textContent = 'Error: ' + d.disk.error;
}
// Server IPs
const ipEl = document.getElementById('serverIps');
if (ipEl) {
ipEl.innerHTML = d.ips?.length
? d.ips.map(i => `${esc(i.iface)}: ${esc(i.ip)}`).join('')
: '—';
}
// Shares table
const sb = document.getElementById('dashSharesBody');
if (!d.shares?.length) {
sb.innerHTML = `
${esc(s.path)}