mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-24 21:11:53 +00:00
feat: render the task result in scan details
This commit is contained in:
@@ -4,16 +4,23 @@ import { Card, CardBody, CardHeader, Divider } from "@nextui-org/react";
|
||||
|
||||
import { DateWithTime, SnippetId } from "@/components/ui/entities";
|
||||
import { StatusBadge } from "@/components/ui/table/status-badge";
|
||||
import { ScanProps } from "@/types";
|
||||
import { ScanProps, TaskDetails } from "@/types";
|
||||
|
||||
export const ScanDetail = ({ scanDetails }: { scanDetails: ScanProps }) => {
|
||||
interface ScanDetailsProps {
|
||||
scanDetails: ScanProps & {
|
||||
taskDetails?: TaskDetails;
|
||||
};
|
||||
}
|
||||
|
||||
export const ScanDetail = ({ scanDetails }: ScanDetailsProps) => {
|
||||
const scanOnDemand = scanDetails.attributes;
|
||||
const taskDetails = scanDetails.taskDetails;
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex flex-col items-baseline md:flex-row md:gap-x-4">
|
||||
<h2 className="text-lg font-black uppercase">Scan Details - </h2>
|
||||
<p>{scanOnDemand.name}</p>
|
||||
<h2 className="text-2xl font-bold">Scan Details</h2>
|
||||
</div>
|
||||
|
||||
<StatusBadge size="lg" status={scanOnDemand.state} />
|
||||
@@ -22,6 +29,7 @@ export const ScanDetail = ({ scanDetails }: { scanDetails: ScanProps }) => {
|
||||
<div className="relative z-0 flex w-full flex-col justify-between gap-4 overflow-auto rounded-large bg-content1 p-4 shadow-small">
|
||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
<div className="space-y-4">
|
||||
<DetailItem label="Scan Name" value={scanOnDemand.name} />
|
||||
<DetailItem
|
||||
label="ID"
|
||||
value={<SnippetId label="Type" entityId={scanDetails.id} />}
|
||||
@@ -99,7 +107,7 @@ export const ScanDetail = ({ scanDetails }: { scanDetails: ScanProps }) => {
|
||||
</div>
|
||||
<Card className="relative w-full border-small border-default-100 p-3 shadow-lg">
|
||||
<CardHeader className="py-2">
|
||||
<h2 className="text-2xl font-bold">Scan Arguments</h2>
|
||||
<h2 className="text-2xl font-bold">Scan arguments</h2>
|
||||
</CardHeader>
|
||||
|
||||
<Divider />
|
||||
@@ -115,6 +123,47 @@ export const ScanDetail = ({ scanDetails }: { scanDetails: ScanProps }) => {
|
||||
</div>
|
||||
</CardBody>
|
||||
</Card>
|
||||
{taskDetails && (
|
||||
<Card className="relative w-full border-small border-default-100 p-3 shadow-lg">
|
||||
<CardHeader className="py-2">
|
||||
<h2 className="text-2xl font-bold">State details</h2>
|
||||
</CardHeader>
|
||||
<Divider />
|
||||
<CardBody className="p-4">
|
||||
<div className="flex flex-col gap-2">
|
||||
<DetailItem label="State" value={taskDetails.attributes.state} />
|
||||
<DetailItem
|
||||
label="Completed At"
|
||||
value={taskDetails.attributes.completed_at}
|
||||
/>
|
||||
|
||||
{taskDetails.attributes.result && (
|
||||
<>
|
||||
<DetailItem
|
||||
label="Error Type"
|
||||
value={taskDetails.attributes.result.exc_type}
|
||||
/>
|
||||
{taskDetails.attributes.result.exc_message && (
|
||||
<DetailItem
|
||||
label="Error Message"
|
||||
value={taskDetails.attributes.result.exc_message.join(
|
||||
", ",
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
||||
<DetailItem
|
||||
label="Checks to Execute"
|
||||
value={taskDetails.attributes.task_args.checks_to_execute.join(
|
||||
", ",
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</CardBody>
|
||||
</Card>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -4,7 +4,9 @@ import { useRouter, useSearchParams } from "next/navigation";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
import { getScan } from "@/actions/scans";
|
||||
import { getTask } from "@/actions/task";
|
||||
import { ScanDetail, SkeletonTableScans } from "@/components/scans/table";
|
||||
import { checkTaskStatus } from "@/lib";
|
||||
import { ScanProps } from "@/types";
|
||||
|
||||
export const DataTableRowDetails = ({ entityId }: { entityId: string }) => {
|
||||
@@ -31,9 +33,24 @@ export const DataTableRowDetails = ({ entityId }: { entityId: string }) => {
|
||||
const fetchScanDetails = async () => {
|
||||
try {
|
||||
const result = await getScan(entityId);
|
||||
setScanDetails(result?.data);
|
||||
|
||||
const taskId = result.data.relationships.task?.data?.id;
|
||||
|
||||
if (taskId) {
|
||||
const taskResult = await checkTaskStatus(taskId);
|
||||
|
||||
if (taskResult.completed !== undefined) {
|
||||
const task = await getTask(taskId);
|
||||
setScanDetails({
|
||||
...result.data,
|
||||
taskDetails: task.data,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
setScanDetails(result.data);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching scan details:", error);
|
||||
console.error("Error in fetchScanDetails:", error);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
|
||||
@@ -26,6 +26,22 @@ export type NextUIColors =
|
||||
| "danger"
|
||||
| "default";
|
||||
|
||||
export interface TaskDetails {
|
||||
attributes: {
|
||||
state: string;
|
||||
completed_at: string;
|
||||
result: {
|
||||
exc_type?: string;
|
||||
exc_message?: string[];
|
||||
exc_module?: string;
|
||||
};
|
||||
task_args: {
|
||||
scan_id: string;
|
||||
provider_id: string;
|
||||
checks_to_execute: string[];
|
||||
};
|
||||
};
|
||||
}
|
||||
export type AWSCredentials = {
|
||||
aws_access_key_id: string;
|
||||
aws_secret_access_key: string;
|
||||
|
||||
Reference in New Issue
Block a user