feat(home): surface TollGate status on the Network tile

Add a TollGate row (Enabled/Disabled/Not installed) to the Home
dashboard's Network tile, polling the existing openwrt.get-status RPC
on the same cadence as the other network rows. Only rendered once an
OpenWrt router is actually configured, so nodes without one aren't
cluttered with an always-"Not configured" row.

Also fixes the underlying reason this could never have worked: nothing
in the OpenWrt Gateway flow ever persisted the router's host/credentials
server-side — the "connect" form only kept them in local component
state, so any no-args openwrt.get-status call (this new tile, and even
the Gateway page's own reload) always failed with "No router
configured" despite a fully working, provisioned router. Now
handle_openwrt_get_status saves the connection to router_config.json
whenever a host is explicitly passed in and the connection succeeds.
This commit is contained in:
2026-07-01 13:25:43 +00:00
parent d6c1feca97
commit e497f8fed1
3 changed files with 71 additions and 0 deletions
+20
View File
@@ -173,6 +173,10 @@
<div class="flex items-center gap-3"><div class="w-2 h-2 rounded-full" :class="fipsDotClass"></div><span class="text-sm text-white/80">FIPS</span></div>
<span class="text-sm font-medium" :class="fipsTextClass">{{ fipsStatusLabel }}</span>
</div>
<div v-if="homeStatus.tollgateStatus" class="flex items-center justify-between p-3 bg-white/5 rounded-lg">
<div class="flex items-center gap-3"><div class="w-2 h-2 rounded-full" :class="tollgateDotClass"></div><span class="text-sm text-white/80">TollGate</span></div>
<span class="text-sm font-medium" :class="tollgateTextClass">{{ tollgateStatusLabel }}</span>
</div>
</div>
<div class="home-card-buttons flex gap-2 mt-auto pt-4 shrink-0">
<RouterLink to="/dashboard/server" class="home-card-btn flex-1 px-4 py-2 glass-button rounded-lg text-sm font-medium text-center transition-colors">{{ t('home.manageNetwork') }}</RouterLink>
@@ -445,6 +449,22 @@ const fipsStatusLabel = computed(() => {
const peers = s.authenticated_peer_count ?? 0
return peers === 1 ? 'Active · 1 peer' : `Active · ${peers} peers`
})
const tollgateDotClass = computed(() => {
const s = homeStatus.tollgateStatus
if (!s || !s.installed) return 'bg-white/40'
return s.enabled ? 'bg-green-400' : 'bg-yellow-400'
})
const tollgateTextClass = computed(() => {
const s = homeStatus.tollgateStatus
if (!s || !s.installed) return 'text-white/40'
return s.enabled ? 'text-green-400' : 'text-yellow-400'
})
const tollgateStatusLabel = computed(() => {
const s = homeStatus.tollgateStatus
if (!s) return homeStatus.tollgateLoadState === 'loading' ? 'Checking…' : 'Not configured'
if (!s.installed) return 'Not installed'
return s.enabled ? 'Enabled' : 'Disabled'
})
const bitcoinSyncDisplay = computed(() => {
if (homeStatus.stats.bitcoinAvailable === null) return 'Checking…'
if (!homeStatus.stats.bitcoinAvailable) return 'Not running'