// Store the latest node data globally let latestNodeData = []; let latestNodeStatus = []; let checkedNodeInfo = []; let firstNode = null; let secondNode = null; document.addEventListener("DOMContentLoaded", function() { loadStateFromCookies(); // Load saved state document.querySelectorAll('.dropdown-item input[type="checkbox"]').forEach((checkbox) => { if (checkedNodeInfo.includes(checkbox.id)) { checkbox.checked = true; // ✅ Ensures checkboxes visually stay checked } checkbox.addEventListener('change', handleCheckboxChange); }); document.querySelectorAll('.dropdown-submenu a.dropdown-toggle').forEach(function(element) { element.addEventListener('click', function(e) { if (!this.nextElementSibling.classList.contains('show')) { this.parentElement.parentElement.querySelectorAll('.dropdown-menu').forEach(function(menu) { menu.classList.remove('show'); }); } this.nextElementSibling.classList.toggle('show'); e.stopPropagation(); }); }); }); // Function to save state in cookies function saveStateToCookies() { document.cookie = `checkedNodeInfo=${JSON.stringify(checkedNodeInfo)}; path=/; max-age=86400`; // Expires in 1 day document.cookie = `selectedNodes=${JSON.stringify([firstNode, secondNode])}; path=/; max-age=86400`; } // Function to load state from cookies function loadStateFromCookies() { const cookies = document.cookie.split("; "); for (let cookie of cookies) { let [name, value] = cookie.split("="); if (name === "checkedNodeInfo") { checkedNodeInfo = JSON.parse(value); } else if (name === "selectedNodes") { [firstNode, secondNode] = JSON.parse(value || "[null, null]"); } } } // Function to handle checkbox state changes function handleCheckboxChange() { checkedNodeInfo = Array.from(document.querySelectorAll('.dropdown-item input[type="checkbox"]:checked')) .map(checkbox => checkbox.id); console.log("Checked metrics:", checkedNodeInfo); // Save selection state saveStateToCookies(); renderGrid(latestNodeData, latestNodeStatus); } // Attach event listeners to checkboxes document.querySelectorAll('.dropdown-item input[type="checkbox"]').forEach((checkbox) => { checkbox.addEventListener('change', handleCheckboxChange); }); function formatTime(seconds) { const days = Math.floor(seconds / (3600*24)) const hours = Math.floor((seconds / 3600) % 24); const minutes = Math.floor((seconds % 3600) / 60); const secs = seconds % 60; // return `${days}d ${hours}h ${minutes}m ${secs}s`; return `${days}d ${hours}h ${minutes}m`; } const socket = new WebSocket("ws://" + location.host); socket.onmessage = (event) => { const { nodeData, nodeStatus } = JSON.parse(event.data); latestNodeData = nodeData; latestNodeStatus = nodeStatus; // Now using global variables to prevent "undefined" errors renderGrid(latestNodeData, latestNodeStatus); }; function renderGrid(nodeData, nodeStatus) { const gridContainer = document.getElementById("grid"); gridContainer.innerHTML = ""; nodeData.forEach((row, y) => { const rowDiv = document.createElement("div"); rowDiv.className = "row"; row.forEach((node, x) => { const cellDiv = document.createElement("div"); const nodeKey = `${y}-${x}`; cellDiv.className = "node"; cellDiv.setAttribute("data-node-id", nodeKey); cellDiv.style.backgroundColor = nodeStatus[y][x]; // Ensure the indicator exists before adding text const indicator = document.createElement("div"); indicator.className = "indicator"; if (nodeKey === firstNode) { indicator.innerText = "1"; indicator.style.display = "flex"; } else if (nodeKey === secondNode) { indicator.innerText = "2"; indicator.style.display = "flex"; } else { indicator.style.display = "none"; // Hide if not selected } if (node) { let displayText = `ID: ${node.id}`; if (checkedNodeInfo.includes("temp")) { displayText += `
Temp: ${node.cpu_temp}°C`; } if (checkedNodeInfo.includes("cutil")) { displayText += `
CPU: ${node.cpu_util}%`; } if (checkedNodeInfo.includes("mutil")) { displayText += `
Mem: ${node.mem_util}%`; } if (checkedNodeInfo.includes("uptime")) { displayText += `
Up: ${formatTime(node.uptime)}`; } cellDiv.innerHTML = displayText; } else { cellDiv.innerHTML = "-"; } cellDiv.appendChild(indicator); cellDiv.addEventListener("click", () => { if (nodeKey === firstNode) { firstNode = null; secondNode = null; } else if (nodeKey === secondNode) { secondNode = null; } else if (!firstNode) { firstNode = nodeKey; } else { secondNode = nodeKey; } console.log("Clicked node:", nodeKey); saveStateToCookies(); renderGrid(nodeData, nodeStatus); }); rowDiv.appendChild(cellDiv); }); gridContainer.appendChild(rowDiv); }); } // Initialize with an empty grid renderGrid( Array.from({ length: 5 }, () => Array(5).fill(null)), Array.from({ length: 5 }, () => Array(5).fill("white")) );