Skip to content
This repository has been archived by the owner on Mar 13, 2024. It is now read-only.

Commit

Permalink
PLT-2863 adding remove user from team (#3429)
Browse files Browse the repository at this point in the history
* PLT-2863 adding remove user from team

* PLT-2863 adding the client side UI

* Fixing trailing space

* Fixing reported issues

* Adding documentatino

* Switching to final javascript driver
  • Loading branch information
coreyhulen committed Jul 6, 2016
1 parent a186fbd commit c7569d7
Show file tree
Hide file tree
Showing 14 changed files with 257 additions and 5 deletions.
7 changes: 7 additions & 0 deletions actions/global_actions.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,13 @@ export function showInviteMemberModal() {
});
}

export function showLeaveTeamModal() {
AppDispatcher.handleViewAction({
type: ActionTypes.TOGGLE_LEAVE_TEAM_MODAL,
value: true
});
}

export function showRegisterAppModal() {
AppDispatcher.handleViewAction({
type: ActionTypes.TOGGLE_REGISTER_APP_MODAL,
Expand Down
17 changes: 17 additions & 0 deletions actions/websocket_actions.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,10 @@ function handleMessage(msg) {
handleNewUserEvent();
break;

case SocketEvents.LEAVE_TEAM:
handleLeaveTeamEvent(msg);
break;

case SocketEvents.USER_ADDED:
handleUserAddedEvent(msg);
break;
Expand Down Expand Up @@ -219,6 +223,19 @@ function handleNewUserEvent() {
AsyncClient.getChannelExtraInfo();
}

function handleLeaveTeamEvent(msg) {
if (UserStore.getCurrentId() === msg.user_id) {
TeamStore.removeTeamMember(msg.team_id);

// if the are on the team begin removed redirect them to the root
if (TeamStore.getCurrentId() === msg.team_id) {
browserHistory.push('/');
}
} else if (TeamStore.getCurrentId() === msg.team_id) {
GlobalActions.emitProfilesForDmList();
}
}

function handleDirectAddedEvent(msg) {
AsyncClient.getChannel(msg.channel_id);
AsyncClient.getDirectProfiles();
Expand Down
4 changes: 4 additions & 0 deletions components/admin_console/team_users.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,10 @@ export default class UserList extends React.Component {
var memberList = this.state.users.map((user) => {
var teamMember = this.getTeamMemberForUser(user.id);

if (teamMember.delete_at > 0) {
return null;
}

return (
<UserItem
team={this.state.team}
Expand Down
35 changes: 34 additions & 1 deletion components/admin_console/user_item.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export default class UserItem extends React.Component {
super(props);

this.handleMakeMember = this.handleMakeMember.bind(this);
this.handleRemoveFromTeam = this.handleRemoveFromTeam.bind(this);
this.handleMakeActive = this.handleMakeActive.bind(this);
this.handleMakeNotActive = this.handleMakeNotActive.bind(this);
this.handleMakeAdmin = this.handleMakeAdmin.bind(this);
Expand Down Expand Up @@ -56,6 +57,19 @@ export default class UserItem extends React.Component {
}
}

handleRemoveFromTeam() {
Client.removeUserFromTeam(
this.props.team.id,
this.props.user.id,
() => {
this.props.refreshProfiles();
},
(err) => {
this.setState({serverError: err.message});
}
);
}

handleMakeActive(e) {
e.preventDefault();
Client.updateActive(this.props.user.id, true,
Expand Down Expand Up @@ -222,6 +236,7 @@ export default class UserItem extends React.Component {
);
}

const me = UserStore.getCurrentUser();
const email = user.email;
let showMakeMember = teamMember.roles === 'admin' || user.roles === 'system_admin';
let showMakeAdmin = teamMember.roles === '' && user.roles !== 'system_admin';
Expand Down Expand Up @@ -299,6 +314,24 @@ export default class UserItem extends React.Component {
);
}

let removeFromTeam = null;
if (this.props.user.id !== me.id) {
removeFromTeam = (
<li role='presentation'>
<a
role='menuitem'
href='#'
onClick={this.handleRemoveFromTeam}
>
<FormattedMessage
id='team_members_dropdown.leave_team'
defaultMessage='Remove From Team'
/>
</a>
</li>
);
}

let makeActive = null;
if (showMakeActive) {
makeActive = (
Expand Down Expand Up @@ -428,7 +461,6 @@ export default class UserItem extends React.Component {
passwordReset = null;
}

const me = UserStore.getCurrentUser();
let makeDemoteModal = null;
if (this.props.user.id === me.id) {
const title = (
Expand Down Expand Up @@ -511,6 +543,7 @@ export default class UserItem extends React.Component {
className='dropdown-menu member-menu'
role='menu'
>
{removeFromTeam}
{makeAdmin}
{makeMember}
{makeActive}
Expand Down
15 changes: 13 additions & 2 deletions components/filtered_user_list.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,24 @@ class FilteredUserList extends React.Component {
this.state = {
filter: '',
users: this.filterUsers(props.teamMembers, props.users),
selected: 'team'
selected: 'team',
teamMembers: props.teamMembers
};
}

componentWillUpdate(nextProps) {
componentWillReceiveProps(nextProps) {
// assume the user list is immutable
if (this.props.users !== nextProps.users) {
this.setState({
users: this.filterUsers(nextProps.teamMembers, nextProps.users)
});
}

if (this.props.teamMembers !== nextProps.teamMembers) {
this.setState({
users: this.filterUsers(nextProps.teamMembers, nextProps.users)
});
}
}

componentDidMount() {
Expand All @@ -70,6 +77,10 @@ class FilteredUserList extends React.Component {
var filteredUsers = users.filter((user) => {
for (const index in teamMembers) {
if (teamMembers.hasOwnProperty(index) && teamMembers[index].user_id === user.id) {
if (teamMembers[index].delete_at > 0) {
return false;
}

return true;
}
}
Expand Down
115 changes: 115 additions & 0 deletions components/leave_team_modal.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.

import Constants from 'utils/constants.jsx';
const ActionTypes = Constants.ActionTypes;
import * as GlobalActions from 'actions/global_actions.jsx';
import ModalStore from 'stores/modal_store.jsx';
import UserStore from 'stores/user_store.jsx';

import {intlShape, injectIntl, FormattedMessage} from 'react-intl';

import {Modal} from 'react-bootstrap';

import React from 'react';

class LeaveTeamModal extends React.Component {
constructor(props) {
super(props);

this.handleToggle = this.handleToggle.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.handleHide = this.handleHide.bind(this);

this.state = {
show: false
};
}

componentDidMount() {
ModalStore.addModalListener(ActionTypes.TOGGLE_LEAVE_TEAM_MODAL, this.handleToggle);
}

componentWillUnmount() {
ModalStore.removeModalListener(ActionTypes.TOGGLE_LEAVE_TEAM_MODAL, this.handleToggle);
}

handleToggle(value) {
this.setState({
show: value
});
}

handleSubmit() {
GlobalActions.emitLeaveTeam();

this.setState({
show: false
});
}

handleHide() {
this.setState({
show: false
});
}

render() {
var currentUser = UserStore.getCurrentUser();

if (currentUser != null) {
return (
<Modal
className='modal-confirm'
show={this.state.show}
onHide={this.handleHide}
>
<Modal.Header closeButton={false}>
<Modal.Title>
<FormattedMessage
id='leave_team_modal.title'
defaultMessage='Leave the team?'
/>
</Modal.Title>
</Modal.Header>
<Modal.Body>
<FormattedMessage
id='leave_team_modal.desc'
defaultMessage='You will be removed from all public channels and private groups. If the team is private you will not be able to rejoin the team. Are you sure?'
/>
</Modal.Body>
<Modal.Footer>
<button
type='button'
className='btn btn-default'
onClick={this.handleHide}
>
<FormattedMessage
id='leave_team_modal.no'
defaultMessage='No'
/>
</button>
<button
type='button'
className='btn btn-danger'
onClick={this.handleSubmit}
>
<FormattedMessage
id='leave_team_modal.yes'
defaultMessage='Yes'
/>
</button>
</Modal.Footer>
</Modal>
);
}

return null;
}
}

LeaveTeamModal.propTypes = {
intl: intlShape.isRequired
};

export default injectIntl(LeaveTeamModal);
14 changes: 14 additions & 0 deletions components/navbar_dropdown.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,20 @@ export default class NavbarDropdown extends React.Component {
);
}

teams.push(
<li key='leaveTeam_li'>
<a
href='#'
onClick={GlobalActions.showLeaveTeamModal}
>
<FormattedMessage
id='navbar_dropdown.leave'
defaultMessage='Leave Team'
/>
</a>
</li>
);

if (this.state.teamMembers && this.state.teamMembers.length > 1) {
teams.push(
<li
Expand Down
2 changes: 2 additions & 0 deletions components/needs_team.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import RemovedFromChannelModal from 'components/removed_from_channel_modal.jsx';
import RegisterAppModal from 'components/register_app_modal.jsx';
import ImportThemeModal from 'components/user_settings/import_theme_modal.jsx';
import InviteMemberModal from 'components/invite_member_modal.jsx';
import LeaveTeamModal from 'components/leave_team_modal.jsx';
import SelectTeamModal from 'components/admin_console/select_team_modal.jsx';

export default class NeedsTeam extends React.Component {
Expand Down Expand Up @@ -129,6 +130,7 @@ export default class NeedsTeam extends React.Component {
<GetPublicLinkModal/>
<GetTeamInviteLinkModal/>
<InviteMemberModal/>
<LeaveTeamModal/>
<ImportThemeModal/>
<TeamSettingsModal/>
<MoreChannelsModal/>
Expand Down
Loading

0 comments on commit c7569d7

Please sign in to comment.