import { useEffect } from "react"; import { Controller, useFieldArray, useForm } from "react-hook-form"; import { SingleValue } from "react-select"; import { faPlus, faTrash } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { zodResolver } from "@hookform/resolvers/zod"; import { z } from "zod"; import { createNotification } from "@app/components/notifications"; import { Button, FilterableSelect, FormControl, FormLabel, IconButton, Input, Modal, ModalContent } from "@app/components/v2"; import { useOrganization, useSubscription } from "@app/context"; import { findOrgMembershipRole, isCustomOrgRole } from "@app/helpers/roles"; import { useGetOrgRoles, useUpdateOrgMembership } from "@app/hooks/api"; import { UsePopUpState } from "@app/hooks/usePopUp"; const schema = z.object({ role: z.object({ name: z.string(), slug: z.string() }), metadata: z .object({ key: z.string().trim().min(1), value: z.string().trim().min(1) }) .array() .optional() }); export type FormData = z.infer; type Props = { popUp: UsePopUpState<["orgMembership"]>; handlePopUpOpen: (popUpName: keyof UsePopUpState<["upgradePlan"]>, data?: object) => void; handlePopUpToggle: (popUpName: keyof UsePopUpState<["orgMembership"]>, state?: boolean) => void; }; export const UserOrgMembershipModal = ({ popUp, handlePopUpOpen, handlePopUpToggle }: Props) => { const { subscription } = useSubscription(); const { currentOrg } = useOrganization(); const orgId = currentOrg?.id || ""; const { data: roles = [] } = useGetOrgRoles(orgId); const { mutateAsync: updateOrgMembership } = useUpdateOrgMembership(); const { control, handleSubmit, reset, formState: { isSubmitting } } = useForm({ resolver: zodResolver(schema) }); const metadataFormFields = useFieldArray({ control, name: "metadata" }); const popUpData = popUp?.orgMembership?.data as { membershipId: string; role: string; roleId?: string; metadata: { key: string; value: string }[]; }; useEffect(() => { if (!roles?.length) return; if (popUpData) { reset({ role: findOrgMembershipRole(roles, popUpData.roleId ?? popUpData.role), metadata: popUpData.metadata }); } else { reset({ role: findOrgMembershipRole(roles, currentOrg!.defaultMembershipRole!) }); } }, [popUp?.orgMembership?.data, roles]); const onFormSubmit = async ({ role, metadata }: FormData) => { try { if (!orgId) return; await updateOrgMembership({ organizationId: orgId, membershipId: popUpData.membershipId, role: role.slug, metadata }); handlePopUpToggle("orgMembership", false); createNotification({ text: "Successfully updated user organization role", type: "success" }); reset(); } catch (err) { console.error(err); const error = err as any; const text = error?.response?.data?.message ?? "Failed to update user organization role"; createNotification({ text, type: "error" }); } }; return ( { handlePopUpToggle("orgMembership", isOpen); reset(); }} >
( { const role = newValue as SingleValue<(typeof roles)[number]>; if (!role) return; const isCustomRole = isCustomOrgRole(role.slug); if (isCustomRole && subscription && !subscription?.rbac) { handlePopUpOpen("upgradePlan", { text: "Your current plan does not include access to assig custom roles to members. To unlock this feature, please upgrade to Infisical Pro plan." }); return; } onChange(role); }} value={value} getOptionValue={(option) => option.slug} getOptionLabel={(option) => option.name} /> )} />
{metadataFormFields.fields.map(({ id: metadataFieldId }, i) => (
{i === 0 && Key} ( )} />
{i === 0 && ( )} ( )} />
metadataFormFields.remove(i)} >
))}
); };