diff --git a/web/roles/create-roles-modal.react.js b/web/roles/create-roles-modal.react.js index 6c9fcc7d5..70fe61dda 100644 --- a/web/roles/create-roles-modal.react.js +++ b/web/roles/create-roles-modal.react.js @@ -1,231 +1,258 @@ // @flow import classNames from 'classnames'; import invariant from 'invariant'; import * as React from 'react'; import { modifyCommunityRole, modifyCommunityRoleActionTypes, } from 'lib/actions/thread-actions.js'; import { useModalContext } from 'lib/components/modal-provider.react.js'; import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js'; import type { LoadingStatus } from 'lib/types/loading-types.js'; import type { UserSurfacedPermission, UserSurfacedPermissionOption, } from 'lib/types/thread-permission-types.js'; import type { ThreadInfo, RoleModificationRequest, } from 'lib/types/thread-types.js'; import { useServerCall, useDispatchActionPromise, } from 'lib/utils/action-utils.js'; import { useFilterPermissionOptionsByThreadType } from 'lib/utils/role-utils.js'; import css from './create-roles-modal.css'; import Button, { buttonThemes } from '../components/button.react.js'; import EnumSettingsOption from '../components/enum-settings-option.react.js'; import LoadingIndicator from '../loading-indicator.react.js'; import Input from '../modals/input.react.js'; import Modal from '../modals/modal.react.js'; +import UnsavedChangesModal from '../modals/unsaved-changes-modal.react.js'; import { useSelector } from '../redux/redux-utils.js'; const createRolesLoadingStatusSelector = createLoadingStatusSelector( modifyCommunityRoleActionTypes, ); type CreateRolesModalProps = { +threadInfo: ThreadInfo, +action: 'create_role' | 'edit_role', +existingRoleID?: string, +roleName: string, +rolePermissions: $ReadOnlySet, }; function CreateRolesModal(props: CreateRolesModalProps): React.Node { - const { popModal } = useModalContext(); + const { pushModal, popModal } = useModalContext(); const { threadInfo, action, existingRoleID, roleName, rolePermissions } = props; const callModifyCommunityRole = useServerCall(modifyCommunityRole); const dispatchActionPromise = useDispatchActionPromise(); const createRolesLoadingStatus: LoadingStatus = useSelector( createRolesLoadingStatusSelector, ); const [pendingRoleName, setPendingRoleName] = React.useState(roleName); const [pendingRolePermissions, setPendingRolePermissions] = React.useState<$ReadOnlySet>(rolePermissions); const onChangeRoleName = React.useCallback( (event: SyntheticEvent) => { setPendingRoleName(event.currentTarget.value); }, [], ); const onCloseModal = React.useCallback(() => { - popModal(); - }, [popModal]); + const pendingSet = new Set(pendingRolePermissions); + const roleSet = new Set(rolePermissions); + + let arePermissionsEqual = true; + if (pendingSet.size !== roleSet.size) { + arePermissionsEqual = false; + } + for (const permission of pendingSet) { + if (!roleSet.has(permission)) { + arePermissionsEqual = false; + break; + } + } + + if (pendingRoleName === roleName && arePermissionsEqual) { + popModal(); + return; + } + + pushModal(); + }, [ + pendingRoleName, + roleName, + pendingRolePermissions, + rolePermissions, + pushModal, + popModal, + ]); const clearPermissionsClassNames = classNames({ [css.clearPermissions]: true, [css.clearPermissionsDisabled]: pendingRolePermissions.size === 0, [css.clearPermissionsEnabled]: pendingRolePermissions.size > 0, }); const onClearPermissions = React.useCallback( () => setPendingRolePermissions(new Set()), [], ); const isUserSurfacedPermissionSelected = React.useCallback( (option: UserSurfacedPermissionOption) => pendingRolePermissions.has(option.userSurfacedPermission), [pendingRolePermissions], ); const onEnumValuePress = React.useCallback( (option: UserSurfacedPermissionOption) => setPendingRolePermissions(currentPermissions => { if (currentPermissions.has(option.userSurfacedPermission)) { const newPermissions = new Set(currentPermissions); newPermissions.delete(option.userSurfacedPermission); return newPermissions; } else { return new Set([ ...currentPermissions, option.userSurfacedPermission, ]); } }), [], ); const filteredUserSurfacedPermissionOptions = useFilterPermissionOptionsByThreadType(threadInfo.type); const permissionsList = React.useMemo( () => [...filteredUserSurfacedPermissionOptions].map(permission => ( onEnumValuePress(permission)} icon={null} title={permission.title} type="checkbox" statements={[{ statement: permission.description }]} /> )), [ filteredUserSurfacedPermissionOptions, isUserSurfacedPermissionSelected, onEnumValuePress, ], ); const onClickCreateRole = React.useCallback(() => { // TODO: Error handling in a later diff let callModifyCommunityRoleParams: RoleModificationRequest; if (action === 'create_role') { callModifyCommunityRoleParams = { community: threadInfo.id, action, name: pendingRoleName, permissions: [...pendingRolePermissions], }; } else { invariant(existingRoleID, 'existingRoleID should be defined'); callModifyCommunityRoleParams = { community: threadInfo.id, existingRoleID, action, name: pendingRoleName, permissions: [...pendingRolePermissions], }; } dispatchActionPromise( modifyCommunityRoleActionTypes, (async () => { const response = await callModifyCommunityRole( callModifyCommunityRoleParams, ); popModal(); return response; })(), ); }, [ callModifyCommunityRole, dispatchActionPromise, threadInfo, action, existingRoleID, pendingRoleName, pendingRolePermissions, popModal, ]); const saveButtonContent = React.useMemo(() => { if (createRolesLoadingStatus === 'loading') { return ( ); } return 'Save'; }, [createRolesLoadingStatus]); return (
Role Name

Permissions
Clear Permissions
{permissionsList}
); } export default CreateRolesModal;