adds remove team action

This commit is contained in:
zmagod 2017-09-13 17:11:51 +02:00
parent 1b3b3dfea9
commit 705d07f60e
11 changed files with 215 additions and 8 deletions

View file

@ -31,7 +31,6 @@ module ClientApi
current_user: current_user,
params: team_params)
team_service.update_team!
success_response('/client_api/teams/update_details',
team_service.single_team_details_data)
rescue ClientApi::CustomTeamError => error

View file

@ -29,6 +29,19 @@ module ClientApi
unsuccess_response(error.to_s)
end
def remove_user
ut_service = ClientApi::UserTeamService.new(
user: current_user,
team_id: params[:team],
user_team_id: params[:user_team]
)
ut_service.destroy_user_team_and_assign_new_team_owner!
success_response('/client_api/teams/team_users',
ut_service.team_users_data)
rescue ClientApi::CustomUserTeamError => error
unsuccess_response(error.to_s)
end
private
def success_response(template, locals)

View file

@ -27,6 +27,7 @@ export const CONTACT_US_LINK =
// user teams
export const LEAVE_TEAM_PATH = "/client_api/users/leave_team";
export const UPDATE_USER_TEAM_ROLE_PATH = "/client_api/users/update_role";
export const REMOVE_USER_FROM_TEAM_PATH = "/client_api/users/remove_user";
// settings
export const SETTINGS_ACCOUNT_PROFILE = "/settings/account/profile";

View file

@ -70,6 +70,15 @@ export default {
warning_message_three: "all repository protocols in the team belonging to you will be reassigned onto a new owner from team administrators.",
leave_team: "Leave"
},
remove_user_modal: {
title: "Remove user {user} from team {team}",
subtitle: "Are you sure you wish to remove user {user} from team {team}?",
warnings: "Removing user from team has following consequences:",
warning_message_one: "user will lose access to all content belonging to the team (including projects, tasks, protocols and activities);",
warning_message_two: "all projects in the team where user was the sole <b>Owner</b> will be reassigned onto you as a new owner;",
warning_message_three: "all repository protocols in the team belonging to user will be reassigned onto you.",
remove_user: "Remove user"
},
update_team_description_modal: {
title: "Edit team description",
label: "Description"

View file

@ -163,7 +163,7 @@ class SettingsTeamPageContainer extends Component {
<TeamsMembers
members={this.state.users}
updateUsersCallback={this.updateUsersCallback}
teamId={this.state.team.id}
team={this.state.team}
/>
<UpdateTeamDescriptionModal
showModal={this.state.showModal}

View file

@ -0,0 +1,99 @@
import React, { Component } from "react";
import PropTypes, { bool, number, string, func } from "prop-types";
import { Modal, Button, Alert, Glyphicon } from "react-bootstrap";
import { FormattedMessage, FormattedHTMLMessage } from "react-intl";
import axios from "../../../../../app/axios";
import { REMOVE_USER_FROM_TEAM_PATH } from "../../../../../app/routes";
class RemoveUserModal extends Component {
constructor(props) {
super(props);
this.onCloseModal = this.onCloseModal.bind(this);
this.removeUser = this.removeUser.bind(this);
}
onCloseModal() {
this.props.hideModal();
}
removeUser() {
const { team_id, team_user_id } = this.props.userToRemove;
axios({
method: "DELETE",
url: REMOVE_USER_FROM_TEAM_PATH,
withCredentials: true,
data: {
team: team_id,
user_team: team_user_id
}
})
.then(response => {
this.props.updateUsersCallback(response.data.team_users);
this.props.hideModal();
})
.catch(error => console.log(error));
}
render() {
const { teamName, userName } = this.props.userToRemove;
return (
<Modal show={this.props.showModal} onHide={this.onCloseModal}>
<Modal.Header closeButton>
<Modal.Title>
<FormattedMessage
id="settings_page.remove_user_modal.title"
values={{ user: userName, team: teamName }}
/>
</Modal.Title>
</Modal.Header>
<Modal.Body>
<p>
<FormattedMessage
id="settings_page.remove_user_modal.subtitle"
values={{ user: userName, team: teamName }}
/>
</p>
<Alert bsStyle="danger">
<Glyphicon glyph="exclamation-sign" />&nbsp;
<FormattedMessage id="settings_page.remove_user_modal.warnings" />
<ul>
<li>
<FormattedMessage id="settings_page.remove_user_modal.warning_message_one" />
</li>
<li>
<FormattedHTMLMessage id="settings_page.remove_user_modal.warning_message_two" />
</li>
<li>
<FormattedMessage id="settings_page.remove_user_modal.warning_message_three" />
</li>
</ul>
</Alert>
</Modal.Body>
<Modal.Footer>
<Button onClick={this.onCloseModal}>
<FormattedMessage id="general.close" />
</Button>
<Button bsStyle="success" onClick={this.removeUser}>
<FormattedMessage id="settings_page.remove_user_modal.remove_user" />
</Button>
</Modal.Footer>
</Modal>
);
}
}
RemoveUserModal.propTypes = {
showModal: bool.isRequired,
hideModal: func.isRequired,
userToRemove: PropTypes.shape({
userName: string.isRequired,
team_user_id: number.isRequired,
teamName: string.isRequired,
team_id: number.isRequired
}).isRequired,
updateUsersCallback: func.isRequired
};
export default RemoveUserModal;

View file

@ -10,13 +10,22 @@ import {
import { FormattedMessage } from "react-intl";
import axios from "../../../../../app/axios";
import RemoveUserModal from "./RemoveUserModal";
import DataTable from "../../../../../shared/data_table";
import { UPDATE_USER_TEAM_ROLE_PATH } from "../../../../../app/routes";
const initalUserToRemove = {
userName: "",
team_user_id: 0,
teamName: "",
team_id: 0
};
class TeamsMembers extends Component {
constructor(params) {
super(params);
this.state = { showModal: false, userToRemove: initalUserToRemove };
this.memberAction = this.memberAction.bind(this);
this.hideModal = this.hideModal.bind(this);
}
currentRole(memberRole, role) {
@ -26,7 +35,7 @@ class TeamsMembers extends Component {
updateRole(userTeamId, role) {
axios
.put(UPDATE_USER_TEAM_ROLE_PATH, {
team: this.props.teamId,
team: this.props.team.id,
user_team: userTeamId,
role
})
@ -36,7 +45,13 @@ class TeamsMembers extends Component {
.catch(error => console.log(error));
}
removeUser(userTeamId) {}
hideModal() {
this.setState({ showModal: false, userToRemove: initalUserToRemove });
}
userToRemove(userToRemove) {
this.setState({ showModal: true, userToRemove });
}
memberAction(data, row) {
return (
@ -83,7 +98,12 @@ class TeamsMembers extends Component {
<MenuItem divider />
<MenuItem
onClick={() => {
this.removeUser(data.team_user_id);
this.userToRemove({
userName: row.name,
team_user_id: data.team_user_id,
teamName: this.props.team.name,
team_id: this.props.team.id
});
}}
>
<FormattedMessage id="settings_page.single_team.actions.remove_user" />
@ -155,6 +175,12 @@ class TeamsMembers extends Component {
</Button>
<DataTable data={this.props.members} columns={columns} />
<RemoveUserModal
showModal={this.state.showModal}
hideModal={this.hideModal}
updateUsersCallback={this.props.updateUsersCallback}
userToRemove={this.state.userToRemove}
/>
</Panel>
);
}
@ -162,7 +188,10 @@ class TeamsMembers extends Component {
TeamsMembers.propTypes = {
updateUsersCallback: func.isRequired,
teamId: number.isRequired,
team: PropTypes.shape({
id: number.isRequired,
name: string.isRequired
}).isRequired,
members: PropTypes.arrayOf(
PropTypes.shape({
id: number.isRequired,

View file

@ -9,10 +9,10 @@ module ClientApi
@user = parsed_args.fetch(:user)
@user_team = UserTeam.find_by_id(parsed_args.fetch(:user_team_id).to_i)
@role = args.fetch(:role) { false }
raise ClientApi::CustomUserTeamError unless @user_team && @user && @team
end
def destroy_user_team_and_assign_new_team_owner!
binding.pry
raise ClientApi::CustomUserTeamError unless user_cant_leave?
new_owner = @team.user_teams
.where(role: 2)
@ -59,7 +59,7 @@ module ClientApi
end
def user_cant_leave?
@user.teams.includes @team &&
@user.teams.includes(@team) &&
@user_team.admin? &&
@team.user_teams.where(role: 2).count <= 1
end

View file

@ -29,6 +29,7 @@ Rails.application.routes.draw do
get '/current_user_info', to: 'users#current_user_info'
namespace :users do
delete '/remove_user', to: 'user_teams#remove_user'
delete '/leave_team', to: 'user_teams#leave_team'
put '/update_role', to: 'user_teams#update_role'
end

View file

@ -0,0 +1,56 @@
require 'rails_helper'
describe ClientApi::UserTeamService do
let(:team_one) { create :team }
let(:user_one) { create :user, email: Faker::Internet.email }
let(:user_team) { create :user_team, user: user_one, team: team_one }
it 'should raise ClientApi::CustomUserTeamError if user is not assigned' do
expect {
ClientApi::UserTeamService.new(
team_id: team_one.id,
user_team_id: user_team.id
)
}.to raise_error(ClientApi::CustomUserTeamError)
end
it 'should raise ClientApi::CustomUserTeamError if team is not assigned' do
expect {
ClientApi::UserTeamService.new(user: user_one, user_team_id: user_team.id)
}.to raise_error(ClientApi::CustomUserTeamError)
end
it 'should raise ClientApi::CustomUserTeamError if ' \
'user_team is not assigned' do
expect {
ClientApi::UserTeamService.new(user: user_one, team_id: team_one.id)
}.to raise_error(ClientApi::CustomUserTeamError)
end
describe '#destroy_user_team_and_assign_new_team_owner!' do
let(:user_two) { create :user, email: Faker::Internet.email }
it 'should raise ClientApi::CustomUserTeamError if user ' \
'can\'t leave the team' do
ut_service = ClientApi::UserTeamService.new(
team_id: team_one.id,
user_team_id: user_team.id,
user: user_one
)
expect {
ut_service.destroy_user_team_and_assign_new_team_owner!
}.to raise_error(ClientApi::CustomUserTeamError)
end
it 'should destroy the user_team relation' do
new_user_team = create :user_team, team: team_one, user: user_two
ut_service = ClientApi::UserTeamService.new(
team_id: team_one.id,
user_team_id: new_user_team.id,
user: user_two
)
ut_service.destroy_user_team_and_assign_new_team_owner!
expect(new_user_team).to_not exist
end
end
end