refactor: massive UX and beginner refactoring (Cookbook, Dashboard, Layout, Wording)

This commit is contained in:
Hitonabi
2026-06-20 22:06:04 +02:00
parent 9d05b2d011
commit e3be7fbfb5
11 changed files with 359 additions and 276 deletions
+7 -63
View File
@@ -1,11 +1,9 @@
// overview.js — Dashboard-Kopf: Hero + Mini-Stats, KPI-Reihe, Stack-Gesundheit,
// kompakte Modell-Liste ("Session Router"). Speist sich aus /api/status + /api/jobs.
// overview.js — Dashboard-Kopf: Hero + kompakte Modell-Liste.
import { $, icon, esc } from "../core/ui.js";
import { $, esc } from "../core/ui.js";
let S = null; // letzter Status
let J = []; // letzte Job-Liste
let SYS = null; // letzte System-Auslastung
const RUNNING = new Set(["running", "ready", "loading", "starting"]);
@@ -16,7 +14,6 @@ function counts() {
running: models.filter(m => RUNNING.has(m.state)).length,
jobsRun: J.filter(j => j.state === "running" || j.state === "queued").length,
jobsErr: J.filter(j => j.state === "failed").length,
swap: !!S?.swap_ok,
};
}
@@ -43,58 +40,6 @@ function renderHero() {
</div>`;
}
function kpi(cls, title, ic, value, sub) {
return `<div class="kpi ${cls}">
<div class="k-h"><span class="k-t">${title}</span><span class="k-ic">${icon(ic)}</span></div>
<div class="k-v">${value}</div>
<div class="k-s">${sub}</div>
</div>`;
}
function renderKpis() {
const c = counts();
const sysV = SYS ? `${SYS.cpu.percent.toFixed(0)}<small>% CPU</small>` : "n/a";
const sysS = SYS ? `${SYS.ram.percent.toFixed(0)}% RAM, ${SYS.gpu_temp ? SYS.gpu_temp.toFixed(0)+'°C' : SYS.cpu.temp ? SYS.cpu.temp.toFixed(0)+'°C' : ''}` : "bald · Live-Auslastung";
$("#kpis").innerHTML =
kpi(c.swap ? "green" : "red", "llama-swap", "swap",
c.swap ? "Online" : "Offline", "Transport-Status") +
kpi("blue", "Modelle", "monitor",
`${c.running}<small>/${c.total}</small>`, "aktiv / gesamt") +
kpi("purple", "Jobs", "layers", c.jobsRun, "laufend") +
kpi(c.jobsErr ? "red" : "muted", "Fehler", "alert", c.jobsErr, "in der Aktivität") +
kpi(SYS ? "blue" : "muted", "System-Last", "gauge", sysV, sysS);
}
function kvRow(k, v, cls = "") {
return `<div class="kv-row"><span class="kv-k">${k}</span><span class="kv-v ${cls}">${v}</span></div>`;
}
function renderHealth() {
const c = counts();
let sysRow = kvRow("Auslastung (RAM/GPU/Disk)", "folgt", "na");
if (SYS) {
const gb = b => (b / 1024 / 1024 / 1024).toFixed(1);
const ram = `${gb(SYS.ram.used)}GB / ${gb(SYS.ram.total)}GB`;
const gpu = (SYS.gpu && SYS.gpu.vram.total) ? `${gb(SYS.gpu.vram.used + SYS.gpu.gtt.used)}GB / ${gb(SYS.gpu.vram.total + SYS.gpu.gtt.total)}GB` : "";
const disk = `${SYS.disk.percent.toFixed(0)}%`;
sysRow = kvRow("Auslastung (RAM/GPU/Disk)", `${ram} | ${gpu} | ${disk}`);
}
$("#health").innerHTML = `
<div class="card-h"><h3>Stack-Gesundheit</h3>
<span class="meta ${c.swap ? "ok" : ""}">${c.swap ? "Connected" : "Offline"}</span></div>
<div class="kv">
${kvRow("llama-swap", c.swap ? "Connected" : "Offline", c.swap ? "ok" : "bad")}
${kvRow("Modelle (gesamt)", c.total)}
${kvRow("Aktiv", c.running, c.running ? "ok" : "")}
${kvRow("Jobs (laufend)", c.jobsRun)}
${kvRow("Fehler", c.jobsErr, c.jobsErr ? "bad" : "")}
${sysRow}
</div>`;
}
function modelRow(m) {
const on = RUNNING.has(m.state);
const dot = m.state === "loading" || m.state === "starting" ? "load" : on ? "on" : "";
@@ -125,18 +70,17 @@ function modelRow(m) {
function renderModels() {
const models = S?.models || [];
$("#ov-models").innerHTML = `
<div class="card-h"><h3>Modelle</h3><span class="meta">${models.length || ""}</span></div>
<div class="card-h"><h3>Aktuelle Modelle im Stack</h3><span class="meta">${models.length || ""}</span></div>
${models.length
? `<div class="list">${models.map(modelRow).join("")}</div>`
: `<div class="empty-c"><div class="e-t">Keine Modelle konfiguriert</div>
<div class="e-s">Hol dir unter „Modelle" eins von HuggingFace.</div></div>`}`;
<div class="e-s">Hol dir unter „Cookbook“ eins von HuggingFace.</div></div>`}`;
}
function renderAll() { renderHero(); renderKpis(); renderHealth(); renderModels(); }
function renderAll() { renderHero(); renderModels(); }
function mount() { renderAll(); }
function onStatus(s) { S = s; renderAll(); }
function onJobs(jobs) { J = jobs || []; renderHero(); renderKpis(); renderHealth(); }
function onSystem(sys) { SYS = sys; renderKpis(); renderHealth(); }
function onJobs(jobs) { J = jobs || []; renderHero(); }
export default { id: "overview", mount, onStatus, onJobs, onSystem };
export default { id: "overview", mount, onStatus, onJobs };