From a2cc3e913dcd2dec84e9c2faf8803c4a115c91c8 Mon Sep 17 00:00:00 2001 From: Pablo Lara Date: Wed, 20 Nov 2024 08:31:29 +0100 Subject: [PATCH] chore: finding details tweaks --- components/filters/custom-date-picker.tsx | 2 +- .../findings/table/data-table-row-details.tsx | 40 ++- components/findings/table/finding-detail.tsx | 308 ++++++++++++------ components/invitations/invitation-details.tsx | 2 +- .../workflow/workflow-send-invite.tsx | 2 +- .../workflow/workflow-add-provider.tsx | 2 +- components/scans/table/scan-detail.tsx | 89 ++--- components/ui/custom/custom-button.tsx | 3 +- components/ui/entities/date-with-time.tsx | 6 +- components/ui/sheet/sheet.tsx | 4 +- components/ui/sheet/trigger-sheet.tsx | 2 +- components/ui/sidebar/sidebar.tsx | 2 +- components/ui/table/data-table-pagination.tsx | 8 +- components/ui/table/data-table.tsx | 2 +- components/ui/table/table.tsx | 2 +- tailwind.config.js | 1 + 16 files changed, 310 insertions(+), 165 deletions(-) diff --git a/components/filters/custom-date-picker.tsx b/components/filters/custom-date-picker.tsx index 91118322af..2a982c1781 100644 --- a/components/filters/custom-date-picker.tsx +++ b/components/filters/custom-date-picker.tsx @@ -63,7 +63,7 @@ export const CustomDatePicker = () => { CalendarTopContent={ { - return ; +import { FindingProps } from "@/types/components"; + +import { FindingDetail } from "./finding-detail"; + +export const DataTableRowDetails = ({ + // entityId, + findingDetails, +}: { + entityId: string; + findingDetails: FindingProps; +}) => { + // const router = useRouter(); + // const pathname = usePathname(); + // const searchParams = useSearchParams(); + + // useEffect(() => { + // if (entityId) { + // const params = new URLSearchParams(searchParams.toString()); + // params.set("id", entityId); + // router.push(`${pathname}?${params.toString()}`, { scroll: false }); + // } + + // return () => { + // if (entityId) { + // const cleanupParams = new URLSearchParams(searchParams.toString()); + // cleanupParams.delete("id"); + // router.push(`${pathname}?${cleanupParams.toString()}`, { + // scroll: false, + // }); + // } + // }; + // }, [entityId, pathname, router, searchParams]); + + return ; }; diff --git a/components/findings/table/finding-detail.tsx b/components/findings/table/finding-detail.tsx index 4d2dfac867..b5865c8c73 100644 --- a/components/findings/table/finding-detail.tsx +++ b/components/findings/table/finding-detail.tsx @@ -1,14 +1,11 @@ "use client"; -import { - Table, - TableBody, - TableCell, - TableColumn, - TableHeader, - TableRow, -} from "@nextui-org/react"; +import { Snippet } from "@nextui-org/react"; +import Link from "next/link"; +import { SnippetId } from "@/components/ui/entities"; +import { DateWithTime } from "@/components/ui/entities/date-with-time"; +import { SeverityBadge } from "@/components/ui/table/severity-badge"; import { FindingProps } from "@/types"; export const FindingDetail = ({ @@ -17,108 +14,203 @@ export const FindingDetail = ({ findingDetails: FindingProps; }) => { const finding = findingDetails; + const attributes = finding.attributes; + const resource = finding.relationships.resource.attributes; + + const remediation = attributes.check_metadata.remediation; + return ( -
+
+ {/* Header */}
- - - Name - Value - - - - Resource ID - {finding.relationships.resource.id} - - - Resource ARN - - {finding.relationships.resource.attributes.uid} - - - - Check ID - {finding.attributes.check_id} - - - Types - - {finding.attributes.check_metadata.checktype} - - - - Scan time - {finding.attributes.inserted_at} - - - Prowler Finding ID - - {finding.relationships.resource.attributes.uid} - - - - Severity - {finding.id} - - - Status - {finding.attributes.status} - - - Region - - {finding.relationships.resource.attributes.region} - - - - Service - - {finding.relationships.resource.attributes.service} - - - - Account - - {finding.relationships.provider.attributes.uid} - - - - Details - {finding.attributes.status_extended} - - - Risk - {finding.attributes.check_metadata.risk} - - - Recommendation - - { - finding.attributes.check_metadata.remediation.recommendation - .text - } - - - - CLI - - {finding.attributes.check_metadata.remediation.code.cli} - - - - Other - - {finding.attributes.check_metadata.remediation.code.other} - - - - Terraform - - {finding.attributes.check_metadata.remediation.code.terraform} - - - -
+
+

+ {attributes.check_metadata.checktitle} +

+

+ {resource.service} +

+
+
+ {attributes.status} +
+
+ + {/* Check Metadata */} +
+
+

+ Check Metadata +

+ +
+ {attributes.status === "FAIL" && ( + +

+ Risk +

+

+ {attributes.check_metadata.risk} +

+
+ )} + +
+

+ Description +

+

+ {attributes.check_metadata.description} +

+
+ +
+

+ Remediation +

+
+ {remediation.recommendation && ( + <> +

Recommendation:

+

{remediation.recommendation.text}

+ + Learn more + + + )} + {remediation.code && + Object.values(remediation.code).some(Boolean) && ( + <> +

+ Check these links: +

+
+ {remediation.code.cli && ( +
+

CLI Command:

+ +

+ {remediation.code.cli} +

+
+
+ )} + {Object.entries(remediation.code) + .filter(([key]) => key !== "cli") + .map(([key, value]) => + value ? ( + + {key === "other" + ? "External doc" + : key.charAt(0).toUpperCase() + + key.slice(1).toLowerCase()} + + ) : null, + )} +
+ + )} +
+
+
+ + {/* Resources Section */} +
+

+ Resource Details +

+
+
+

+ Resource ID +

+ +

{resource.uid}

+
+
+
+

+ Resource Name +

+

+ {resource.name} +

+
+
+

+ Region +

+

+ {resource.region} +

+
+
+

+ Resource Type +

+

+ {resource.type} +

+
+
+

+ Severity +

+ +
+ {resource.tags && + Object.entries(resource.tags).map(([key, value]) => ( +
+

+ Tag: {key} +

+ +

{value}

+
+
+ ))} +
+
+

+ Inserted At +

+ +
+
+

+ Updated At +

+ +
+
+
); diff --git a/components/invitations/invitation-details.tsx b/components/invitations/invitation-details.tsx index 7739cf8adb..f335ad6487 100644 --- a/components/invitations/invitation-details.tsx +++ b/components/invitations/invitation-details.tsx @@ -32,7 +32,7 @@ export const InvitationDetails = ({ attributes }: InvitationDetailsProps) => {
diff --git a/components/invitations/workflow/workflow-send-invite.tsx b/components/invitations/workflow/workflow-send-invite.tsx index cf87d04f06..9cbe848093 100644 --- a/components/invitations/workflow/workflow-send-invite.tsx +++ b/components/invitations/workflow/workflow-send-invite.tsx @@ -55,7 +55,7 @@ export const WorkflowSendInvite = () => { diff --git a/components/providers/workflow/workflow-add-provider.tsx b/components/providers/workflow/workflow-add-provider.tsx index 69bc885638..1f2e631f06 100644 --- a/components/providers/workflow/workflow-add-provider.tsx +++ b/components/providers/workflow/workflow-add-provider.tsx @@ -67,7 +67,7 @@ export const WorkflowAddProvider = () => { diff --git a/components/scans/table/scan-detail.tsx b/components/scans/table/scan-detail.tsx index b0a85f73f3..d6d9fedf7b 100644 --- a/components/scans/table/scan-detail.tsx +++ b/components/scans/table/scan-detail.tsx @@ -17,22 +17,25 @@ export const ScanDetail = ({ scanDetails }: ScanDetailsProps) => { const taskDetails = scanDetails.taskDetails; return ( -
+
+ {/* Header */}
-
-

Scan Details

-
- +

+ Scan Details +

- -
-
-
+ + + + {/* Details Section */} +
+
+
{ value={`${scanOnDemand.duration} seconds`} />
-
+
{ dateTime={scanOnDemand.completed_at.toString()} /> ) : ( - "Not Started" + "Not Completed" ) } /> @@ -109,17 +112,21 @@ export const ScanDetail = ({ scanDetails }: ScanDetailsProps) => {
- - -

Scan arguments

+ + {/* Scan Arguments Section */} + + +

+ Scan Arguments +

- - - - + +
- Checks - + + Checks + + {(scanOnDemand.scanner_args as any)?.checks_to_execute?.join( ", ", ) || "N/A"} @@ -127,25 +134,28 @@ export const ScanDetail = ({ scanDetails }: ScanDetailsProps) => {
+ + {/* Task Details Section */} {taskDetails && ( - - -

State details

+ + +

+ State Details +

- - -
+ + +
- {taskDetails.attributes.result && ( <> {taskDetails.attributes.result.exc_message && ( { )} )} -
@@ -180,8 +191,10 @@ const DateItem = ({ value: React.ReactNode; }) => (
- {label}: - {value} +

+ {label}: +

+

{value}

); @@ -193,7 +206,9 @@ const DetailItem = ({ value: React.ReactNode; }) => (
- {label}: - {value} +

+ {label}: +

+

{value}

); diff --git a/components/ui/custom/custom-button.tsx b/components/ui/custom/custom-button.tsx index eeffd07783..a5cdf54a14 100644 --- a/components/ui/custom/custom-button.tsx +++ b/components/ui/custom/custom-button.tsx @@ -8,7 +8,8 @@ import { NextUIColors, NextUIVariants } from "@/types"; export const buttonClasses = { base: "px-4 inline-flex items-center justify-center relative z-0 text-center whitespace-nowrap", - primary: "bg-default-100 hover:bg-default-200 text-default-800", + primary: + "bg-default-100 hover:bg-default-200 text-default-800 dark:bg-prowler-blue-800", secondary: "bg-prowler-grey-light dark:bg-prowler-grey-medium text-white", action: "bg-prowler-theme-green font-bold text-prowler-theme-midnight", dashed: diff --git a/components/ui/entities/date-with-time.tsx b/components/ui/entities/date-with-time.tsx index ae89c61985..05a00b1b3a 100644 --- a/components/ui/entities/date-with-time.tsx +++ b/components/ui/entities/date-with-time.tsx @@ -4,11 +4,13 @@ import React from "react"; interface DateWithTimeProps { dateTime: string | null; // e.g., "2024-07-17T09:55:14.191475Z" showTime?: boolean; + inline?: boolean; } export const DateWithTime: React.FC = ({ dateTime, showTime = true, + inline = false, }) => { if (!dateTime) return --; const date = parseISO(dateTime); @@ -17,7 +19,9 @@ export const DateWithTime: React.FC = ({ return (
-
+
{formattedDate} {showTime && ( {formattedTime} diff --git a/components/ui/sheet/sheet.tsx b/components/ui/sheet/sheet.tsx index cf945c0f9d..d1fc590d84 100644 --- a/components/ui/sheet/sheet.tsx +++ b/components/ui/sheet/sheet.tsx @@ -31,7 +31,7 @@ const SheetOverlay = React.forwardRef< SheetOverlay.displayName = SheetPrimitive.Overlay.displayName; const sheetVariants = cva( - "fixed z-50 gap-4 bg-white p-6 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500 data-[state=open]:animate-in data-[state=closed]:animate-out dark:bg-neutral-950", + "fixed z-50 gap-4 bg-white p-6 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500 data-[state=open]:animate-in data-[state=closed]:animate-out dark:bg-neutral-950 dark:border-prowler-blue-800", { variants: { side: { @@ -40,7 +40,7 @@ const sheetVariants = cva( "inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom", left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left", right: - "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right", + "inset-y-0 right-0 h-full w-3/4 border-t-1 border-b-1 border-l-2 data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right", }, }, defaultVariants: { diff --git a/components/ui/sheet/trigger-sheet.tsx b/components/ui/sheet/trigger-sheet.tsx index 232173d2d4..5d5fc45ce6 100644 --- a/components/ui/sheet/trigger-sheet.tsx +++ b/components/ui/sheet/trigger-sheet.tsx @@ -27,7 +27,7 @@ export function TriggerSheet({ {triggerComponent} - + {title} {description} diff --git a/components/ui/sidebar/sidebar.tsx b/components/ui/sidebar/sidebar.tsx index 23a58abc79..63feff298e 100644 --- a/components/ui/sidebar/sidebar.tsx +++ b/components/ui/sidebar/sidebar.tsx @@ -280,7 +280,7 @@ const Sidebar = React.forwardRef( itemClasses={{ ...itemClasses, base: clsx( - "px-3 rounded-large data-[selected=true]:bg-default-100", + "px-3 rounded-large data-[selected=true]:bg-default-100 dark:data-[selected=true]:bg-prowler-blue-800", itemClasses?.base, ), title: clsx( diff --git a/components/ui/table/data-table-pagination.tsx b/components/ui/table/data-table-pagination.tsx index e17170d7c8..dfcec441a3 100644 --- a/components/ui/table/data-table-pagination.tsx +++ b/components/ui/table/data-table-pagination.tsx @@ -49,7 +49,7 @@ export function DataTablePagination({ metadata }: DataTablePaginationProps) {
@@ -57,7 +57,7 @@ export function DataTablePagination({ metadata }: DataTablePaginationProps) { @@ -65,14 +65,14 @@ export function DataTablePagination({ metadata }: DataTablePaginationProps) {
)} -
+
{table.getHeaderGroups().map((headerGroup) => ( diff --git a/components/ui/table/table.tsx b/components/ui/table/table.tsx index aca884960c..bd04b9daf3 100644 --- a/components/ui/table/table.tsx +++ b/components/ui/table/table.tsx @@ -75,7 +75,7 @@ const TableHead = React.forwardRef<