chore(codebase) Update/UI code base (#5960)

This commit is contained in:
Pablo Lara
2024-11-29 06:54:38 +01:00
committed by GitHub
parent bcf1ef1d31
commit 6dea923866
9 changed files with 138 additions and 22 deletions
+25 -12
View File
@@ -37,6 +37,10 @@ export async function authenticate(
credentials: "Incorrect email or password",
},
};
case "CallbackRouteError":
return {
message: error.cause?.err?.message,
};
default:
return {
message: "Unknown error",
@@ -152,22 +156,31 @@ export const getUserByMe = async (accessToken: string) => {
},
});
if (!response.ok) throw new Error("Error in trying to get user by me");
const parsedResponse = await response.json();
if (!response.ok) {
// Handle different HTTP error codes
switch (response.status) {
case 401:
throw new Error("Invalid or expired token");
case 403:
throw new Error(parsedResponse.errors?.[0]?.detail);
case 404:
throw new Error("User not found");
default:
throw new Error(
parsedResponse.errors?.[0]?.detail || "Unknown error",
);
}
}
const name = parsedResponse.data.attributes.name;
const email = parsedResponse.data.attributes.email;
const company = parsedResponse.data.attributes.company_name;
const dateJoined = parsedResponse.data.attributes.date_joined;
return {
name,
email,
company,
dateJoined,
name: parsedResponse.data.attributes.name,
email: parsedResponse.data.attributes.email,
company: parsedResponse.data.attributes.company_name,
dateJoined: parsedResponse.data.attributes.date_joined,
};
} catch (error) {
throw new Error("Error in trying to get user by me");
} catch (error: any) {
throw new Error(error.message || "Network error or server unreachable");
}
};
+2
View File
@@ -140,6 +140,7 @@ const SSRComplianceGrid = async ({
const { attributes } = compliance;
const {
framework,
version,
requirements_status: { passed, total },
} = attributes;
@@ -147,6 +148,7 @@ const SSRComplianceGrid = async ({
<ComplianceCard
key={compliance.id}
title={framework}
version={version}
passingRequirements={passed}
totalRequirements={total}
prevPassingRequirements={passed}
+1
View File
@@ -105,6 +105,7 @@ export const authConfig = {
const isLoggedIn = !!auth?.user;
const isOnDashboard = nextUrl.pathname.startsWith("/");
const isSignUpPage = nextUrl.pathname === "/sign-up";
//CLOUD API CHANGES
// Allow access to sign-up page
if (isSignUpPage) return true;
+10 -2
View File
@@ -17,9 +17,11 @@ import { ApiError, authFormSchema } from "@/types";
export const AuthForm = ({
type,
invitationToken,
isCloudEnv,
}: {
type: string;
invitationToken?: string | null;
isCloudEnv?: boolean;
}) => {
const formSchema = authFormSchema(type);
const router = useRouter();
@@ -47,7 +49,6 @@ export const AuthForm = ({
email: data.email.toLowerCase(),
password: data.password,
});
if (result?.message === "Success") {
router.push("/");
} else if (result?.errors && "credentials" in result.errors) {
@@ -55,6 +56,8 @@ export const AuthForm = ({
type: "server",
message: result.errors.credentials ?? "Incorrect email or password",
});
} else if (result?.message === "User email is not verified") {
router.push("/email-verification");
} else {
toast({
variant: "destructive",
@@ -73,7 +76,12 @@ export const AuthForm = ({
description: "The user was registered successfully.",
});
form.reset();
router.push("/sign-in");
if (isCloudEnv) {
router.push("/email-verification");
} else {
router.push("/sign-in");
}
} else {
newUser.errors.forEach((error: ApiError) => {
const errorMessage = error.detail;
+11 -2
View File
@@ -6,6 +6,7 @@ import { getComplianceIcon } from "../icons";
interface ComplianceCardProps {
title: string;
version: string;
passingRequirements: number;
totalRequirements: number;
prevPassingRequirements: number;
@@ -14,9 +15,14 @@ interface ComplianceCardProps {
export const ComplianceCard: React.FC<ComplianceCardProps> = ({
title,
version,
passingRequirements,
totalRequirements,
}) => {
const formatTitle = (title: string) => {
return title.split("-").join(" ");
};
const ratingPercentage = Math.floor(
(passingRequirements / totalRequirements) * 100,
);
@@ -47,7 +53,7 @@ export const ComplianceCard: React.FC<ComplianceCardProps> = ({
};
return (
<Card fullWidth isPressable isHoverable shadow="sm">
<Card fullWidth isHoverable shadow="sm">
<CardBody className="flex flex-row items-center justify-between space-x-4 dark:bg-prowler-blue-800">
<div className="flex w-full items-center space-x-4">
<Image
@@ -56,7 +62,10 @@ export const ComplianceCard: React.FC<ComplianceCardProps> = ({
className="h-10 w-10 min-w-10 rounded-md border-1 border-gray-300 bg-white object-contain p-1"
/>
<div className="flex w-full flex-col">
<h4 className="text-md font-bold leading-5 3xl:text-lg">{title}</h4>
<h4 className="text-md font-bold leading-5 3xl:text-lg">
{formatTitle(title)}
{version ? ` - ${version}` : ""}
</h4>
<Progress
label="Your Rating:"
size="sm"
@@ -17,7 +17,15 @@ export const DataCompliance = ({ scans, regions }: DataComplianceProps) => {
const searchParams = useSearchParams();
const [showClearButton, setShowClearButton] = useState(false);
const scanIdParam = searchParams.get("scanId");
const selectedScanId = scanIdParam || scans[0]?.id;
const selectedScanId = scanIdParam || (scans.length > 0 ? scans[0].id : "");
useEffect(() => {
if (!scanIdParam && scans.length > 0) {
const params = new URLSearchParams(searchParams);
params.set("scanId", scans[0].id);
router.push(`?${params.toString()}`);
}
}, [scans, scanIdParam, searchParams, router]);
useEffect(() => {
const hasFilters = Array.from(searchParams.keys()).some(
@@ -1,6 +1,6 @@
import { Control } from "react-hook-form";
import { CustomInput } from "@/components/ui/custom";
import { CustomTextarea } from "@/components/ui/custom";
import { KubernetesCredentials } from "@/types";
export const KubernetesCredentialsForm = ({
@@ -15,17 +15,17 @@ export const KubernetesCredentialsForm = ({
Connect via Credentials
</div>
<div className="py-2 text-default-500">
Please provide the information for your Kubernetes credentials.
Please provide the kubeconfig content for your Kubernetes credentials.
</div>
</div>
<CustomInput
<CustomTextarea
control={control}
name="kubeconfig_content"
type="text"
label="Kubeconfig Content"
labelPlacement="inside"
placeholder="Enter the Kubeconfig Content"
placeholder="Paste your Kubeconfig YAML content here"
variant="bordered"
minRows={10}
isRequired
isInvalid={!!control._formState.errors.kubeconfig_content}
/>
@@ -0,0 +1,74 @@
"use client";
import { Textarea } from "@nextui-org/input";
import React from "react";
import { Control, FieldPath, FieldValues } from "react-hook-form";
import { FormControl, FormField, FormMessage } from "@/components/ui/form";
interface CustomTextareaProps<T extends FieldValues> {
control: Control<T>;
name: FieldPath<T>;
label?: string;
labelPlacement?: "inside" | "outside" | "outside-left";
variant?: "flat" | "bordered" | "underlined" | "faded";
size?: "sm" | "md" | "lg";
placeholder?: string;
defaultValue?: string;
isRequired?: boolean;
isInvalid?: boolean;
minRows?: number;
maxRows?: number;
fullWidth?: boolean;
disableAutosize?: boolean;
description?: React.ReactNode;
}
export const CustomTextarea = <T extends FieldValues>({
control,
name,
label = name,
labelPlacement = "inside",
placeholder,
variant = "flat",
size = "md",
defaultValue,
isRequired = false,
isInvalid = false,
minRows = 3,
maxRows = 8,
fullWidth = true,
disableAutosize = false,
description,
}: CustomTextareaProps<T>) => {
return (
<FormField
control={control}
name={name}
render={({ field }) => (
<>
<FormControl>
<Textarea
id={name}
label={label}
labelPlacement={labelPlacement}
placeholder={placeholder}
variant={variant}
size={size}
isInvalid={isInvalid}
isRequired={isRequired}
defaultValue={defaultValue}
minRows={minRows}
maxRows={maxRows}
fullWidth={fullWidth}
disableAutosize={disableAutosize}
description={description}
{...field}
/>
</FormControl>
<FormMessage className="text-system-error dark:text-system-error" />
</>
)}
/>
);
};
+1
View File
@@ -5,3 +5,4 @@ export * from "./custom-dropdown-filter";
export * from "./custom-input";
export * from "./custom-loader";
export * from "./custom-radio";
export * from "./custom-textarea";