const elements = { health: document.querySelector("#health"), payloadCount: document.querySelector("#payloadCount"), apiCount: document.querySelector("#apiCount"), serverCount: document.querySelector("#serverCount"), activity: document.querySelector("#activity"), payloads: document.querySelector("#payloads"), refresh: document.querySelector("#refresh"), columnToggles: [...document.querySelectorAll("[data-column-toggle]")], }; const columnPreferenceKey = "arduino-playground-visible-columns"; function escapeHtml(value) { return String(value).replace(/[&<>'"]/g, (character) => ({ "&": "&", "<": "<", ">": ">", "'": "'", '"': """, })[character]); } function readColumnPreferences() { try { return JSON.parse(localStorage.getItem(columnPreferenceKey)) ?? {}; } catch { return {}; } } function applyColumnPreferences() { const preferences = readColumnPreferences(); for (const toggle of elements.columnToggles) { const column = toggle.dataset.columnToggle; if (column in preferences) toggle.checked = preferences[column]; document.querySelectorAll(`[data-column="${column}"]`).forEach((cell) => { cell.hidden = !toggle.checked; }); } } function saveColumnPreferences() { const preferences = Object.fromEntries( elements.columnToggles.map((toggle) => [toggle.dataset.columnToggle, toggle.checked]), ); localStorage.setItem(columnPreferenceKey, JSON.stringify(preferences)); applyColumnPreferences(); } async function refresh() { try { const dashboardRequest = { headers: { "X-Monitor-Request": "dashboard" } }; const [healthResponse, payloadResponse, activityResponse] = await Promise.all([ fetch("/api/health", dashboardRequest), fetch("/api/payloads", dashboardRequest), fetch("/api/activity", dashboardRequest), ]); if (![healthResponse, payloadResponse, activityResponse].every((response) => response.ok)) { throw new Error("Serveren returnerede en fejl"); } const [health, payloads, activity] = await Promise.all([ healthResponse.json(), payloadResponse.json(), activityResponse.json(), ]); elements.health.textContent = "API online"; elements.health.className = "status online"; elements.payloadCount.textContent = payloads.length; elements.apiCount.textContent = activity.filter((event) => event.source === "api").length; elements.serverCount.textContent = activity.filter((event) => event.source === "server").length; elements.payloads.textContent = JSON.stringify(payloads, null, 2); const requests = activity.filter((event) => event.source === "api"); elements.activity.innerHTML = requests.slice(0, 30).map((event) => { const detail = event.detail; return ` ${new Date(event.timestamp).toLocaleTimeString("en-GB")} ${escapeHtml(detail.deviceId ?? "—")} ${escapeHtml(detail.clientName ?? "—")} ${escapeHtml(detail.path ?? "—")} ${escapeHtml(detail.method ?? "—")} ${escapeHtml(detail.status ?? "—")} `; }).join("") || 'No external API requests yet.'; applyColumnPreferences(); } catch (error) { elements.health.textContent = "Server offline"; elements.health.className = "status"; } } elements.refresh.addEventListener("click", refresh); elements.columnToggles.forEach((toggle) => toggle.addEventListener("change", saveColumnPreferences)); applyColumnPreferences(); refresh(); setInterval(refresh, 3000);