document.addEventListener('DOMContentLoaded', () => { const nodeGridContainer = document.getElementById('node-grid-container'); const nodeCountSpan = document.getElementById('node-count'); const POLLING_INTERVAL_MS = 3000; // Poll every 3 seconds async function fetchNodeData() { try { const response = await fetch('/nodes/status'); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.json(); renderNodeGrid(data.nodes); } catch (error) { console.error("Error fetching node data:", error); nodeGridContainer.innerHTML = '
'; } } function renderNodeGrid(nodes) { nodeGridContainer.innerHTML = ''; // Clear existing nodes nodeCountSpan.textContent = nodes.length; // Update total node count if (nodes.length === 0) { nodeGridContainer.innerHTML = ' '; return; } nodes.forEach(node => { const nodeCell = document.createElement('div'); nodeCell.classList.add('node-cell'); nodeCell.classList.add(`node-${node.health_status}`); // Apply health color class // Truncate UUID for display const displayUuid = node.uuid.substring(0, 8) + '...'; nodeCell.innerHTML = `UUID: ${node.uuid}
IP: ${node.ip}
Last Seen: ${new Date(node.last_seen).toLocaleTimeString()}
Uptime: ${node.uptime_seconds ? formatUptime(node.uptime_seconds) : 'N/A'}
Load Avg (1m, 5m, 15m): ${node.load_avg ? node.load_avg.join(', ') : 'N/A'}
Memory Usage: ${node.memory_usage_percent ? node.memory_usage_percent.toFixed(2) + '%' : 'N/A'}