From e15ae2253a15c7951c31ce0a2f9eea188ba2b639 Mon Sep 17 00:00:00 2001 From: George Goldberg Date: Wed, 18 Jan 2017 20:54:49 +0000 Subject: PLT-5050 (WebApp): Change channel member roles. (#5076) Admins can now Promote/Demote channel members in the Channel Manage Membersmodal. --- webapp/actions/channel_actions.jsx | 72 ++++++++++++++++++++++++++ webapp/actions/user_actions.jsx | 35 ++----------- webapp/client/client.jsx | 15 ++++++ webapp/components/channel_members_dropdown.jsx | 68 +++++++++++++++++++++++- webapp/i18n/en.json | 2 + 5 files changed, 159 insertions(+), 33 deletions(-) diff --git a/webapp/actions/channel_actions.jsx b/webapp/actions/channel_actions.jsx index 40e0cde30..3e41a2310 100644 --- a/webapp/actions/channel_actions.jsx +++ b/webapp/actions/channel_actions.jsx @@ -125,6 +125,48 @@ export function removeUserFromChannel(channelId, userId, success, error) { ); } +export function makeUserChannelAdmin(channelId, userId, success, error) { + Client.updateChannelMemberRoles( + channelId, + userId, + 'channel_user channel_admin', + () => { + AsyncClient.getChannelMember(channelId, userId); + getChannelMembersForUserIds(channelId, [userId]); + + if (success) { + success(); + } + }, + (err) => { + if (error) { + error(err); + } + } + ); +} + +export function makeUserChannelMember(channelId, userId, success, error) { + Client.updateChannelMemberRoles( + channelId, + userId, + 'channel_user', + () => { + AsyncClient.getChannelMember(channelId, userId); + getChannelMembersForUserIds(channelId, [userId]); + + if (success) { + success(); + } + }, + (err) => { + if (error) { + error(err); + } + } + ); +} + export function openDirectChannelToUser(user, success, error) { const channelName = Utils.getDirectChannelName(UserStore.getCurrentId(), user.id); const channel = ChannelStore.getByName(channelName); @@ -343,3 +385,33 @@ export function updateChannelHeader(channelId, header, success, error) { } ); } + +export function getChannelMembersForUserIds(channelId, userIds, success, error) { + Client.getChannelMembersByIds( + channelId, + userIds, + (data) => { + const memberMap = {}; + for (let i = 0; i < data.length; i++) { + memberMap[data[i].user_id] = data[i]; + } + + AppDispatcher.handleServerAction({ + type: ActionTypes.RECEIVED_MEMBERS_IN_CHANNEL, + channel_id: channelId, + channel_members: memberMap + }); + + if (success) { + success(data); + } + }, + (err) => { + AsyncClient.dispatchError(err, 'getChannelMembersByIds'); + + if (error) { + error(err); + } + } + ); +} diff --git a/webapp/actions/user_actions.jsx b/webapp/actions/user_actions.jsx index f51b11692..76879b5f5 100644 --- a/webapp/actions/user_actions.jsx +++ b/webapp/actions/user_actions.jsx @@ -8,6 +8,7 @@ import TeamStore from 'stores/team_store.jsx'; import UserStore from 'stores/user_store.jsx'; import ChannelStore from 'stores/channel_store.jsx'; +import {getChannelMembersForUserIds} from 'actions/channel_actions.jsx'; import {loadStatusesForProfilesList, loadStatusesForProfilesMap} from 'actions/status_actions.jsx'; import {getDirectChannelName} from 'utils/utils.jsx'; @@ -180,7 +181,7 @@ export function loadChannelMembersForProfilesMap(profiles, channelId = ChannelSt return; } - loadChannelMembersForProfiles(list, channelId, success, error); + getChannelMembersForUserIds(channelId, list, success, error); } export function loadTeamMembersAndChannelMembersForProfilesList(profiles, teamId = TeamStore.getCurrentId(), channelId = ChannelStore.getCurrentId(), success, error) { @@ -207,37 +208,7 @@ export function loadChannelMembersForProfilesList(profiles, channelId = ChannelS return; } - loadChannelMembersForProfiles(list, channelId, success, error); -} - -function loadChannelMembersForProfiles(userIds, channelId, success, error) { - Client.getChannelMembersByIds( - channelId, - userIds, - (data) => { - const memberMap = {}; - for (let i = 0; i < data.length; i++) { - memberMap[data[i].user_id] = data[i]; - } - - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_MEMBERS_IN_CHANNEL, - channel_id: channelId, - channel_members: memberMap - }); - - if (success) { - success(data); - } - }, - (err) => { - AsyncClient.dispatchError(err, 'getChannelMembersByIds'); - - if (error) { - error(err); - } - } - ); + getChannelMembersForUserIds(channelId, list, success, error); } function populateDMChannelsWithProfiles(userIds) { diff --git a/webapp/client/client.jsx b/webapp/client/client.jsx index 5104f34e2..639f2da2e 100644 --- a/webapp/client/client.jsx +++ b/webapp/client/client.jsx @@ -1530,6 +1530,21 @@ export default class Client { this.track('api', 'api_channels_remove_member'); } + updateChannelMemberRoles(channelId, userId, newRoles, success, error) { + var data = { + user_id: userId, + new_roles: newRoles + }; + + request. + post(`${this.getChannelNeededRoute(channelId)}/update_member_roles`). + set(this.defaultHeaders). + type('application/json'). + accept('application/json'). + send(data). + end(this.handleResponse.bind(this, 'updateChannelMemberRoles', success, error)); + } + // Routes for Commands listCommands(success, error) { diff --git a/webapp/components/channel_members_dropdown.jsx b/webapp/components/channel_members_dropdown.jsx index 82aaf0612..a7b3259af 100644 --- a/webapp/components/channel_members_dropdown.jsx +++ b/webapp/components/channel_members_dropdown.jsx @@ -5,7 +5,7 @@ import ChannelStore from 'stores/channel_store.jsx'; import TeamStore from 'stores/team_store.jsx'; import UserStore from 'stores/user_store.jsx'; -import {removeUserFromChannel} from 'actions/channel_actions.jsx'; +import {removeUserFromChannel, makeUserChannelAdmin, makeUserChannelMember} from 'actions/channel_actions.jsx'; import * as AsyncClient from 'utils/async_client.jsx'; import * as Utils from 'utils/utils.jsx'; @@ -18,6 +18,8 @@ export default class ChannelMembersDropdown extends React.Component { super(props); this.handleRemoveFromChannel = this.handleRemoveFromChannel.bind(this); + this.handleMakeChannelMember = this.handleMakeChannelMember.bind(this); + this.handleMakeChannelAdmin = this.handleMakeChannelAdmin.bind(this); this.state = { serverError: null, @@ -39,6 +41,32 @@ export default class ChannelMembersDropdown extends React.Component { ); } + handleMakeChannelMember() { + makeUserChannelMember( + this.props.channel.id, + this.props.user.id, + () => { + AsyncClient.getChannelStats(this.props.channel.id); + }, + (err) => { + this.setState({serverError: err.message}); + } + ); + } + + handleMakeChannelAdmin() { + makeUserChannelAdmin( + this.props.channel.id, + this.props.user.id, + () => { + AsyncClient.getChannelStats(this.props.channel.id); + }, + (err) => { + this.setState({serverError: err.message}); + } + ); + } + // Checks if the user this menu is for is a channel admin or not. isChannelAdmin() { if (Utils.isChannelAdmin(this.props.channelMember.roles)) { @@ -116,6 +144,42 @@ export default class ChannelMembersDropdown extends React.Component { ); } + let makeChannelMember = null; + if (this.isChannelAdmin()) { + makeChannelMember = ( +
  • + + + +
  • + ); + } + + let makeChannelAdmin = null; + if (!this.isChannelAdmin()) { + makeChannelAdmin = ( +
  • + + + +
  • + ); + } + return (
    + {makeChannelMember} + {makeChannelAdmin} {removeFromChannel} {serverError} diff --git a/webapp/i18n/en.json b/webapp/i18n/en.json index f92516119..7961084da 100644 --- a/webapp/i18n/en.json +++ b/webapp/i18n/en.json @@ -1094,6 +1094,8 @@ "channel_loader.wrote": " wrote: ", "channel_members_dropdown.channel_admin": "Channel Admin", "channel_members_dropdown.channel_member": "Channel Member", + "channel_members_dropdown.make_channel_admin": "Make Channel Admin", + "channel_members_dropdown.make_channel_member": "Make Channel Member", "channel_members_dropdown.remove_from_channel": "Remove From Channel", "channel_members_dropdown.remove_member": "Remove Member", "channel_members_modal.addNew": " Add New Members", -- cgit v1.2.3-1-g7c22