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, undefined, { numeric: true });
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 = buildSummary("IPv4", data.ipv4_info);
ipv6Sum.innerHTML = buildSummary("IPv6", data.ipv6_info);
renderPeers(ipv4Body, data.ipv4_peers);
renderPeers(ipv6Body, data.ipv6_peers);
activatePopovers();
} catch (e) {
showError(ipv4Sum, ipv4Body, "IPv4");
showError(ipv6Sum, ipv6Body, "IPv6");
}
}
function buildSummary(label, info) {
const popContent = `
BGP Router ID: ${info.router_id}
Local AS: ${info.local_as}
VRF ID: ${info.vrf_id}
RIB Entries: ${info.rib_entries} (using ${info.rib_memory})
Peers: ${info.peers} (using ${info.peers_memory})
BGP Table Version: ${info.table_version}
`.trim();
return `