// ═══════════════════════════════════════════════ // Ced's NOC script.js // NOC data loads from data/noc-status.json // Refreshes every 30s. Graceful fallback on fail. // ═══════════════════════════════════════════════ document.addEventListener("DOMContentLoaded", () => { // Set copyright year const yearSpan = document.querySelector("[data-year]"); if (yearSpan) yearSpan.textContent = new Date().getFullYear(); // NOC data loadNocStatus(); setInterval(loadNocStatus, 30000); // GitHub pinned repos loadGithubRepos(); }); // Track consecutive failures so we can show the fallback let failCount = 0; const MAX_FAILS = 3; async function loadNocStatus() { const dot = document.getElementById("noc-dot"); const statusText = document.getElementById("noc-status-text"); const badge = document.getElementById("noc-refresh-badge"); const nodes = document.getElementById("metric-nodes"); const services = document.getElementById("metric-services"); const vlans = document.getElementById("metric-vlans"); const edge = document.getElementById("metric-edge"); const grid = document.getElementById("noc-system-grid"); const alertList = document.getElementById("noc-alert-list"); const fallback = document.getElementById("noc-fallback"); try { const nocDataUrl = window.location.hostname === 'noc.chasedumphord.com' ? `https://chasedumphord.com/data/noc-status.json?t=${Date.now()}` : `data/noc-status.json?t=${Date.now()}`; const res = await fetch(nocDataUrl); if (!res.ok) throw new Error(`HTTP ${res.status}`); const data = await res.json(); failCount = 0; if (dot) dot.className = "status-dot live"; if (statusText) { const d = new Date(data.lastUpdated); const formatted = d.toLocaleString('en-US', { month: 'long', day: 'numeric', year: 'numeric', hour: 'numeric', minute: '2-digit', hour12: true }); statusText.textContent = `${data.nocName} — ${data.status} — Last updated: ${formatted}`; } if (badge) badge.textContent = `Auto-refresh: 30s`; if (fallback) fallback.style.display = "none"; if (nodes) animateMetric(nodes, data.summary.nodes); if (services) animateMetric(services, data.summary.services); if (vlans) animateMetric(vlans, data.summary.vlans); if (edge) animateMetric(edge, data.summary.edgeSystems); if (grid) { grid.innerHTML = ""; data.systems.forEach((system) => { const card = document.createElement("article"); card.className = "noc-system-card"; const rawStatus = system.status.toLowerCase(); const statusClass = rawStatus.includes("online") || rawStatus.includes("operational") ? "online" : rawStatus.includes("building") || rawStatus.includes("tuning") || rawStatus.includes("active") ? "warning" : "offline"; card.innerHTML = `
${system.type}
`; grid.appendChild(card); }); } if (alertList) renderAlerts(data.systems, alertList); } catch (err) { failCount++; console.warn(`[NOC] Fetch failed (${failCount}/${MAX_FAILS}):`, err.message); if (dot) dot.className = "status-dot error"; if (statusText) { statusText.textContent = failCount >= MAX_FAILS ? "NOC feed offline — view live dashboard at noc.chasedumphord.com" : `NOC data unavailable — retrying... (${failCount}/${MAX_FAILS})`; } if (badge) badge.textContent = ""; if (failCount >= MAX_FAILS && fallback) { fallback.style.display = "block"; } } } function animateMetric(el, value) { el.classList.remove("metric-pop"); el.textContent = value; void el.offsetWidth; el.classList.add("metric-pop"); } // ═══════════════════════════════════════════════ // GitHub Repos // ═══════════════════════════════════════════════ const LANG_COLORS = { Python: "#3572A5", JavaScript: "#f1e05a", Shell: "#89e051", HTML: "#e34c26", CSS: "#563d7c", Dockerfile: "#384d54", YAML: "#cb171e", Makefile: "#427819", }; async function loadGithubRepos() { const container = document.getElementById("github-repos"); if (!container) return; try { const res = await fetch( "https://api.github.com/users/ced4568/repos?sort=pushed&per_page=6", { headers: { Accept: "application/vnd.github+json" } } ); if (!res.ok) throw new Error(`GitHub API ${res.status}`); const repos = await res.json(); const ownRepos = repos.filter((r) => !r.fork).slice(0, 6); if (ownRepos.length === 0) { container.innerHTML = `No public repositories found.
`; return; } container.innerHTML = ownRepos.map((repo) => { const langColor = LANG_COLORS[repo.language] || "var(--accent-2)"; const desc = repo.description ? repo.description : "No description provided."; const updatedDate = new Date(repo.pushed_at).toLocaleDateString("en-US", { month: "short", year: "numeric", }); return `${desc}
Could not load repositories. View on GitHub