--Added delete funct
	--Added uuid funct
This commit is contained in:
george committed 2026-09-09 16:04:34 +05:30
1 parent eb16c93fb0
commit 79e10f9cad
2 files changed
+128 -34

No files matched your search

+25 -3
View File
@@ -265,7 +265,8 @@
} }
.primary-button, .primary-button,
.secondary-button { .secondary-button,
.danger-button {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@@ -292,7 +293,8 @@
} }
.primary-button:disabled, .primary-button:disabled,
.secondary-button:disabled { .secondary-button:disabled,
.danger-button:disabled {
cursor: not-allowed; cursor: not-allowed;
opacity: 0.65; opacity: 0.65;
} }
@@ -315,11 +317,31 @@
.primary-button:focus-visible, .primary-button:focus-visible,
.secondary-button:focus-visible, .secondary-button:focus-visible,
.danger-button:focus-visible,
.register-form input:focus-visible { .register-form input:focus-visible {
outline: 2px solid var(--accent); outline: 2px solid var(--accent);
outline-offset: 2px; outline-offset: 2px;
} }
.danger-button {
min-height: 34px;
border: 1px solid #ef4444;
background: #ef4444;
color: #ffffff;
font-size: 14px;
padding-inline: 12px;
}
.danger-button:hover {
border-color: #dc2626;
background: #dc2626;
}
.danger-button:disabled:hover {
border-color: #ef4444;
background: #ef4444;
}
.status-message { .status-message {
width: fit-content; width: fit-content;
margin-bottom: 18px; margin-bottom: 18px;
@@ -410,7 +432,7 @@
.nodes-table { .nodes-table {
width: 100%; width: 100%;
min-width: 720px; min-width: 820px;
border-collapse: collapse; border-collapse: collapse;
color: var(--text-h); color: var(--text-h);
font-size: 14px; font-size: 14px;
+103 -31
View File
@@ -37,6 +37,7 @@ type NodeInterface = {
port: number port: number
dbname: string dbname: string
user: string user: string
uuid: string
} }
type NodeInterfacesResponse = { type NodeInterfacesResponse = {
@@ -46,6 +47,11 @@ type NodeInterfacesResponse = {
message?: string message?: string
} }
type DeleteNodeInterfaceResponse = {
status: string
message?: string
}
const getSavedTheme = (): Theme => { const getSavedTheme = (): Theme => {
try { try {
return localStorage.getItem('theme') === 'dark' ? 'dark' : 'light' return localStorage.getItem('theme') === 'dark' ? 'dark' : 'light'
@@ -154,6 +160,34 @@ const getNodeInterfaces = async (): Promise<NodeInterfacesResponse> => {
return response.json() as Promise<NodeInterfacesResponse> return response.json() as Promise<NodeInterfacesResponse>
} }
const deleteNodeInterface = async (
node: NodeInterface,
): Promise<DeleteNodeInterfaceResponse> => {
const accessToken = localStorage.getItem('access_token')
const headers: Record<string, string> = {}
const params = new URLSearchParams({
uuid: node.uuid,
})
if (accessToken) {
headers.Authorization = `Bearer ${accessToken}`
}
const response = await fetch(
`${API_BASE_URL}/spock/del-node-interfaces?${params.toString()}`,
{
method: 'DELETE',
headers,
},
)
if (!response.ok) {
throw new Error('Failed to delete node interface')
}
return response.json() as Promise<DeleteNodeInterfaceResponse>
}
function App() { function App() {
const [isCollapsed, setIsCollapsed] = useState(false) const [isCollapsed, setIsCollapsed] = useState(false)
const [activePage, setActivePage] = useState<PageId>(getSavedPage) const [activePage, setActivePage] = useState<PageId>(getSavedPage)
@@ -166,6 +200,7 @@ function App() {
const [nodes, setNodes] = useState<NodeInterface[]>([]) const [nodes, setNodes] = useState<NodeInterface[]>([])
const [nodesStatus, setNodesStatus] = useState<NodesStatus>('idle') const [nodesStatus, setNodesStatus] = useState<NodesStatus>('idle')
const [nodesError, setNodesError] = useState('') const [nodesError, setNodesError] = useState('')
const [deletingNodeId, setDeletingNodeId] = useState<number | null>(null)
const nextTheme = theme === 'light' ? 'dark' : 'light' const nextTheme = theme === 'light' ? 'dark' : 'light'
const loadNodeInterfaces = async () => { const loadNodeInterfaces = async () => {
@@ -270,6 +305,28 @@ function App() {
} }
} }
const handleDeleteNodeClick = async (node: NodeInterface) => {
setDeletingNodeId(node.if_id)
setNodesError('')
try {
const deleteResponse = await deleteNodeInterface(node)
if (deleteResponse.status !== 'success') {
throw new Error(deleteResponse.message ?? 'Failed to delete node')
}
await loadNodeInterfaces()
} catch (error) {
setNodesStatus('error')
setNodesError(
error instanceof Error ? error.message : 'Failed to delete node',
)
} finally {
setDeletingNodeId(null)
}
}
return ( return (
<div <div
className={`app-shell theme-${theme} ${isCollapsed ? 'nav-collapsed' : ''}`} className={`app-shell theme-${theme} ${isCollapsed ? 'nav-collapsed' : ''}`}
@@ -442,38 +499,53 @@ function App() {
</form> </form>
) : null} ) : null}
<div className="nodes-table-wrap"> {!isRegisterFormOpen && (
{nodesStatus === 'loading' ? ( <div className="nodes-table-wrap">
<p className="table-state">Loading nodes...</p> {nodesStatus === 'loading' ? (
) : nodes.length > 0 ? ( <p className="table-state">Loading nodes...</p>
<table className="nodes-table"> ) : nodes.length > 0 ? (
<thead> <table className="nodes-table">
<tr> <thead>
<th>Node ID</th> <tr>
<th>Node Name</th> <th>Node ID</th>
<th>Host</th> <th>Node Name</th>
<th>Port</th> <th>Host</th>
<th>DB Name</th> <th>Port</th>
<th>DB Username</th> <th>DB Name</th>
</tr> <th>DB Username</th>
</thead> <th>Actions</th>
<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> </tr>
))} </thead>
</tbody> <tbody>
</table> {nodes.map((node) => (
) : ( <tr key={node.if_id}>
<p className="table-state">No nodes found.</p> <td>{node.if_nodeid}</td>
)} <td>{node.if_name}</td>
</div> <td>{node.host}</td>
<td>{node.port}</td>
<td>{node.dbname}</td>
<td>{node.user}</td>
<td>
<button
type="button"
className="danger-button"
disabled={deletingNodeId === node.if_id}
onClick={() => handleDeleteNodeClick(node)}
>
{deletingNodeId === node.if_id
? 'Deleting'
: 'Delete'}
</button>
</td>
</tr>
))}
</tbody>
</table>
) : (
<p className="table-state">No nodes found.</p>
)}
</div>
)}
</section> </section>
)} )}