Changeset View
Changeset View
Standalone View
Standalone View
web/modals/threads/members/change-member-role-modal.react.js
// @flow | // @flow | ||||
import invariant from 'invariant'; | import invariant from 'invariant'; | ||||
import * as React from 'react'; | import * as React from 'react'; | ||||
import { | import { | ||||
changeThreadMemberRoles, | changeThreadMemberRoles, | ||||
changeThreadMemberRolesActionTypes, | changeThreadMemberRolesActionTypes, | ||||
} from 'lib/actions/thread-actions.js'; | } from 'lib/actions/thread-actions.js'; | ||||
import { useModalContext } from 'lib/components/modal-provider.react.js'; | import { useModalContext } from 'lib/components/modal-provider.react.js'; | ||||
import SWMansionIcon from 'lib/components/SWMansionIcon.react.js'; | |||||
import { otherUsersButNoOtherAdmins } from 'lib/selectors/thread-selectors.js'; | |||||
import { roleIsAdminRole } from 'lib/shared/thread-utils.js'; | |||||
import type { RelativeMemberInfo, ThreadInfo } from 'lib/types/thread-types'; | import type { RelativeMemberInfo, ThreadInfo } from 'lib/types/thread-types'; | ||||
import { | import { | ||||
useDispatchActionPromise, | useDispatchActionPromise, | ||||
useServerCall, | useServerCall, | ||||
} from 'lib/utils/action-utils.js'; | } from 'lib/utils/action-utils.js'; | ||||
import { values } from 'lib/utils/objects.js'; | import { values } from 'lib/utils/objects.js'; | ||||
import css from './change-member-role-modal.css'; | import css from './change-member-role-modal.css'; | ||||
import UserAvatar from '../../../avatars/user-avatar.react.js'; | import UserAvatar from '../../../avatars/user-avatar.react.js'; | ||||
import Button, { buttonThemes } from '../../../components/button.react.js'; | import Button, { buttonThemes } from '../../../components/button.react.js'; | ||||
import Dropdown from '../../../components/dropdown.react.js'; | import Dropdown from '../../../components/dropdown.react.js'; | ||||
import { useSelector } from '../../../redux/redux-utils.js'; | |||||
import Modal from '../../modal.react.js'; | import Modal from '../../modal.react.js'; | ||||
import UnsavedChangesModal from '../../unsaved-changes-modal.react.js'; | import UnsavedChangesModal from '../../unsaved-changes-modal.react.js'; | ||||
type ChangeMemberRoleModalProps = { | type ChangeMemberRoleModalProps = { | ||||
+memberInfo: RelativeMemberInfo, | +memberInfo: RelativeMemberInfo, | ||||
+threadInfo: ThreadInfo, | +threadInfo: ThreadInfo, | ||||
}; | }; | ||||
function ChangeMemberRoleModal(props: ChangeMemberRoleModalProps): React.Node { | function ChangeMemberRoleModal(props: ChangeMemberRoleModalProps): React.Node { | ||||
const { memberInfo, threadInfo } = props; | const { memberInfo, threadInfo } = props; | ||||
const { pushModal, popModal } = useModalContext(); | const { pushModal, popModal } = useModalContext(); | ||||
const dispatchActionPromise = useDispatchActionPromise(); | const dispatchActionPromise = useDispatchActionPromise(); | ||||
const callChangeThreadMemberRoles = useServerCall(changeThreadMemberRoles); | const callChangeThreadMemberRoles = useServerCall(changeThreadMemberRoles); | ||||
const otherUsersButNoOtherAdminsValue = useSelector( | |||||
otherUsersButNoOtherAdmins(threadInfo.id), | |||||
); | |||||
const roleOptions = React.useMemo( | const roleOptions = React.useMemo( | ||||
() => | () => | ||||
values(threadInfo.roles).map(role => ({ | values(threadInfo.roles).map(role => ({ | ||||
id: role.id, | id: role.id, | ||||
name: role.name, | name: role.name, | ||||
})), | })), | ||||
[threadInfo.roles], | [threadInfo.roles], | ||||
); | ); | ||||
const initialSelectedRole = memberInfo.role; | const initialSelectedRole = memberInfo.role; | ||||
invariant(initialSelectedRole, "Member's role must be defined"); | invariant(initialSelectedRole, "Member's role must be defined"); | ||||
const [selectedRole, setSelectedRole] = React.useState(initialSelectedRole); | const [selectedRole, setSelectedRole] = React.useState(initialSelectedRole); | ||||
const onBackClick = React.useCallback(() => { | const onBackClick = React.useCallback(() => { | ||||
if (selectedRole === initialSelectedRole) { | if (selectedRole === initialSelectedRole) { | ||||
popModal(); | popModal(); | ||||
return; | return; | ||||
} | } | ||||
pushModal(<UnsavedChangesModal />); | pushModal(<UnsavedChangesModal />); | ||||
}, [initialSelectedRole, popModal, pushModal, selectedRole]); | }, [initialSelectedRole, popModal, pushModal, selectedRole]); | ||||
const disabledRoleChangeMessage = React.useMemo(() => { | |||||
const memberIsAdmin = roleIsAdminRole( | |||||
threadInfo.roles[initialSelectedRole], | |||||
); | |||||
if (!otherUsersButNoOtherAdminsValue || !memberIsAdmin) { | |||||
return null; | |||||
} | |||||
return ( | |||||
<> | |||||
ashoat: This `<>` doesn't appear to be doing anything | |||||
<div className={css.roleModalDisabled}> | |||||
<SWMansionIcon | |||||
icon="info-circle" | |||||
size={36} | |||||
className={css.infoIcon} | |||||
/> | |||||
<div className={css.infoText}> | |||||
There must be at least one admin at any given time in a community. | |||||
</div> | |||||
</div> | |||||
</> | |||||
); | |||||
}, [initialSelectedRole, otherUsersButNoOtherAdminsValue, threadInfo.roles]); | |||||
const onSave = React.useCallback(() => { | const onSave = React.useCallback(() => { | ||||
if (selectedRole === initialSelectedRole) { | if (selectedRole === initialSelectedRole) { | ||||
popModal(); | popModal(); | ||||
return; | return; | ||||
} | } | ||||
const createChangeThreadMemberRolesPromise = () => { | const createChangeThreadMemberRolesPromise = () => { | ||||
return callChangeThreadMemberRoles( | return callChangeThreadMemberRoles( | ||||
Show All 30 Lines | <Modal name="Change Role" onClose={popModal} size="large"> | ||||
</div> | </div> | ||||
<div className={css.roleModalMemberName}>{memberInfo.username}</div> | <div className={css.roleModalMemberName}>{memberInfo.username}</div> | ||||
</div> | </div> | ||||
<div className={css.roleModalRoleSelector}> | <div className={css.roleModalRoleSelector}> | ||||
<Dropdown | <Dropdown | ||||
options={roleOptions} | options={roleOptions} | ||||
activeSelection={selectedRole} | activeSelection={selectedRole} | ||||
setActiveSelection={setSelectedRole} | setActiveSelection={setSelectedRole} | ||||
disabled={!!disabledRoleChangeMessage} | |||||
/> | /> | ||||
</div> | </div> | ||||
{disabledRoleChangeMessage} | |||||
<div className={css.roleModalActionButtons}> | <div className={css.roleModalActionButtons}> | ||||
<Button | <Button | ||||
variant="outline" | variant="outline" | ||||
className={css.roleModalBackButton} | className={css.roleModalBackButton} | ||||
onClick={onBackClick} | onClick={onBackClick} | ||||
> | > | ||||
Back | Back | ||||
</Button> | </Button> | ||||
<Button | <Button | ||||
variant="filled" | variant="filled" | ||||
className={css.roleModalSaveButton} | className={css.roleModalSaveButton} | ||||
buttonColor={buttonThemes.primary} | buttonColor={buttonThemes.primary} | ||||
onClick={onSave} | onClick={onSave} | ||||
disabled={!!disabledRoleChangeMessage} | |||||
> | > | ||||
Save | Save | ||||
</Button> | </Button> | ||||
</div> | </div> | ||||
</Modal> | </Modal> | ||||
); | ); | ||||
} | } | ||||
export default ChangeMemberRoleModal; | export default ChangeMemberRoleModal; |
This <> doesn't appear to be doing anything