mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-23 20:42:02 +00:00
chore: add scan details for demo purposes
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
import { Spacer } from "@nextui-org/react";
|
||||
import { Link, Spacer, Tooltip } from "@nextui-org/react";
|
||||
import { Suspense } from "react";
|
||||
|
||||
import { getProviders } from "@/actions/providers";
|
||||
import { getScans } from "@/actions/scans";
|
||||
import { FilterControls, filterScans } from "@/components/filters";
|
||||
import { InfoIcon } from "@/components/icons";
|
||||
import { SkeletonTableScans } from "@/components/scans/table";
|
||||
import { ColumnProviderScans } from "@/components/scans/table/provider-scans";
|
||||
import { ColumnGetScans } from "@/components/scans/table/scans";
|
||||
@@ -32,7 +33,7 @@ export default async function Scans({
|
||||
<SSRDataTableScans searchParams={searchParams} />
|
||||
</Suspense>
|
||||
</div>
|
||||
<div className="col-span-12 lg:col-span-4">
|
||||
<div className="col-span-12 lg:col-span-6">
|
||||
<Suspense key={searchParamsKey} fallback={<SkeletonTableScans />}>
|
||||
<SSRDataTableProviders />
|
||||
</Suspense>
|
||||
@@ -46,7 +47,26 @@ const SSRDataTableProviders = async () => {
|
||||
const filters = { "filter[connected]": "true" };
|
||||
const providersData = await getProviders({ page: 1, filters });
|
||||
return (
|
||||
<DataTable columns={ColumnProviderScans} data={providersData?.data || []} />
|
||||
<>
|
||||
<div className="mb-2 flex items-center gap-2">
|
||||
<Tooltip content="Only connected providers can be scanned">
|
||||
<InfoIcon size={16} />
|
||||
</Tooltip>
|
||||
<p className="text-sm text-default-500">Connected providers</p>
|
||||
</div>
|
||||
<DataTable
|
||||
columns={ColumnProviderScans}
|
||||
data={providersData?.data || []}
|
||||
/>
|
||||
<p className="-mt-4 text-sm text-default-500">
|
||||
If you don't see any providers, please check your connection settings on
|
||||
the{" "}
|
||||
<Link className="text-sm font-medium" href="/providers">
|
||||
providers page
|
||||
</Link>
|
||||
.
|
||||
</p>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -785,3 +785,26 @@ export const ScheduleIcon: React.FC<IconSvgProps> = ({
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
export const InfoIcon: React.FC<IconSvgProps> = ({
|
||||
size = 24,
|
||||
width,
|
||||
height,
|
||||
...props
|
||||
}) => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={size || width}
|
||||
height={size || height}
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
{...props}
|
||||
>
|
||||
<circle cx="12" cy="12" r="10" />
|
||||
<path d="M12 16v-4M12 8h.01" />
|
||||
</svg>
|
||||
);
|
||||
|
||||
@@ -84,10 +84,14 @@ export const ScanDetail = ({ scanDetails }: { scanDetails: ScanProps }) => {
|
||||
<DetailItem
|
||||
label="Task ID"
|
||||
value={
|
||||
<SnippetId
|
||||
label="Task ID"
|
||||
entityId={scanDetails.relationships.task.data.id}
|
||||
/>
|
||||
scanDetails.relationships.task?.data?.id ? (
|
||||
<SnippetId
|
||||
label="Task ID"
|
||||
entityId={scanDetails.relationships.task.data.id}
|
||||
/>
|
||||
) : (
|
||||
"N/A"
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
@@ -101,14 +105,14 @@ export const ScanDetail = ({ scanDetails }: { scanDetails: ScanProps }) => {
|
||||
<Divider />
|
||||
|
||||
<CardBody className="p-4">
|
||||
<DetailItem
|
||||
label="Checks"
|
||||
value={
|
||||
(scanOnDemand.scanner_args as any)?.checks_to_execute?.join(
|
||||
<div className="flex flex-col gap-2">
|
||||
<span className="font-semibold text-default-500">Checks</span>
|
||||
<span className="text-default-700">
|
||||
{(scanOnDemand.scanner_args as any)?.checks_to_execute?.join(
|
||||
", ",
|
||||
) || "N/A"
|
||||
}
|
||||
/>
|
||||
) || "N/A"}
|
||||
</span>
|
||||
</div>
|
||||
</CardBody>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
@@ -2,11 +2,14 @@
|
||||
|
||||
import { ColumnDef } from "@tanstack/react-table";
|
||||
|
||||
import { InfoIcon, PlusIcon } from "@/components/icons";
|
||||
import { DateWithTime, EntityInfoShort } from "@/components/ui/entities";
|
||||
import { TriggerSheet } from "@/components/ui/sheet";
|
||||
import { DataTableColumnHeader, StatusBadge } from "@/components/ui/table";
|
||||
import { ScanProps } from "@/types";
|
||||
|
||||
import { DataTableRowActions } from "./data-table-row-actions";
|
||||
import { DataTableRowDetails } from "./data-table-row-details";
|
||||
|
||||
const getScanData = (row: { original: ScanProps }) => {
|
||||
return row.original;
|
||||
@@ -118,6 +121,21 @@ export const ColumnGetScans: ColumnDef<ScanProps>[] = [
|
||||
return <p className="font-medium">{unique_resource_count}</p>;
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "moreInfo",
|
||||
header: "Details",
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<TriggerSheet
|
||||
triggerComponent={<InfoIcon className="text-primary" size={16} />}
|
||||
title="Scan Details"
|
||||
description="View the scan details"
|
||||
>
|
||||
<DataTableRowDetails entityId={row.original.id} />
|
||||
</TriggerSheet>
|
||||
);
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
id: "actions",
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
import { getScan } from "@/actions/scans";
|
||||
import { ScanDetail, SkeletonTableScans } from "@/components/scans/table";
|
||||
import { ScanProps } from "@/types";
|
||||
|
||||
export const DataTableRowDetails = ({ entityId }: { entityId: string }) => {
|
||||
const [scanDetails, setScanDetails] = useState<ScanProps | null>(null);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchScanDetails = async () => {
|
||||
try {
|
||||
const result = await getScan(entityId);
|
||||
setScanDetails(result?.data);
|
||||
} catch (error) {
|
||||
console.error("Error fetching scan details:", error);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchScanDetails();
|
||||
}, [entityId]);
|
||||
|
||||
if (isLoading) {
|
||||
return <SkeletonTableScans />;
|
||||
}
|
||||
|
||||
if (!scanDetails) {
|
||||
return <div>No scan details available</div>;
|
||||
}
|
||||
|
||||
return <ScanDetail scanDetails={scanDetails} />;
|
||||
};
|
||||
@@ -1,2 +1,3 @@
|
||||
export * from "./column-get-scans";
|
||||
export * from "./data-table-row-actions";
|
||||
export * from "./data-table-row-details";
|
||||
|
||||
@@ -22,7 +22,9 @@ export function TriggerSheet({
|
||||
}: TriggerSheetProps) {
|
||||
return (
|
||||
<Sheet>
|
||||
<SheetTrigger>{triggerComponent}</SheetTrigger>
|
||||
<SheetTrigger className="flex items-center gap-2">
|
||||
{triggerComponent}
|
||||
</SheetTrigger>
|
||||
<SheetContent className="max-w-[95vw] pt-10 md:max-w-[45vw]">
|
||||
<SheetHeader>
|
||||
<SheetTitle className="sr-only">{title}</SheetTitle>
|
||||
|
||||
Reference in New Issue
Block a user