mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
Merge pull request #4964 from Infisical/ENG-4217
improvement(frontend): update project identity creation flow
This commit is contained in:
@@ -203,7 +203,11 @@ export const IdentitySection = withPermission(
|
||||
>
|
||||
<ModalContent
|
||||
bodyClassName="overflow-visible"
|
||||
title="Add Machine Identity"
|
||||
title={
|
||||
isSubOrganization
|
||||
? "Add Machine Identity to Sub-Organization"
|
||||
: "Create Organization Machine Identity"
|
||||
}
|
||||
subTitle={
|
||||
isSubOrganization
|
||||
? "Create a new machine identity or assign an existing one"
|
||||
|
||||
@@ -12,8 +12,7 @@ import {
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { useNavigate } from "@tanstack/react-router";
|
||||
import { AnimatePresence, motion } from "framer-motion";
|
||||
import { LinkIcon, PlusIcon } from "lucide-react";
|
||||
import { InfoIcon } from "lucide-react";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
import { createNotification } from "@app/components/notifications";
|
||||
@@ -83,10 +82,9 @@ import { ProjectLinkIdentityModal } from "./components/ProjectLinkIdentityModal"
|
||||
|
||||
const MAX_ROLES_TO_BE_SHOWN_IN_TABLE = 2;
|
||||
|
||||
enum WizardSteps {
|
||||
SelectAction = "select-action",
|
||||
LinkIdentity = "link-identity",
|
||||
ProjectIdentity = "project-identity"
|
||||
enum AddIdentityType {
|
||||
CreateNew,
|
||||
AssignExisting
|
||||
}
|
||||
|
||||
export const IdentityTab = withProjectPermission(
|
||||
@@ -95,7 +93,9 @@ export const IdentityTab = withProjectPermission(
|
||||
const navigate = useNavigate();
|
||||
const { isSubOrganization, currentOrg } = useOrganization();
|
||||
|
||||
const [wizardStep, setWizardStep] = useState(WizardSteps.SelectAction);
|
||||
const [addMachineIdentityType, setAddMachineIdentityType] = useState<AddIdentityType>(
|
||||
AddIdentityType.CreateNew
|
||||
);
|
||||
|
||||
const {
|
||||
offset,
|
||||
@@ -510,93 +510,89 @@ export const IdentityTab = withProjectPermission(
|
||||
isOpen={popUp.createIdentity.isOpen}
|
||||
onOpenChange={(open) => {
|
||||
handlePopUpToggle("createIdentity", open);
|
||||
if (!open) setWizardStep(WizardSteps.SelectAction);
|
||||
}}
|
||||
>
|
||||
<ModalContent
|
||||
bodyClassName="overflow-visible"
|
||||
title="Add Project Machine Identity"
|
||||
title="Add Machine Identity to Project"
|
||||
subTitle="Create a new machine identity or assign an existing one"
|
||||
>
|
||||
<AnimatePresence mode="wait">
|
||||
{wizardStep === WizardSteps.SelectAction && (
|
||||
<motion.div
|
||||
key="select-type-step"
|
||||
transition={{ duration: 0.1 }}
|
||||
initial={{ opacity: 0, translateX: 30 }}
|
||||
animate={{ opacity: 1, translateX: 0 }}
|
||||
exit={{ opacity: 0, translateX: -30 }}
|
||||
<div className="mb-4 flex items-center justify-center gap-x-2">
|
||||
<div className="flex w-3/4 gap-x-0.5 rounded-md border border-mineshaft-600 bg-mineshaft-800 p-1">
|
||||
<Button
|
||||
variant="outline_bg"
|
||||
onClick={() => {
|
||||
setAddMachineIdentityType(AddIdentityType.CreateNew);
|
||||
}}
|
||||
size="xs"
|
||||
className={twMerge(
|
||||
"min-w-[2.4rem] flex-1 rounded border-none hover:bg-mineshaft-600",
|
||||
addMachineIdentityType === AddIdentityType.CreateNew
|
||||
? "bg-mineshaft-500"
|
||||
: "bg-transparent"
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className="cursor-pointer rounded-md border border-mineshaft-600 p-4 transition-all hover:bg-mineshaft-700"
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
onClick={() => setWizardStep(WizardSteps.ProjectIdentity)}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "Enter") {
|
||||
setWizardStep(WizardSteps.ProjectIdentity);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<PlusIcon size="1rem" />
|
||||
<div>Create Machine Identity</div>
|
||||
</div>
|
||||
<div className="mt-2 text-xs text-mineshaft-300">
|
||||
Create a new machine identity specifically for this project. This machine
|
||||
identity will be managed at the project-level.
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="mt-4 cursor-pointer rounded-md border border-mineshaft-600 p-4 transition-all hover:bg-mineshaft-700"
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
onClick={() => setWizardStep(WizardSteps.LinkIdentity)}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "Enter") {
|
||||
setWizardStep(WizardSteps.LinkIdentity);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<LinkIcon size="1rem" />
|
||||
<div>Assign Existing Machine Identity</div>
|
||||
</div>
|
||||
<div className="mt-2 text-xs text-mineshaft-300">
|
||||
Assign an existing machine identity from your organization. The machine
|
||||
identity will continue to be managed at its original scope.
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
{wizardStep === WizardSteps.ProjectIdentity && (
|
||||
<motion.div
|
||||
key="identity-step"
|
||||
transition={{ duration: 0.1 }}
|
||||
initial={{ opacity: 0, translateX: 30 }}
|
||||
animate={{ opacity: 1, translateX: 0 }}
|
||||
exit={{ opacity: 0, translateX: -30 }}
|
||||
Create New
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline_bg"
|
||||
onClick={() => {
|
||||
setAddMachineIdentityType(AddIdentityType.AssignExisting);
|
||||
}}
|
||||
size="xs"
|
||||
className={twMerge(
|
||||
"min-w-[2.4rem] flex-1 rounded border-none hover:bg-mineshaft-600",
|
||||
addMachineIdentityType === AddIdentityType.AssignExisting
|
||||
? "bg-mineshaft-500"
|
||||
: "bg-transparent"
|
||||
)}
|
||||
>
|
||||
<ProjectIdentityModal
|
||||
onClose={() => {
|
||||
handlePopUpClose("createIdentity");
|
||||
setWizardStep(WizardSteps.SelectAction);
|
||||
}}
|
||||
/>
|
||||
</motion.div>
|
||||
)}
|
||||
{wizardStep === WizardSteps.LinkIdentity && (
|
||||
<motion.div
|
||||
key="link-step"
|
||||
transition={{ duration: 0.1 }}
|
||||
initial={{ opacity: 0, translateX: 30 }}
|
||||
animate={{ opacity: 1, translateX: 0 }}
|
||||
exit={{ opacity: 0, translateX: -30 }}
|
||||
>
|
||||
<ProjectLinkIdentityModal handlePopUpToggle={handlePopUpToggle} />
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
Assign Existing
|
||||
</Button>
|
||||
</div>
|
||||
<Tooltip
|
||||
className="max-w-sm"
|
||||
position="right"
|
||||
align="start"
|
||||
content={
|
||||
<>
|
||||
<p className="mb-2 text-mineshaft-300">
|
||||
You can add machine identities to your project in one of two ways:
|
||||
</p>
|
||||
<ul className="ml-3.5 flex list-disc flex-col gap-y-4">
|
||||
<li className="text-mineshaft-200">
|
||||
<strong className="font-medium text-mineshaft-100">Create New</strong> -
|
||||
Create a dedicated machine identity managed at the project-level.
|
||||
<p className="mt-2">
|
||||
This method is recommended for autonomous teams that need to manage
|
||||
machine identity authentication.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<strong className="font-medium text-mineshaft-100">Assign Existing</strong>{" "}
|
||||
- Assign an existing machine identity from your organization.
|
||||
<p className="mt-2">
|
||||
This method is recommended for organizations that need to maintain
|
||||
centralized control.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<InfoIcon size={16} className="text-mineshaft-400" />
|
||||
</Tooltip>
|
||||
</div>
|
||||
{addMachineIdentityType === AddIdentityType.CreateNew && (
|
||||
<ProjectIdentityModal
|
||||
onClose={() => {
|
||||
handlePopUpClose("createIdentity");
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{addMachineIdentityType === AddIdentityType.AssignExisting && (
|
||||
<ProjectLinkIdentityModal handlePopUpToggle={handlePopUpToggle} />
|
||||
)}
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
<DeleteActionModal
|
||||
|
||||
@@ -5,7 +5,7 @@ import { useQuery } from "@tanstack/react-query";
|
||||
import { z } from "zod";
|
||||
|
||||
import { createNotification } from "@app/components/notifications";
|
||||
import { Button, FilterableSelect, FormControl, ModalClose, Spinner } from "@app/components/v2";
|
||||
import { Button, FilterableSelect, FormControl, ModalClose } from "@app/components/v2";
|
||||
import { useProject } from "@app/context";
|
||||
import {
|
||||
projectIdentityMembershipQuery,
|
||||
@@ -101,13 +101,6 @@ export const ProjectLinkIdentityModal = ({ handlePopUpToggle }: Props) => {
|
||||
handlePopUpToggle("createIdentity", false);
|
||||
};
|
||||
|
||||
if (isMembershipsLoading || isRolesLoading)
|
||||
return (
|
||||
<div className="flex w-full items-center justify-center py-10">
|
||||
<Spinner className="text-mineshaft-400" />
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit(onFormSubmit)}>
|
||||
<Controller
|
||||
@@ -118,6 +111,7 @@ export const ProjectLinkIdentityModal = ({ handlePopUpToggle }: Props) => {
|
||||
<FilterableSelect
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
isLoading={isMembershipsLoading}
|
||||
placeholder="Select machine identity..."
|
||||
// onInputChange={setSearchValue}
|
||||
options={filteredIdentityMembershipOrgs.map((membership) => ({
|
||||
@@ -142,6 +136,7 @@ export const ProjectLinkIdentityModal = ({ handlePopUpToggle }: Props) => {
|
||||
>
|
||||
<FilterableSelect
|
||||
value={value}
|
||||
isLoading={isRolesLoading}
|
||||
onChange={onChange}
|
||||
options={roles}
|
||||
placeholder="Select role..."
|
||||
@@ -159,7 +154,7 @@ export const ProjectLinkIdentityModal = ({ handlePopUpToggle }: Props) => {
|
||||
isLoading={isSubmitting}
|
||||
isDisabled={isSubmitting}
|
||||
>
|
||||
Link
|
||||
Assign to Project
|
||||
</Button>
|
||||
<ModalClose asChild>
|
||||
<Button colorSchema="secondary" variant="plain">
|
||||
|
||||
Reference in New Issue
Block a user