summaryrefslogtreecommitdiffstats
path: root/webapp
diff options
context:
space:
mode:
authorJoram Wilander <jwawilander@gmail.com>2016-11-04 11:21:14 -0400
committerHarrison Healey <harrisonmhealey@gmail.com>2016-11-04 11:21:14 -0400
commite6f7a47c99075a39d862308659b904bfaf64a11a (patch)
tree863f6eb80a2367fb080437d9e037fca283e3c270 /webapp
parentdbdd719c51d061dfc327644d4b2ca89a0595b4f1 (diff)
downloadchat-e6f7a47c99075a39d862308659b904bfaf64a11a.tar.gz
chat-e6f7a47c99075a39d862308659b904bfaf64a11a.tar.bz2
chat-e6f7a47c99075a39d862308659b904bfaf64a11a.zip
PLT-4507 Don't mount modals until opened to make resetting state automatic (#4358)
* Don't mount modals until opened to make resetting state automatic * Move dimiss handler to be fired after modal exit animation complete
Diffstat (limited to 'webapp')
-rw-r--r--webapp/components/access_history_modal.jsx38
-rw-r--r--webapp/components/activity_log_modal.jsx38
-rw-r--r--webapp/components/channel_header.jsx36
-rw-r--r--webapp/components/channel_info_modal.jsx22
-rw-r--r--webapp/components/channel_invite_modal.jsx42
-rw-r--r--webapp/components/channel_members_modal.jsx49
-rw-r--r--webapp/components/channel_notifications_modal.jsx37
-rw-r--r--webapp/components/delete_channel_modal.jsx15
-rw-r--r--webapp/components/edit_channel_header_modal.jsx32
-rw-r--r--webapp/components/edit_channel_purpose_modal.jsx33
-rw-r--r--webapp/components/more_direct_channels.jsx15
-rw-r--r--webapp/components/navbar.jsx48
-rw-r--r--webapp/components/sidebar.jsx15
-rw-r--r--webapp/components/sidebar_header_dropdown.jsx16
-rw-r--r--webapp/components/sidebar_right_menu.jsx2
-rw-r--r--webapp/components/team_members_modal.jsx16
-rw-r--r--webapp/components/toggle_modal_button.jsx24
17 files changed, 233 insertions, 245 deletions
diff --git a/webapp/components/access_history_modal.jsx b/webapp/components/access_history_modal.jsx
index 9c49c3879..4ed2ad9ab 100644
--- a/webapp/components/access_history_modal.jsx
+++ b/webapp/components/access_history_modal.jsx
@@ -1,8 +1,6 @@
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
-import $ from 'jquery';
-import {Modal} from 'react-bootstrap';
import LoadingScreen from './loading_screen.jsx';
import AuditTable from './audit_table.jsx';
@@ -11,11 +9,13 @@ import UserStore from 'stores/user_store.jsx';
import * as AsyncClient from 'utils/async_client.jsx';
import * as Utils from 'utils/utils.jsx';
-import {intlShape, injectIntl, FormattedMessage} from 'react-intl';
-
+import $ from 'jquery';
import React from 'react';
-class AccessHistoryModal extends React.Component {
+import {Modal} from 'react-bootstrap';
+import {FormattedMessage} from 'react-intl';
+
+export default class AccessHistoryModal extends React.Component {
constructor(props) {
super(props);
@@ -25,45 +25,44 @@ class AccessHistoryModal extends React.Component {
const state = this.getStateFromStoresForAudits();
state.moreInfo = [];
+ state.show = true;
this.state = state;
}
+
getStateFromStoresForAudits() {
return {
audits: UserStore.getAudits()
};
}
+
onShow() {
AsyncClient.getAudits();
if (!Utils.isMobile()) {
$('.modal-body').perfectScrollbar();
}
}
+
onHide() {
- this.setState({moreInfo: []});
- this.props.onHide();
+ this.setState({show: false});
}
+
componentDidMount() {
UserStore.addAuditsChangeListener(this.onAuditChange);
-
- if (this.props.show) {
- this.onShow();
- }
- }
- componentDidUpdate(prevProps) {
- if (this.props.show && !prevProps.show) {
- this.onShow();
- }
+ this.onShow();
}
+
componentWillUnmount() {
UserStore.removeAuditsChangeListener(this.onAuditChange);
}
+
onAuditChange() {
var newState = this.getStateFromStoresForAudits();
if (!Utils.areObjectsEqual(newState.audits, this.state.audits)) {
this.setState(newState);
}
}
+
render() {
var content;
if (this.state.audits.loading) {
@@ -80,8 +79,9 @@ class AccessHistoryModal extends React.Component {
return (
<Modal
- show={this.props.show}
+ show={this.state.show}
onHide={this.onHide}
+ onExited={this.props.onHide}
bsSize='large'
>
<Modal.Header closeButton={true}>
@@ -101,9 +101,5 @@ class AccessHistoryModal extends React.Component {
}
AccessHistoryModal.propTypes = {
- intl: intlShape.isRequired,
- show: React.PropTypes.bool.isRequired,
onHide: React.PropTypes.func.isRequired
};
-
-export default injectIntl(AccessHistoryModal);
diff --git a/webapp/components/activity_log_modal.jsx b/webapp/components/activity_log_modal.jsx
index 2c093e1d2..b907668f0 100644
--- a/webapp/components/activity_log_modal.jsx
+++ b/webapp/components/activity_log_modal.jsx
@@ -1,17 +1,18 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
-import $ from 'jquery';
+import LoadingScreen from './loading_screen.jsx';
+
import UserStore from 'stores/user_store.jsx';
+
import Client from 'client/web_client.jsx';
import * as AsyncClient from 'utils/async_client.jsx';
-import {Modal} from 'react-bootstrap';
-import LoadingScreen from './loading_screen.jsx';
import * as Utils from 'utils/utils.jsx';
-import {FormattedMessage, FormattedTime, FormattedDate} from 'react-intl';
-
+import $ from 'jquery';
import React from 'react';
+import {Modal} from 'react-bootstrap';
+import {FormattedMessage, FormattedTime, FormattedDate} from 'react-intl';
export default class ActivityLogModal extends React.Component {
constructor(props) {
@@ -25,9 +26,11 @@ export default class ActivityLogModal extends React.Component {
const state = this.getStateFromStores();
state.moreInfo = [];
+ state.show = true;
this.state = state;
}
+
getStateFromStores() {
return {
sessions: UserStore.getSessions(),
@@ -35,6 +38,7 @@ export default class ActivityLogModal extends React.Component {
clientError: null
};
}
+
submitRevoke(altId, e) {
e.preventDefault();
var modalContent = $(e.target).closest('.modal-content');
@@ -53,42 +57,40 @@ export default class ActivityLogModal extends React.Component {
}
);
}
+
onShow() {
AsyncClient.getSessions();
if (!Utils.isMobile()) {
$('.modal-body').perfectScrollbar();
}
}
+
onHide() {
- this.setState({moreInfo: []});
- this.props.onHide();
+ this.setState({show: false});
}
+
componentDidMount() {
UserStore.addSessionsChangeListener(this.onListenerChange);
-
- if (this.props.show) {
- this.onShow();
- }
- }
- componentDidUpdate(prevProps) {
- if (this.props.show && !prevProps.show) {
- this.onShow();
- }
+ this.onShow();
}
+
componentWillUnmount() {
UserStore.removeSessionsChangeListener(this.onListenerChange);
}
+
onListenerChange() {
const newState = this.getStateFromStores();
if (!Utils.areObjectsEqual(newState.sessions, this.state.sessions)) {
this.setState(newState);
}
}
+
handleMoreInfo(index) {
const newMoreInfo = this.state.moreInfo;
newMoreInfo[index] = true;
this.setState({moreInfo: newMoreInfo});
}
+
render() {
const activityList = [];
@@ -263,8 +265,9 @@ export default class ActivityLogModal extends React.Component {
return (
<Modal
- show={this.props.show}
+ show={this.state.show}
onHide={this.onHide}
+ onExited={this.props.onHide}
bsSize='large'
>
<Modal.Header closeButton={true}>
@@ -290,6 +293,5 @@ export default class ActivityLogModal extends React.Component {
}
ActivityLogModal.propTypes = {
- show: React.PropTypes.bool.isRequired,
onHide: React.PropTypes.func.isRequired
};
diff --git a/webapp/components/channel_header.jsx b/webapp/components/channel_header.jsx
index c7842aaa3..dd0fd5b70 100644
--- a/webapp/components/channel_header.jsx
+++ b/webapp/components/channel_header.jsx
@@ -450,6 +450,7 @@ export default class ChannelHeader extends React.Component {
role='presentation'
>
<ToggleModalButton
+ ref='channelInviteModalButton'
role='menuitem'
dialogType={ChannelInviteModal}
dialogProps={{channel, currentUser: this.state.currentUser}}
@@ -662,6 +663,28 @@ export default class ChannelHeader extends React.Component {
</OverlayTrigger>
);
+ let channelMembersModal;
+ if (this.state.showMembersModal) {
+ channelMembersModal = (
+ <ChannelMembersModal
+ onModalDismissed={() => this.setState({showMembersModal: false})}
+ showInviteModal={() => this.refs.channelInviteModalButton.show()}
+ channel={channel}
+ isAdmin={isAdmin}
+ />
+ );
+ }
+
+ let editPurposeModal;
+ if (this.state.showEditChannelPurposeModal) {
+ editPurposeModal = (
+ <EditChannelPurposeModal
+ onModalDismissed={() => this.setState({showEditChannelPurposeModal: false})}
+ channel={channel}
+ />
+ );
+ }
+
return (
<div
id='channel-header'
@@ -753,17 +776,8 @@ export default class ChannelHeader extends React.Component {
</tr>
</tbody>
</table>
- <EditChannelPurposeModal
- show={this.state.showEditChannelPurposeModal}
- onModalDismissed={() => this.setState({showEditChannelPurposeModal: false})}
- channel={channel}
- />
- <ChannelMembersModal
- show={this.state.showMembersModal}
- onModalDismissed={() => this.setState({showMembersModal: false})}
- channel={channel}
- isAdmin={isAdmin}
- />
+ {editPurposeModal}
+ {channelMembersModal}
<RenameChannelModal
show={this.state.showRenameChannelModal}
onHide={this.hideRenameChannelModal}
diff --git a/webapp/components/channel_info_modal.jsx b/webapp/components/channel_info_modal.jsx
index 7e0ff3873..fce4b75db 100644
--- a/webapp/components/channel_info_modal.jsx
+++ b/webapp/components/channel_info_modal.jsx
@@ -11,16 +11,16 @@ import * as TextFormatting from 'utils/text_formatting.jsx';
import React from 'react';
export default class ChannelInfoModal extends React.Component {
- shouldComponentUpdate(nextProps) {
- if (nextProps.show !== this.props.show) {
- return true;
- }
+ constructor(props) {
+ super(props);
- if (!Utils.areObjectsEqual(nextProps.channel, this.props.channel)) {
- return true;
- }
+ this.onHide = this.onHide.bind(this);
+
+ this.state = {show: true};
+ }
- return false;
+ onHide() {
+ this.setState({show: false});
}
render() {
@@ -83,8 +83,9 @@ export default class ChannelInfoModal extends React.Component {
return (
<Modal
dialogClassName='about-modal'
- show={this.props.show}
- onHide={this.props.onHide}
+ show={this.state.show}
+ onHide={this.onHide}
+ onExited={this.props.onHide}
>
<Modal.Header closeButton={true}>
<Modal.Title>
@@ -123,7 +124,6 @@ export default class ChannelInfoModal extends React.Component {
}
ChannelInfoModal.propTypes = {
- show: React.PropTypes.bool.isRequired,
onHide: React.PropTypes.func.isRequired,
channel: React.PropTypes.object.isRequired
};
diff --git a/webapp/components/channel_invite_modal.jsx b/webapp/components/channel_invite_modal.jsx
index 576a33dc5..29607136c 100644
--- a/webapp/components/channel_invite_modal.jsx
+++ b/webapp/components/channel_invite_modal.jsx
@@ -26,6 +26,7 @@ export default class ChannelInviteModal extends React.Component {
this.onChange = this.onChange.bind(this);
this.onStatusChange = this.onStatusChange.bind(this);
+ this.onHide = this.onHide.bind(this);
this.handleInviteError = this.handleInviteError.bind(this);
this.nextPage = this.nextPage.bind(this);
this.search = this.search.bind(this);
@@ -36,34 +37,27 @@ export default class ChannelInviteModal extends React.Component {
const teamStats = TeamStore.getCurrentStats();
this.state = {
- users: [],
+ users: null,
total: teamStats.member_count - channelStats.member_count,
+ show: true,
search: false,
statusChange: false
};
}
- componentWillReceiveProps(nextProps) {
- if (!this.props.show && nextProps.show) {
- TeamStore.addStatsChangeListener(this.onChange);
- ChannelStore.addStatsChangeListener(this.onChange);
- UserStore.addNotInChannelChangeListener(this.onChange);
- UserStore.addStatusesChangeListener(this.onStatusChange);
-
- this.onChange();
- AsyncClient.getProfilesNotInChannel(this.props.channel.id, 0);
- AsyncClient.getTeamStats(TeamStore.getCurrentId());
- } else if (this.props.show && !nextProps.show) {
- TeamStore.removeStatsChangeListener(this.onChange);
- ChannelStore.removeStatsChangeListener(this.onChange);
- UserStore.removeNotInChannelChangeListener(this.onChange);
- UserStore.removeStatusesChangeListener(this.onStatusChange);
- }
+ componentDidMount() {
+ TeamStore.addStatsChangeListener(this.onChange);
+ ChannelStore.addStatsChangeListener(this.onChange);
+ UserStore.addNotInChannelChangeListener(this.onChange);
+ UserStore.addStatusesChangeListener(this.onStatusChange);
+
+ AsyncClient.getProfilesNotInChannel(this.props.channel.id, 0);
+ AsyncClient.getTeamStats(TeamStore.getCurrentId());
}
componentWillUnmount() {
+ TeamStore.removeStatsChangeListener(this.onChange);
ChannelStore.removeStatsChangeListener(this.onChange);
- ChannelStore.removeChangeListener(this.onChange);
UserStore.removeNotInChannelChangeListener(this.onChange);
UserStore.removeStatusesChangeListener(this.onStatusChange);
}
@@ -90,6 +84,10 @@ export default class ChannelInviteModal extends React.Component {
});
}
+ onHide() {
+ this.setState({show: false});
+ }
+
handleInviteError(err) {
if (err) {
this.setState({
@@ -159,8 +157,9 @@ export default class ChannelInviteModal extends React.Component {
return (
<Modal
dialogClassName='more-modal'
- show={this.props.show}
- onHide={this.props.onHide}
+ show={this.state.show}
+ onHide={this.onHide}
+ onExited={this.props.onHide}
>
<Modal.Header closeButton={true}>
<Modal.Title>
@@ -179,7 +178,7 @@ export default class ChannelInviteModal extends React.Component {
<button
type='button'
className='btn btn-default'
- onClick={this.props.onHide}
+ onClick={this.onHide}
>
<FormattedMessage
id='channel_invite.close'
@@ -193,7 +192,6 @@ export default class ChannelInviteModal extends React.Component {
}
ChannelInviteModal.propTypes = {
- show: React.PropTypes.bool.isRequired,
onHide: React.PropTypes.func.isRequired,
channel: React.PropTypes.object.isRequired
};
diff --git a/webapp/components/channel_members_modal.jsx b/webapp/components/channel_members_modal.jsx
index 75810cf05..85226fd02 100644
--- a/webapp/components/channel_members_modal.jsx
+++ b/webapp/components/channel_members_modal.jsx
@@ -3,7 +3,6 @@
import SearchableUserList from './searchable_user_list.jsx';
import LoadingScreen from './loading_screen.jsx';
-import ChannelInviteModal from './channel_invite_modal.jsx';
import UserStore from 'stores/user_store.jsx';
import ChannelStore from 'stores/channel_store.jsx';
@@ -28,6 +27,7 @@ export default class ChannelMembersModal extends React.Component {
this.onChange = this.onChange.bind(this);
this.onStatusChange = this.onStatusChange.bind(this);
+ this.onHide = this.onHide.bind(this);
this.handleRemove = this.handleRemove.bind(this);
this.createRemoveMemberButton = this.createRemoveMemberButton.bind(this);
this.search = this.search.bind(this);
@@ -40,25 +40,18 @@ export default class ChannelMembersModal extends React.Component {
this.state = {
users: [],
total: stats.member_count,
- showInviteModal: false,
+ show: true,
search: false,
statusChange: false
};
}
- componentWillReceiveProps(nextProps) {
- if (!this.props.show && nextProps.show) {
- ChannelStore.addStatsChangeListener(this.onChange);
- UserStore.addInChannelChangeListener(this.onChange);
- UserStore.addStatusesChangeListener(this.onStatusChange);
-
- this.onChange();
- AsyncClient.getProfilesInChannel(this.props.channel.id, 0);
- } else if (this.props.show && !nextProps.show) {
- ChannelStore.removeStatsChangeListener(this.onChange);
- UserStore.removeInChannelChangeListener(this.onChange);
- UserStore.removeStatusesChangeListener(this.onStatusChange);
- }
+ componentDidMount() {
+ ChannelStore.addStatsChangeListener(this.onChange);
+ UserStore.addInChannelChangeListener(this.onChange);
+ UserStore.addStatusesChangeListener(this.onStatusChange);
+
+ AsyncClient.getProfilesInChannel(this.props.channel.id, 0);
}
componentWillUnmount() {
@@ -87,6 +80,10 @@ export default class ChannelMembersModal extends React.Component {
});
}
+ onHide() {
+ this.setState({show: false});
+ }
+
handleRemove(user) {
const userId = user.id;
@@ -175,8 +172,9 @@ export default class ChannelMembersModal extends React.Component {
<div>
<Modal
dialogClassName='more-modal'
- show={this.props.show}
- onHide={this.props.onModalDismissed}
+ show={this.state.show}
+ onHide={this.onHide}
+ onExited={this.props.onModalDismissed}
>
<Modal.Header closeButton={true}>
<Modal.Title>
@@ -190,8 +188,8 @@ export default class ChannelMembersModal extends React.Component {
className='btn btn-md btn-primary'
href='#'
onClick={() => {
- this.setState({showInviteModal: true});
- this.props.onModalDismissed();
+ this.props.showInviteModal();
+ this.onHide();
}}
>
<FormattedMessage
@@ -209,7 +207,7 @@ export default class ChannelMembersModal extends React.Component {
<button
type='button'
className='btn btn-default'
- onClick={this.props.onModalDismissed}
+ onClick={this.onHide}
>
<FormattedMessage
id='channel_members_modal.close'
@@ -218,23 +216,14 @@ export default class ChannelMembersModal extends React.Component {
</button>
</Modal.Footer>
</Modal>
- <ChannelInviteModal
- show={this.state.showInviteModal}
- onHide={() => this.setState({showInviteModal: false})}
- channel={this.props.channel}
- />
</div>
);
}
}
-ChannelMembersModal.defaultProps = {
- show: false
-};
-
ChannelMembersModal.propTypes = {
- show: React.PropTypes.bool.isRequired,
onModalDismissed: React.PropTypes.func.isRequired,
+ showInviteModal: React.PropTypes.func.isRequired,
channel: React.PropTypes.object.isRequired,
isAdmin: React.PropTypes.bool.isRequired
};
diff --git a/webapp/components/channel_notifications_modal.jsx b/webapp/components/channel_notifications_modal.jsx
index 59ec40d84..ff6e69f70 100644
--- a/webapp/components/channel_notifications_modal.jsx
+++ b/webapp/components/channel_notifications_modal.jsx
@@ -1,23 +1,23 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
-import $ from 'jquery';
-import {Modal} from 'react-bootstrap';
-import SettingItemMin from './setting_item_min.jsx';
-import SettingItemMax from './setting_item_max.jsx';
+import SettingItemMin from 'components/setting_item_min.jsx';
+import SettingItemMax from 'components/setting_item_max.jsx';
import Client from 'client/web_client.jsx';
import ChannelStore from 'stores/channel_store.jsx';
-import {FormattedMessage} from 'react-intl';
-
+import $ from 'jquery';
import React from 'react';
+import {Modal} from 'react-bootstrap';
+import {FormattedMessage} from 'react-intl';
export default class ChannelNotificationsModal extends React.Component {
constructor(props) {
super(props);
this.updateSection = this.updateSection.bind(this);
+ this.onHide = this.onHide.bind(this);
this.handleSubmitNotifyLevel = this.handleSubmitNotifyLevel.bind(this);
this.handleUpdateNotifyLevel = this.handleUpdateNotifyLevel.bind(this);
@@ -29,24 +29,23 @@ export default class ChannelNotificationsModal extends React.Component {
this.state = {
activeSection: '',
- notifyLevel: '',
- unreadLevel: ''
+ show: true,
+ notifyLevel: props.channelMember.notify_props.desktop,
+ unreadLevel: props.channelMember.notify_props.mark_unread
};
}
+
updateSection(section) {
if ($('.section-max').length) {
$('.settings-modal .modal-body').scrollTop(0).perfectScrollbar('update');
}
this.setState({activeSection: section});
}
- componentWillReceiveProps(nextProps) {
- if (!this.props.show && nextProps.show) {
- this.setState({
- notifyLevel: nextProps.channelMember.notify_props.desktop,
- unreadLevel: nextProps.channelMember.notify_props.mark_unread
- });
- }
+
+ onHide() {
+ this.setState({show: false});
}
+
handleSubmitNotifyLevel() {
var channelId = this.props.channel.id;
var notifyLevel = this.state.notifyLevel;
@@ -75,9 +74,11 @@ export default class ChannelNotificationsModal extends React.Component {
}
);
}
+
handleUpdateNotifyLevel(notifyLevel) {
this.setState({notifyLevel});
}
+
createNotifyLevelSection(serverError) {
// Get glabal user setting for notifications
const globalNotifyLevel = this.props.currentUser.notify_props ? this.props.currentUser.notify_props.desktop : 'all';
@@ -380,9 +381,10 @@ export default class ChannelNotificationsModal extends React.Component {
return (
<Modal
- show={this.props.show}
+ show={this.state.show}
dialogClassName='settings-modal'
- onHide={this.props.onHide}
+ onHide={this.onHide}
+ onExited={this.props.onHide}
>
<Modal.Header closeButton={true}>
<Modal.Title>
@@ -417,7 +419,6 @@ export default class ChannelNotificationsModal extends React.Component {
}
ChannelNotificationsModal.propTypes = {
- show: React.PropTypes.bool.isRequired,
onHide: React.PropTypes.func.isRequired,
channel: React.PropTypes.object.isRequired,
channelMember: React.PropTypes.object.isRequired,
diff --git a/webapp/components/delete_channel_modal.jsx b/webapp/components/delete_channel_modal.jsx
index 7ad213395..1b642861a 100644
--- a/webapp/components/delete_channel_modal.jsx
+++ b/webapp/components/delete_channel_modal.jsx
@@ -20,6 +20,9 @@ export default class DeleteChannelModal extends React.Component {
super(props);
this.handleDelete = this.handleDelete.bind(this);
+ this.onHide = this.onHide.bind(this);
+
+ this.state = {show: true};
}
handleDelete() {
@@ -39,6 +42,10 @@ export default class DeleteChannelModal extends React.Component {
);
}
+ onHide() {
+ this.setState({show: false});
+ }
+
render() {
let channelTerm = (
<FormattedMessage
@@ -57,8 +64,9 @@ export default class DeleteChannelModal extends React.Component {
return (
<Modal
- show={this.props.show}
- onHide={this.props.onHide}
+ show={this.state.show}
+ onHide={this.onHide}
+ onExited={this.props.onHide}
>
<Modal.Header closeButton={true}>
<h4 className='modal-title'>
@@ -84,7 +92,7 @@ export default class DeleteChannelModal extends React.Component {
<button
type='button'
className='btn btn-default'
- onClick={this.props.onHide}
+ onClick={this.onHide}
>
<FormattedMessage
id='delete_channel.cancel'
@@ -109,7 +117,6 @@ export default class DeleteChannelModal extends React.Component {
}
DeleteChannelModal.propTypes = {
- show: React.PropTypes.bool.isRequired,
onHide: React.PropTypes.func.isRequired,
channel: React.PropTypes.object.isRequired
};
diff --git a/webapp/components/edit_channel_header_modal.jsx b/webapp/components/edit_channel_header_modal.jsx
index 6112668ba..490b9fb31 100644
--- a/webapp/components/edit_channel_header_modal.jsx
+++ b/webapp/components/edit_channel_header_modal.jsx
@@ -36,38 +36,21 @@ class EditChannelHeaderModal extends React.Component {
this.state = {
header: props.channel.header,
+ show: true,
serverError: '',
submitted: false
};
}
componentDidMount() {
- if (this.props.show) {
- this.onShow();
- }
-
PreferenceStore.addChangeListener(this.onPreferenceChange);
+ this.onShow();
}
componentWillUnmount() {
PreferenceStore.removeChangeListener(this.onPreferenceChange);
}
- componentWillReceiveProps(nextProps) {
- if (this.props.channel.header !== nextProps.channel.header && !this.props.show) {
- this.setState({
- header: nextProps.channel.header,
- submitted: false
- });
- }
- }
-
- componentDidUpdate(prevProps) {
- if (this.props.show && !prevProps.show) {
- this.onShow();
- }
- }
-
handleChange(e) {
this.setState({
header: e.target.value
@@ -110,12 +93,7 @@ class EditChannelHeaderModal extends React.Component {
}
onHide() {
- this.setState({
- serverError: '',
- header: this.props.channel.header
- });
-
- this.props.onHide();
+ this.setState({show: false});
}
handleKeyDown(e) {
@@ -156,8 +134,9 @@ class EditChannelHeaderModal extends React.Component {
return (
<Modal
- show={this.props.show}
+ show={this.state.show}
onHide={this.onHide}
+ onExited={this.props.onHide}
>
<Modal.Header closeButton={true}>
<Modal.Title>
@@ -213,7 +192,6 @@ class EditChannelHeaderModal extends React.Component {
EditChannelHeaderModal.propTypes = {
intl: intlShape.isRequired,
- show: React.PropTypes.bool.isRequired,
onHide: React.PropTypes.func.isRequired,
channel: React.PropTypes.object.isRequired
};
diff --git a/webapp/components/edit_channel_purpose_modal.jsx b/webapp/components/edit_channel_purpose_modal.jsx
index 31d8e1bbd..bfb4d181a 100644
--- a/webapp/components/edit_channel_purpose_modal.jsx
+++ b/webapp/components/edit_channel_purpose_modal.jsx
@@ -1,17 +1,16 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
-import $ from 'jquery';
-import ReactDOM from 'react-dom';
+import PreferenceStore from 'stores/preference_store.jsx';
+
import * as AsyncClient from 'utils/async_client.jsx';
import Client from 'client/web_client.jsx';
import Constants from 'utils/constants.jsx';
-import {FormattedMessage} from 'react-intl';
-import PreferenceStore from 'stores/preference_store.jsx';
-import {Modal} from 'react-bootstrap';
import * as Utils from 'utils/utils.jsx';
import React from 'react';
+import {Modal} from 'react-bootstrap';
+import {FormattedMessage} from 'react-intl';
export default class EditChannelPurposeModal extends React.Component {
constructor(props) {
@@ -26,30 +25,22 @@ export default class EditChannelPurposeModal extends React.Component {
this.state = {
serverError: '',
+ show: true,
submitted: false
};
}
componentDidMount() {
PreferenceStore.addChangeListener(this.onPreferenceChange);
+ Utils.placeCaretAtEnd(this.refs.purpose);
}
componentWillUnmount() {
PreferenceStore.removeChangeListener(this.onPreferenceChange);
}
- componentDidUpdate() {
- if (this.props.show) {
- $(ReactDOM.findDOMNode(this.refs.purpose)).focus();
- }
- }
-
handleHide() {
- this.setState({serverError: '', submitted: false});
-
- if (this.props.onModalDismissed) {
- this.props.onModalDismissed();
- }
+ this.setState({show: false});
}
onPreferenceChange() {
@@ -75,7 +66,7 @@ export default class EditChannelPurposeModal extends React.Component {
Client.updateChannelPurpose(
this.props.channel.id,
- ReactDOM.findDOMNode(this.refs.purpose).value.trim(),
+ this.refs.purpose.value.trim(),
() => {
AsyncClient.getChannel(this.props.channel.id);
@@ -92,10 +83,6 @@ export default class EditChannelPurposeModal extends React.Component {
}
render() {
- if (!this.props.show) {
- return null;
- }
-
let serverError = null;
if (this.state.serverError) {
serverError = (
@@ -145,8 +132,9 @@ export default class EditChannelPurposeModal extends React.Component {
<Modal
className='modal-edit-channel-purpose'
ref='modal'
- show={this.props.show}
+ show={this.state.show}
onHide={this.handleHide}
+ onExited={this.props.onModalDismissed}
>
<Modal.Header closeButton={true}>
<Modal.Title>
@@ -202,7 +190,6 @@ export default class EditChannelPurposeModal extends React.Component {
}
EditChannelPurposeModal.propTypes = {
- show: React.PropTypes.bool.isRequired,
channel: React.PropTypes.object,
onModalDismissed: React.PropTypes.func.isRequired
};
diff --git a/webapp/components/more_direct_channels.jsx b/webapp/components/more_direct_channels.jsx
index 7e57261b6..7c61d2f2e 100644
--- a/webapp/components/more_direct_channels.jsx
+++ b/webapp/components/more_direct_channels.jsx
@@ -34,13 +34,11 @@ export default class MoreDirectChannels extends React.Component {
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, true),
+ users: null,
loadingDMChannel: -1,
listType: 'team',
- loading: false,
search: false
};
}
@@ -62,10 +60,6 @@ export default class MoreDirectChannels extends React.Component {
TeamStore.removeChangeListener(this.onChange);
}
- loadComplete() {
- this.setState({loading: false});
- }
-
handleHide() {
if (this.props.onModalDismissed) {
this.props.onModalDismissed();
@@ -229,11 +223,6 @@ export default class MoreDirectChannels extends React.Component {
);
}
- let users = this.state.users;
- if (this.state.loading) {
- users = null;
- }
-
return (
<Modal
dialogClassName='more-modal more-direct-channels'
@@ -254,7 +243,7 @@ export default class MoreDirectChannels extends React.Component {
<SearchableUserList
key={'moreDirectChannelsList_' + this.state.listType}
style={{maxHeight}}
- users={users}
+ users={this.state.users}
usersPerPage={USERS_PER_PAGE}
nextPage={this.nextPage}
search={this.search}
diff --git a/webapp/components/navbar.jsx b/webapp/components/navbar.jsx
index 9852e0c59..9721ddee1 100644
--- a/webapp/components/navbar.jsx
+++ b/webapp/components/navbar.jsx
@@ -730,21 +730,23 @@ export default class Navbar extends React.Component {
);
}
- editChannelHeaderModal = (
- <EditChannelHeaderModal
- show={this.state.showEditChannelHeaderModal}
- onHide={() => this.setState({showEditChannelHeaderModal: false})}
- channel={channel}
- />
- );
+ if (this.state.showEditChannelHeaderModal) {
+ editChannelHeaderModal = (
+ <EditChannelHeaderModal
+ onHide={() => this.setState({showEditChannelHeaderModal: false})}
+ channel={channel}
+ />
+ );
+ }
- editChannelPurposeModal = (
- <EditChannelPurposeModal
- show={this.state.showEditChannelPurposeModal}
- onModalDismissed={() => this.setState({showEditChannelPurposeModal: false})}
- channel={channel}
- />
- );
+ if (this.state.showEditChannelPurposeModal) {
+ editChannelPurposeModal = (
+ <EditChannelPurposeModal
+ onModalDismissed={() => this.setState({showEditChannelPurposeModal: false})}
+ channel={channel}
+ />
+ );
+ }
renameChannelModal = (
<RenameChannelModal
@@ -754,14 +756,16 @@ export default class Navbar extends React.Component {
/>
);
- channelMembersModal = (
- <ChannelMembersModal
- show={this.state.showMembersModal}
- onModalDismissed={this.hideMembersModal}
- channel={channel}
- isAdmin={isAdmin}
- />
- );
+ if (this.state.showMembersModal) {
+ channelMembersModal = (
+ <ChannelMembersModal
+ show={true}
+ onModalDismissed={this.hideMembersModal}
+ channel={channel}
+ isAdmin={isAdmin}
+ />
+ );
+ }
channelSwitchModal = (
<ChannelSwitchModal
diff --git a/webapp/components/sidebar.jsx b/webapp/components/sidebar.jsx
index 21df429f7..08f89c2ff 100644
--- a/webapp/components/sidebar.jsx
+++ b/webapp/components/sidebar.jsx
@@ -715,6 +715,16 @@ export default class Sidebar extends React.Component {
}
}
+ let moreDirectChannelsModal;
+ if (this.state.showDirectChannelsModal) {
+ moreDirectChannelsModal = (
+ <MoreDirectChannels
+ show={true}
+ onModalDismissed={this.hideMoreDirectChannelsModal}
+ />
+ );
+ }
+
return (
<div
className='sidebar--left'
@@ -726,10 +736,7 @@ export default class Sidebar extends React.Component {
channelType={this.state.newChannelModalType}
onModalDismissed={this.hideNewChannelModal}
/>
- <MoreDirectChannels
- show={this.state.showDirectChannelsModal}
- onModalDismissed={this.hideMoreDirectChannelsModal}
- />
+ {moreDirectChannelsModal}
<SidebarHeader
teamDisplayName={this.state.currentTeam.display_name}
diff --git a/webapp/components/sidebar_header_dropdown.jsx b/webapp/components/sidebar_header_dropdown.jsx
index d3d2979d5..b665eef52 100644
--- a/webapp/components/sidebar_header_dropdown.jsx
+++ b/webapp/components/sidebar_header_dropdown.jsx
@@ -437,6 +437,16 @@ export default class SidebarHeaderDropdown extends React.Component {
);
}
+ let teamMembersModal;
+ if (this.state.showTeamMembersModal) {
+ teamMembersModal = (
+ <TeamMembersModal
+ onHide={this.hideTeamMembersModal}
+ isAdmin={isAdmin}
+ />
+ );
+ }
+
return (
<Dropdown
open={this.state.showDropdown}
@@ -508,11 +518,7 @@ export default class SidebarHeaderDropdown extends React.Component {
show={this.state.showUserSettingsModal}
onModalDismissed={() => this.setState({showUserSettingsModal: false})}
/>
- <TeamMembersModal
- show={this.state.showTeamMembersModal}
- onHide={this.hideTeamMembersModal}
- isAdmin={isAdmin}
- />
+ {teamMembersModal}
<AboutBuildModal
show={this.state.showAboutModal}
onModalDismissed={this.aboutModalDismissed}
diff --git a/webapp/components/sidebar_right_menu.jsx b/webapp/components/sidebar_right_menu.jsx
index a11869cc2..86026967a 100644
--- a/webapp/components/sidebar_right_menu.jsx
+++ b/webapp/components/sidebar_right_menu.jsx
@@ -1,7 +1,7 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
-import AppDispatcher from '../dispatcher/app_dispatcher.jsx';
+import AppDispatcher from 'dispatcher/app_dispatcher.jsx';
import TeamMembersModal from './team_members_modal.jsx';
import ToggleModalButton from './toggle_modal_button.jsx';
import UserSettingsModal from './user_settings/user_settings_modal.jsx';
diff --git a/webapp/components/team_members_modal.jsx b/webapp/components/team_members_modal.jsx
index e41268805..76ffafe27 100644
--- a/webapp/components/team_members_modal.jsx
+++ b/webapp/components/team_members_modal.jsx
@@ -16,9 +16,11 @@ export default class TeamMembersModal extends React.Component {
super(props);
this.teamChanged = this.teamChanged.bind(this);
+ this.onHide = this.onHide.bind(this);
this.state = {
- team: TeamStore.getCurrent()
+ team: TeamStore.getCurrent(),
+ show: true
};
}
@@ -34,6 +36,10 @@ export default class TeamMembersModal extends React.Component {
this.setState({team: TeamStore.getCurrent()});
}
+ onHide() {
+ this.setState({show: false});
+ }
+
render() {
let teamDisplayName = '';
if (this.state.team) {
@@ -48,8 +54,9 @@ export default class TeamMembersModal extends React.Component {
return (
<Modal
dialogClassName='more-modal'
- show={this.props.show}
- onHide={this.props.onHide}
+ show={this.state.show}
+ onHide={this.onHide}
+ onExited={this.props.onHide}
>
<Modal.Header closeButton={true}>
<Modal.Title>
@@ -72,7 +79,7 @@ export default class TeamMembersModal extends React.Component {
<button
type='button'
className='btn btn-default'
- onClick={this.props.onHide}
+ onClick={this.onHide}
>
<FormattedMessage
id='team_member_modal.close'
@@ -86,7 +93,6 @@ export default class TeamMembersModal extends React.Component {
}
TeamMembersModal.propTypes = {
- show: React.PropTypes.bool.isRequired,
onHide: React.PropTypes.func.isRequired,
isAdmin: React.PropTypes.bool.isRequired
};
diff --git a/webapp/components/toggle_modal_button.jsx b/webapp/components/toggle_modal_button.jsx
index 6082901de..304ba386c 100644
--- a/webapp/components/toggle_modal_button.jsx
+++ b/webapp/components/toggle_modal_button.jsx
@@ -16,7 +16,9 @@ export default class ModalToggleButton extends React.Component {
}
show(e) {
- e.preventDefault();
+ if (e) {
+ e.preventDefault();
+ }
this.setState({show: true});
}
@@ -37,17 +39,19 @@ export default class ModalToggleButton extends React.Component {
};
}
- // this assumes that all modals will have a show property and an onHide event
- const dialog = React.createElement(dialogType, Object.assign({}, dialogProps, {
- show: this.state.show,
- onHide: () => {
- this.hide();
+ let dialog;
+ if (this.state.show) {
+ // this assumes that all modals will have an onHide event and will show when mounted
+ dialog = React.createElement(dialogType, Object.assign({}, dialogProps, {
+ onHide: () => {
+ this.hide();
- if (dialogProps.onHide) {
- dialogProps.onHide();
+ if (dialogProps.onHide) {
+ dialogProps.onHide();
+ }
}
- }
- }));
+ }));
+ }
// nesting the dialog in the anchor tag looks like it shouldn't work, but it does due to how react-bootstrap
// renders modals at the top level of the DOM instead of where you specify in the virtual DOM