feat: introduce inline error messages in SamlConfiguration and RoleMappings forms
This commit is contained in:
@@ -3,7 +3,7 @@ import LoadingButton from '@mui/lab/LoadingButton';
|
||||
import Divider from '@mui/material/Divider';
|
||||
import Stack from '@mui/material/Stack';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import useEnqueueSnackbar from 'hooks/useEnqueueSnackbar';
|
||||
import Alert from '@mui/material/Alert';
|
||||
import { useMemo } from 'react';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import * as yup from 'yup';
|
||||
@@ -13,6 +13,7 @@ import useFormatMessage from 'hooks/useFormatMessage';
|
||||
import useAdminSamlAuthProviderRoleMappings from 'hooks/useAdminSamlAuthProviderRoleMappings';
|
||||
import useAdminUpdateSamlAuthProviderRoleMappings from 'hooks/useAdminUpdateSamlAuthProviderRoleMappings';
|
||||
import RoleMappingsFieldArray from './RoleMappingsFieldsArray';
|
||||
import { getGeneralErrorMessage } from 'helpers/errors';
|
||||
|
||||
function generateFormRoleMappings(roleMappings) {
|
||||
if (roleMappings?.length === 0) {
|
||||
@@ -63,11 +64,11 @@ const getValidationSchema = (formatMessage) =>
|
||||
|
||||
function RoleMappings({ provider, providerLoading }) {
|
||||
const formatMessage = useFormatMessage();
|
||||
const enqueueSnackbar = useEnqueueSnackbar();
|
||||
|
||||
const {
|
||||
mutateAsync: updateRoleMappings,
|
||||
isPending: isUpdateRoleMappingsPending,
|
||||
isSuccess: isUpdateRoleMappingsSuccess,
|
||||
} = useAdminUpdateSamlAuthProviderRoleMappings(provider?.id);
|
||||
|
||||
const { data, isLoading: isAdminSamlAuthProviderRoleMappingsLoading } =
|
||||
@@ -75,8 +76,9 @@ function RoleMappings({ provider, providerLoading }) {
|
||||
adminSamlAuthProviderId: provider?.id,
|
||||
});
|
||||
const roleMappings = data?.data;
|
||||
const fieldNames = ['remoteRoleName', 'roleId'];
|
||||
|
||||
const handleRoleMappingsUpdate = async (values) => {
|
||||
const handleRoleMappingsUpdate = async (values, e, setError) => {
|
||||
try {
|
||||
if (provider?.id) {
|
||||
await updateRoleMappings(
|
||||
@@ -85,29 +87,31 @@ function RoleMappings({ provider, providerLoading }) {
|
||||
remoteRoleName,
|
||||
})),
|
||||
);
|
||||
|
||||
enqueueSnackbar(formatMessage('roleMappingsForm.successfullySaved'), {
|
||||
variant: 'success',
|
||||
SnackbarProps: {
|
||||
'data-test': 'snackbar-update-role-mappings-success',
|
||||
},
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
const errors = Object.values(
|
||||
error.response.data.errors || [['Failed while saving!']],
|
||||
);
|
||||
|
||||
for (const [error] of errors) {
|
||||
enqueueSnackbar(error, {
|
||||
variant: 'error',
|
||||
SnackbarProps: {
|
||||
'data-test': 'snackbar-update-role-mappings-error',
|
||||
},
|
||||
const errors = error?.response?.data?.errors;
|
||||
if (errors) {
|
||||
Object.entries(errors).forEach(([fieldName, fieldErrors]) => {
|
||||
if (fieldNames.includes(fieldName) && Array.isArray(fieldErrors)) {
|
||||
setError(`root.${fieldName}`, {
|
||||
type: 'fieldRequestError',
|
||||
message: `${fieldName}: ${fieldErrors.join(', ')}`,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
throw new Error('Failed while saving!');
|
||||
const generalError = getGeneralErrorMessage({
|
||||
error,
|
||||
fallbackMessage: formatMessage('roleMappingsForm.error'),
|
||||
});
|
||||
|
||||
if (generalError) {
|
||||
setError('root.general', {
|
||||
type: 'requestError',
|
||||
message: generalError,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -118,6 +122,17 @@ function RoleMappings({ provider, providerLoading }) {
|
||||
[roleMappings],
|
||||
);
|
||||
|
||||
const renderErrors = (errors) => {
|
||||
const rootErrors = errors?.root;
|
||||
if (rootErrors) {
|
||||
return Object.values(rootErrors).map((error, index) => (
|
||||
<Alert key={index} data-test="error-alert" severity="error">
|
||||
{error.message}
|
||||
</Alert>
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
if (
|
||||
providerLoading ||
|
||||
!provider?.id ||
|
||||
@@ -140,27 +155,35 @@ function RoleMappings({ provider, providerLoading }) {
|
||||
reValidateMode="onChange"
|
||||
noValidate
|
||||
automaticValidation={false}
|
||||
>
|
||||
<Stack direction="column" spacing={2}>
|
||||
<RoleMappingsFieldArray />
|
||||
<LoadingButton
|
||||
type="submit"
|
||||
variant="contained"
|
||||
color="primary"
|
||||
sx={{ boxShadow: 2 }}
|
||||
loading={isUpdateRoleMappingsPending}
|
||||
>
|
||||
{formatMessage('roleMappingsForm.save')}
|
||||
</LoadingButton>
|
||||
</Stack>
|
||||
</Form>
|
||||
render={({ formState: { errors, isDirty } }) => (
|
||||
<Stack direction="column" spacing={2}>
|
||||
<RoleMappingsFieldArray />
|
||||
{renderErrors(errors)}
|
||||
{isUpdateRoleMappingsSuccess && !isDirty && (
|
||||
<Alert data-test="success-alert" severity="success">
|
||||
{formatMessage('roleMappingsForm.successfullySaved')}
|
||||
</Alert>
|
||||
)}
|
||||
<LoadingButton
|
||||
type="submit"
|
||||
variant="contained"
|
||||
color="primary"
|
||||
sx={{ boxShadow: 2 }}
|
||||
loading={isUpdateRoleMappingsPending}
|
||||
disabled={!isDirty}
|
||||
>
|
||||
{formatMessage('roleMappingsForm.save')}
|
||||
</LoadingButton>
|
||||
</Stack>
|
||||
)}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
RoleMappings.propTypes = {
|
||||
provider: PropTypes.shape({
|
||||
id: PropTypes.oneOf([PropTypes.number, PropTypes.string]).isRequired,
|
||||
id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
|
||||
}),
|
||||
providerLoading: PropTypes.bool,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user