mirror of
https://github.com/mattermost/mattermost.git
synced 2025-02-25 18:55:24 -06:00
When a new channel is selected, we set `exitToDirectChannel` to the newly selected channel. In `handleExit` if `exitToDirectChannel` exists, the new channel information is pushed. This fixes an issue where the create_post textarea gains and then loses focus due to the way that react-overlays (react-bootstrap dependency) handles previous focus which in this particular case is the `More...` link.
284 lines
9.0 KiB
JavaScript
284 lines
9.0 KiB
JavaScript
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
|
|
// See License.txt for license information.
|
|
|
|
import SearchableUserList from 'components/searchable_user_list.jsx';
|
|
import SpinnerButton from 'components/spinner_button.jsx';
|
|
|
|
import {searchUsers} from 'actions/user_actions.jsx';
|
|
import {openDirectChannelToUser} from 'actions/channel_actions.jsx';
|
|
|
|
import UserStore from 'stores/user_store.jsx';
|
|
import TeamStore from 'stores/team_store.jsx';
|
|
|
|
import * as AsyncClient from 'utils/async_client.jsx';
|
|
import * as Utils from 'utils/utils.jsx';
|
|
import Constants from 'utils/constants.jsx';
|
|
|
|
import React from 'react';
|
|
import {Modal} from 'react-bootstrap';
|
|
import {FormattedMessage} from 'react-intl';
|
|
import {browserHistory} from 'react-router/es6';
|
|
|
|
const USERS_PER_PAGE = 50;
|
|
|
|
export default class MoreDirectChannels extends React.Component {
|
|
constructor(props) {
|
|
super(props);
|
|
|
|
this.handleHide = this.handleHide.bind(this);
|
|
this.handleExit = this.handleExit.bind(this);
|
|
this.handleShowDirectChannel = this.handleShowDirectChannel.bind(this);
|
|
this.onChange = this.onChange.bind(this);
|
|
this.createJoinDirectChannelButton = this.createJoinDirectChannelButton.bind(this);
|
|
this.toggleList = this.toggleList.bind(this);
|
|
this.nextPage = this.nextPage.bind(this);
|
|
this.search = this.search.bind(this);
|
|
this.loadComplete = this.loadComplete.bind(this);
|
|
|
|
this.state = {
|
|
users: UserStore.getProfileListInTeam(TeamStore.getCurrentId(), true),
|
|
loadingDMChannel: -1,
|
|
listType: 'team',
|
|
loading: false,
|
|
search: false
|
|
};
|
|
}
|
|
|
|
componentDidMount() {
|
|
UserStore.addChangeListener(this.onChange);
|
|
UserStore.addInTeamChangeListener(this.onChange);
|
|
UserStore.addStatusesChangeListener(this.onChange);
|
|
TeamStore.addChangeListener(this.onChange);
|
|
|
|
AsyncClient.getProfiles(0, Constants.PROFILE_CHUNK_SIZE);
|
|
AsyncClient.getProfilesInTeam(TeamStore.getCurrentId(), 0, Constants.PROFILE_CHUNK_SIZE);
|
|
}
|
|
|
|
componentWillUnmount() {
|
|
UserStore.removeChangeListener(this.onChange);
|
|
UserStore.removeInTeamChangeListener(this.onChange);
|
|
UserStore.removeStatusesChangeListener(this.onChange);
|
|
TeamStore.removeChangeListener(this.onChange);
|
|
}
|
|
|
|
loadComplete() {
|
|
this.setState({loading: false});
|
|
}
|
|
|
|
handleHide() {
|
|
if (this.props.onModalDismissed) {
|
|
this.props.onModalDismissed();
|
|
}
|
|
}
|
|
|
|
handleExit() {
|
|
if (this.exitToDirectChannel) {
|
|
browserHistory.push(this.exitToDirectChannel);
|
|
}
|
|
}
|
|
|
|
handleShowDirectChannel(teammate, e) {
|
|
e.preventDefault();
|
|
|
|
if (this.state.loadingDMChannel !== -1) {
|
|
return;
|
|
}
|
|
|
|
this.setState({loadingDMChannel: teammate.id});
|
|
openDirectChannelToUser(
|
|
teammate,
|
|
(channel) => {
|
|
// Due to how react-overlays Modal handles focus, we delay pushing
|
|
// the new channel information until the modal is fully exited.
|
|
// The channel information will be pushed in `handleExit`
|
|
this.exitToDirectChannel = TeamStore.getCurrentTeamRelativeUrl() + '/channels/' + channel.name;
|
|
this.setState({loadingDMChannel: -1});
|
|
this.handleHide();
|
|
},
|
|
() => {
|
|
this.setState({loadingDMChannel: -1});
|
|
}
|
|
);
|
|
}
|
|
|
|
onChange(force) {
|
|
if (this.state.search && !force) {
|
|
return;
|
|
}
|
|
|
|
let users;
|
|
if (this.state.listType === 'any') {
|
|
users = UserStore.getProfileList();
|
|
} else {
|
|
users = UserStore.getProfileListInTeam(TeamStore.getCurrentId(), true);
|
|
}
|
|
|
|
this.setState({
|
|
users
|
|
});
|
|
}
|
|
|
|
toggleList(e) {
|
|
const listType = e.target.value;
|
|
let users;
|
|
if (listType === 'any') {
|
|
users = UserStore.getProfileList();
|
|
} else {
|
|
users = UserStore.getProfileListInTeam(TeamStore.getCurrentId(), true);
|
|
}
|
|
|
|
this.setState({
|
|
users,
|
|
listType
|
|
});
|
|
}
|
|
|
|
createJoinDirectChannelButton({user}) {
|
|
return (
|
|
<SpinnerButton
|
|
className='btn btm-sm btn-primary'
|
|
spinning={this.state.loadingDMChannel === user.id}
|
|
onClick={this.handleShowDirectChannel.bind(this, user)}
|
|
>
|
|
<FormattedMessage
|
|
id='more_direct_channels.message'
|
|
defaultMessage='Message'
|
|
/>
|
|
</SpinnerButton>
|
|
);
|
|
}
|
|
|
|
nextPage(page) {
|
|
if (this.state.listType === 'any') {
|
|
AsyncClient.getProfiles((page + 1) * USERS_PER_PAGE, USERS_PER_PAGE);
|
|
} else {
|
|
AsyncClient.getProfilesInTeam(TeamStore.getCurrentId(), (page + 1) * USERS_PER_PAGE, USERS_PER_PAGE);
|
|
}
|
|
}
|
|
|
|
search(term) {
|
|
if (term === '') {
|
|
this.onChange(true);
|
|
this.setState({search: false});
|
|
return;
|
|
}
|
|
|
|
let teamId;
|
|
if (this.state.listType === 'any') {
|
|
teamId = '';
|
|
} else {
|
|
teamId = TeamStore.getCurrentId();
|
|
}
|
|
|
|
searchUsers(
|
|
term,
|
|
teamId,
|
|
{},
|
|
(users) => {
|
|
for (let i = 0; i < users.length; i++) {
|
|
if (users[i].id === UserStore.getCurrentId()) {
|
|
users.splice(i, 1);
|
|
break;
|
|
}
|
|
}
|
|
this.setState({search: true, users});
|
|
}
|
|
);
|
|
}
|
|
|
|
render() {
|
|
let maxHeight = 1000;
|
|
if (Utils.windowHeight() <= 1200) {
|
|
maxHeight = Utils.windowHeight() - 300;
|
|
}
|
|
|
|
let teamToggle;
|
|
if (global.window.mm_config.RestrictDirectMessage === 'any') {
|
|
teamToggle = (
|
|
<div className='member-select__container'>
|
|
<select
|
|
className='form-control'
|
|
id='restrictList'
|
|
ref='restrictList'
|
|
defaultValue='team'
|
|
onChange={this.toggleList}
|
|
>
|
|
<option value='any'>
|
|
<FormattedMessage
|
|
id='filtered_user_list.any_team'
|
|
defaultMessage='All Users'
|
|
/>
|
|
</option>
|
|
<option value='team'>
|
|
<FormattedMessage
|
|
id='filtered_user_list.team_only'
|
|
defaultMessage='Members of this Team'
|
|
/>
|
|
</option>
|
|
</select>
|
|
<span
|
|
className='member-show'
|
|
>
|
|
<FormattedMessage
|
|
id='filtered_user_list.show'
|
|
defaultMessage='Filter:'
|
|
/>
|
|
</span>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
let users = this.state.users;
|
|
if (this.state.loading) {
|
|
users = null;
|
|
}
|
|
|
|
return (
|
|
<Modal
|
|
dialogClassName='more-modal more-direct-channels'
|
|
show={this.props.show}
|
|
onHide={this.handleHide}
|
|
onExited={this.handleExit}
|
|
>
|
|
<Modal.Header closeButton={true}>
|
|
<Modal.Title>
|
|
<FormattedMessage
|
|
id='more_direct_channels.title'
|
|
defaultMessage='Direct Messages'
|
|
/>
|
|
</Modal.Title>
|
|
</Modal.Header>
|
|
<Modal.Body>
|
|
{teamToggle}
|
|
<SearchableUserList
|
|
key={'moreDirectChannelsList_' + this.state.listType}
|
|
style={{maxHeight}}
|
|
users={users}
|
|
usersPerPage={USERS_PER_PAGE}
|
|
nextPage={this.nextPage}
|
|
search={this.search}
|
|
actions={[this.createJoinDirectChannelButton]}
|
|
/>
|
|
</Modal.Body>
|
|
<Modal.Footer>
|
|
<button
|
|
type='button'
|
|
className='btn btn-default'
|
|
onClick={this.handleHide}
|
|
>
|
|
<FormattedMessage
|
|
id='more_direct_channels.close'
|
|
defaultMessage='Close'
|
|
/>
|
|
</button>
|
|
</Modal.Footer>
|
|
</Modal>
|
|
);
|
|
}
|
|
}
|
|
|
|
MoreDirectChannels.propTypes = {
|
|
show: React.PropTypes.bool.isRequired,
|
|
onModalDismissed: React.PropTypes.func
|
|
};
|