mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-23 20:42:02 +00:00
chore: add sorting to provider's table
This commit is contained in:
+20
-8
@@ -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;
|
||||
|
||||
|
||||
@@ -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 (
|
||||
<>
|
||||
<Header title="Providers" icon="fluent:cloud-sync-24-regular" />
|
||||
@@ -22,7 +28,7 @@ export default async function Providers({ searchParams }: searchParamsProps) {
|
||||
<AddProviderModal />
|
||||
</div>
|
||||
<Spacer y={6} />
|
||||
<Suspense key={searchParams.page} fallback={<SkeletonTableProvider />}>
|
||||
<Suspense key={searchParams?.page} fallback={<SkeletonTableProvider />}>
|
||||
<SSRDataTable searchParams={searchParams} />
|
||||
</Suspense>
|
||||
</div>
|
||||
@@ -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");
|
||||
|
||||
@@ -14,6 +14,7 @@ async function getUser(email: string, password: string): Promise<any | null> {
|
||||
|
||||
return {
|
||||
id: user.id,
|
||||
tenantId: user.tenantId,
|
||||
name: user.name,
|
||||
companyName: user.companyName,
|
||||
email: user.email,
|
||||
|
||||
@@ -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<ProviderProps>[] = [
|
||||
},
|
||||
{
|
||||
accessorKey: "account",
|
||||
header: "Account",
|
||||
header: ({ column }) => (
|
||||
<DataTableColumnHeader column={column} title={"Account"} param="alias" />
|
||||
),
|
||||
cell: ({ row }) => {
|
||||
const {
|
||||
attributes: { connection, provider, alias, provider_id },
|
||||
@@ -55,7 +58,13 @@ export const ColumnsProvider: ColumnDef<ProviderProps>[] = [
|
||||
},
|
||||
{
|
||||
accessorKey: "lastScan",
|
||||
header: "Last Scan",
|
||||
header: ({ column }) => (
|
||||
<DataTableColumnHeader
|
||||
column={column}
|
||||
title={"Last Scan"}
|
||||
param="updated_at"
|
||||
/>
|
||||
),
|
||||
cell: ({ row }) => {
|
||||
const {
|
||||
attributes: { updated_at },
|
||||
@@ -86,7 +95,13 @@ export const ColumnsProvider: ColumnDef<ProviderProps>[] = [
|
||||
},
|
||||
{
|
||||
accessorKey: "added",
|
||||
header: "Added",
|
||||
header: ({ column }) => (
|
||||
<DataTableColumnHeader
|
||||
column={column}
|
||||
title={"Added"}
|
||||
param="inserted_at"
|
||||
/>
|
||||
),
|
||||
cell: ({ row }) => {
|
||||
const {
|
||||
attributes: { inserted_at },
|
||||
|
||||
@@ -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<TData, TValue>
|
||||
extends HTMLAttributes<HTMLDivElement> {
|
||||
column: Column<TData, TValue>;
|
||||
title: string;
|
||||
param?: string;
|
||||
}
|
||||
|
||||
export const DataTableColumnHeader = <TData, TValue>({
|
||||
column,
|
||||
title,
|
||||
className,
|
||||
param,
|
||||
}: DataTableColumnHeaderProps<TData, TValue>) => {
|
||||
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 <ChevronsLeftRightIcon className="ml-2 h-4 w-4 rotate-90" />;
|
||||
}
|
||||
return sort === "desc" ? (
|
||||
return currentSortParam === `-${param}` ? (
|
||||
<ArrowDownIcon className="ml-2 h-4 w-4" />
|
||||
) : (
|
||||
<ArrowUpIcon className="ml-2 h-4 w-4" />
|
||||
@@ -31,19 +69,18 @@ export const DataTableColumnHeader = <TData, TValue>({
|
||||
};
|
||||
|
||||
if (!column.getCanSort()) {
|
||||
return <div className={className}>{title}</div>;
|
||||
return <div>{title}</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="h-8"
|
||||
onClick={column.getToggleSortingHandler()}
|
||||
>
|
||||
<span>{title}</span>
|
||||
{renderSortIcon()}
|
||||
</Button>
|
||||
</div>
|
||||
<Button
|
||||
variant="light"
|
||||
size="md"
|
||||
className="h-8"
|
||||
onClick={getToggleSortingHandler}
|
||||
>
|
||||
<span>{title}</span>
|
||||
{renderSortIcon()}
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -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",
|
||||
|
||||
Vendored
+1
@@ -4,6 +4,7 @@ declare module "next-auth" {
|
||||
interface Session {
|
||||
user: {
|
||||
id: string;
|
||||
tenantId: string;
|
||||
firstName: string;
|
||||
companyName: string;
|
||||
email: string;
|
||||
|
||||
Reference in New Issue
Block a user