aboutsummaryrefslogtreecommitdiffstats
path: root/static/app.js
diff options
context:
space:
mode:
Diffstat (limited to 'static/app.js')
-rw-r--r--static/app.js39
1 files changed, 39 insertions, 0 deletions
diff --git a/static/app.js b/static/app.js
new file mode 100644
index 0000000..7a9ff40
--- /dev/null
+++ b/static/app.js
@@ -0,0 +1,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();