Router-tools/static/js/pages/dhcpv6_leases.js

166 lines
No EOL
6.1 KiB
JavaScript

document.addEventListener('DOMContentLoaded', function() {
if (document.getElementById('poolSelect')) {
refreshLeaseTable();
}
});
function refreshLeaseTable() {
const tableBody = document.getElementById('leaseTableBody');
const refreshButton = document.getElementById('refreshButton');
const refreshIcon = document.getElementById('refreshIcon');
const refreshSpinner = document.getElementById('refreshSpinner');
const poolSelect = document.getElementById('poolSelect');
if (!tableBody || !poolSelect || !refreshButton || !refreshIcon || !refreshSpinner) {
console.error("Not all elements required for DHCPv6 leases were found.");
return;
}
const selectedPool = poolSelect.value;
if (!selectedPool) {
tableBody.innerHTML = '<tr><td colspan="8" class="text-center text-danger">No pool selected or available.</td></tr>';
return;
}
refreshButton.disabled = true;
refreshIcon.classList.add('d-none');
refreshSpinner.classList.remove('d-none');
const loadingHTML = `
<tr id="lease-loading-row">
<td colspan="8" class="text-center">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</td>
</tr>`;
tableBody.innerHTML = loadingHTML;
fetch(`/dhcpv6-leases/json?pool=${selectedPool}`)
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
})
.then(data => {
tableBody.innerHTML = '';
if (data.error) {
throw new Error(data.error);
}
if (data.data && data.data.length > 0) {
data.data.forEach((lease, index) => {
const row = document.createElement('tr');
row.setAttribute('data-index', index);
row.innerHTML = `
<td>${escapeHTML(lease.prefix)}</td>
<td>${escapeHTML(lease.state)}</td>
<td>${escapeHTML(lease.last_communication)}</td>
<td>${escapeHTML(lease.lease_expiration)}</td>
<td>${escapeHTML(lease.remaining)}</td>
<td>${escapeHTML(lease.type)}</td>
<td>${escapeHTML(lease.pool)}</td>
<td>${escapeHTML(lease.duid)}</td>
`;
tableBody.appendChild(row);
});
} else {
tableBody.innerHTML = '<tr><td colspan="8" class="text-center">No active leases found for this pool.</td></tr>';
}
})
.catch(error => {
console.error('Error fetching DHCPv6 leases:', error);
tableBody.innerHTML = `<tr><td colspan="8" class="text-center text-danger">Failed to retrieve data: ${error.message}</td></tr>`;
})
.finally(() => {
refreshButton.disabled = false;
refreshIcon.classList.remove('d-none');
refreshSpinner.classList.add('d-none');
});
}
function filterTable(searchInputId, tableId) {
const input = document.getElementById(searchInputId);
if (!input) return;
const filter = input.value.toUpperCase();
const table = document.getElementById(tableId);
if (!table) return;
const tr = table.getElementsByTagName("tr");
for (let i = 1; i < tr.length; i++) {
if (tr[i].parentNode.tagName.toLowerCase() !== 'tbody') {
continue;
}
tr[i].style.display = "none";
const td = tr[i].getElementsByTagName("td");
for (let j = 0; j < td.length; j++) {
if (td[j]) {
const txtValue = td[j].textContent || td[j].innerText;
if (txtValue.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
break;
}
}
}
}
}
function sortTable(tableId, columnIndex, th) {
const table = document.getElementById(tableId);
if (!table || !table.tBodies[0]) return;
const tbody = table.tBodies[0];
const rows = Array.from(tbody.rows);
const headers = Array.from(th.parentNode.children);
headers.forEach(header => {
if (header !== th) {
header.classList.remove('asc', 'desc');
header.setAttribute('data-sort-state', 'none');
}
});
let currentState = th.getAttribute('data-sort-state') || 'none';
let newState = currentState === 'none' ? 'asc' : currentState === 'asc' ? 'desc' : 'none';
th.classList.remove('asc', 'desc');
if (newState !== 'none') th.classList.add(newState);
th.setAttribute('data-sort-state', newState);
if (newState === 'none') {
rows.sort((a, b) => parseInt(a.getAttribute('data-index')) - parseInt(b.getAttribute('data-index')));
} else {
rows.sort((a, b) => {
const aText = a.cells[columnIndex]?.textContent.trim() || '';
const bText = b.cells[columnIndex]?.textContent.trim() || '';
const aNum = parseFloat(aText.replace(/[^0-9.-]/g, ''));
const bNum = parseFloat(bText.replace(/[^0-9.-]/g, ''));
const isNumeric = !isNaN(aNum) && !isNaN(bNum) && aText.match(/^[0-9.-]/) && bText.match(/^[0-9.-]/);
return newState === 'asc'
? (isNumeric ? aNum - bNum : aText.localeCompare(bText))
: (isNumeric ? bNum - aNum : bText.localeCompare(aText));
});
}
rows.forEach(row => tbody.appendChild(row));
}
function escapeHTML(str) {
if (str === null || str === undefined) {
return 'N/A';
}
return str.toString()
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;');
}