diff --git a/web/roles/create-roles-modal.css b/web/roles/create-roles-modal.css --- a/web/roles/create-roles-modal.css +++ b/web/roles/create-roles-modal.css @@ -16,6 +16,17 @@ margin: 8px 0 12px 0; } +.errorMessage { + color: var(--error); + font-size: var(--s-font-14); + align-self: center; + visibility: hidden; +} + +.errorMessageVisible { + visibility: visible; +} + .separator { border: 0; margin: 16px 32px 8px 32px; diff --git a/web/roles/create-roles-modal.react.js b/web/roles/create-roles-modal.react.js --- a/web/roles/create-roles-modal.react.js +++ b/web/roles/create-roles-modal.react.js @@ -16,6 +16,7 @@ useServerCall, useDispatchActionPromise, } from 'lib/utils/action-utils.js'; +import { values } from 'lib/utils/objects.js'; import css from './create-roles-modal.css'; import { @@ -42,6 +43,8 @@ +rolePermissions: $ReadOnlyArray, }; +type RoleCreationErrorVariant = 'already_exists' | 'unknown_error'; + function CreateRolesModal(props: CreateRolesModalProps): React.Node { const { pushModal, popModal } = useModalContext(); const { threadInfo, action, existingRoleID, roleName, rolePermissions } = @@ -59,8 +62,12 @@ const [pendingRolePermissions, setPendingRolePermissions] = React.useState<$ReadOnlyArray>(rolePermissions); + const [roleCreationFailed, setRoleCreationFailed] = + React.useState(); + const onChangeRoleName = React.useCallback( (event: SyntheticEvent) => { + setRoleCreationFailed(null); setPendingRoleName(event.currentTarget.value); }, [], @@ -152,13 +159,21 @@ ], ); + const errorMessageClassNames = classNames({ + [css.errorMessage]: true, + [css.errorMessageVisible]: !!roleCreationFailed, + }); + const onClickCreateRole = React.useCallback(() => { - // TODO: Error handling in a later diff + const threadRoleNames = values(threadInfo.roles).map(role => role.name); + if (threadRoleNames.includes(pendingRoleName) && action === 'create_role') { + setRoleCreationFailed('already_exists'); + return; + } dispatchActionPromise( modifyCommunityRoleActionTypes, (async () => { - //eslint-disable-next-line no-useless-catch try { const response = await callModifyCommunityRole({ community: threadInfo.id, @@ -170,6 +185,7 @@ popModal(); return response; } catch (e) { + setRoleCreationFailed('unknown_error'); throw e; } })(), @@ -185,6 +201,16 @@ popModal, ]); + const errorMessage = React.useMemo(() => { + if (roleCreationFailed === 'already_exists') { + return 'There is already a role with this name in the community'; + } else if (roleCreationFailed === 'unknown_error') { + return 'An unknown error occurred. Please try again'; + } else { + return 'An unknown error occurred. Please try again'; + } + }, [roleCreationFailed]); + const saveButtonContent = React.useMemo(() => { if (createRolesLoadingStatus === 'loading') { return ( @@ -206,6 +232,7 @@ onChange={onChangeRoleName} /> +
{errorMessage}