chore: Refactor and improve UI

This commit is contained in:
Meet
2024-09-20 12:29:26 +05:30
parent 040fa511f6
commit 10574bfe26
7 changed files with 169 additions and 215 deletions
@@ -11,10 +11,10 @@ import { createNotification } from "@app/components/notifications";
import {
Button,
FormControl,
Input,
Spinner,
Input
} from "@app/components/v2";
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@app/components/v2/Dropdown/Dropdown";
import { Tooltip } from "@app/components/v2/Tooltip";
import { useCreateDynamicSecret } from "@app/hooks/api";
import { useGetDynamicSecretProviderData } from "@app/hooks/api/dynamicSecret/queries";
import { DynamicSecretProviders } from "@app/hooks/api/dynamicSecret/types";
@@ -81,8 +81,10 @@ export const AzureEntraIdInputForm = ({
const applicationId = watch("provider.applicationId");
const clientSecret = watch("provider.clientSecret");
const configurationComplete = tenantId && applicationId && clientSecret;
const { data, isLoading, isFetched, isError, isFetching } = useGetDynamicSecretProviderData({ dataFetchType: "Users", provider: { type: DynamicSecretProviders.AzureEntraId, inputs: { userId: "unused", email: "unused", tenantId, applicationId, clientSecret } }, enabled: !!configurationComplete });
const configurationComplete = !!(tenantId && applicationId && clientSecret);
const { data, isLoading, isError, isFetching } = useGetDynamicSecretProviderData({ tenantId, applicationId, clientSecret, enabled: !!configurationComplete });
const loading = configurationComplete && isFetching;
const errored = configurationComplete && !isFetching && isError;
const createDynamicSecret = useCreateDynamicSecret();
const handleCreateDynamicSecret = async ({ name, selectedUsers, provider, maxTTL, defaultTTL }: TForm) => {
@@ -165,7 +167,7 @@ export const AzureEntraIdInputForm = ({
</div>
<div>
<div className="mb-4 mt-4 border-b border-mineshaft-500 pb-2 pl-1 font-medium text-mineshaft-200">
Configuration
Configuration
<Link href="https://infisical.com/docs/documentation/platform/dynamic-secrets/azure-entra-id" passHref>
<a target="_blank" rel="noopener noreferrer">
<div className="ml-2 mb-1 inline-block cursor-default rounded-md bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] text-sm text-yellow opacity-80 hover:opacity-100">
@@ -247,64 +249,94 @@ export const AzureEntraIdInputForm = ({
</div>
<div className="flex flex-col">
<div className="flex items-center space-x-4">
{
configurationComplete && !isError && !isFetching && isFetched && data &&
<Controller
control={control}
name="selectedUsers"
render={({ field: { value, onChange }, fieldState: { error } }) => (
<FormControl
isRequired
isError={Boolean(error)}
errorText={error?.message}
>
<DropdownMenu>
<DropdownMenuTrigger asChild className="w-72">
<Input
isReadOnly
value={value?.length ? `${value.length} selected` : "None"}
className="text-left"
/>
</DropdownMenuTrigger>
<DropdownMenuContent align="start"
style={{ width: "var(--radix-dropdown-menu-trigger-width)" }}
<Controller
control={control}
name="selectedUsers"
render={({ field: { value, onChange }, fieldState: { error } }) => (
<FormControl
isRequired
isError={Boolean(error)}
errorText={error?.message}
>
<DropdownMenu >
<DropdownMenuTrigger
className="w-72"
disabled={loading || errored || !configurationComplete}
>
<Tooltip
hidden={!loading && !errored && configurationComplete}
content=
{
<div>
{(() => {
let icon;
if (errored) {
icon = <FontAwesomeIcon icon={faWarning} color="red" />;
} else if (loading || !configurationComplete) {
icon = <FontAwesomeIcon icon={faWarning} color="yellow" />;
} else {
icon = null;
}
return icon;
})()}
<span className="ml-4 cursor-default text-mineshaft-300 hover:text-mineshaft-200">
{(() => {
let message;
if (loading) {
message = "Loading, please wait...";
} else if (errored) {
message = "Check the configuration";
} else if (!configurationComplete) {
message = "Configuration incomplete";
} else {
message = ""; // or you can leave it undefined
}
return message;
})()}
</span>
</div>
}
>
{data.map((user) => {
const ids = value?.map((selectedUser) => selectedUser.id)
const isChecked = ids?.includes(user.id);
return (
<DropdownMenuItem
onClick={(evt) => {
evt.preventDefault();
onChange(
isChecked
? value?.filter((el) => el.id !== user.id)
: [...(value || []), user]
);
}}
key={`create-policy-members-${user.id}`}
iconPos="right"
icon={isChecked && <FontAwesomeIcon icon={faCheckCircle} />}
>
{user.name} <br /> {`(${user.email})`}
</DropdownMenuItem>
);
})}
</DropdownMenuContent>
</DropdownMenu>
</FormControl>
)}
/>
}
{
configurationComplete && isFetching && (<div className="pl-3 pb-2 w-full flex items-center" ><Spinner size="xs" /><p> &nbsp; Loading </p></div>)
}
{
configurationComplete && !isFetching && isError && (<div className="pl-3 pb-2 w-full flex items-center"><FontAwesomeIcon icon={faWarning} /> <p> &nbsp; Error loading users please ensure Entra Id app is installed and configuration is correct</p></div>)
}
{
!configurationComplete && (<div className="pl-3 pb-2 w-full flex items-center" ><FontAwesomeIcon icon={faWarning} /><p> &nbsp; Complete configuration to fetch users</p></div>)
}
<div>
<Input
isReadOnly
value={value?.length ? `${value.length} selected` : ""}
className={`text-left ${loading || errored || !configurationComplete ? "cursor-not-allowed" : ""}`}
placeholder="Select users"
/>
</div>
</Tooltip>
</DropdownMenuTrigger>
<DropdownMenuContent align="start"
style={{ width: "var(--radix-dropdown-menu-trigger-width)" }}
>
{data && data.map((user) => {
const ids = value?.map((selectedUser) => selectedUser.id)
const isChecked = ids?.includes(user.id);
return (
<DropdownMenuItem
onClick={(evt) => {
evt.preventDefault();
onChange(
isChecked
? value?.filter((el) => el.id !== user.id)
: [...(value || []), user]
);
}}
key={`create-policy-members-${user.id}`}
iconPos="right"
icon={isChecked && <FontAwesomeIcon icon={faCheckCircle} />}
>
{user.name} <br /> {`(${user.email})`}
</DropdownMenuItem>
);
})}
</DropdownMenuContent>
</DropdownMenu>
</FormControl>
)}
/>
</div>
</div>
</div>
@@ -1,77 +0,0 @@
import Image from "next/image"
import Link from "next/link"
import { useRouter } from "next/router";
import { faCopy } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { createNotification } from "@app/components/notifications";
import { IconButton } from "@app/components/v2";
export const AzureEntraIdCallbackPage = () => {
const router = useRouter();
return (
<div className="flex h-screen flex-col justify-between overflow-auto bg-gradient-to-tr from-mineshaft-700 to-bunker-800 text-gray-200 dark:[color-scheme:dark]">
<div />
<div className="mx-auto w-full max-w-xl px-4 py-4 md:px-0">
<div className="mb-8 text-center">
<div className="mb-4 flex justify-center pt-8">
<Link href="https://infisical.com">
<Image
src="/images/gradientLogo.svg"
height={90}
width={120}
alt="Infisical logo"
className="cursor-pointer"
/>
</Link>
</div>
</div>
<div className="m-auto my-8 flex w-full" />
<div className="m-auto mb-2 flex w-full flex-col rounded-md border bg-white/[0.05] border-white-500/30 p-6 pt-5">
<div className="flex flex-col items-start sm:flex-row sm:items-center">
<p className="md:text-md text-md mr-4 w-full">
<p
className="text-bold text-white bg-clip-text text-transparent"
>
Copy Tenant ID add and paste it in the dynamic secret configuration.
</p>{" "}
</p>
</div>
</div>
<div className="m-auto flex w-full flex-col rounded-md border border-primary-500/30 bg-primary/5 p-6 pt-5">
<div className="flex flex-col items-start sm:flex-row sm:items-center">
<p className="md:text-md text-md mr-4 w-full">
<p
className="text-bold bg-gradient-to-tr from-yellow-500 to-primary-500 bg-clip-text text-transparent"
>
Tenant ID
</p>{" "}
<br />
<div className="w-full mr-2 flex items-center rounded-md bg-white/[0.05] p-2 text-base text-gray-400">
<p className="mr-4 break-all text-left">{router.query.tenant}</p>
<IconButton
ariaLabel="copy icon"
colorSchema="secondary"
className="group relative ml-auto"
onClick={() => {
if (typeof router.query.tenant === "string") {
navigator.clipboard.writeText(router.query.tenant);
createNotification({
title: "Copied Tenant ID to clipboard succesfully",
type: "success",
text: ""
});
}
}}
>
<FontAwesomeIcon icon={faCopy} />
</IconButton>
</div>
</p>
</div>
</div>
</div>
<div className="w-full bg-mineshaft-600 p-2" />
</div>
)
}