Ported ConfirmModal and InviteMemberModal to React-Bootstrap

Этот коммит содержится в:
hmhealey
2015-10-29 17:49:38 -04:00
родитель e52669c2da
Коммит efa7b8252f
6 изменённых файлов: 142 добавлений и 144 удалений

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

@@ -1,70 +1,66 @@
// 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'); if (this.props.onConfirm) {
$('#' + this.props.parent_id).modal('hide'); this.props.onConfirm();
$('#' + 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' enforceFocus={false}
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
}; };

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

@@ -7,11 +7,14 @@ 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.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);
@@ -22,38 +25,11 @@ export default class InviteMemberModal extends React.Component {
emailErrors: {}, emailErrors: {},
firstNameErrors: {}, firstNameErrors: {},
lastNameErrors: {}, 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() { handleSubmit() {
if (!this.state.emailEnabled) { if (!this.state.emailEnabled) {
return; return;
@@ -94,25 +70,55 @@ 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({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() { addInviteFields() {
@@ -292,7 +298,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 +308,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 +329,49 @@ export default class InviteMemberModal extends React.Component {
return ( return (
<div> <div>
<div <Modal
className='modal fade' className='modal-invite-member'
ref='modal' show={this.props.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;
} }
} }
InviteMemberModal.propTypes = { InviteMemberModal.propTypes = {
teamType: React.PropTypes.string show: React.PropTypes.bool.isRequired,
onModalDismissed: React.PropTypes.func.isRequired
}; };

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

@@ -7,6 +7,7 @@ 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 Constants = require('../utils/constants.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.onListenerChange = this.onListenerChange.bind(this);
this.aboutModalDismissed = this.aboutModalDismissed.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) { handleLogoutClick(e) {
e.preventDefault(); e.preventDefault();
@@ -96,8 +100,7 @@ export default class NavbarDropdown extends React.Component {
<li> <li>
<a <a
href='#' href='#'
data-toggle='modal' onClick={() => this.setState({showInviteMemberModal: true})}
data-target='#invite_member'
> >
{'Invite New Member'} {'Invite New Member'}
</a> </a>
@@ -268,6 +271,10 @@ export default class NavbarDropdown extends React.Component {
show={this.state.showAboutModal} show={this.state.showAboutModal}
onModalDismissed={this.aboutModalDismissed} onModalDismissed={this.aboutModalDismissed}
/> />
<InviteMemberModal
show={this.state.showInviteMemberModal}
onModalDismissed={() => this.setState({showInviteMemberModal: false})}
/>
</ul> </ul>
</li> </li>
</ul> </ul>

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

@@ -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 InviteMemberModal = require('./invite_member_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 +16,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 = {
showInviteMemberModal: false
};
} }
handleLogoutClick(e) { handleLogoutClick(e) {
@@ -38,10 +43,12 @@ export default class SidebarRightMenu extends React.Component {
inviteLink = ( inviteLink = (
<li> <li>
<a href='#' <a
data-toggle='modal' href='#'
data-target='#invite_member' onClick={() => this.setState({showInviteMemberModal: true})}
><i className='glyphicon glyphicon-user'></i>Invite New Member</a> >
<i className='glyphicon glyphicon-user'></i>Invite New Member
</a>
</li> </li>
); );
@@ -141,6 +148,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>
<InviteMemberModal
show={this.state.showInviteMemberModal}
onModalDismissed={() => this.setState({showInviteMemberModal: false})}
/>
</div> </div>
); );
} }

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

@@ -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');
@@ -102,11 +101,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')

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

@@ -186,6 +186,8 @@ export function createStandardIntroMessage(channel) {
); );
} }
// TODO show channel_invite modal now that it's a React-Bootstrap modal
return ( return (
<div className='channel-intro'> <div className='channel-intro'>
<h4 className='channel-intro__title'>{'Beginning of ' + uiName}</h4> <h4 className='channel-intro__title'>{'Beginning of ' + uiName}</h4>
@@ -213,6 +215,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>
); );
} }