diff --git a/app/(prowler)/scans/page.tsx b/app/(prowler)/scans/page.tsx index 70ded7e723..4ea3db2b76 100644 --- a/app/(prowler)/scans/page.tsx +++ b/app/(prowler)/scans/page.tsx @@ -16,10 +16,10 @@ export default async function Scans({ }: { searchParams: SearchParamsProps; }) { - const searchParamsKey = JSON.stringify(searchParams || {}); - // const providersData = await getProviders({ - // filters: { "filter[connected]": "true" }, - // }); + const filteredParams = { ...searchParams }; + delete filteredParams.scanId; + const searchParamsKey = JSON.stringify(filteredParams); + const providersData = await getProviders({}); const providerInfo = providersData?.data?.length @@ -59,9 +59,11 @@ const SSRDataTableScans = async ({ const page = parseInt(searchParams.page?.toString() || "1", 10); const sort = searchParams.sort?.toString(); - // Extract all filter parameters + // Extract all filter parameters, excluding scanId const filters = Object.fromEntries( - Object.entries(searchParams).filter(([key]) => key.startsWith("filter[")), + Object.entries(searchParams).filter( + ([key]) => key.startsWith("filter[") && key !== "scanId", + ), ); // Extract query from filters diff --git a/components/scans/forms/index.ts b/components/scans/forms/index.ts index 59deb9251a..4acd302cb9 100644 --- a/components/scans/forms/index.ts +++ b/components/scans/forms/index.ts @@ -1,3 +1,2 @@ export * from "./edit-scan-form"; -export * from "./scan-on-demand-form"; export * from "./schedule-form"; diff --git a/components/scans/forms/scan-on-demand-form.tsx b/components/scans/forms/scan-on-demand-form.tsx deleted file mode 100644 index a805e55ac5..0000000000 --- a/components/scans/forms/scan-on-demand-form.tsx +++ /dev/null @@ -1,126 +0,0 @@ -"use client"; - -import { zodResolver } from "@hookform/resolvers/zod"; -import { RocketIcon } from "lucide-react"; -import { Dispatch, SetStateAction } from "react"; -import { useForm } from "react-hook-form"; -import * as z from "zod"; - -import { scanOnDemand } from "@/actions/scans"; -import { useToast } from "@/components/ui"; -import { CustomButton, CustomInput } from "@/components/ui/custom"; -import { Form } from "@/components/ui/form"; -import { onDemandScanFormSchema } from "@/types"; - -export const ScanOnDemandForm = ({ - providerId, - scanName, - scannerArgs, - setIsOpen, -}: { - providerId: string; - scanName?: string; - scannerArgs?: { checksToExecute: string[] }; - setIsOpen: Dispatch>; -}) => { - const formSchema = onDemandScanFormSchema(); - - const form = useForm>({ - resolver: zodResolver(formSchema), - defaultValues: { - providerId: providerId, - scanName: scanName, - scannerArgs: scannerArgs, - }, - }); - - const { toast } = useToast(); - - const isLoading = form.formState.isSubmitting; - - const onSubmitClient = async (values: z.infer) => { - const formData = new FormData(); - - // Loop through form values and add to formData, converting objects to JSON strings - Object.entries(values).forEach( - ([key, value]) => - value !== undefined && - formData.append( - key, - typeof value === "object" ? JSON.stringify(value) : value, - ), - ); - - const data = await scanOnDemand(formData); - - if (data?.errors && data.errors.length > 0) { - const error = data.errors[0]; - const errorMessage = `${error.detail}`; - // show error - toast({ - variant: "destructive", - title: "Oops! Something went wrong", - description: errorMessage, - }); - } else { - toast({ - title: "Success!", - description: "The scan was launched successfully.", - }); - setIsOpen(false); - } - }; - - return ( -
- - - -
- -
- -
- setIsOpen(false)} - isDisabled={isLoading} - > - Cancel - - - } - > - {isLoading ? <>Loading : Start now} - -
-
- - ); -}; diff --git a/components/scans/table/scans/column-get-scans.tsx b/components/scans/table/scans/column-get-scans.tsx index 930f189de5..3e2d940e8e 100644 --- a/components/scans/table/scans/column-get-scans.tsx +++ b/components/scans/table/scans/column-get-scans.tsx @@ -1,6 +1,7 @@ "use client"; import { ColumnDef } from "@tanstack/react-table"; +import { useSearchParams } from "next/navigation"; import { InfoIcon } from "@/components/icons"; import { DateWithTime, EntityInfoShort } from "@/components/ui/entities"; @@ -125,11 +126,16 @@ export const ColumnGetScans: ColumnDef[] = [ id: "moreInfo", header: "Details", cell: ({ row }) => { + const searchParams = useSearchParams(); + const scanId = searchParams.get("scanId"); + const isOpen = scanId === row.original.id; + return ( } title="Scan Details" description="View the scan details" + defaultOpen={isOpen} > diff --git a/components/scans/table/scans/data-table-row-details.tsx b/components/scans/table/scans/data-table-row-details.tsx index 997fa0e5d9..14de7184de 100644 --- a/components/scans/table/scans/data-table-row-details.tsx +++ b/components/scans/table/scans/data-table-row-details.tsx @@ -1,5 +1,6 @@ "use client"; +import { useRouter, useSearchParams } from "next/navigation"; import { useEffect, useState } from "react"; import { getScan } from "@/actions/scans"; @@ -7,9 +8,25 @@ import { ScanDetail, SkeletonTableScans } from "@/components/scans/table"; import { ScanProps } from "@/types"; export const DataTableRowDetails = ({ entityId }: { entityId: string }) => { + const router = useRouter(); + const searchParams = useSearchParams(); const [scanDetails, setScanDetails] = useState(null); const [isLoading, setIsLoading] = useState(true); + useEffect(() => { + // Add scanId to URL + const params = new URLSearchParams(searchParams.toString()); + params.set("scanId", entityId); + router.push(`?${params.toString()}`, { scroll: false }); + + // Cleanup function: remove scanId from URL when component unmounts + return () => { + const newParams = new URLSearchParams(searchParams.toString()); + newParams.delete("scanId"); + router.push(`?${newParams.toString()}`, { scroll: false }); + }; + }, [entityId, router, searchParams]); + useEffect(() => { const fetchScanDetails = async () => { try { diff --git a/components/ui/sheet/trigger-sheet.tsx b/components/ui/sheet/trigger-sheet.tsx index 2275577cbd..142b5a51cc 100644 --- a/components/ui/sheet/trigger-sheet.tsx +++ b/components/ui/sheet/trigger-sheet.tsx @@ -12,6 +12,7 @@ interface TriggerSheetProps { title: string; description: string; children: React.ReactNode; + defaultOpen?: boolean; } export function TriggerSheet({ @@ -19,9 +20,10 @@ export function TriggerSheet({ title, description, children, + defaultOpen = false, }: TriggerSheetProps) { return ( - + {triggerComponent}