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 SettingsIcon from '@mui/icons-material/Settings';
|
||||||
import IconButton from '@mui/material/IconButton';
|
import IconButton from '@mui/material/IconButton';
|
||||||
import Paper from '@mui/material/Paper';
|
import Paper from '@mui/material/Paper';
|
||||||
@@ -10,12 +9,16 @@ import TableContainer from '@mui/material/TableContainer';
|
|||||||
import TableHead from '@mui/material/TableHead';
|
import TableHead from '@mui/material/TableHead';
|
||||||
import TableRow from '@mui/material/TableRow';
|
import TableRow from '@mui/material/TableRow';
|
||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
|
import ControlledCheckbox from 'components/ControlledCheckbox';
|
||||||
import usePermissionCatalog from 'hooks/usePermissionCatalog.ee';
|
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 PermissionCatalogFieldLoader from './PermissionCatalogFieldLoader';
|
||||||
import ActionField from './ActionField';
|
import PermissionSettings from './PermissionSettings.ee';
|
||||||
|
|
||||||
const PermissionCatalogField = ({
|
const PermissionCatalogField = ({
|
||||||
name = 'permissions',
|
name = 'permissions',
|
||||||
@@ -23,6 +26,7 @@ const PermissionCatalogField = ({
|
|||||||
syncIsCreator = false,
|
syncIsCreator = false,
|
||||||
loading = false,
|
loading = false,
|
||||||
}) => {
|
}) => {
|
||||||
|
const formatMessage = useFormatMessage();
|
||||||
const { data, isLoading: isPermissionCatalogLoading } =
|
const { data, isLoading: isPermissionCatalogLoading } =
|
||||||
usePermissionCatalog();
|
usePermissionCatalog();
|
||||||
const permissionCatalog = data?.data;
|
const permissionCatalog = data?.data;
|
||||||
@@ -39,24 +43,44 @@ const PermissionCatalogField = ({
|
|||||||
<TableCell component="th" />
|
<TableCell component="th" />
|
||||||
|
|
||||||
{permissionCatalog?.actions.map((action) => (
|
{permissionCatalog?.actions.map((action) => (
|
||||||
<TableCell component="th" key={action.key}>
|
<React.Fragment key={action.key}>
|
||||||
<Typography
|
<TableCell component="th" key={action.key}>
|
||||||
component="div"
|
<Typography
|
||||||
variant="subtitle1"
|
component="div"
|
||||||
align="center"
|
variant="subtitle2"
|
||||||
sx={{
|
align="center"
|
||||||
color: 'text.secondary',
|
sx={{
|
||||||
fontWeight: 700,
|
color: 'text.secondary',
|
||||||
}}
|
fontWeight: 700,
|
||||||
>
|
}}
|
||||||
{action.label}
|
>
|
||||||
</Typography>
|
{action.label}{' '}
|
||||||
</TableCell>
|
{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>
|
</TableRow>
|
||||||
</TableHead>
|
</TableHead>
|
||||||
|
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{permissionCatalog?.subjects.map((subject) => (
|
{permissionCatalog?.subjects.map((subject) => (
|
||||||
<TableRow
|
<TableRow
|
||||||
@@ -71,44 +95,43 @@ const PermissionCatalogField = ({
|
|||||||
</TableCell>
|
</TableCell>
|
||||||
|
|
||||||
{permissionCatalog?.actions.map((action) => (
|
{permissionCatalog?.actions.map((action) => (
|
||||||
<TableCell key={`${subject.key}.${action.key}`} align="center">
|
<React.Fragment key={`${subject.key}.${action.key}`}>
|
||||||
<Typography variant="subtitle2" component="div">
|
<TableCell
|
||||||
{action.subjects.includes(subject.key) && (
|
key={`${subject.key}.${action.key}-isCreator-condition`}
|
||||||
<ActionField
|
align="center"
|
||||||
action={action}
|
|
||||||
subject={subject}
|
|
||||||
disabled={disabled}
|
|
||||||
name={name}
|
|
||||||
syncIsCreator={syncIsCreator}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{!action.subjects.includes(subject.key) && '-'}
|
|
||||||
</Typography>
|
|
||||||
</TableCell>
|
|
||||||
))}
|
|
||||||
|
|
||||||
<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 />
|
<Typography variant="subtitle2" component="div">
|
||||||
</IconButton>
|
{action.subjects.includes(subject.key) && (
|
||||||
|
<ConditionField
|
||||||
|
action={action}
|
||||||
|
subject={subject}
|
||||||
|
disabled={disabled}
|
||||||
|
name={name}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{!action.subjects.includes(subject.key) && '-'}
|
||||||
|
</Typography>
|
||||||
|
</TableCell>
|
||||||
|
|
||||||
<PermissionSettings
|
<TableCell
|
||||||
open={dialogName === subject.key}
|
key={`${subject.key}.${action.key}`}
|
||||||
onClose={() => setDialogName('')}
|
align="center"
|
||||||
fieldPrefix={`${name}.${subject.key}`}
|
>
|
||||||
subject={subject.key}
|
<Typography variant="subtitle2" component="div">
|
||||||
actions={permissionCatalog?.actions}
|
{action.subjects.includes(subject.key) && (
|
||||||
conditions={permissionCatalog?.conditions}
|
<AllEntitiesPermissions
|
||||||
/>
|
action={action}
|
||||||
</Stack>
|
subject={subject}
|
||||||
</TableCell>
|
disabled={disabled}
|
||||||
|
name={name}
|
||||||
|
syncIsCreator={syncIsCreator}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{!action.subjects.includes(subject.key) && '-'}
|
||||||
|
</Typography>
|
||||||
|
</TableCell>
|
||||||
|
</React.Fragment>
|
||||||
|
))}
|
||||||
</TableRow>
|
</TableRow>
|
||||||
))}
|
))}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
@@ -116,6 +139,7 @@ const PermissionCatalogField = ({
|
|||||||
</TableContainer>
|
</TableContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
PermissionCatalogField.propTypes = {
|
PermissionCatalogField.propTypes = {
|
||||||
name: PropTypes.string,
|
name: PropTypes.string,
|
||||||
disabled: PropTypes.bool,
|
disabled: PropTypes.bool,
|
||||||
|
|||||||
@@ -6,10 +6,8 @@ export function getRoleWithComputedPermissions(role) {
|
|||||||
[permission.subject]: {
|
[permission.subject]: {
|
||||||
...(computedPermissions[permission.subject] || {}),
|
...(computedPermissions[permission.subject] || {}),
|
||||||
[permission.action]: {
|
[permission.action]: {
|
||||||
conditions: Object.fromEntries(
|
allEntities: permission.conditions.includes('isCreator') === false,
|
||||||
permission.conditions.map((condition) => [condition, true]),
|
ownEntities: true,
|
||||||
),
|
|
||||||
value: true,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -28,15 +26,19 @@ export function getPermissions(computedPermissions) {
|
|||||||
(permissions, computedPermissionEntry) => {
|
(permissions, computedPermissionEntry) => {
|
||||||
const [subject, actionsWithConditions] = computedPermissionEntry;
|
const [subject, actionsWithConditions] = computedPermissionEntry;
|
||||||
for (const action in actionsWithConditions) {
|
for (const action in actionsWithConditions) {
|
||||||
const { value: permitted, conditions = {} } =
|
const { ownEntities, allEntities } = actionsWithConditions[action];
|
||||||
actionsWithConditions[action];
|
|
||||||
if (permitted) {
|
if (ownEntities && !allEntities) {
|
||||||
permissions.push({
|
permissions.push({
|
||||||
action,
|
action,
|
||||||
subject,
|
subject,
|
||||||
conditions: Object.entries(conditions)
|
conditions: ['isCreator'],
|
||||||
.filter(([, enabled]) => enabled)
|
});
|
||||||
.map(([condition]) => condition),
|
} else if (ownEntities && allEntities) {
|
||||||
|
permissions.push({
|
||||||
|
action,
|
||||||
|
subject,
|
||||||
|
conditions: [],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -46,18 +48,9 @@ export function getPermissions(computedPermissions) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getComputedPermissionsDefaultValues = (
|
export const getComputedPermissionsDefaultValues = (data) => {
|
||||||
data,
|
|
||||||
conditionsInitialValues,
|
|
||||||
) => {
|
|
||||||
if (!data) return {};
|
if (!data) return {};
|
||||||
|
|
||||||
const conditions = {};
|
|
||||||
data.conditions.forEach((condition) => {
|
|
||||||
conditions[condition.key] =
|
|
||||||
conditionsInitialValues?.[condition.key] || false;
|
|
||||||
});
|
|
||||||
|
|
||||||
const result = {};
|
const result = {};
|
||||||
|
|
||||||
data.subjects.forEach((subject) => {
|
data.subjects.forEach((subject) => {
|
||||||
@@ -69,8 +62,8 @@ export const getComputedPermissionsDefaultValues = (
|
|||||||
|
|
||||||
if (action.subjects.includes(subjectKey)) {
|
if (action.subjects.includes(subjectKey)) {
|
||||||
result[subjectKey][actionKey] = {
|
result[subjectKey][actionKey] = {
|
||||||
value: false,
|
ownEntities: false,
|
||||||
conditions: { ...conditions },
|
allEntities: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -403,5 +403,7 @@
|
|||||||
"executionFilters.statusFilterSuccessfulOption": "Successful",
|
"executionFilters.statusFilterSuccessfulOption": "Successful",
|
||||||
"executionFilters.statusFilterFailedOption": "Failed",
|
"executionFilters.statusFilterFailedOption": "Failed",
|
||||||
"executionFilters.startDateLabel": "Start Date",
|
"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: '',
|
description: '',
|
||||||
computedPermissions: getComputedPermissionsDefaultValues(
|
computedPermissions: getComputedPermissionsDefaultValues(
|
||||||
permissionCatalogData?.data,
|
permissionCatalogData?.data,
|
||||||
{
|
|
||||||
isCreator: true,
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
}),
|
}),
|
||||||
[permissionCatalogData],
|
[permissionCatalogData],
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ export default function EditRole() {
|
|||||||
try {
|
try {
|
||||||
setPermissionError(null);
|
setPermissionError(null);
|
||||||
const newPermissions = getPermissions(roleData.computedPermissions);
|
const newPermissions = getPermissions(roleData.computedPermissions);
|
||||||
|
|
||||||
await updateRole({
|
await updateRole({
|
||||||
name: roleData.name,
|
name: roleData.name,
|
||||||
description: roleData.description,
|
description: roleData.description,
|
||||||
|
|||||||
Reference in New Issue
Block a user