No One Can Stop Me Now
This commit is contained in:
109
services/setec-manager/web/static/js/app.js
Normal file
109
services/setec-manager/web/static/js/app.js
Normal file
@@ -0,0 +1,109 @@
|
||||
/* Setec App Manager — Client JS */
|
||||
|
||||
// ── API helper ──
|
||||
const api = {
|
||||
async get(url) {
|
||||
const r = await fetch(url, { credentials: 'same-origin' });
|
||||
if (r.status === 401) { window.location.href = '/login'; return null; }
|
||||
if (!r.ok) throw new Error(`GET ${url}: ${r.status}`);
|
||||
return r.json();
|
||||
},
|
||||
async post(url, body) {
|
||||
const r = await fetch(url, {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: body ? JSON.stringify(body) : undefined
|
||||
});
|
||||
if (r.status === 401) { window.location.href = '/login'; return null; }
|
||||
if (!r.ok) throw new Error(`POST ${url}: ${r.status}`);
|
||||
return r.json();
|
||||
},
|
||||
async del(url) {
|
||||
const r = await fetch(url, { method: 'DELETE', credentials: 'same-origin' });
|
||||
if (r.status === 401) { window.location.href = '/login'; return null; }
|
||||
if (!r.ok) throw new Error(`DELETE ${url}: ${r.status}`);
|
||||
return r.json();
|
||||
}
|
||||
};
|
||||
|
||||
// ── Active nav highlight ──
|
||||
(function highlightNav() {
|
||||
const path = window.location.pathname;
|
||||
document.querySelectorAll('.nav-link').forEach(link => {
|
||||
const href = link.getAttribute('href');
|
||||
if (href === '/' && path === '/') {
|
||||
link.classList.add('active');
|
||||
} else if (href !== '/' && path.startsWith(href)) {
|
||||
link.classList.add('active');
|
||||
}
|
||||
});
|
||||
})();
|
||||
|
||||
// ── Dashboard auto-refresh ──
|
||||
(function dashboardRefresh() {
|
||||
if (window.location.pathname !== '/') return;
|
||||
|
||||
const INTERVAL = 10000; // 10 seconds
|
||||
|
||||
async function refresh() {
|
||||
try {
|
||||
const data = await api.get('/api/stats');
|
||||
if (!data) return;
|
||||
|
||||
// Update stat card values if elements exist
|
||||
const updates = {
|
||||
cpuBar: { style: `width: ${data.cpu || 0}%` },
|
||||
memBar: { style: `width: ${data.mem_percent || 0}%` },
|
||||
diskBar: { style: `width: ${data.disk_percent || 0}%` },
|
||||
};
|
||||
|
||||
for (const [id, props] of Object.entries(updates)) {
|
||||
const el = document.getElementById(id);
|
||||
if (el && props.style) el.setAttribute('style', props.style);
|
||||
if (el && props.text) el.textContent = props.text;
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('Stats refresh failed:', e.message);
|
||||
}
|
||||
}
|
||||
|
||||
setInterval(refresh, INTERVAL);
|
||||
})();
|
||||
|
||||
// ── Monitor page auto-refresh ──
|
||||
(function monitorRefresh() {
|
||||
if (window.location.pathname !== '/monitor') return;
|
||||
|
||||
const INTERVAL = 5000;
|
||||
|
||||
async function refresh() {
|
||||
try {
|
||||
const data = await api.get('/api/stats');
|
||||
if (!data) return;
|
||||
|
||||
const bar = (id, pct) => {
|
||||
const el = document.getElementById(id);
|
||||
if (el) el.style.width = pct + '%';
|
||||
};
|
||||
const txt = (id, val) => {
|
||||
const el = document.getElementById(id);
|
||||
if (el) el.textContent = val;
|
||||
};
|
||||
|
||||
bar('cpuBar', data.cpu || 0);
|
||||
txt('cpuText', (data.cpu || 0).toFixed(1) + '%');
|
||||
bar('memBar', data.mem_percent || 0);
|
||||
bar('diskBar', data.disk_percent || 0);
|
||||
|
||||
if (data.mem_text) txt('memText', data.mem_text);
|
||||
if (data.disk_text) txt('diskText', data.disk_text);
|
||||
if (data.net_in) txt('netIn', data.net_in);
|
||||
if (data.net_out) txt('netOut', data.net_out);
|
||||
} catch (e) {
|
||||
console.warn('Monitor refresh failed:', e.message);
|
||||
}
|
||||
}
|
||||
|
||||
setInterval(refresh, INTERVAL);
|
||||
})();
|
||||
Reference in New Issue
Block a user