feat(Roles): adopt request form data for new form style
This commit is contained in:
@@ -1,51 +0,0 @@
|
||||
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 (
|
||||
<ControlledCheckbox
|
||||
disabled={disabled}
|
||||
name={`${name}.${subject.key}.${action.key}.value`}
|
||||
dataTest={`${action.key.toLowerCase()}-checkbox`}
|
||||
onChange={(e, value) => {
|
||||
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;
|
||||
@@ -0,0 +1,63 @@
|
||||
import React from 'react';
|
||||
import { useFormContext } from 'react-hook-form';
|
||||
import PropTypes from 'prop-types';
|
||||
import ControlledCheckbox from 'components/ControlledCheckbox';
|
||||
|
||||
const AllEntitiesPermissions = ({
|
||||
action,
|
||||
subject,
|
||||
disabled,
|
||||
name,
|
||||
syncIsCreator,
|
||||
}) => {
|
||||
const { getValues, formState, resetField } = useFormContext();
|
||||
|
||||
const fieldName = `${name}.${subject.key}.${action.key}.allEntities`;
|
||||
const defaultValue =
|
||||
formState.defaultValues?.[name]?.[subject.key]?.[action.key].allEntities;
|
||||
const ownEntitiesFieldName = `${name}.${subject.key}.${action.key}.ownEntities`;
|
||||
const ownEntitiesFieldTouched =
|
||||
formState.touchedFields?.[name]?.[subject.key]?.[action.key]
|
||||
?.ownEntities === true;
|
||||
|
||||
const currentValue = getValues(fieldName);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (currentValue === true) {
|
||||
resetField(ownEntitiesFieldName, { defaultValue: true });
|
||||
}
|
||||
}, [ownEntitiesFieldName, currentValue]);
|
||||
|
||||
const handleSyncIsCreator = (newValue) => {
|
||||
if (syncIsCreator && defaultValue === false && !ownEntitiesFieldTouched) {
|
||||
resetField(ownEntitiesFieldName, { defaultValue: newValue });
|
||||
}
|
||||
|
||||
if (newValue === true) {
|
||||
resetField(ownEntitiesFieldName, { defaultValue: true });
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<ControlledCheckbox
|
||||
disabled={disabled}
|
||||
name={fieldName}
|
||||
dataTest={`${action.key.toLowerCase()}-checkbox`}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
AllEntitiesPermissions.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 AllEntitiesPermissions;
|
||||
@@ -0,0 +1,41 @@
|
||||
import React from 'react';
|
||||
import { useFormContext } from 'react-hook-form';
|
||||
import PropTypes from 'prop-types';
|
||||
import ControlledCheckbox from 'components/ControlledCheckbox';
|
||||
|
||||
const OwnEntitiesPermission = ({ action, subject, disabled, name }) => {
|
||||
const { getValues, resetField } = useFormContext();
|
||||
|
||||
const fieldName = `${name}.${subject.key}.${action.key}.ownEntities`;
|
||||
const allEntitiesFieldName = `${name}.${subject.key}.${action.key}.allEntities`;
|
||||
|
||||
const currentValue = getValues(fieldName);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (currentValue === false) {
|
||||
resetField(allEntitiesFieldName, { defaultValue: false });
|
||||
}
|
||||
}, [allEntitiesFieldName, currentValue]);
|
||||
|
||||
return (
|
||||
<ControlledCheckbox
|
||||
name={fieldName}
|
||||
disabled={disabled}
|
||||
dataTest={`isCreator-${action.key.toLowerCase()}-checkbox`}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
OwnEntitiesPermission.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,
|
||||
};
|
||||
|
||||
export default OwnEntitiesPermission;
|
||||
@@ -1,4 +1,3 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import SettingsIcon from '@mui/icons-material/Settings';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import Paper from '@mui/material/Paper';
|
||||
@@ -10,12 +9,16 @@ import TableContainer from '@mui/material/TableContainer';
|
||||
import TableHead from '@mui/material/TableHead';
|
||||
import TableRow from '@mui/material/TableRow';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import PropTypes from 'prop-types';
|
||||
import * as React from 'react';
|
||||
|
||||
import ControlledCheckbox from 'components/ControlledCheckbox';
|
||||
import usePermissionCatalog from 'hooks/usePermissionCatalog.ee';
|
||||
import PermissionSettings from './PermissionSettings.ee';
|
||||
import useFormatMessage from 'hooks/useFormatMessage';
|
||||
import AllEntitiesPermissions from './AllEntitiesPermissions';
|
||||
import ConditionField from './OwnEntitiesPermission';
|
||||
import PermissionCatalogFieldLoader from './PermissionCatalogFieldLoader';
|
||||
import ActionField from './ActionField';
|
||||
import PermissionSettings from './PermissionSettings.ee';
|
||||
|
||||
const PermissionCatalogField = ({
|
||||
name = 'permissions',
|
||||
@@ -23,6 +26,7 @@ const PermissionCatalogField = ({
|
||||
syncIsCreator = false,
|
||||
loading = false,
|
||||
}) => {
|
||||
const formatMessage = useFormatMessage();
|
||||
const { data, isLoading: isPermissionCatalogLoading } =
|
||||
usePermissionCatalog();
|
||||
const permissionCatalog = data?.data;
|
||||
@@ -39,24 +43,44 @@ const PermissionCatalogField = ({
|
||||
<TableCell component="th" />
|
||||
|
||||
{permissionCatalog?.actions.map((action) => (
|
||||
<React.Fragment key={action.key}>
|
||||
<TableCell component="th" key={action.key}>
|
||||
<Typography
|
||||
component="div"
|
||||
variant="subtitle1"
|
||||
variant="subtitle2"
|
||||
align="center"
|
||||
sx={{
|
||||
color: 'text.secondary',
|
||||
fontWeight: 700,
|
||||
}}
|
||||
>
|
||||
{action.label}
|
||||
{action.label}{' '}
|
||||
{formatMessage('permissionCatalogField.ownEntitiesLabel')}
|
||||
</Typography>
|
||||
</TableCell>
|
||||
))}
|
||||
|
||||
<TableCell component="th" />
|
||||
<TableCell
|
||||
component="th"
|
||||
key={`${action.key}-isCreator-condition`}
|
||||
>
|
||||
<Typography
|
||||
component="div"
|
||||
variant="subtitle2"
|
||||
align="center"
|
||||
sx={{
|
||||
color: 'text.secondary',
|
||||
fontWeight: 700,
|
||||
}}
|
||||
>
|
||||
{action.label}{' '}
|
||||
{formatMessage('permissionCatalogField.allEntitiesLabel')}
|
||||
</Typography>
|
||||
</TableCell>
|
||||
</React.Fragment>
|
||||
))}
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
|
||||
<TableBody>
|
||||
{permissionCatalog?.subjects.map((subject) => (
|
||||
<TableRow
|
||||
@@ -71,10 +95,31 @@ const PermissionCatalogField = ({
|
||||
</TableCell>
|
||||
|
||||
{permissionCatalog?.actions.map((action) => (
|
||||
<TableCell key={`${subject.key}.${action.key}`} align="center">
|
||||
<React.Fragment key={`${subject.key}.${action.key}`}>
|
||||
<TableCell
|
||||
key={`${subject.key}.${action.key}-isCreator-condition`}
|
||||
align="center"
|
||||
>
|
||||
<Typography variant="subtitle2" component="div">
|
||||
{action.subjects.includes(subject.key) && (
|
||||
<ActionField
|
||||
<ConditionField
|
||||
action={action}
|
||||
subject={subject}
|
||||
disabled={disabled}
|
||||
name={name}
|
||||
/>
|
||||
)}
|
||||
{!action.subjects.includes(subject.key) && '-'}
|
||||
</Typography>
|
||||
</TableCell>
|
||||
|
||||
<TableCell
|
||||
key={`${subject.key}.${action.key}`}
|
||||
align="center"
|
||||
>
|
||||
<Typography variant="subtitle2" component="div">
|
||||
{action.subjects.includes(subject.key) && (
|
||||
<AllEntitiesPermissions
|
||||
action={action}
|
||||
subject={subject}
|
||||
disabled={disabled}
|
||||
@@ -85,30 +130,8 @@ const PermissionCatalogField = ({
|
||||
{!action.subjects.includes(subject.key) && '-'}
|
||||
</Typography>
|
||||
</TableCell>
|
||||
</React.Fragment>
|
||||
))}
|
||||
|
||||
<TableCell>
|
||||
<Stack direction="row" gap={1} justifyContent="right">
|
||||
<IconButton
|
||||
color="info"
|
||||
size="small"
|
||||
onClick={() => setDialogName(subject.key)}
|
||||
disabled={disabled}
|
||||
data-test="permission-settings-button"
|
||||
>
|
||||
<SettingsIcon />
|
||||
</IconButton>
|
||||
|
||||
<PermissionSettings
|
||||
open={dialogName === subject.key}
|
||||
onClose={() => setDialogName('')}
|
||||
fieldPrefix={`${name}.${subject.key}`}
|
||||
subject={subject.key}
|
||||
actions={permissionCatalog?.actions}
|
||||
conditions={permissionCatalog?.conditions}
|
||||
/>
|
||||
</Stack>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
@@ -116,6 +139,7 @@ const PermissionCatalogField = ({
|
||||
</TableContainer>
|
||||
);
|
||||
};
|
||||
|
||||
PermissionCatalogField.propTypes = {
|
||||
name: PropTypes.string,
|
||||
disabled: PropTypes.bool,
|
||||
|
||||
@@ -6,10 +6,8 @@ export function getRoleWithComputedPermissions(role) {
|
||||
[permission.subject]: {
|
||||
...(computedPermissions[permission.subject] || {}),
|
||||
[permission.action]: {
|
||||
conditions: Object.fromEntries(
|
||||
permission.conditions.map((condition) => [condition, true]),
|
||||
),
|
||||
value: true,
|
||||
allEntities: permission.conditions.includes('isCreator') === false,
|
||||
ownEntities: true,
|
||||
},
|
||||
},
|
||||
}),
|
||||
@@ -28,15 +26,19 @@ export function getPermissions(computedPermissions) {
|
||||
(permissions, computedPermissionEntry) => {
|
||||
const [subject, actionsWithConditions] = computedPermissionEntry;
|
||||
for (const action in actionsWithConditions) {
|
||||
const { value: permitted, conditions = {} } =
|
||||
actionsWithConditions[action];
|
||||
if (permitted) {
|
||||
const { ownEntities, allEntities } = actionsWithConditions[action];
|
||||
|
||||
if (ownEntities && !allEntities) {
|
||||
permissions.push({
|
||||
action,
|
||||
subject,
|
||||
conditions: Object.entries(conditions)
|
||||
.filter(([, enabled]) => enabled)
|
||||
.map(([condition]) => condition),
|
||||
conditions: ['isCreator'],
|
||||
});
|
||||
} else if (ownEntities && allEntities) {
|
||||
permissions.push({
|
||||
action,
|
||||
subject,
|
||||
conditions: [],
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -46,18 +48,9 @@ export function getPermissions(computedPermissions) {
|
||||
);
|
||||
}
|
||||
|
||||
export const getComputedPermissionsDefaultValues = (
|
||||
data,
|
||||
conditionsInitialValues,
|
||||
) => {
|
||||
export const getComputedPermissionsDefaultValues = (data) => {
|
||||
if (!data) return {};
|
||||
|
||||
const conditions = {};
|
||||
data.conditions.forEach((condition) => {
|
||||
conditions[condition.key] =
|
||||
conditionsInitialValues?.[condition.key] || false;
|
||||
});
|
||||
|
||||
const result = {};
|
||||
|
||||
data.subjects.forEach((subject) => {
|
||||
@@ -69,8 +62,8 @@ export const getComputedPermissionsDefaultValues = (
|
||||
|
||||
if (action.subjects.includes(subjectKey)) {
|
||||
result[subjectKey][actionKey] = {
|
||||
value: false,
|
||||
conditions: { ...conditions },
|
||||
ownEntities: false,
|
||||
allEntities: false,
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
@@ -403,5 +403,7 @@
|
||||
"executionFilters.statusFilterSuccessfulOption": "Successful",
|
||||
"executionFilters.statusFilterFailedOption": "Failed",
|
||||
"executionFilters.startDateLabel": "Start Date",
|
||||
"executionFilters.endDateLabel": "End Date"
|
||||
"executionFilters.endDateLabel": "End Date",
|
||||
"permissionCatalogField.ownEntitiesLabel": "(own entities)",
|
||||
"permissionCatalogField.allEntitiesLabel": "(all entities)"
|
||||
}
|
||||
|
||||
@@ -73,9 +73,6 @@ export default function CreateRole() {
|
||||
description: '',
|
||||
computedPermissions: getComputedPermissionsDefaultValues(
|
||||
permissionCatalogData?.data,
|
||||
{
|
||||
isCreator: true,
|
||||
},
|
||||
),
|
||||
}),
|
||||
[permissionCatalogData],
|
||||
|
||||
@@ -78,6 +78,7 @@ export default function EditRole() {
|
||||
try {
|
||||
setPermissionError(null);
|
||||
const newPermissions = getPermissions(roleData.computedPermissions);
|
||||
|
||||
await updateRole({
|
||||
name: roleData.name,
|
||||
description: roleData.description,
|
||||
|
||||
Reference in New Issue
Block a user