Fix IP filter to check connected client IPs
Fetches clients for every AP in parallel using the existing /api/ap-clients endpoint, then keeps only APs where at least one client has an IP with last octet 150–155. Shows a loading spinner while fetching. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -222,6 +222,7 @@
|
|||||||
const allRows = [...document.querySelectorAll('#ap-table-body tr')];
|
const allRows = [...document.querySelectorAll('#ap-table-body tr')];
|
||||||
|
|
||||||
let ipFilterActive = false;
|
let ipFilterActive = false;
|
||||||
|
let ipMatchedMacs = new Set(); // AP MACs that have a client with a .150–.155 IP
|
||||||
|
|
||||||
function isTargetIp(ip) {
|
function isTargetIp(ip) {
|
||||||
if (!ip) return false;
|
if (!ip) return false;
|
||||||
@@ -229,6 +230,8 @@
|
|||||||
return last >= 150 && last <= 155;
|
return last >= 150 && last <= 155;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normMac(s) { return (s || '').toUpperCase().replace(/-/g, ':'); }
|
||||||
|
|
||||||
function applyFilters() {
|
function applyFilters() {
|
||||||
const q = filterInput.value.toLowerCase().trim();
|
const q = filterInput.value.toLowerCase().trim();
|
||||||
let shown = 0;
|
let shown = 0;
|
||||||
@@ -240,7 +243,7 @@
|
|||||||
let ipMatch = true;
|
let ipMatch = true;
|
||||||
if (ipFilterActive) {
|
if (ipFilterActive) {
|
||||||
const cb = row.querySelector('.ap-checkbox');
|
const cb = row.querySelector('.ap-checkbox');
|
||||||
ipMatch = isTargetIp(cb?.dataset.ip || '');
|
ipMatch = ipMatchedMacs.has(normMac(cb?.dataset.mac));
|
||||||
}
|
}
|
||||||
|
|
||||||
const visible = nameMatch && ipMatch;
|
const visible = nameMatch && ipMatch;
|
||||||
@@ -256,6 +259,7 @@
|
|||||||
// ── IP range filter button ─────────────────────────────────────────────────
|
// ── IP range filter button ─────────────────────────────────────────────────
|
||||||
const btnIpFilter = document.getElementById('btn-ip-filter');
|
const btnIpFilter = document.getElementById('btn-ip-filter');
|
||||||
const ipFilterLabel = document.getElementById('ip-filter-label');
|
const ipFilterLabel = document.getElementById('ip-filter-label');
|
||||||
|
const ipFilterIcon = document.getElementById('ip-filter-icon');
|
||||||
|
|
||||||
function setIpFilterActive(active) {
|
function setIpFilterActive(active) {
|
||||||
ipFilterActive = active;
|
ipFilterActive = active;
|
||||||
@@ -274,9 +278,48 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
btnIpFilter?.addEventListener('click', () => {
|
btnIpFilter?.addEventListener('click', async () => {
|
||||||
setIpFilterActive(!ipFilterActive);
|
if (ipFilterActive) {
|
||||||
|
ipMatchedMacs.clear();
|
||||||
|
setIpFilterActive(false);
|
||||||
applyFilters();
|
applyFilters();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
btnIpFilter.disabled = true;
|
||||||
|
ipFilterLabel.textContent = 'Loading…';
|
||||||
|
ipFilterIcon.classList.add('animate-spin');
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Collect each AP's mac + site_key from the DOM checkboxes
|
||||||
|
const apList = [];
|
||||||
|
allRows.forEach(row => {
|
||||||
|
const cb = row.querySelector('.ap-checkbox');
|
||||||
|
if (cb?.dataset.mac && cb?.dataset.siteKey) {
|
||||||
|
apList.push({ mac: cb.dataset.mac, siteKey: cb.dataset.siteKey });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Fetch clients for every AP in parallel (reuses the same endpoint as the popup)
|
||||||
|
const hits = await Promise.all(apList.map(async ({ mac, siteKey }) => {
|
||||||
|
try {
|
||||||
|
const res = await fetch(`/api/ap-clients?mac=${encodeURIComponent(mac)}&site_key=${encodeURIComponent(siteKey)}`);
|
||||||
|
if (!res.ok) return null;
|
||||||
|
const { clients } = await res.json();
|
||||||
|
return (clients || []).some(c => isTargetIp(c.ip)) ? normMac(mac) : null;
|
||||||
|
} catch { return null; }
|
||||||
|
}));
|
||||||
|
|
||||||
|
ipMatchedMacs = new Set(hits.filter(Boolean));
|
||||||
|
setIpFilterActive(true);
|
||||||
|
applyFilters();
|
||||||
|
} catch (e) {
|
||||||
|
showToast('Failed to load client data', 'error');
|
||||||
|
ipFilterLabel.textContent = 'Filter .150–.155';
|
||||||
|
} finally {
|
||||||
|
btnIpFilter.disabled = false;
|
||||||
|
ipFilterIcon.classList.remove('animate-spin');
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// ── Refresh ────────────────────────────────────────────────────────────────
|
// ── Refresh ────────────────────────────────────────────────────────────────
|
||||||
|
|||||||
Reference in New Issue
Block a user