Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This seems to improve the performance in the role form while still maintaining the same validation logic. A big factor was the memoization of the categories calculation and respective elements, which is especially impactful when there are many environments.
- Loading branch information
Showing
5 changed files
with
137 additions
and
106 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
110 changes: 110 additions & 0 deletions
110
.../src/component/admin/roles/RoleForm/RolePermissionCategories/RolePermissionCategories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
import { | ||
Person as UserIcon, | ||
Topic as TopicIcon, | ||
CloudCircle as CloudCircleIcon, | ||
} from '@mui/icons-material'; | ||
import { | ||
ENVIRONMENT_PERMISSION_TYPE, | ||
PROJECT_PERMISSION_TYPE, | ||
PROJECT_ROLE_TYPES, | ||
} from '@server/util/constants'; | ||
import usePermissions from 'hooks/api/getters/usePermissions/usePermissions'; | ||
import { ICheckedPermissions, IPermission } from 'interfaces/permissions'; | ||
import { PredefinedRoleType } from 'interfaces/role'; | ||
import { | ||
flattenProjectPermissions, | ||
getCategorizedProjectPermissions, | ||
getCategorizedRootPermissions, | ||
toggleAllPermissions, | ||
togglePermission, | ||
} from 'utils/permissions'; | ||
import { RolePermissionCategory } from './RolePermissionCategory'; | ||
import { useMemo } from 'react'; | ||
|
||
interface IPermissionCategoriesProps { | ||
type: PredefinedRoleType; | ||
checkedPermissions: ICheckedPermissions; | ||
setCheckedPermissions: React.Dispatch< | ||
React.SetStateAction<ICheckedPermissions> | ||
>; | ||
validatePermissions: (permissions: ICheckedPermissions) => boolean; | ||
} | ||
|
||
export const RolePermissionCategories = ({ | ||
type, | ||
checkedPermissions, | ||
setCheckedPermissions, | ||
validatePermissions, | ||
}: IPermissionCategoriesProps) => { | ||
const { permissions } = usePermissions({ | ||
revalidateIfStale: false, | ||
revalidateOnReconnect: false, | ||
revalidateOnFocus: false, | ||
}); | ||
|
||
const isProjectRole = PROJECT_ROLE_TYPES.includes(type); | ||
|
||
const categories = useMemo( | ||
() => | ||
isProjectRole | ||
? getCategorizedProjectPermissions( | ||
flattenProjectPermissions( | ||
permissions.project, | ||
permissions.environments, | ||
), | ||
) | ||
: getCategorizedRootPermissions(permissions.root), | ||
[permissions, isProjectRole], | ||
); | ||
|
||
const onPermissionChange = (permission: IPermission) => { | ||
const newCheckedPermissions = togglePermission( | ||
checkedPermissions, | ||
permission, | ||
); | ||
validatePermissions(newCheckedPermissions); | ||
setCheckedPermissions(newCheckedPermissions); | ||
}; | ||
|
||
const onCheckAll = (permissions: IPermission[]) => { | ||
const newCheckedPermissions = toggleAllPermissions( | ||
checkedPermissions, | ||
permissions, | ||
); | ||
validatePermissions(newCheckedPermissions); | ||
setCheckedPermissions(newCheckedPermissions); | ||
}; | ||
|
||
return useMemo( | ||
() => ( | ||
<> | ||
{categories.map(({ label, type, permissions }) => ( | ||
<RolePermissionCategory | ||
key={label} | ||
title={`${label} permissions`} | ||
context={label.toLowerCase()} | ||
Icon={ | ||
type === PROJECT_PERMISSION_TYPE ? ( | ||
<TopicIcon color='disabled' sx={{ mr: 1 }} /> | ||
) : type === ENVIRONMENT_PERMISSION_TYPE ? ( | ||
<CloudCircleIcon | ||
color='disabled' | ||
sx={{ mr: 1 }} | ||
/> | ||
) : ( | ||
<UserIcon color='disabled' sx={{ mr: 1 }} /> | ||
) | ||
} | ||
permissions={permissions} | ||
checkedPermissions={checkedPermissions} | ||
onPermissionChange={(permission: IPermission) => | ||
onPermissionChange(permission) | ||
} | ||
onCheckAll={() => onCheckAll(permissions)} | ||
/> | ||
))} | ||
</> | ||
), | ||
[categories, checkedPermissions], | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters