import React, { useState, useEffect, useRef } from 'react'; import { Activity, Cpu, HardDrive, Terminal, Settings, RefreshCw, CheckCircle, XCircle, Zap, Flame, Server, AlertTriangle, Play, Search, Code, FileCode, Clock, ChevronDown, ChevronUp, ArrowRight, Sliders } from 'lucide-react'; import sideBarLogo from './assets/side-bar-logo.png'; import { API_BASE, apiFetch } from './api'; function App() { const [token, setToken] = useState(localStorage.getItem('rmm_token') || ''); const [loginUsername, setLoginUsername] = useState(''); const [loginPassword, setLoginPassword] = useState(''); const [loginError, setLoginError] = useState(''); const [activeTab, setActiveTab] = useState('dashboard'); // 'dashboard' | 'editor' const [clients, setClients] = useState({}); const [telemetry, setTelemetry] = useState({}); const [logs, setLogs] = useState({}); const [whitelist, setWhitelist] = useState({}); // Remote video fetch state const [fileTransfers, setFileTransfers] = useState({}); const [videoNameInputs, setVideoNameInputs] = useState({}); const [shiftPathInputs, setShiftPathInputs] = useState({}); const [searchInputs, setSearchInputs] = useState({}); // Dispatcher form state const [selectedClients, setSelectedClients] = useState([]); const [selectedCommand, setSelectedCommand] = useState(''); const [manualClient, setManualClient] = useState(''); const [manualCommand, setManualCommand] = useState(''); // Whitelist config editor state const [editorText, setEditorText] = useState('{\n "nt": {},\n "posix": {}\n}'); const [jsonError, setJsonError] = useState(null); // Real-time JSON validation error const [toast, setToast] = useState(null); const [isSyncing, setIsSyncing] = useState(false); const [filterClient, setFilterClient] = useState('all'); const [nodeFilter, setNodeFilter] = useState('all'); // 'all' | 'online' | 'offline' const [searchQuery, setSearchQuery] = useState(''); // Live search filter for clients const [expandedClients, setExpandedClients] = useState({}); // Expanded telemetry details for offline nodes const terminalRef = useRef(null); const showToast = (message, type = 'success') => { setToast({ message, type }); setTimeout(() => setToast(null), 4000); }; // 1. Initial configuration bootstrap const fetchWhitelist = async () => { try { const response = await apiFetch(`${API_BASE}/api/get-raw-commands`); if (response.ok) { const data = await response.json(); setWhitelist(data); setEditorText(JSON.stringify(data, null, 2)); } } catch (err) { console.error('Failed to load raw commands whitelist:', err); } }; // 2. Continuous telemetry & log sync polling const syncFleetData = async () => { setIsSyncing(true); try { // Sync active clients registry const clientsRes = await apiFetch(`${API_BASE}/api/clients`); if (clientsRes.ok) { const clientsData = await clientsRes.json(); setClients(clientsData); } // Sync active telemetry details const telRes = await apiFetch(`${API_BASE}/api/telemetry`); if (telRes.ok) { const telData = await telRes.json(); setTelemetry(telData); } // Sync circular history logs const logsRes = await apiFetch(`${API_BASE}/api/logs`); if (logsRes.ok) { const logsData = await logsRes.json(); setLogs(logsData); } // Sync remote video fetch transfer states const ftRes = await apiFetch(`${API_BASE}/api/file-transfers`); if (ftRes.ok) { setFileTransfers(await ftRes.json()); } } catch (err) { console.error('Network sync failure:', err); } finally { setIsSyncing(false); } }; useEffect(() => { const handleUnauthorized = () => { setToken(''); }; window.addEventListener('rmm_unauthorized', handleUnauthorized); return () => window.removeEventListener('rmm_unauthorized', handleUnauthorized); }, []); useEffect(() => { if (!token) return; fetchWhitelist(); syncFleetData(); // Set up rapid 3-second fleet synchronization loop const syncInterval = setInterval(syncFleetData, 3000); return () => clearInterval(syncInterval); }, [token]); const handleLogin = async (e) => { e.preventDefault(); setLoginError(''); try { const response = await fetch(`${API_BASE}/api/login`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username: loginUsername, password: loginPassword }) }); const data = await response.json(); if (response.ok) { localStorage.setItem('rmm_token', data.token); setToken(data.token); setLoginPassword(''); showToast('Login successful!', 'success'); } else { setLoginError(data.detail || 'Login failed. Invalid username or password.'); } } catch (err) { setLoginError('Cannot connect to RMM backend server.'); } }; const handleRequestFile = async (clientId, overrideName) => { const filename = (overrideName || videoNameInputs[clientId] || '').trim(); if (!filename) { showToast('Enter a video file name first.', 'error'); return; } try { const response = await apiFetch( `${API_BASE}/api/request-file?client_id=${encodeURIComponent(clientId)}&filename=${encodeURIComponent(filename)}`, { method: 'POST' } ); if (response.ok) { showToast(`Requested '${filename}' from ${clientId}`); syncFleetData(); } else { const data = await response.json().catch(() => ({})); showToast(data.detail || 'Failed to request file.', 'error'); } } catch (err) { showToast('Cannot connect to RMM backend server.', 'error'); } }; const handleSaveShiftPath = async (clientId) => { const path = (shiftPathInputs[clientId] ?? clients[clientId]?.shift_path ?? '').trim(); try { const response = await apiFetch( `${API_BASE}/api/set-shift-path?client_id=${encodeURIComponent(clientId)}&shift_path=${encodeURIComponent(path)}`, { method: 'POST' } ); if (response.ok) { showToast(`SHIFT path saved for ${clientId}`); syncFleetData(); } else { const data = await response.json().catch(() => ({})); showToast(data.detail || 'Failed to save SHIFT path.', 'error'); } } catch (err) { showToast('Cannot connect to RMM backend server.', 'error'); } }; const handleSearchVideos = async (clientId) => { const query = (searchInputs[clientId] || '').trim(); if (!query) { showToast('Enter a search term first (e.g. a date like 20260716).', 'error'); return; } try { const response = await apiFetch( `${API_BASE}/api/request-search?client_id=${encodeURIComponent(clientId)}&query=${encodeURIComponent(query)}`, { method: 'POST' } ); if (response.ok) { showToast(`Searching '${query}' on ${clientId}...`); syncFleetData(); } else { const data = await response.json().catch(() => ({})); showToast(data.detail || 'Failed to start search.', 'error'); } } catch (err) { showToast('Cannot connect to RMM backend server.', 'error'); } }; const handleCancelUpload = async (clientId, filename) => { try { const response = await apiFetch( `${API_BASE}/api/cancel-upload?client_id=${encodeURIComponent(clientId)}&filename=${encodeURIComponent(filename)}`, { method: 'POST' } ); if (response.ok) { showToast(`Cancelled upload for '${filename}'`); syncFleetData(); } else { const data = await response.json().catch(() => ({})); showToast(data.detail || 'Failed to cancel upload.', 'error'); } } catch (err) { showToast('Cannot connect to server.', 'error'); } }; const handleLogout = () => { localStorage.removeItem('rmm_token'); setToken(''); setClients({}); setTelemetry({}); setLogs({}); showToast('Logged out successfully.', 'success'); }; // Scroll terminal logs to bottom automatically when new actions populate, // but only if the user is already looking at the latest logs (near the bottom)! // If they scrolled up to inspect an error, we freeze the screen scroll. useEffect(() => { if (terminalRef.current) { const { scrollTop, scrollHeight, clientHeight } = terminalRef.current; // Define a 120px threshold close to the bottom const isNearBottom = scrollHeight - scrollTop - clientHeight < 120; const isFirstLoad = scrollTop === 0; if (isNearBottom || isFirstLoad) { terminalRef.current.scrollTop = scrollHeight; } } }, [logs]); // Real-time JSON validation useEffect(() => { try { if (editorText.trim() === '') { setJsonError('JSON configuration cannot be empty.'); return; } JSON.parse(editorText); setJsonError(null); } catch (err) { setJsonError(err.message); } }, [editorText]); // Dispatch command to client execution queue const handleDispatch = async (e) => { e.preventDefault(); // Resolve final list of targets let finalClientsString = ''; if (manualClient.trim()) { finalClientsString = manualClient.trim(); } else if (selectedClients.length > 0) { finalClientsString = selectedClients.join(','); } const finalCommand = (manualCommand.trim() || selectedCommand).trim(); if (!finalClientsString) { showToast('Please select target nodes or specify a manual name!', 'error'); return; } if (!finalCommand) { showToast('Please specify a Whitelisted Operation Key!', 'error'); return; } try { const response = await apiFetch( `${API_BASE}/api/schedule-command?client_id=${encodeURIComponent(finalClientsString)}&command=${encodeURIComponent(finalCommand)}`, { method: 'POST' } ); const data = await response.json(); if (response.ok) { showToast(`Operation batch successfully dispatched to: ${finalClientsString}!`, 'success'); setManualCommand(''); setManualClient(''); setSelectedClients([]); syncFleetData(); } else { showToast(data.detail || 'Dispatch scheduling failed.', 'error'); } } catch (err) { showToast('Network error contacting central RMM server API.', 'error'); } }; // Dynamic Whitelist Save Config const handleSaveWhitelist = async () => { if (jsonError) { showToast('Cannot save configuration. Please resolve JSON errors first.', 'error'); return; } try { const parsedConfig = JSON.parse(editorText); const response = await apiFetch(`${API_BASE}/api/save-commands`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(parsedConfig) }); if (response.ok) { showToast('Dynamic Commands Whitelist successfully deployed to cluster!', 'success'); fetchWhitelist(); // Reload whitelists } else { const errorData = await response.json(); showToast(`Failed to deploy: ${errorData.detail}`, 'error'); } } catch (err) { showToast('Invalid JSON structure! Please audit your config syntax.', 'error'); } }; const toggleClientDetails = (clientId) => { setExpandedClients(prev => ({ ...prev, [clientId]: !prev[clientId] })); }; // Compile individual client arrays into a single global chronological timeline for terminal display const getSortedTimeline = () => { const timeline = []; Object.entries(logs).forEach(([cid, entryList]) => { // Apply system filter if (filterClient !== 'all' && cid !== filterClient) { return; } if (Array.isArray(entryList)) { entryList.forEach((logItem) => { timeline.push({ ...logItem, client_id: cid }); }); } }); // Sort ascending by ISO timestamp return timeline.sort((a, b) => new Date(a.timestamp) - new Date(b.timestamp)); }; const sortedTimelineLogs = getSortedTimeline(); const activeClients = Object.values(clients).filter(c => c.active).length; const totalClients = Object.keys(clients).length; // Filter clients based on search query AND node status tab const filteredClientEntries = Object.entries(clients).filter(([clientId, info]) => { const matchesSearch = clientId.toLowerCase().includes(searchQuery.toLowerCase()); const matchesFilter = nodeFilter === 'all' || (nodeFilter === 'online' && info.active) || (nodeFilter === 'offline' && !info.active); return matchesSearch && matchesFilter; }); if (!token) { return (
{/* Decorative background glows */}
Seekright Logo
{loginError && (
{loginError}
)}
setLoginUsername(e.target.value)} className="w-full bg-slate-950 border border-white/10 rounded-xl p-3 text-xs text-slate-200 font-semibold focus:outline-none focus:border-violet-500 focus:ring-1 focus:ring-violet-500/20 placeholder-slate-700 transition-all" />
setLoginPassword(e.target.value)} className="w-full bg-slate-950 border border-white/10 rounded-xl p-3 text-xs text-slate-200 font-semibold focus:outline-none focus:border-violet-500 focus:ring-1 focus:ring-violet-500/20 placeholder-slate-700 transition-all" />
); } return (
{/* Dynamic Toast Alerts */} {toast && (
{toast.type === 'error' ? (
) : (
)} {toast.message}
)} {/* Modern Glass Header Section */}
Seekright Logo
{/* Action Controls & Navigation tabs */}
{/* Sync indicator status badge */}
API Status: Online
{/* Main Container */}
{activeTab === 'dashboard' ? ( <> {/* Dashboard Vitals: Grid of Cards (Left/Center Column) */}
{/* Central Metrics Board — clickable filter tabs */}
{/* ALL tab */} {/* ONLINE tab */} {/* OFFLINE tab */}
{/* Vitals Node Grid Cards */}

Remote Fleet Systems Grid ({filteredClientEntries.length}) {nodeFilter !== 'all' && ( {nodeFilter === 'online' ? '🟢 Online' : '🔴 Offline'} )}

{/* Clear filter shortcut */} {nodeFilter !== 'all' && ( )} {/* Node Search Bar */}
setSearchQuery(e.target.value)} className="w-full bg-slate-950/60 border border-white/5 rounded-xl pl-9 pr-4 py-1.5 text-xs text-slate-300 placeholder-slate-500 focus:outline-none focus:border-violet-500 focus:ring-1 focus:ring-violet-500/20 transition-all" />
{filteredClientEntries.length === 0 ? (

No systems matching your query.

Make sure the agent services are actively running

) : ( filteredClientEntries.map(([clientId, info]) => { const clientTelemetry = telemetry[clientId]; const isOnline = info.active; const lastSeenDate = info.last_seen ? new Date(info.last_seen).toLocaleString() : 'Never'; const isExpanded = expandedClients[clientId] || false; const ft = fileTransfers[clientId]; {/* Render Compact Card for Offline System */ } if (!isOnline) { return (
{clientId} Offline {info.agent_version ? `v${info.agent_version}` : 'legacy'}
Last Contact {lastSeenDate}
{/* Expanded Empty Telemetry Status */} {isExpanded && (
Telemetry check-in pending. System is offline and not responding to pings.
)}
); } {/* Render Full Card for Active/Online System */ } return (
{/* Status top glow line */}
{/* Title block */}
{clientId} Active {info.agent_version ? `v${info.agent_version}` : 'legacy'}
LAST CHECK-IN {lastSeenDate}
{/* Telemetry charts row */} {clientTelemetry ? (
{/* CPU & RAM progress */}
{/* CPU Progress block */} {(() => { const cpu = clientTelemetry.cpu_percent || 0; const isWarning = cpu > 80; return (
CPU Load {cpu}% {clientTelemetry.cpu_temp !== undefined && clientTelemetry.cpu_temp !== null && ( @ {clientTelemetry.cpu_temp}°C )}
60 ? 'bg-gradient-to-r from-amber-500 to-yellow-400' : 'bg-gradient-to-r from-violet-500 to-indigo-500' }`} style={{ width: `${cpu}%` }} />
{isWarning && (
High CPU Warning
)}
); })()} {/* Memory Progress block */} {(() => { const total = clientTelemetry.memory_total_gb || 0; const free = clientTelemetry.memory_free_gb || 0; const used = (total - free).toFixed(2); const ram = clientTelemetry.memory_percent || 0; const isWarning = ram > 85; return (
Virtual RAM {ram}%
70 ? 'bg-gradient-to-r from-amber-500 to-yellow-400' : 'bg-gradient-to-r from-violet-500 to-indigo-500' }`} style={{ width: `${ram}%` }} />
Used: {used}G Free: {free}G Total: {total}G
); })()}
{/* GPU and Partition details */}
{/* Partition Storage */}
Disk Drive Space
{clientTelemetry.disks && clientTelemetry.disks.length > 0 ? ( clientTelemetry.disks.map((d, index) => { const diskTotal = d.total_gb || 0; const diskFree = d.free_gb || 0; const diskUsed = (diskTotal - diskFree).toFixed(2); // Get friendly label const diskLabel = d.label || (d.mount === '/' ? 'Computer' : (d.mount.split(/[/\\]/).pop() || 'Volume')); return (
{/* Left side: Icon, Label, Device badge, Mount path */}
{diskLabel} {d.device && ( {d.device} )} {d.device && on} {d.mount}
{/* Right side: Free Space / Total */}
{diskFree} GB free of {diskTotal} GB
{/* Progress bar */}
85 ? 'bg-gradient-to-r from-rose-500 to-red-500' : d.percent > 70 ? 'bg-gradient-to-r from-amber-500 to-yellow-500' : 'bg-gradient-to-r from-indigo-500 to-violet-500' }`} style={{ width: `${d.percent}%` }} />
{diskUsed} GB Used 85 ? "text-rose-400 font-bold" : ""}> {d.percent}% Used
); }) ) : ( No storage drives reported. )}
{/* Nvidia Core GPU Vitals */}
Nvidia GPU Accelerator
{clientTelemetry.gpus && clientTelemetry.gpus.length > 0 ? ( clientTelemetry.gpus.map((gpu, index) => (
🎮 {gpu.name} Load: {gpu.utilization}
Temp: {gpu.temp}
Fans: {gpu.fan_speed}
VRAM: {gpu.memory_used} / {gpu.memory_total || 'N/A'}
Power: {gpu.power_draw} / {gpu.power_limit || 'N/A'}
)) ) : (
No NVIDIA GPU hardware detected.
)}
) : (

Telemetry check-in pending... Waiting for dynamic vitals transmission

)} {/* Remote Video Fetch panel */}
Fetch Video From Node {/* SHIFT folder location for this node */}
setShiftPathInputs(prev => ({ ...prev, [clientId]: e.target.value }))} onKeyDown={(e) => { if (e.key === 'Enter') handleSaveShiftPath(clientId); }} className="w-full bg-slate-950/60 border border-white/5 rounded-xl pl-9 pr-3 py-2 text-xs text-slate-300 font-mono placeholder-slate-600 focus:outline-none focus:border-violet-500 focus:ring-1 focus:ring-violet-500/20 transition-all" />
{/* Search videos inside the SHIFT folder */}
setSearchInputs(prev => ({ ...prev, [clientId]: e.target.value }))} onKeyDown={(e) => { if (e.key === 'Enter') handleSearchVideos(clientId); }} className="w-full bg-slate-950/60 border border-white/5 rounded-xl pl-9 pr-3 py-2 text-xs text-slate-300 font-mono placeholder-slate-600 focus:outline-none focus:border-violet-500 focus:ring-1 focus:ring-violet-500/20 transition-all" />
{parseFloat(info.agent_version) < 3.3 && (

Search needs agent v3.3-shift — run update_agent on this node first.

)} {/* Search results */} {info.file_search && (
Results for '{info.file_search.query}' {info.file_search.searched_path && ( in {info.file_search.searched_path} )} {info.file_search.status === 'searching' && } {info.file_search.status === 'done' ? `${(info.file_search.results || []).length} found` : info.file_search.status}
{info.file_search.error && (

{info.file_search.error}

)} {info.file_search.status === 'done' && (info.file_search.results || []).length > 0 && (
{info.file_search.results.map((r) => (

{r.name}

{r.size_mb !== undefined ? `${r.size_mb} MB` : ''}{r.modified ? ` · ${r.modified}` : ''}

))}
)}
)}
setVideoNameInputs(prev => ({ ...prev, [clientId]: e.target.value }))} onKeyDown={(e) => { if (e.key === 'Enter') handleRequestFile(clientId); }} className="flex-1 bg-slate-950/60 border border-white/5 rounded-xl px-3 py-2 text-xs text-slate-300 font-mono placeholder-slate-600 focus:outline-none focus:border-violet-500 focus:ring-1 focus:ring-violet-500/20 transition-all" />
{ft && (
{ft.filename} {(ft.status === 'requested' || ft.status === 'searching' || ft.status === 'uploading') && ( )} {ft.status === 'ready' && } {(ft.status === 'not_found' || ft.status === 'error') && } {ft.status}
{ft.message && (

{ft.message}

)} {ft.progress_percent !== undefined && ft.progress_percent !== null && (
)} {(ft.status === 'requested' || ft.status === 'searching' || ft.status === 'uploading') && (
)} {ft.status === 'ready' && ( )}
)}
); }) )}
{/* Maintenance Command Dispatch deck (Right sidebar) */}

Maintenance Dispatcher

Send a whitelisted command down to a node

{/* Select target node check list */}
{Object.entries(clients).length === 0 ? ( No registered nodes found. ) : ( Object.entries(clients).map(([id, info]) => { const isSelected = selectedClients.includes(id); return ( ); }) )}
{/* Manual Target target ID */}
setManualClient(e.target.value)} className="w-full bg-slate-950 border border-white/10 rounded-xl p-3 text-xs text-slate-200 font-semibold focus:outline-none focus:border-violet-500 focus:ring-1 focus:ring-violet-500/20 placeholder-slate-600 transition-all focus-glow-violet" />
{/* Select command key */}
{/* Manual command command key */}
setManualCommand(e.target.value)} className="w-full bg-slate-950 border border-white/10 rounded-xl p-3 text-xs text-slate-200 font-semibold focus:outline-none focus:border-violet-500 focus:ring-1 focus:ring-violet-500/20 placeholder-slate-600 transition-all focus-glow-violet" />
{/* Fire execution button */}
) : activeTab === 'editor' ? ( /* Visual Whitelist JSON Configuration Editor */

Visual Commands whitelist Editor

Permitted operations are checked against whitelist config and pushed to nodes without restarts.

{/* JSON Validation Status Badge */}
{jsonError ? ( Invalid JSON Config ) : ( Valid JSON Config )}
{/* IDE Editor UI wrapper */}
{/* Editor Tab Bar */}
commands.json
JSON