"use client"; import { useEnvContext } from "@app/hooks/useEnvContext"; import { useNavigationContext } from "@app/hooks/useNavigationContext"; import { toast } from "@app/hooks/useToast"; import { createApiClient, formatAxiosError } from "@app/lib/api"; import type { AttachedResource, ListResourcePoliciesResponse } from "@server/routers/resource/types"; import type { PaginationState } from "@tanstack/react-table"; import { ArrowRight, ChevronDown, MoreHorizontal, Waypoints } from "lucide-react"; import { useTranslations } from "next-intl"; import Link from "next/link"; import { useRouter } from "next/navigation"; import { useState, useTransition } from "react"; import { useDebouncedCallback } from "use-debounce"; import { Button } from "./ui/button"; import { ControlledDataTable } from "./ui/controlled-data-table"; import type { ExtendedColumnDef } from "./ui/data-table"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "./ui/dropdown-menu"; import ConfirmDeleteDialog from "./ConfirmDeleteDialog"; import { PaidFeaturesAlert } from "./PaidFeaturesAlert"; import { tierMatrix, TierFeature } from "@server/lib/billing/tierMatrix"; type ResourcePolicyRow = ListResourcePoliciesResponse["policies"][number]; export type ResourcePoliciesTableProps = { policies: Array; orgId: string; pagination: PaginationState; rowCount: number; }; export function ResourcePoliciesTable({ policies, orgId, pagination, rowCount }: ResourcePoliciesTableProps) { const router = useRouter(); const { navigate: filter, isNavigating: isFiltering, searchParams } = useNavigationContext(); const t = useTranslations(); const { env } = useEnvContext(); const api = createApiClient({ env }); const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); const [selectedResourcePolicy, setSelectedResourcePolicy] = useState(null); const deleteResourcePolicy = async (resourcePolicyId: number) => { await api .delete(`/resource-policy/${resourcePolicyId}`) .catch((e) => { console.error(t("resourceErrorDelte"), e); toast({ variant: "destructive", title: t("resourceErrorDelte"), description: formatAxiosError(e, t("resourceErrorDelte")) }); }) .then(() => { router.refresh(); setIsDeleteModalOpen(false); }); }; const [isRefreshing, startTransition] = useTransition(); const [isNavigatingToAddPage, startNavigation] = useTransition(); const refreshData = () => { startTransition(() => { try { router.refresh(); } catch (error) { toast({ title: t("error"), description: t("refreshError"), variant: "destructive" }); } }); }; function ResourceListCell({ resources }: { resources?: AttachedResource[]; }) { if (!resources || resources.length === 0) { return (
{t("resourcePoliciesAttachedResourcesEmpty")}
); } return ( {resources.map((resource) => (
{resource.name}
{resource.fullDomain}
))}
); } const proxyColumns: ExtendedColumnDef[] = [ { accessorKey: "name", enableHiding: false, friendlyName: t("name"), header: () => {t("name")}, cell: ({ row }) => {row.original.name} }, { id: "niceId", accessorKey: "nice", friendlyName: t("identifier"), enableHiding: true, header: () => {t("identifier")}, cell: ({ row }) => { return {row.original.niceId || "-"}; } }, { id: "resources", accessorKey: "resources", friendlyName: t("resourcePoliciesAttachedResourcesColumnTitle"), header: () => ( {t("resourcePoliciesAttachedResourcesColumnTitle")} ), cell: ({ row }) => { return ; } }, { id: "actions", enableHiding: false, header: () => , cell: ({ row }) => { const policyRow = row.original; return (
{t("viewSettings")} { setSelectedResourcePolicy(policyRow); setIsDeleteModalOpen(true); }} > {t("delete")}
); } } ]; const handlePaginationChange = (newPage: PaginationState) => { searchParams.set("page", (newPage.pageIndex + 1).toString()); searchParams.set("pageSize", newPage.pageSize.toString()); filter({ searchParams }); }; const handleSearchChange = useDebouncedCallback((query: string) => { searchParams.set("query", query); searchParams.delete("page"); filter({ searchParams }); }, 300); return ( <> {selectedResourcePolicy && ( { setIsDeleteModalOpen(val); setSelectedResourcePolicy(null); }} dialog={

{t("resourcePolicyQuestionRemove")}

{t("resourcePolicyMessageRemove")}

} buttonText={t("resourcePolicyDeleteConfirm")} onConfirm={async () => deleteResourcePolicy( selectedResourcePolicy.resourcePolicyId ) } string={selectedResourcePolicy.name} title={t("resourcePolicyDelete")} /> )} startNavigation(() => router.push( `/${orgId}/settings/policies/resource/create` ) ) } addButtonText={t("resourcePoliciesAdd")} onRefresh={refreshData} isRefreshing={isRefreshing || isFiltering} isNavigatingToAddPage={isNavigatingToAddPage} enableColumnVisibility columnVisibility={{ niceId: false }} stickyLeftColumn="name" stickyRightColumn="actions" /> ); }