improvement: revise edit role page and access tree

This commit is contained in:
Scott Wilson
2025-06-24 15:23:27 -07:00
parent b59fa14bb6
commit ffac24ce75
28 changed files with 668 additions and 1799 deletions
@@ -1,4 +1,4 @@
import { useMemo } from "react";
import { useMemo, useState } from "react";
import { FormProvider, useForm } from "react-hook-form";
import { MongoAbility, MongoQuery, RawRuleOf } from "@casl/ability";
import { faSave } from "@fortawesome/free-solid-svg-icons";
@@ -88,6 +88,8 @@ export const RolePermissionsSection = ({ roleSlug, isDisabled }: Props) => {
roleSlug as string
);
const [showAccessTree, setShowAccessTree] = useState<ProjectPermissionSub | null>(null);
const form = useForm<TFormSchema>({
values: role ? { ...role, permissions: rolePermission2Form(role.permissions) } : undefined,
resolver: zodResolver(projectRoleFormSchema)
@@ -133,71 +135,90 @@ export const RolePermissionsSection = ({ roleSlug, isDisabled }: Props) => {
[JSON.stringify(permissions)]
);
const isSecretManagerProject = currentWorkspace.type === ProjectType.SecretManager;
return (
<div className="w-full">
{currentWorkspace.type === ProjectType.SecretManager && (
<AccessTree permissions={formattedPermissions} />
)}
<form
onSubmit={handleSubmit(onSubmit)}
className="w-full rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4"
className="flex h-full w-full flex-1 flex-col rounded-lg border border-mineshaft-600 bg-mineshaft-900 py-4"
>
<FormProvider {...form}>
<div className="flex items-center justify-between border-b border-mineshaft-400 pb-4">
<h3 className="text-lg font-semibold text-mineshaft-100">Policies</h3>
<div className="flex items-center space-x-4">
{isCustomRole && (
<>
{isDirty && (
<Button
className="mr-4 text-mineshaft-300"
variant="link"
isDisabled={isSubmitting}
isLoading={isSubmitting}
onClick={() => reset()}
>
Discard
</Button>
)}
<div className="flex items-center">
<Button
variant="outline_bg"
type="submit"
className={twMerge(
"mr-4 h-10 border",
isDirty && "bg-primary text-black hover:bg-primary hover:opacity-80"
)}
isDisabled={isSubmitting || !isDirty}
isLoading={isSubmitting}
leftIcon={<FontAwesomeIcon icon={faSave} />}
>
Save
</Button>
<AddPoliciesButton isDisabled={isDisabled} />
</div>
</>
)}
<div className="mx-4 flex items-center justify-between border-b border-mineshaft-400 pb-4">
<div>
<h3 className="text-lg font-semibold text-mineshaft-100">Policies</h3>
<p className="text-sm leading-3 text-mineshaft-400">
Configure granular access policies
</p>
</div>
</div>
<div className="py-4">
{!isPending && <PermissionEmptyState />}
{(Object.keys(PROJECT_PERMISSION_OBJECT) as ProjectPermissionSub[])
.filter((subject) => !EXCLUDED_PERMISSION_SUBS.includes(subject))
.filter((subject) => ProjectTypePermissionSubjects[currentWorkspace.type][subject])
.map((subject) => (
<GeneralPermissionPolicies
subject={subject}
actions={PROJECT_PERMISSION_OBJECT[subject].actions}
title={PROJECT_PERMISSION_OBJECT[subject].title}
key={`project-permission-${subject}`}
isDisabled={isDisabled}
{isCustomRole && (
<div className="flex items-center gap-2">
{isDirty && (
<Button
className="mr-4 text-mineshaft-300"
variant="link"
isDisabled={isSubmitting}
isLoading={isSubmitting}
onClick={() => reset()}
>
Discard
</Button>
)}
<Button
colorSchema="secondary"
type="submit"
className={twMerge("h-10 border")}
isDisabled={isSubmitting || !isDirty}
isLoading={isSubmitting}
leftIcon={<FontAwesomeIcon icon={faSave} />}
>
{renderConditionalComponents(subject, isDisabled)}
</GeneralPermissionPolicies>
))}
Save
</Button>
<div className="ml-2 border-l border-mineshaft-500 pl-4">
<AddPoliciesButton isDisabled={isDisabled} />
</div>
</div>
)}
</div>
<div className="flex flex-1 flex-col overflow-hidden pl-4 pr-1">
<div className="thin-scrollbar flex-1 overflow-y-scroll py-4">
{!isPending && <PermissionEmptyState />}
{(Object.keys(PROJECT_PERMISSION_OBJECT) as ProjectPermissionSub[])
.filter((subject) => !EXCLUDED_PERMISSION_SUBS.includes(subject))
.filter((subject) => ProjectTypePermissionSubjects[currentWorkspace.type][subject])
.map((subject) => (
<GeneralPermissionPolicies
subject={subject}
actions={PROJECT_PERMISSION_OBJECT[subject].actions}
title={PROJECT_PERMISSION_OBJECT[subject].title}
key={`project-permission-${subject}`}
isDisabled={isDisabled}
onShowAccessTree={
isSecretManagerProject &&
[
ProjectPermissionSub.Secrets,
ProjectPermissionSub.SecretFolders,
ProjectPermissionSub.DynamicSecrets,
ProjectPermissionSub.SecretImports
].includes(subject)
? setShowAccessTree
: undefined
}
>
{renderConditionalComponents(subject, isDisabled)}
</GeneralPermissionPolicies>
))}
</div>
</div>
</FormProvider>
</form>
{isSecretManagerProject && showAccessTree && (
<AccessTree
permissions={formattedPermissions}
subject={showAccessTree}
onClose={() => setShowAccessTree(null)}
/>
)}
</div>
);
};