blob: 7a9ff403906b477f0cafd7c2d74376a77498c5b9 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
// The shell: discover modules, mount each panel, poll its state.
// A module is static/modules/<name>.js exporting default {title, interval,
// mount(el), update(state, el)}. A missing or broken panel is skipped.
const grid = document.getElementById("grid");
async function mountModule(name) {
let panel;
try {
panel = (await import(`./modules/${name}.js`)).default;
} catch {
return;
}
const el = document.createElement("section");
el.className = "panel";
el.dataset.module = name;
el.innerHTML = `<h2>${panel.title ?? name}</h2>`;
grid.append(el);
panel.mount?.(el);
const poll = async () => {
try {
const r = await fetch(`/api/${name}`);
if (r.ok) panel.update?.(await r.json(), el);
} catch {
// keep the last state; the next tick retries
}
};
await poll();
setInterval(poll, (panel.interval ?? 1) * 1000);
}
async function boot() {
const r = await fetch("/api/modules");
if (!r.ok) return;
for (const { name } of await r.json()) await mountModule(name);
}
boot();
|