import { swrFetcher } from "@/api/api"; import { Checkbox } from "@/components/ui/checkbox"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; import { ModelServer as Server, ModelForceUpdateResponse } from "@/types"; import { ColumnDef, flexRender, getCoreRowModel, useReactTable } from "@tanstack/react-table"; import useSWR from "swr"; import { HeaderButtonGroup } from "@/components/header-button-group"; import { deleteServer, forceUpdateServer } from "@/api/server"; import { ServerCard } from "@/components/server"; import { ActionButtonGroup } from "@/components/action-button-group"; import { useEffect, useMemo } from "react"; import { toast } from "sonner"; import { IconButton } from "@/components/xui/icon-button"; import { InstallCommandsMenu } from "@/components/install-commands"; import { NoteMenu } from "@/components/note-menu"; import { TerminalButton } from "@/components/terminal"; import { useServer } from "@/hooks/useServer"; import { joinIP } from "@/lib/utils"; export default function ServerPage() { const { data, mutate, error, isLoading } = useSWR("/api/v1/server", swrFetcher); const { serverGroups } = useServer(); useEffect(() => { if (error) toast("Error", { description: `Error fetching resource: ${error.message}.`, }); }, [error]); const columns: ColumnDef[] = [ { id: "select", header: ({ table }) => ( table.toggleAllPageRowsSelected(!!value)} aria-label="Select all" /> ), cell: ({ row }) => ( row.toggleSelected(!!value)} aria-label="Select row" /> ), enableSorting: false, enableHiding: false, }, { header: "ID", accessorKey: "id", accessorFn: (row) => `${row.id}(${row.display_index})`, }, { header: "Name", accessorKey: "name", accessorFn: (row) => row.name, cell: ({ row }) => { const s = row.original; return
{s.name}
; }, }, { header: "Groups", accessorKey: "groups", accessorFn: (row) => { return ( serverGroups?.filter((sg) => sg.servers?.includes(row.id)).map((sg) => sg.group.id) || [] ); }, }, { id: "ip", header: "IP", cell: ({ row }) => { const s = row.original; return
{joinIP(s.geoip?.ip)}
; }, }, { header: "Version", accessorKey: "host.version", accessorFn: (row) => row.host.version || "Unknown", }, { header: "Enable DDNS", accessorKey: "enableDDNS", accessorFn: (row) => row.enable_ddns ?? false, }, { header: "Hide from Guest", accessorKey: "hideForGuest", accessorFn: (row) => row.hide_for_guest ?? false, }, { id: "installCommands", header: "Install commands", cell: () => , }, { id: "note", header: "Note", cell: ({ row }) => { const s = row.original; return ; }, }, { id: "actions", header: "Actions", cell: ({ row }) => { const s = row.original; return ( <> ); }, }, ]; const dataCache = useMemo(() => { return data ?? []; }, [data]); const table = useReactTable({ data: dataCache, columns, getCoreRowModel: getCoreRowModel(), }); const selectedRows = table.getSelectedRowModel().rows; return (

Server

r.original.id), mutate: mutate, }} > { const id = selectedRows.map((r) => r.original.id); if (id.length < 1) { toast("Error", { description: "No rows are selected.", }); return; } let resp: ModelForceUpdateResponse = {}; try { resp = await forceUpdateServer(id); } catch (e) { console.error(e); toast("Error executing task", { description: "Please see the console for details.", }); return; } toast("Task executed successfully", { description: `Result (Server ID): ${resp.success?.length ? `Success: ${resp.success.join(",")}, ` : ""} ${resp.failure?.length ? `Failure: ${resp.failure.join(",")}, ` : ""} ${resp.offline?.length ? `Offline: ${resp.offline.join(",")}` : ""} `, }); }} />
{table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => { return ( {header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())} ); })} ))} {isLoading ? ( Loading ... ) : table.getRowModel().rows?.length ? ( table.getRowModel().rows.map((row) => ( {row.getVisibleCells().map((cell) => ( {flexRender(cell.column.columnDef.cell, cell.getContext())} ))} )) ) : ( No results. )}
); }