diff --git a/packages/web/src/components/PermissionCatalogField/ActionField.jsx b/packages/web/src/components/PermissionCatalogField/ActionField.jsx new file mode 100644 index 00000000..3bf2dde6 --- /dev/null +++ b/packages/web/src/components/PermissionCatalogField/ActionField.jsx @@ -0,0 +1,51 @@ +import React from 'react'; +import { useFormContext } from 'react-hook-form'; +import PropTypes from 'prop-types'; +import ControlledCheckbox from 'components/ControlledCheckbox'; + +const ActionField = ({ action, subject, disabled, name, syncIsCreator }) => { + const { formState, resetField } = useFormContext(); + + const actionDefaultValue = + formState.defaultValues?.[name]?.[subject.key]?.[action.key].value; + const conditionFieldName = `${name}.${subject.key}.${action.key}.conditions.isCreator`; + const conditionFieldTouched = + formState.touchedFields?.[name]?.[subject.key]?.[action.key]?.conditions + ?.isCreator === true; + + const handleSyncIsCreator = (newValue) => { + if ( + syncIsCreator && + actionDefaultValue === false && + !conditionFieldTouched + ) { + resetField(conditionFieldName, { defaultValue: newValue }); + } + }; + + return ( + { + handleSyncIsCreator(value); + }} + /> + ); +}; + +ActionField.propTypes = { + action: PropTypes.shape({ + key: PropTypes.string.isRequired, + subjects: PropTypes.arrayOf(PropTypes.string).isRequired, + }), + subject: PropTypes.shape({ + key: PropTypes.string.isRequired, + }).isRequired, + disabled: PropTypes.bool, + name: PropTypes.string.isRequired, + syncIsCreator: PropTypes.bool, +}; + +export default ActionField; diff --git a/packages/web/src/components/PermissionCatalogField/PermissionSettings.ee.jsx b/packages/web/src/components/PermissionCatalogField/PermissionSettings.ee.jsx index 14237a20..71cc4691 100644 --- a/packages/web/src/components/PermissionCatalogField/PermissionSettings.ee.jsx +++ b/packages/web/src/components/PermissionCatalogField/PermissionSettings.ee.jsx @@ -25,7 +25,6 @@ function PermissionSettings(props) { subject, actions, conditions, - defaultChecked, } = props; const formatMessage = useFormatMessage(); const { getValues, resetField } = useFormContext(); @@ -34,7 +33,7 @@ function PermissionSettings(props) { for (const action of actions) { for (const condition of conditions) { const fieldName = `${fieldPrefix}.${action.key}.conditions.${condition.key}`; - resetField(fieldName); + resetField(fieldName, { keepTouched: true }); } } onClose(); @@ -45,7 +44,7 @@ function PermissionSettings(props) { for (const condition of conditions) { const fieldName = `${fieldPrefix}.${action.key}.conditions.${condition.key}`; const value = getValues(fieldName); - resetField(fieldName, { defaultValue: value }); + resetField(fieldName, { defaultValue: value, keepTouched: true }); } } onClose(); @@ -56,6 +55,7 @@ function PermissionSettings(props) { open={open} onClose={cancel} data-test={`${subject}-role-conditions-modal`} + keepMounted > {formatMessage('permissionSettings.title')} @@ -65,10 +65,10 @@ function PermissionSettings(props) { - {actions.map((action) => ( - + {condition.label} @@ -99,14 +99,13 @@ function PermissionSettings(props) { key={`${action.key}.${condition.key}`} align="center" > - + {action.subjects.includes(subject) && ( { const { data, isLoading: isPermissionCatalogLoading } = usePermissionCatalog(); @@ -39,6 +39,7 @@ const PermissionCatalogField = ({ {permissionCatalog?.actions.map((action) => ( - {subject.label} + + {subject.label} + {permissionCatalog?.actions.map((action) => ( - + {action.subjects.includes(subject.key) && ( - )} - {!action.subjects.includes(subject.key) && '-'} @@ -100,7 +104,6 @@ const PermissionCatalogField = ({ subject={subject.key} actions={permissionCatalog?.actions} conditions={permissionCatalog?.conditions} - defaultChecked={defaultChecked} /> @@ -114,7 +117,7 @@ const PermissionCatalogField = ({ PermissionCatalogField.propTypes = { name: PropTypes.string, disabled: PropTypes.bool, - defaultChecked: PropTypes.bool, + syncIsCreator: PropTypes.bool, }; export default PermissionCatalogField; diff --git a/packages/web/src/helpers/computePermissions.ee.js b/packages/web/src/helpers/computePermissions.ee.js index 7c6ae20e..3bcfa521 100644 --- a/packages/web/src/helpers/computePermissions.ee.js +++ b/packages/web/src/helpers/computePermissions.ee.js @@ -45,3 +45,36 @@ export function getPermissions(computedPermissions) { [], ); } + +export const getComputedPermissionsDefaultValues = ( + data, + conditionsInitialValues, +) => { + if (!data) return {}; + + const conditions = {}; + data.conditions.forEach((condition) => { + conditions[condition.key] = + conditionsInitialValues?.[condition.key] || false; + }); + + const result = {}; + + data.subjects.forEach((subject) => { + const subjectKey = subject.key; + result[subjectKey] = {}; + + data.actions.forEach((action) => { + const actionKey = action.key; + + if (action.subjects.includes(subjectKey)) { + result[subjectKey][actionKey] = { + value: false, + conditions: { ...conditions }, + }; + } + }); + }); + + return result; +}; diff --git a/packages/web/src/pages/CreateRole/index.ee.jsx b/packages/web/src/pages/CreateRole/index.ee.jsx index a7767e76..b5ff22c9 100644 --- a/packages/web/src/pages/CreateRole/index.ee.jsx +++ b/packages/web/src/pages/CreateRole/index.ee.jsx @@ -11,9 +11,13 @@ import Form from 'components/Form'; import PageTitle from 'components/PageTitle'; import TextField from 'components/TextField'; import * as URLS from 'config/urls'; -import { getPermissions } from 'helpers/computePermissions.ee'; +import { + getComputedPermissionsDefaultValues, + getPermissions, +} from 'helpers/computePermissions.ee'; import useFormatMessage from 'hooks/useFormatMessage'; import useAdminCreateRole from 'hooks/useAdminCreateRole'; +import usePermissionCatalog from 'hooks/usePermissionCatalog.ee'; export default function CreateRole() { const navigate = useNavigate(); @@ -21,6 +25,21 @@ export default function CreateRole() { const enqueueSnackbar = useEnqueueSnackbar(); const { mutateAsync: createRole, isPending: isCreateRolePending } = useAdminCreateRole(); + const { data: permissionCatalogData } = usePermissionCatalog(); + + const defaultValues = React.useMemo( + () => ({ + name: '', + description: '', + computedPermissions: getComputedPermissionsDefaultValues( + permissionCatalogData?.data, + { + isCreator: true, + }, + ), + }), + [permissionCatalogData], + ); const handleRoleCreation = async (roleData) => { try { @@ -64,7 +83,7 @@ export default function CreateRole() { -
+ - + { @@ -52,7 +57,20 @@ export default function EditRole() { } }; - const roleWithComputedPermissions = getRoleWithComputedPermissions(role); + const defaultValues = React.useMemo(() => { + const roleWithComputedPermissions = getRoleWithComputedPermissions(role); + const computedPermissionsDefaultValues = + getComputedPermissionsDefaultValues(permissionCatalog); + + return { + ...roleWithComputedPermissions, + computedPermissions: merge( + {}, + computedPermissionsDefaultValues, + roleWithComputedPermissions.computedPermissions, + ), + }; + }, [role, permissionCatalog]); return ( @@ -64,10 +82,7 @@ export default function EditRole() { - + {isRoleLoading && ( <> @@ -95,12 +110,11 @@ export default function EditRole() { /> )} - -