97 lines
2.9 KiB
JavaScript
97 lines
2.9 KiB
JavaScript
// main.js — App-Boot: Panels mounten, Nav starten, Topbar/Alert pflegen, Polling fahren.
|
||
// Panel-Vertrag: { id, mount?(), onStatus?(s), onJobs?(jobs) }.
|
||
|
||
import { api, getToken, setToken } from "./core/api.js";
|
||
import { $ } from "./core/ui.js";
|
||
import { initNav } from "./core/nav.js";
|
||
|
||
import overview from "./panels/overview.js";
|
||
import models from "./panels/models.js";
|
||
import maintenance from "./panels/maintenance.js";
|
||
import jobs from "./panels/jobs.js";
|
||
import cookbook from "./panels/cookbook.js";
|
||
import guides from "./panels/guides.js";
|
||
|
||
const panels = [overview, models, maintenance, jobs, cookbook, guides];
|
||
|
||
let lastJobs = [];
|
||
let lastSystem = null;
|
||
|
||
// ---- Topbar / Alert aus dem Status ableiten ----
|
||
function applyStatus(s) {
|
||
const dot = $("#swdot"), label = $("#swlabel"), alert = $("#alert");
|
||
|
||
if (!s) {
|
||
dot.className = "dot off";
|
||
label.textContent = "Backend nicht erreichbar";
|
||
$("#top-models").textContent = "–";
|
||
showAlert("Backend nicht erreichbar — läuft uvicorn?", false);
|
||
} else {
|
||
const host = s.swap_url.replace(/^https?:\/\//, "");
|
||
dot.className = "dot " + (s.swap_ok ? "on" : "off");
|
||
label.textContent = (s.swap_ok ? "llama-swap online · " : "llama-swap offline · ") + host;
|
||
$("#top-models").textContent = (s.models || []).length;
|
||
if (s.swap_ok) hideAlert();
|
||
else showAlert(`llama-swap nicht erreichbar unter <b>${host}</b> — läuft der Dienst?`, true);
|
||
}
|
||
for (const p of panels) p.onStatus?.(s);
|
||
}
|
||
|
||
function applyJobs(jobs) {
|
||
lastJobs = jobs || [];
|
||
$("#top-jobs").textContent = lastJobs.filter(j => j.state === "running" || j.state === "queued").length;
|
||
for (const p of panels) p.onJobs?.(lastJobs);
|
||
}
|
||
|
||
function applySystem(sys) {
|
||
lastSystem = sys;
|
||
for (const p of panels) p.onSystem?.(sys);
|
||
}
|
||
|
||
function showAlert(html, warn) {
|
||
const a = $("#alert");
|
||
a.className = "alert" + (warn ? " warn" : "");
|
||
a.innerHTML = `<span class="a-dot"></span><span>${html}</span>`;
|
||
a.style.display = "flex";
|
||
}
|
||
function hideAlert() { $("#alert").style.display = "none"; }
|
||
|
||
// ---- Polling ----
|
||
async function pollStatus() {
|
||
try { applyStatus(await api("/api/status")); }
|
||
catch { applyStatus(null); }
|
||
}
|
||
async function pollJobs() {
|
||
try { applyJobs(await api("/api/jobs")); }
|
||
catch { /* still */ }
|
||
}
|
||
|
||
async function pollSystem() {
|
||
try { applySystem(await api("/api/system/status")); }
|
||
catch { /* still */ }
|
||
}
|
||
|
||
// ---- Boot ----
|
||
function bootToken() {
|
||
const i = $("#token");
|
||
i.value = getToken();
|
||
i.addEventListener("change", e => { setToken(e.target.value); pollStatus(); });
|
||
}
|
||
function tickClock() {
|
||
$("#clock").textContent = new Date().toTimeString().slice(0, 5);
|
||
}
|
||
|
||
for (const p of panels) p.mount?.();
|
||
initNav("overview");
|
||
bootToken();
|
||
tickClock();
|
||
document.addEventListener("mc:refresh", pollStatus);
|
||
|
||
pollStatus();
|
||
pollJobs();
|
||
pollSystem();
|
||
setInterval(tickClock, 1000);
|
||
setInterval(pollStatus, 3000);
|
||
setInterval(pollJobs, 1500);
|
||
setInterval(pollSystem, 3000);
|