function filterTable(searchInputId, tableId) { const filter = document.getElementById(searchInputId).value.toUpperCase(); const rows = document.getElementById(tableId).getElementsByTagName("tr"); for (let i = 1; i < rows.length; i++) { rows[i].style.display = "none"; for (const cell of rows[i].getElementsByTagName("td")) { if ((cell.textContent || cell.innerText).toUpperCase().includes(filter)) { rows[i].style.display = ""; break; } } } } function sortTable(tableId, columnIndex, th) { const tbody = document.getElementById(tableId).tBodies[0]; const rows = Array.from(tbody.rows); const headers = Array.from(th.parentNode.children); headers.forEach(h => h !== th && (h.className = "", h.dataset.sortState = "none")); const state = th.dataset.sortState || "none"; const newState = state === "none" ? "asc" : state === "asc" ? "desc" : "none"; th.dataset.sortState = newState; th.className = newState !== "none" ? newState : ""; if (newState === "none") { rows.sort((a, b) => a.dataset.index - b.dataset.index); } else { rows.sort((a, b) => { const aTxt = a.cells[columnIndex].textContent.trim(); const bTxt = b.cells[columnIndex].textContent.trim(); const aNum = parseFloat(aTxt.replace(/[^0-9.-]/g, "")); const bNum = parseFloat(bTxt.replace(/[^0-9.-]/g, "")); const numeric = !isNaN(aNum) && !isNaN(bNum); const cmp = numeric ? aNum - bNum : aTxt.localeCompare(bTxt); return newState === "asc" ? cmp : -cmp; }); } rows.forEach(r => tbody.appendChild(r)); } async function loadBgpTables() { const ipv4Sum = document.getElementById("ipv4Summary"); const ipv6Sum = document.getElementById("ipv6Summary"); const ipv4Body = document.getElementById("ipv4TableBody"); const ipv6Body = document.getElementById("ipv6TableBody"); try { const res = await fetch("/bgp/json"); const data = await res.json(); ipv4Sum.innerHTML = summaryHtml(data.ipv4_info); ipv6Sum.innerHTML = summaryHtml(data.ipv6_info); renderPeers(ipv4Body, data.ipv4_peers, "ipv4Table"); renderPeers(ipv6Body, data.ipv6_peers, "ipv6Table"); bootstrap.Popover.getInstance(document.body)?.dispose?.(); document.querySelectorAll('[data-bs-toggle="popover"]').forEach(el => new bootstrap.Popover(el)); } catch (e) { showError(ipv4Sum, ipv4Body, "IPv4"); showError(ipv6Sum, ipv6Body, "IPv6"); } } function summaryHtml(info) { return `
BGP Router ID: ${info.router_id}, Local AS: ${info.local_as}, VRF ID: ${info.vrf_id}
${info.rib_entries} RIB Entries, using ${info.rib_memory}
${info.peers} Peers, using ${info.peers_memory}
BGP Table Version: ${info.table_version}
`; } function renderPeers(tbody, peers, tableId) { tbody.innerHTML = ""; if (!peers.length) { tbody.innerHTML = `