diff --git a/web/react/components/user_settings/user_settings.jsx b/web/react/components/user_settings/user_settings.jsx index cebbbebce1..e089ce973e 100644 --- a/web/react/components/user_settings/user_settings.jsx +++ b/web/react/components/user_settings/user_settings.jsx @@ -16,6 +16,7 @@ export default class UserSettings extends React.Component { constructor(props) { super(props); + this.getActiveTab = this.getActiveTab.bind(this); this.onListenerChange = this.onListenerChange.bind(this); this.state = {user: UserStore.getCurrentUser()}; @@ -29,6 +30,10 @@ export default class UserSettings extends React.Component { UserStore.removeChangeListener(this.onListenerChange); } + getActiveTab() { + return this.refs.activeTab; + } + onListenerChange() { var user = UserStore.getCurrentUser(); if (!utils.areStatesEqual(this.state.user, user)) { @@ -41,10 +46,13 @@ export default class UserSettings extends React.Component { return (
); @@ -52,10 +60,13 @@ export default class UserSettings extends React.Component { return (
@@ -64,10 +75,13 @@ export default class UserSettings extends React.Component { return (
); @@ -75,9 +89,12 @@ export default class UserSettings extends React.Component { return (
@@ -87,8 +104,11 @@ export default class UserSettings extends React.Component { return (
); @@ -96,10 +116,13 @@ export default class UserSettings extends React.Component { return (
); @@ -107,10 +130,13 @@ export default class UserSettings extends React.Component { return (
); @@ -118,10 +144,13 @@ export default class UserSettings extends React.Component { return (
); @@ -136,6 +165,8 @@ UserSettings.propTypes = { activeSection: React.PropTypes.string, updateSection: 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 }; diff --git a/web/react/components/user_settings/user_settings_advanced.jsx b/web/react/components/user_settings/user_settings_advanced.jsx index 8d91d264a7..2616981bac 100644 --- a/web/react/components/user_settings/user_settings_advanced.jsx +++ b/web/react/components/user_settings/user_settings_advanced.jsx @@ -126,6 +126,7 @@ export default class AdvancedSettingsDisplay extends React.Component { className='close' data-dismiss='modal' aria-label='Close' + onClick={this.props.closeModal} > @@ -133,7 +134,10 @@ export default class AdvancedSettingsDisplay extends React.Component { className='modal-title' ref='title' > - + {'Advanced Settings'}
@@ -152,5 +156,7 @@ AdvancedSettingsDisplay.propTypes = { user: React.PropTypes.object, updateSection: 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 }; diff --git a/web/react/components/user_settings/user_settings_appearance.jsx b/web/react/components/user_settings/user_settings_appearance.jsx index 28fc9018ad..425645c1f5 100644 --- a/web/react/components/user_settings/user_settings_appearance.jsx +++ b/web/react/components/user_settings/user_settings_appearance.jsx @@ -20,7 +20,8 @@ export default class UserSettingsAppearance extends React.Component { this.submitTheme = this.submitTheme.bind(this); this.updateTheme = this.updateTheme.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.state = this.getStateFromStores(); @@ -42,8 +43,6 @@ export default class UserSettingsAppearance extends React.Component { } componentWillUnmount() { UserStore.removeChangeListener(this.onChange); - - this.handleClose(); } getStateFromStores() { const user = UserStore.getCurrentUser(); @@ -130,11 +129,20 @@ export default class UserSettingsAppearance extends React.Component { updateType(type) { this.setState({type}); } - handleClose() { + deactivate() { const state = this.getStateFromStores(); Utils.applyTheme(state.theme); } + resetFields() { + const state = this.getStateFromStores(); + state.serverError = null; + this.setState(state); + + Utils.applyTheme(state.theme); + + this.props.setRequireConfirm(false); + } handleImportModal() { AppDispatcher.handleViewAction({ type: ActionTypes.TOGGLE_IMPORT_THEME_MODAL, @@ -212,7 +220,7 @@ export default class UserSettingsAppearance extends React.Component { {'Cancel'} @@ -226,8 +234,8 @@ export default class UserSettingsAppearance extends React.Component { @@ -235,7 +243,11 @@ export default class UserSettingsAppearance extends React.Component { className='modal-title' ref='title' > - {'Appearance Settings'} + + {'Appearance Settings'}
@@ -262,6 +274,8 @@ UserSettingsAppearance.defaultProps = { UserSettingsAppearance.propTypes = { activeSection: React.PropTypes.string, updateTab: React.PropTypes.func, + closeModal: React.PropTypes.func.isRequired, + collapseModal: React.PropTypes.func.isRequired, setRequireConfirm: React.PropTypes.func.isRequired, setEnforceFocus: React.PropTypes.func.isRequired }; diff --git a/web/react/components/user_settings/user_settings_developer.jsx b/web/react/components/user_settings/user_settings_developer.jsx index c2d7a9710d..e6adba1d4b 100644 --- a/web/react/components/user_settings/user_settings_developer.jsx +++ b/web/react/components/user_settings/user_settings_developer.jsx @@ -63,6 +63,7 @@ export default class DeveloperTab extends React.Component { className='close' data-dismiss='modal' aria-label='Close' + onClick={this.props.closeModal} > @@ -70,7 +71,11 @@ export default class DeveloperTab extends React.Component { className='modal-title' ref='title' > - {'Developer Settings'} + + {'Developer Settings'}
@@ -89,5 +94,7 @@ DeveloperTab.defaultProps = { }; DeveloperTab.propTypes = { activeSection: React.PropTypes.string, - updateSection: React.PropTypes.func + updateSection: React.PropTypes.func, + closeModal: React.PropTypes.func.isRequired, + collapseModal: React.PropTypes.func.isRequired }; diff --git a/web/react/components/user_settings/user_settings_display.jsx b/web/react/components/user_settings/user_settings_display.jsx index 8c31fdd939..3c12ead23c 100644 --- a/web/react/components/user_settings/user_settings_display.jsx +++ b/web/react/components/user_settings/user_settings_display.jsx @@ -217,6 +217,7 @@ export default class UserSettingsDisplay extends React.Component { className='close' data-dismiss='modal' aria-label='Close' + onClick={this.props.closeModal} > @@ -224,7 +225,10 @@ export default class UserSettingsDisplay extends React.Component { className='modal-title' ref='title' > - + {'Display Settings'}
@@ -245,5 +249,7 @@ UserSettingsDisplay.propTypes = { user: React.PropTypes.object, updateSection: 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 }; diff --git a/web/react/components/user_settings/user_settings_general.jsx b/web/react/components/user_settings/user_settings_general.jsx index 8cd71f01c1..9f0c161940 100644 --- a/web/react/components/user_settings/user_settings_general.jsx +++ b/web/react/components/user_settings/user_settings_general.jsx @@ -564,6 +564,7 @@ export default class UserSettingsGeneralTab extends React.Component { className='close' data-dismiss='modal' aria-label='Close' + onClick={this.props.closeModal} > @@ -571,7 +572,10 @@ export default class UserSettingsGeneralTab extends React.Component { className='modal-title' ref='title' > - + {'General Settings'} @@ -598,5 +602,7 @@ UserSettingsGeneralTab.propTypes = { user: React.PropTypes.object, updateSection: 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 }; diff --git a/web/react/components/user_settings/user_settings_integrations.jsx b/web/react/components/user_settings/user_settings_integrations.jsx index 95f02d9f43..744a6beeab 100644 --- a/web/react/components/user_settings/user_settings_integrations.jsx +++ b/web/react/components/user_settings/user_settings_integrations.jsx @@ -92,6 +92,7 @@ export default class UserSettingsIntegrationsTab extends React.Component { className='close' data-dismiss='modal' aria-label='Close' + onClick={this.props.closeModal} > @@ -99,7 +100,10 @@ export default class UserSettingsIntegrationsTab extends React.Component { className='modal-title' ref='title' > - + {'Integration Settings'} @@ -120,5 +124,7 @@ UserSettingsIntegrationsTab.propTypes = { user: React.PropTypes.object, updateSection: 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 }; diff --git a/web/react/components/user_settings/user_settings_modal.jsx b/web/react/components/user_settings/user_settings_modal.jsx index 94b07f3a59..4dcf32cb9b 100644 --- a/web/react/components/user_settings/user_settings_modal.jsx +++ b/web/react/components/user_settings/user_settings_modal.jsx @@ -12,9 +12,14 @@ export default class UserSettingsModal extends React.Component { 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.updateSection = this.updateSection.bind(this); @@ -28,27 +33,6 @@ export default class UserSettingsModal extends React.Component { this.requireConfirm = false; } - componentDidMount() { - $('body').on('click', '.settings-content .modal-back', () => { - if (!this.requireConfirm) { - $(this).closest('.modal-dialog').removeClass('display--content'); - } - }); - $('body').on('click', '.settings-content .modal-header .close', () => { - if (!this.props.show) { - return; - } - - this.handleHide(); - - if (!this.requireConfirm) { - setTimeout(() => { - $('.modal-dialog.display--content').removeClass('display--content'); - }, 500); - } - }); - } - componentDidUpdate(prevProps) { if (!prevProps.show && this.props.show) { $(ReactDOM.findDOMNode(this.refs.modalBody)).css('max-height', $(window).height() - 300); @@ -58,15 +42,16 @@ export default class UserSettingsModal extends React.Component { } } - // called when the close button is pressed - handleHide(skipConfirm) { - if (!skipConfirm && this.requireConfirm) { - this.afterConfirm = () => this.handleHide(true); + // 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(); } @@ -78,6 +63,18 @@ export default class UserSettingsModal extends React.Component { }); } + // 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: '' + }); + } + handleConfirm() { this.setState({ showConfirmModal: false, @@ -97,20 +94,53 @@ export default class UserSettingsModal extends React.Component { showConfirmModal: false, enforceFocus: true }); + + this.afterConfirm = null; } - showConfirmModal() { + 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.afterConfirm = () => this.updateTab(tab, true); - this.showConfirmModal(); + this.showConfirmModal(() => this.updateTab(tab, true)); } else { + this.deactivateTab(); + this.setState({ active_tab: tab, active_section: '' @@ -120,8 +150,7 @@ export default class UserSettingsModal extends React.Component { updateSection(section, skipConfirm) { if (!skipConfirm && this.requireConfirm) { - this.afterConfirm = () => this.updateSection(section, true); - this.showConfirmModal(); + this.showConfirmModal(() => this.updateSection(section, true)); } else { this.setState({active_section: section}); } @@ -170,6 +199,8 @@ export default class UserSettingsModal extends React.Component { activeSection={this.state.active_section} updateSection={this.updateSection} updateTab={this.updateTab} + closeModal={this.closeModal} + collapseModal={this.collapseModal} setEnforceFocus={(enforceFocus) => this.setState({enforceFocus})} setRequireConfirm={(requireConfirm) => this.requireConfirm = requireConfirm} /> diff --git a/web/react/components/user_settings/user_settings_notifications.jsx b/web/react/components/user_settings/user_settings_notifications.jsx index 49a94b74a5..c6f47804ff 100644 --- a/web/react/components/user_settings/user_settings_notifications.jsx +++ b/web/react/components/user_settings/user_settings_notifications.jsx @@ -630,15 +630,19 @@ export default class NotificationsTab extends React.Component { className='close' data-dismiss='modal' aria-label='Close' + onClick={this.props.closeModal} > - +

- - Notifications + + {'Notification Settings'}

- +

- Security Settings + + {'Security Settings'}

@@ -291,5 +296,7 @@ SecurityTab.propTypes = { activeSection: React.PropTypes.string, updateSection: React.PropTypes.func, updateTab: React.PropTypes.func, + closeModal: React.PropTypes.func.isRequired, + collapseModal: React.PropTypes.func.isRequired, setEnforceFocus: React.PropTypes.func.isRequired };