diff --git a/README.md b/README.md index 1208e29..9361356 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.16.6_Beta-blue) +![Version](https://img.shields.io/badge/version-0.16.7_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 6b78f73..93f0e9f 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,6 +1,6 @@ { "name": "mikrotik-manager-backend", - "version": "0.16.6-beta", + "version": "0.16.7-beta", "description": "Mikrotik Network Management Platform - Backend API", "main": "dist/index.js", "scripts": { diff --git a/frontend/package.json b/frontend/package.json index d65c403..12aa617 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "mikrotik-manager-frontend", - "version": "0.16.6-beta", + "version": "0.16.7-beta", "private": true, "type": "module", "scripts": { diff --git a/frontend/src/components/device-detail/SystemConfigTab.tsx b/frontend/src/components/device-detail/SystemConfigTab.tsx index 9aa6559..3a4141d 100644 --- a/frontend/src/components/device-detail/SystemConfigTab.tsx +++ b/frontend/src/components/device-detail/SystemConfigTab.tsx @@ -135,10 +135,23 @@ export default function SystemConfigTab({ deviceId, device }: Props) { } }, [device.id]); + // Firmware state is rendered on many screens (Devices list, Firmware page, + // dashboard "Things to handle", Security Center). The backend persists the + // new state immediately, so refresh those caches whenever it changes here — + // otherwise other pages keep stale "update available" data until their own + // 30s refetch fires. + const invalidateFirmwareState = () => { + queryClient.invalidateQueries({ queryKey: ['devices'] }); + queryClient.invalidateQueries({ queryKey: ['device', deviceId] }); + queryClient.invalidateQueries({ queryKey: ['fw-overview'] }); + queryClient.invalidateQueries({ queryKey: ['ops-insights'] }); + queryClient.invalidateQueries({ queryKey: ['security-fleet'] }); + }; + const checkUpdateMutation = useMutation({ mutationFn: () => devicesApi.checkUpdate(deviceId), onMutate: () => { setUpdateChecking(true); setUpdateError(''); setInstallSuccess(''); }, - onSuccess: (res) => { setUpdateInfo(res.data); setUpdateChecking(false); }, + onSuccess: (res) => { setUpdateInfo(res.data); setUpdateChecking(false); invalidateFirmwareState(); }, onError: (err: unknown) => { const msg = (err as { response?: { data?: { error?: string } } })?.response?.data?.error; setUpdateError(msg || 'Failed to check for updates'); @@ -151,6 +164,7 @@ export default function SystemConfigTab({ deviceId, device }: Props) { onSuccess: () => { setUpdateInfo(null); setInstallSuccess('Update installation initiated. The device will reboot shortly.'); + invalidateFirmwareState(); }, onError: (err: unknown) => { const msg = (err as { response?: { data?: { error?: string } } })?.response?.data?.error; @@ -188,7 +202,7 @@ export default function SystemConfigTab({ deviceId, device }: Props) { const checkRouterboardMutation = useMutation({ mutationFn: () => devicesApi.checkRouterboard(deviceId), onMutate: () => { setRbChecking(true); setRbError(''); setRbInstallSuccess(''); }, - onSuccess: (res) => { setRbInfo(res.data); setRbChecking(false); }, + onSuccess: (res) => { setRbInfo(res.data); setRbChecking(false); invalidateFirmwareState(); }, onError: (err: unknown) => { const msg = (err as { response?: { data?: { error?: string } } })?.response?.data?.error; setRbError(msg || 'Failed to check RouterBOOT'); @@ -201,6 +215,7 @@ export default function SystemConfigTab({ deviceId, device }: Props) { onSuccess: () => { setRbInfo(null); setRbInstallSuccess('RouterBOOT upgrade initiated. The device will reboot shortly.'); + invalidateFirmwareState(); }, onError: (err: unknown) => { const msg = (err as { response?: { data?: { error?: string } } })?.response?.data?.error; diff --git a/frontend/src/pages/FirmwarePage.tsx b/frontend/src/pages/FirmwarePage.tsx index 70f4976..ce29c9b 100644 --- a/frontend/src/pages/FirmwarePage.tsx +++ b/frontend/src/pages/FirmwarePage.tsx @@ -147,6 +147,11 @@ export default function FirmwarePage() { const invalidate = () => { qc.invalidateQueries({ queryKey: ['fw-overview'] }); qc.invalidateQueries({ queryKey: ['fw-rollouts'] }); + // Firmware flags also drive the Devices page badges, dashboard insights, + // and Security Center findings — keep those screens in sync too. + qc.invalidateQueries({ queryKey: ['devices'] }); + qc.invalidateQueries({ queryKey: ['ops-insights'] }); + qc.invalidateQueries({ queryKey: ['security-fleet'] }); }; const checkAll = useMutation({ diff --git a/frontend/src/version.ts b/frontend/src/version.ts index 2621bf0..1a5afa9 100644 --- a/frontend/src/version.ts +++ b/frontend/src/version.ts @@ -1 +1 @@ -export const APP_VERSION = 'v0.16.6 Beta'; +export const APP_VERSION = 'v0.16.7 Beta';