"use client"; import ConfirmDeleteDialog from "@app/components/ConfirmDeleteDialog"; import CopyToClipboard from "@app/components/CopyToClipboard"; import { DataTable } from "@app/components/ui/data-table"; import { ExtendedColumnDef } from "@app/components/ui/data-table"; import { Button } from "@app/components/ui/button"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@app/components/ui/dropdown-menu"; import { useEnvContext } from "@app/hooks/useEnvContext"; import { toast } from "@app/hooks/useToast"; import { createApiClient, formatAxiosError } from "@app/lib/api"; import { ArrowUpDown, ArrowUpRight, MoreHorizontal } from "lucide-react"; import { useTranslations } from "next-intl"; import Link from "next/link"; import { useRouter } from "next/navigation"; import { useState, useTransition } from "react"; import CreateInternalResourceDialog from "@app/components/CreateInternalResourceDialog"; import EditInternalResourceDialog from "@app/components/EditInternalResourceDialog"; import { orgQueries } from "@app/lib/queries"; import { useQuery } from "@tanstack/react-query"; export type InternalResourceRow = { id: number; name: string; orgId: string; siteName: string; siteAddress: string | null; // mode: "host" | "cidr" | "port"; mode: "host" | "cidr"; // protocol: string | null; // proxyPort: number | null; siteId: number; siteNiceId: string; destination: string; // destinationPort: number | null; alias: string | null; niceId: string; }; type ClientResourcesTableProps = { internalResources: InternalResourceRow[]; orgId: string; defaultSort?: { id: string; desc: boolean; }; }; export default function ClientResourcesTable({ internalResources, orgId, defaultSort }: ClientResourcesTableProps) { const router = useRouter(); const t = useTranslations(); const { env } = useEnvContext(); const api = createApiClient({ env }); const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); const [selectedInternalResource, setSelectedInternalResource] = useState(); const [isEditDialogOpen, setIsEditDialogOpen] = useState(false); const [editingResource, setEditingResource] = useState(); const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false); const { data: sites = [] } = useQuery(orgQueries.sites({ orgId })); const [isRefreshing, startTransition] = useTransition(); const refreshData = () => { startTransition(() => { try { router.refresh(); } catch (error) { toast({ title: t("error"), description: t("refreshError"), variant: "destructive" }); } }); }; const deleteInternalResource = async ( resourceId: number, siteId: number ) => { try { await api .delete(`/org/${orgId}/site/${siteId}/resource/${resourceId}`) .then(() => { startTransition(() => { router.refresh(); setIsDeleteModalOpen(false); }); }); } catch (e) { console.error(t("resourceErrorDelete"), e); toast({ variant: "destructive", title: t("resourceErrorDelte"), description: formatAxiosError(e, t("v")) }); } }; const internalColumns: ExtendedColumnDef[] = [ { accessorKey: "name", enableHiding: false, friendlyName: t("name"), header: ({ column }) => { return ( ); } }, { id: "niceId", accessorKey: "niceId", friendlyName: t("identifier"), enableHiding: true, header: ({ column }) => { return ( ); }, cell: ({ row }) => { return {row.original.niceId || "-"}; } }, { accessorKey: "siteName", friendlyName: t("site"), header: () => {t("site")}, cell: ({ row }) => { const resourceRow = row.original; return ( ); } }, { accessorKey: "mode", friendlyName: t("editInternalResourceDialogMode"), header: () => ( {t("editInternalResourceDialogMode")} ), cell: ({ row }) => { const resourceRow = row.original; const modeLabels: Record<"host" | "cidr" | "port", string> = { host: t("editInternalResourceDialogModeHost"), cidr: t("editInternalResourceDialogModeCidr"), port: t("editInternalResourceDialogModePort") }; return {modeLabels[resourceRow.mode]}; } }, { accessorKey: "destination", friendlyName: t("resourcesTableDestination"), header: () => ( {t("resourcesTableDestination")} ), cell: ({ row }) => { const resourceRow = row.original; return ( ); } }, { accessorKey: "alias", friendlyName: t("resourcesTableAlias"), header: () => ( {t("resourcesTableAlias")} ), cell: ({ row }) => { const resourceRow = row.original; return resourceRow.mode === "host" && resourceRow.alias ? ( ) : ( - ); } }, { id: "actions", enableHiding: false, header: () => , cell: ({ row }) => { const resourceRow = row.original; return (
{ setSelectedInternalResource( resourceRow ); setIsDeleteModalOpen(true); }} > {t("delete")}
); } } ]; return ( <> {selectedInternalResource && ( { setIsDeleteModalOpen(val); setSelectedInternalResource(null); }} dialog={

{t("resourceQuestionRemove")}

{t("resourceMessageRemove")}

} buttonText={t("resourceDeleteConfirm")} onConfirm={async () => deleteInternalResource( selectedInternalResource!.id, selectedInternalResource!.siteId ) } string={selectedInternalResource.name} title={t("resourceDelete")} /> )} setIsCreateDialogOpen(true)} addButtonText={t("resourceAdd")} onRefresh={refreshData} isRefreshing={isRefreshing} defaultSort={defaultSort} enableColumnVisibility={true} persistColumnVisibility="internal-resources" stickyLeftColumn="name" stickyRightColumn="actions" /> {editingResource && ( { router.refresh(); setEditingResource(null); }} /> )} { router.refresh(); }} /> ); }