// overview.js — Dashboard: Quick Actions, Modelle & Recent Jobs
import { api } from "../core/api.js";
import { $, esc, icon, toast } from "../core/ui.js";
let S = null; // letzter Status
let J = []; // letzte Job-Liste
let SYS = null;
const RUNNING = new Set(["running", "ready", "loading", "starting"]);
function counts() {
const models = S?.models || [];
return {
total: models.length,
running: models.filter(m => RUNNING.has(m.state)).length,
};
}
function renderHero() {
$("#hero").innerHTML = `
Dashboard
Mission Control
Steuerzentrale für deinen lokalen llama-swap-Stack. Hier verwaltest du Modelle, Downloads und Server-Wartung.
`;
}
async function triggerAction(action) {
if (action === "restart_llama") {
toast("Neustart ausgelöst...");
try {
await api("/api/service/llama-swap/restart", { method: "POST" });
toast("llama-swap wird neugestartet.");
} catch(e) {
toast("Fehler: " + e.message, true);
}
} else if (action === "update_mc") {
toast("Update gestartet! Siehe Aktivitäten.");
try {
await api("/api/update", { method: "POST" });
document.querySelector('.nav-item[data-view=\\'activity\\']').click();
} catch(e) {
toast("Fehler: " + e.message, true);
}
}
}
// Global hook für onclick
window.triggerAction = triggerAction;
function renderQuickActions() {
let actionsHtml = "";
if (SYS) {
const ram_percent = SYS.ram.percent || 0;
// Wenn RAM über 90% ist, zeige Warnung.
// Wir nehmen 90 für Produktion, aber für den Test könnte es angepasst werden.
if (ram_percent >= 90) {
actionsHtml += `
⚠️ Arbeitsspeicher kritisch (${ram_percent.toFixed(0)}%)
Der RAM/VRAM ist fast voll. Dies kann zu Systeminstabilität führen.
VRAM leeren (Neustart)
`;
}
// Simulierter Update-Check (Idealerweise vom Backend, hier als permanenter Button wenn man manuell checken will,
// oder wir blenden ihn ein wenn ein lokales flag gesetzt ist. Wir zeigen ihn hier als Feature-Highlight)
// Da wir aktuell keinen echten Git-Check im Backend haben, zeigen wir einen "Update Prüfen" Button in den QuickActions.
}
// 3 Standard Kacheln (Cookbook, Server-Status, Aktivität/Guides)
$("#ov-quick").innerHTML = actionsHtml + `
Modell finden
${icon("book")}
Durchsuche HuggingFace nach neuen Modellen im Cookbook.
Container Updates
${icon("download")}
Prüfe auf Updates für Mission-Control und Llama.cpp.
Wartung
${icon("server")}
Server neustarten, VRAM leeren oder OS aktualisieren.
`;
}
function modelRow(m) {
const on = RUNNING.has(m.state);
const dot = m.state === "loading" || m.state === "starting" ? "load" : on ? "on" : "";
const state = on ? (m.state === "loading" ? "lädt…" : "geladen") : "bereit";
let caps = "";
if (m.meta && m.meta.caps) {
caps = m.meta.caps.map(c => {
if (c === "Code") return `{ } `;
if (c === "Bild") return `👁 `;
return "";
}).join("");
}
const filename = m.meta?.filename ? `${esc(m.meta.filename)}
` : '';
return `
${esc(m.name)}${caps}
${filename}
`;
}
function renderModels() {
const models = S?.models || [];
$("#ov-models").innerHTML = `
Aktuelle Modelle im Stack ${models.length || ""}
${models.length
? `${models.map(modelRow).join("")}
`
: `Keine Modelle konfiguriert
Hol dir unter „Cookbook“ eins von HuggingFace.
`}`;
}
function renderRecentJobs() {
const latest = J.slice(0, 4);
const statusBadge = (s) => {
if (s === "done") return 'fertig ';
if (s === "failed") return 'fehler ';
return 'lädt… ';
};
$("#ov-recent-jobs").innerHTML = `
Letzte Aktivitäten Alle ansehen →
${latest.length
? `
${latest.map(j => `
`).join("")}
`
: `Keine Aktivitäten
Alles läuft ruhig.
`
}
`;
}
function renderAll() {
renderHero();
renderQuickActions();
renderModels();
renderRecentJobs();
}
function mount() { renderAll(); }
function onStatus(s) { S = s; renderModels(); }
function onJobs(jobs) { J = jobs || []; renderRecentJobs(); }
function onSystem(sys) { SYS = sys; renderQuickActions(); }
export default { id: "overview", mount, onStatus, onJobs, onSystem };