1import { useState, useEffect, useRef } from 'react';
8} from '@/components/ui/dialog';
9import { Button } from '@/components/ui/button';
10import { Input } from '@/components/ui/input';
11import { Label } from '@/components/ui/label';
12import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
13import { Monitor, X, Loader2, AlertCircle } from 'lucide-react';
14import { Alert, AlertDescription } from '@/components/ui/alert';
17 * RemoteDesktop Component
18 * Provides web-based remote desktop access using MeshCentral
20export function RemoteDesktop({ agent, open, onClose }) {
21 const [loading, setLoading] = useState(false);
22 const [error, setError] = useState(null);
23 const [connectionUrl, setConnectionUrl] = useState(null);
24 const [meshInfo, setMeshInfo] = useState(null);
25 const iframeRef = useRef(null);
33 const loadMeshCentralUrl = async () => {
38 // Get MeshCentral URL for this agent
39 const agentId = agent.agent_uuid || agent.agent_id;
40 const response = await fetch(`/api/agent/${agentId}/meshcentral-url`);
43 const errorData = await response.json();
44 throw new Error(errorData.error || 'Failed to get MeshCentral URL');
47 const data = await response.json();
51 console.error('Failed to load MeshCentral URL:', err);
52 setError(err.message);
58 const handleConnect = () => {
59 if (meshInfo?.remoteDesktopUrl) {
60 // Open MeshCentral in new window
61 window.open(meshInfo.remoteDesktopUrl, '_blank', 'width=1400,height=900');
65 const handleConnectInline = () => {
66 if (meshInfo?.remoteDesktopUrl) {
67 setConnectionUrl(meshInfo.remoteDesktopUrl);
71 const handleDisconnect = () => {
72 setConnectionUrl(null);
75 const handleClose = () => {
80 if (!agent) return null;
83 <Dialog open={open} onOpenChange={handleClose}>
84 <DialogContent className="max-w-[95vw] max-h-[95vh] w-[1400px] h-[900px]">
86 <DialogTitle className="flex items-center gap-2">
87 <Monitor className="h-5 w-5" />
88 Remote Desktop - {agent.hostname || agent.agent_id}
91 {agent.last_ip && `Connecting to ${agent.last_ip}`}
96 <div className="space-y-4 py-4">
98 <Alert variant="destructive">
99 <AlertCircle className="h-4 w-4" />
100 <AlertDescription>{error}</AlertDescription>
105 <div className="flex items-center justify-center py-8">
106 <Loader2 className="h-8 w-8 animate-spin text-primary" />
107 <span className="ml-2">Loading MeshCentral connection...</span>
110 <div className="space-y-4">
111 <div className="text-sm space-y-2">
112 <p className="font-medium">MeshCentral Remote Desktop</p>
113 <ul className="space-y-1 text-muted-foreground">
114 <li>• Hostname: {meshInfo.hostname}</li>
115 <li>• Agent ID: {meshInfo.agentId}</li>
116 <li>• Node ID: {meshInfo.meshcentralNodeId}</li>
120 <div className="flex gap-2 pt-4">
121 <Button onClick={handleConnect} className="flex-1">
122 <Monitor className="mr-2 h-4 w-4" />
125 <Button variant="outline" onClick={handleConnectInline} className="flex-1">
130 <Button variant="outline" onClick={handleClose} className="w-full">
135 <div className="text-center py-8 text-muted-foreground">
136 <AlertCircle className="h-8 w-8 mx-auto mb-2" />
137 <p>MeshCentral not configured for this agent</p>
142 <div className="flex flex-col h-full">
143 <div className="flex items-center justify-between mb-2">
144 <span className="text-sm text-muted-foreground">
145 MeshCentral Remote Desktop - {meshInfo?.hostname}
147 <Button variant="destructive" size="sm" onClick={handleDisconnect}>
148 <X className="h-4 w-4 mr-1" />
153 <div className="flex-1 border rounded-lg overflow-hidden bg-black">
157 className="w-full h-full"
158 title="MeshCentral Remote Desktop"
159 allow="clipboard-read; clipboard-write"
169export default RemoteDesktop;