Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F3394930
D8640.id29098.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
6 KB
Referenced Files
None
Subscribers
None
D8640.id29098.diff
View Options
diff --git a/lib/utils/role-utils.js b/lib/utils/role-utils.js
--- a/lib/utils/role-utils.js
+++ b/lib/utils/role-utils.js
@@ -35,4 +35,26 @@
}, [shouldFilterVoicedInAnnouncementChannel]);
}
-export { useFilterPermissionOptionsByThreadType };
+function constructRoleDeletionMessagePrompt(
+ defaultRoleName: string,
+ memberCount: number,
+): string {
+ let message;
+ if (memberCount === 0) {
+ message = 'Are you sure you want to delete this role?';
+ } else {
+ const messageNoun = memberCount === 1 ? 'member' : 'members';
+ const messageVerb = memberCount === 1 ? 'is' : 'are';
+ message =
+ `There ${messageVerb} currently ${memberCount} ${messageNoun} with ` +
+ `this role. Deleting the role will automatically assign the ` +
+ `${messageNoun} affected to the ${defaultRoleName} role.`;
+ }
+
+ return message;
+}
+
+export {
+ useFilterPermissionOptionsByThreadType,
+ constructRoleDeletionMessagePrompt,
+};
diff --git a/lib/utils/role-utils.test.js b/lib/utils/role-utils.test.js
new file mode 100644
--- /dev/null
+++ b/lib/utils/role-utils.test.js
@@ -0,0 +1,34 @@
+// @flow
+
+import { constructRoleDeletionMessagePrompt } from './role-utils.js';
+
+describe('constructRoleDeletionMessagePrompt', () => {
+ it('should return generic deletion message if no members have this role', () => {
+ const result = constructRoleDeletionMessagePrompt('defaultRole', 0);
+ expect(result).toBe('Are you sure you want to delete this role?');
+ });
+
+ it('should correctly format message for single member', () => {
+ const result = constructRoleDeletionMessagePrompt('defaultRole', 1);
+ expect(result).toBe(
+ `There is currently 1 member with this role. Deleting the role will ` +
+ `automatically assign the member affected to the defaultRole role.`,
+ );
+ });
+
+ it('should correctly format message for multiple members', () => {
+ const result = constructRoleDeletionMessagePrompt('defaultRole', 5);
+ expect(result).toBe(
+ `There are currently 5 members with this role. Deleting the role will ` +
+ `automatically assign the members affected to the defaultRole role.`,
+ );
+ });
+
+ it('should correctly incorporate the name of the default role', () => {
+ const result = constructRoleDeletionMessagePrompt('testRole', 5);
+ expect(result).toBe(
+ `There are currently 5 members with this role. Deleting the role will ` +
+ `automatically assign the members affected to the testRole role.`,
+ );
+ });
+});
diff --git a/native/roles/role-panel-entry.react.js b/native/roles/role-panel-entry.react.js
--- a/native/roles/role-panel-entry.react.js
+++ b/native/roles/role-panel-entry.react.js
@@ -9,6 +9,7 @@
import type { UserSurfacedPermission } from 'lib/types/thread-permission-types.js';
import type { ThreadInfo } from 'lib/types/thread-types.js';
+import { useDisplayDeleteRoleAlert } from './role-utils.react.js';
import type { RolesNavigationProp } from './roles-navigator.react.js';
import CommIcon from '../components/comm-icon.react.js';
import SWMansionIcon from '../components/swmansion-icon.react.js';
@@ -38,15 +39,33 @@
);
invariant(existingRoleID, 'Role ID must exist for an existing role');
+ const defaultRoleID = Object.keys(threadInfo.roles).find(
+ roleID => threadInfo.roles[roleID].isDefault,
+ );
+ invariant(defaultRoleID, 'Default role ID must exist');
+
+ const displayDeleteRoleAlert = useDisplayDeleteRoleAlert(
+ threadInfo,
+ existingRoleID,
+ defaultRoleID,
+ memberCount,
+ );
+
const options = React.useMemo(() => {
const availableOptions = ['Edit role'];
+ // Since the `Members` role is able to be renamed, we need to check if the
+ // default role ID is the same as the existing role ID.
+ if (defaultRoleID !== existingRoleID) {
+ availableOptions.push('Delete role');
+ }
+
if (Platform.OS === 'ios') {
availableOptions.push('Cancel');
}
return availableOptions;
- }, []);
+ }, [defaultRoleID, existingRoleID]);
const onOptionSelected = React.useCallback(
(index: ?number) => {
@@ -64,6 +83,8 @@
roleName,
rolePermissions,
});
+ } else if (selectedOption === 'Delete role') {
+ displayDeleteRoleAlert();
}
},
[
@@ -73,6 +94,7 @@
roleName,
rolePermissions,
threadInfo,
+ displayDeleteRoleAlert,
],
);
diff --git a/native/roles/role-utils.react.js b/native/roles/role-utils.react.js
new file mode 100644
--- /dev/null
+++ b/native/roles/role-utils.react.js
@@ -0,0 +1,64 @@
+// @flow
+
+import * as React from 'react';
+import { Alert } from 'react-native';
+
+import {
+ deleteCommunityRole,
+ deleteCommunityRoleActionTypes,
+} from 'lib/actions/thread-actions.js';
+import type { ThreadInfo } from 'lib/types/thread-types.js';
+import {
+ useDispatchActionPromise,
+ useServerCall,
+} from 'lib/utils/action-utils.js';
+import { constructRoleDeletionMessagePrompt } from 'lib/utils/role-utils.js';
+
+function useDisplayDeleteRoleAlert(
+ threadInfo: ThreadInfo,
+ existingRoleID: string,
+ defaultRoleID: string,
+ memberCount: number,
+): () => void {
+ const defaultRoleName = threadInfo.roles[defaultRoleID].name;
+ const callDeleteCommunityRole = useServerCall(deleteCommunityRole);
+ const dispatchActionPromise = useDispatchActionPromise();
+
+ const onDeleteRole = React.useCallback(() => {
+ dispatchActionPromise(
+ deleteCommunityRoleActionTypes,
+ callDeleteCommunityRole({
+ community: threadInfo.id,
+ roleID: existingRoleID,
+ }),
+ );
+ }, [
+ callDeleteCommunityRole,
+ dispatchActionPromise,
+ existingRoleID,
+ threadInfo.id,
+ ]);
+
+ const message = constructRoleDeletionMessagePrompt(
+ defaultRoleName,
+ memberCount,
+ );
+
+ return React.useCallback(
+ () =>
+ Alert.alert('Delete role', message, [
+ {
+ text: 'Yes, delete role',
+ style: 'destructive',
+ onPress: onDeleteRole,
+ },
+ {
+ text: 'Cancel',
+ style: 'cancel',
+ },
+ ]),
+ [message, onDeleteRole],
+ );
+}
+
+export { useDisplayDeleteRoleAlert };
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Dec 1, 11:47 PM (4 h, 7 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2606310
Default Alt Text
D8640.id29098.diff (6 KB)
Attached To
Mode
D8640: [native] Introduce client-side logic for deleting roles on native
Attached
Detach File
Event Timeline
Log In to Comment