import React, { useEffect, useMemo, useState } from "react"; function severityForEventId(eventId) { const id = parseInt(eventId, 10); const high = new Set([1, 3, 8, 10]); const med = new Set([5, 6, 7, 11, 22]); if (high.has(id)) return "high"; if (med.has(id)) return "medium"; return "low"; } export default function ComputerDetailsModal({ open, computer, onClose, onAskAI }) { const [tab, setTab] = useState("overview"); const [loading, setLoading] = useState(false); const [details, setDetails] = useState(null); const [search, setSearch] = useState(""); // JSON viewer state const [jsonOpen, setJsonOpen] = useState(false); const [jsonTitle, setJsonTitle] = useState(""); const [jsonData, setJsonData] = useState(null); useEffect(() => { if (!open || !computer?.name) return; let cancelled = false; async function load() { try { setLoading(true); const r = await fetch(`/api/computer/${encodeURIComponent(computer.name)}`); const d = await r.json(); if (!cancelled) setDetails(d); } catch (e) { console.error("details error", e); } finally { if (!cancelled) setLoading(false); } } load(); return () => { cancelled = true; }; }, [open, computer?.name]); const filteredSysmon = useMemo(() => { const list = details?.sysmon_events || []; const q = search.trim().toLowerCase(); if (!q) return list; return list.filter((ev) => { const msg = (ev.message || "").toLowerCase(); const type = (ev.event_type || "").toLowerCase(); const id = String(ev.event_id ?? ""); return msg.includes(q) || type.includes(q) || id.includes(q); }); }, [details, search]); function openJson(ev) { // server ти враќа: { event_id, event_type, message, timestamp, details } setJsonTitle(`Sysmon Event ${ev?.event_id ?? ""} • ${ev?.event_type ?? ""}`); setJsonData(ev?.details ?? ev); // ако нема details, покажи цел event setJsonOpen(true); } function closeJson() { setJsonOpen(false); setJsonTitle(""); setJsonData(null); } if (!open) return null; return ( <>
e.stopPropagation()}>
{computer.name}
{computer.ip || "—"} • {computer.user || "—"} • {computer.status || "—"}
{loading &&
Loading…
} {!loading && details && tab === "overview" && (
System Overview
User: {details.computer?.user}
IP: {details.computer?.ip}
OS: {details.computer?.os}
First seen: {details.computer?.first_seen}
Last seen: {details.computer?.last_seen}
Total logs: {details.computer?.total_logs}
)} {!loading && details && tab === "sysmon" && (
Sysmon Events
{filteredSysmon.length} events setSearch(e.target.value)} />
{filteredSysmon.slice(0, 200).map((ev, idx) => { const sev = severityForEventId(ev.event_id); return ( ); })} {filteredSysmon.length === 0 && ( )}
Time ID Type Severity Message View
{ev.timestamp ? new Date(ev.timestamp).toLocaleTimeString() : "—"} {ev.event_id} {ev.event_type} {sev.toUpperCase()} {(ev.message || "").slice(0, 140)}
No sysmon events.
{filteredSysmon.length > 200 && (
Showing first 200 (for speed).
)}
)} {!loading && details && tab === "processes" && (
Recent Processes
{(details.recent_processes || []).slice(0, 150).map((p, idx) => ( ))} {(details.recent_processes || []).length === 0 && ( )}
Time PID Name User CPU% RAM MB Cmdline
{p.timestamp ? new Date(p.timestamp).toLocaleTimeString() : "—"} {p.pid} {p.name} {p.username || "—"} {p.cpu_percent ?? 0} {p.memory_mb ?? 0} {(p.cmdline || "").slice(0, 120)}
No process data.
)} {!loading && details && tab === "network" && (
Network Connections
{(details.network_connections || []).slice(0, 150).map((n, idx) => ( ))} {(details.network_connections || []).length === 0 && ( )}
Time PID Process Local Remote Status
{n.timestamp ? new Date(n.timestamp).toLocaleTimeString() : "—"} {n.pid} {n.process_name || "—"} {n.local_address || "—"} {n.remote_address || "—"} {n.status || "—"}
No network data.
)} {!loading && !details &&
No details.
}
{/* JSON VIEWER MODAL */} {jsonOpen && (
e.stopPropagation()} style={{ width: "min(900px, 96vw)" }}>
View JSON
{jsonTitle}
                {JSON.stringify(jsonData ?? {}, null, 2)}
              
)} ); }