mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-24 13:01:56 +00:00
chore: render an message if there is no data for compliances
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
"use server";
|
||||
import { revalidatePath } from "next/cache";
|
||||
|
||||
import { auth } from "@/auth.config";
|
||||
import { parseStringify } from "@/lib";
|
||||
|
||||
export const getCompliancesOverview = async ({
|
||||
scanId,
|
||||
}: {
|
||||
scanId: string;
|
||||
}) => {
|
||||
const session = await auth();
|
||||
|
||||
const keyServer = process.env.API_BASE_URL;
|
||||
const url = new URL(
|
||||
`${keyServer}/compliance-overviews?filter[scan_id]=${scanId}`,
|
||||
);
|
||||
try {
|
||||
const compliances = await fetch(url.toString(), {
|
||||
headers: {
|
||||
Accept: "application/vnd.api+json",
|
||||
Authorization: `Bearer ${session?.accessToken}`,
|
||||
},
|
||||
});
|
||||
const data = await compliances.json();
|
||||
const parsedData = parseStringify(data);
|
||||
revalidatePath("/compliance");
|
||||
return parsedData;
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error("Error fetching providers:", error);
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export * from "./compliances";
|
||||
@@ -0,0 +1 @@
|
||||
export * from "./invitation";
|
||||
@@ -42,6 +42,7 @@ export const getInvitations = async ({
|
||||
revalidatePath("/invitations");
|
||||
return parsedData;
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error("Error fetching invitations:", error);
|
||||
return undefined;
|
||||
}
|
||||
@@ -117,6 +118,7 @@ export const updateInvite = async (formData: FormData) => {
|
||||
revalidatePath("/invitations");
|
||||
return parseStringify(data);
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error("Error updating invitation:", error);
|
||||
return {
|
||||
error: getErrorMessage(error),
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
import { Spacer } from "@nextui-org/react";
|
||||
import { redirect } from "next/navigation";
|
||||
import { Suspense } from "react";
|
||||
|
||||
import { getCompliance } from "@/actions/compliance";
|
||||
import { getCompliancesOverview } from "@/actions/compliances";
|
||||
import {
|
||||
ComplianceCard,
|
||||
ComplianceSkeletonGrid,
|
||||
} from "@/components/compliance";
|
||||
import { FilterControls } from "@/components/filters";
|
||||
import { Header } from "@/components/ui";
|
||||
import { SearchParamsProps } from "@/types";
|
||||
import { ComplianceOverviewData, SearchParamsProps } from "@/types";
|
||||
|
||||
export default async function Compliance({
|
||||
searchParams,
|
||||
@@ -23,41 +22,48 @@ export default async function Compliance({
|
||||
<Header title="Compliance" icon="fluent-mdl2:compliance-audit" />
|
||||
<Spacer y={4} />
|
||||
<FilterControls mutedFindings={false} />
|
||||
<Spacer y={4} />
|
||||
<Spacer y={8} />
|
||||
<Suspense key={searchParamsKey} fallback={<ComplianceSkeletonGrid />}>
|
||||
<SSRComplianceGrid searchParams={searchParams} />
|
||||
<SSRComplianceGrid />
|
||||
</Suspense>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
const SSRComplianceGrid = async ({
|
||||
searchParams,
|
||||
}: {
|
||||
searchParams: SearchParamsProps;
|
||||
}) => {
|
||||
const page = parseInt(searchParams.page?.toString() || "1", 10);
|
||||
const compliancesData = await getCompliance({ page });
|
||||
const [compliances] = await Promise.all([compliancesData]);
|
||||
const SSRComplianceGrid = async () => {
|
||||
// const scanId = "01929f57-c0ee-7553-be0b-cbde006fb6f7";
|
||||
const scanId = "0193358c-bd7f-7eec-b13a-2d4a648b8df";
|
||||
const compliancesData = await getCompliancesOverview({ scanId });
|
||||
console.log(compliancesData, "compliancesData");
|
||||
|
||||
if (compliances?.errors) redirect("/compliance");
|
||||
if (compliancesData?.errors?.length > 0) {
|
||||
return (
|
||||
<div className="flex h-full items-center justify-center">
|
||||
<div className="text-default-500">There is no compliance data.</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-3 3xl:grid-cols-4">
|
||||
{compliances.compliance?.data.map((compliance: any) => (
|
||||
<ComplianceCard
|
||||
key={compliance.id}
|
||||
title={compliance.attributes.title}
|
||||
passingRequirements={compliance.attributes.passingRequirements}
|
||||
totalRequirements={compliance.attributes.totalRequirements}
|
||||
prevPassingRequirements={
|
||||
compliance.lastScan.attributes.passingRequirements
|
||||
}
|
||||
prevTotalRequirements={
|
||||
compliance.lastScan.attributes.totalRequirements
|
||||
}
|
||||
/>
|
||||
))}
|
||||
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-3">
|
||||
{compliancesData?.data?.map((compliance: ComplianceOverviewData) => {
|
||||
const { attributes } = compliance;
|
||||
const {
|
||||
framework,
|
||||
requirements_status: { passed, total },
|
||||
} = attributes;
|
||||
|
||||
return (
|
||||
<ComplianceCard
|
||||
key={compliance.id}
|
||||
title={framework}
|
||||
passingRequirements={passed}
|
||||
totalRequirements={total}
|
||||
prevPassingRequirements={passed}
|
||||
prevTotalRequirements={total}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -100,6 +100,53 @@ export interface ApiError {
|
||||
};
|
||||
code: string;
|
||||
}
|
||||
export interface CompliancesOverview {
|
||||
links: {
|
||||
first: string;
|
||||
last: string;
|
||||
next: string | null;
|
||||
prev: string | null;
|
||||
};
|
||||
data: ComplianceOverviewData[];
|
||||
meta: {
|
||||
pagination: {
|
||||
page: number;
|
||||
pages: number;
|
||||
count: number;
|
||||
};
|
||||
version: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface ComplianceOverviewData {
|
||||
type: "compliance-overviews";
|
||||
id: string;
|
||||
attributes: {
|
||||
inserted_at: string;
|
||||
compliance_id: string;
|
||||
framework: string;
|
||||
version: string;
|
||||
requirements_status: {
|
||||
passed: number;
|
||||
failed: number;
|
||||
manual: number;
|
||||
total: number;
|
||||
};
|
||||
region: string;
|
||||
provider_type: string;
|
||||
};
|
||||
relationships: {
|
||||
scan: {
|
||||
data: {
|
||||
type: "scans";
|
||||
id: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
links: {
|
||||
self: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface InvitationProps {
|
||||
type: "invitations";
|
||||
|
||||
Reference in New Issue
Block a user