feat: wire real RPC data to Server.vue Local Network card
Replace hardcoded values with live data from network.diagnostics and router.list-forwards RPC calls. Add skeleton loading states and graceful N/A fallbacks when endpoints are unavailable. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
38b29dd2fd
commit
4874f59e1d
@ -42,7 +42,7 @@
|
||||
|
||||
- [x] **UI-03** — Remove duplicate network diagnostics from Settings.vue. Settings.vue contains a "Network Diagnostics" section that duplicates functionality available on the Server.vue (Network) page. Remove the entire Network Diagnostics section from Settings.vue. Add a small link/button in Settings that says "Network Diagnostics" and routes to `/dashboard/server` instead. Keep the "Network Diagnostics" section only in Server.vue. **Acceptance**: Settings no longer shows duplicate network info; link navigates to Server page. Deploy and verify.
|
||||
|
||||
- [ ] **UI-04** — Server.vue: wire real RPC data to Local Network card. The Local Network card in `neode-ui/src/views/Server.vue` lines 100-159 shows hardcoded values ("2 configured", "12 active", "5 rules"). Replace with data from RPC calls: `network.diagnostics` for connectivity info and `router.list-forwards` for port forwarding count. Add `onMounted` lifecycle hook to fetch data. Show skeleton loading states while fetching. **Acceptance**: Network card shows real data from backend (or graceful "N/A" if RPC unavailable). Deploy and verify.
|
||||
- [x] **UI-04** — Server.vue: wire real RPC data to Local Network card. The Local Network card in `neode-ui/src/views/Server.vue` lines 100-159 shows hardcoded values ("2 configured", "12 active", "5 rules"). Replace with data from RPC calls: `network.diagnostics` for connectivity info and `router.list-forwards` for port forwarding count. Add `onMounted` lifecycle hook to fetch data. Show skeleton loading states while fetching. **Acceptance**: Network card shows real data from backend (or graceful "N/A" if RPC unavailable). Deploy and verify.
|
||||
|
||||
- [ ] **UI-05** — Server.vue: wire real RPC data to Web3 card. The Web3 card in Server.vue lines 161-220 shows hardcoded values ("3 active", "2.4 GB used"). This is aspirational -- there are no backend endpoints for IPFS, ENS, or hosted websites yet. Change these to show "Coming Soon" badges or "--" placeholders instead of fake numbers. Keep the card layout and icons. **Acceptance**: No fake data shown; coming-soon state is visually clean. Deploy and verify.
|
||||
|
||||
|
||||
@ -112,45 +112,58 @@
|
||||
</div>
|
||||
|
||||
<div class="space-y-3 flex-1 min-h-0">
|
||||
<div class="flex items-center justify-between p-3 bg-white/5 rounded-lg">
|
||||
<div class="flex items-center gap-3">
|
||||
<svg class="w-5 h-5 text-white/60" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z" />
|
||||
</svg>
|
||||
<span class="text-white/80 text-sm">Firewall Active</span>
|
||||
<!-- Skeleton loading -->
|
||||
<template v-if="networkLoading">
|
||||
<div v-for="i in 4" :key="i" class="flex items-center justify-between p-3 bg-white/5 rounded-lg animate-pulse">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="w-5 h-5 bg-white/10 rounded"></div>
|
||||
<div class="w-24 h-4 bg-white/10 rounded"></div>
|
||||
</div>
|
||||
<div class="w-16 h-4 bg-white/10 rounded"></div>
|
||||
</div>
|
||||
<span class="text-green-400 text-sm font-medium">Protected</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="flex items-center justify-between p-3 bg-white/5 rounded-lg">
|
||||
<div class="flex items-center gap-3">
|
||||
<svg class="w-5 h-5 text-white/60" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" />
|
||||
</svg>
|
||||
<span class="text-white/80 text-sm">WiFi Networks</span>
|
||||
<template v-else>
|
||||
<div class="flex items-center justify-between p-3 bg-white/5 rounded-lg">
|
||||
<div class="flex items-center gap-3">
|
||||
<svg class="w-5 h-5 text-white/60" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z" />
|
||||
</svg>
|
||||
<span class="text-white/80 text-sm">Firewall Active</span>
|
||||
</div>
|
||||
<span class="text-green-400 text-sm font-medium">Protected</span>
|
||||
</div>
|
||||
<span class="text-white/60 text-sm">2 configured</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-between p-3 bg-white/5 rounded-lg">
|
||||
<div class="flex items-center gap-3">
|
||||
<svg class="w-5 h-5 text-white/60" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9" />
|
||||
</svg>
|
||||
<span class="text-white/80 text-sm">DHCP Clients</span>
|
||||
<div class="flex items-center justify-between p-3 bg-white/5 rounded-lg">
|
||||
<div class="flex items-center gap-3">
|
||||
<svg class="w-5 h-5 text-white/60" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" />
|
||||
</svg>
|
||||
<span class="text-white/80 text-sm">WiFi Networks</span>
|
||||
</div>
|
||||
<span class="text-white/60 text-sm">{{ networkData.wifiCount }}</span>
|
||||
</div>
|
||||
<span class="text-white/60 text-sm">12 active</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-between p-3 bg-white/5 rounded-lg">
|
||||
<div class="flex items-center gap-3">
|
||||
<svg class="w-5 h-5 text-white/60" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z" />
|
||||
</svg>
|
||||
<span class="text-white/80 text-sm">Port Forwarding</span>
|
||||
<div class="flex items-center justify-between p-3 bg-white/5 rounded-lg">
|
||||
<div class="flex items-center gap-3">
|
||||
<svg class="w-5 h-5 text-white/60" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9" />
|
||||
</svg>
|
||||
<span class="text-white/80 text-sm">Connectivity</span>
|
||||
</div>
|
||||
<span class="text-sm" :class="networkData.torConnected ? 'text-green-400' : 'text-white/60'">{{ networkData.torConnected ? 'Tor Connected' : 'N/A' }}</span>
|
||||
</div>
|
||||
<span class="text-white/60 text-sm">5 rules</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-between p-3 bg-white/5 rounded-lg">
|
||||
<div class="flex items-center gap-3">
|
||||
<svg class="w-5 h-5 text-white/60" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z" />
|
||||
</svg>
|
||||
<span class="text-white/80 text-sm">Port Forwarding</span>
|
||||
</div>
|
||||
<span class="text-white/60 text-sm">{{ networkData.forwardCount }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<button class="mt-auto pt-4 w-full px-4 py-2 glass-button rounded-lg text-sm font-medium text-white/90 hover:text-white transition-colors shrink-0">
|
||||
@ -223,11 +236,11 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { rpcClient } from '@/api/rpc-client'
|
||||
|
||||
// Connected nodes
|
||||
const connectedNodes = ref(12)
|
||||
const connectedNodes = ref(0)
|
||||
|
||||
// Service status
|
||||
const servicesRunning = ref(true)
|
||||
@ -241,7 +254,56 @@ const checkingConnectivity = ref(false)
|
||||
const autoSyncEnabled = ref(true)
|
||||
|
||||
// Logs
|
||||
const logCount = ref(3)
|
||||
const logCount = ref(0)
|
||||
|
||||
// Network data
|
||||
const networkLoading = ref(true)
|
||||
const networkData = ref({
|
||||
wifiCount: 'N/A',
|
||||
torConnected: false,
|
||||
forwardCount: 'N/A',
|
||||
})
|
||||
|
||||
async function loadNetworkData() {
|
||||
networkLoading.value = true
|
||||
try {
|
||||
const [diagRes, fwdRes] = await Promise.allSettled([
|
||||
rpcClient.call<{ wan_ip: string | null; nat_type: string; upnp_available: boolean; tor_connected: boolean; wifi_count?: number }>({ method: 'network.diagnostics' }),
|
||||
rpcClient.call<{ forwards: unknown[] }>({ method: 'router.list-forwards' }),
|
||||
])
|
||||
|
||||
if (diagRes.status === 'fulfilled') {
|
||||
networkData.value.torConnected = diagRes.value.tor_connected
|
||||
networkData.value.wifiCount = diagRes.value.wifi_count !== undefined
|
||||
? `${diagRes.value.wifi_count} configured`
|
||||
: 'N/A'
|
||||
}
|
||||
|
||||
if (fwdRes.status === 'fulfilled') {
|
||||
const count = fwdRes.value.forwards?.length ?? 0
|
||||
networkData.value.forwardCount = `${count} rule${count !== 1 ? 's' : ''}`
|
||||
}
|
||||
} catch {
|
||||
// Keep N/A defaults on failure
|
||||
} finally {
|
||||
networkLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// Load peer count
|
||||
async function loadPeerCount() {
|
||||
try {
|
||||
const res = await rpcClient.listPeers()
|
||||
connectedNodes.value = res.peers?.length ?? 0
|
||||
} catch {
|
||||
connectedNodes.value = 0
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadNetworkData()
|
||||
loadPeerCount()
|
||||
})
|
||||
|
||||
async function restartServices() {
|
||||
restarting.value = true
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user