Fixed theme confirmation dialog to work in all cases and removed some jquery magic related to it

Этот коммит содержится в:
hmhealey
2015-11-03 14:09:09 -05:00
родитель be442b6221
Коммит a7ceba2e57
10 изменённых файлов: 173 добавлений и 53 удалений

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

@@ -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,6 +30,10 @@ 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)) {
@@ -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,13 @@ 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} setEnforceFocus={this.props.setEnforceFocus}
/> />
</div> </div>
@@ -64,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>
); );
@@ -75,9 +89,12 @@ 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} setEnforceFocus={this.props.setEnforceFocus}
setRequireConfirm={this.props.setRequireConfirm} setRequireConfirm={this.props.setRequireConfirm}
/> />
@@ -87,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>
); );
@@ -96,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>
); );
@@ -107,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>
); );
@@ -118,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>
); );
@@ -136,6 +165,8 @@ UserSettings.propTypes = {
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, setEnforceFocus: React.PropTypes.func.isRequired,
setRequireConfirm: React.PropTypes.func.isRequired setRequireConfirm: React.PropTypes.func.isRequired
}; };

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

@@ -126,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>
@@ -133,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>
@@ -152,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,7 +20,8 @@ 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();
@@ -42,8 +43,6 @@ export default class UserSettingsAppearance extends React.Component {
} }
componentWillUnmount() { componentWillUnmount() {
UserStore.removeChangeListener(this.onChange); UserStore.removeChangeListener(this.onChange);
this.handleClose();
} }
getStateFromStores() { getStateFromStores() {
const user = UserStore.getCurrentUser(); const user = UserStore.getCurrentUser();
@@ -130,11 +129,20 @@ export default class UserSettingsAppearance extends React.Component {
updateType(type) { updateType(type) {
this.setState({type}); this.setState({type});
} }
handleClose() { deactivate() {
const state = this.getStateFromStores(); const state = this.getStateFromStores();
Utils.applyTheme(state.theme); Utils.applyTheme(state.theme);
} }
resetFields() {
const state = this.getStateFromStores();
state.serverError = null;
this.setState(state);
Utils.applyTheme(state.theme);
this.props.setRequireConfirm(false);
}
handleImportModal() { handleImportModal() {
AppDispatcher.handleViewAction({ AppDispatcher.handleViewAction({
type: ActionTypes.TOGGLE_IMPORT_THEME_MODAL, type: ActionTypes.TOGGLE_IMPORT_THEME_MODAL,
@@ -212,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>
@@ -226,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>
@@ -235,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'>
@@ -262,6 +274,8 @@ 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, setRequireConfirm: React.PropTypes.func.isRequired,
setEnforceFocus: 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
}; };

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

@@ -217,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>
@@ -224,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>
@@ -245,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
}; };

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

@@ -564,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>
@@ -571,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>
@@ -598,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
}; };

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

@@ -92,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>
@@ -99,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>
@@ -120,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
}; };

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

@@ -12,9 +12,14 @@ export default class UserSettingsModal extends React.Component {
this.handleHide = this.handleHide.bind(this); this.handleHide = this.handleHide.bind(this);
this.handleHidden = this.handleHidden.bind(this); this.handleHidden = this.handleHidden.bind(this);
this.handleCollapse = this.handleCollapse.bind(this);
this.handleConfirm = this.handleConfirm.bind(this); this.handleConfirm = this.handleConfirm.bind(this);
this.handleCancelConfirmation = this.handleCancelConfirmation.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);
@@ -28,27 +33,6 @@ export default class UserSettingsModal extends React.Component {
this.requireConfirm = false; 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) { componentDidUpdate(prevProps) {
if (!prevProps.show && this.props.show) { if (!prevProps.show && this.props.show) {
$(ReactDOM.findDOMNode(this.refs.modalBody)).css('max-height', $(window).height() - 300); $(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 // Called when the close button is pressed on the main modal
handleHide(skipConfirm) { handleHide() {
if (!skipConfirm && this.requireConfirm) { if (this.requireConfirm) {
this.afterConfirm = () => this.handleHide(true); this.afterConfirm = () => this.handleHide();
this.showConfirmModal(); this.showConfirmModal();
return false; return false;
} }
this.deactivateTab();
this.props.onModalDismissed(); 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() { handleConfirm() {
this.setState({ this.setState({
showConfirmModal: false, showConfirmModal: false,
@@ -97,20 +94,53 @@ export default class UserSettingsModal extends React.Component {
showConfirmModal: false, showConfirmModal: false,
enforceFocus: true enforceFocus: true
}); });
this.afterConfirm = null;
} }
showConfirmModal() { showConfirmModal(afterConfirm) {
this.setState({ this.setState({
showConfirmModal: true, showConfirmModal: true,
enforceFocus: false 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) { updateTab(tab, skipConfirm) {
if (!skipConfirm && this.requireConfirm) { if (!skipConfirm && this.requireConfirm) {
this.afterConfirm = () => this.updateTab(tab, true); this.showConfirmModal(() => this.updateTab(tab, true));
this.showConfirmModal();
} else { } else {
this.deactivateTab();
this.setState({ this.setState({
active_tab: tab, active_tab: tab,
active_section: '' active_section: ''
@@ -120,8 +150,7 @@ export default class UserSettingsModal extends React.Component {
updateSection(section, skipConfirm) { updateSection(section, skipConfirm) {
if (!skipConfirm && this.requireConfirm) { if (!skipConfirm && this.requireConfirm) {
this.afterConfirm = () => this.updateSection(section, true); this.showConfirmModal(() => this.updateSection(section, true));
this.showConfirmModal();
} else { } else {
this.setState({active_section: section}); this.setState({active_section: section});
} }
@@ -170,6 +199,8 @@ export default class UserSettingsModal extends React.Component {
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})} setEnforceFocus={(enforceFocus) => this.setState({enforceFocus})}
setRequireConfirm={(requireConfirm) => this.requireConfirm = requireConfirm} setRequireConfirm={(requireConfirm) => this.requireConfirm = requireConfirm}
/> />

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

@@ -630,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
@@ -672,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
}; };

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

@@ -237,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'>
@@ -291,5 +296,7 @@ SecurityTab.propTypes = {
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 setEnforceFocus: React.PropTypes.func.isRequired
}; };