diff --git a/application/src/components/servers/ServerTable.tsx b/application/src/components/servers/ServerTable.tsx index c73172f..8664c30 100644 --- a/application/src/components/servers/ServerTable.tsx +++ b/application/src/components/servers/ServerTable.tsx @@ -8,11 +8,14 @@ import { Input } from "@/components/ui/input"; import { Badge } from "@/components/ui/badge"; import { Progress } from "@/components/ui/progress"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger } from "@/components/ui/dropdown-menu"; +import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle } from "@/components/ui/alert-dialog"; import { RefreshCw, Search, Eye, Activity, MoreHorizontal, Pause, Play, Edit, Trash2 } from "lucide-react"; import { Server } from "@/types/server.types"; import { ServerStatusBadge } from "./ServerStatusBadge"; import { OSTypeIcon } from "./OSTypeIcon"; import { serverService } from "@/services/serverService"; +import { useToast } from "@/hooks/use-toast"; +import { pb } from "@/lib/pocketbase"; interface ServerTableProps { servers: Server[]; @@ -22,8 +25,12 @@ interface ServerTableProps { export const ServerTable = ({ servers, isLoading, onRefresh }: ServerTableProps) => { const [searchTerm, setSearchTerm] = useState(""); - const [pausedServers, setPausedServers] = useState>(new Set()); + const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); + const [selectedServer, setSelectedServer] = useState(null); + const [isDeleting, setIsDeleting] = useState(false); + const [pausingServers, setPausingServers] = useState>(new Set()); const navigate = useNavigate(); + const { toast } = useToast(); const filteredServers = servers.filter(server => server.name.toLowerCase().includes(searchTerm.toLowerCase()) || @@ -39,29 +46,105 @@ export const ServerTable = ({ servers, isLoading, onRefresh }: ServerTableProps) navigate(`/container-monitoring/${serverId}`); }; - const handlePauseResume = (serverId: string) => { - const isPaused = pausedServers.has(serverId); - if (isPaused) { - setPausedServers(prev => { + const handlePauseResume = async (server: Server) => { + const serverId = server.id; + const isPaused = server.status === "paused"; + + if (pausingServers.has(serverId)) { + return; // Already processing this server + } + + try { + setPausingServers(prev => new Set(prev).add(serverId)); + + if (isPaused) { + // Resume monitoring + await pb.collection('servers').update(serverId, { + status: "up", + last_checked: new Date().toISOString() + }); + + toast({ + title: "Server resumed", + description: `Monitoring resumed for ${server.name}`, + }); + + console.log(`Resume server monitoring: ${serverId}`); + } else { + // Pause monitoring + await pb.collection('servers').update(serverId, { + status: "paused", + last_checked: new Date().toISOString() + }); + + toast({ + title: "Server paused", + description: `Monitoring paused for ${server.name}`, + }); + + console.log(`Pause server monitoring: ${serverId}`); + } + + // Refresh the server list to show updated status + onRefresh(); + + } catch (error) { + console.error('Error updating server status:', error); + toast({ + variant: "destructive", + title: "Error", + description: `Failed to ${isPaused ? 'resume' : 'pause'} server monitoring. Please try again.`, + }); + } finally { + setPausingServers(prev => { const newSet = new Set(prev); newSet.delete(serverId); return newSet; }); - // console.log('Resume server monitoring:', serverId); - } else { - setPausedServers(prev => new Set(prev).add(serverId)); - // console.log('Pause server monitoring:', serverId); } }; const handleEdit = (serverId: string) => { // TODO: Implement edit functionality - // console.log('Edit server:', serverId); + console.log('Edit server:', serverId); }; - const handleDelete = (serverId: string) => { - // TODO: Implement delete functionality - // console.log('Delete server:', serverId); + const handleDelete = (server: Server) => { + setSelectedServer(server); + setDeleteDialogOpen(true); + }; + + const confirmDelete = async () => { + if (!selectedServer || isDeleting) return; + + try { + setIsDeleting(true); + + // Delete the server from the database + await pb.collection('servers').delete(selectedServer.id); + + toast({ + title: "Server deleted", + description: `${selectedServer.name} has been deleted successfully.`, + }); + + // Refresh the server list + onRefresh(); + + // Close the dialog + setDeleteDialogOpen(false); + setSelectedServer(null); + + } catch (error) { + console.error('Error deleting server:', error); + toast({ + variant: "destructive", + title: "Error", + description: "Failed to delete server. Please try again.", + }); + } finally { + setIsDeleting(false); + } }; if (isLoading) { @@ -81,189 +164,226 @@ export const ServerTable = ({ servers, isLoading, onRefresh }: ServerTableProps) } return ( - - -
- Servers -
-
- - setSearchTerm(e.target.value)} - className="pl-8" - /> + <> + + +
+ Servers +
+
+ + setSearchTerm(e.target.value)} + className="pl-8" + /> +
+
-
-
- - - {filteredServers.length === 0 ? ( -
-

No servers found

-
- ) : ( -
- - - - Name - Status - OS - IP Address - CPU - Memory - Disk - Uptime - Last Checked - Actions - - - - {filteredServers.map((server) => { - const cpuUsage = server.cpu_usage || 0; - const memoryUsage = server.ram_total > 0 ? (server.ram_used / server.ram_total) * 100 : 0; - const diskUsage = server.disk_total > 0 ? (server.disk_used / server.disk_total) * 100 : 0; - const isPaused = pausedServers.has(server.id); + + + {filteredServers.length === 0 ? ( +
+

No servers found

+
+ ) : ( +
+
+ + + Name + Status + OS + IP Address + CPU + Memory + Disk + Uptime + Last Checked + Actions + + + + {filteredServers.map((server) => { + const cpuUsage = server.cpu_usage || 0; + const memoryUsage = server.ram_total > 0 ? (server.ram_used / server.ram_total) * 100 : 0; + const diskUsage = server.disk_total > 0 ? (server.disk_used / server.disk_total) * 100 : 0; + const isPaused = server.status === "paused"; + const isProcessing = pausingServers.has(server.id); - return ( - - -
-
{server.name}
- -
-
- - - - -
- - {server.os_type} -
-
- - {server.ip_address} - - -
-
- {cpuUsage.toFixed(1)}% - {server.cpu_cores} cores + return ( + + +
+
{server.name}
- 90 ? "bg-red-00" : - cpuUsage > 75 ? "bg-orange-500" : - cpuUsage > 60 ? "bg-yellow-500" : "bg-green-500" - } - /> -
- - -
-
- {memoryUsage.toFixed(1)}% - {serverService.formatBytes(server.ram_total)} + + + + + +
+ + {server.os_type}
- 90 ? "bg-red-500" : - memoryUsage > 75 ? "bg-yellow-500" : "bg-blue-500" - } - /> -
- - -
-
- {diskUsage.toFixed(1)}% - {serverService.formatBytes(server.disk_total)} + + + {server.ip_address} + + +
+
+ {cpuUsage.toFixed(1)}% + {server.cpu_cores} cores +
+ 90 ? "bg-red-500" : + cpuUsage > 75 ? "bg-orange-500" : + cpuUsage > 60 ? "bg-yellow-500" : "bg-green-500" + } + />
- 95 ? "bg-red-500" : - diskUsage > 85 ? "bg-yellow-500" : "bg-orange-500" - } - /> -
- - -
{server.uptime}
-
- - -
- {new Date(server.last_checked).toLocaleString()} -
-
- - - - - - - handleViewDetails(server.id)}> - - View Server Detail - - {server.docker === 'true' && ( - handleViewContainers(server.id)}> - - Container Monitoring + + +
+
+ {memoryUsage.toFixed(1)}% + {serverService.formatBytes(server.ram_total)} +
+ 90 ? "bg-red-500" : + memoryUsage > 75 ? "bg-yellow-500" : "bg-blue-500" + } + /> +
+
+ +
+
+ {diskUsage.toFixed(1)}% + {serverService.formatBytes(server.disk_total)} +
+ 95 ? "bg-red-500" : + diskUsage > 85 ? "bg-yellow-500" : "bg-orange-500" + } + /> +
+
+ +
{server.uptime}
+
+ + +
+ {new Date(server.last_checked).toLocaleString()} +
+
+ + + + + + + handleViewDetails(server.id)}> + + View Server Detail - )} - - handlePauseResume(server.id)}> - {isPaused ? ( - <> - - Resume Monitoring - - ) : ( - <> - - Pause Monitoring - + {server.docker === 'true' && ( + handleViewContainers(server.id)}> + + Container Monitoring + )} - - - handleEdit(server.id)}> - - Edit Server - - handleDelete(server.id)} - className="text-red-600 focus:text-red-600" - > - - Delete Server - - - - - - ); - })} - -
-
- )} -
- + + handlePauseResume(server)} + disabled={isProcessing} + > + {isPaused ? ( + <> + + Resume Monitoring + + ) : ( + <> + + Pause Monitoring + + )} + + + handleEdit(server.id)}> + + Edit Server + + handleDelete(server)} + className="text-red-600 focus:text-red-600" + > + + Delete Server + + + + + + ); + })} + + +
+ )} + + + + {/* Delete Confirmation Dialog */} + + + + Are you sure you want to delete this server? + + This action cannot be undone. This will permanently delete{' '} + + {selectedServer?.name} + {' '} + and all of its monitoring data. + + + + + Cancel + + + {isDeleting ? "Deleting..." : "Delete"} + + + + + ); }; \ No newline at end of file diff --git a/application/src/types/server.types.ts b/application/src/types/server.types.ts index de0c42d..c346d01 100644 --- a/application/src/types/server.types.ts +++ b/application/src/types/server.types.ts @@ -8,7 +8,7 @@ export interface Server { hostname: string; ip_address: string; os_type: string; - status: 'up' | 'down' | 'warning'; + status: 'up' | 'down' | 'warning' | 'paused'; uptime: string; ram_total: number; ram_used: number;