diff --git a/frontend/src/views/Project/MembersPage/components/ProjectRoleListTab/components/ProjectRoleModifySection/ProjectRoleModifySection.tsx b/frontend/src/views/Project/MembersPage/components/ProjectRoleListTab/components/ProjectRoleModifySection/ProjectRoleModifySection.tsx index 2140887de..c386ebc11 100644 --- a/frontend/src/views/Project/MembersPage/components/ProjectRoleListTab/components/ProjectRoleModifySection/ProjectRoleModifySection.tsx +++ b/frontend/src/views/Project/MembersPage/components/ProjectRoleListTab/components/ProjectRoleModifySection/ProjectRoleModifySection.tsx @@ -14,7 +14,8 @@ import { faShield, faTags, faUser, - faUsers} from "@fortawesome/free-solid-svg-icons"; + faUsers +} from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { zodResolver } from "@hookform/resolvers/zod"; diff --git a/frontend/src/views/Project/RolePage/RolePage.tsx b/frontend/src/views/Project/RolePage/RolePage.tsx index 235c28974..19ec657ec 100644 --- a/frontend/src/views/Project/RolePage/RolePage.tsx +++ b/frontend/src/views/Project/RolePage/RolePage.tsx @@ -20,9 +20,7 @@ import { withProjectPermission } from "@app/hoc"; import { useGetProjectRoleBySlug } from "@app/hooks/api"; import { usePopUp } from "@app/hooks/usePopUp"; -import { RoleDetailsSection, RolePermissionsSection } from "./components"; - -// import { RoleDetailsSection, RoleModal, RolePermissionsSection } from "./components"; +import { RoleDetailsSection, RoleModal,RolePermissionsSection } from "./components"; export const RolePage = withProjectPermission( () => { @@ -66,7 +64,7 @@ export const RolePage = withProjectPermission( } }; - const isCustomRole = !["admin", "member", "no-access"].includes(data?.slug ?? ""); + const isCustomRole = !["admin", "member", "viewer", "no-access"].includes(data?.slug ?? ""); return (
@@ -148,7 +146,7 @@ export const RolePage = withProjectPermission(
)} - {/* */} + , data?: {}) => void; + handlePopUpOpen: (popUpName: keyof UsePopUpState<["role"]>, data?: {}) => void; }; -export const RoleDetailsSection = ({ - roleSlug -}: // handlePopUpOpen -Props) => { +export const RoleDetailsSection = ({ roleSlug, handlePopUpOpen }: Props) => { const [copyTextId, isCopyingId, setCopyTextId] = useTimedReset({ initialState: "Copy ID to clipboard" }); @@ -41,10 +38,9 @@ Props) => { variant="plain" className="group relative" onClick={() => { - // TODO - // handlePopUpOpen("role", { - // roleId - // }) + handlePopUpOpen("role", { + roleSlug + }); }} > diff --git a/frontend/src/views/Project/RolePage/components/RoleModal.tsx b/frontend/src/views/Project/RolePage/components/RoleModal.tsx new file mode 100644 index 000000000..463f36a78 --- /dev/null +++ b/frontend/src/views/Project/RolePage/components/RoleModal.tsx @@ -0,0 +1,231 @@ +import { useEffect } from "react"; +import { Controller, useForm } from "react-hook-form"; +// import { useRouter } from "next/router"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { z } from "zod"; + +import { createNotification } from "@app/components/notifications"; +import { Button, FormControl, Input, Modal, ModalContent } from "@app/components/v2"; +import { + // useOrganization, + useWorkspace +} from "@app/context"; +import { + // useCreateProjectRole, + // useUpdateProjectRole, + useGetProjectRoleBySlug + // useCreateOrgRole, + // useGetOrgRole, + // useUpdateOrgRole +} from "@app/hooks/api"; +import { UsePopUpState } from "@app/hooks/usePopUp"; + +const schema = z + .object({ + name: z.string(), + description: z.string(), + slug: z.string() + }) + .required(); + +export type FormData = z.infer; + +type Props = { + popUp: UsePopUpState<["role"]>; + handlePopUpToggle: (popUpName: keyof UsePopUpState<["role"]>, state?: boolean) => void; +}; + +export const RoleModal = ({ popUp, handlePopUpToggle }: Props) => { + // const router = useRouter(); + + const popupData = popUp?.role?.data as { + roleSlug: string; + }; + + const { currentWorkspace } = useWorkspace(); + const projectSlug = currentWorkspace?.slug || ""; + + const { data: role } = useGetProjectRoleBySlug(projectSlug, popupData?.roleSlug ?? ""); + + console.log("Project RoleModal role: ", role); + + // const { mutateAsync: createProjectRole } = useCreateProjectRole(); + // const { mutateAsync: updateProjectRole } = useUpdateProjectRole(); + + const { + control, + handleSubmit, + reset, + formState: { isSubmitting } + } = useForm({ + resolver: zodResolver(schema), + defaultValues: { + name: "", + description: "" + } + }); + + useEffect(() => { + if (role) { + reset({ + name: role.name, + description: role.description, + slug: role.slug + }); + } else { + reset({ + name: "", + description: "", + slug: "" + }); + } + }, [role]); + + const onFormSubmit = async ({ name, description, slug }: FormData) => { + try { + console.log("onFormSubmit args: ", { + name, + description, + slug + }); + + if (!projectSlug || !role?.id) return; + + if (role) { + // update + console.log("update"); + // const u1 = await updateProjectRole({ + // id: role.id, + // projectSlug, + // name, + // description, + // slug + // }); + // console.log("u1: ", u1); + } else { + // create + console.log("create"); + } + + // if (!orgId) return; + + // if (role) { + // // update + + // await updateOrgRole({ + // orgId, + // id: role.id, + // name, + // description, + // slug + // }); + + // handlePopUpToggle("role", false); + // } else { + // // create + + // const newRole = await createOrgRole({ + // orgId, + // name, + // description, + // slug, + // permissions: [] + // }); + + // handlePopUpToggle("role", false); + // router.push(`/org/${orgId}/roles/${newRole.id}`); + // } + + createNotification({ + text: `Successfully ${popUp?.role?.data ? "updated" : "created"} role`, + type: "success" + }); + + reset(); + } catch (err) { + console.error(err); + const error = err as any; + const text = + error?.response?.data?.message ?? + `Failed to ${popUp?.role?.data ? "update" : "create"} role`; + + createNotification({ + text, + type: "error" + }); + } + }; + + return ( + { + handlePopUpToggle("role", isOpen); + reset(); + }} + > + +
+ ( + + + + )} + /> + ( + + + + )} + /> + ( + + + + )} + /> +
+ + +
+ +
+
+ ); +}; diff --git a/frontend/src/views/Project/RolePage/components/RolePermissionsSection/RolePermissionSecretsRow.tsx b/frontend/src/views/Project/RolePage/components/RolePermissionsSection/RolePermissionSecretsRow.tsx index d36be71ae..786f58cf1 100644 --- a/frontend/src/views/Project/RolePage/components/RolePermissionsSection/RolePermissionSecretsRow.tsx +++ b/frontend/src/views/Project/RolePage/components/RolePermissionsSection/RolePermissionSecretsRow.tsx @@ -1,16 +1,24 @@ import { useMemo } from "react"; -import { - Control, - // Controller, - UseFormGetValues, - UseFormSetValue, - useWatch -} from "react-hook-form"; -import { faChevronDown, faChevronRight } from "@fortawesome/free-solid-svg-icons"; +import { Control, Controller, UseFormGetValues, UseFormSetValue, useWatch } from "react-hook-form"; +import { faChevronDown } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { Select, SelectItem,Td, Tr } from "@app/components/v2"; -import { useToggle } from "@app/hooks"; +import GlobPatternExamples from "@app/components/basic/popups/GlobPatternExamples"; +import { + Checkbox, + FormControl, + Input, + Select, + SelectItem, + Table, + TableContainer, + TBody, + Td, + Th, + THead, + Tr +} from "@app/components/v2"; +import { useWorkspace } from "@app/context"; import { TFormSchema } from "@app/views/Project/MembersPage/components/ProjectRoleListTab/components/ProjectRoleModifySection/ProjectRoleModifySection.utils"; type Props = { @@ -37,8 +45,14 @@ export const RowPermissionSecretsRow = ({ getValue, control }: Props) => { - const [isRowExpanded, setIsRowExpanded] = useToggle(); - // const [isCustom, setIsCustom] = useToggle(); + const { currentWorkspace } = useWorkspace(); + const environments = currentWorkspace?.environments || []; + + const customRule = useWatch({ + control, + name: `permissions.${formName}.custom` + }); + const isCustom = Boolean(customRule); const allRule = useWatch({ control, name: `permissions.${formName}.all` }); @@ -83,17 +97,13 @@ export const RowPermissionSecretsRow = ({ }; return ( - setIsRowExpanded.toggle()} - > - - - + <> + + {isCustom && } {title} + + )} + /> + + + ( +
+ +
+ )} + /> + + + ( +
+ +
+ )} + /> + + + ( +
+ +
+ )} + /> + + + ( +
+ +
+ )} + /> + + + ))} + + + + + + + )} + ); }; diff --git a/frontend/src/views/Project/RolePage/components/RolePermissionsSection/RolePermissionsSection.tsx b/frontend/src/views/Project/RolePage/components/RolePermissionsSection/RolePermissionsSection.tsx index 3097520bc..6a03503ea 100644 --- a/frontend/src/views/Project/RolePage/components/RolePermissionsSection/RolePermissionsSection.tsx +++ b/frontend/src/views/Project/RolePage/components/RolePermissionsSection/RolePermissionsSection.tsx @@ -2,27 +2,17 @@ import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { createNotification } from "@app/components/notifications"; +import { Button, Table, TableContainer, TBody, Th, THead, Tr } from "@app/components/v2"; +import { ProjectPermissionSub, useWorkspace } from "@app/context"; +import { useGetProjectRoleBySlug, useUpdateProjectRole } from "@app/hooks/api"; import { - Button, - Table, - TableContainer, - TBody, - Th, - THead, - Tr - // Td -} from "@app/components/v2"; -import { ProjectPermissionSub,useWorkspace } from "@app/context"; -import { - // useUpdateOrgRole, - useGetProjectRoleBySlug -} from "@app/hooks/api"; -import { - formSchema, +formRolePermission2API, formSchema, rolePermission2Form, - TFormSchema} from "@app/views/Project/MembersPage/components/ProjectRoleListTab/components/ProjectRoleModifySection/ProjectRoleModifySection.utils"; + TFormSchema + } from "@app/views/Project/MembersPage/components/ProjectRoleListTab/components/ProjectRoleModifySection/ProjectRoleModifySection.utils"; import { RolePermissionRow } from "./RolePermissionRow"; +import { RowPermissionSecretsRow } from "./RolePermissionSecretsRow"; const SINGLE_PERMISSION_LIST = [ { @@ -99,16 +89,15 @@ type Props = { roleSlug: string; }; -// TODO: fill table - +// note: isEditable should also depend on if user has edit role permission export const RolePermissionsSection = ({ roleSlug }: Props) => { const { currentWorkspace } = useWorkspace(); + const projectSlug = currentWorkspace?.slug || ""; const { data: role } = useGetProjectRoleBySlug(currentWorkspace?.slug ?? "", roleSlug as string); - console.log("RolePermissionsSection role data: ", role); - const { setValue, + getValues, control, handleSubmit, formState: { isDirty, isSubmitting }, @@ -118,16 +107,19 @@ export const RolePermissionsSection = ({ roleSlug }: Props) => { resolver: zodResolver(formSchema) }); - // const { mutateAsync: updateRole } = useUpdateOrgRole(); + const { mutateAsync: updateRole } = useUpdateProjectRole(); - const onSubmit = async () => { + const onSubmit = async (el: TFormSchema) => { try { - // await updateRole({ - // orgId, - // id: roleId, - // ...el, - // permissions: formRolePermission2API(el.permissions) - // }); + if (!projectSlug || !role?.id) return; + + await updateRole({ + id: role?.id as string, + projectSlug, + ...el, + permissions: formRolePermission2API(el.permissions) + }); + createNotification({ type: "success", text: "Successfully updated role" }); } catch (err) { console.log(err); @@ -177,8 +169,15 @@ export const RolePermissionsSection = ({ roleSlug }: Props) => { + {SINGLE_PERMISSION_LIST.map((permission) => { - console.log("permission: ", permission); return (