Skip to content

Commit

Permalink
[web] Create the modals that will allow the user to confirm role dele…
Browse files Browse the repository at this point in the history
…tion

Summary:
This should be the final stack in the entire roles project. This is the client-side logic for `web` to handle role deletion. Per the designs, the warning message is the same as on `native`, with
either a generic deletion message if nobody is assigned the role or a more specific one if members have this custom role.

[[ https://linear.app/comm/issue/ENG-4432/create-the-modals-that-will-allow-the-user-to-confirm-role-deletion | ENG-4432 ]]

Depends on D8624

Test Plan:
Verified that the modal appears as expected for roles with and without members, and pressing the delete button actually deletes

{F653374}

Reviewers: atul, ginsu

Reviewed By: atul

Subscribers: tomek, ashoat

Differential Revision: https://phab.comm.dev/D8625
  • Loading branch information
RohanK6 committed Aug 1, 2023
1 parent bdab982 commit f3684a7
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 1 deletion.
20 changes: 20 additions & 0 deletions web/roles/delete-role-modal.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
.roleDeletionText {
color: var(--modal-fg);
font-size: var(--m-font-14);
padding: 16px 32px;
}

.buttonsContainer {
display: flex;
flex-direction: row;
justify-content: flex-end;
padding: 16px 32px;
}

.cancelButton {
width: 100px;
}

.deleteRoleButton {
margin-left: 8px;
}
111 changes: 111 additions & 0 deletions web/roles/delete-role-modal.react.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// @flow

import * as React from 'react';

import {
deleteCommunityRole,
deleteCommunityRoleActionTypes,
} from 'lib/actions/thread-actions.js';
import { useModalContext } from 'lib/components/modal-provider.react.js';
import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js';
import { useRoleMemberCountsForCommunity } from 'lib/shared/thread-utils.js';
import type { LoadingStatus } from 'lib/types/loading-types.js';
import type { ThreadInfo } from 'lib/types/thread-types.js';
import {
useServerCall,
useDispatchActionPromise,
} from 'lib/utils/action-utils.js';
import { constructRoleDeletionMessagePrompt } from 'lib/utils/role-utils.js';

import css from './delete-role-modal.css';
import Button, { buttonThemes } from '../components/button.react.js';
import LoadingIndicator from '../loading-indicator.react.js';
import Modal from '../modals/modal.react.js';
import { useSelector } from '../redux/redux-utils.js';

const deleteRoleLoadingStatusSelector = createLoadingStatusSelector(
deleteCommunityRoleActionTypes,
);

type DeleteRoleModalProps = {
+threadInfo: ThreadInfo,
+defaultRoleID: string,
+roleID: string,
};

function DeleteRoleModal(props: DeleteRoleModalProps): React.Node {
const { threadInfo, defaultRoleID, roleID } = props;
const { popModal } = useModalContext();

const callDeleteCommunityRole = useServerCall(deleteCommunityRole);
const dispatchActionPromise = useDispatchActionPromise();

const deleteRoleLoadingStatus: LoadingStatus = useSelector(
deleteRoleLoadingStatusSelector,
);

const roleNamesToMemberCounts = useRoleMemberCountsForCommunity(threadInfo);
const roleName = threadInfo.roles[roleID].name;
const memberCount = roleNamesToMemberCounts[roleName];
const defaultRoleName = threadInfo.roles[defaultRoleID].name;

const message = constructRoleDeletionMessagePrompt(
defaultRoleName,
memberCount,
);

const onDeleteRole = React.useCallback(() => {
dispatchActionPromise(
deleteCommunityRoleActionTypes,
(async () => {
const response = await callDeleteCommunityRole({
community: threadInfo.id,
roleID: roleID,
});
popModal();
return response;
})(),
);
}, [
callDeleteCommunityRole,
dispatchActionPromise,
roleID,
threadInfo.id,
popModal,
]);

const deleteButtonContent = React.useMemo(() => {
if (deleteRoleLoadingStatus === 'loading') {
return (
<LoadingIndicator status={deleteRoleLoadingStatus} size="medium" />
);
}
return 'Yes, delete role';
}, [deleteRoleLoadingStatus]);

return (
<Modal name="Delete role" onClose={popModal} size="large">
<div className={css.roleDeletionText}>{message}</div>
<div className={css.buttonsContainer}>
<Button
variant="outline"
className={css.cancelButton}
buttonColor={buttonThemes.outline}
onClick={popModal}
>
Cancel
</Button>
<Button
variant="filled"
className={css.deleteRoleButton}
buttonColor={buttonThemes.danger}
onClick={onDeleteRole}
>
{deleteButtonContent}
</Button>
</div>
</Modal>
);
}

export default DeleteRoleModal;
11 changes: 10 additions & 1 deletion web/roles/role-actions-menu.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type { ThreadInfo } from 'lib/types/thread-types.js';
import { useRoleDeletableAndEditableStatus } from 'lib/utils/role-utils.js';

import CreateRolesModal from './create-roles-modal.react.js';
import DeleteRoleModal from './delete-role-modal.react.js';
import css from './role-actions-menu.css';
import MenuItem from '../components/menu-item.react.js';
import Menu from '../components/menu.react.js';
Expand Down Expand Up @@ -63,7 +64,15 @@ function RoleActionsMenu(props: RoleActionsMenuProps): React.Node {
threadInfo,
],
);
const openDeleteRoleModal = React.useCallback(() => {}, []);
const openDeleteRoleModal = React.useCallback(() => {
pushModal(
<DeleteRoleModal
threadInfo={threadInfo}
defaultRoleID={defaultRoleID}
roleID={existingRoleID}
/>,
);
}, [existingRoleID, pushModal, threadInfo, defaultRoleID]);

const menuItems = React.useMemo(() => {
const availableOptions = [];
Expand Down

0 comments on commit f3684a7

Please sign in to comment.