PLT-6098 Added Manage Teams modal to System Console users list (#5914)
* Added Manage Teams modal to System Console users list * Localized ManageTeamsModal * Fixed borders between Manage Teams list items * Updated appearance of ManageTeamsModal * Fixed admin being redirected from system console when removing self from a team * Sorted teams in ManageTeamsModal * Updated Manage Teams styling
Этот коммит содержится в:
коммит произвёл
Corey Hulen
родитель
4c9019b9eb
Коммит
348374fba5
@@ -150,3 +150,11 @@ export function switchTeams(url) {
|
|||||||
AsyncClient.viewChannel();
|
AsyncClient.viewChannel();
|
||||||
browserHistory.push(url);
|
browserHistory.push(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getTeamsForUser(userId, success, error) {
|
||||||
|
Client.getTeamsForUser(userId, success, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getTeamMembersForUser(userId, success, error) {
|
||||||
|
Client.getTeamMembersForUser(userId, success, error);
|
||||||
|
}
|
||||||
|
|||||||
@@ -251,8 +251,11 @@ function handleLeaveTeamEvent(msg) {
|
|||||||
Client.setTeamId('');
|
Client.setTeamId('');
|
||||||
BrowserStore.removeGlobalItem('team');
|
BrowserStore.removeGlobalItem('team');
|
||||||
BrowserStore.removeGlobalItem(msg.data.team_id);
|
BrowserStore.removeGlobalItem(msg.data.team_id);
|
||||||
|
|
||||||
|
if (!global.location.pathname.startsWith('/admin_console')) {
|
||||||
GlobalActions.redirectUserToDefaultTeam();
|
GlobalActions.redirectUserToDefaultTeam();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
UserStore.removeProfileFromTeam(msg.data.team_id, msg.data.user_id);
|
UserStore.removeProfileFromTeam(msg.data.team_id, msg.data.user_id);
|
||||||
TeamStore.removeMemberInTeam(msg.data.team_id, msg.data.user_id);
|
TeamStore.removeMemberInTeam(msg.data.team_id, msg.data.user_id);
|
||||||
|
|||||||
@@ -550,6 +550,16 @@ export default class Client {
|
|||||||
end(this.handleResponse.bind(this, 'getAllTeamListings', success, error));
|
end(this.handleResponse.bind(this, 'getAllTeamListings', success, error));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getTeamsForUser(userId, success, error) {
|
||||||
|
// Call out to API v4 since this call doesn't exist in v3
|
||||||
|
request.
|
||||||
|
get(`${this.url}/api/v4/users/${userId}/teams`).
|
||||||
|
set(this.defaultHeaders).
|
||||||
|
type('application/json').
|
||||||
|
accept('application/json').
|
||||||
|
end(this.handleResponse.bind(this, 'getTeamsForUser', success, error));
|
||||||
|
}
|
||||||
|
|
||||||
getMyTeam(success, error) {
|
getMyTeam(success, error) {
|
||||||
request.
|
request.
|
||||||
get(`${this.getTeamNeededRoute()}/me`).
|
get(`${this.getTeamNeededRoute()}/me`).
|
||||||
@@ -586,6 +596,16 @@ export default class Client {
|
|||||||
end(this.handleResponse.bind(this, 'getMyTeamMembers', success, error));
|
end(this.handleResponse.bind(this, 'getMyTeamMembers', success, error));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getTeamMembersForUser(userId, success, error) {
|
||||||
|
// Call out to API v4 since this call doesn't exist in v3
|
||||||
|
request.
|
||||||
|
get(`${this.url}/api/v4/users/${userId}/teams/members`).
|
||||||
|
set(this.defaultHeaders).
|
||||||
|
type('application/json').
|
||||||
|
accept('application/json').
|
||||||
|
end(this.handleResponse.bind(this, 'getTeamsForUser', success, error));
|
||||||
|
}
|
||||||
|
|
||||||
getMyTeamsUnread(teamId, success, error) {
|
getMyTeamsUnread(teamId, success, error) {
|
||||||
let url = `${this.getTeamsRoute()}/unread`;
|
let url = `${this.getTeamsRoute()}/unread`;
|
||||||
|
|
||||||
@@ -1275,6 +1295,16 @@ export default class Client {
|
|||||||
this.trackEvent('api', 'api_users_update_profile_picture');
|
this.trackEvent('api', 'api_users_update_profile_picture');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getProfilePictureUrl(id, lastPictureUpdate) {
|
||||||
|
let url = `${this.getUsersRoute()}/${id}/image`;
|
||||||
|
|
||||||
|
if (lastPictureUpdate) {
|
||||||
|
url += `?time=${lastPictureUpdate}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
// Channel Routes Section
|
// Channel Routes Section
|
||||||
|
|
||||||
createChannel(channel, success, error) {
|
createChannel(channel, success, error) {
|
||||||
|
|||||||
@@ -0,0 +1,137 @@
|
|||||||
|
// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See License.txt for license information.
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import {Dropdown, MenuItem} from 'react-bootstrap';
|
||||||
|
import {FormattedMessage} from 'react-intl';
|
||||||
|
|
||||||
|
import {updateTeamMemberRoles, removeUserFromTeam} from 'actions/team_actions.jsx';
|
||||||
|
|
||||||
|
import * as Utils from 'utils/utils.jsx';
|
||||||
|
|
||||||
|
export default class ManageTeamsDropdown extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
user: React.PropTypes.object.isRequired,
|
||||||
|
teamMember: React.PropTypes.object.isRequired,
|
||||||
|
onError: React.PropTypes.func.isRequired,
|
||||||
|
onMemberChange: React.PropTypes.func.isRequired,
|
||||||
|
onMemberRemove: React.PropTypes.func.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.toggleDropdown = this.toggleDropdown.bind(this);
|
||||||
|
|
||||||
|
this.makeTeamAdmin = this.makeTeamAdmin.bind(this);
|
||||||
|
this.makeMember = this.makeMember.bind(this);
|
||||||
|
this.removeFromTeam = this.removeFromTeam.bind(this);
|
||||||
|
|
||||||
|
this.handleMemberChange = this.handleMemberChange.bind(this);
|
||||||
|
this.handleMemberRemove = this.handleMemberRemove.bind(this);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
show: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleDropdown() {
|
||||||
|
this.setState({
|
||||||
|
show: !this.state.show
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
makeTeamAdmin() {
|
||||||
|
updateTeamMemberRoles(
|
||||||
|
this.props.teamMember.team_id,
|
||||||
|
this.props.user.id,
|
||||||
|
'team_user team_admin',
|
||||||
|
this.handleMemberChange,
|
||||||
|
this.props.onError
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
makeMember() {
|
||||||
|
updateTeamMemberRoles(
|
||||||
|
this.props.teamMember.team_id,
|
||||||
|
this.props.user.id,
|
||||||
|
'team_user',
|
||||||
|
this.handleMemberChange,
|
||||||
|
this.props.onError
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
removeFromTeam() {
|
||||||
|
removeUserFromTeam(
|
||||||
|
this.props.teamMember.team_id,
|
||||||
|
this.props.user.id,
|
||||||
|
this.handleMemberRemove,
|
||||||
|
this.props.onError
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleMemberChange() {
|
||||||
|
this.props.onMemberChange(this.props.teamMember.team_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleMemberRemove() {
|
||||||
|
this.props.onMemberRemove(this.props.teamMember.team_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const isTeamAdmin = Utils.isAdmin(this.props.teamMember.roles);
|
||||||
|
|
||||||
|
let title;
|
||||||
|
if (isTeamAdmin) {
|
||||||
|
title = Utils.localizeMessage('admin.user_item.teamAdmin', 'Team Admin');
|
||||||
|
} else {
|
||||||
|
title = Utils.localizeMessage('admin.user_item.teamMember', 'Team Member');
|
||||||
|
}
|
||||||
|
|
||||||
|
let makeTeamAdmin = null;
|
||||||
|
if (!isTeamAdmin) {
|
||||||
|
makeTeamAdmin = (
|
||||||
|
<MenuItem onSelect={this.makeTeamAdmin}>
|
||||||
|
<FormattedMessage
|
||||||
|
id='admin.user_item.makeTeamAdmin'
|
||||||
|
defaultMessage='Make Team Admin'
|
||||||
|
/>
|
||||||
|
</MenuItem>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let makeMember = null;
|
||||||
|
if (isTeamAdmin) {
|
||||||
|
makeMember = (
|
||||||
|
<MenuItem onSelect={this.makeMember}>
|
||||||
|
<FormattedMessage
|
||||||
|
id='admin.user_item.makeMember'
|
||||||
|
defaultMessage='Make Member'
|
||||||
|
/>
|
||||||
|
</MenuItem>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dropdown
|
||||||
|
id={`manage-teams-${this.props.user.id}-${this.props.teamMember.team_id}`}
|
||||||
|
open={this.state.show}
|
||||||
|
onToggle={this.toggleDropdown}
|
||||||
|
>
|
||||||
|
<Dropdown.Toggle useAnchor={true}>
|
||||||
|
{title}
|
||||||
|
</Dropdown.Toggle>
|
||||||
|
<Dropdown.Menu>
|
||||||
|
{makeTeamAdmin}
|
||||||
|
{makeMember}
|
||||||
|
<MenuItem onSelect={this.removeFromTeam}>
|
||||||
|
<FormattedMessage
|
||||||
|
id='team_members_dropdown.leave_team'
|
||||||
|
defaultMessage='Remove from Team'
|
||||||
|
/>
|
||||||
|
</MenuItem>
|
||||||
|
</Dropdown.Menu>
|
||||||
|
</Dropdown>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,225 @@
|
|||||||
|
// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See License.txt for license information.
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import {Modal} from 'react-bootstrap';
|
||||||
|
import {FormattedMessage} from 'react-intl';
|
||||||
|
|
||||||
|
import * as TeamActions from 'actions/team_actions.jsx';
|
||||||
|
|
||||||
|
import Client from 'client/web_client.jsx';
|
||||||
|
|
||||||
|
import LoadingScreen from 'components/loading_screen.jsx';
|
||||||
|
|
||||||
|
import {sortTeamsByDisplayName} from 'utils/team_utils.jsx';
|
||||||
|
import * as Utils from 'utils/utils.jsx';
|
||||||
|
|
||||||
|
import ManageTeamsDropdown from './manage_teams_dropdown.jsx';
|
||||||
|
import RemoveFromTeamButton from './remove_from_team_button.jsx';
|
||||||
|
|
||||||
|
export default class ManageTeamsModal extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
onModalDismissed: React.PropTypes.func.isRequired,
|
||||||
|
show: React.PropTypes.bool.isRequired,
|
||||||
|
user: React.PropTypes.object
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.loadTeamsAndTeamMembers = this.loadTeamsAndTeamMembers.bind(this);
|
||||||
|
|
||||||
|
this.handleError = this.handleError.bind(this);
|
||||||
|
this.handleMemberChange = this.handleMemberChange.bind(this);
|
||||||
|
this.handleMemberRemove = this.handleMemberRemove.bind(this);
|
||||||
|
|
||||||
|
this.renderContents = this.renderContents.bind(this);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
error: null,
|
||||||
|
teams: null,
|
||||||
|
teamMembers: null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
if (this.props.user) {
|
||||||
|
this.loadTeamsAndTeamMembers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(nextProps) {
|
||||||
|
const userId = this.props.user ? this.props.user.id : '';
|
||||||
|
const nextUserId = nextProps.user ? nextProps.user.id : '';
|
||||||
|
|
||||||
|
if (userId !== nextUserId) {
|
||||||
|
this.setState({
|
||||||
|
teams: null,
|
||||||
|
teamMembers: null
|
||||||
|
});
|
||||||
|
|
||||||
|
if (nextProps.user) {
|
||||||
|
this.loadTeamsAndTeamMembers(nextProps.user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loadTeamsAndTeamMembers(user = this.props.user) {
|
||||||
|
TeamActions.getTeamsForUser(user.id, (teams) => {
|
||||||
|
this.setState({
|
||||||
|
teams: teams.sort(sortTeamsByDisplayName)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
TeamActions.getTeamMembersForUser(user.id, (teamMembers) => {
|
||||||
|
this.setState({
|
||||||
|
teamMembers
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleError(error) {
|
||||||
|
this.setState({
|
||||||
|
error
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleMemberChange() {
|
||||||
|
TeamActions.getTeamMembersForUser(this.props.user.id, (teamMembers) => {
|
||||||
|
this.setState({
|
||||||
|
teamMembers
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleMemberRemove(teamId) {
|
||||||
|
this.setState({
|
||||||
|
teams: this.state.teams.filter((team) => team.id !== teamId),
|
||||||
|
teamMembers: this.state.teamMembers.filter((teamMember) => teamMember.team_id !== teamId)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
renderContents() {
|
||||||
|
const {user} = this.props;
|
||||||
|
const {teams, teamMembers} = this.state;
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return <LoadingScreen/>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isSystemAdmin = Utils.isAdmin(user.roles);
|
||||||
|
|
||||||
|
let name = Utils.getFullName(user);
|
||||||
|
if (name) {
|
||||||
|
name += ` (@${user.username})`;
|
||||||
|
} else {
|
||||||
|
name = `@${user.username}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
let teamList;
|
||||||
|
if (teams && teamMembers) {
|
||||||
|
teamList = teams.map((team) => {
|
||||||
|
const teamMember = teamMembers.find((member) => member.team_id === team.id);
|
||||||
|
if (!teamMember) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let action;
|
||||||
|
if (isSystemAdmin) {
|
||||||
|
action = (
|
||||||
|
<RemoveFromTeamButton
|
||||||
|
user={user}
|
||||||
|
team={team}
|
||||||
|
onError={this.handleError}
|
||||||
|
onMemberRemove={this.handleMemberRemove}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
action = (
|
||||||
|
<ManageTeamsDropdown
|
||||||
|
user={user}
|
||||||
|
team={team}
|
||||||
|
teamMember={teamMember}
|
||||||
|
onError={this.handleError}
|
||||||
|
onMemberChange={this.handleMemberChange}
|
||||||
|
onMemberRemove={this.handleMemberRemove}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={team.id}
|
||||||
|
className='manage-teams__team'
|
||||||
|
>
|
||||||
|
<div className='manage-teams__team-name'>
|
||||||
|
{team.display_name}
|
||||||
|
</div>
|
||||||
|
<div className='manage-teams__team-actions'>
|
||||||
|
{action}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
teamList = <LoadingScreen/>;
|
||||||
|
}
|
||||||
|
|
||||||
|
let systemAdminIndicator = null;
|
||||||
|
if (isSystemAdmin) {
|
||||||
|
systemAdminIndicator = (
|
||||||
|
<div className='manage-teams__system-admin'>
|
||||||
|
<FormattedMessage
|
||||||
|
id='admin.user_item.sysAdmin'
|
||||||
|
defaultMessage='System Admin'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className='manage-teams__user'>
|
||||||
|
<img
|
||||||
|
className='manage-teams__profile-picture'
|
||||||
|
src={Client.getProfilePictureUrl(user.id, user.last_picture_update)}
|
||||||
|
/>
|
||||||
|
<div className='manage-teams__info'>
|
||||||
|
<div className='manage-teams__name'>
|
||||||
|
{name}
|
||||||
|
</div>
|
||||||
|
<div className='manage-teams__email'>
|
||||||
|
{user.email}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{systemAdminIndicator}
|
||||||
|
</div>
|
||||||
|
<div className='manage-teams__teams'>
|
||||||
|
{teamList}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
show={this.props.show}
|
||||||
|
onHide={this.props.onModalDismissed}
|
||||||
|
dialogClassName='manage-teams'
|
||||||
|
>
|
||||||
|
<Modal.Header closeButton={true}>
|
||||||
|
<Modal.Title>
|
||||||
|
<FormattedMessage
|
||||||
|
id='admin.user_item.manageTeams'
|
||||||
|
defaultMessage='Manage Teams'
|
||||||
|
/>
|
||||||
|
</Modal.Title>
|
||||||
|
</Modal.Header>
|
||||||
|
<Modal.Body>
|
||||||
|
{this.renderContents()}
|
||||||
|
</Modal.Body>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See License.txt for license information.
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import {FormattedMessage} from 'react-intl';
|
||||||
|
|
||||||
|
import {removeUserFromTeam} from 'actions/team_actions.jsx';
|
||||||
|
|
||||||
|
export default class RemoveFromTeamButton extends React.PureComponent {
|
||||||
|
static propTypes = {
|
||||||
|
onError: React.PropTypes.func.isRequired,
|
||||||
|
onMemberRemove: React.PropTypes.func.isRequired,
|
||||||
|
team: React.PropTypes.object.isRequired,
|
||||||
|
user: React.PropTypes.object.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.handleClick = this.handleClick.bind(this);
|
||||||
|
this.handleMemberRemove = this.handleMemberRemove.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleClick(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
removeUserFromTeam(
|
||||||
|
this.props.team.id,
|
||||||
|
this.props.user.id,
|
||||||
|
this.handleMemberRemove,
|
||||||
|
this.props.onError
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleMemberRemove() {
|
||||||
|
this.props.onMemberRemove(this.props.team.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
className='btn btn-default'
|
||||||
|
onClick={this.handleClick}
|
||||||
|
>
|
||||||
|
<FormattedMessage
|
||||||
|
id='team_members_dropdown.leave_team'
|
||||||
|
defaultMessage='Remove from Team'
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,7 +18,8 @@ import React from 'react';
|
|||||||
export default class SystemUsersDropdown extends React.Component {
|
export default class SystemUsersDropdown extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
user: React.PropTypes.object.isRequired,
|
user: React.PropTypes.object.isRequired,
|
||||||
doPasswordReset: React.PropTypes.func.isRequired
|
doPasswordReset: React.PropTypes.func.isRequired,
|
||||||
|
doManageTeams: React.PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@@ -28,6 +29,7 @@ export default class SystemUsersDropdown extends React.Component {
|
|||||||
this.handleMakeActive = this.handleMakeActive.bind(this);
|
this.handleMakeActive = this.handleMakeActive.bind(this);
|
||||||
this.handleMakeNotActive = this.handleMakeNotActive.bind(this);
|
this.handleMakeNotActive = this.handleMakeNotActive.bind(this);
|
||||||
this.handleMakeSystemAdmin = this.handleMakeSystemAdmin.bind(this);
|
this.handleMakeSystemAdmin = this.handleMakeSystemAdmin.bind(this);
|
||||||
|
this.handleManageTeams = this.handleManageTeams.bind(this);
|
||||||
this.handleResetPassword = this.handleResetPassword.bind(this);
|
this.handleResetPassword = this.handleResetPassword.bind(this);
|
||||||
this.handleResetMfa = this.handleResetMfa.bind(this);
|
this.handleResetMfa = this.handleResetMfa.bind(this);
|
||||||
this.handleDemoteSystemAdmin = this.handleDemoteSystemAdmin.bind(this);
|
this.handleDemoteSystemAdmin = this.handleDemoteSystemAdmin.bind(this);
|
||||||
@@ -94,6 +96,12 @@ export default class SystemUsersDropdown extends React.Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleManageTeams(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
this.props.doManageTeams(this.props.user);
|
||||||
|
}
|
||||||
|
|
||||||
handleResetPassword(e) {
|
handleResetPassword(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.props.doPasswordReset(this.props.user);
|
this.props.doPasswordReset(this.props.user);
|
||||||
@@ -177,6 +185,7 @@ export default class SystemUsersDropdown extends React.Component {
|
|||||||
let showMakeSystemAdmin = !Utils.isSystemAdmin(user.roles);
|
let showMakeSystemAdmin = !Utils.isSystemAdmin(user.roles);
|
||||||
let showMakeActive = false;
|
let showMakeActive = false;
|
||||||
let showMakeNotActive = !Utils.isSystemAdmin(user.roles);
|
let showMakeNotActive = !Utils.isSystemAdmin(user.roles);
|
||||||
|
let showManageTeams = true;
|
||||||
const mfaEnabled = global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.MFA === 'true' && global.window.mm_config.EnableMultifactorAuthentication === 'true';
|
const mfaEnabled = global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.MFA === 'true' && global.window.mm_config.EnableMultifactorAuthentication === 'true';
|
||||||
const showMfaReset = mfaEnabled && user.mfa_active;
|
const showMfaReset = mfaEnabled && user.mfa_active;
|
||||||
|
|
||||||
@@ -191,6 +200,7 @@ export default class SystemUsersDropdown extends React.Component {
|
|||||||
showMakeSystemAdmin = false;
|
showMakeSystemAdmin = false;
|
||||||
showMakeActive = true;
|
showMakeActive = true;
|
||||||
showMakeNotActive = false;
|
showMakeNotActive = false;
|
||||||
|
showManageTeams = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let disableActivationToggle = false;
|
let disableActivationToggle = false;
|
||||||
@@ -281,6 +291,24 @@ export default class SystemUsersDropdown extends React.Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let manageTeams = null;
|
||||||
|
if (showManageTeams) {
|
||||||
|
manageTeams = (
|
||||||
|
<li role='presentation'>
|
||||||
|
<a
|
||||||
|
role='menuitem'
|
||||||
|
href='#'
|
||||||
|
onClick={this.handleManageTeams}
|
||||||
|
>
|
||||||
|
<FormattedMessage
|
||||||
|
id='admin.user_item.manageTeams'
|
||||||
|
defaultMessage='Manage Teams'
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let mfaReset = null;
|
let mfaReset = null;
|
||||||
if (showMfaReset) {
|
if (showMfaReset) {
|
||||||
mfaReset = (
|
mfaReset = (
|
||||||
@@ -404,6 +432,7 @@ export default class SystemUsersDropdown extends React.Component {
|
|||||||
{makeActive}
|
{makeActive}
|
||||||
{makeNotActive}
|
{makeNotActive}
|
||||||
{makeSystemAdmin}
|
{makeSystemAdmin}
|
||||||
|
{manageTeams}
|
||||||
{mfaReset}
|
{mfaReset}
|
||||||
{passwordReset}
|
{passwordReset}
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {FormattedMessage, FormattedHTMLMessage} from 'react-intl';
|
import {FormattedMessage, FormattedHTMLMessage} from 'react-intl';
|
||||||
|
|
||||||
|
import ManageTeamsModal from 'components/admin_console/manage_teams_modal/manage_teams_modal.jsx';
|
||||||
import ResetPasswordModal from 'components/admin_console/reset_password_modal.jsx';
|
import ResetPasswordModal from 'components/admin_console/reset_password_modal.jsx';
|
||||||
import SearchableUserList from 'components/searchable_user_list/searchable_user_list.jsx';
|
import SearchableUserList from 'components/searchable_user_list/searchable_user_list.jsx';
|
||||||
|
|
||||||
@@ -35,6 +36,9 @@ export default class SystemUsersList extends React.Component {
|
|||||||
this.previousPage = this.previousPage.bind(this);
|
this.previousPage = this.previousPage.bind(this);
|
||||||
this.search = this.search.bind(this);
|
this.search = this.search.bind(this);
|
||||||
|
|
||||||
|
this.doManageTeams = this.doManageTeams.bind(this);
|
||||||
|
this.doManageTeamsDismiss = this.doManageTeamsDismiss.bind(this);
|
||||||
|
|
||||||
this.doPasswordReset = this.doPasswordReset.bind(this);
|
this.doPasswordReset = this.doPasswordReset.bind(this);
|
||||||
this.doPasswordResetDismiss = this.doPasswordResetDismiss.bind(this);
|
this.doPasswordResetDismiss = this.doPasswordResetDismiss.bind(this);
|
||||||
this.doPasswordResetSubmit = this.doPasswordResetSubmit.bind(this);
|
this.doPasswordResetSubmit = this.doPasswordResetSubmit.bind(this);
|
||||||
@@ -42,6 +46,7 @@ export default class SystemUsersList extends React.Component {
|
|||||||
this.state = {
|
this.state = {
|
||||||
page: 0,
|
page: 0,
|
||||||
|
|
||||||
|
showManageTeamsModal: false,
|
||||||
showPasswordModal: false,
|
showPasswordModal: false,
|
||||||
user: null
|
user: null
|
||||||
};
|
};
|
||||||
@@ -71,6 +76,20 @@ export default class SystemUsersList extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
doManageTeams(user) {
|
||||||
|
this.setState({
|
||||||
|
showManageTeamsModal: true,
|
||||||
|
user
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
doManageTeamsDismiss() {
|
||||||
|
this.setState({
|
||||||
|
showManageTeamsModal: false,
|
||||||
|
user: null
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
doPasswordReset(user) {
|
doPasswordReset(user) {
|
||||||
this.setState({
|
this.setState({
|
||||||
showPasswordModal: true,
|
showPasswordModal: true,
|
||||||
@@ -211,7 +230,8 @@ export default class SystemUsersList extends React.Component {
|
|||||||
extraInfo={extraInfo}
|
extraInfo={extraInfo}
|
||||||
actions={[SystemUsersDropdown]}
|
actions={[SystemUsersDropdown]}
|
||||||
actionProps={{
|
actionProps={{
|
||||||
doPasswordReset: this.doPasswordReset
|
doPasswordReset: this.doPasswordReset,
|
||||||
|
doManageTeams: this.doManageTeams
|
||||||
}}
|
}}
|
||||||
nextPage={this.nextPage}
|
nextPage={this.nextPage}
|
||||||
previousPage={this.previousPage}
|
previousPage={this.previousPage}
|
||||||
@@ -220,6 +240,11 @@ export default class SystemUsersList extends React.Component {
|
|||||||
term={this.props.term}
|
term={this.props.term}
|
||||||
onTermChange={this.props.onTermChange}
|
onTermChange={this.props.onTermChange}
|
||||||
/>
|
/>
|
||||||
|
<ManageTeamsModal
|
||||||
|
user={this.state.user}
|
||||||
|
show={this.state.showManageTeamsModal}
|
||||||
|
onModalDismissed={this.doManageTeamsDismiss}
|
||||||
|
/>
|
||||||
<ResetPasswordModal
|
<ResetPasswordModal
|
||||||
user={this.state.user}
|
user={this.state.user}
|
||||||
show={this.state.showPasswordModal}
|
show={this.state.showPasswordModal}
|
||||||
|
|||||||
@@ -896,6 +896,7 @@
|
|||||||
"admin.user_item.makeMember": "Make Member",
|
"admin.user_item.makeMember": "Make Member",
|
||||||
"admin.user_item.makeSysAdmin": "Make System Admin",
|
"admin.user_item.makeSysAdmin": "Make System Admin",
|
||||||
"admin.user_item.makeTeamAdmin": "Make Team Admin",
|
"admin.user_item.makeTeamAdmin": "Make Team Admin",
|
||||||
|
"admin.user_item.manageTeams": "Manage Teams",
|
||||||
"admin.user_item.member": "Member",
|
"admin.user_item.member": "Member",
|
||||||
"admin.user_item.mfaNo": "<strong>MFA</strong>: No",
|
"admin.user_item.mfaNo": "<strong>MFA</strong>: No",
|
||||||
"admin.user_item.mfaYes": "<strong>MFA</strong>: Yes",
|
"admin.user_item.mfaYes": "<strong>MFA</strong>: Yes",
|
||||||
@@ -903,6 +904,7 @@
|
|||||||
"admin.user_item.resetPwd": "Reset Password",
|
"admin.user_item.resetPwd": "Reset Password",
|
||||||
"admin.user_item.switchToEmail": "Switch to Email/Password",
|
"admin.user_item.switchToEmail": "Switch to Email/Password",
|
||||||
"admin.user_item.teamAdmin": "Team Admin",
|
"admin.user_item.teamAdmin": "Team Admin",
|
||||||
|
"admin.user_item.sysAdmin": "System Admin",
|
||||||
"admin.webrtc.enableDescription": "When true, Mattermost allows making <strong>one-on-one</strong> video calls. WebRTC calls are available on Chrome, Firefox and Mattermost Desktop Apps.",
|
"admin.webrtc.enableDescription": "When true, Mattermost allows making <strong>one-on-one</strong> video calls. WebRTC calls are available on Chrome, Firefox and Mattermost Desktop Apps.",
|
||||||
"admin.webrtc.enableTitle": "Enable Mattermost WebRTC: ",
|
"admin.webrtc.enableTitle": "Enable Mattermost WebRTC: ",
|
||||||
"admin.webrtc.gatewayAdminSecretDescription": "Enter your admin secret password to access the Gateway Admin URL.",
|
"admin.webrtc.gatewayAdminSecretDescription": "Enter your admin secret password to access the Gateway Admin URL.",
|
||||||
|
|||||||
@@ -501,3 +501,73 @@
|
|||||||
width: 200px
|
width: 200px
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.manage-teams {
|
||||||
|
.manage-teams__user {
|
||||||
|
align-items: center;
|
||||||
|
border-bottom-color: lightgray;
|
||||||
|
border-bottom-style: solid;
|
||||||
|
border-bottom-width: 1px;
|
||||||
|
display: flex;
|
||||||
|
padding-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.manage-teams__profile-picture {
|
||||||
|
border-radius: 20px;
|
||||||
|
height: 40px;
|
||||||
|
width: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.manage-teams__info {
|
||||||
|
flex: 1;
|
||||||
|
margin-left: 10px;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
.manage-teams__name {
|
||||||
|
font-weight: bold;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.manage-teams__email {
|
||||||
|
opacity: 0.5;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.manage-teams__system-admin {
|
||||||
|
margin-left: 10px;
|
||||||
|
opacity: 0.5;
|
||||||
|
padding-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.manage-teams__team {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.manage-teams__team + .manage-teams__team {
|
||||||
|
border-top-color: lightgray;
|
||||||
|
border-top-style: solid;
|
||||||
|
border-top-width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.manage-teams__team-name {
|
||||||
|
flex: 1;
|
||||||
|
font-weight: bold;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.manage-teams__team-actions {
|
||||||
|
margin-left: 10px;
|
||||||
|
|
||||||
|
// Override default react-bootstrap style
|
||||||
|
.dropdown-toggle {
|
||||||
|
@include box-shadow(none);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user