"use client"; import { ColumnDef } from "@tanstack/react-table"; import { ExtendedColumnDef } from "@app/components/ui/data-table"; import { ExitNodesDataTable } from "@app/components/ExitNodesDataTable"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@app/components/ui/dropdown-menu"; import { Button } from "@app/components/ui/button"; import { ArrowRight, ArrowUpDown, MoreHorizontal } from "lucide-react"; import Link from "next/link"; import { useRouter } from "next/navigation"; import { useState, useEffect } from "react"; import ConfirmDeleteDialog from "@app/components/ConfirmDeleteDialog"; import { toast } from "@app/hooks/useToast"; import { formatAxiosError } from "@app/lib/api"; import { createApiClient } from "@app/lib/api"; import { useEnvContext } from "@app/hooks/useEnvContext"; import { useTranslations } from "next-intl"; import { Badge } from "@app/components/ui/badge"; export type RemoteExitNodeRow = { id: string; exitNodeId: number | null; name: string; address: string; endpoint: string; orgId: string; type: string | null; online: boolean; dateCreated: string; version?: string; }; type ExitNodesTableProps = { remoteExitNodes: RemoteExitNodeRow[]; orgId: string; }; export default function ExitNodesTable({ remoteExitNodes, orgId }: ExitNodesTableProps) { const router = useRouter(); const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); const [selectedNode, setSelectedNode] = useState( null ); const [rows, setRows] = useState(remoteExitNodes); const [isRefreshing, setIsRefreshing] = useState(false); const api = createApiClient(useEnvContext()); const t = useTranslations(); useEffect(() => { setRows(remoteExitNodes); }, [remoteExitNodes]); const refreshData = async () => { console.log("Data refreshed"); setIsRefreshing(true); try { await new Promise((resolve) => setTimeout(resolve, 200)); router.refresh(); } catch (error) { toast({ title: t("error"), description: t("refreshError"), variant: "destructive" }); } finally { setIsRefreshing(false); } }; const deleteRemoteExitNode = (remoteExitNodeId: string) => { api.delete(`/org/${orgId}/remote-exit-node/${remoteExitNodeId}`) .catch((e) => { console.error(t("remoteExitNodeErrorDelete"), e); toast({ variant: "destructive", title: t("remoteExitNodeErrorDelete"), description: formatAxiosError( e, t("remoteExitNodeErrorDelete") ) }); }) .then(() => { setIsDeleteModalOpen(false); const newRows = rows.filter( (row) => row.id !== remoteExitNodeId ); setRows(newRows); }); }; const columns: ExtendedColumnDef[] = [ { accessorKey: "name", friendlyName: t("name"), header: ({ column }) => { return ( ); } }, { accessorKey: "online", friendlyName: t("online"), header: ({ column }) => { return ( ); }, cell: ({ row }) => { const originalRow = row.original; if (originalRow.online) { return (
{t("online")}
); } else { return (
{t("offline")}
); } } }, { accessorKey: "type", friendlyName: t("connectionType"), header: ({ column }) => { return ( ); }, cell: ({ row }) => { const originalRow = row.original; return ( {originalRow.type === "remoteExitNode" ? "Remote Exit Node" : originalRow.type} ); } }, { accessorKey: "address", friendlyName: "Address", header: ({ column }) => { return ( ); } }, { accessorKey: "endpoint", friendlyName: "Endpoint", header: ({ column }) => { return ( ); } }, { accessorKey: "version", header: ({ column }) => { return ( ); }, cell: ({ row }) => { const originalRow = row.original; return (
{originalRow.version && originalRow.version ? ( {"v" + originalRow.version} ) : ( "-" )}
); } }, { id: "actions", enableHiding: false, header: () => , cell: ({ row }) => { const nodeRow = row.original; const remoteExitNodeId = nodeRow.id; return (
{t("viewSettings")} { setSelectedNode(nodeRow); setIsDeleteModalOpen(true); }} > {t("delete")}
); } } ]; return ( <> {selectedNode && ( { setIsDeleteModalOpen(val); setSelectedNode(null); }} dialog={

{t("remoteExitNodeQuestionRemove")}

{t("remoteExitNodeMessageRemove")}

} buttonText={t("remoteExitNodeConfirmDelete")} onConfirm={async () => deleteRemoteExitNode(selectedNode!.id) } string={selectedNode.name} title={t("remoteExitNodeDelete")} /> )} router.push(`/${orgId}/settings/remote-exit-nodes/create`) } onRefresh={refreshData} isRefreshing={isRefreshing} columnVisibility={{ type: false, address: false }} enableColumnVisibility={true} /> ); }