Update static/js/pages/bgp.js

This commit is contained in:
Blackwhitebear8 2025-06-28 13:21:40 +02:00
parent 82db3d6972
commit 0c44bb4bfe

View file

@ -1,141 +1,154 @@
function filterTable(searchInputId, tableId) { function filterTable(searchInputId, tableId) {
const filter = document.getElementById(searchInputId).value.toUpperCase(); const filter = document.getElementById(searchInputId).value.toUpperCase();
const rows = document.getElementById(tableId).getElementsByTagName("tr"); const rows = document.getElementById(tableId).getElementsByTagName("tr");
for (let i = 1; i < rows.length; i++) { for (let i = 1; i < rows.length; i++) {
rows[i].style.display = "none"; rows[i].style.display = "none";
for (const cell of rows[i].getElementsByTagName("td")) { for (const cell of rows[i].getElementsByTagName("td")) {
if ((cell.textContent || cell.innerText).toUpperCase().includes(filter)) { if ((cell.textContent || cell.innerText).toUpperCase().includes(filter)) {
rows[i].style.display = ""; rows[i].style.display = "";
break; break;
} }
}
} }
}
} }
function sortTable(tableId, columnIndex, th) { function sortTable(tableId, columnIndex, th) {
const tbody = document.getElementById(tableId).tBodies[0]; const tbody = document.getElementById(tableId).tBodies[0];
const rows = Array.from(tbody.rows); const rows = Array.from(tbody.rows);
const headers = Array.from(th.parentNode.children); const headers = Array.from(th.parentNode.children);
headers.forEach(h => h !== th && (h.className = "", h.dataset.sortState = "none")); headers.forEach(h => h !== th && (h.className = "", h.dataset.sortState = "none"));
const state = th.dataset.sortState || "none"; const state = th.dataset.sortState || "none";
const newState = state === "none" ? "asc" : state === "asc" ? "desc" : "none"; const newState = state === "none" ? "asc" : state === "asc" ? "desc" : "none";
th.dataset.sortState = newState; th.dataset.sortState = newState;
th.className = newState !== "none" ? newState : ""; th.className = newState !== "none" ? newState : "";
if (newState === "none") { if (newState === "none") {
rows.sort((a, b) => a.dataset.index - b.dataset.index); rows.sort((a, b) => a.dataset.index - b.dataset.index);
} else { } else {
rows.sort((a, b) => { rows.sort((a, b) => {
const aTxt = a.cells[columnIndex].textContent.trim(); const aTxt = a.cells[columnIndex].textContent.trim();
const bTxt = b.cells[columnIndex].textContent.trim(); const bTxt = b.cells[columnIndex].textContent.trim();
const aNum = parseFloat(aTxt.replace(/[^0-9.-]/g, "")); const aNum = parseFloat(aTxt.replace(/[^0-9.-]/g, ""));
const bNum = parseFloat(bTxt.replace(/[^0-9.-]/g, "")); const bNum = parseFloat(bTxt.replace(/[^0-9.-]/g, ""));
const numeric = !isNaN(aNum) && !isNaN(bNum); const numeric = !isNaN(aNum) && !isNaN(bNum);
const cmp = numeric ? aNum - bNum : aTxt.localeCompare(bTxt); const cmp = numeric ? aNum - bNum : aTxt.localeCompare(bTxt, undefined, { numeric: true });
return newState === "asc" ? cmp : -cmp; return newState === "asc" ? cmp : -cmp;
}); });
} }
rows.forEach(r => tbody.appendChild(r)); rows.forEach(r => tbody.appendChild(r));
} }
async function loadBgpTables() { async function loadBgpTables() {
const ipv4Sum = document.getElementById("ipv4Summary"); const ipv4Sum = document.getElementById("ipv4Summary");
const ipv6Sum = document.getElementById("ipv6Summary"); const ipv6Sum = document.getElementById("ipv6Summary");
const ipv4Body = document.getElementById("ipv4TableBody"); const ipv4Body = document.getElementById("ipv4TableBody");
const ipv6Body = document.getElementById("ipv6TableBody"); const ipv6Body = document.getElementById("ipv6TableBody");
try { try {
const res = await fetch("/bgp/json"); const res = await fetch("/bgp/json");
const data = await res.json(); const data = await res.json();
ipv4Sum.innerHTML = summaryHtml(data.ipv4_info); ipv4Sum.innerHTML = buildSummary("IPv4", data.ipv4_info);
ipv6Sum.innerHTML = summaryHtml(data.ipv6_info); ipv6Sum.innerHTML = buildSummary("IPv6", data.ipv6_info);
renderPeers(ipv4Body, data.ipv4_peers, "ipv4Table"); renderPeers(ipv4Body, data.ipv4_peers);
renderPeers(ipv6Body, data.ipv6_peers, "ipv6Table"); renderPeers(ipv6Body, data.ipv6_peers);
bootstrap.Popover.getInstance(document.body)?.dispose?.(); activatePopovers();
document.querySelectorAll('[data-bs-toggle="popover"]').forEach(el => new bootstrap.Popover(el)); } catch (e) {
showError(ipv4Sum, ipv4Body, "IPv4");
} catch (e) { showError(ipv6Sum, ipv6Body, "IPv6");
showError(ipv4Sum, ipv4Body, "IPv4"); }
showError(ipv6Sum, ipv6Body, "IPv6");
}
} }
function summaryHtml(info) { function buildSummary(label, info) {
return ` const popContent = `
<p>BGP Router ID: ${info.router_id}, <strong>BGP Router ID:</strong> ${info.router_id}<br>
Local AS: <a href="https://bgp.tools/search?q=${info.local_as}" target="_blank">${info.local_as}</a>, <strong>Local AS:</strong> <a href='https://bgp.tools/search?q=${info.local_as}' target='_blank'>${info.local_as}</a><br>
VRF ID: ${info.vrf_id}</p> <strong>VRF ID:</strong> ${info.vrf_id}<br>
<p>${info.rib_entries} RIB Entries, using ${info.rib_memory}</p> <strong>RIB Entries:</strong> ${info.rib_entries} (using ${info.rib_memory})<br>
<p>${info.peers} Peers, using ${info.peers_memory}</p> <strong>Peers:</strong> ${info.peers}, using ${info.peers_memory}<br>
<p>BGP Table Version: ${info.table_version}</p> <strong>BGP Table Version:</strong> ${info.table_version}
`.trim();
return `
<h2 class="d-inline me-2">${label} Unicast Summary</h2>
<span tabindex="0" role="button" class="info-icon"
data-bs-toggle="popover" data-bs-trigger="hover focus"
data-bs-html="true" data-bs-title="${label} Summary Info"
data-bs-content="${popContent}">
</span>
<div class="mt-1"><strong>Peers:</strong> ${info.peers}</div>
`;
}
function renderPeers(tbody, peers) {
tbody.innerHTML = "";
if (!peers.length) {
tbody.innerHTML = `<tr><td colspan="7" class="text-center">No data available.</td></tr>`;
return;
}
peers.forEach((p, i) => {
const popTitle = `<a href="https://bgp.tools/search?q=${p.as_number}" target="_blank" rel="noopener noreferrer">${p.as_number}</a> details<a>`;
const popContent = `
Messages Received: ${p.msg_received}<br>
Messages Sent: ${p.msg_sent}<br>
Inbound Q: ${p.in_queue}<br>
Outbound Q: ${p.out_queue}
`.trim();
const tr = document.createElement("tr");
tr.dataset.index = i;
tr.innerHTML = `
<td>${p.neighbor}</td>
<td><a href="https://bgp.tools/search?q=${p.as_number}" target="_blank">${p.as_number}</a></td>
<td>${p.up_down}</td>
<td>${p.state_pfx_rcd}</td>
<td>${p.prefix_sent}</td>
<td>${p.description}</td>
<td>
<span tabindex="0" role="button" class="info-icon"
data-bs-toggle="popover" data-bs-trigger="hover focus"
data-bs-html="true" data-bs-title='${popTitle}'
data-bs-content="${popContent}">
</span>
</td>
`; `;
tbody.appendChild(tr);
});
} }
function renderPeers(tbody, peers, tableId) { function activatePopovers() {
tbody.innerHTML = ""; document.querySelectorAll('[data-bs-toggle="popover"]').forEach(el => {
if (!peers.length) { const existing = bootstrap.Popover.getInstance(el);
tbody.innerHTML = `<tr><td colspan="7" class="text-center">No data available.</td></tr>`; if (existing) existing.dispose();
return; new bootstrap.Popover(el);
} });
peers.forEach((p, i) => {
const popTitle =
`<a href="https://bgp.tools/search?q=${p.as_number}" target="_blank" rel="noopener noreferrer">${p.as_number}</a> details<a>`;
const popContent = `
Messages Received: ${p.msg_received}<br>
Messages Sent: ${p.msg_sent}<br>
Inbound Queue: ${p.in_queue}<br>
Outbound Queue: ${p.out_queue}
`.trim();
const tr = document.createElement("tr");
tr.dataset.index = i;
tr.innerHTML = `
<td>${p.neighbor}</td>
<td><a href="https://bgp.tools/search?q=${p.as_number}" target="_blank">${p.as_number}</a></td>
<td>${p.up_down}</td>
<td>${p.state_pfx_rcd}</td>
<td>${p.prefix_sent}</td>
<td>${p.description}</td>
<td>
<span tabindex="0" role="button" class="info-icon"
data-bs-toggle="popover"
data-bs-trigger="focus"
data-bs-html="true"
data-bs-title='${popTitle}'
data-bs-content="${popContent}">
</span>
</td>
`;
tbody.appendChild(tr);
});
} }
function showError(sumEl, bodyEl, label) { function showError(sumEl, bodyEl, label) {
sumEl.textContent = `Error fetching ${label} data.`; sumEl.textContent = `Error fetching ${label} data.`;
bodyEl.innerHTML = `<tr><td colspan="7" class="text-center text-danger">Error retrieving data.</td></tr>`; bodyEl.innerHTML = `<tr><td colspan="7" class="text-center text-danger">Error retrieving data.</td></tr>`;
} }
function refreshBGPTable() { function refreshBGPTable() {
["ipv4Search", "ipv6Search"].forEach(id => (document.getElementById(id).value = "")); ["ipv4Search", "ipv6Search"].forEach(id => (document.getElementById(id).value = ""));
toggleRefresh(true); toggleRefresh(true);
loadBgpTables().finally(() => toggleRefresh(false)); loadBgpTables().finally(() => toggleRefresh(false));
} }
function toggleRefresh(loading) { function toggleRefresh(loading) {
document.getElementById("refreshIcon").classList.toggle("d-none", loading); document.getElementById("refreshIcon").classList.toggle("d-none", loading);
document.getElementById("refreshSpinner").classList.toggle("d-none", !loading); document.getElementById("refreshSpinner").classList.toggle("d-none", !loading);
document.getElementById("refreshIcon2").classList.toggle("d-none", loading); document.getElementById("refreshIcon2").classList.toggle("d-none", loading);
document.getElementById("refreshSpinner2").classList.toggle("d-none", !loading); document.getElementById("refreshSpinner2").classList.toggle("d-none", !loading);
} }
document.addEventListener("DOMContentLoaded", loadBgpTables); document.addEventListener("DOMContentLoaded", loadBgpTables);