diff --git a/app.py b/app.py index 6997b32..0a900e0 100644 --- a/app.py +++ b/app.py @@ -291,7 +291,7 @@ def api_links(): return jsonify(json.loads(raw)) except Exception as e: logger.error(f'Failed to parse link_stats JSON: {e}') - return jsonify({'hosts': {}, 'updated': None}) + return jsonify({'hosts': {}, 'unifi_switches': {}, 'updated': None}) @app.route('/api/events') diff --git a/templates/index.html b/templates/index.html index cdc7f6f..47ee69b 100644 --- a/templates/index.html +++ b/templates/index.html @@ -92,7 +92,7 @@
{% if events %} {% if total_active is defined and total_active > events|length %} -
Showing {{ events|length }} of {{ total_active }} active alerts — view all via API
+
Showing {{ events|length }} of {{ total_active }} active alerts — use the search box to filter, or export all as JSON
{% endif %}
diff --git a/templates/inspector.html b/templates/inspector.html index 7002e65..ed7e79e 100644 --- a/templates/inspector.html +++ b/templates/inspector.html @@ -487,7 +487,13 @@ document.addEventListener('click', e => { if (diagBtn) { runDiagnostic(diagBtn.dataset.sw, parseInt(diagBtn.dataset.idx, 10)); return; } const toggleDiag = e.target.closest('[data-action="toggle-diag"]'); - if (toggleDiag) { toggleDiag.parentElement.classList.toggle('diag-open'); return; } + if (toggleDiag) { + const section = toggleDiag.parentElement; + const nowOpen = section.classList.toggle('diag-open'); + const hint = toggleDiag.querySelector('.diag-toggle-hint'); + if (hint) hint.textContent = nowOpen ? '[collapse]' : '[expand]'; + return; + } }); // ── Link Diagnostics ───────────────────────────────────────────────── @@ -510,7 +516,10 @@ function runDiagnostic(swName, portIdx) { pollDiagnostic(resp.job_id, statusEl, resultsEl); }) .catch(e => { - statusEl.textContent = 'Error: ' + (e.message || 'Request failed'); + const msg = (e && e.status === 429) + ? 'Rate limit reached — max 5 diagnostics per minute. Please wait.' + : 'Error: ' + (e && e.message || 'Request failed'); + statusEl.textContent = msg; }); } @@ -520,7 +529,13 @@ function pollDiagnostic(jobId, statusEl, resultsEl) { attempts++; if (attempts > 120) { // 2min timeout clearInterval(_diagPollTimer); - statusEl.textContent = 'Timed out waiting for results.'; + _diagPollTimer = null; + statusEl.innerHTML = 'Timed out waiting for results. ' + + ''; + document.getElementById('diag-retry-btn')?.addEventListener('click', () => { + const sel = document.querySelector('.switch-port-block.selected'); + if (sel) runDiagnostic(sel.dataset.switch, parseInt(sel.dataset.portIdx)); + }); return; } lt.api.get(`/api/diagnose/${jobId}`) @@ -535,7 +550,12 @@ function pollDiagnostic(jobId, statusEl, resultsEl) { .catch(() => { clearInterval(_diagPollTimer); _diagPollTimer = null; - statusEl.textContent = 'Error: lost connection while collecting diagnostics.'; + statusEl.innerHTML = 'Error: lost connection while collecting diagnostics. ' + + ''; + document.getElementById('diag-retry-btn')?.addEventListener('click', () => { + const sel = document.querySelector('.switch-port-block.selected'); + if (sel) runDiagnostic(sel.dataset.switch, parseInt(sel.dataset.portIdx)); + }); }); }, 2000); }