feat(card): host-perf

This commit is contained in:
root
2026-06-02 22:34:44 +10:00
parent 3492b24dac
commit 01177a2cbd

View File

@@ -1,2 +1,33 @@
// temporary stub — filled in Task 9
export default { id: 'host-perf', title: 'Host Perf', size: 'm', mount() {}, start() {}, stop() {} };
// public/views/cards/host_perf.js
import { el, mount } from '../../dom.js';
import { api } from '../../api.js';
let body, timer, prev;
const GB = 1024 ** 3;
function bar(pct) { return el('div', { class: 'sv-bar' }, el('i', { style: { width: Math.min(100, pct) + '%' } })); }
async function load() {
if (!body) return;
try {
const h = await api.get('/api/host');
let rate = '';
if (prev) {
const dt = (h.at - prev.at) / 1000 || 1;
const dn = (b) => ((b) / dt / 1e6).toFixed(1);
rate = `${dn(h.net.rx_bytes - prev.net.rx_bytes)}${dn(h.net.tx_bytes - prev.net.tx_bytes)} MB/s`;
}
prev = h;
mount(body,
el('div', { class: 'sv-row' }, el('span', { class: 'k' }, 'CPU'), el('span', {}, h.cpu_pct + '%')), bar(h.cpu_pct),
el('div', { class: 'sv-row' }, el('span', { class: 'k' }, 'RAM'),
el('span', {}, `${(h.mem.used / GB).toFixed(1)} / ${(h.mem.total / GB).toFixed(0)} GB`)), bar(h.mem.pct),
el('div', { class: 'sv-row' }, el('span', { class: 'k' }, 'DISK'), el('span', {}, h.disk.pct + '%')), bar(h.disk.pct),
el('div', { class: 'sv-row' }, el('span', { class: 'k' }, 'NET'), el('span', {}, rate || '—'))
);
} catch { mount(body, el('span', { class: 'muted' }, 'Host unavailable')); }
}
export default {
id: 'host-perf', title: 'Host Perf · CT 311', size: 'm',
mount(el_) { body = el_; prev = null; load(); },
start() { timer = setInterval(load, 30000); },
stop() { clearInterval(timer); body = null; }
};