From 3eb85087f20b35ffd452720d80f8946f1307aa4e Mon Sep 17 00:00:00 2001 From: 2GT-Rich <107219997+2GT-Rich@users.noreply.github.com> Date: Sun, 17 May 2026 20:04:33 -0700 Subject: [PATCH] fix: SNMP status table no longer vanishes after back/return navigation (v0.11.9 Beta) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Root cause: backend filtered switches by status='online', so a mid-poll-cycle device (briefly 'unknown') caused the endpoint to return [] — and the frontend rendered nothing when the array was empty. - Backend: query ALL switch devices (not just online ones); unreachable devices already fall through to the Promise.allSettled error path and render with an error badge, so no data is lost - Frontend: replace silent `length > 0 &&` guard with a three-way ternary that shows a "No managed switches found" message when the array is empty, so the user always sees feedback instead of a blank section - Frontend: add staleTime: 60_000 to the SNMP query to prevent the hair-trigger background refetch that raced with the poller on every navigation --- README.md | 2 +- backend/package.json | 2 +- backend/src/routes/switches.ts | 6 ++++-- frontend/package.json | 2 +- frontend/src/pages/SwitchesSettingsPage.tsx | 5 ++++- frontend/src/version.ts | 2 +- 6 files changed, 12 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index cc243e9..ed404b5 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ A self-hosted, full-stack network management platform for MikroTik devices. Monitor, configure, and manage your entire MikroTik infrastructure — routers, switches, and wireless access points — from a single web interface. -![Version](https://img.shields.io/badge/version-0.11.8_Beta-blue) +![Version](https://img.shields.io/badge/version-0.11.9_Beta-blue) ![License](https://img.shields.io/badge/license-AGPLv3-blue) ![Docker](https://img.shields.io/badge/docker-compose-2496ED?logo=docker&logoColor=white) ![TypeScript](https://img.shields.io/badge/TypeScript-5.3-3178C6?logo=typescript&logoColor=white) diff --git a/backend/package.json b/backend/package.json index 20d8c99..47e6505 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,6 +1,6 @@ { "name": "mikrotik-manager-backend", - "version": "0.11.8-beta", + "version": "0.11.9-beta", "description": "Mikrotik Network Management Platform - Backend API", "main": "dist/index.js", "scripts": { diff --git a/backend/src/routes/switches.ts b/backend/src/routes/switches.ts index d69f001..19f7929 100644 --- a/backend/src/routes/switches.ts +++ b/backend/src/routes/switches.ts @@ -101,10 +101,12 @@ router.put('/lldp', requireWrite, async (req: Request, res: Response) => { }); }); -// GET /api/switches/snmp — SNMP config/status per online switch +// GET /api/switches/snmp — SNMP config/status for all managed switches +// Includes offline/unknown devices so the list never disappears during a poll cycle. +// Unreachable devices fall through to the Promise.allSettled error path and render with an error note. router.get('/snmp', async (_req: Request, res: Response) => { const switches = await query( - `SELECT * FROM devices WHERE device_type = 'switch' AND status = 'online'` + `SELECT * FROM devices WHERE device_type = 'switch' ORDER BY name` ); const results = await Promise.allSettled( diff --git a/frontend/package.json b/frontend/package.json index 0236e95..aceea21 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "mikrotik-manager-frontend", - "version": "0.11.8-beta", + "version": "0.11.9-beta", "private": true, "type": "module", "scripts": { diff --git a/frontend/src/pages/SwitchesSettingsPage.tsx b/frontend/src/pages/SwitchesSettingsPage.tsx index f490d0f..fcbab08 100644 --- a/frontend/src/pages/SwitchesSettingsPage.tsx +++ b/frontend/src/pages/SwitchesSettingsPage.tsx @@ -93,6 +93,7 @@ export default function SwitchesSettingsPage() { const { data: snmpStatuses = [], isLoading: snmpLoading, refetch: refetchSnmp, isFetching: snmpFetching } = useQuery({ queryKey: ['switches-snmp'], + staleTime: 60_000, queryFn: () => switchesApi.getSnmpStatus().then(r => { // Pre-populate form from first successful result (if form not yet manually edited) const first = r.data.find(s => s.enabled != null && !s.error); @@ -436,7 +437,9 @@ export default function SwitchesSettingsPage() {
Checking SNMP status on all switches…
- ) : snmpStatuses.length > 0 && ( + ) : snmpStatuses.length === 0 ? ( +

No managed switches found.

+ ) : (
diff --git a/frontend/src/version.ts b/frontend/src/version.ts index 796a515..8f0dc7f 100644 --- a/frontend/src/version.ts +++ b/frontend/src/version.ts @@ -1 +1 @@ -export const APP_VERSION = 'v0.11.8 Beta'; +export const APP_VERSION = 'v0.11.9 Beta';