91 lines
4.6 KiB
JavaScript
91 lines
4.6 KiB
JavaScript
function serviceTone(status) {
|
|
if (status === "offline") return "offline";
|
|
if (status === "degraded") return "warning";
|
|
return "online";
|
|
}
|
|
|
|
function healthLabel(status) {
|
|
if (status === "offline") return "Offline";
|
|
if (status === "degraded") return "Degraded";
|
|
return "Healthy";
|
|
}
|
|
|
|
function sourceLabel(source) {
|
|
if (source === "home_assistant") return "Core Automation Hub";
|
|
if (source === "uptime_kuma") return "External availability and latency surface.";
|
|
if (source === "docker") return "Container runtime state without external monitor data.";
|
|
return "Service state from aggregator.";
|
|
}
|
|
|
|
function formatTimestamp(value) {
|
|
if (!value) return "n/a";
|
|
const date = new Date(value);
|
|
return new Intl.DateTimeFormat("de-DE", {
|
|
hour: "2-digit",
|
|
minute: "2-digit",
|
|
second: "2-digit",
|
|
hour12: false,
|
|
}).format(date);
|
|
}
|
|
|
|
export function renderServices(state) {
|
|
const { services, overview } = state.data;
|
|
|
|
const dockerPill = document.getElementById("docker-summary-pill");
|
|
dockerPill.className = `status-pill ${services.summary.docker.source_status === "online" ? "online" : "offline"}`;
|
|
dockerPill.textContent = services.summary.docker.source_status === "online" ? "Online" : "Offline";
|
|
document.getElementById("docker-running").textContent = String(services.summary.docker.running);
|
|
document.getElementById("docker-stopped").textContent = String(services.summary.docker.stopped);
|
|
document.getElementById("docker-unhealthy").textContent = String(services.summary.docker.unhealthy);
|
|
|
|
const kumaPill = document.getElementById("kuma-summary-pill");
|
|
kumaPill.className = `status-pill ${services.summary.uptime_kuma.source_status === "online" ? "online" : "offline"}`;
|
|
kumaPill.textContent = services.summary.uptime_kuma.source_status === "online" ? "Synced" : "Offline";
|
|
document.getElementById("kuma-up").textContent = String(services.summary.uptime_kuma.monitors_up);
|
|
document.getElementById("kuma-down").textContent = String(services.summary.uptime_kuma.monitors_down);
|
|
document.getElementById("kuma-paused").textContent = String(services.summary.uptime_kuma.monitors_paused);
|
|
|
|
const ha = services.services.find((service) => service.id === "homeassistant");
|
|
if (ha) {
|
|
const haPill = document.getElementById("service-ha-pill");
|
|
const tone = serviceTone(ha.status);
|
|
haPill.className = `status-pill ${tone}`;
|
|
haPill.textContent = ha.status === "online" ? "Reachable" : ha.status === "degraded" ? "Degraded" : "Offline";
|
|
document.getElementById("service-ha-version").textContent = overview.home_assistant.version ?? "unknown";
|
|
document.getElementById("service-ha-version").className = "info";
|
|
document.getElementById("service-ha-latency").textContent = ha.latency_ms != null ? `${ha.latency_ms} MS` : "N/A";
|
|
document.getElementById("service-ha-latency").className = tone === "offline" ? "offline" : tone === "warning" ? "warning" : "online";
|
|
document.getElementById("service-ha-last-check").textContent = formatTimestamp(ha.last_checked);
|
|
}
|
|
|
|
const dynamicServices = services.services.filter((service) => service.id !== "homeassistant").slice(0, 3);
|
|
const existingFallbacks = [
|
|
document.getElementById("service-card-fallback-1"),
|
|
document.getElementById("service-card-fallback-2"),
|
|
document.getElementById("service-card-fallback-3"),
|
|
];
|
|
|
|
dynamicServices.forEach((service, index) => {
|
|
const node = existingFallbacks[index];
|
|
if (!node) return;
|
|
node.style.display = "";
|
|
const tone = serviceTone(service.status);
|
|
const pillClass = tone === "warning" ? "warning" : tone === "offline" ? "offline" : "online";
|
|
node.querySelector(".card-label").textContent = service.name;
|
|
node.querySelector(".status-pill").className = `status-pill ${pillClass}`;
|
|
node.querySelector(".status-pill").textContent = healthLabel(service.status);
|
|
node.querySelector(".card-title").textContent = service.name === "Immich" ? "Photo Pipeline" : service.name === "Gitea" ? "Git Platform" : `${service.name} Service`;
|
|
node.querySelector(".card-copy").textContent = sourceLabel(service.source);
|
|
|
|
const rows = node.querySelectorAll(".service-meta-row strong");
|
|
rows[0].textContent = service.latency_ms != null ? `${service.latency_ms} MS` : "N/A";
|
|
rows[0].className = tone === "offline" ? "offline" : tone === "warning" ? "warning" : "online";
|
|
rows[1].textContent = String(service.docker_state).toUpperCase();
|
|
rows[1].className = service.docker_state === "stopped" ? "offline" : service.docker_state === "unhealthy" ? "warning" : "online";
|
|
});
|
|
|
|
for (let index = dynamicServices.length; index < existingFallbacks.length; index += 1) {
|
|
existingFallbacks[index].style.display = "none";
|
|
}
|
|
}
|