From 84674ffdafb7f173b755c443b773cbeca5d54628 Mon Sep 17 00:00:00 2001 From: archipelago Date: Thu, 8 Oct 2026 19:47:32 -0400 Subject: [PATCH] fix(ui): refresh Server disk warning after cached revalidation --- neode-ui/src/views/Server.vue | 20 ++++++++-------- .../views/__tests__/serverTabCache.test.ts | 24 ++++++++++++++++++- 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/neode-ui/src/views/Server.vue b/neode-ui/src/views/Server.vue index 76eeac95..ea582ebb 100644 --- a/neode-ui/src/views/Server.vue +++ b/neode-ui/src/views/Server.vue @@ -787,8 +787,6 @@ async function connectToWifi(password: string) { } // Disk space -const diskWarning = ref<{ level: 'warning' | 'critical'; used_percent: number; free_bytes: number } | null>(null) -const diskEncrypted = ref(false) const diskCleaning = ref(false) // 02-06: the seventh Server load group. TTL 10s (fast tier, same as @@ -805,15 +803,17 @@ const diskStatusRes = useCachedResource<{ used_bytes: number; total_bytes: numbe persist: true, fetcher: () => rpcClient.diskStatus(), }) +// Reactivation refreshes the cached resource directly. Derive its display +// state reactively so a successful refresh cannot leave an old warning behind. +const diskWarning = computed(() => { + const res = diskStatusRes.data.value + return res?.level === 'warning' || res?.level === 'critical' + ? { level: res.level, used_percent: res.used_percent, free_bytes: res.free_bytes } + : null +}) +const diskEncrypted = computed(() => !!diskStatusRes.data.value?.encrypted) function loadDiskStatus() { - return diskStatusRes.refresh().then(() => { - const res = diskStatusRes.data.value - if (!res) return - diskEncrypted.value = !!(res as Record).encrypted - if (res.level === 'warning' || res.level === 'critical') { - diskWarning.value = { level: res.level, used_percent: res.used_percent, free_bytes: res.free_bytes } - } else { diskWarning.value = null } - }) + return diskStatusRes.refresh() } async function runDiskCleanup() { diff --git a/neode-ui/src/views/__tests__/serverTabCache.test.ts b/neode-ui/src/views/__tests__/serverTabCache.test.ts index edb3a4d0..1b211212 100644 --- a/neode-ui/src/views/__tests__/serverTabCache.test.ts +++ b/neode-ui/src/views/__tests__/serverTabCache.test.ts @@ -47,7 +47,7 @@ const dnsStatusMock = vi.fn(async () => ({ provider: 'system', servers: [], doh_enabled: false, doh_url: null, resolv_conf_servers: [], })) const diskStatusMock = vi.fn(async () => ({ - used_bytes: 0, total_bytes: 0, free_bytes: 0, used_percent: 0, level: 'ok' as const, + used_bytes: 0, total_bytes: 0, free_bytes: 0, used_percent: 0, level: 'ok' as 'ok' | 'warning' | 'critical', encrypted: false, })) vi.mock('@/api/rpc-client', () => ({ @@ -296,3 +296,25 @@ describe('Server tab cache (Task 1): seven load groups', () => { wrapper.unmount() }) }) + +describe('Disk status display follows cached revalidation', () => { + it('clears an old warning after freeing space and revisiting Server', async () => { + diskStatusMock.mockResolvedValueOnce({ used_bytes: 90, total_bytes: 100, free_bytes: 10, used_percent: 90, level: 'critical', encrypted: true }) + const wrapper = mountServerHost(); await flushPromises() + expect(wrapper.text()).toContain('90.0% used') + await toggleTab(wrapper, false); vi.advanceTimersByTime(12000) + diskStatusMock.mockResolvedValueOnce({ used_bytes: 50, total_bytes: 100, free_bytes: 50, used_percent: 50, level: 'ok', encrypted: false }) + await toggleTab(wrapper, true); await flushPromises() + expect(wrapper.text()).not.toContain('90.0% used'); expect(wrapper.text()).not.toContain('remaining') + wrapper.unmount() + }) + it('shows a newly returned disk warning on re-entry', async () => { + const wrapper = mountServerHost(); await flushPromises() + expect(wrapper.text()).not.toContain('95.0% used') + await toggleTab(wrapper, false); vi.advanceTimersByTime(12000) + diskStatusMock.mockResolvedValueOnce({ used_bytes: 95, total_bytes: 100, free_bytes: 5, used_percent: 95, level: 'critical', encrypted: true }) + await toggleTab(wrapper, true); await flushPromises() + expect(wrapper.text()).toContain('95.0% used') + wrapper.unmount() + }) +})