From c93ab340213a9eca9131beda48c708f74de97f98 Mon Sep 17 00:00:00 2001 From: Fred KISSIE Date: Tue, 2 Dec 2025 19:08:35 +0100 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20some=20refactors?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/ClientResourcesTable.tsx | 134 +++------------- src/components/MachineClientsTable.tsx | 6 +- src/components/ProxyResourcesTable.tsx | 200 +++++++----------------- src/components/UserDevicesTable.tsx | 6 +- 4 files changed, 79 insertions(+), 267 deletions(-) diff --git a/src/components/ClientResourcesTable.tsx b/src/components/ClientResourcesTable.tsx index 39578a9b..5d96d1d2 100644 --- a/src/components/ClientResourcesTable.tsx +++ b/src/components/ClientResourcesTable.tsx @@ -27,7 +27,6 @@ import { import { useEnvContext } from "@app/hooks/useEnvContext"; import { toast } from "@app/hooks/useToast"; import { createApiClient, formatAxiosError } from "@app/lib/api"; -import { ListSitesResponse } from "@server/routers/site"; import { ColumnFiltersState, flexRender, @@ -36,28 +35,26 @@ import { getPaginationRowModel, getSortedRowModel, SortingState, - useReactTable, - VisibilityState + useReactTable } from "@tanstack/react-table"; import { ArrowUpDown, ArrowUpRight, - CheckCircle2, - Clock, Columns, MoreHorizontal, Plus, RefreshCw, - Search, - XCircle + Search } from "lucide-react"; import { useTranslations } from "next-intl"; import Link from "next/link"; import { useRouter } from "next/navigation"; -import { useEffect, useState, useTransition } from "react"; +import { useState, useTransition } from "react"; import CreateInternalResourceDialog from "@app/components/CreateInternalResourceDialog"; import EditInternalResourceDialog from "@app/components/EditInternalResourceDialog"; +import { useStoredColumnVisibility } from "@app/hooks/useStoredColumnVisibility"; +import { useStoredPageSize } from "@app/hooks/useStoredPageSize"; import { siteQueries } from "@app/lib/queries"; import { useQuery } from "@tanstack/react-query"; @@ -113,88 +110,6 @@ type ClientResourcesTableProps = { }; }; -const STORAGE_KEYS = { - PAGE_SIZE: "datatable-page-size", - COLUMN_VISIBILITY: "datatable-column-visibility", - getTablePageSize: (tableId?: string) => - tableId ? `datatable-${tableId}-page-size` : STORAGE_KEYS.PAGE_SIZE, - getTableColumnVisibility: (tableId?: string) => - tableId - ? `datatable-${tableId}-column-visibility` - : STORAGE_KEYS.COLUMN_VISIBILITY -}; - -const getStoredPageSize = (tableId?: string, defaultSize = 20): number => { - if (typeof window === "undefined") return defaultSize; - - try { - const key = STORAGE_KEYS.getTablePageSize(tableId); - const stored = localStorage.getItem(key); - if (stored) { - const parsed = parseInt(stored, 10); - if (parsed > 0 && parsed <= 1000) { - return parsed; - } - } - } catch (error) { - console.warn("Failed to read page size from localStorage:", error); - } - return defaultSize; -}; - -const setStoredPageSize = (pageSize: number, tableId?: string): void => { - if (typeof window === "undefined") return; - - try { - const key = STORAGE_KEYS.getTablePageSize(tableId); - localStorage.setItem(key, pageSize.toString()); - } catch (error) { - console.warn("Failed to save page size to localStorage:", error); - } -}; - -const getStoredColumnVisibility = ( - tableId?: string, - defaultVisibility?: Record -): Record => { - if (typeof window === "undefined") return defaultVisibility || {}; - - try { - const key = STORAGE_KEYS.getTableColumnVisibility(tableId); - const stored = localStorage.getItem(key); - if (stored) { - const parsed = JSON.parse(stored); - // Validate that it's an object - if (typeof parsed === "object" && parsed !== null) { - return parsed; - } - } - } catch (error) { - console.warn( - "Failed to read column visibility from localStorage:", - error - ); - } - return defaultVisibility || {}; -}; - -const setStoredColumnVisibility = ( - visibility: Record, - tableId?: string -): void => { - if (typeof window === "undefined") return; - - try { - const key = STORAGE_KEYS.getTableColumnVisibility(tableId); - localStorage.setItem(key, JSON.stringify(visibility)); - } catch (error) { - console.warn( - "Failed to save column visibility to localStorage:", - error - ); - } -}; - export default function ClientResourcesTable({ internalResources, orgId, @@ -207,10 +122,10 @@ export default function ClientResourcesTable({ const api = createApiClient({ env }); - const [internalPageSize, setInternalPageSize] = useState(() => - getStoredPageSize("internal-resources", 20) + const [internalPageSize, setInternalPageSize] = useStoredPageSize( + "internal-resources", + 20 ); - const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); const [selectedInternalResource, setSelectedInternalResource] = @@ -233,10 +148,7 @@ export default function ClientResourcesTable({ const [isRefreshing, startTransition] = useTransition(); const [internalColumnVisibility, setInternalColumnVisibility] = - useState(() => - getStoredColumnVisibility("internal-resources", {}) - ); - + useStoredColumnVisibility("internal-resources", {}); const refreshData = async () => { try { router.refresh(); @@ -255,11 +167,14 @@ export default function ClientResourcesTable({ siteId: number ) => { try { - await api.delete( - `/org/${orgId}/site/${siteId}/resource/${resourceId}` - ); - router.refresh(); - setIsDeleteModalOpen(false); + await api + .delete(`/org/${orgId}/site/${siteId}/resource/${resourceId}`) + .then(() => { + startTransition(() => { + router.refresh(); + setIsDeleteModalOpen(false); + }); + }); } catch (e) { console.error(t("resourceErrorDelete"), e); toast({ @@ -515,19 +430,6 @@ export default function ClientResourcesTable({ } }); - const handleInternalPageSizeChange = (newPageSize: number) => { - setInternalPageSize(newPageSize); - setStoredPageSize(newPageSize, "internal-resources"); - }; - - // Persist column visibility changes to localStorage - useEffect(() => { - setStoredColumnVisibility( - internalColumnVisibility, - "internal-resources" - ); - }, [internalColumnVisibility]); - return ( <> {selectedInternalResource && ( @@ -700,7 +602,7 @@ export default function ClientResourcesTable({
diff --git a/src/components/MachineClientsTable.tsx b/src/components/MachineClientsTable.tsx index 0ba8bd13..daff754b 100644 --- a/src/components/MachineClientsTable.tsx +++ b/src/components/MachineClientsTable.tsx @@ -138,8 +138,10 @@ export default function MachineClientsTable({ }); }) .then(() => { - router.refresh(); - setIsDeleteModalOpen(false); + startTransition(() => { + router.refresh(); + setIsDeleteModalOpen(false); + }); }); }; diff --git a/src/components/ProxyResourcesTable.tsx b/src/components/ProxyResourcesTable.tsx index 29107100..9fb4c91e 100644 --- a/src/components/ProxyResourcesTable.tsx +++ b/src/components/ProxyResourcesTable.tsx @@ -1,60 +1,23 @@ "use client"; -import { - flexRender, - getCoreRowModel, - useReactTable, - getPaginationRowModel, - SortingState, - getSortedRowModel, - ColumnFiltersState, - getFilteredRowModel, - VisibilityState -} from "@tanstack/react-table"; +import ConfirmDeleteDialog from "@app/components/ConfirmDeleteDialog"; +import CopyToClipboard from "@app/components/CopyToClipboard"; +import { DataTablePagination } from "@app/components/DataTablePagination"; +import { Button } from "@app/components/ui/button"; +import { Card, CardContent, CardHeader } from "@app/components/ui/card"; import { ExtendedColumnDef } from "@app/components/ui/data-table"; import { DropdownMenu, + DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuItem, - DropdownMenuTrigger, DropdownMenuLabel, DropdownMenuSeparator, - DropdownMenuCheckboxItem + DropdownMenuTrigger } from "@app/components/ui/dropdown-menu"; -import { Button } from "@app/components/ui/button"; -import { - ArrowRight, - ArrowUpDown, - MoreHorizontal, - ShieldOff, - ShieldCheck, - RefreshCw, - Columns, - Plus, - Search, - ChevronDown, - Clock, - CheckCircle2, - XCircle -} from "lucide-react"; -import Link from "next/link"; -import { useRouter } from "next/navigation"; -import { useState, useEffect, useTransition } from "react"; -import ConfirmDeleteDialog from "@app/components/ConfirmDeleteDialog"; -import { formatAxiosError } from "@app/lib/api"; -import { toast } from "@app/hooks/useToast"; -import { createApiClient } from "@app/lib/api"; -import { useEnvContext } from "@app/hooks/useEnvContext"; -import CopyToClipboard from "@app/components/CopyToClipboard"; -import { Switch } from "@app/components/ui/switch"; -import { AxiosResponse } from "axios"; -import { UpdateResourceResponse } from "@server/routers/resource"; -import { ListSitesResponse } from "@server/routers/site"; -import { useTranslations } from "next-intl"; import { InfoPopup } from "@app/components/ui/info-popup"; import { Input } from "@app/components/ui/input"; -import { DataTablePagination } from "@app/components/DataTablePagination"; -import { Card, CardContent, CardHeader } from "@app/components/ui/card"; +import { Switch } from "@app/components/ui/switch"; import { Table, TableBody, @@ -63,6 +26,42 @@ import { TableHeader, TableRow } from "@app/components/ui/table"; +import { useEnvContext } from "@app/hooks/useEnvContext"; +import { useStoredColumnVisibility } from "@app/hooks/useStoredColumnVisibility"; +import { useStoredPageSize } from "@app/hooks/useStoredPageSize"; +import { toast } from "@app/hooks/useToast"; +import { createApiClient, formatAxiosError } from "@app/lib/api"; +import { UpdateResourceResponse } from "@server/routers/resource"; +import { + ColumnFiltersState, + flexRender, + getCoreRowModel, + getFilteredRowModel, + getPaginationRowModel, + getSortedRowModel, + SortingState, + useReactTable +} from "@tanstack/react-table"; +import { AxiosResponse } from "axios"; +import { + ArrowRight, + ArrowUpDown, + CheckCircle2, + ChevronDown, + Clock, + Columns, + MoreHorizontal, + Plus, + RefreshCw, + Search, + ShieldCheck, + ShieldOff, + XCircle +} from "lucide-react"; +import { useTranslations } from "next-intl"; +import Link from "next/link"; +import { useRouter } from "next/navigation"; +import { useState, useTransition } from "react"; export type TargetHealth = { targetId: number; @@ -153,88 +152,6 @@ type ProxyResourcesTableProps = { }; }; -const STORAGE_KEYS = { - PAGE_SIZE: "datatable-page-size", - COLUMN_VISIBILITY: "datatable-column-visibility", - getTablePageSize: (tableId?: string) => - tableId ? `datatable-${tableId}-page-size` : STORAGE_KEYS.PAGE_SIZE, - getTableColumnVisibility: (tableId?: string) => - tableId - ? `datatable-${tableId}-column-visibility` - : STORAGE_KEYS.COLUMN_VISIBILITY -}; - -const getStoredPageSize = (tableId?: string, defaultSize = 20): number => { - if (typeof window === "undefined") return defaultSize; - - try { - const key = STORAGE_KEYS.getTablePageSize(tableId); - const stored = localStorage.getItem(key); - if (stored) { - const parsed = parseInt(stored, 10); - if (parsed > 0 && parsed <= 1000) { - return parsed; - } - } - } catch (error) { - console.warn("Failed to read page size from localStorage:", error); - } - return defaultSize; -}; - -const setStoredPageSize = (pageSize: number, tableId?: string): void => { - if (typeof window === "undefined") return; - - try { - const key = STORAGE_KEYS.getTablePageSize(tableId); - localStorage.setItem(key, pageSize.toString()); - } catch (error) { - console.warn("Failed to save page size to localStorage:", error); - } -}; - -const getStoredColumnVisibility = ( - tableId?: string, - defaultVisibility?: Record -): Record => { - if (typeof window === "undefined") return defaultVisibility || {}; - - try { - const key = STORAGE_KEYS.getTableColumnVisibility(tableId); - const stored = localStorage.getItem(key); - if (stored) { - const parsed = JSON.parse(stored); - // Validate that it's an object - if (typeof parsed === "object" && parsed !== null) { - return parsed; - } - } - } catch (error) { - console.warn( - "Failed to read column visibility from localStorage:", - error - ); - } - return defaultVisibility || {}; -}; - -const setStoredColumnVisibility = ( - visibility: Record, - tableId?: string -): void => { - if (typeof window === "undefined") return; - - try { - const key = STORAGE_KEYS.getTableColumnVisibility(tableId); - localStorage.setItem(key, JSON.stringify(visibility)); - } catch (error) { - console.warn( - "Failed to save column visibility to localStorage:", - error - ); - } -}; - export default function ProxyResourcesTable({ resources, orgId, @@ -247,10 +164,10 @@ export default function ProxyResourcesTable({ const api = createApiClient({ env }); - const [proxyPageSize, setProxyPageSize] = useState(() => - getStoredPageSize("proxy-resources", 20) + const [proxyPageSize, setProxyPageSize] = useStoredPageSize( + "proxy-resources", + 20 ); - const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); const [selectedResource, setSelectedResource] = useState(); @@ -265,10 +182,7 @@ export default function ProxyResourcesTable({ const [isRefreshing, startTransition] = useTransition(); const [proxyColumnVisibility, setProxyColumnVisibility] = - useState(() => - getStoredColumnVisibility("proxy-resources", {}) - ); - + useStoredColumnVisibility("proxy-resources", {}); const refreshData = () => { try { router.refresh(); @@ -292,8 +206,10 @@ export default function ProxyResourcesTable({ }); }) .then(() => { - router.refresh(); - setIsDeleteModalOpen(false); + startTransition(() => { + router.refresh(); + setIsDeleteModalOpen(false); + }); }); }; @@ -734,16 +650,6 @@ export default function ProxyResourcesTable({ } }); - const handleProxyPageSizeChange = (newPageSize: number) => { - setProxyPageSize(newPageSize); - setStoredPageSize(newPageSize, "proxy-resources"); - }; - - // Persist column visibility changes to localStorage - useEffect(() => { - setStoredColumnVisibility(proxyColumnVisibility, "proxy-resources"); - }, [proxyColumnVisibility]); - return ( <> {selectedResource && ( @@ -913,7 +819,7 @@ export default function ProxyResourcesTable({
diff --git a/src/components/UserDevicesTable.tsx b/src/components/UserDevicesTable.tsx index f4573eec..0d903c88 100644 --- a/src/components/UserDevicesTable.tsx +++ b/src/components/UserDevicesTable.tsx @@ -130,8 +130,10 @@ export default function UserDevicesTable({ userClients }: ClientTableProps) { }); }) .then(() => { - router.refresh(); - setIsDeleteModalOpen(false); + startTransition(() => { + router.refresh(); + setIsDeleteModalOpen(false); + }); }); };