diff --git a/neode-ui/src/views/Credentials.vue b/neode-ui/src/views/Credentials.vue
index d50f7f92..84130045 100644
--- a/neode-ui/src/views/Credentials.vue
+++ b/neode-ui/src/views/Credentials.vue
@@ -199,8 +199,9 @@
diff --git a/neode-ui/src/views/__tests__/CredentialsRefresh.test.ts b/neode-ui/src/views/__tests__/CredentialsRefresh.test.ts
index 903d0fc2..a2b7aabc 100644
--- a/neode-ui/src/views/__tests__/CredentialsRefresh.test.ts
+++ b/neode-ui/src/views/__tests__/CredentialsRefresh.test.ts
@@ -1,5 +1,6 @@
import { flushPromises, mount } from '@vue/test-utils'
import { describe, expect, it, vi } from 'vitest'
+import { createPinia } from 'pinia'
import Credentials from '../Credentials.vue'
import { rpcClient } from '@/api/rpc-client'
@@ -42,6 +43,8 @@ describe('Credentials', () => {
const wrapper = mount(Credentials, {
global: {
+ // The cached-resource layer pulls the Pinia resources store in setup.
+ plugins: [createPinia()],
mocks: {
$router: { push: vi.fn() },
},
diff --git a/neode-ui/src/views/server/OpenWrtGateway.vue b/neode-ui/src/views/server/OpenWrtGateway.vue
index 1b091056..c959096e 100644
--- a/neode-ui/src/views/server/OpenWrtGateway.vue
+++ b/neode-ui/src/views/server/OpenWrtGateway.vue
@@ -2,6 +2,7 @@
import { ref, computed, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { rpcClient } from '@/api/rpc-client'
+import { useResourcesStore } from '@/stores/resources'
import BackButton from '@/components/BackButton.vue'
const router = useRouter()
@@ -73,8 +74,15 @@ interface ScannedNetwork {
encryption: string
}
-const status = ref(null)
-const loading = ref(true)
+const status = computed(() => statusEntry().data)
+// Router status is cached in the shared resources store so revisits paint
+// the last-known state instantly while a fresh read runs behind it.
+const resources = useResourcesStore()
+const statusEntry = () => resources.entry('server.openwrt-status')
+const loading = computed(() => {
+ const s = statusEntry().loadState
+ return s === 'loading' || s === 'refreshing' || (s === 'idle' && statusEntry().data === null)
+})
const error = ref('')
const host = ref('')
const sshUser = ref('root')
@@ -115,25 +123,25 @@ const dhcpLimit = ref(150)
const masqEnabled = ref(true)
async function load(params?: Record) {
- loading.value = true
error.value = ''
- try {
- status.value = await rpcClient.call({
+ await resources.refresh('server.openwrt-status', () =>
+ rpcClient.call({
method: 'openwrt.get-status',
params: params ?? {},
timeout: 30000,
- })
- showConnectForm.value = false
- if (params) connectedParams.value = params
- } catch (e) {
- const msg = e instanceof Error ? e.message : String(e)
- if (msg.includes('No router configured')) {
+ dedup: true,
+ maxRetries: 1,
+ }))
+ const err = statusEntry().error
+ if (err) {
+ if (err.includes('No router configured')) {
showConnectForm.value = true
} else {
- error.value = msg
+ error.value = err
}
- } finally {
- loading.value = false
+ } else {
+ showConnectForm.value = false
+ if (params) connectedParams.value = params
}
}