--Added Registered nodes data endpoint
This commit is contained in:
george committed 2026-09-09 11:57:23 +05:30
1 parent 0a5899b009
commit eb16c93fb0
3 files changed
+178 -7

No files matched your search

+1
View File
@@ -0,0 +1 @@
VITE_API_BASE_URL=http://127.0.0.1:8000
+44
View File
@@ -355,6 +355,7 @@
}
.register-form {
margin-bottom: 22px;
border: 1px solid var(--border);
border-radius: 8px;
background: var(--bg);
@@ -400,6 +401,49 @@
margin-top: 22px;
}
.nodes-table-wrap {
overflow-x: auto;
border: 1px solid var(--border);
border-radius: 8px;
background: var(--bg);
}
.nodes-table {
width: 100%;
min-width: 720px;
border-collapse: collapse;
color: var(--text-h);
font-size: 14px;
}
.nodes-table th,
.nodes-table td {
border-bottom: 1px solid var(--border);
padding: 13px 14px;
text-align: left;
white-space: nowrap;
}
.nodes-table th {
background: var(--surface);
color: var(--text);
font-size: 12px;
font-weight: 700;
letter-spacing: 0;
text-transform: uppercase;
}
.nodes-table tbody tr:last-child td {
border-bottom: 0;
}
.table-state {
margin: 0;
color: var(--text);
font-size: 15px;
padding: 18px;
}
.eyebrow {
margin-bottom: 12px;
color: var(--accent);
+133 -7
View File
@@ -1,6 +1,8 @@
import { useState } from 'react'
import { useEffect, useState } from 'react'
import './App.css'
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL
const navItems = [
{ id: 'dashboard', label: 'Dashboard' },
{ id: 'nodes', label: 'Nodes' },
@@ -11,6 +13,7 @@ type PageId = (typeof navItems)[number]['id']
type Theme = 'light' | 'dark'
type TokenStatus = 'idle' | 'loading' | 'success' | 'error'
type RegisterStatus = 'idle' | 'loading' | 'success' | 'error'
type NodesStatus = 'idle' | 'loading' | 'success' | 'error'
type RegisterNodePayload = {
node_name: string
@@ -21,6 +24,28 @@ type RegisterNodePayload = {
password: string
}
type RegisterNodeResponse = {
status: string
message?: string
}
type NodeInterface = {
if_id: number
if_name: string
if_nodeid: number
host: string
port: number
dbname: string
user: string
}
type NodeInterfacesResponse = {
status: string
count: number
nodes: NodeInterface[]
message?: string
}
const getSavedTheme = (): Theme => {
try {
return localStorage.getItem('theme') === 'dark' ? 'dark' : 'light'
@@ -58,7 +83,7 @@ const savePage = (page: PageId) => {
}
const getSessionToken = async () => {
const response = await fetch('http://127.0.0.1:8000/get-token', {
const response = await fetch(`${API_BASE_URL}/get-token`, {
method: 'POST',
})
@@ -84,7 +109,9 @@ const getSessionToken = async () => {
return storedToken
}
const registerNode = async (payload: RegisterNodePayload) => {
const registerNode = async (
payload: RegisterNodePayload,
): Promise<RegisterNodeResponse> => {
const accessToken = localStorage.getItem('access_token')
const headers: Record<string, string> = {
'Content-Type': 'application/json',
@@ -94,7 +121,7 @@ const registerNode = async (payload: RegisterNodePayload) => {
headers.Authorization = `Bearer ${accessToken}`
}
const response = await fetch('http://127.0.0.1:8000/register-node', {
const response = await fetch(`${API_BASE_URL}/register-node`, {
method: 'POST',
headers,
body: JSON.stringify(payload),
@@ -104,7 +131,27 @@ const registerNode = async (payload: RegisterNodePayload) => {
throw new Error('Failed to register node')
}
return response.json()
return response.json() as Promise<RegisterNodeResponse>
}
const getNodeInterfaces = async (): Promise<NodeInterfacesResponse> => {
const accessToken = localStorage.getItem('access_token')
const headers: Record<string, string> = {}
if (accessToken) {
headers.Authorization = `Bearer ${accessToken}`
}
const response = await fetch(`${API_BASE_URL}/spock/node-interfaces`, {
method: 'GET',
headers,
})
if (!response.ok) {
throw new Error('Failed to get node interfaces')
}
return response.json() as Promise<NodeInterfacesResponse>
}
function App() {
@@ -116,8 +163,42 @@ function App() {
const [tokenError, setTokenError] = useState('')
const [registerStatus, setRegisterStatus] = useState<RegisterStatus>('idle')
const [registerError, setRegisterError] = useState('')
const [nodes, setNodes] = useState<NodeInterface[]>([])
const [nodesStatus, setNodesStatus] = useState<NodesStatus>('idle')
const [nodesError, setNodesError] = useState('')
const nextTheme = theme === 'light' ? 'dark' : 'light'
const loadNodeInterfaces = async () => {
setNodesStatus('loading')
setNodesError('')
try {
const nodeInterfacesResponse = await getNodeInterfaces()
if (nodeInterfacesResponse.status !== 'success') {
throw new Error(
nodeInterfacesResponse.message ?? 'Failed to get node interfaces',
)
}
setNodes(nodeInterfacesResponse.nodes)
setNodesStatus('success')
} catch (error) {
setNodesStatus('error')
setNodesError(
error instanceof Error
? error.message
: 'Failed to get node interfaces',
)
}
}
useEffect(() => {
if (activePage === 'nodes') {
void loadNodeInterfaces()
}
}, [activePage])
const selectPage = (page: PageId) => {
setActivePage(page)
savePage(page)
@@ -140,6 +221,7 @@ function App() {
try {
await getSessionToken()
setTokenStatus('success')
await loadNodeInterfaces()
} catch (error) {
setTokenStatus('error')
setTokenError(
@@ -152,10 +234,12 @@ function App() {
event: React.FormEvent<HTMLFormElement>,
) => {
event.preventDefault()
const form = event.currentTarget
setRegisterStatus('loading')
setRegisterError('')
const formData = new FormData(event.currentTarget)
const formData = new FormData(form)
const payload: RegisterNodePayload = {
node_name: String(formData.get('node_name') ?? ''),
host: String(formData.get('host') ?? ''),
@@ -170,9 +254,14 @@ function App() {
console.log('Node registration response:', registerResponse)
if (registerResponse.status !== 'success') {
throw new Error(registerResponse.message ?? 'Failed to register node')
}
setRegisterStatus('success')
event.currentTarget.reset()
form.reset()
setIsRegisterFormOpen(false)
window.location.reload()
} catch (error) {
setRegisterStatus('error')
setRegisterError(
@@ -289,6 +378,10 @@ function App() {
<p className="status-message error">{registerError}</p>
)}
{nodesStatus === 'error' && (
<p className="status-message error">{nodesError}</p>
)}
{isRegisterFormOpen ? (
<form className="register-form" onSubmit={handleRegisterNode}>
<div className="form-grid">
@@ -348,6 +441,39 @@ function App() {
</div>
</form>
) : null}
<div className="nodes-table-wrap">
{nodesStatus === 'loading' ? (
<p className="table-state">Loading nodes...</p>
) : nodes.length > 0 ? (
<table className="nodes-table">
<thead>
<tr>
<th>Node ID</th>
<th>Node Name</th>
<th>Host</th>
<th>Port</th>
<th>DB Name</th>
<th>DB Username</th>
</tr>
</thead>
<tbody>
{nodes.map((node) => (
<tr key={node.if_id}>
<td>{node.if_nodeid}</td>
<td>{node.if_name}</td>
<td>{node.host}</td>
<td>{node.port}</td>
<td>{node.dbname}</td>
<td>{node.user}</td>
</tr>
))}
</tbody>
</table>
) : (
<p className="table-state">No nodes found.</p>
)}
</div>
</section>
)}