179 lines
5.5 KiB
JavaScript
179 lines
5.5 KiB
JavaScript
class ServersPage {
|
|
constructor() {
|
|
this.form = document.getElementById("server-form");
|
|
this.serverIdInput = document.getElementById("server-id");
|
|
this.serverNameInput = document.getElementById("server-name");
|
|
this.serverHostInput = document.getElementById("server-host");
|
|
this.clearFormBtn = document.getElementById("clear-form-btn");
|
|
this.serversList = document.getElementById("servers-list");
|
|
this.serversCount = document.getElementById("servers-count");
|
|
|
|
this.init();
|
|
}
|
|
|
|
init() {
|
|
this.form?.addEventListener("submit", (event) => {
|
|
event.preventDefault();
|
|
this.saveServer();
|
|
});
|
|
|
|
this.clearFormBtn?.addEventListener("click", () => this.resetForm());
|
|
this.renderServers();
|
|
}
|
|
|
|
saveServer() {
|
|
const name = this.serverNameInput?.value.trim() || "";
|
|
const host = normalizeHost(this.serverHostInput?.value || "");
|
|
|
|
if (!name || !host) {
|
|
return;
|
|
}
|
|
|
|
const existingId = this.serverIdInput?.value || "";
|
|
const servers = loadServers();
|
|
|
|
if (existingId) {
|
|
const index = servers.findIndex((server) => server.id === existingId);
|
|
if (index >= 0) {
|
|
servers[index] = { ...servers[index], name, host };
|
|
}
|
|
saveServers(servers);
|
|
setActiveServerId(existingId);
|
|
} else {
|
|
const newServer = {
|
|
id: generateServerId(),
|
|
name,
|
|
host
|
|
};
|
|
servers.push(newServer);
|
|
saveServers(servers);
|
|
setActiveServerId(newServer.id);
|
|
}
|
|
|
|
this.resetForm();
|
|
this.renderServers();
|
|
}
|
|
|
|
editServer(serverId) {
|
|
const server = getServerById(serverId);
|
|
if (!server) {
|
|
return;
|
|
}
|
|
|
|
this.serverIdInput.value = server.id;
|
|
this.serverNameInput.value = server.name;
|
|
this.serverHostInput.value = server.host;
|
|
}
|
|
|
|
deleteServer(serverId) {
|
|
const servers = loadServers().filter((server) => server.id !== serverId);
|
|
saveServers(servers);
|
|
|
|
const activeServerId = getActiveServerId();
|
|
if (activeServerId === serverId) {
|
|
if (servers.length > 0) {
|
|
setActiveServerId(servers[0].id);
|
|
} else {
|
|
localStorage.removeItem(ACTIVE_SERVER_KEY);
|
|
}
|
|
}
|
|
|
|
this.renderServers();
|
|
}
|
|
|
|
selectServer(serverId) {
|
|
setActiveServerId(serverId);
|
|
this.renderServers();
|
|
}
|
|
|
|
openAvailable(serverId) {
|
|
window.location.href = buildServerUrl("/models-available", serverId);
|
|
}
|
|
|
|
openRunning(serverId) {
|
|
window.location.href = buildServerUrl("/models-running", serverId);
|
|
}
|
|
|
|
resetForm() {
|
|
this.serverIdInput.value = "";
|
|
this.serverNameInput.value = "";
|
|
this.serverHostInput.value = "";
|
|
}
|
|
|
|
renderServers() {
|
|
const servers = loadServers();
|
|
const activeServerId = getActiveServerId();
|
|
|
|
if (this.serversCount) {
|
|
this.serversCount.textContent = `${servers.length} server${servers.length === 1 ? "" : "s"}`;
|
|
}
|
|
|
|
if (!this.serversList) {
|
|
return;
|
|
}
|
|
|
|
if (servers.length === 0) {
|
|
this.serversList.innerHTML = `
|
|
<div class="text-center py-10 text-gray-400 border border-dashed border-gray-600 rounded-lg">
|
|
No servers configured yet. Add your first Ollama endpoint in the control panel.
|
|
</div>
|
|
`;
|
|
return;
|
|
}
|
|
|
|
this.serversList.innerHTML = servers
|
|
.map((server) => {
|
|
const isActive = server.id === activeServerId;
|
|
return `
|
|
<div class="bg-gray-700 border ${isActive ? "border-purple-500" : "border-gray-600"} rounded-lg p-4">
|
|
<div class="flex flex-col md:flex-row md:items-center md:justify-between gap-4">
|
|
<div>
|
|
<h3 class="text-lg font-semibold">${this.escapeHtml(server.name)}</h3>
|
|
<p class="text-xs text-gray-300 mt-1">${this.escapeHtml(server.host)}</p>
|
|
</div>
|
|
<div class="flex flex-wrap gap-2">
|
|
<button data-action="select" data-server-id="${server.id}" class="bg-gray-800 hover:bg-gray-900 px-3 py-2 rounded text-xs">${isActive ? "Selected" : "Select"}</button>
|
|
<button data-action="available" data-server-id="${server.id}" class="bg-blue-700 hover:bg-blue-800 px-3 py-2 rounded text-xs">Available</button>
|
|
<button data-action="running" data-server-id="${server.id}" class="bg-green-700 hover:bg-green-800 px-3 py-2 rounded text-xs">Running</button>
|
|
<button data-action="edit" data-server-id="${server.id}" class="bg-amber-700 hover:bg-amber-800 px-3 py-2 rounded text-xs">Edit</button>
|
|
<button data-action="delete" data-server-id="${server.id}" class="bg-red-700 hover:bg-red-800 px-3 py-2 rounded text-xs">Delete</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`;
|
|
})
|
|
.join("");
|
|
|
|
this.bindServerActions();
|
|
}
|
|
|
|
bindServerActions() {
|
|
this.serversList.querySelectorAll("button[data-action]").forEach((button) => {
|
|
button.addEventListener("click", () => {
|
|
const action = button.getAttribute("data-action");
|
|
const serverId = button.getAttribute("data-server-id") || "";
|
|
|
|
if (!serverId) {
|
|
return;
|
|
}
|
|
|
|
if (action === "select") this.selectServer(serverId);
|
|
if (action === "available") this.openAvailable(serverId);
|
|
if (action === "running") this.openRunning(serverId);
|
|
if (action === "edit") this.editServer(serverId);
|
|
if (action === "delete") this.deleteServer(serverId);
|
|
});
|
|
});
|
|
}
|
|
|
|
escapeHtml(text) {
|
|
const div = document.createElement("div");
|
|
div.textContent = text;
|
|
return div.innerHTML;
|
|
}
|
|
}
|
|
|
|
document.addEventListener("DOMContentLoaded", () => {
|
|
window.serversPage = new ServersPage();
|
|
});
|