feat: Tenable-style patch_status - pending_updates, last_patch, reboot_pending across full stack

This commit is contained in:
AetherForge
2026-05-30 23:11:32 -07:00
parent 9232f4c448
commit 4207f6c21b
43 changed files with 4359 additions and 180 deletions

View File

@@ -1,4 +1,4 @@
import { useState, useEffect, useMemo, useCallback } from 'react';
import { useState, useEffect, useMemo, useCallback, useRef } from 'react';
import { api } from '../api/client';
import { useWebSocket } from '../hooks/useWebSocket';
import type { Agent, HashrateSample, ServerInfo } from '../types';
@@ -93,13 +93,25 @@ export default function AgentsPage() {
const [tagsDraft, setTagsDraft] = useState('');
const [metaSaving, setMetaSaving] = useState(false);
const [metaMsg, setMetaMsg] = useState('');
const isConnectedRef = useRef(isConnected);
isConnectedRef.current = isConnected;
useEffect(() => {
let cancelled = false;
api.listAgents()
.then(setAgents)
.catch((err) => setLoadError(err instanceof Error ? err.message : 'Failed to load agents'))
.finally(() => setLoading(false));
.then((data) => {
if (!cancelled && !isConnectedRef.current) setAgents(data);
})
.catch((err) => {
if (!cancelled) setLoadError(err instanceof Error ? err.message : 'Failed to load agents');
})
.finally(() => {
if (!cancelled) setLoading(false);
});
api.getServerInfo().then(setServerInfo).catch(() => {});
return () => {
cancelled = true;
};
}, []);
useEffect(() => {
@@ -214,6 +226,7 @@ export default function AgentsPage() {
await api.sendBulkCommand(onlineIds, action);
} catch (err) {
console.error(err);
alert(err instanceof Error ? err.message : 'Bulk command failed');
} finally {
setBulkBusy(false);
}