mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-18 18:11:57 +00:00
4d5676f00e
Co-authored-by: Alan Buscaglia <alanbuscaglia@MacBook-Pro.local> Co-authored-by: alejandrobailo <alejandrobailo94@gmail.com> Co-authored-by: César Arroba <cesar@prowler.com> Co-authored-by: Alejandro Bailo <59607668+alejandrobailo@users.noreply.github.com>
175 lines
4.8 KiB
TypeScript
175 lines
4.8 KiB
TypeScript
"use client";
|
|
|
|
import { ColumnDef } from "@tanstack/react-table";
|
|
import { Database } from "lucide-react";
|
|
import { useSearchParams } from "next/navigation";
|
|
|
|
import { InfoIcon } from "@/components/icons";
|
|
import { EntityInfoShort, SnippetChip } from "@/components/ui/entities";
|
|
import { TriggerSheet } from "@/components/ui/sheet";
|
|
import { DataTableColumnHeader } from "@/components/ui/table";
|
|
import { ProviderType, ResourceProps } from "@/types";
|
|
|
|
import { ResourceDetail } from "./resource-detail";
|
|
|
|
const getResourceData = (
|
|
row: { original: ResourceProps },
|
|
field: keyof ResourceProps["attributes"],
|
|
) => {
|
|
return row.original.attributes?.[field];
|
|
};
|
|
|
|
const getChipStyle = (count: number) => {
|
|
if (count === 0) return "bg-green-100 text-green-800";
|
|
if (count >= 10) return "bg-red-100 text-red-800";
|
|
if (count >= 1) return "bg-yellow-100 text-yellow-800";
|
|
};
|
|
|
|
const getProviderData = (
|
|
row: { original: ResourceProps },
|
|
field: keyof ResourceProps["relationships"]["provider"]["data"]["attributes"],
|
|
) => {
|
|
return (
|
|
row.original.relationships?.provider?.data?.attributes?.[field] ??
|
|
`No ${field} found in provider`
|
|
);
|
|
};
|
|
|
|
const ResourceDetailsCell = ({ row }: { row: any }) => {
|
|
const searchParams = useSearchParams();
|
|
const resourceId = searchParams.get("resourceId");
|
|
const isOpen = resourceId === row.original.id;
|
|
|
|
return (
|
|
<div className="flex w-9 items-center justify-center">
|
|
<TriggerSheet
|
|
triggerComponent={<InfoIcon className="text-primary" size={16} />}
|
|
title="Resource Details"
|
|
description="View the Resource details"
|
|
defaultOpen={isOpen}
|
|
>
|
|
<ResourceDetail
|
|
resourceId={row.original.id}
|
|
initialResourceData={row.original}
|
|
/>
|
|
</TriggerSheet>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export const ColumnResources: ColumnDef<ResourceProps>[] = [
|
|
{
|
|
id: "moreInfo",
|
|
header: "Details",
|
|
cell: ({ row }) => <ResourceDetailsCell row={row} />,
|
|
},
|
|
{
|
|
accessorKey: "resourceName",
|
|
header: "Resource name",
|
|
cell: ({ row }) => {
|
|
const resourceName = getResourceData(row, "name");
|
|
const displayName =
|
|
typeof resourceName === "string" && resourceName.trim().length > 0
|
|
? resourceName
|
|
: "Unnamed resource";
|
|
|
|
return (
|
|
<SnippetChip
|
|
value={displayName}
|
|
className="max-w-[320px]"
|
|
icon={<Database size={16} />}
|
|
/>
|
|
);
|
|
},
|
|
},
|
|
{
|
|
accessorKey: "failedFindings",
|
|
header: () => <div className="text-center">Failed Findings</div>,
|
|
cell: ({ row }) => {
|
|
const failedFindingsCount = getResourceData(
|
|
row,
|
|
"failed_findings_count",
|
|
) as number;
|
|
|
|
return (
|
|
<>
|
|
<p className="text-center">
|
|
<span
|
|
className={`mx-auto flex h-6 w-6 items-center justify-center rounded-full bg-yellow-100 text-xs font-semibold text-yellow-800 ${getChipStyle(failedFindingsCount)}`}
|
|
>
|
|
{failedFindingsCount}
|
|
</span>
|
|
</p>
|
|
</>
|
|
);
|
|
},
|
|
},
|
|
{
|
|
accessorKey: "region",
|
|
header: ({ column }) => (
|
|
<DataTableColumnHeader column={column} title={"Region"} param="region" />
|
|
),
|
|
cell: ({ row }) => {
|
|
const region = getResourceData(row, "region");
|
|
|
|
return (
|
|
<div className="w-[80px] text-xs">
|
|
{typeof region === "string" ? region : "Invalid region"}
|
|
</div>
|
|
);
|
|
},
|
|
},
|
|
{
|
|
accessorKey: "type",
|
|
header: ({ column }) => (
|
|
<DataTableColumnHeader column={column} title={"Type"} param="type" />
|
|
),
|
|
cell: ({ row }) => {
|
|
const type = getResourceData(row, "type");
|
|
|
|
return (
|
|
<div className="max-w-[150px] text-xs break-words whitespace-nowrap">
|
|
{typeof type === "string" ? type : "Invalid type"}
|
|
</div>
|
|
);
|
|
},
|
|
},
|
|
{
|
|
accessorKey: "service",
|
|
header: ({ column }) => (
|
|
<DataTableColumnHeader
|
|
column={column}
|
|
title={"Service"}
|
|
param="service"
|
|
/>
|
|
),
|
|
cell: ({ row }) => {
|
|
const service = getResourceData(row, "service");
|
|
|
|
return (
|
|
<div className="max-w-96 truncate text-xs">
|
|
{typeof service === "string" ? service : "Invalid region"}
|
|
</div>
|
|
);
|
|
},
|
|
},
|
|
{
|
|
accessorKey: "provider",
|
|
header: "Cloud Provider",
|
|
cell: ({ row }) => {
|
|
const provider = getProviderData(row, "provider");
|
|
const alias = getProviderData(row, "alias");
|
|
const uid = getProviderData(row, "uid");
|
|
return (
|
|
<>
|
|
<EntityInfoShort
|
|
cloudProvider={provider as ProviderType}
|
|
entityAlias={alias && typeof alias === "string" ? alias : undefined}
|
|
entityId={uid && typeof uid === "string" ? uid : undefined}
|
|
/>
|
|
</>
|
|
);
|
|
},
|
|
},
|
|
];
|