From efa7b8252fff96e52cca82d332fbf812305049b3 Mon Sep 17 00:00:00 2001 From: hmhealey Date: Thu, 29 Oct 2015 17:49:38 -0400 Subject: [PATCH] Ported ConfirmModal and InviteMemberModal to React-Bootstrap --- web/react/components/confirm_modal.jsx | 82 +++++----- web/react/components/invite_member_modal.jsx | 163 +++++++++---------- web/react/components/navbar_dropdown.jsx | 13 +- web/react/components/sidebar_right_menu.jsx | 19 ++- web/react/pages/channel.jsx | 6 - web/react/utils/channel_intro_mssages.jsx | 3 + 6 files changed, 142 insertions(+), 144 deletions(-) diff --git a/web/react/components/confirm_modal.jsx b/web/react/components/confirm_modal.jsx index 12002f33fc..60069b2b14 100644 --- a/web/react/components/confirm_modal.jsx +++ b/web/react/components/confirm_modal.jsx @@ -1,70 +1,66 @@ // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. +const Modal = ReactBootstrap.Modal; + export default class ConfirmModal extends React.Component { constructor(props) { super(props); this.handleConfirm = this.handleConfirm.bind(this); + } - this.state = {}; - } handleConfirm() { - $('#' + this.props.parent_id).attr('data-confirm', 'true'); - $('#' + this.props.parent_id).modal('hide'); - $('#' + this.props.id).modal('hide'); + if (this.props.onConfirm) { + this.props.onConfirm(); + } } + render() { return ( - + + {this.props.title} + + + {this.props.message} + + + + + + ); } } ConfirmModal.defaultProps = { - parent_id: '', - id: '', title: '', message: '', confirm_button: '' }; ConfirmModal.propTypes = { - parent_id: React.PropTypes.string, - id: React.PropTypes.string, + show: React.PropTypes.bool.isRequired, title: 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 }; diff --git a/web/react/components/invite_member_modal.jsx b/web/react/components/invite_member_modal.jsx index bea7007250..71f72625d6 100644 --- a/web/react/components/invite_member_modal.jsx +++ b/web/react/components/invite_member_modal.jsx @@ -7,11 +7,14 @@ var UserStore = require('../stores/user_store.jsx'); var TeamStore = require('../stores/team_store.jsx'); var ConfirmModal = require('./confirm_modal.jsx'); +const Modal = ReactBootstrap.Modal; + export default class InviteMemberModal extends React.Component { constructor(props) { super(props); this.handleSubmit = this.handleSubmit.bind(this); + this.handleHide = this.handleHide.bind(this); this.addInviteFields = this.addInviteFields.bind(this); this.clearFields = this.clearFields.bind(this); this.removeInviteFields = this.removeInviteFields.bind(this); @@ -22,38 +25,11 @@ export default class InviteMemberModal extends React.Component { emailErrors: {}, firstNameErrors: {}, lastNameErrors: {}, - emailEnabled: global.window.mm_config.SendEmailNotifications === 'true' + emailEnabled: global.window.mm_config.SendEmailNotifications === 'true', + showConfirmModal: false }; } - componentDidMount() { - var self = this; - $('#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; - for (var i = 0; i < self.state.inviteIds.length; i++) { - var index = self.state.inviteIds[i]; - if (ReactDOM.findDOMNode(self.refs['email' + index]).value.trim() !== '') { - notEmpty = true; - break; - } - } - - if (notEmpty) { - $('#confirm_invite_modal').modal('show'); - e.preventDefault(); - } - }); - - $('#invite_member').on('hidden.bs.modal', function show() { - self.clearFields(); - }); - } - handleSubmit() { if (!this.state.emailEnabled) { return; @@ -94,25 +70,55 @@ export default class InviteMemberModal extends React.Component { var data = {}; data.invites = invites; - Client.inviteMembers(data, - function success() { - $(ReactDOM.findDOMNode(this.refs.modal)).attr('data-confirm', 'true'); - $(ReactDOM.findDOMNode(this.refs.modal)).modal('hide'); - }.bind(this), - function fail(err) { + Client.inviteMembers( + data, + () => { + this.handleHide(false); + }, + (err) => { if (err.message === 'This person is already on your team') { emailErrors[err.detailed_error] = err.message; this.setState({emailErrors: emailErrors}); } else { this.setState({serverError: err.message}); } - }.bind(this) + } ); } - componentDidUpdate() { - $(ReactDOM.findDOMNode(this.refs.modalBody)).css('max-height', $(window).height() - 200); - $(ReactDOM.findDOMNode(this.refs.modalBody)).css('overflow-y', 'scroll'); + handleHide(requireConfirm) { + if (requireConfirm) { + 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({showConfirmModal: false}); + this.props.onModalDismissed(); + } + + componentDidUpdate(prevProps) { + if (!prevProps.show && this.props.show) { + $(ReactDOM.findDOMNode(this.refs.modalBody)).css('max-height', $(window).height() - 300); + if ($(window).width() > 768) { + $(ReactDOM.findDOMNode(this.refs.modalBody)).perfectScrollbar(); + } + } } addInviteFields() { @@ -292,7 +298,7 @@ export default class InviteMemberModal extends React.Component { ); } else { 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 link = ( @@ -302,11 +308,7 @@ export default class InviteMemberModal extends React.Component { data-target='#get_link' data-title='Team Invite' data-value={linkUrl} - onClick={ - function click() { - $('#invite_member').modal('hide'); - } - } + onClick={() => this.handleHide(this, false)} >Team Invite Link ); @@ -327,64 +329,49 @@ export default class InviteMemberModal extends React.Component { return (
- + {sendButton} + + this.setState({showConfirmModal: false})} />
); } - return
; + + return null; } } InviteMemberModal.propTypes = { - teamType: React.PropTypes.string + show: React.PropTypes.bool.isRequired, + onModalDismissed: React.PropTypes.func.isRequired }; diff --git a/web/react/components/navbar_dropdown.jsx b/web/react/components/navbar_dropdown.jsx index dc21fad21e..7d7acf5b93 100644 --- a/web/react/components/navbar_dropdown.jsx +++ b/web/react/components/navbar_dropdown.jsx @@ -7,6 +7,7 @@ var UserStore = require('../stores/user_store.jsx'); var TeamStore = require('../stores/team_store.jsx'); var AboutBuildModal = require('./about_build_modal.jsx'); +var InviteMemberModal = require('./invite_member_modal.jsx'); var Constants = require('../utils/constants.jsx'); @@ -41,7 +42,10 @@ export default class NavbarDropdown extends React.Component { this.onListenerChange = this.onListenerChange.bind(this); this.aboutModalDismissed = this.aboutModalDismissed.bind(this); - this.state = getStateFromStores(); + const state = getStateFromStores(); + state.showAboutModal = false; + state.showInviteMemberModal = false; + this.state = state; } handleLogoutClick(e) { e.preventDefault(); @@ -96,8 +100,7 @@ export default class NavbarDropdown extends React.Component {
  • this.setState({showInviteMemberModal: true})} > {'Invite New Member'} @@ -268,6 +271,10 @@ export default class NavbarDropdown extends React.Component { show={this.state.showAboutModal} onModalDismissed={this.aboutModalDismissed} /> + this.setState({showInviteMemberModal: false})} + />
  • diff --git a/web/react/components/sidebar_right_menu.jsx b/web/react/components/sidebar_right_menu.jsx index 9350bbd42a..5da8829ad4 100644 --- a/web/react/components/sidebar_right_menu.jsx +++ b/web/react/components/sidebar_right_menu.jsx @@ -1,6 +1,7 @@ // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. +var InviteMemberModal = require('./invite_member_modal.jsx'); var UserStore = require('../stores/user_store.jsx'); var TeamStore = require('../stores/team_store.jsx'); var client = require('../utils/client.jsx'); @@ -15,6 +16,10 @@ export default class SidebarRightMenu extends React.Component { super(props); this.handleLogoutClick = this.handleLogoutClick.bind(this); + + this.state = { + showInviteMemberModal: false + }; } handleLogoutClick(e) { @@ -38,10 +43,12 @@ export default class SidebarRightMenu extends React.Component { inviteLink = (
  • - Invite New Member + this.setState({showInviteMemberModal: true})} + > + Invite New Member +
  • ); @@ -141,6 +148,10 @@ export default class SidebarRightMenu extends React.Component { >Report a Problem
    + this.setState({showInviteMemberModal: false})} + /> ); } diff --git a/web/react/pages/channel.jsx b/web/react/pages/channel.jsx index 067dcde507..e0272d276a 100644 --- a/web/react/pages/channel.jsx +++ b/web/react/pages/channel.jsx @@ -9,7 +9,6 @@ var ErrorStore = require('../stores/error_store.jsx'); var MentionList = require('../components/mention_list.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 DeleteChannelModal = require('../components/delete_channel_modal.jsx'); var RenameChannelModal = require('../components/rename_channel_modal.jsx'); @@ -102,11 +101,6 @@ function setupChannelPage(props) { document.getElementById('team_members_modal') ); - ReactDOM.render( - , - document.getElementById('invite_member_modal') - ); - ReactDOM.render( , document.getElementById('edit_channel_modal') diff --git a/web/react/utils/channel_intro_mssages.jsx b/web/react/utils/channel_intro_mssages.jsx index b3f8684567..fdeb17bc1c 100644 --- a/web/react/utils/channel_intro_mssages.jsx +++ b/web/react/utils/channel_intro_mssages.jsx @@ -186,6 +186,8 @@ export function createStandardIntroMessage(channel) { ); } + // TODO show channel_invite modal now that it's a React-Bootstrap modal + return (

    {'Beginning of ' + uiName}

    @@ -213,6 +215,7 @@ export function createStandardIntroMessage(channel) { > {'Invite others to this ' + uiType} +
    ); }