From f196cbc79dfd5c7a6b296c35fef53fb556780960 Mon Sep 17 00:00:00 2001 From: Junyan Qin Date: Sun, 19 Apr 2026 14:41:41 +0800 Subject: [PATCH] feat(web): show active sandbox details in dashboard Box status popover Fetch box sessions alongside status and display each active sandbox in the popover with session ID, image, resources (CPU/memory), and last used time. --- .../overview-cards/SystemStatusCards.tsx | 39 ++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/web/src/app/home/monitoring/components/overview-cards/SystemStatusCards.tsx b/web/src/app/home/monitoring/components/overview-cards/SystemStatusCards.tsx index 6db46959..bb3d9e71 100644 --- a/web/src/app/home/monitoring/components/overview-cards/SystemStatusCards.tsx +++ b/web/src/app/home/monitoring/components/overview-cards/SystemStatusCards.tsx @@ -7,6 +7,8 @@ import { CircleX, Loader2, ChevronDown, + Container, + Clock, } from 'lucide-react'; import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card'; import { @@ -17,6 +19,7 @@ import { import { ApiRespPluginSystemStatus, ApiRespBoxStatus, + BoxSessionInfo, } from '@/app/infra/entities/api'; import { httpClient } from '@/app/infra/http/HttpClient'; @@ -41,16 +44,19 @@ export default function SystemStatusCard({ const [pluginStatus, setPluginStatus] = useState(null); const [boxStatus, setBoxStatus] = useState(null); + const [boxSessions, setBoxSessions] = useState([]); const [loading, setLoading] = useState(true); const fetchStatus = useCallback(async () => { try { - const [plugin, box] = await Promise.all([ + const [plugin, box, sessions] = await Promise.all([ httpClient.getPluginSystemStatus().catch(() => null), httpClient.getBoxStatus().catch(() => null), + httpClient.getBoxSessions().catch(() => [] as BoxSessionInfo[]), ]); setPluginStatus(plugin); setBoxStatus(box); + setBoxSessions(sessions); } finally { setLoading(false); } @@ -209,6 +215,37 @@ export default function SystemStatusCard({ )} )} + {boxSessions.length > 0 && ( +
+ {boxSessions.map((session) => ( +
+
+ + + {session.session_id} + +
+
+ + {session.image.split(':').pop() || session.image} + + + {session.cpus} CPU / {session.memory_mb}MB + +
+
+ + + {new Date(session.last_used_at).toLocaleString()} + +
+
+ ))} +
+ )}