Merge pull request #1287 from hmhealey/plt382

PLT-382 Refactored some modals to use React-Bootstrap and added a confirmation when discarding theme changes
Этот коммит содержится в:
Christopher Speller
2015-11-04 12:59:41 -05:00
родитель 2840c317e5 a7ceba2e57
Коммит aee6d9b608
24 изменённых файлов: 637 добавлений и 449 удалений

Просмотреть файл

@@ -1,6 +1,7 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information. // See License.txt for license information.
var Modal = ReactBootstrap.Modal;
var UserStore = require('../stores/user_store.jsx'); var UserStore = require('../stores/user_store.jsx');
var ChannelStore = require('../stores/channel_store.jsx'); var ChannelStore = require('../stores/channel_store.jsx');
var AsyncClient = require('../utils/async_client.jsx'); var AsyncClient = require('../utils/async_client.jsx');
@@ -30,16 +31,23 @@ export default class AccessHistoryModal extends React.Component {
} }
onShow() { onShow() {
AsyncClient.getAudits(); AsyncClient.getAudits();
$(ReactDOM.findDOMNode(this.refs.modalBody)).css('max-height', $(window).height() - 300);
if ($(window).width() > 768) {
$(ReactDOM.findDOMNode(this.refs.modalBody)).perfectScrollbar();
}
} }
onHide() { onHide() {
$('#user_settings').modal('show');
this.setState({moreInfo: []}); this.setState({moreInfo: []});
this.props.onModalDismissed();
} }
componentDidMount() { componentDidMount() {
UserStore.addAuditsChangeListener(this.onAuditChange); UserStore.addAuditsChangeListener(this.onAuditChange);
$(ReactDOM.findDOMNode(this.refs.modal)).on('shown.bs.modal', this.onShow); }
componentDidUpdate(prevProps) {
$(ReactDOM.findDOMNode(this.refs.modal)).on('hidden.bs.modal', this.onHide); if (this.props.show && !prevProps.show) {
this.onShow();
}
} }
componentWillUnmount() { componentWillUnmount() {
UserStore.removeAuditsChangeListener(this.onAuditChange); UserStore.removeAuditsChangeListener(this.onAuditChange);
@@ -380,43 +388,23 @@ export default class AccessHistoryModal extends React.Component {
} }
return ( return (
<div> <Modal
<div show={this.props.show}
className='modal fade' onHide={this.onHide}
ref='modal' bsSize='large'
id='access-history' >
tabIndex='-1' <Modal.Header closeButton={true}>
role='dialog' <Modal.Title>{'Access History'}</Modal.Title>
aria-hidden='true' </Modal.Header>
> <Modal.Body ref='modalBody'>
<div className='modal-dialog modal-lg'> {content}
<div className='modal-content'> </Modal.Body>
<div className='modal-header'> </Modal>
<button
type='button'
className='close'
data-dismiss='modal'
aria-label='Close'
>
<span aria-hidden='true'>{'×'}</span>
</button>
<h4
className='modal-title'
id='myModalLabel'
>
{'Access History'}
</h4>
</div>
<div
ref='modalBody'
className='modal-body'
>
{content}
</div>
</div>
</div>
</div>
</div>
); );
} }
} }
AccessHistoryModal.propTypes = {
show: React.PropTypes.bool.isRequired,
onModalDismissed: React.PropTypes.func.isRequired
};

Просмотреть файл

@@ -4,6 +4,7 @@
const UserStore = require('../stores/user_store.jsx'); const UserStore = require('../stores/user_store.jsx');
const Client = require('../utils/client.jsx'); const Client = require('../utils/client.jsx');
const AsyncClient = require('../utils/async_client.jsx'); const AsyncClient = require('../utils/async_client.jsx');
const Modal = ReactBootstrap.Modal;
const LoadingScreen = require('./loading_screen.jsx'); const LoadingScreen = require('./loading_screen.jsx');
const Utils = require('../utils/utils.jsx'); const Utils = require('../utils/utils.jsx');
@@ -49,16 +50,23 @@ export default class ActivityLogModal extends React.Component {
} }
onShow() { onShow() {
AsyncClient.getSessions(); AsyncClient.getSessions();
$(ReactDOM.findDOMNode(this.refs.modalBody)).css('max-height', $(window).height() - 300);
if ($(window).width() > 768) {
$(ReactDOM.findDOMNode(this.refs.modalBody)).perfectScrollbar();
}
} }
onHide() { onHide() {
$('#user_settings').modal('show');
this.setState({moreInfo: []}); this.setState({moreInfo: []});
this.props.onModalDismissed();
} }
componentDidMount() { componentDidMount() {
UserStore.addSessionsChangeListener(this.onListenerChange); UserStore.addSessionsChangeListener(this.onListenerChange);
$(ReactDOM.findDOMNode(this.refs.modal)).on('shown.bs.modal', this.onShow); }
componentDidUpdate(prevProps) {
$(ReactDOM.findDOMNode(this.refs.modal)).on('hidden.bs.modal', this.onHide); if (this.props.show && !prevProps.show) {
this.onShow();
}
} }
componentWillUnmount() { componentWillUnmount() {
UserStore.removeSessionsChangeListener(this.onListenerChange); UserStore.removeSessionsChangeListener(this.onListenerChange);
@@ -151,44 +159,24 @@ export default class ActivityLogModal extends React.Component {
} }
return ( return (
<div> <Modal
<div show={this.props.show}
className='modal fade' onHide={this.onHide}
ref='modal' bsSize='large'
id='activity-log' >
tabIndex='-1' <Modal.Header closeButton={true}>
role='dialog' <Modal.Title>{'Active Sessions'}</Modal.Title>
aria-hidden='true' </Modal.Header>
> <p className='session-help-text'>{'Sessions are created when you log in with your email and password to a new browser on a device. Sessions let you use Mattermost for up to 30 days without having to log in again. If you want to log out sooner, use the \'Logout\' button below to end a session.'}</p>
<div className='modal-dialog modal-lg'> <Modal.Body ref='modalBody'>
<div className='modal-content'> {content}
<div className='modal-header'> </Modal.Body>
<button </Modal>
type='button'
className='close'
data-dismiss='modal'
aria-label='Close'
>
<span aria-hidden='true'>&times;</span>
</button>
<h4
className='modal-title'
id='myModalLabel'
>
Active Sessions
</h4>
</div>
<p className='session-help-text'>Sessions are created when you log in with your email and password to a new browser on a device. Sessions let you use Mattermost for up to 30 days without having to log in again. If you want to log out sooner, use the 'Logout' button below to end a session.</p>
<div
ref='modalBody'
className='modal-body'
>
{content}
</div>
</div>
</div>
</div>
</div>
); );
} }
} }
ActivityLogModal.propTypes = {
show: React.PropTypes.bool.isRequired,
onModalDismissed: React.PropTypes.func.isRequired
};

Просмотреть файл

@@ -1,70 +1,63 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information. // See License.txt for license information.
const Modal = ReactBootstrap.Modal;
export default class ConfirmModal extends React.Component { export default class ConfirmModal extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.handleConfirm = this.handleConfirm.bind(this); this.handleConfirm = this.handleConfirm.bind(this);
}
this.state = {};
}
handleConfirm() { handleConfirm() {
$('#' + this.props.parent_id).attr('data-confirm', 'true'); this.props.onConfirm();
$('#' + this.props.parent_id).modal('hide');
$('#' + this.props.id).modal('hide');
} }
render() { render() {
return ( return (
<div <Modal
className='modal fade' className='modal-confirm'
id={this.props.id} show={this.props.show}
tabIndex='-1' onHide={this.props.onCancel}
role='dialog'
aria-hidden='true'
> >
<div className='modal-dialog'> <Modal.Header closeButton={false}>
<div className='modal-content'> <Modal.Title>{this.props.title}</Modal.Title>
<div className='modal-header'> </Modal.Header>
<h4 className='modal-title'>{this.props.title}</h4> <Modal.Body>
</div> {this.props.message}
<div className='modal-body'> </Modal.Body>
{this.props.message} <Modal.Footer>
</div> <button
<div className='modal-footer'> type='button'
<button className='btn btn-default'
type='button' onClick={this.props.onCancel}
className='btn btn-default' >
data-dismiss='modal' {'Cancel'}
> </button>
Cancel <button
</button> type='button'
<button className='btn btn-primary'
onClick={this.handleConfirm} onClick={this.props.onConfirm}
type='button' >
className='btn btn-primary' {this.props.confirm_button}
> </button>
{this.props.confirm_button} </Modal.Footer>
</button> </Modal>
</div>
</div>
</div>
</div>
); );
} }
} }
ConfirmModal.defaultProps = { ConfirmModal.defaultProps = {
parent_id: '',
id: '',
title: '', title: '',
message: '', message: '',
confirm_button: '' confirm_button: ''
}; };
ConfirmModal.propTypes = { ConfirmModal.propTypes = {
parent_id: React.PropTypes.string, show: React.PropTypes.bool.isRequired,
id: React.PropTypes.string,
title: React.PropTypes.string, title: React.PropTypes.string,
message: React.PropTypes.string, message: React.PropTypes.string,
confirm_button: React.PropTypes.string confirm_button: React.PropTypes.string,
onConfirm: React.PropTypes.func.isRequired,
onCancel: React.PropTypes.func.isRequired
}; };

Просмотреть файл

@@ -2,55 +2,50 @@
// See License.txt for license information. // See License.txt for license information.
var utils = require('../utils/utils.jsx'); var utils = require('../utils/utils.jsx');
var ActionTypes = require('../utils/constants.jsx').ActionTypes;
var AppDispatcher = require('../dispatcher/app_dispatcher.jsx');
var Client = require('../utils/client.jsx'); var Client = require('../utils/client.jsx');
var ModalStore = require('../stores/modal_store.jsx');
var UserStore = require('../stores/user_store.jsx'); var UserStore = require('../stores/user_store.jsx');
var TeamStore = require('../stores/team_store.jsx'); var TeamStore = require('../stores/team_store.jsx');
var ConfirmModal = require('./confirm_modal.jsx'); var ConfirmModal = require('./confirm_modal.jsx');
const Modal = ReactBootstrap.Modal;
export default class InviteMemberModal extends React.Component { export default class InviteMemberModal extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.handleToggle = this.handleToggle.bind(this);
this.handleSubmit = this.handleSubmit.bind(this); this.handleSubmit = this.handleSubmit.bind(this);
this.handleHide = this.handleHide.bind(this);
this.addInviteFields = this.addInviteFields.bind(this); this.addInviteFields = this.addInviteFields.bind(this);
this.clearFields = this.clearFields.bind(this); this.clearFields = this.clearFields.bind(this);
this.removeInviteFields = this.removeInviteFields.bind(this); this.removeInviteFields = this.removeInviteFields.bind(this);
this.state = { this.state = {
show: false,
inviteIds: [0], inviteIds: [0],
idCount: 0, idCount: 0,
emailErrors: {}, emailErrors: {},
firstNameErrors: {}, firstNameErrors: {},
lastNameErrors: {}, lastNameErrors: {},
emailEnabled: global.window.mm_config.SendEmailNotifications === 'true' emailEnabled: global.window.mm_config.SendEmailNotifications === 'true',
showConfirmModal: false
}; };
} }
componentDidMount() { componentDidMount() {
var self = this; ModalStore.addModalListener(ActionTypes.TOGGLE_INVITE_MEMBER_MODAL, this.handleToggle);
$('#invite_member').on('hide.bs.modal', function hide(e) { }
if ($('#invite_member').attr('data-confirm') === 'true') {
$('#invite_member').attr('data-confirm', 'false');
return;
}
var notEmpty = false; componentWillUnmount() {
for (var i = 0; i < self.state.inviteIds.length; i++) { ModalStore.removeModalListener(ActionTypes.TOGGLE_INVITE_MEMBER_MODAL, this.handleToggle);
var index = self.state.inviteIds[i]; }
if (ReactDOM.findDOMNode(self.refs['email' + index]).value.trim() !== '') {
notEmpty = true;
break;
}
}
if (notEmpty) { handleToggle(value) {
$('#confirm_invite_modal').modal('show'); this.setState({
e.preventDefault(); show: value
}
});
$('#invite_member').on('hidden.bs.modal', function show() {
self.clearFields();
}); });
} }
@@ -94,25 +89,57 @@ export default class InviteMemberModal extends React.Component {
var data = {}; var data = {};
data.invites = invites; data.invites = invites;
Client.inviteMembers(data, Client.inviteMembers(
function success() { data,
$(ReactDOM.findDOMNode(this.refs.modal)).attr('data-confirm', 'true'); () => {
$(ReactDOM.findDOMNode(this.refs.modal)).modal('hide'); this.handleHide(false);
}.bind(this), },
function fail(err) { (err) => {
if (err.message === 'This person is already on your team') { if (err.message === 'This person is already on your team') {
emailErrors[err.detailed_error] = err.message; emailErrors[err.detailed_error] = err.message;
this.setState({emailErrors: emailErrors}); this.setState({emailErrors: emailErrors});
} else { } else {
this.setState({serverError: err.message}); this.setState({serverError: err.message});
} }
}.bind(this) }
); );
} }
componentDidUpdate() { handleHide(requireConfirm) {
$(ReactDOM.findDOMNode(this.refs.modalBody)).css('max-height', $(window).height() - 200); if (requireConfirm) {
$(ReactDOM.findDOMNode(this.refs.modalBody)).css('overflow-y', 'scroll'); var notEmpty = false;
for (var i = 0; i < this.state.inviteIds.length; i++) {
var index = this.state.inviteIds[i];
if (ReactDOM.findDOMNode(this.refs['email' + index]).value.trim() !== '') {
notEmpty = true;
break;
}
}
if (notEmpty) {
this.setState({
showConfirmModal: true
});
return;
}
}
this.clearFields();
this.setState({
show: false,
showConfirmModal: false
});
}
componentDidUpdate(prevProps, prevState) {
if (!prevState.show && this.state.show) {
$(ReactDOM.findDOMNode(this.refs.modalBody)).css('max-height', $(window).height() - 300);
if ($(window).width() > 768) {
$(ReactDOM.findDOMNode(this.refs.modalBody)).perfectScrollbar();
}
}
} }
addInviteFields() { addInviteFields() {
@@ -292,7 +319,7 @@ export default class InviteMemberModal extends React.Component {
); );
} else { } else {
var teamInviteLink = null; var teamInviteLink = null;
if (currentUser && this.props.teamType === 'O') { if (currentUser && TeamStore.getCurrent().type === 'O') {
var linkUrl = utils.getWindowLocationOrigin() + '/signup_user_complete/?id=' + TeamStore.getCurrent().invite_id; var linkUrl = utils.getWindowLocationOrigin() + '/signup_user_complete/?id=' + TeamStore.getCurrent().invite_id;
var link = var link =
( (
@@ -302,11 +329,7 @@ export default class InviteMemberModal extends React.Component {
data-target='#get_link' data-target='#get_link'
data-title='Team Invite' data-title='Team Invite'
data-value={linkUrl} data-value={linkUrl}
onClick={ onClick={() => this.handleHide(this, false)}
function click() {
$('#invite_member').modal('hide');
}
}
>Team Invite Link</a> >Team Invite Link</a>
); );
@@ -327,64 +350,54 @@ export default class InviteMemberModal extends React.Component {
return ( return (
<div> <div>
<div <Modal
className='modal fade' className='modal-invite-member'
ref='modal' show={this.state.show}
id='invite_member' onHide={this.handleHide.bind(this, true)}
tabIndex='-1' enforceFocus={!this.state.showConfirmModal}
role='dialog'
aria-hidden='true'
> >
<div className='modal-dialog'> <Modal.Header closeButton={true}>
<div className='modal-content'> <Modal.Title>{'Invite New Member'}</Modal.Title>
<div className='modal-header'> </Modal.Header>
<Modal.Body ref='modalBody'>
<form role='form'>
{inviteSections}
</form>
{content}
</Modal.Body>
<Modal.Footer>
<button <button
type='button' type='button'
className='close' className='btn btn-default'
data-dismiss='modal' onClick={this.handleHide.bind(this, true)}
aria-label='Close'
> >
<span aria-hidden='true'>×</span> {'Cancel'}
</button> </button>
<h4 {sendButton}
className='modal-title' </Modal.Footer>
id='myModalLabel' </Modal>
>Invite New Member</h4>
</div>
<div
ref='modalBody'
className='modal-body'
>
<form role='form'>
{inviteSections}
</form>
{content}
</div>
<div className='modal-footer'>
<button
type='button'
className='btn btn-default'
data-dismiss='modal'
>Cancel</button>
{sendButton}
</div>
</div>
</div>
</div>
<ConfirmModal <ConfirmModal
id='confirm_invite_modal'
parent_id='invite_member'
title='Discard Invitations?' title='Discard Invitations?'
message='You have unsent invitations, are you sure you want to discard them?' message='You have unsent invitations, are you sure you want to discard them?'
confirm_button='Yes, Discard' confirm_button='Yes, Discard'
show={this.state.showConfirmModal}
onConfirm={this.handleHide.bind(this, false)}
onCancel={() => this.setState({showConfirmModal: false})}
/> />
</div> </div>
); );
} }
return <div/>;
return null;
}
static show() {
AppDispatcher.handleViewAction({
type: ActionTypes.TOGGLE_INVITE_MEMBER_MODAL,
value: true
});
} }
} }
InviteMemberModal.propTypes = { InviteMemberModal.propTypes = {
teamType: React.PropTypes.string
}; };

Просмотреть файл

@@ -7,6 +7,8 @@ var UserStore = require('../stores/user_store.jsx');
var TeamStore = require('../stores/team_store.jsx'); var TeamStore = require('../stores/team_store.jsx');
var AboutBuildModal = require('./about_build_modal.jsx'); var AboutBuildModal = require('./about_build_modal.jsx');
var InviteMemberModal = require('./invite_member_modal.jsx');
var UserSettingsModal = require('./user_settings/user_settings_modal.jsx');
var Constants = require('../utils/constants.jsx'); var Constants = require('../utils/constants.jsx');
@@ -33,7 +35,10 @@ export default class NavbarDropdown extends React.Component {
this.onListenerChange = this.onListenerChange.bind(this); this.onListenerChange = this.onListenerChange.bind(this);
this.aboutModalDismissed = this.aboutModalDismissed.bind(this); this.aboutModalDismissed = this.aboutModalDismissed.bind(this);
this.state = getStateFromStores(); const state = getStateFromStores();
state.showUserSettingsModal = false;
state.showAboutModal = false;
this.state = state;
} }
handleLogoutClick(e) { handleLogoutClick(e) {
e.preventDefault(); e.preventDefault();
@@ -88,8 +93,7 @@ export default class NavbarDropdown extends React.Component {
<li> <li>
<a <a
href='#' href='#'
data-toggle='modal' onClick={InviteMemberModal.show}
data-target='#invite_member'
> >
{'Invite New Member'} {'Invite New Member'}
</a> </a>
@@ -210,8 +214,7 @@ export default class NavbarDropdown extends React.Component {
<li> <li>
<a <a
href='#' href='#'
data-toggle='modal' onClick={() => this.setState({showUserSettingsModal: true})}
data-target='#user_settings'
> >
{'Account Settings'} {'Account Settings'}
</a> </a>
@@ -256,6 +259,10 @@ export default class NavbarDropdown extends React.Component {
{'About Mattermost'} {'About Mattermost'}
</a> </a>
</li> </li>
<UserSettingsModal
show={this.state.showUserSettingsModal}
onModalDismissed={() => this.setState({showUserSettingsModal: false})}
/>
<AboutBuildModal <AboutBuildModal
show={this.state.showAboutModal} show={this.state.showAboutModal}
onModalDismissed={this.aboutModalDismissed} onModalDismissed={this.aboutModalDismissed}

Просмотреть файл

@@ -1,6 +1,8 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information. // See License.txt for license information.
var InviteMemberModal = require('./invite_member_modal.jsx');
var UserSettingsModal = require('./user_settings/user_settings_modal.jsx');
var UserStore = require('../stores/user_store.jsx'); var UserStore = require('../stores/user_store.jsx');
var TeamStore = require('../stores/team_store.jsx'); var TeamStore = require('../stores/team_store.jsx');
var client = require('../utils/client.jsx'); var client = require('../utils/client.jsx');
@@ -15,6 +17,10 @@ export default class SidebarRightMenu extends React.Component {
super(props); super(props);
this.handleLogoutClick = this.handleLogoutClick.bind(this); this.handleLogoutClick = this.handleLogoutClick.bind(this);
this.state = {
showUserSettingsModal: false
};
} }
handleLogoutClick(e) { handleLogoutClick(e) {
@@ -38,10 +44,12 @@ export default class SidebarRightMenu extends React.Component {
inviteLink = ( inviteLink = (
<li> <li>
<a href='#' <a
data-toggle='modal' href='#'
data-target='#invite_member' onClick={InviteMemberModal.show}
><i className='glyphicon glyphicon-user'></i>Invite New Member</a> >
<i className='glyphicon glyphicon-user'></i>Invite New Member
</a>
</li> </li>
); );
@@ -115,9 +123,11 @@ export default class SidebarRightMenu extends React.Component {
<li> <li>
<a <a
href='#' href='#'
data-toggle='modal' onClick={() => this.setState({showUserSettingsModal: true})}
data-target='#user_settings' >
><i className='glyphicon glyphicon-cog'></i>Account Settings</a></li> <i className='glyphicon glyphicon-cog'></i>Account Settings
</a>
</li>
{teamSettingsLink} {teamSettingsLink}
{inviteLink} {inviteLink}
{teamLink} {teamLink}
@@ -141,6 +151,10 @@ export default class SidebarRightMenu extends React.Component {
><i className='glyphicon glyphicon-earphone'></i>Report a Problem</a></li> ><i className='glyphicon glyphicon-earphone'></i>Report a Problem</a></li>
</ul> </ul>
</div> </div>
<UserSettingsModal
show={this.state.showUserSettingsModal}
onModalDismissed={() => this.setState({showUserSettingsModal: false})}
/>
</div> </div>
); );
} }

Просмотреть файл

@@ -17,11 +17,13 @@ export default class TeamSettingsModal extends React.Component {
}; };
} }
componentDidMount() { componentDidMount() {
$('body').on('click', '.modal-back', function handleBackClick() { const modal = $(ReactDOM.findDOMNode(this.refs.modal));
modal.on('click', '.modal-back', function handleBackClick() {
$(this).closest('.modal-dialog').removeClass('display--content'); $(this).closest('.modal-dialog').removeClass('display--content');
$(this).closest('.modal-dialog').find('.settings-table .nav li.active').removeClass('active'); $(this).closest('.modal-dialog').find('.settings-table .nav li.active').removeClass('active');
}); });
$('body').on('click', '.modal-header .close', () => { modal.on('click', '.modal-header .close', () => {
setTimeout(() => { setTimeout(() => {
$('.modal-dialog.display--content').removeClass('display--content'); $('.modal-dialog.display--content').removeClass('display--content');
}, 500); }, 500);

Просмотреть файл

@@ -1,6 +1,7 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information. // See License.txt for license information.
const ModalStore = require('../../stores/modal_store.jsx');
const UserStore = require('../../stores/user_store.jsx'); const UserStore = require('../../stores/user_store.jsx');
const Utils = require('../../utils/utils.jsx'); const Utils = require('../../utils/utils.jsx');
const Client = require('../../utils/client.jsx'); const Client = require('../../utils/client.jsx');
@@ -24,10 +25,10 @@ export default class ImportThemeModal extends React.Component {
}; };
} }
componentDidMount() { componentDidMount() {
UserStore.addImportModalListener(this.updateShow); ModalStore.addModalListener(ActionTypes.TOGGLE_IMPORT_THEME_MODAL, this.updateShow);
} }
componentWillUnmount() { componentWillUnmount() {
UserStore.removeImportModalListener(this.updateShow); ModalStore.removeModalListener(ActionTypes.TOGGLE_IMPORT_THEME_MODAL, this.updateShow);
} }
updateShow(show) { updateShow(show) {
this.setState({show}); this.setState({show});
@@ -74,7 +75,6 @@ export default class ImportThemeModal extends React.Component {
this.setState({show: false}); this.setState({show: false});
Utils.applyTheme(theme); Utils.applyTheme(theme);
$('#user_settings').modal('show');
}, },
(err) => { (err) => {
var state = this.getStateFromStores(); var state = this.getStateFromStores();

Просмотреть файл

@@ -16,6 +16,7 @@ export default class UserSettings extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.getActiveTab = this.getActiveTab.bind(this);
this.onListenerChange = this.onListenerChange.bind(this); this.onListenerChange = this.onListenerChange.bind(this);
this.state = {user: UserStore.getCurrentUser()}; this.state = {user: UserStore.getCurrentUser()};
@@ -29,10 +30,14 @@ export default class UserSettings extends React.Component {
UserStore.removeChangeListener(this.onListenerChange); UserStore.removeChangeListener(this.onListenerChange);
} }
getActiveTab() {
return this.refs.activeTab;
}
onListenerChange() { onListenerChange() {
var user = UserStore.getCurrentUser(); var user = UserStore.getCurrentUser();
if (!utils.areStatesEqual(this.state.user, user)) { if (!utils.areStatesEqual(this.state.user, user)) {
this.setState({user: user}); this.setState({user});
} }
} }
@@ -41,10 +46,13 @@ export default class UserSettings extends React.Component {
return ( return (
<div> <div>
<GeneralTab <GeneralTab
ref='activeTab'
user={this.state.user} user={this.state.user}
activeSection={this.props.activeSection} activeSection={this.props.activeSection}
updateSection={this.props.updateSection} updateSection={this.props.updateSection}
updateTab={this.props.updateTab} updateTab={this.props.updateTab}
closeModal={this.props.closeModal}
collapseModal={this.props.collapseModal}
/> />
</div> </div>
); );
@@ -52,10 +60,14 @@ export default class UserSettings extends React.Component {
return ( return (
<div> <div>
<SecurityTab <SecurityTab
ref='activeTab'
user={this.state.user} user={this.state.user}
activeSection={this.props.activeSection} activeSection={this.props.activeSection}
updateSection={this.props.updateSection} updateSection={this.props.updateSection}
updateTab={this.props.updateTab} updateTab={this.props.updateTab}
closeModal={this.props.closeModal}
collapseModal={this.props.collapseModal}
setEnforceFocus={this.props.setEnforceFocus}
/> />
</div> </div>
); );
@@ -63,10 +75,13 @@ export default class UserSettings extends React.Component {
return ( return (
<div> <div>
<NotificationsTab <NotificationsTab
ref='activeTab'
user={this.state.user} user={this.state.user}
activeSection={this.props.activeSection} activeSection={this.props.activeSection}
updateSection={this.props.updateSection} updateSection={this.props.updateSection}
updateTab={this.props.updateTab} updateTab={this.props.updateTab}
closeModal={this.props.closeModal}
collapseModal={this.props.collapseModal}
/> />
</div> </div>
); );
@@ -74,9 +89,14 @@ export default class UserSettings extends React.Component {
return ( return (
<div> <div>
<AppearanceTab <AppearanceTab
ref='activeTab'
activeSection={this.props.activeSection} activeSection={this.props.activeSection}
updateSection={this.props.updateSection} updateSection={this.props.updateSection}
updateTab={this.props.updateTab} updateTab={this.props.updateTab}
closeModal={this.props.closeModal}
collapseModal={this.props.collapseModal}
setEnforceFocus={this.props.setEnforceFocus}
setRequireConfirm={this.props.setRequireConfirm}
/> />
</div> </div>
); );
@@ -84,8 +104,11 @@ export default class UserSettings extends React.Component {
return ( return (
<div> <div>
<DeveloperTab <DeveloperTab
ref='activeTab'
activeSection={this.props.activeSection} activeSection={this.props.activeSection}
updateSection={this.props.updateSection} updateSection={this.props.updateSection}
closeModal={this.props.closeModal}
collapseModal={this.props.collapseModal}
/> />
</div> </div>
); );
@@ -93,10 +116,13 @@ export default class UserSettings extends React.Component {
return ( return (
<div> <div>
<IntegrationsTab <IntegrationsTab
ref='activeTab'
user={this.state.user} user={this.state.user}
activeSection={this.props.activeSection} activeSection={this.props.activeSection}
updateSection={this.props.updateSection} updateSection={this.props.updateSection}
updateTab={this.props.updateTab} updateTab={this.props.updateTab}
closeModal={this.props.closeModal}
collapseModal={this.props.collapseModal}
/> />
</div> </div>
); );
@@ -104,10 +130,13 @@ export default class UserSettings extends React.Component {
return ( return (
<div> <div>
<DisplayTab <DisplayTab
ref='activeTab'
user={this.state.user} user={this.state.user}
activeSection={this.props.activeSection} activeSection={this.props.activeSection}
updateSection={this.props.updateSection} updateSection={this.props.updateSection}
updateTab={this.props.updateTab} updateTab={this.props.updateTab}
closeModal={this.props.closeModal}
collapseModal={this.props.collapseModal}
/> />
</div> </div>
); );
@@ -115,10 +144,13 @@ export default class UserSettings extends React.Component {
return ( return (
<div> <div>
<AdvancedTab <AdvancedTab
ref='activeTab'
user={this.state.user} user={this.state.user}
activeSection={this.props.activeSection} activeSection={this.props.activeSection}
updateSection={this.props.updateSection} updateSection={this.props.updateSection}
updateTab={this.props.updateTab} updateTab={this.props.updateTab}
closeModal={this.props.closeModal}
collapseModal={this.props.collapseModal}
/> />
</div> </div>
); );
@@ -132,5 +164,9 @@ UserSettings.propTypes = {
activeTab: React.PropTypes.string, activeTab: React.PropTypes.string,
activeSection: React.PropTypes.string, activeSection: React.PropTypes.string,
updateSection: React.PropTypes.func, updateSection: React.PropTypes.func,
updateTab: React.PropTypes.func updateTab: React.PropTypes.func,
closeModal: React.PropTypes.func.isRequired,
collapseModal: React.PropTypes.func.isRequired,
setEnforceFocus: React.PropTypes.func.isRequired,
setRequireConfirm: React.PropTypes.func.isRequired
}; };

Просмотреть файл

@@ -13,7 +13,6 @@ export default class AdvancedSettingsDisplay extends React.Component {
this.updateSection = this.updateSection.bind(this); this.updateSection = this.updateSection.bind(this);
this.updateSetting = this.updateSetting.bind(this); this.updateSetting = this.updateSetting.bind(this);
this.handleClose = this.handleClose.bind(this);
this.setupInitialState = this.setupInitialState.bind(this); this.setupInitialState = this.setupInitialState.bind(this);
this.state = this.setupInitialState(); this.state = this.setupInitialState();
@@ -59,18 +58,6 @@ export default class AdvancedSettingsDisplay extends React.Component {
this.props.updateSection(section); this.props.updateSection(section);
} }
handleClose() {
this.updateSection('');
}
componentDidMount() {
$('#user_settings').on('hidden.bs.modal', this.handleClose);
}
componentWillUnmount() {
$('#user_settings').off('hidden.bs.modal', this.handleClose);
}
render() { render() {
const serverError = this.state.serverError || null; const serverError = this.state.serverError || null;
let ctrlSendSection; let ctrlSendSection;
@@ -139,6 +126,7 @@ export default class AdvancedSettingsDisplay extends React.Component {
className='close' className='close'
data-dismiss='modal' data-dismiss='modal'
aria-label='Close' aria-label='Close'
onClick={this.props.closeModal}
> >
<span aria-hidden='true'>{'×'}</span> <span aria-hidden='true'>{'×'}</span>
</button> </button>
@@ -146,7 +134,10 @@ export default class AdvancedSettingsDisplay extends React.Component {
className='modal-title' className='modal-title'
ref='title' ref='title'
> >
<i className='modal-back'></i> <i
className='modal-back'
onClick={this.props.collapseModal}
/>
{'Advanced Settings'} {'Advanced Settings'}
</h4> </h4>
</div> </div>
@@ -165,5 +156,7 @@ AdvancedSettingsDisplay.propTypes = {
user: React.PropTypes.object, user: React.PropTypes.object,
updateSection: React.PropTypes.func, updateSection: React.PropTypes.func,
updateTab: React.PropTypes.func, updateTab: React.PropTypes.func,
activeSection: React.PropTypes.string activeSection: React.PropTypes.string,
closeModal: React.PropTypes.func.isRequired,
collapseModal: React.PropTypes.func.isRequired
}; };

Просмотреть файл

@@ -20,13 +20,13 @@ export default class UserSettingsAppearance extends React.Component {
this.submitTheme = this.submitTheme.bind(this); this.submitTheme = this.submitTheme.bind(this);
this.updateTheme = this.updateTheme.bind(this); this.updateTheme = this.updateTheme.bind(this);
this.updateCodeTheme = this.updateCodeTheme.bind(this); this.updateCodeTheme = this.updateCodeTheme.bind(this);
this.handleClose = this.handleClose.bind(this); this.deactivate = this.deactivate.bind(this);
this.resetFields = this.resetFields.bind(this);
this.handleImportModal = this.handleImportModal.bind(this); this.handleImportModal = this.handleImportModal.bind(this);
this.state = this.getStateFromStores(); this.state = this.getStateFromStores();
this.originalTheme = this.state.theme; this.originalTheme = Object.assign({}, this.state.theme);
this.originalCodeTheme = this.state.theme.codeTheme;
} }
componentDidMount() { componentDidMount() {
UserStore.addChangeListener(this.onChange); UserStore.addChangeListener(this.onChange);
@@ -34,7 +34,6 @@ export default class UserSettingsAppearance extends React.Component {
if (this.props.activeSection === 'theme') { if (this.props.activeSection === 'theme') {
$(ReactDOM.findDOMNode(this.refs[this.state.theme])).addClass('active-border'); $(ReactDOM.findDOMNode(this.refs[this.state.theme])).addClass('active-border');
} }
$('#user_settings').on('hidden.bs.modal', this.handleClose);
} }
componentDidUpdate() { componentDidUpdate() {
if (this.props.activeSection === 'theme') { if (this.props.activeSection === 'theme') {
@@ -44,14 +43,13 @@ export default class UserSettingsAppearance extends React.Component {
} }
componentWillUnmount() { componentWillUnmount() {
UserStore.removeChangeListener(this.onChange); UserStore.removeChangeListener(this.onChange);
$('#user_settings').off('hidden.bs.modal', this.handleClose);
} }
getStateFromStores() { getStateFromStores() {
const user = UserStore.getCurrentUser(); const user = UserStore.getCurrentUser();
let theme = null; let theme = null;
if ($.isPlainObject(user.theme_props) && !$.isEmptyObject(user.theme_props)) { if ($.isPlainObject(user.theme_props) && !$.isEmptyObject(user.theme_props)) {
theme = user.theme_props; theme = Object.assign({}, user.theme_props);
} else { } else {
theme = $.extend(true, {}, Constants.THEMES.default); theme = $.extend(true, {}, Constants.THEMES.default);
} }
@@ -73,6 +71,8 @@ export default class UserSettingsAppearance extends React.Component {
if (!Utils.areStatesEqual(this.state, newState)) { if (!Utils.areStatesEqual(this.state, newState)) {
this.setState(newState); this.setState(newState);
} }
this.props.setEnforceFocus(true);
} }
submitTheme(e) { submitTheme(e) {
e.preventDefault(); e.preventDefault();
@@ -86,11 +86,11 @@ export default class UserSettingsAppearance extends React.Component {
me: data me: data
}); });
$('#user_settings').off('hidden.bs.modal', this.handleClose); this.props.setRequireConfirm(false);
this.props.updateTab('general'); this.originalTheme = Object.assign({}, this.state.theme);
$('.ps-container.modal-body').scrollTop(0); $('.ps-container.modal-body').scrollTop(0);
$('.ps-container.modal-body').perfectScrollbar('update'); $('.ps-container.modal-body').perfectScrollbar('update');
$('#user_settings').modal('hide');
}, },
(err) => { (err) => {
var state = this.getStateFromStores(); var state = this.getStateFromStores();
@@ -103,37 +103,53 @@ export default class UserSettingsAppearance extends React.Component {
if (!theme.codeTheme) { if (!theme.codeTheme) {
theme.codeTheme = this.state.theme.codeTheme; theme.codeTheme = this.state.theme.codeTheme;
} }
let themeChanged = this.state.theme.length === theme.length;
if (!themeChanged) {
for (const field in theme) {
if (theme.hasOwnProperty(field)) {
if (this.state.theme[field] !== theme[field]) {
themeChanged = true;
break;
}
}
}
}
this.props.setRequireConfirm(themeChanged);
this.setState({theme}); this.setState({theme});
Utils.applyTheme(theme); Utils.applyTheme(theme);
} }
updateCodeTheme(codeTheme) { updateCodeTheme(codeTheme) {
var theme = this.state.theme; var theme = this.state.theme;
theme.codeTheme = codeTheme; theme.codeTheme = codeTheme;
this.setState({theme}); this.updateTheme(theme);
Utils.applyTheme(theme);
} }
updateType(type) { updateType(type) {
this.setState({type}); this.setState({type});
} }
handleClose() { deactivate() {
const state = this.getStateFromStores();
Utils.applyTheme(state.theme);
}
resetFields() {
const state = this.getStateFromStores(); const state = this.getStateFromStores();
state.serverError = null; state.serverError = null;
state.theme.codeTheme = this.originalCodeTheme; this.setState(state);
Utils.applyTheme(state.theme); Utils.applyTheme(state.theme);
this.setState(state); this.props.setRequireConfirm(false);
$('.ps-container.modal-body').scrollTop(0);
$('.ps-container.modal-body').perfectScrollbar('update');
$('#user_settings').modal('hide');
} }
handleImportModal() { handleImportModal() {
$('#user_settings').modal('hide');
AppDispatcher.handleViewAction({ AppDispatcher.handleViewAction({
type: ActionTypes.TOGGLE_IMPORT_THEME_MODAL, type: ActionTypes.TOGGLE_IMPORT_THEME_MODAL,
value: true value: true
}); });
this.props.setEnforceFocus(false);
} }
render() { render() {
var serverError; var serverError;
@@ -204,7 +220,7 @@ export default class UserSettingsAppearance extends React.Component {
<a <a
className='btn btn-sm theme' className='btn btn-sm theme'
href='#' href='#'
onClick={this.handleClose} onClick={this.resetFields}
> >
{'Cancel'} {'Cancel'}
</a> </a>
@@ -218,8 +234,8 @@ export default class UserSettingsAppearance extends React.Component {
<button <button
type='button' type='button'
className='close' className='close'
data-dismiss='modal'
aria-label='Close' aria-label='Close'
onClick={this.props.closeModal}
> >
<span aria-hidden='true'>{'×'}</span> <span aria-hidden='true'>{'×'}</span>
</button> </button>
@@ -227,7 +243,11 @@ export default class UserSettingsAppearance extends React.Component {
className='modal-title' className='modal-title'
ref='title' ref='title'
> >
<i className='modal-back'></i>{'Appearance Settings'} <i
className='modal-back'
onClick={this.props.collapseModal}
/>
{'Appearance Settings'}
</h4> </h4>
</div> </div>
<div className='user-settings'> <div className='user-settings'>
@@ -253,5 +273,9 @@ UserSettingsAppearance.defaultProps = {
}; };
UserSettingsAppearance.propTypes = { UserSettingsAppearance.propTypes = {
activeSection: React.PropTypes.string, activeSection: React.PropTypes.string,
updateTab: React.PropTypes.func updateTab: React.PropTypes.func,
closeModal: React.PropTypes.func.isRequired,
collapseModal: React.PropTypes.func.isRequired,
setRequireConfirm: React.PropTypes.func.isRequired,
setEnforceFocus: React.PropTypes.func.isRequired
}; };

Просмотреть файл

@@ -63,6 +63,7 @@ export default class DeveloperTab extends React.Component {
className='close' className='close'
data-dismiss='modal' data-dismiss='modal'
aria-label='Close' aria-label='Close'
onClick={this.props.closeModal}
> >
<span aria-hidden='true'>{'×'}</span> <span aria-hidden='true'>{'×'}</span>
</button> </button>
@@ -70,7 +71,11 @@ export default class DeveloperTab extends React.Component {
className='modal-title' className='modal-title'
ref='title' ref='title'
> >
<i className='modal-back'></i>{'Developer Settings'} <i
className='modal-back'
onClick={this.props.collapseModal}
/>
{'Developer Settings'}
</h4> </h4>
</div> </div>
<div className='user-settings'> <div className='user-settings'>
@@ -89,5 +94,7 @@ DeveloperTab.defaultProps = {
}; };
DeveloperTab.propTypes = { DeveloperTab.propTypes = {
activeSection: React.PropTypes.string, activeSection: React.PropTypes.string,
updateSection: React.PropTypes.func updateSection: React.PropTypes.func,
closeModal: React.PropTypes.func.isRequired,
collapseModal: React.PropTypes.func.isRequired
}; };

Просмотреть файл

@@ -25,7 +25,6 @@ export default class UserSettingsDisplay extends React.Component {
this.handleClockRadio = this.handleClockRadio.bind(this); this.handleClockRadio = this.handleClockRadio.bind(this);
this.handleNameRadio = this.handleNameRadio.bind(this); this.handleNameRadio = this.handleNameRadio.bind(this);
this.updateSection = this.updateSection.bind(this); this.updateSection = this.updateSection.bind(this);
this.handleClose = this.handleClose.bind(this);
this.state = getDisplayStateFromStores(); this.state = getDisplayStateFromStores();
} }
@@ -53,15 +52,6 @@ export default class UserSettingsDisplay extends React.Component {
this.setState(getDisplayStateFromStores()); this.setState(getDisplayStateFromStores());
this.props.updateSection(section); this.props.updateSection(section);
} }
handleClose() {
this.updateSection('');
}
componentDidMount() {
$('#user_settings').on('hidden.bs.modal', this.handleClose);
}
componentWillUnmount() {
$('#user_settings').off('hidden.bs.modal', this.handleClose);
}
render() { render() {
const serverError = this.state.serverError || null; const serverError = this.state.serverError || null;
let clockSection; let clockSection;
@@ -227,6 +217,7 @@ export default class UserSettingsDisplay extends React.Component {
className='close' className='close'
data-dismiss='modal' data-dismiss='modal'
aria-label='Close' aria-label='Close'
onClick={this.props.closeModal}
> >
<span aria-hidden='true'>{'×'}</span> <span aria-hidden='true'>{'×'}</span>
</button> </button>
@@ -234,7 +225,10 @@ export default class UserSettingsDisplay extends React.Component {
className='modal-title' className='modal-title'
ref='title' ref='title'
> >
<i className='modal-back'></i> <i
className='modal-back'
onClick={this.props.collapseModal}
/>
{'Display Settings'} {'Display Settings'}
</h4> </h4>
</div> </div>
@@ -255,5 +249,7 @@ UserSettingsDisplay.propTypes = {
user: React.PropTypes.object, user: React.PropTypes.object,
updateSection: React.PropTypes.func, updateSection: React.PropTypes.func,
updateTab: React.PropTypes.func, updateTab: React.PropTypes.func,
activeSection: React.PropTypes.string activeSection: React.PropTypes.string,
closeModal: React.PropTypes.func.isRequired,
collapseModal: React.PropTypes.func.isRequired
}; };

Просмотреть файл

@@ -32,7 +32,6 @@ export default class UserSettingsGeneralTab extends React.Component {
this.updatePicture = this.updatePicture.bind(this); this.updatePicture = this.updatePicture.bind(this);
this.updateSection = this.updateSection.bind(this); this.updateSection = this.updateSection.bind(this);
this.handleClose = this.handleClose.bind(this);
this.setupInitialState = this.setupInitialState.bind(this); this.setupInitialState = this.setupInitialState.bind(this);
this.state = this.setupInitialState(props); this.state = this.setupInitialState(props);
@@ -210,20 +209,6 @@ export default class UserSettingsGeneralTab extends React.Component {
this.submitActive = false; this.submitActive = false;
this.props.updateSection(section); this.props.updateSection(section);
} }
handleClose() {
$(ReactDOM.findDOMNode(this)).find('.form-control').each(function clearForms() {
this.value = '';
});
this.setState(assign({}, this.setupInitialState(this.props), {clientError: null, serverError: null, emailError: null}));
this.props.updateSection('');
}
componentDidMount() {
$('#user_settings').on('hidden.bs.modal', this.handleClose);
}
componentWillUnmount() {
$('#user_settings').off('hidden.bs.modal', this.handleClose);
}
setupInitialState(props) { setupInitialState(props) {
var user = props.user; var user = props.user;
@@ -579,6 +564,7 @@ export default class UserSettingsGeneralTab extends React.Component {
className='close' className='close'
data-dismiss='modal' data-dismiss='modal'
aria-label='Close' aria-label='Close'
onClick={this.props.closeModal}
> >
<span aria-hidden='true'>{'×'}</span> <span aria-hidden='true'>{'×'}</span>
</button> </button>
@@ -586,7 +572,10 @@ export default class UserSettingsGeneralTab extends React.Component {
className='modal-title' className='modal-title'
ref='title' ref='title'
> >
<i className='modal-back'></i> <i
className='modal-back'
onClick={this.props.collapseModal}
/>
{'General Settings'} {'General Settings'}
</h4> </h4>
</div> </div>
@@ -613,5 +602,7 @@ UserSettingsGeneralTab.propTypes = {
user: React.PropTypes.object, user: React.PropTypes.object,
updateSection: React.PropTypes.func, updateSection: React.PropTypes.func,
updateTab: React.PropTypes.func, updateTab: React.PropTypes.func,
activeSection: React.PropTypes.string activeSection: React.PropTypes.string,
closeModal: React.PropTypes.func.isRequired,
collapseModal: React.PropTypes.func.isRequired
}; };

Просмотреть файл

@@ -11,24 +11,12 @@ export default class UserSettingsIntegrationsTab extends React.Component {
super(props); super(props);
this.updateSection = this.updateSection.bind(this); this.updateSection = this.updateSection.bind(this);
this.handleClose = this.handleClose.bind(this);
this.state = {}; this.state = {};
} }
updateSection(section) { updateSection(section) {
this.props.updateSection(section); this.props.updateSection(section);
} }
handleClose() {
this.updateSection('');
$('.ps-container.modal-body').scrollTop(0);
$('.ps-container.modal-body').perfectScrollbar('update');
}
componentDidMount() {
$('#user_settings').on('hidden.bs.modal', this.handleClose);
}
componentWillUnmount() {
$('#user_settings').off('hidden.bs.modal', this.handleClose);
}
render() { render() {
let incomingHooksSection; let incomingHooksSection;
let outgoingHooksSection; let outgoingHooksSection;
@@ -104,6 +92,7 @@ export default class UserSettingsIntegrationsTab extends React.Component {
className='close' className='close'
data-dismiss='modal' data-dismiss='modal'
aria-label='Close' aria-label='Close'
onClick={this.props.closeModal}
> >
<span aria-hidden='true'>{'×'}</span> <span aria-hidden='true'>{'×'}</span>
</button> </button>
@@ -111,7 +100,10 @@ export default class UserSettingsIntegrationsTab extends React.Component {
className='modal-title' className='modal-title'
ref='title' ref='title'
> >
<i className='modal-back'></i> <i
className='modal-back'
onClick={this.props.collapseModal}
/>
{'Integration Settings'} {'Integration Settings'}
</h4> </h4>
</div> </div>
@@ -132,5 +124,7 @@ UserSettingsIntegrationsTab.propTypes = {
user: React.PropTypes.object, user: React.PropTypes.object,
updateSection: React.PropTypes.func, updateSection: React.PropTypes.func,
updateTab: React.PropTypes.func, updateTab: React.PropTypes.func,
activeSection: React.PropTypes.string activeSection: React.PropTypes.string,
closeModal: React.PropTypes.func.isRequired,
collapseModal: React.PropTypes.func.isRequired
}; };

Просмотреть файл

@@ -1,34 +1,161 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information. // See License.txt for license information.
var SettingsSidebar = require('../settings_sidebar.jsx'); const ConfirmModal = require('../confirm_modal.jsx');
var UserSettings = require('./user_settings.jsx'); const Modal = ReactBootstrap.Modal;
const SettingsSidebar = require('../settings_sidebar.jsx');
const UserSettings = require('./user_settings.jsx');
export default class UserSettingsModal extends React.Component { export default class UserSettingsModal extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.handleHide = this.handleHide.bind(this);
this.handleHidden = this.handleHidden.bind(this);
this.handleCollapse = this.handleCollapse.bind(this);
this.handleConfirm = this.handleConfirm.bind(this);
this.handleCancelConfirmation = this.handleCancelConfirmation.bind(this);
this.deactivateTab = this.deactivateTab.bind(this);
this.closeModal = this.closeModal.bind(this);
this.collapseModal = this.collapseModal.bind(this);
this.updateTab = this.updateTab.bind(this); this.updateTab = this.updateTab.bind(this);
this.updateSection = this.updateSection.bind(this); this.updateSection = this.updateSection.bind(this);
this.state = {active_tab: 'general', active_section: ''}; this.state = {
active_tab: 'general',
active_section: '',
showConfirmModal: false,
enforceFocus: true
};
this.requireConfirm = false;
} }
componentDidMount() {
$('body').on('click', '.modal-back', function changeDisplay() { componentDidUpdate(prevProps) {
$(this).closest('.modal-dialog').removeClass('display--content'); if (!prevProps.show && this.props.show) {
}); $(ReactDOM.findDOMNode(this.refs.modalBody)).css('max-height', $(window).height() - 300);
$('body').on('click', '.modal-header .close', () => { if ($(window).width() > 768) {
setTimeout(() => { $(ReactDOM.findDOMNode(this.refs.modalBody)).perfectScrollbar();
$('.modal-dialog.display--content').removeClass('display--content'); }
}, 500); }
}
// Called when the close button is pressed on the main modal
handleHide() {
if (this.requireConfirm) {
this.afterConfirm = () => this.handleHide();
this.showConfirmModal();
return false;
}
this.deactivateTab();
this.props.onModalDismissed();
}
// called after the dialog is fully hidden and faded out
handleHidden() {
this.setState({
active_tab: 'general',
active_section: ''
}); });
} }
updateTab(tab) {
this.setState({active_tab: tab}); // Called to hide the settings pane when on mobile
handleCollapse() {
$(ReactDOM.findDOMNode(this.refs.modalBody)).closest('.modal-dialog').removeClass('display--content');
this.deactivateTab();
this.setState({
active_tab: '',
active_section: ''
});
} }
updateSection(section) {
this.setState({active_section: section}); handleConfirm() {
this.setState({
showConfirmModal: false,
enforceFocus: true
});
this.requireConfirm = false;
if (this.afterConfirm) {
this.afterConfirm();
this.afterConfirm = null;
}
} }
handleCancelConfirmation() {
this.setState({
showConfirmModal: false,
enforceFocus: true
});
this.afterConfirm = null;
}
showConfirmModal(afterConfirm) {
this.setState({
showConfirmModal: true,
enforceFocus: false
});
if (afterConfirm) {
this.afterConfirm = afterConfirm;
}
}
// Called to let settings tab perform cleanup before being closed
deactivateTab() {
const activeTab = this.refs.userSettings.getActiveTab();
if (activeTab && activeTab.deactivate) {
activeTab.deactivate();
}
}
// Called by settings tabs when their close button is pressed
closeModal() {
if (this.requireConfirm) {
this.showConfirmModal(this.closeModal);
} else {
this.handleHide();
}
}
// Called by settings tabs when their back button is pressed
collapseModal() {
if (this.requireConfirm) {
this.showConfirmModal(this.collapseModal);
} else {
this.handleCollapse();
}
}
updateTab(tab, skipConfirm) {
if (!skipConfirm && this.requireConfirm) {
this.showConfirmModal(() => this.updateTab(tab, true));
} else {
this.deactivateTab();
this.setState({
active_tab: tab,
active_section: ''
});
}
}
updateSection(section, skipConfirm) {
if (!skipConfirm && this.requireConfirm) {
this.showConfirmModal(() => this.updateSection(section, true));
} else {
this.setState({active_section: section});
}
}
render() { render() {
var tabs = []; var tabs = [];
tabs.push({name: 'general', uiName: 'General', icon: 'glyphicon glyphicon-cog'}); tabs.push({name: 'general', uiName: 'General', icon: 'glyphicon glyphicon-cog'});
@@ -46,33 +173,17 @@ export default class UserSettingsModal extends React.Component {
tabs.push({name: 'advanced', uiName: 'Advanced', icon: 'glyphicon glyphicon-list-alt'}); tabs.push({name: 'advanced', uiName: 'Advanced', icon: 'glyphicon glyphicon-list-alt'});
return ( return (
<div <Modal
className='modal fade' dialogClassName='settings-modal'
ref='modal' show={this.props.show}
id='user_settings' onHide={this.handleHide}
role='dialog' onExited={this.handleHidden}
tabIndex='-1' enforceFocus={this.state.enforceFocus}
aria-hidden='true'
> >
<div className='modal-dialog settings-modal'> <Modal.Header closeButton={true}>
<div className='modal-content'> <Modal.Title>{'Account Settings'}</Modal.Title>
<div className='modal-header'> </Modal.Header>
<button <Modal.Body ref='modalBody'>
type='button'
className='close'
data-dismiss='modal'
aria-label='Close'
>
<span aria-hidden='true'>{'×'}</span>
</button>
<h4
className='modal-title'
ref='title'
>
{'Account Settings'}
</h4>
</div>
<div className='modal-body'>
<div className='settings-table'> <div className='settings-table'>
<div className='settings-links'> <div className='settings-links'>
<SettingsSidebar <SettingsSidebar
@@ -83,17 +194,33 @@ export default class UserSettingsModal extends React.Component {
</div> </div>
<div className='settings-content minimize-settings'> <div className='settings-content minimize-settings'>
<UserSettings <UserSettings
ref='userSettings'
activeTab={this.state.active_tab} activeTab={this.state.active_tab}
activeSection={this.state.active_section} activeSection={this.state.active_section}
updateSection={this.updateSection} updateSection={this.updateSection}
updateTab={this.updateTab} updateTab={this.updateTab}
closeModal={this.closeModal}
collapseModal={this.collapseModal}
setEnforceFocus={(enforceFocus) => this.setState({enforceFocus})}
setRequireConfirm={(requireConfirm) => this.requireConfirm = requireConfirm}
/> />
</div> </div>
</div> </div>
</div> </Modal.Body>
</div> <ConfirmModal
</div> title='Discard Changes?'
</div> message='You have unsaved changes, are you sure you want to discard them?'
confirm_button='Yes, Discard'
show={this.state.showConfirmModal}
onConfirm={this.handleConfirm}
onCancel={this.handleCancelConfirmation}
/>
</Modal>
); );
} }
} }
UserSettingsModal.propTypes = {
show: React.PropTypes.bool.isRequired,
onModalDismissed: React.PropTypes.func.isRequired
};

Просмотреть файл

@@ -7,7 +7,6 @@ var SettingItemMax = require('../setting_item_max.jsx');
var client = require('../../utils/client.jsx'); var client = require('../../utils/client.jsx');
var AsyncClient = require('../../utils/async_client.jsx'); var AsyncClient = require('../../utils/async_client.jsx');
var utils = require('../../utils/utils.jsx'); var utils = require('../../utils/utils.jsx');
var assign = require('object-assign');
function getNotificationsStateFromStores() { function getNotificationsStateFromStores() {
var user = UserStore.getCurrentUser(); var user = UserStore.getCurrentUser();
@@ -77,7 +76,6 @@ export default class NotificationsTab extends React.Component {
super(props); super(props);
this.handleSubmit = this.handleSubmit.bind(this); this.handleSubmit = this.handleSubmit.bind(this);
this.handleClose = this.handleClose.bind(this);
this.updateSection = this.updateSection.bind(this); this.updateSection = this.updateSection.bind(this);
this.onListenerChange = this.onListenerChange.bind(this); this.onListenerChange = this.onListenerChange.bind(this);
this.handleNotifyRadio = this.handleNotifyRadio.bind(this); this.handleNotifyRadio = this.handleNotifyRadio.bind(this);
@@ -128,27 +126,15 @@ export default class NotificationsTab extends React.Component {
}.bind(this) }.bind(this)
); );
} }
handleClose() {
$(ReactDOM.findDOMNode(this)).find('.form-control').each(function clearField() {
this.value = '';
});
this.setState(assign({}, getNotificationsStateFromStores(), {serverError: null}));
this.props.updateTab('general');
}
updateSection(section) { updateSection(section) {
this.setState(getNotificationsStateFromStores()); this.setState(getNotificationsStateFromStores());
this.props.updateSection(section); this.props.updateSection(section);
} }
componentDidMount() { componentDidMount() {
UserStore.addChangeListener(this.onListenerChange); UserStore.addChangeListener(this.onListenerChange);
$('#user_settings').on('hidden.bs.modal', this.handleClose);
} }
componentWillUnmount() { componentWillUnmount() {
UserStore.removeChangeListener(this.onListenerChange); UserStore.removeChangeListener(this.onListenerChange);
$('#user_settings').off('hidden.bs.modal', this.handleClose);
this.props.updateSection('');
} }
onListenerChange() { onListenerChange() {
var newState = getNotificationsStateFromStores(); var newState = getNotificationsStateFromStores();
@@ -644,15 +630,19 @@ export default class NotificationsTab extends React.Component {
className='close' className='close'
data-dismiss='modal' data-dismiss='modal'
aria-label='Close' aria-label='Close'
onClick={this.props.closeModal}
> >
<span aria-hidden='true'>&times;</span> <span aria-hidden='true'>{'×'}</span>
</button> </button>
<h4 <h4
className='modal-title' className='modal-title'
ref='title' ref='title'
> >
<i className='modal-back'></i> <i
Notifications className='modal-back'
onClick={this.props.collapseModal}
/>
{'Notification Settings'}
</h4> </h4>
</div> </div>
<div <div
@@ -686,5 +676,7 @@ NotificationsTab.propTypes = {
updateSection: React.PropTypes.func, updateSection: React.PropTypes.func,
updateTab: React.PropTypes.func, updateTab: React.PropTypes.func,
activeSection: React.PropTypes.string, activeSection: React.PropTypes.string,
activeTab: React.PropTypes.string activeTab: React.PropTypes.string,
closeModal: React.PropTypes.func.isRequired,
collapseModal: React.PropTypes.func.isRequired
}; };

Просмотреть файл

@@ -3,6 +3,8 @@
var SettingItemMin = require('../setting_item_min.jsx'); var SettingItemMin = require('../setting_item_min.jsx');
var SettingItemMax = require('../setting_item_max.jsx'); var SettingItemMax = require('../setting_item_max.jsx');
var AccessHistoryModal = require('../access_history_modal.jsx');
var ActivityLogModal = require('../activity_log_modal.jsx');
var Client = require('../../utils/client.jsx'); var Client = require('../../utils/client.jsx');
var AsyncClient = require('../../utils/async_client.jsx'); var AsyncClient = require('../../utils/async_client.jsx');
var Constants = require('../../utils/constants.jsx'); var Constants = require('../../utils/constants.jsx');
@@ -11,14 +13,34 @@ export default class SecurityTab extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.showAccessHistoryModal = this.showAccessHistoryModal.bind(this);
this.showActivityLogModal = this.showActivityLogModal.bind(this);
this.hideModals = this.hideModals.bind(this);
this.submitPassword = this.submitPassword.bind(this); this.submitPassword = this.submitPassword.bind(this);
this.updateCurrentPassword = this.updateCurrentPassword.bind(this); this.updateCurrentPassword = this.updateCurrentPassword.bind(this);
this.updateNewPassword = this.updateNewPassword.bind(this); this.updateNewPassword = this.updateNewPassword.bind(this);
this.updateConfirmPassword = this.updateConfirmPassword.bind(this); this.updateConfirmPassword = this.updateConfirmPassword.bind(this);
this.handleClose = this.handleClose.bind(this);
this.setupInitialState = this.setupInitialState.bind(this); this.setupInitialState = this.setupInitialState.bind(this);
this.state = this.setupInitialState(); const state = this.setupInitialState();
state.showAccessHistoryModal = false;
state.showActivityLogModal = false;
this.state = state;
}
showAccessHistoryModal() {
this.props.setEnforceFocus(false);
this.setState({showAccessHistoryModal: true});
}
showActivityLogModal() {
this.props.setEnforceFocus(false);
this.setState({showActivityLogModal: true});
}
hideModals() {
this.props.setEnforceFocus(true);
this.setState({
showAccessHistoryModal: false,
showActivityLogModal: false
});
} }
submitPassword(e) { submitPassword(e) {
e.preventDefault(); e.preventDefault();
@@ -75,30 +97,9 @@ export default class SecurityTab extends React.Component {
updateConfirmPassword(e) { updateConfirmPassword(e) {
this.setState({confirmPassword: e.target.value}); this.setState({confirmPassword: e.target.value});
} }
handleHistoryOpen() {
$('#user_settings').modal('hide');
}
handleDevicesOpen() {
$('#user_settings').modal('hide');
}
handleClose() {
$(ReactDOM.findDOMNode(this)).find('.form-control').each(function resetValue() {
this.value = '';
});
this.setState({currentPassword: '', newPassword: '', confirmPassword: '', serverError: null, passwordError: null});
this.props.updateTab('general');
}
setupInitialState() { setupInitialState() {
return {currentPassword: '', newPassword: '', confirmPassword: ''}; return {currentPassword: '', newPassword: '', confirmPassword: ''};
} }
componentDidMount() {
$('#user_settings').on('hidden.bs.modal', this.handleClose);
}
componentWillUnmount() {
$('#user_settings').off('hidden.bs.modal', this.handleClose);
this.props.updateSection('');
}
render() { render() {
var serverError; var serverError;
if (this.state.serverError) { if (this.state.serverError) {
@@ -236,14 +237,19 @@ export default class SecurityTab extends React.Component {
className='close' className='close'
data-dismiss='modal' data-dismiss='modal'
aria-label='Close' aria-label='Close'
onClick={this.props.closeModal}
> >
<span aria-hidden='true'>&times;</span> <span aria-hidden='true'>{'×'}</span>
</button> </button>
<h4 <h4
className='modal-title' className='modal-title'
ref='title' ref='title'
> >
<i className='modal-back'></i>Security Settings <i
className='modal-back'
onClick={this.props.collapseModal}
/>
{'Security Settings'}
</h4> </h4>
</div> </div>
<div className='user-settings'> <div className='user-settings'>
@@ -253,25 +259,29 @@ export default class SecurityTab extends React.Component {
<div className='divider-dark'/> <div className='divider-dark'/>
<br></br> <br></br>
<a <a
data-toggle='modal'
className='security-links theme' className='security-links theme'
data-target='#access-history'
href='#' href='#'
onClick={this.handleHistoryOpen} onClick={this.showAccessHistoryModal}
> >
<i className='fa fa-clock-o'></i>View Access History <i className='fa fa-clock-o'></i>View Access History
</a> </a>
<b> </b> <b> </b>
<a <a
data-toggle='modal'
className='security-links theme' className='security-links theme'
data-target='#activity-log'
href='#' href='#'
onClick={this.handleDevicesOpen} onClick={this.showActivityLogModal}
> >
<i className='fa fa-globe'></i>View and Logout of Active Sessions <i className='fa fa-globe'></i>View and Logout of Active Sessions
</a> </a>
</div> </div>
<AccessHistoryModal
show={this.state.showAccessHistoryModal}
onModalDismissed={this.hideModals}
/>
<ActivityLogModal
show={this.state.showActivityLogModal}
onModalDismissed={this.hideModals}
/>
</div> </div>
); );
} }
@@ -285,5 +295,8 @@ SecurityTab.propTypes = {
user: React.PropTypes.object, user: React.PropTypes.object,
activeSection: React.PropTypes.string, activeSection: React.PropTypes.string,
updateSection: React.PropTypes.func, updateSection: React.PropTypes.func,
updateTab: React.PropTypes.func updateTab: React.PropTypes.func,
closeModal: React.PropTypes.func.isRequired,
collapseModal: React.PropTypes.func.isRequired,
setEnforceFocus: React.PropTypes.func.isRequired
}; };

Просмотреть файл

@@ -9,7 +9,6 @@ var ErrorStore = require('../stores/error_store.jsx');
var MentionList = require('../components/mention_list.jsx'); var MentionList = require('../components/mention_list.jsx');
var GetLinkModal = require('../components/get_link_modal.jsx'); var GetLinkModal = require('../components/get_link_modal.jsx');
var MemberInviteModal = require('../components/invite_member_modal.jsx');
var EditChannelModal = require('../components/edit_channel_modal.jsx'); var EditChannelModal = require('../components/edit_channel_modal.jsx');
var DeleteChannelModal = require('../components/delete_channel_modal.jsx'); var DeleteChannelModal = require('../components/delete_channel_modal.jsx');
var RenameChannelModal = require('../components/rename_channel_modal.jsx'); var RenameChannelModal = require('../components/rename_channel_modal.jsx');
@@ -18,17 +17,15 @@ var DeletePostModal = require('../components/delete_post_modal.jsx');
var MoreChannelsModal = require('../components/more_channels.jsx'); var MoreChannelsModal = require('../components/more_channels.jsx');
var PostDeletedModal = require('../components/post_deleted_modal.jsx'); var PostDeletedModal = require('../components/post_deleted_modal.jsx');
var ChannelNotificationsModal = require('../components/channel_notifications.jsx'); var ChannelNotificationsModal = require('../components/channel_notifications.jsx');
var UserSettingsModal = require('../components/user_settings/user_settings_modal.jsx');
var TeamSettingsModal = require('../components/team_settings_modal.jsx'); var TeamSettingsModal = require('../components/team_settings_modal.jsx');
var ChannelMembersModal = require('../components/channel_members.jsx'); var ChannelMembersModal = require('../components/channel_members.jsx');
var ChannelInviteModal = require('../components/channel_invite_modal.jsx'); var ChannelInviteModal = require('../components/channel_invite_modal.jsx');
var TeamMembersModal = require('../components/team_members.jsx'); var TeamMembersModal = require('../components/team_members.jsx');
var ChannelInfoModal = require('../components/channel_info_modal.jsx'); var ChannelInfoModal = require('../components/channel_info_modal.jsx');
var AccessHistoryModal = require('../components/access_history_modal.jsx');
var ActivityLogModal = require('../components/activity_log_modal.jsx');
var RemovedFromChannelModal = require('../components/removed_from_channel_modal.jsx'); var RemovedFromChannelModal = require('../components/removed_from_channel_modal.jsx');
var RegisterAppModal = require('../components/register_app_modal.jsx'); var RegisterAppModal = require('../components/register_app_modal.jsx');
var ImportThemeModal = require('../components/user_settings/import_theme_modal.jsx'); var ImportThemeModal = require('../components/user_settings/import_theme_modal.jsx');
var InviteMemberModal = require('../components/invite_member_modal.jsx');
var AsyncClient = require('../utils/async_client.jsx'); var AsyncClient = require('../utils/async_client.jsx');
var Constants = require('../utils/constants.jsx'); var Constants = require('../utils/constants.jsx');
@@ -83,8 +80,8 @@ function setupChannelPage(props) {
); );
ReactDOM.render( ReactDOM.render(
<UserSettingsModal />, <InviteMemberModal />,
document.getElementById('user_settings_modal') document.getElementById('invite_member_modal')
); );
ReactDOM.render( ReactDOM.render(
@@ -102,11 +99,6 @@ function setupChannelPage(props) {
document.getElementById('team_members_modal') document.getElementById('team_members_modal')
); );
ReactDOM.render(
<MemberInviteModal teamType={props.TeamType} />,
document.getElementById('invite_member_modal')
);
ReactDOM.render( ReactDOM.render(
<EditChannelModal />, <EditChannelModal />,
document.getElementById('edit_channel_modal') document.getElementById('edit_channel_modal')
@@ -162,16 +154,6 @@ function setupChannelPage(props) {
document.getElementById('post_deleted_modal') document.getElementById('post_deleted_modal')
); );
ReactDOM.render(
<AccessHistoryModal />,
document.getElementById('access_history_modal')
);
ReactDOM.render(
<ActivityLogModal />,
document.getElementById('activity_log_modal')
);
ReactDOM.render( ReactDOM.render(
<RemovedFromChannelModal />, <RemovedFromChannelModal />,
document.getElementById('removed_from_channel_modal') document.getElementById('removed_from_channel_modal')

42
web/react/stores/modal_store.jsx Обычный файл
Просмотреть файл

@@ -0,0 +1,42 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
const AppDispatcher = require('../dispatcher/app_dispatcher.jsx');
const EventEmitter = require('events').EventEmitter;
const Constants = require('../utils/constants.jsx');
const ActionTypes = Constants.ActionTypes;
class ModalStoreClass extends EventEmitter {
constructor() {
super();
this.addModalListener = this.addModalListener.bind(this);
this.removeModalListener = this.removeModalListener.bind(this);
this.handleEventPayload = this.handleEventPayload.bind(this);
this.dispatchToken = AppDispatcher.register(this.handleEventPayload);
}
addModalListener(action, callback) {
this.on(action, callback);
}
removeModalListener(action, callback) {
this.removeListener(action, callback);
}
handleEventPayload(payload) {
const action = payload.action;
switch (action.type) {
case ActionTypes.TOGGLE_IMPORT_THEME_MODAL:
case ActionTypes.TOGGLE_INVITE_MEMBER_MODAL:
this.emit(action.type, action.value);
break;
}
}
}
const ModalStore = new ModalStoreClass();
export default ModalStore;

Просмотреть файл

@@ -13,7 +13,6 @@ var CHANGE_EVENT_SESSIONS = 'change_sessions';
var CHANGE_EVENT_AUDITS = 'change_audits'; var CHANGE_EVENT_AUDITS = 'change_audits';
var CHANGE_EVENT_TEAMS = 'change_teams'; var CHANGE_EVENT_TEAMS = 'change_teams';
var CHANGE_EVENT_STATUSES = 'change_statuses'; var CHANGE_EVENT_STATUSES = 'change_statuses';
var TOGGLE_IMPORT_MODAL_EVENT = 'toggle_import_modal';
class UserStoreClass extends EventEmitter { class UserStoreClass extends EventEmitter {
constructor() { constructor() {
@@ -34,9 +33,6 @@ class UserStoreClass extends EventEmitter {
this.emitStatusesChange = this.emitStatusesChange.bind(this); this.emitStatusesChange = this.emitStatusesChange.bind(this);
this.addStatusesChangeListener = this.addStatusesChangeListener.bind(this); this.addStatusesChangeListener = this.addStatusesChangeListener.bind(this);
this.removeStatusesChangeListener = this.removeStatusesChangeListener.bind(this); this.removeStatusesChangeListener = this.removeStatusesChangeListener.bind(this);
this.emitToggleImportModal = this.emitToggleImportModal.bind(this);
this.addImportModalListener = this.addImportModalListener.bind(this);
this.removeImportModalListener = this.removeImportModalListener.bind(this);
this.getCurrentId = this.getCurrentId.bind(this); this.getCurrentId = this.getCurrentId.bind(this);
this.getCurrentUser = this.getCurrentUser.bind(this); this.getCurrentUser = this.getCurrentUser.bind(this);
this.setCurrentUser = this.setCurrentUser.bind(this); this.setCurrentUser = this.setCurrentUser.bind(this);
@@ -124,18 +120,6 @@ class UserStoreClass extends EventEmitter {
this.removeListener(CHANGE_EVENT_STATUSES, callback); this.removeListener(CHANGE_EVENT_STATUSES, callback);
} }
emitToggleImportModal(value) {
this.emit(TOGGLE_IMPORT_MODAL_EVENT, value);
}
addImportModalListener(callback) {
this.on(TOGGLE_IMPORT_MODAL_EVENT, callback);
}
removeImportModalListener(callback) {
this.removeListener(TOGGLE_IMPORT_MODAL_EVENT, callback);
}
getCurrentUser() { getCurrentUser() {
if (this.getProfiles()[global.window.mm_user.id] == null) { if (this.getProfiles()[global.window.mm_user.id] == null) {
this.saveProfile(global.window.mm_user); this.saveProfile(global.window.mm_user);
@@ -353,10 +337,6 @@ UserStore.dispatchToken = AppDispatcher.register((payload) => {
UserStore.pSetStatuses(action.statuses); UserStore.pSetStatuses(action.statuses);
UserStore.emitStatusesChange(); UserStore.emitStatusesChange();
break; break;
case ActionTypes.TOGGLE_IMPORT_THEME_MODAL:
UserStore.emitToggleImportModal(action.value);
break;
default: default:
} }
}); });

Просмотреть файл

@@ -3,6 +3,7 @@
// See License.txt for license information. // See License.txt for license information.
const Utils = require('./utils.jsx'); const Utils = require('./utils.jsx');
const InviteMemberModal = require('../components/invite_member_modal.jsx');
const UserProfile = require('../components/user_profile.jsx'); const UserProfile = require('../components/user_profile.jsx');
const ChannelStore = require('../stores/channel_store.jsx'); const ChannelStore = require('../stores/channel_store.jsx');
const Constants = require('../utils/constants.jsx'); const Constants = require('../utils/constants.jsx');
@@ -109,8 +110,7 @@ export function createDefaultIntroMessage(channel) {
<a <a
className='intro-links' className='intro-links'
href='#' href='#'
data-toggle='modal' onClick={InviteMemberModal.show}
data-target='#invite_member'
> >
<i className='fa fa-user-plus'></i>{'Invite others to this team'} <i className='fa fa-user-plus'></i>{'Invite others to this team'}
</a> </a>
@@ -213,6 +213,7 @@ export function createStandardIntroMessage(channel) {
> >
<i className='fa fa-user-plus'></i>{'Invite others to this ' + uiType} <i className='fa fa-user-plus'></i>{'Invite others to this ' + uiType}
</a> </a>
</div> </div>
); );
} }

Просмотреть файл

@@ -39,7 +39,8 @@ module.exports = {
RECIEVED_LOGS: null, RECIEVED_LOGS: null,
RECIEVED_ALL_TEAMS: null, RECIEVED_ALL_TEAMS: null,
TOGGLE_IMPORT_THEME_MODAL: null TOGGLE_IMPORT_THEME_MODAL: null,
TOGGLE_INVITE_MEMBER_MODAL: null
}), }),
PayloadSources: keyMirror({ PayloadSources: keyMirror({

Просмотреть файл

@@ -13,6 +13,10 @@
.settings-modal { .settings-modal {
width:800px; width:800px;
max-width: 100%; max-width: 100%;
.modal-content {
width:800px;
max-width: 100%;
}
.modal-back { .modal-back {
width: 40px; width: 40px;
height: 56px; height: 56px;