From 45f398bf309f2d00c086b674650da089e3f0ef89 Mon Sep 17 00:00:00 2001 From: Pablo Lara Date: Tue, 3 Sep 2024 16:31:05 +0200 Subject: [PATCH] chore: add sorting to provider's table --- actions/providers.ts | 28 +++++--- app/(prowler)/providers/page.tsx | 31 +++++++-- auth.config.ts | 1 + .../providers/table/ColumnsProvider.tsx | 21 +++++- .../providers/table/DataTableColumnHeader.tsx | 69 ++++++++++++++----- lib/seed.ts | 2 + nextauth.d.ts | 1 + 7 files changed, 120 insertions(+), 33 deletions(-) diff --git a/actions/providers.ts b/actions/providers.ts index 6892e8c922..8c50440f46 100644 --- a/actions/providers.ts +++ b/actions/providers.ts @@ -3,22 +3,33 @@ import { revalidatePath } from "next/cache"; import { redirect } from "next/navigation"; +import { auth } from "@/auth.config"; import { parseStringify } from "@/lib"; -export const getProvider = async ({ page = 1 }) => { +export const getProvider = async ({ + page = 1, + query = "", + sort = "", + filter = "", +}) => { + const session = await auth(); + const tenantId = session?.user.tenantId; + if (isNaN(Number(page)) || page < 1) redirect("/providers"); const keyServer = process.env.LOCAL_SERVER_URL; + const url = new URL(`${keyServer}/providers`); + if (page) url.searchParams.append("page[number]", page.toString()); + if (query) url.searchParams.append("filter[query]", query); + if (sort) url.searchParams.append("sort", sort); + if (filter) url.searchParams.append("filter[provider]", filter); try { - const providers = await fetch( - `${keyServer}/providers?page%5Bnumber%5D=${page}`, - { - headers: { - "X-Tenant-ID": `${process.env.HEADER_TENANT_ID}`, - }, + const providers = await fetch(`${url.toString()}`, { + headers: { + "X-Tenant-ID": `${tenantId}`, }, - ); + }); const data = await providers.json(); const parsedData = parseStringify(data); revalidatePath("/providers"); @@ -28,6 +39,7 @@ export const getProvider = async ({ page = 1 }) => { return undefined; } }; + export const addProvider = async (formData: FormData) => { const keyServer = process.env.LOCAL_SERVER_URL; diff --git a/app/(prowler)/providers/page.tsx b/app/(prowler)/providers/page.tsx index 780d736710..c49117fcd2 100644 --- a/app/(prowler)/providers/page.tsx +++ b/app/(prowler)/providers/page.tsx @@ -10,9 +10,15 @@ import { SkeletonTableProvider, } from "@/components/providers"; import { Header } from "@/components/ui"; -import { searchParamsProps } from "@/types"; -export default async function Providers({ searchParams }: searchParamsProps) { +export default async function Providers({ + searchParams, +}: { + searchParams?: { + query?: string; + page: string; + }; +}) { return ( <>
@@ -22,7 +28,7 @@ export default async function Providers({ searchParams }: searchParamsProps) { - }> + }> @@ -30,9 +36,22 @@ export default async function Providers({ searchParams }: searchParamsProps) { ); } -const SSRDataTable = async ({ searchParams }: searchParamsProps) => { - const page = searchParams.page ? parseInt(searchParams.page) : 1; - const providersData = await getProvider({ page }); +const SSRDataTable = async ({ + searchParams, +}: { + searchParams?: { + query?: string; + page?: string; + sort?: string; + filter?: string; + }; +}) => { + const query = searchParams?.query || ""; + const page = searchParams?.page ? parseInt(searchParams.page) : 1; + const sort = searchParams?.sort || ""; + const filter = searchParams?.filter || ""; + + const providersData = await getProvider({ query, page, sort, filter }); const [providers] = await Promise.all([providersData]); if (providers?.errors) redirect("/providers"); diff --git a/auth.config.ts b/auth.config.ts index 93d8387346..55a81edcca 100644 --- a/auth.config.ts +++ b/auth.config.ts @@ -14,6 +14,7 @@ async function getUser(email: string, password: string): Promise { return { id: user.id, + tenantId: user.tenantId, name: user.name, companyName: user.companyName, email: user.email, diff --git a/components/providers/table/ColumnsProvider.tsx b/components/providers/table/ColumnsProvider.tsx index 82fe4992e2..7a6b6d6270 100644 --- a/components/providers/table/ColumnsProvider.tsx +++ b/components/providers/table/ColumnsProvider.tsx @@ -18,6 +18,7 @@ import { CheckConnectionProvider } from "../CheckConnectionProvider"; import { DateWithTime } from "../DateWithTime"; import { DeleteProvider } from "../DeleteProvider"; import { ProviderInfo } from "../ProviderInfo"; +import { DataTableColumnHeader } from "./DataTableColumnHeader"; const getProviderData = (row: { original: ProviderProps }) => { return row.original; @@ -30,7 +31,9 @@ export const ColumnsProvider: ColumnDef[] = [ }, { accessorKey: "account", - header: "Account", + header: ({ column }) => ( + + ), cell: ({ row }) => { const { attributes: { connection, provider, alias, provider_id }, @@ -55,7 +58,13 @@ export const ColumnsProvider: ColumnDef[] = [ }, { accessorKey: "lastScan", - header: "Last Scan", + header: ({ column }) => ( + + ), cell: ({ row }) => { const { attributes: { updated_at }, @@ -86,7 +95,13 @@ export const ColumnsProvider: ColumnDef[] = [ }, { accessorKey: "added", - header: "Added", + header: ({ column }) => ( + + ), cell: ({ row }) => { const { attributes: { inserted_at }, diff --git a/components/providers/table/DataTableColumnHeader.tsx b/components/providers/table/DataTableColumnHeader.tsx index 7fe6027527..6d460c5fb0 100644 --- a/components/providers/table/DataTableColumnHeader.tsx +++ b/components/providers/table/DataTableColumnHeader.tsx @@ -1,3 +1,5 @@ +"use client"; + import { Button } from "@nextui-org/react"; import { Column } from "@tanstack/react-table"; import { @@ -5,25 +7,61 @@ import { ArrowUpIcon, ChevronsLeftRightIcon, } from "lucide-react"; +import { usePathname, useRouter, useSearchParams } from "next/navigation"; import { HTMLAttributes } from "react"; interface DataTableColumnHeaderProps extends HTMLAttributes { column: Column; title: string; + param?: string; } export const DataTableColumnHeader = ({ column, title, - className, + param, }: DataTableColumnHeaderProps) => { + const router = useRouter(); + const pathname = usePathname(); + const searchParams = useSearchParams(); + + const getToggleSortingHandler = () => { + const currentSortParam = searchParams.get("sort"); + let newSortParam = ""; + + if ( + !currentSortParam || + currentSortParam === "" || + currentSortParam !== param + ) { + // Sort ascending for the first time or switch to a different column + newSortParam = `${param}`; + } else if (currentSortParam === param) { + // If already sorting ascending, switch to descending + newSortParam = `-${param}`; + } else if (currentSortParam === `-${param}`) { + // If already sorting descending, remove sorting + newSortParam = ""; + } + + // Construct the new URL with the sorting parameter + const newUrl = newSortParam ? `${pathname}?sort=${newSortParam}` : pathname; + + router.push(newUrl, { + scroll: false, + }); + }; const renderSortIcon = () => { - const sort = column.getIsSorted(); - if (!sort) { + const currentSortParam = searchParams.get("sort"); + if ( + !currentSortParam || + currentSortParam === "" || + (currentSortParam !== param && currentSortParam !== `-${param}`) + ) { return ; } - return sort === "desc" ? ( + return currentSortParam === `-${param}` ? ( ) : ( @@ -31,19 +69,18 @@ export const DataTableColumnHeader = ({ }; if (!column.getCanSort()) { - return
{title}
; + return
{title}
; } + return ( -
- -
+ ); }; diff --git a/lib/seed.ts b/lib/seed.ts index 4a808d2219..1ff00ee60b 100644 --- a/lib/seed.ts +++ b/lib/seed.ts @@ -4,6 +4,7 @@ import { v4 as uuidv4 } from "uuid"; export const userMockData = [ { id: uuidv4(), // Generate a unique UUID. + tenantId: "12646005-9067-4d2a-a098-8bb378604362", email: "admin@prowler.com", name: "Admin Prowler", companyName: "Prowler", @@ -13,6 +14,7 @@ export const userMockData = [ }, { id: uuidv4(), // Generate a unique UUID. + tenantId: "12646005-9067-4d2a-a098-8bb378604362", email: "user@prowler.com", name: "User Prowler", companyName: "Prowler", diff --git a/nextauth.d.ts b/nextauth.d.ts index 052e4d4a7c..2fe2480ce5 100644 --- a/nextauth.d.ts +++ b/nextauth.d.ts @@ -4,6 +4,7 @@ declare module "next-auth" { interface Session { user: { id: string; + tenantId: string; firstName: string; companyName: string; email: string;