From b961fa05d97be5849a9a8969f8257005b25a0511 Mon Sep 17 00:00:00 2001 From: Gerzon Z Date: Thu, 6 May 2021 08:57:53 -0400 Subject: [PATCH] Added addTeamMember and removeTeamMember --- app/i18n/locales/en.json | 6 +- app/lib/methods/getPermissions.js | 2 + app/lib/rocketchat.js | 10 ++ app/views/RoomActionsView/index.js | 46 +++++++- app/views/RoomMembersView/index.js | 166 ++++++++++++++++++++++------- app/views/RoomView/index.js | 2 +- app/views/SelectListView.js | 20 ++++ 7 files changed, 207 insertions(+), 45 deletions(-) diff --git a/app/i18n/locales/en.json b/app/i18n/locales/en.json index 46e15db18..ea20c91e7 100644 --- a/app/i18n/locales/en.json +++ b/app/i18n/locales/en.json @@ -733,5 +733,9 @@ "Select_Teams": "Select the Team's channels you would like to leave.", "Cannot_leave": "Cannot leave", "Last_owner_team_room": "You are the last owner of this channel. Once you leave the team, the channel will be kept inside the team but you will be managing it from outside.", - "last-owner-can-not-be-removed": "Last owner cannot be removed" + "last-owner-can-not-be-removed": "Last owner cannot be removed", + "Removing_user_from_this_Team": "You are removing {{user}} from this Team", + "Remove_User_Teams": "Select channels you want the user to be removed from.", + "Remove_Member": "Remove Member", + "Error": "Error" } diff --git a/app/lib/methods/getPermissions.js b/app/lib/methods/getPermissions.js index 1f4bcb9cb..8a837e4b1 100644 --- a/app/lib/methods/getPermissions.js +++ b/app/lib/methods/getPermissions.js @@ -13,6 +13,7 @@ const PERMISSIONS = [ 'add-user-to-any-c-room', 'add-user-to-any-p-room', 'add-user-to-joined-room', + 'add-team-member', 'add-team-channel', 'archive-room', 'auto-translate', @@ -22,6 +23,7 @@ const PERMISSIONS = [ 'delete-p', 'edit-message', 'edit-room', + 'edit-team-member', 'edit-team-channel', 'force-delete-message', 'mute-user', diff --git a/app/lib/rocketchat.js b/app/lib/rocketchat.js index 965b5be08..5478c6b22 100644 --- a/app/lib/rocketchat.js +++ b/app/lib/rocketchat.js @@ -762,6 +762,16 @@ const RocketChat = { // RC 3.13.0 return this.post('teams.leave', { teamName }); }, + addTeamMember(teamName) { + const { users } = reduxStore.getState().selectedUsers; + const members = users.map(u => ({ userId: u._id, roles: ['member'] })); + // RC 3.13.0 + return this.post('teams.addMembers', { teamName, members }); + }, + removeTeamMember({ teamName, userId }) { + // RC 3.13.0 + return this.post('teams.removeMember', { teamName, userId }); + }, joinRoom(roomId, joinCode, type) { // TODO: join code // RC 0.48.0 diff --git a/app/views/RoomActionsView/index.js b/app/views/RoomActionsView/index.js index c091e8895..b0c12a2bd 100644 --- a/app/views/RoomActionsView/index.js +++ b/app/views/RoomActionsView/index.js @@ -61,7 +61,8 @@ class RoomActionsView extends React.Component { editRoomPermission: PropTypes.array, toggleRoomE2EEncryptionPermission: PropTypes.array, viewBroadcastMemberListPermission: PropTypes.array, - transferLivechatGuestPermission: PropTypes.array + transferLivechatGuestPermission: PropTypes.array, + addTeamMemberPermission: PropTypes.array } constructor(props) { @@ -171,12 +172,19 @@ class RoomActionsView extends React.Component { canAddUser = async() => { const { room, joined } = this.state; - const { addUserToJoinedRoomPermission, addUserToAnyCRoomPermission, addUserToAnyPRoomPermission } = this.props; + const { + addUserToJoinedRoomPermission, addUserToAnyCRoomPermission, addUserToAnyPRoomPermission, addTeamMemberPermission + } = this.props; const { rid, t } = room; let canAddUser = false; + let permissions; const userInRoom = joined; - const permissions = await RocketChat.hasPermission([addUserToJoinedRoomPermission, addUserToAnyCRoomPermission, addUserToAnyPRoomPermission], rid); + if (room.teamMain) { + permissions = await RocketChat.hasPermission([addTeamMemberPermission], rid); + } else { + permissions = await RocketChat.hasPermission([addUserToJoinedRoomPermission, addUserToAnyCRoomPermission, addUserToAnyPRoomPermission], rid); + } if (userInRoom && permissions[0]) { canAddUser = true; @@ -321,6 +329,31 @@ class RoomActionsView extends React.Component { setLoadingInvite(true); await RocketChat.addUsersToRoom(rid); navigation.pop(); + } catch (e) { + log(e); + Alert.alert( + I18n.t('Confirmation'), + I18n.t('Removing_user_from_this_Team'), + [ + { + text: I18n.t('OK'), + style: 'cancel' + } + ], + { cancelable: false } + ); + } finally { + setLoadingInvite(false); + } + } + + addMemberToTeam = async() => { + const { room } = this.state; + const { setLoadingInvite, navigation } = this.props; + try { + setLoadingInvite(true); + await RocketChat.addTeamMember(room.name); + navigation.pop(); } catch (e) { log(e); } finally { @@ -438,7 +471,9 @@ class RoomActionsView extends React.Component { ); if (teamChannels) { - navigation.navigate('SelectListView', { title: 'Leave_Team', teamChannels, teamName: room.name }); + navigation.navigate('SelectListView', { + title: 'Leave_Team', teamChannels, teamName: room.name, subtitle: 'Select_Teams' + }); } else { Alert.alert( I18n.t('Confirmation'), @@ -678,7 +713,7 @@ class RoomActionsView extends React.Component { params: { rid, title: I18n.t('Add_users'), - nextAction: this.addUser + nextAction: room.teamId ? this.addMemberToTeam : this.addUser } })} testID='room-actions-add-user' @@ -930,6 +965,7 @@ const mapStateToProps = state => ({ encryptionEnabled: state.encryption.enabled, serverVersion: state.server.version, addUserToJoinedRoomPermission: state.permissions['add-user-to-joined-room'], + addTeamMemberPermission: state.permissions['add-team-member'], addUserToAnyCRoomPermission: state.permissions['add-user-to-any-c-room'], addUserToAnyPRoomPermission: state.permissions['add-user-to-any-p-room'], createInviteLinksPermission: state.permissions['create-invite-links'], diff --git a/app/views/RoomMembersView/index.js b/app/views/RoomMembersView/index.js index 9a47b60f7..c6b74a9f9 100644 --- a/app/views/RoomMembersView/index.js +++ b/app/views/RoomMembersView/index.js @@ -1,6 +1,6 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { FlatList } from 'react-native'; +import { FlatList, Alert } from 'react-native'; import { connect } from 'react-redux'; import { Q } from '@nozbe/watermelondb'; import * as List from '../../containers/List'; @@ -34,6 +34,7 @@ const PERMISSION_SET_LEADER = 'set-leader'; const PERMISSION_SET_OWNER = 'set-owner'; const PERMISSION_SET_MODERATOR = 'set-moderator'; const PERMISSION_REMOVE_USER = 'remove-user'; +const PERMISSION_EDIT_TEAM_MEMBER = 'edit-team-member'; class RoomMembersView extends React.Component { static propTypes = { @@ -55,7 +56,8 @@ class RoomMembersView extends React.Component { setLeaderPermission: PropTypes.array, setOwnerPermission: PropTypes.array, setModeratorPermission: PropTypes.array, - removeUserPermission: PropTypes.array + removeUserPermission: PropTypes.array, + editTeamMemberPermission: PropTypes.array } constructor(props) { @@ -94,18 +96,44 @@ class RoomMembersView extends React.Component { const { room } = this.state; const { - muteUserPermission, setLeaderPermission, setOwnerPermission, setModeratorPermission, removeUserPermission + muteUserPermission, setLeaderPermission, setOwnerPermission, setModeratorPermission, removeUserPermission, editTeamMemberPermission } = this.props; - const result = await RocketChat.hasPermission([ - muteUserPermission, setLeaderPermission, setOwnerPermission, setModeratorPermission, removeUserPermission - ], room.rid); + let result; + + if (room.teamId) { + result = await RocketChat.hasPermission([ + muteUserPermission, setLeaderPermission, setOwnerPermission, setModeratorPermission, removeUserPermission, editTeamMemberPermission + ], room.rid); + + this.permissions = { + [PERMISSION_MUTE_USER]: result[0], + [PERMISSION_SET_LEADER]: result[1], + [PERMISSION_SET_OWNER]: result[2], + [PERMISSION_SET_MODERATOR]: result[3], + [PERMISSION_REMOVE_USER]: result[4], + [PERMISSION_EDIT_TEAM_MEMBER]: result[5] + }; + } else { + result = await RocketChat.hasPermission([ + muteUserPermission, setLeaderPermission, setOwnerPermission, setModeratorPermission, removeUserPermission + ], room.rid); + + this.permissions = { + [PERMISSION_MUTE_USER]: result[0], + [PERMISSION_SET_LEADER]: result[1], + [PERMISSION_SET_OWNER]: result[2], + [PERMISSION_SET_MODERATOR]: result[3], + [PERMISSION_REMOVE_USER]: result[4] + }; + } this.permissions = { [PERMISSION_MUTE_USER]: result[0], [PERMISSION_SET_LEADER]: result[1], [PERMISSION_SET_OWNER]: result[2], [PERMISSION_SET_MODERATOR]: result[3], - [PERMISSION_REMOVE_USER]: result[4] + [PERMISSION_REMOVE_USER]: result[4], + [PERMISSION_EDIT_TEAM_MEMBER]: result[5] }; const hasSinglePermission = Object.values(this.permissions).some(p => !!p); @@ -163,6 +191,56 @@ class RoomMembersView extends React.Component { } } + handleRemoveFromTeam = async(selectedUser) => { + const { navigation } = this.props; + const { room } = this.state; + const db = database.active; + const subCollection = db.get('subscriptions'); + const teamChannels = await subCollection.query( + Q.where('team_id', Q.eq(room.teamId)) + ); + if (teamChannels) { + navigation.navigate('SelectListView', { + title: 'Remove_Member', subtitle: 'Remove_User_Teams', teamChannels, selectedUser + }); + } else { + Alert.alert( + I18n.t('Confirmation'), + I18n.t('Removing_user_from_this_Team', { user: selectedUser.username }), + [ + { + text: I18n.t('Cancel'), + style: 'cancel' + }, + { + text: I18n.t('Yes_action_it', { action: I18n.t('remove') }), + style: 'destructive', + onPress: () => this.removeFromTeam(selectedUser) + } + ], + { cancelable: false } + ); + } + } + + removeFromTeam = async(selectedUser) => { + try { + const { members, membersFiltered, room } = this.state; + const userId = selectedUser._id; + const result = await RocketChat.removeTeamMember({ teamName: room.name, userId }); + if (result.success) { + const message = I18n.t('User_has_been_removed_from_s', { s: RocketChat.getRoomTitle(room) }); + EventEmitter.emit(LISTENER, { message }); + this.setState({ + members: members.filter(member => member._id !== userId), + membersFiltered: membersFiltered.filter(member => member._id !== userId) + }); + } + } catch (e) { + log(e); + } + } + onPressUser = (selectedUser) => { const { room } = this.state; const { showActionSheet, user } = this.props; @@ -173,6 +251,46 @@ class RoomMembersView extends React.Component { onPress: () => this.navToDirectMessage(selectedUser) }]; + // Ignore + if (selectedUser._id !== user.id) { + const { ignored } = room; + const isIgnored = ignored?.includes?.(selectedUser._id); + options.push({ + icon: 'ignore', + title: I18n.t(isIgnored ? 'Unignore' : 'Ignore'), + onPress: () => this.handleIgnore(selectedUser, !isIgnored) + }); + } + + if (this.permissions['mute-user']) { + const { muted = [] } = room; + const userIsMuted = muted.find?.(m => m === selectedUser.username); + selectedUser.muted = !!userIsMuted; + options.push({ + icon: userIsMuted ? 'audio' : 'audio-disabled', + title: I18n.t(userIsMuted ? 'Unmute' : 'Mute'), + onPress: () => { + showConfirmationAlert({ + message: I18n.t(`The_user_${ userIsMuted ? 'will' : 'wont' }_be_able_to_type_in_roomName`, { + roomName: RocketChat.getRoomTitle(room) + }), + confirmationText: I18n.t(userIsMuted ? 'Unmute' : 'Mute'), + onPress: () => this.handleMute(selectedUser) + }); + } + }); + } + + // Remove from team + if (this.permissions['edit-team-member']) { + options.push({ + icon: 'close', + danger: true, + title: I18n.t('Remove_from_Team'), + onPress: () => this.handleRemoveFromTeam(selectedUser) + }); + } + // Owner if (this.permissions['set-owner']) { const userRoleResult = this.roomRoles.find(r => r.u._id === selectedUser._id); @@ -206,36 +324,6 @@ class RoomMembersView extends React.Component { }); } - // Ignore - if (selectedUser._id !== user.id) { - const { ignored } = room; - const isIgnored = ignored?.includes?.(selectedUser._id); - options.push({ - icon: 'ignore', - title: I18n.t(isIgnored ? 'Unignore' : 'Ignore'), - onPress: () => this.handleIgnore(selectedUser, !isIgnored) - }); - } - - if (this.permissions['mute-user']) { - const { muted = [] } = room; - const userIsMuted = muted.find?.(m => m === selectedUser.username); - selectedUser.muted = !!userIsMuted; - options.push({ - icon: userIsMuted ? 'audio' : 'audio-disabled', - title: I18n.t(userIsMuted ? 'Unmute' : 'Mute'), - onPress: () => { - showConfirmationAlert({ - message: I18n.t(`The_user_${ userIsMuted ? 'will' : 'wont' }_be_able_to_type_in_roomName`, { - roomName: RocketChat.getRoomTitle(room) - }), - confirmationText: I18n.t(userIsMuted ? 'Unmute' : 'Mute'), - onPress: () => this.handleMute(selectedUser) - }); - } - }); - } - // Remove from room if (this.permissions['remove-user']) { options.push({ @@ -292,6 +380,7 @@ class RoomMembersView extends React.Component { this.setState({ isLoading: true }); try { const membersResult = await RocketChat.getRoomMembers(rid, allUsers, members.length, PAGE_SIZE); + console.log({ membersResult }); const newMembers = membersResult.records; this.setState({ members: members.concat(newMembers || []), @@ -477,7 +566,8 @@ const mapStateToProps = state => ({ setLeaderPermission: state.permissions[PERMISSION_SET_LEADER], setOwnerPermission: state.permissions[PERMISSION_SET_OWNER], setModeratorPermission: state.permissions[PERMISSION_SET_MODERATOR], - removeUserPermission: state.permissions[PERMISSION_REMOVE_USER] + removeUserPermission: state.permissions[PERMISSION_REMOVE_USER], + editTeamMemberPermission: state.permissions['edit-team-member'] }); export default connect(mapStateToProps)(withActionSheet(withTheme(RoomMembersView))); diff --git a/app/views/RoomView/index.js b/app/views/RoomView/index.js index d7bba1017..6ffc07e7f 100644 --- a/app/views/RoomView/index.js +++ b/app/views/RoomView/index.js @@ -1033,7 +1033,7 @@ class RoomView extends React.Component { renderActions = () => { const { room, readOnly } = this.state; const { user } = this.props; - console.log({ room }); + return ( <> { + try { + const { data, room } = this.state; + const userId = selectedUser._id; + const result = await RocketChat.removeTeamMember({ teamName: room.name, userId }); + if (result.success) { + const message = I18n.t('User_has_been_removed_from_s', { s: RocketChat.getRoomTitle(room) }); + EventEmitter.emit(LISTENER, { message }); + this.setState({ data: data.filter(member => member._id !== userId) }); + } + } catch (e) { + log(e); + } + } + renderChannel = ({ onPress, testID, title, icon, checked, alert }) => {