diff --git a/app/templates/index.html b/app/templates/index.html index 130d2c9..f6c0b32 100644 --- a/app/templates/index.html +++ b/app/templates/index.html @@ -221,9 +221,13 @@ const visibleCount = document.getElementById('visible-count'); const allRows = [...document.querySelectorAll('#ap-table-body tr')]; - let ipMatchingMacs = null; // null = inactive; Set = active + let ipFilterActive = false; - function normMac(s) { return (s || '').toUpperCase().replace(/-/g, ':'); } + function isTargetIp(ip) { + if (!ip) return false; + const last = parseInt((ip.split('.')[3] || ''), 10); + return last >= 150 && last <= 155; + } function applyFilters() { const q = filterInput.value.toLowerCase().trim(); @@ -234,9 +238,9 @@ const nameMatch = !q || name.includes(q) || site.includes(q); let ipMatch = true; - if (ipMatchingMacs !== null) { + if (ipFilterActive) { const cb = row.querySelector('.ap-checkbox'); - ipMatch = ipMatchingMacs.has(normMac(cb?.dataset.mac)); + ipMatch = isTargetIp(cb?.dataset.ip || ''); } const visible = nameMatch && ipMatch; @@ -252,18 +256,9 @@ // ── IP range filter button ───────────────────────────────────────────────── const btnIpFilter = document.getElementById('btn-ip-filter'); const ipFilterLabel = document.getElementById('ip-filter-label'); - const ipFilterIcon = document.getElementById('ip-filter-icon'); - let cachedApClients = null; - - function isTargetIp(ip) { - if (!ip) return false; - const parts = ip.split('.'); - if (parts.length !== 4) return false; - const last = parseInt(parts[3], 10); - return last >= 150 && last <= 155; - } function setIpFilterActive(active) { + ipFilterActive = active; if (active) { btnIpFilter.classList.replace('bg-white', 'bg-blue-50'); btnIpFilter.classList.replace('hover:bg-gray-50', 'hover:bg-blue-100'); @@ -279,40 +274,9 @@ } } - btnIpFilter?.addEventListener('click', async () => { - if (ipMatchingMacs !== null) { - // Clear filter - ipMatchingMacs = null; - setIpFilterActive(false); - applyFilters(); - return; - } - - btnIpFilter.disabled = true; - ipFilterLabel.textContent = 'Loading…'; - ipFilterIcon.classList.add('animate-spin'); - - try { - if (!cachedApClients) { - const res = await fetch('/api/all-clients'); - if (!res.ok) { const e = await res.json(); throw new Error(e.detail || 'Request failed'); } - cachedApClients = (await res.json()).ap_clients || {}; - } - - ipMatchingMacs = new Set(); - for (const [apMac, clients] of Object.entries(cachedApClients)) { - if (clients.some(c => isTargetIp(c.ip))) ipMatchingMacs.add(apMac); - } - - setIpFilterActive(true); - applyFilters(); - } catch (e) { - showToast('Failed to load client data: ' + e.message, 'error'); - ipFilterLabel.textContent = 'Filter .150–.155'; - } finally { - btnIpFilter.disabled = false; - ipFilterIcon.classList.remove('animate-spin'); - } + btnIpFilter?.addEventListener('click', () => { + setIpFilterActive(!ipFilterActive); + applyFilters(); }); // ── Refresh ────────────────────────────────────────────────────────────────