mirror of
https://github.com/bunny-lab-io/Borealis.git
synced 2025-09-11 08:08:43 -06:00
Collect and expose agent device details
This commit is contained in:
@@ -18,32 +18,51 @@ import {
|
||||
export default function DeviceDetails({ device, onBack }) {
|
||||
const [tab, setTab] = useState(0);
|
||||
const [agent, setAgent] = useState(device || {});
|
||||
const [details, setDetails] = useState({});
|
||||
|
||||
useEffect(() => {
|
||||
if (!device || !device.id) return;
|
||||
const fetchAgent = async () => {
|
||||
const load = async () => {
|
||||
try {
|
||||
const res = await fetch("/api/agents");
|
||||
const data = await res.json();
|
||||
if (data && data[device.id]) {
|
||||
setAgent({ id: device.id, ...data[device.id] });
|
||||
const [agentsRes, detailsRes] = await Promise.all([
|
||||
fetch("/api/agents"),
|
||||
fetch(`/api/agent/details/${device.id}`)
|
||||
]);
|
||||
const agentsData = await agentsRes.json();
|
||||
if (agentsData && agentsData[device.id]) {
|
||||
setAgent({ id: device.id, ...agentsData[device.id] });
|
||||
}
|
||||
const detailData = await detailsRes.json();
|
||||
setDetails(detailData || {});
|
||||
} catch (e) {
|
||||
console.warn("Failed to load agent", e);
|
||||
console.warn("Failed to load device info", e);
|
||||
}
|
||||
};
|
||||
fetchAgent();
|
||||
load();
|
||||
}, [device]);
|
||||
|
||||
const formatBytes = (val) => {
|
||||
if (val === undefined || val === null || val === "unknown") return "unknown";
|
||||
let num = Number(val);
|
||||
const units = ["B", "KB", "MB", "GB", "TB"];
|
||||
let i = 0;
|
||||
while (num >= 1024 && i < units.length - 1) {
|
||||
num /= 1024;
|
||||
i++;
|
||||
}
|
||||
return `${num.toFixed(1)} ${units[i]}`;
|
||||
};
|
||||
|
||||
const summary = details.summary || {};
|
||||
const summaryItems = [
|
||||
{ label: "Device Name", value: agent.hostname || device?.hostname || "unknown" },
|
||||
{ label: "Description", value: "unknown" },
|
||||
{ label: "Operating System", value: agent.agent_operating_system || "unknown" },
|
||||
{ label: "Last User", value: "unknown" },
|
||||
{ label: "Internal IP", value: agent.internal_ip || "unknown" },
|
||||
{ label: "External IP", value: "unknown" },
|
||||
{ label: "Last Reboot", value: agent.last_reboot || "unknown" },
|
||||
{ label: "Created", value: agent.created || "unknown" }
|
||||
{ label: "Device Name", value: summary.hostname || agent.hostname || device?.hostname || "unknown" },
|
||||
{ label: "Description", value: summary.description || "unknown" },
|
||||
{ label: "Operating System", value: summary.operating_system || agent.agent_operating_system || "unknown" },
|
||||
{ label: "Last User", value: summary.last_user || "unknown" },
|
||||
{ label: "Internal IP", value: summary.internal_ip || "unknown" },
|
||||
{ label: "External IP", value: summary.external_ip || "unknown" },
|
||||
{ label: "Last Reboot", value: summary.last_reboot || "unknown" },
|
||||
{ label: "Created", value: summary.created || "unknown" }
|
||||
];
|
||||
|
||||
const renderSummary = () => (
|
||||
@@ -78,6 +97,121 @@ export default function DeviceDetails({ device, onBack }) {
|
||||
</Table>
|
||||
);
|
||||
|
||||
const renderSoftware = () => {
|
||||
const rows = details.software || [];
|
||||
if (!rows.length) return placeholderTable(["Software Name", "Version", "Action"]);
|
||||
return (
|
||||
<Table size="small">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell>Software Name</TableCell>
|
||||
<TableCell>Version</TableCell>
|
||||
<TableCell>Action</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{rows.map((s, i) => (
|
||||
<TableRow key={`${s.name}-${i}`}>
|
||||
<TableCell>{s.name}</TableCell>
|
||||
<TableCell>{s.version}</TableCell>
|
||||
<TableCell></TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
);
|
||||
};
|
||||
|
||||
const renderMemory = () => {
|
||||
const rows = details.memory || [];
|
||||
if (!rows.length) return placeholderTable(["Slot", "Speed", "Serial Number", "Capacity"]);
|
||||
return (
|
||||
<Table size="small">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell>Slot</TableCell>
|
||||
<TableCell>Speed</TableCell>
|
||||
<TableCell>Serial Number</TableCell>
|
||||
<TableCell>Capacity</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{rows.map((m, i) => (
|
||||
<TableRow key={`${m.slot}-${i}`}>
|
||||
<TableCell>{m.slot}</TableCell>
|
||||
<TableCell>{m.speed}</TableCell>
|
||||
<TableCell>{m.serial}</TableCell>
|
||||
<TableCell>{formatBytes(m.capacity)}</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
);
|
||||
};
|
||||
|
||||
const renderStorage = () => {
|
||||
const rows = details.storage || [];
|
||||
if (!rows.length)
|
||||
return placeholderTable(["Drive Letter", "Disk Type", "Usage", "Total Size", "Free %"]);
|
||||
return (
|
||||
<Table size="small">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell>Drive Letter</TableCell>
|
||||
<TableCell>Disk Type</TableCell>
|
||||
<TableCell>Usage</TableCell>
|
||||
<TableCell>Total Size</TableCell>
|
||||
<TableCell>Free %</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{rows.map((d, i) => (
|
||||
<TableRow key={`${d.drive}-${i}`}>
|
||||
<TableCell>{d.drive}</TableCell>
|
||||
<TableCell>{d.disk_type}</TableCell>
|
||||
<TableCell>
|
||||
{d.usage !== undefined && d.usage !== null && d.usage !== "unknown"
|
||||
? `${d.usage.toFixed ? d.usage.toFixed(1) : d.usage}%`
|
||||
: "unknown"}
|
||||
</TableCell>
|
||||
<TableCell>{formatBytes(d.total)}</TableCell>
|
||||
<TableCell>
|
||||
{d.free !== undefined && d.free !== null && d.free !== "unknown"
|
||||
? `${d.free.toFixed ? d.free.toFixed(1) : d.free}%`
|
||||
: "unknown"}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
);
|
||||
};
|
||||
|
||||
const renderNetwork = () => {
|
||||
const rows = details.network || [];
|
||||
if (!rows.length) return placeholderTable(["Adapter", "IP Address", "MAC Address"]);
|
||||
return (
|
||||
<Table size="small">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell>Adapter</TableCell>
|
||||
<TableCell>IP Address</TableCell>
|
||||
<TableCell>MAC Address</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{rows.map((n, i) => (
|
||||
<TableRow key={`${n.adapter}-${i}`}>
|
||||
<TableCell>{n.adapter}</TableCell>
|
||||
<TableCell>{(n.ips || []).join(", ")}</TableCell>
|
||||
<TableCell>{n.mac}</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
);
|
||||
};
|
||||
|
||||
const tabs = [
|
||||
{ label: "Summary", content: renderSummary() },
|
||||
{
|
||||
@@ -91,28 +225,10 @@ export default function DeviceDetails({ device, onBack }) {
|
||||
"Enabled/Disabled Status"
|
||||
])
|
||||
},
|
||||
{
|
||||
label: "Software",
|
||||
content: placeholderTable(["Software Name", "Version", "Action"])
|
||||
},
|
||||
{
|
||||
label: "Memory",
|
||||
content: placeholderTable(["Slot", "Speed", "Serial Number", "Capacity"])
|
||||
},
|
||||
{
|
||||
label: "Storage",
|
||||
content: placeholderTable([
|
||||
"Drive Letter",
|
||||
"Disk Type",
|
||||
"Usage",
|
||||
"Total Size",
|
||||
"Free %"
|
||||
])
|
||||
},
|
||||
{
|
||||
label: "Network",
|
||||
content: placeholderTable(["Adapter", "IP Address", "MAC Address"])
|
||||
}
|
||||
{ label: "Software", content: renderSoftware() },
|
||||
{ label: "Memory", content: renderMemory() },
|
||||
{ label: "Storage", content: renderStorage() },
|
||||
{ label: "Network", content: renderNetwork() }
|
||||
];
|
||||
|
||||
return (
|
||||
|
Reference in New Issue
Block a user