feat: add multi-server control panel and host-aware sync

This commit is contained in:
Luca Sacchi Ricciardi
2026-04-25 15:40:20 +02:00
parent 3ba6a9a41c
commit f60781bd7f
13 changed files with 641 additions and 41 deletions
+58 -1
View File
@@ -1,9 +1,17 @@
class RunningModelsPage {
constructor() {
this.activeServer = getActiveServer();
this.init();
}
init() {
this.updateServerContextUI();
if (!this.activeServer) {
this.renderNoServerState();
return;
}
document.getElementById("refresh-btn")?.addEventListener("click", () => {
this.loadRunningModels();
});
@@ -25,7 +33,7 @@ class RunningModelsPage {
`;
try {
const response = await fetch("/api/v1/models/running");
const response = await fetch(this.buildApiUrl("/api/v1/models/running"));
if (!response.ok) {
throw new Error("Failed to load running models");
}
@@ -46,6 +54,55 @@ class RunningModelsPage {
}
}
buildApiUrl(path) {
const url = new URL(path, window.location.origin);
url.searchParams.set("host", this.activeServer.host);
return `${url.pathname}${url.search}`;
}
updateServerContextUI() {
if (!this.activeServer) {
return;
}
const serverLabel = document.getElementById("active-server-label");
if (serverLabel) {
serverLabel.textContent = `Server: ${this.activeServer.name}`;
serverLabel.classList.remove("hidden");
}
const availableLink = document.getElementById("available-link");
if (availableLink) {
availableLink.href = buildServerUrl("/models-available", this.activeServer.id);
}
const serversLink = document.getElementById("servers-link");
if (serversLink) {
serversLink.href = "/servers";
}
}
renderNoServerState() {
const container = document.getElementById("running-models");
const runningCountEl = document.getElementById("running-count");
const vramTotalEl = document.getElementById("vram-total");
const lastRefreshEl = document.getElementById("last-refresh");
if (runningCountEl) runningCountEl.textContent = "0";
if (vramTotalEl) vramTotalEl.textContent = "0 B";
if (lastRefreshEl) lastRefreshEl.textContent = "-";
if (container) {
container.innerHTML = `
<div class="text-center py-10 text-gray-300">
<p class="text-lg font-semibold">No server selected</p>
<p class="text-sm text-gray-400 mt-2">Select a server in the control panel to load ollama ps data.</p>
<a href="/servers" class="inline-block mt-4 bg-purple-600 hover:bg-purple-700 px-4 py-2 rounded">Open Servers Control Panel</a>
</div>
`;
}
}
renderStats(models) {
const runningCountEl = document.getElementById("running-count");
const vramTotalEl = document.getElementById("vram-total");