From b455b2fd151531a315bc585198a4ae3daf173739 Mon Sep 17 00:00:00 2001 From: Christoph Gasser Date: Mon, 27 Apr 2026 15:51:43 +0200 Subject: [PATCH] Fix IP filter to check AP's own IP from DOM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previous implementation fetched connected client IPs via API (which was returning empty data). The filter now checks the AP's own management IP directly from the data already in the table — no network request, instant. An AP is shown when its IP last octet is between 150 and 155 inclusive. Co-Authored-By: Claude Sonnet 4.6 --- app/templates/index.html | 60 ++++++++-------------------------------- 1 file changed, 12 insertions(+), 48 deletions(-) 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 ────────────────────────────────────────────────────────────────