Merge pull request #539 from rgarmsen2295/reformat_part_one
MM-2063 Cosmetic Refactoring
Этот коммит содержится в:
@@ -10,13 +10,18 @@ var SocketStore = require('../stores/socket_store.jsx');
|
|||||||
var ChannelStore = require('../stores/channel_store.jsx');
|
var ChannelStore = require('../stores/channel_store.jsx');
|
||||||
var PostStore = require('../stores/post_store.jsx');
|
var PostStore = require('../stores/post_store.jsx');
|
||||||
var UserStore = require('../stores/user_store.jsx');
|
var UserStore = require('../stores/user_store.jsx');
|
||||||
var Constants = require('../utils/constants.jsx');
|
|
||||||
|
|
||||||
var utils = require('../utils/utils.jsx');
|
var Utils = require('../utils/utils.jsx');
|
||||||
|
|
||||||
module.exports = React.createClass({
|
export default class ChannelLoader extends React.Component {
|
||||||
componentDidMount: function() {
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.onSocketChange = this.onSocketChange.bind(this);
|
||||||
|
|
||||||
|
this.state = {};
|
||||||
|
}
|
||||||
|
componentDidMount() {
|
||||||
/* Initial aysnc loads */
|
/* Initial aysnc loads */
|
||||||
AsyncClient.getMe();
|
AsyncClient.getMe();
|
||||||
AsyncClient.getPosts(ChannelStore.getCurrentId());
|
AsyncClient.getPosts(ChannelStore.getCurrentId());
|
||||||
@@ -60,32 +65,32 @@ module.exports = React.createClass({
|
|||||||
var user = UserStore.getCurrentUser();
|
var user = UserStore.getCurrentUser();
|
||||||
|
|
||||||
if (user.props && user.props.theme) {
|
if (user.props && user.props.theme) {
|
||||||
utils.changeCss('div.theme', 'background-color:' + user.props.theme + ';');
|
Utils.changeCss('div.theme', 'background-color:' + user.props.theme + ';');
|
||||||
utils.changeCss('.btn.btn-primary', 'background: ' + user.props.theme + ';');
|
Utils.changeCss('.btn.btn-primary', 'background: ' + user.props.theme + ';');
|
||||||
utils.changeCss('.modal .modal-header', 'background: ' + user.props.theme + ';');
|
Utils.changeCss('.modal .modal-header', 'background: ' + user.props.theme + ';');
|
||||||
utils.changeCss('.mention', 'background: ' + user.props.theme + ';');
|
Utils.changeCss('.mention', 'background: ' + user.props.theme + ';');
|
||||||
utils.changeCss('.mention-link', 'color: ' + user.props.theme + ';');
|
Utils.changeCss('.mention-link', 'color: ' + user.props.theme + ';');
|
||||||
utils.changeCss('@media(max-width: 768px){.search-bar__container', 'background: ' + user.props.theme + ';}');
|
Utils.changeCss('@media(max-width: 768px){.search-bar__container', 'background: ' + user.props.theme + ';}');
|
||||||
utils.changeCss('.search-item-container:hover', 'background: ' + utils.changeOpacity(user.props.theme, 0.05) + ';');
|
Utils.changeCss('.search-item-container:hover', 'background: ' + Utils.changeOpacity(user.props.theme, 0.05) + ';');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user.props.theme !== '#000000' && user.props.theme !== '#585858') {
|
if (user.props.theme !== '#000000' && user.props.theme !== '#585858') {
|
||||||
utils.changeCss('.btn.btn-primary:hover, .btn.btn-primary:active, .btn.btn-primary:focus', 'background: ' + utils.changeColor(user.props.theme, -10) + ';');
|
Utils.changeCss('.btn.btn-primary:hover, .btn.btn-primary:active, .btn.btn-primary:focus', 'background: ' + Utils.changeColor(user.props.theme, -10) + ';');
|
||||||
utils.changeCss('a.theme', 'color:' + user.props.theme + '; fill:' + user.props.theme + '!important;');
|
Utils.changeCss('a.theme', 'color:' + user.props.theme + '; fill:' + user.props.theme + '!important;');
|
||||||
} else if (user.props.theme === '#000000') {
|
} else if (user.props.theme === '#000000') {
|
||||||
utils.changeCss('.btn.btn-primary:hover, .btn.btn-primary:active, .btn.btn-primary:focus', 'background: ' + utils.changeColor(user.props.theme, +50) + ';');
|
Utils.changeCss('.btn.btn-primary:hover, .btn.btn-primary:active, .btn.btn-primary:focus', 'background: ' + Utils.changeColor(user.props.theme, +50) + ';');
|
||||||
$('.team__header').addClass('theme--black');
|
$('.team__header').addClass('theme--black');
|
||||||
} else if (user.props.theme === '#585858') {
|
} else if (user.props.theme === '#585858') {
|
||||||
utils.changeCss('.btn.btn-primary:hover, .btn.btn-primary:active, .btn.btn-primary:focus', 'background: ' + utils.changeColor(user.props.theme, +10) + ';');
|
Utils.changeCss('.btn.btn-primary:hover, .btn.btn-primary:active, .btn.btn-primary:focus', 'background: ' + Utils.changeColor(user.props.theme, +10) + ';');
|
||||||
$('.team__header').addClass('theme--gray');
|
$('.team__header').addClass('theme--gray');
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
onSocketChange: function(msg) {
|
onSocketChange(msg) {
|
||||||
if (msg && msg.user_id && msg.user_id !== UserStore.getCurrentId()) {
|
if (msg && msg.user_id && msg.user_id !== UserStore.getCurrentId()) {
|
||||||
UserStore.setStatus(msg.user_id, 'online');
|
UserStore.setStatus(msg.user_id, 'online');
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
render: function() {
|
render() {
|
||||||
return <div/>;
|
return <div/>;
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|||||||
@@ -1,31 +1,70 @@
|
|||||||
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
|
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
|
||||||
// See License.txt for license information.
|
// See License.txt for license information.
|
||||||
|
|
||||||
module.exports = React.createClass({
|
export default class ConfirmModal extends React.Component {
|
||||||
handleConfirm: function() {
|
constructor(props) {
|
||||||
$('#'+this.props.parent_id).attr('data-confirm', 'true');
|
super(props);
|
||||||
$('#'+this.props.parent_id).modal('hide');
|
|
||||||
$('#'+this.props.id).modal('hide');
|
this.handleConfirm = this.handleConfirm.bind(this);
|
||||||
},
|
|
||||||
render: function() {
|
this.state = {};
|
||||||
|
}
|
||||||
|
handleConfirm() {
|
||||||
|
$('#' + this.props.parent_id).attr('data-confirm', 'true');
|
||||||
|
$('#' + this.props.parent_id).modal('hide');
|
||||||
|
$('#' + this.props.id).modal('hide');
|
||||||
|
}
|
||||||
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className="modal fade" id={this.props.id} tabIndex="-1" role="dialog" aria-hidden="true">
|
<div
|
||||||
<div className="modal-dialog">
|
className='modal fade'
|
||||||
<div className="modal-content">
|
id={this.props.id}
|
||||||
<div className="modal-header">
|
tabIndex='-1'
|
||||||
<h4 className="modal-title">{this.props.title}</h4>
|
role='dialog'
|
||||||
|
aria-hidden='true'
|
||||||
|
>
|
||||||
|
<div className='modal-dialog'>
|
||||||
|
<div className='modal-content'>
|
||||||
|
<div className='modal-header'>
|
||||||
|
<h4 className='modal-title'>{this.props.title}</h4>
|
||||||
</div>
|
</div>
|
||||||
<div className="modal-body">
|
<div className='modal-body'>
|
||||||
{this.props.message}
|
{this.props.message}
|
||||||
</div>
|
</div>
|
||||||
<div className="modal-footer">
|
<div className='modal-footer'>
|
||||||
<button type="button" className="btn btn-default" data-dismiss="modal">Cancel</button>
|
<button
|
||||||
<button onClick={this.handleConfirm} type="button" className="btn btn-primary">{this.props.confirm_button}</button>
|
type='button'
|
||||||
|
className='btn btn-default'
|
||||||
|
data-dismiss='modal'
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={this.handleConfirm}
|
||||||
|
type='button'
|
||||||
|
className='btn btn-primary'
|
||||||
|
>
|
||||||
|
{this.props.confirm_button}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
|
ConfirmModal.defaultProps = {
|
||||||
|
parent_id: '',
|
||||||
|
id: '',
|
||||||
|
title: '',
|
||||||
|
message: '',
|
||||||
|
confirm_button: ''
|
||||||
|
};
|
||||||
|
ConfirmModal.propTypes = {
|
||||||
|
parent_id: React.PropTypes.string,
|
||||||
|
id: React.PropTypes.string,
|
||||||
|
title: React.PropTypes.string,
|
||||||
|
message: React.PropTypes.string,
|
||||||
|
confirm_button: React.PropTypes.string
|
||||||
|
};
|
||||||
|
|||||||
@@ -4,20 +4,28 @@
|
|||||||
var Client = require('../utils/client.jsx');
|
var Client = require('../utils/client.jsx');
|
||||||
var PostStore = require('../stores/post_store.jsx');
|
var PostStore = require('../stores/post_store.jsx');
|
||||||
var BrowserStore = require('../stores/browser_store.jsx');
|
var BrowserStore = require('../stores/browser_store.jsx');
|
||||||
var utils = require('../utils/utils.jsx');
|
var Utils = require('../utils/utils.jsx');
|
||||||
var AsyncClient = require('../utils/async_client.jsx');
|
var AsyncClient = require('../utils/async_client.jsx');
|
||||||
var AppDispatcher = require('../dispatcher/app_dispatcher.jsx');
|
var AppDispatcher = require('../dispatcher/app_dispatcher.jsx');
|
||||||
var Constants = require('../utils/constants.jsx');
|
var Constants = require('../utils/constants.jsx');
|
||||||
var ActionTypes = Constants.ActionTypes;
|
var ActionTypes = Constants.ActionTypes;
|
||||||
|
|
||||||
module.exports = React.createClass({
|
export default class DeletePostModal extends React.Component {
|
||||||
handleDelete: function(e) {
|
constructor(props) {
|
||||||
Client.deletePost(this.state.channel_id, this.state.post_id,
|
super(props);
|
||||||
function(data) {
|
|
||||||
var selected_list = this.state.selectedList;
|
this.handleDelete = this.handleDelete.bind(this);
|
||||||
if (selected_list && selected_list.order && selected_list.order.length > 0) {
|
this.onListenerChange = this.onListenerChange.bind(this);
|
||||||
var selected_post = selected_list.posts[selected_list.order[0]];
|
|
||||||
if ((selected_post.id === this.state.post_id && this.state.title === "Post") || selected_post.root_id === this.state.post_id) {
|
this.state = {title: '', postId: '', channelId: '', selectedList: PostStore.getSelectedPost(), comments: 0};
|
||||||
|
}
|
||||||
|
handleDelete() {
|
||||||
|
Client.deletePost(this.state.channelId, this.state.postId,
|
||||||
|
function deleteSuccess() {
|
||||||
|
var selectedList = this.state.selectedList;
|
||||||
|
if (selectedList && selectedList.order && selectedList.order.length > 0) {
|
||||||
|
var selectedPost = selectedList.posts[selectedList.order[0]];
|
||||||
|
if ((selectedPost.id === this.state.postId && this.state.title === 'Post') || selectedPost.root_id === this.state.postId) {
|
||||||
AppDispatcher.handleServerAction({
|
AppDispatcher.handleServerAction({
|
||||||
type: ActionTypes.RECIEVED_SEARCH,
|
type: ActionTypes.RECIEVED_SEARCH,
|
||||||
results: null
|
results: null
|
||||||
@@ -27,14 +35,14 @@ module.exports = React.createClass({
|
|||||||
type: ActionTypes.RECIEVED_POST_SELECTED,
|
type: ActionTypes.RECIEVED_POST_SELECTED,
|
||||||
results: null
|
results: null
|
||||||
});
|
});
|
||||||
} else if (selected_post.id === this.state.post_id && this.state.title === "Comment") {
|
} else if (selectedPost.id === this.state.postId && this.state.title === 'Comment') {
|
||||||
if (selected_post.root_id && selected_post.root_id.length > 0 && selected_list.posts[selected_post.root_id]) {
|
if (selectedPost.root_id && selectedPost.root_id.length > 0 && selectedList.posts[selectedPost.root_id]) {
|
||||||
selected_list.order = [selected_post.root_id];
|
selectedList.order = [selectedPost.root_id];
|
||||||
delete selected_list.posts[selected_post.id];
|
delete selectedList.posts[selectedPost.id];
|
||||||
|
|
||||||
AppDispatcher.handleServerAction({
|
AppDispatcher.handleServerAction({
|
||||||
type: ActionTypes.RECIEVED_POST_SELECTED,
|
type: ActionTypes.RECIEVED_POST_SELECTED,
|
||||||
post_list: selected_list
|
post_list: selectedList
|
||||||
});
|
});
|
||||||
|
|
||||||
AppDispatcher.handleServerAction({
|
AppDispatcher.handleServerAction({
|
||||||
@@ -44,67 +52,97 @@ module.exports = React.createClass({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PostStore.removePost(this.state.post_id, this.state.channel_id);
|
PostStore.removePost(this.state.postId, this.state.channelId);
|
||||||
AsyncClient.getPosts(this.state.channel_id);
|
AsyncClient.getPosts(this.state.channelId);
|
||||||
}.bind(this),
|
}.bind(this),
|
||||||
function(err) {
|
function deleteFailed(err) {
|
||||||
AsyncClient.dispatchError(err, "deletePost");
|
AsyncClient.dispatchError(err, 'deletePost');
|
||||||
}.bind(this)
|
}
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
componentDidMount: function() {
|
componentDidMount() {
|
||||||
var self = this;
|
$(React.findDOMNode(this.refs.modal)).on('show.bs.modal', function freshOpen(e) {
|
||||||
$(this.refs.modal.getDOMNode()).on('show.bs.modal', function(e) {
|
|
||||||
var newState = {};
|
var newState = {};
|
||||||
if(BrowserStore.getItem('edit_state_transfer')) {
|
if (BrowserStore.getItem('edit_state_transfer')) {
|
||||||
newState = BrowserStore.getItem('edit_state_transfer');
|
newState = BrowserStore.getItem('edit_state_transfer');
|
||||||
BrowserStore.removeItem('edit_state_transfer');
|
BrowserStore.removeItem('edit_state_transfer');
|
||||||
} else {
|
} else {
|
||||||
var button = e.relatedTarget;
|
var button = e.relatedTarget;
|
||||||
newState = { title: $(button).attr('data-title'), channel_id: $(button).attr('data-channelid'), post_id: $(button).attr('data-postid'), comments: $(button).attr('data-comments') };
|
newState = {title: $(button).attr('data-title'), channelId: $(button).attr('data-channelid'), postId: $(button).attr('data-postid'), comments: $(button).attr('data-comments')};
|
||||||
}
|
}
|
||||||
self.setState(newState);
|
this.setState(newState);
|
||||||
});
|
}.bind(this));
|
||||||
PostStore.addSelectedPostChangeListener(this._onChange);
|
PostStore.addSelectedPostChangeListener(this.onListenerChange);
|
||||||
},
|
}
|
||||||
componentWillUnmount: function() {
|
componentWillUnmount() {
|
||||||
PostStore.removeSelectedPostChangeListener(this._onChange);
|
PostStore.removeSelectedPostChangeListener(this.onListenerChange);
|
||||||
},
|
}
|
||||||
_onChange: function() {
|
onListenerChange() {
|
||||||
var newList = PostStore.getSelectedPost();
|
var newList = PostStore.getSelectedPost();
|
||||||
if (!utils.areStatesEqual(this.state.selectedList, newList)) {
|
if (!Utils.areStatesEqual(this.state.selectedList, newList)) {
|
||||||
this.setState({ selectedList: newList });
|
this.setState({selectedList: newList});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
var error = null;
|
||||||
|
if (this.state.error) {
|
||||||
|
error = <div className='form-group has-error'><label className='control-label'>{this.state.error}</label></div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
var commentWarning = '';
|
||||||
|
if (this.state.comments > 0) {
|
||||||
|
commentWarning = 'This post has ' + this.state.comments + ' comment(s) on it.';
|
||||||
}
|
}
|
||||||
},
|
|
||||||
getInitialState: function() {
|
|
||||||
return { title: "", post_id: "", channel_id: "", selectedList: PostStore.getSelectedPost(), comments: 0 };
|
|
||||||
},
|
|
||||||
render: function() {
|
|
||||||
var error = this.state.error ? <div className='form-group has-error'><label className='control-label'>{ this.state.error }</label></div> : null;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="modal fade" id="delete_post" ref="modal" role="dialog" tabIndex="-1" aria-hidden="true">
|
<div
|
||||||
<div className="modal-dialog modal-push-down">
|
className='modal fade'
|
||||||
<div className="modal-content">
|
id='delete_post'
|
||||||
<div className="modal-header">
|
ref='modal'
|
||||||
<button type="button" className="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
role='dialog'
|
||||||
<h4 className="modal-title">Confirm {this.state.title} Delete</h4>
|
tabIndex='-1'
|
||||||
|
aria-hidden='true'
|
||||||
|
>
|
||||||
|
<div className='modal-dialog modal-push-down'>
|
||||||
|
<div className='modal-content'>
|
||||||
|
<div className='modal-header'>
|
||||||
|
<button
|
||||||
|
type='button'
|
||||||
|
className='close'
|
||||||
|
data-dismiss='modal'
|
||||||
|
aria-label='Close'
|
||||||
|
>
|
||||||
|
<span aria-hidden='true'>×</span>
|
||||||
|
</button>
|
||||||
|
<h4 className='modal-title'>Confirm {this.state.title} Delete</h4>
|
||||||
</div>
|
</div>
|
||||||
<div className="modal-body">
|
<div className='modal-body'>
|
||||||
Are you sure you want to delete the {this.state.title.toLowerCase()}?
|
Are you sure you want to delete the {this.state.title.toLowerCase()}?
|
||||||
<br/>
|
<br/>
|
||||||
<br/>
|
<br/>
|
||||||
{ this.state.comments > 0 ?
|
{commentWarning}
|
||||||
"This post has " + this.state.comments + " comment(s) on it."
|
|
||||||
: "" }
|
|
||||||
</div>
|
</div>
|
||||||
<div className="modal-footer">
|
{error}
|
||||||
<button type="button" className="btn btn-default" data-dismiss="modal">Cancel</button>
|
<div className='modal-footer'>
|
||||||
<button type="button" className="btn btn-danger" data-dismiss="modal" onClick={this.handleDelete}>Delete</button>
|
<button
|
||||||
|
type='button'
|
||||||
|
className='btn btn-default'
|
||||||
|
data-dismiss='modal'
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type='button'
|
||||||
|
className='btn btn-danger'
|
||||||
|
data-dismiss='modal'
|
||||||
|
onClick={this.handleDelete}
|
||||||
|
>
|
||||||
|
Delete
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|||||||
@@ -1,35 +1,58 @@
|
|||||||
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
|
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
|
||||||
// See License.txt for license information.
|
// See License.txt for license information.
|
||||||
|
|
||||||
module.exports = React.createClass({
|
export default class EmailVerify extends React.Component {
|
||||||
handleResend: function() {
|
constructor(props) {
|
||||||
window.location.href = window.location.href + "&resend=true"
|
super(props);
|
||||||
},
|
|
||||||
render: function() {
|
this.handleResend = this.handleResend.bind(this);
|
||||||
var title = "";
|
|
||||||
var body = "";
|
this.state = {};
|
||||||
var resend = "";
|
}
|
||||||
if (this.props.isVerified === "true") {
|
handleResend() {
|
||||||
title = config.SiteName + " Email Verified";
|
window.location.href = window.location.href + '&resend=true';
|
||||||
body = <p>Your email has been verified! Click <a href={this.props.teamURL + "?email=" + this.props.userEmail}>here</a> to log in.</p>;
|
}
|
||||||
|
render() {
|
||||||
|
var title = '';
|
||||||
|
var body = '';
|
||||||
|
var resend = '';
|
||||||
|
if (this.props.isVerified === 'true') {
|
||||||
|
title = config.SiteName + ' Email Verified';
|
||||||
|
body = <p>Your email has been verified! Click <a href={this.props.teamURL + '?email=' + this.props.userEmail}>here</a> to log in.</p>;
|
||||||
} else {
|
} else {
|
||||||
title = config.SiteName + " Email Not Verified";
|
title = config.SiteName + ' Email Not Verified';
|
||||||
body = <p>Please verify your email address. Check your inbox for an email.</p>;
|
body = <p>Please verify your email address. Check your inbox for an email.</p>;
|
||||||
resend = <button onClick={this.handleResend} className="btn btn-primary">Resend Email</button>
|
resend = (<button
|
||||||
|
onClick={this.handleResend}
|
||||||
|
className='btn btn-primary'
|
||||||
|
>
|
||||||
|
Resend Email
|
||||||
|
</button>);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="col-sm-offset-4 col-sm-4">
|
<div className='col-sm-offset-4 col-sm-4'>
|
||||||
<div className="panel panel-default">
|
<div className='panel panel-default'>
|
||||||
<div className="panel-heading">
|
<div className='panel-heading'>
|
||||||
<h3 className="panel-title">{ title }</h3>
|
<h3 className='panel-title'>{title}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div className="panel-body">
|
<div className='panel-body'>
|
||||||
{ body }
|
{body}
|
||||||
{ resend }
|
{resend}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
|
EmailVerify.defaultProps = {
|
||||||
|
isVerified: 'false',
|
||||||
|
teamURL: '',
|
||||||
|
userEmail: ''
|
||||||
|
};
|
||||||
|
EmailVerify.propTypes = {
|
||||||
|
isVerified: React.PropTypes.string,
|
||||||
|
teamURL: React.PropTypes.string,
|
||||||
|
userEmail: React.PropTypes.string
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,14 +1,17 @@
|
|||||||
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
|
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
|
||||||
// See License.txt for license information.
|
// See License.txt for license information.
|
||||||
|
|
||||||
var UserStore = require('../stores/user_store.jsx');
|
var Utils = require('../utils/utils.jsx');
|
||||||
var ChannelStore = require('../stores/channel_store.jsx');
|
|
||||||
var client = require('../utils/client.jsx');
|
|
||||||
var utils = require('../utils/utils.jsx');
|
|
||||||
var Constants = require('../utils/constants.jsx');
|
|
||||||
|
|
||||||
module.exports = React.createClass({
|
export default class FilePreview extends React.Component {
|
||||||
handleRemove: function(e) {
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.handleRemove = this.handleRemove.bind(this);
|
||||||
|
|
||||||
|
this.state = {};
|
||||||
|
}
|
||||||
|
handleRemove(e) {
|
||||||
var previewDiv = e.target.parentNode.parentNode;
|
var previewDiv = e.target.parentNode.parentNode;
|
||||||
|
|
||||||
if (previewDiv.hasAttribute('data-filename')) {
|
if (previewDiv.hasAttribute('data-filename')) {
|
||||||
@@ -16,51 +19,96 @@ module.exports = React.createClass({
|
|||||||
} else if (previewDiv.hasAttribute('data-client-id')) {
|
} else if (previewDiv.hasAttribute('data-client-id')) {
|
||||||
this.props.onRemove(previewDiv.getAttribute('data-client-id'));
|
this.props.onRemove(previewDiv.getAttribute('data-client-id'));
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
render: function() {
|
render() {
|
||||||
var previews = [];
|
var previews = [];
|
||||||
this.props.files.forEach(function(filename) {
|
this.props.files.forEach(function setupPreview(fullFilename) {
|
||||||
|
var filename = fullFilename;
|
||||||
var originalFilename = filename;
|
var originalFilename = filename;
|
||||||
var filenameSplit = filename.split('.');
|
var filenameSplit = filename.split('.');
|
||||||
var ext = filenameSplit[filenameSplit.length-1];
|
var ext = filenameSplit[filenameSplit.length - 1];
|
||||||
var type = utils.getFileType(ext);
|
var type = Utils.getFileType(ext);
|
||||||
// This is a temporary patch to fix issue with old files using absolute paths
|
|
||||||
if (filename.indexOf("/api/v1/files/get") != -1) {
|
|
||||||
filename = filename.split("/api/v1/files/get")[1];
|
|
||||||
}
|
|
||||||
filename = utils.getWindowLocationOrigin() + "/api/v1/files/get" + filename;
|
|
||||||
|
|
||||||
if (type === "image") {
|
// This is a temporary patch to fix issue with old files using absolute paths
|
||||||
|
|
||||||
|
if (filename.indexOf('/api/v1/files/get') !== -1) {
|
||||||
|
filename = filename.split('/api/v1/files/get')[1];
|
||||||
|
}
|
||||||
|
filename = Utils.getWindowLocationOrigin() + '/api/v1/files/get' + filename;
|
||||||
|
|
||||||
|
if (type === 'image') {
|
||||||
previews.push(
|
previews.push(
|
||||||
<div key={filename} className="preview-div" data-filename={originalFilename}>
|
<div
|
||||||
<img className="preview-img" src={filename}/>
|
key={filename}
|
||||||
<a className="remove-preview" onClick={this.handleRemove}><i className="glyphicon glyphicon-remove"/></a>
|
className='preview-div'
|
||||||
|
data-filename={originalFilename}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
className='preview-img'
|
||||||
|
src={filename}
|
||||||
|
/>
|
||||||
|
<a
|
||||||
|
className='remove-preview'
|
||||||
|
onClick={this.handleRemove}
|
||||||
|
>
|
||||||
|
<i className='glyphicon glyphicon-remove'/>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
previews.push(
|
previews.push(
|
||||||
<div key={filename} className="preview-div custom-file" data-filename={originalFilename}>
|
<div
|
||||||
<div className={"file-icon "+utils.getIconClassName(type)}/>
|
key={filename}
|
||||||
<a className="remove-preview" onClick={this.handleRemove}><i className="glyphicon glyphicon-remove"/></a>
|
className='preview-div custom-file'
|
||||||
|
data-filename={originalFilename}
|
||||||
|
>
|
||||||
|
<div className={'file-icon ' + Utils.getIconClassName(type)}/>
|
||||||
|
<a
|
||||||
|
className='remove-preview'
|
||||||
|
onClick={this.handleRemove}
|
||||||
|
>
|
||||||
|
<i className='glyphicon glyphicon-remove'/>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
||||||
this.props.uploadsInProgress.forEach(function(clientId) {
|
this.props.uploadsInProgress.forEach(function addUploadsInProgress(clientId) {
|
||||||
previews.push(
|
previews.push(
|
||||||
<div className="preview-div" data-client-id={clientId}>
|
<div
|
||||||
<img className="spinner" src="/static/images/load.gif"/>
|
key={clientId}
|
||||||
<a className="remove-preview" onClick={this.handleRemove}><i className="glyphicon glyphicon-remove"/></a>
|
className='preview-div'
|
||||||
|
data-client-id={clientId}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
className='spinner'
|
||||||
|
src='/static/images/load.gif'
|
||||||
|
/>
|
||||||
|
<a
|
||||||
|
className='remove-preview'
|
||||||
|
onClick={this.handleRemove}
|
||||||
|
>
|
||||||
|
<i className='glyphicon glyphicon-remove'/>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="preview-container">
|
<div className='preview-container'>
|
||||||
{previews}
|
{previews}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
|
FilePreview.defaultProps = {
|
||||||
|
files: null,
|
||||||
|
uploadsInProgress: null
|
||||||
|
};
|
||||||
|
FilePreview.propTypes = {
|
||||||
|
onRemove: React.PropTypes.func.isRequired,
|
||||||
|
files: React.PropTypes.array,
|
||||||
|
uploadsInProgress: React.PropTypes.array
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,30 +1,57 @@
|
|||||||
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
|
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
|
||||||
// See License.txt for license information.
|
// See License.txt for license information.
|
||||||
var UserStore = require("../stores/user_store.jsx");
|
var UserStore = require('../stores/user_store.jsx');
|
||||||
|
|
||||||
module.exports = React.createClass({
|
export default class Mention extends React.Component {
|
||||||
handleClick: function() {
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.handleClick = this.handleClick.bind(this);
|
||||||
|
|
||||||
|
this.state = null;
|
||||||
|
}
|
||||||
|
handleClick() {
|
||||||
this.props.handleClick(this.props.username);
|
this.props.handleClick(this.props.username);
|
||||||
},
|
}
|
||||||
getInitialState: function() {
|
render() {
|
||||||
return null;
|
|
||||||
},
|
|
||||||
render: function() {
|
|
||||||
var self = this;
|
|
||||||
var icon;
|
var icon;
|
||||||
var timestamp = UserStore.getCurrentUser().update_at;
|
var timestamp = UserStore.getCurrentUser().update_at;
|
||||||
if (this.props.id === "allmention" || this.props.id === "channelmention") {
|
if (this.props.id === 'allmention' || this.props.id === 'channelmention') {
|
||||||
icon = <span><i className="mention-img fa fa-users fa-2x"></i></span>;
|
icon = <span><i className='mention-img fa fa-users fa-2x'></i></span>;
|
||||||
} else if (this.props.id != null) {
|
} else if (this.props.id != null) {
|
||||||
icon = <span><img className="mention-img" src={"/api/v1/users/" + this.props.id + "/image?time=" + timestamp}/></span>;
|
icon = (<span><img
|
||||||
|
className='mention-img'
|
||||||
|
src={'/api/v1/users/' + this.props.id + '/image?time=' + timestamp}
|
||||||
|
/>
|
||||||
|
</span>);
|
||||||
} else {
|
} else {
|
||||||
icon = <span><i className="mention-img fa fa-users fa-2x"></i></span>;
|
icon = <span><i className='mention-img fa fa-users fa-2x'></i></span>;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div className={"mentions-name " + this.props.isFocused} id={this.props.id + "_mentions"} onClick={this.handleClick} onMouseEnter={this.props.handleMouseEnter}>
|
<div
|
||||||
<div className="pull-left">{icon}</div>
|
className={'mentions-name ' + this.props.isFocused}
|
||||||
<div className="pull-left mention-align"><span>@{this.props.username}</span><span className="mention-fullname">{this.props.secondary_text}</span></div>
|
id={this.props.id + '_mentions'}
|
||||||
|
onClick={this.handleClick}
|
||||||
|
onMouseEnter={this.props.handleMouseEnter}
|
||||||
|
>
|
||||||
|
<div className='pull-left'>{icon}</div>
|
||||||
|
<div className='pull-left mention-align'><span>@{this.props.username}</span><span className='mention-fullname'>{this.props.secondary_text}</span></div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
|
Mention.defaultProps = {
|
||||||
|
username: '',
|
||||||
|
id: '',
|
||||||
|
isFocused: '',
|
||||||
|
secondary_text: ''
|
||||||
|
};
|
||||||
|
Mention.propTypes = {
|
||||||
|
handleClick: React.PropTypes.func.isRequired,
|
||||||
|
handleMouseEnter: React.PropTypes.func.isRequired,
|
||||||
|
username: React.PropTypes.string,
|
||||||
|
id: React.PropTypes.string,
|
||||||
|
isFocused: React.PropTypes.string,
|
||||||
|
secondary_text: React.PropTypes.string
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,17 +1,30 @@
|
|||||||
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
|
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
|
||||||
// See License.txt for license information.
|
// See License.txt for license information.
|
||||||
|
|
||||||
var utils = require('../utils/utils.jsx');
|
var Utils = require('../utils/utils.jsx');
|
||||||
|
|
||||||
module.exports = React.createClass({
|
export default class MessageWrapper extends React.Component {
|
||||||
render: function() {
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {};
|
||||||
|
}
|
||||||
|
render() {
|
||||||
if (this.props.message) {
|
if (this.props.message) {
|
||||||
var inner = utils.textToJsx(this.props.message, this.props.options);
|
var inner = Utils.textToJsx(this.props.message, this.props.options);
|
||||||
return (
|
return (
|
||||||
<div>{inner}</div>
|
<div>{inner}</div>
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
return <div/>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return <div/>;
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
|
MessageWrapper.defaultProps = {
|
||||||
|
message: null,
|
||||||
|
options: null
|
||||||
|
};
|
||||||
|
MessageWrapper.propTypes = {
|
||||||
|
message: React.PropTypes.string,
|
||||||
|
options: React.PropTypes.object
|
||||||
|
};
|
||||||
|
|||||||
209
web/react/components/navbar_dropdown.jsx
Обычный файл
209
web/react/components/navbar_dropdown.jsx
Обычный файл
@@ -0,0 +1,209 @@
|
|||||||
|
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
|
||||||
|
// See License.txt for license information.
|
||||||
|
|
||||||
|
var Utils = require('../utils/utils.jsx');
|
||||||
|
var client = require('../utils/client.jsx');
|
||||||
|
var UserStore = require('../stores/user_store.jsx');
|
||||||
|
var TeamStore = require('../stores/team_store.jsx');
|
||||||
|
|
||||||
|
var Constants = require('../utils/constants.jsx');
|
||||||
|
|
||||||
|
function getStateFromStores() {
|
||||||
|
return {teams: UserStore.getTeams(), currentTeam: TeamStore.getCurrent()};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class NavbarDropdown extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.blockToggle = false;
|
||||||
|
|
||||||
|
this.handleLogoutClick = this.handleLogoutClick.bind(this);
|
||||||
|
this.onListenerChange = this.onListenerChange.bind(this);
|
||||||
|
|
||||||
|
this.state = getStateFromStores();
|
||||||
|
}
|
||||||
|
handleLogoutClick(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
client.logout();
|
||||||
|
}
|
||||||
|
componentDidMount() {
|
||||||
|
UserStore.addTeamsChangeListener(this.onListenerChange);
|
||||||
|
TeamStore.addChangeListener(this.onListenerChange);
|
||||||
|
|
||||||
|
$(React.findDOMNode(this.refs.dropdown)).on('hide.bs.dropdown', function resetDropdown() {
|
||||||
|
this.blockToggle = true;
|
||||||
|
setTimeout(function blockTimeout() {
|
||||||
|
this.blockToggle = false;
|
||||||
|
}.bind(this), 100);
|
||||||
|
}.bind(this));
|
||||||
|
}
|
||||||
|
componentWillUnmount() {
|
||||||
|
UserStore.removeTeamsChangeListener(this.onListenerChange);
|
||||||
|
TeamStore.removeChangeListener(this.onListenerChange);
|
||||||
|
|
||||||
|
$(React.findDOMNode(this.refs.dropdown)).off('hide.bs.dropdown');
|
||||||
|
}
|
||||||
|
onListenerChange() {
|
||||||
|
var newState = getStateFromStores();
|
||||||
|
if (!Utils.areStatesEqual(newState, this.state)) {
|
||||||
|
this.setState(newState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
var teamLink = '';
|
||||||
|
var inviteLink = '';
|
||||||
|
var manageLink = '';
|
||||||
|
var currentUser = UserStore.getCurrentUser();
|
||||||
|
var isAdmin = false;
|
||||||
|
var teamSettings = null;
|
||||||
|
|
||||||
|
if (currentUser != null) {
|
||||||
|
isAdmin = currentUser.roles.indexOf('admin') > -1;
|
||||||
|
|
||||||
|
inviteLink = (<li>
|
||||||
|
<a
|
||||||
|
href='#'
|
||||||
|
data-toggle='modal'
|
||||||
|
data-target='#invite_member'
|
||||||
|
>
|
||||||
|
Invite New Member
|
||||||
|
</a>
|
||||||
|
</li>);
|
||||||
|
|
||||||
|
if (this.props.teamType === 'O') {
|
||||||
|
teamLink = (
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href='#'
|
||||||
|
data-toggle='modal'
|
||||||
|
data-target='#get_link'
|
||||||
|
data-title='Team Invite'
|
||||||
|
data-value={Utils.getWindowLocationOrigin() + '/signup_user_complete/?id=' + currentUser.team_id}
|
||||||
|
>
|
||||||
|
Get Team Invite Link
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isAdmin) {
|
||||||
|
manageLink = (<li>
|
||||||
|
<a
|
||||||
|
href='#'
|
||||||
|
data-toggle='modal'
|
||||||
|
data-target='#team_members'
|
||||||
|
>
|
||||||
|
Manage Team
|
||||||
|
</a>
|
||||||
|
</li>);
|
||||||
|
teamSettings = (<li>
|
||||||
|
<a
|
||||||
|
href='#'
|
||||||
|
data-toggle='modal'
|
||||||
|
data-target='#team_settings'
|
||||||
|
>
|
||||||
|
Team Settings
|
||||||
|
</a>
|
||||||
|
</li>);
|
||||||
|
}
|
||||||
|
|
||||||
|
var teams = [];
|
||||||
|
|
||||||
|
teams.push(<li
|
||||||
|
className='divider'
|
||||||
|
key='div'
|
||||||
|
>
|
||||||
|
</li>);
|
||||||
|
if (this.state.teams.length > 1 && this.state.currentTeam) {
|
||||||
|
var curTeamName = this.state.currentTeam.name;
|
||||||
|
this.state.teams.forEach(function listTeams(teamName) {
|
||||||
|
if (teamName !== curTeamName) {
|
||||||
|
teams.push(<li key={teamName}><a href={Utils.getWindowLocationOrigin() + '/' + teamName}>Switch to {teamName}</a></li>);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
teams.push(<li key='newTeam_li'>
|
||||||
|
<a
|
||||||
|
key='newTeam_a'
|
||||||
|
target='_blank'
|
||||||
|
href={Utils.getWindowLocationOrigin() + '/signup_team'}
|
||||||
|
>
|
||||||
|
Create a New Team
|
||||||
|
</a>
|
||||||
|
</li>);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ul className='nav navbar-nav navbar-right'>
|
||||||
|
<li
|
||||||
|
ref='dropdown'
|
||||||
|
className='dropdown'
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href='#'
|
||||||
|
className='dropdown-toggle'
|
||||||
|
data-toggle='dropdown'
|
||||||
|
role='button'
|
||||||
|
aria-expanded='false'
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
className='dropdown__icon'
|
||||||
|
dangerouslySetInnerHTML={{__html: Constants.MENU_ICON}}
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
<ul
|
||||||
|
className='dropdown-menu'
|
||||||
|
role='menu'
|
||||||
|
>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href='#'
|
||||||
|
data-toggle='modal'
|
||||||
|
data-target='#user_settings'
|
||||||
|
>
|
||||||
|
Account Settings
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{teamSettings}
|
||||||
|
{inviteLink}
|
||||||
|
{teamLink}
|
||||||
|
{manageLink}
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href='#'
|
||||||
|
onClick={this.handleLogoutClick}
|
||||||
|
>
|
||||||
|
Logout
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{teams}
|
||||||
|
<li className='divider'></li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
target='_blank'
|
||||||
|
href={config.HelpLink}
|
||||||
|
>
|
||||||
|
Help
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
target='_blank'
|
||||||
|
href={config.ReportProblemLink}
|
||||||
|
>
|
||||||
|
Report a Problem
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NavbarDropdown.defaultProps = {
|
||||||
|
teamType: ''
|
||||||
|
};
|
||||||
|
NavbarDropdown.propTypes = {
|
||||||
|
teamType: React.PropTypes.string
|
||||||
|
};
|
||||||
@@ -23,27 +23,30 @@ function getCountsStateFromStores() {
|
|||||||
return {count: count};
|
return {count: count};
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = React.createClass({
|
export default class NotifyCounts extends React.Component {
|
||||||
displayName: 'NotifyCounts',
|
constructor(props) {
|
||||||
componentDidMount: function() {
|
super(props);
|
||||||
|
|
||||||
|
this.onListenerChange = this.onListenerChange.bind(this);
|
||||||
|
|
||||||
|
this.state = getCountsStateFromStores();
|
||||||
|
}
|
||||||
|
componentDidMount() {
|
||||||
ChannelStore.addChangeListener(this.onListenerChange);
|
ChannelStore.addChangeListener(this.onListenerChange);
|
||||||
},
|
}
|
||||||
componentWillUnmount: function() {
|
componentWillUnmount() {
|
||||||
ChannelStore.removeChangeListener(this.onListenerChange);
|
ChannelStore.removeChangeListener(this.onListenerChange);
|
||||||
},
|
}
|
||||||
onListenerChange: function() {
|
onListenerChange() {
|
||||||
var newState = getCountsStateFromStores();
|
var newState = getCountsStateFromStores();
|
||||||
if (!utils.areStatesEqual(newState, this.state)) {
|
if (!utils.areStatesEqual(newState, this.state)) {
|
||||||
this.setState(newState);
|
this.setState(newState);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
getInitialState: function() {
|
render() {
|
||||||
return getCountsStateFromStores();
|
|
||||||
},
|
|
||||||
render: function() {
|
|
||||||
if (this.state.count) {
|
if (this.state.count) {
|
||||||
return <span className='badge badge-notify'>{this.state.count}</span>;
|
return <span className='badge badge-notify'>{this.state.count}</span>;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|||||||
@@ -1,137 +1,27 @@
|
|||||||
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
|
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
|
||||||
// See License.txt for license information.
|
// See License.txt for license information.
|
||||||
|
|
||||||
var utils = require('../utils/utils.jsx');
|
var PasswordResetSendLink = require('./password_reset_send_link.jsx');
|
||||||
var client = require('../utils/client.jsx');
|
var PasswordResetForm = require('./password_reset_form.jsx');
|
||||||
var UserStore = require('../stores/user_store.jsx');
|
|
||||||
|
|
||||||
SendResetPasswordLink = React.createClass({
|
export default class PasswordReset extends React.Component {
|
||||||
handleSendLink: function(e) {
|
constructor(props) {
|
||||||
e.preventDefault();
|
super(props);
|
||||||
var state = {};
|
|
||||||
|
|
||||||
var email = this.refs.email.getDOMNode().value.trim();
|
this.state = {};
|
||||||
if (!email) {
|
|
||||||
state.error = "Please enter a valid email address."
|
|
||||||
this.setState(state);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
render() {
|
||||||
state.error = null;
|
if (this.props.isReset === 'false') {
|
||||||
this.setState(state);
|
|
||||||
|
|
||||||
data = {};
|
|
||||||
data['email'] = email;
|
|
||||||
data['name'] = this.props.teamName;
|
|
||||||
|
|
||||||
client.sendPasswordReset(data,
|
|
||||||
function(data) {
|
|
||||||
this.setState({ error: null, update_text: <p>A password reset link has been sent to <b>{email}</b> for your <b>{this.props.teamDisplayName}</b> team on {window.location.hostname}.</p>, more_update_text: "Please check your inbox." });
|
|
||||||
$(this.refs.reset_form.getDOMNode()).hide();
|
|
||||||
}.bind(this),
|
|
||||||
function(err) {
|
|
||||||
this.setState({ error: err.message, update_text: null, more_update_text: null });
|
|
||||||
}.bind(this)
|
|
||||||
);
|
|
||||||
},
|
|
||||||
getInitialState: function() {
|
|
||||||
return {};
|
|
||||||
},
|
|
||||||
render: function() {
|
|
||||||
var update_text = this.state.update_text ? <div className="reset-form alert alert-success">{this.state.update_text}{this.state.more_update_text}</div> : null;
|
|
||||||
var error = this.state.error ? <div className="form-group has-error"><label className="control-label">{this.state.error}</label></div> : null;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="col-sm-12">
|
<PasswordResetSendLink
|
||||||
<div className="signup-team__container">
|
|
||||||
<h3>Password Reset</h3>
|
|
||||||
{ update_text }
|
|
||||||
<form onSubmit={this.handleSendLink} ref="reset_form">
|
|
||||||
<p>{"To reset your password, enter the email address you used to sign up for " + this.props.teamDisplayName + "."}</p>
|
|
||||||
<div className={error ? 'form-group has-error' : 'form-group'}>
|
|
||||||
<input type="text" className="form-control" name="email" ref="email" placeholder="Email" />
|
|
||||||
</div>
|
|
||||||
{ error }
|
|
||||||
<button type="submit" className="btn btn-primary">Reset my password</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
ResetPassword = React.createClass({
|
|
||||||
handlePasswordReset: function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
var state = {};
|
|
||||||
|
|
||||||
var password = this.refs.password.getDOMNode().value.trim();
|
|
||||||
if (!password || password.length < 5) {
|
|
||||||
state.error = "Please enter at least 5 characters."
|
|
||||||
this.setState(state);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
state.error = null;
|
|
||||||
this.setState(state);
|
|
||||||
|
|
||||||
data = {};
|
|
||||||
data['new_password'] = password;
|
|
||||||
data['hash'] = this.props.hash;
|
|
||||||
data['data'] = this.props.data;
|
|
||||||
data['name'] = this.props.teamName;
|
|
||||||
|
|
||||||
client.resetPassword(data,
|
|
||||||
function(data) {
|
|
||||||
this.setState({ error: null, update_text: "Your password has been updated successfully." });
|
|
||||||
}.bind(this),
|
|
||||||
function(err) {
|
|
||||||
this.setState({ error: err.message, update_text: null });
|
|
||||||
}.bind(this)
|
|
||||||
);
|
|
||||||
},
|
|
||||||
getInitialState: function() {
|
|
||||||
return {};
|
|
||||||
},
|
|
||||||
render: function() {
|
|
||||||
var update_text = this.state.update_text ? <div className="form-group"><br/><label className="control-label reset-form">{this.state.update_text} Click <a href={"/" + this.props.teamName + "/login"}>here</a> to log in.</label></div> : null;
|
|
||||||
var error = this.state.error ? <div className="form-group has-error"><label className="control-label">{this.state.error}</label></div> : null;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="col-sm-12">
|
|
||||||
<div className="signup-team__container">
|
|
||||||
<h3>Password Reset</h3>
|
|
||||||
<form onSubmit={this.handlePasswordReset}>
|
|
||||||
<p>{"Enter a new password for your " + this.props.teamDisplayName + " " + config.SiteName + " account."}</p>
|
|
||||||
<div className={error ? 'form-group has-error' : 'form-group'}>
|
|
||||||
<input type="password" className="form-control" name="password" ref="password" placeholder="Password" />
|
|
||||||
</div>
|
|
||||||
{ error }
|
|
||||||
<button type="submit" className="btn btn-primary">Change my password</button>
|
|
||||||
{ update_text }
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = React.createClass({
|
|
||||||
getInitialState: function() {
|
|
||||||
return {};
|
|
||||||
},
|
|
||||||
render: function() {
|
|
||||||
|
|
||||||
if (this.props.isReset === "false") {
|
|
||||||
return (
|
|
||||||
<SendResetPasswordLink
|
|
||||||
teamDisplayName={this.props.teamDisplayName}
|
teamDisplayName={this.props.teamDisplayName}
|
||||||
teamName={this.props.teamName}
|
teamName={this.props.teamName}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
} else {
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ResetPassword
|
<PasswordResetForm
|
||||||
teamDisplayName={this.props.teamDisplayName}
|
teamDisplayName={this.props.teamDisplayName}
|
||||||
teamName={this.props.teamName}
|
teamName={this.props.teamName}
|
||||||
hash={this.props.hash}
|
hash={this.props.hash}
|
||||||
@@ -139,5 +29,19 @@ module.exports = React.createClass({
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
PasswordReset.defaultProps = {
|
||||||
|
isReset: '',
|
||||||
|
teamName: '',
|
||||||
|
teamDisplayName: '',
|
||||||
|
hash: '',
|
||||||
|
data: ''
|
||||||
|
};
|
||||||
|
PasswordReset.propTypes = {
|
||||||
|
isReset: React.PropTypes.string,
|
||||||
|
teamName: React.PropTypes.string,
|
||||||
|
teamDisplayName: React.PropTypes.string,
|
||||||
|
hash: React.PropTypes.string,
|
||||||
|
data: React.PropTypes.string
|
||||||
|
};
|
||||||
|
|||||||
100
web/react/components/password_reset_form.jsx
Обычный файл
100
web/react/components/password_reset_form.jsx
Обычный файл
@@ -0,0 +1,100 @@
|
|||||||
|
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
|
||||||
|
// See License.txt for license information.
|
||||||
|
|
||||||
|
var client = require('../utils/client.jsx');
|
||||||
|
|
||||||
|
export default class PasswordResetForm extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.handlePasswordReset = this.handlePasswordReset.bind(this);
|
||||||
|
|
||||||
|
this.state = {};
|
||||||
|
}
|
||||||
|
handlePasswordReset(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var state = {};
|
||||||
|
|
||||||
|
var password = React.findDOMNode(this.refs.password).value.trim();
|
||||||
|
if (!password || password.length < 5) {
|
||||||
|
state.error = 'Please enter at least 5 characters.';
|
||||||
|
this.setState(state);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
state.error = null;
|
||||||
|
this.setState(state);
|
||||||
|
|
||||||
|
var data = {};
|
||||||
|
data.new_password = password;
|
||||||
|
data.hash = this.props.hash;
|
||||||
|
data.data = this.props.data;
|
||||||
|
data.name = this.props.teamName;
|
||||||
|
|
||||||
|
client.resetPassword(data,
|
||||||
|
function resetSuccess() {
|
||||||
|
this.setState({error: null, updateText: 'Your password has been updated successfully.'});
|
||||||
|
}.bind(this),
|
||||||
|
function resetFailure(err) {
|
||||||
|
this.setState({error: err.message, updateText: null});
|
||||||
|
}.bind(this)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
var updateText = null;
|
||||||
|
if (this.state.updateText) {
|
||||||
|
updateText = <div className='form-group'><br/><label className='control-label reset-form'>{this.state.updateText} Click <a href={'/' + this.props.teamName + '/login'}>here</a> to log in.</label></div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
var error = null;
|
||||||
|
if (this.state.error) {
|
||||||
|
error = <div className='form-group has-error'><label className='control-label'>{this.state.error}</label></div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
var formClass = 'form-group';
|
||||||
|
if (error) {
|
||||||
|
formClass += ' has-error';
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='col-sm-12'>
|
||||||
|
<div className='signup-team__container'>
|
||||||
|
<h3>Password Reset</h3>
|
||||||
|
<form onSubmit={this.handlePasswordReset}>
|
||||||
|
<p>{'Enter a new password for your ' + this.props.teamDisplayName + ' ' + config.SiteName + ' account.'}</p>
|
||||||
|
<div className={formClass}>
|
||||||
|
<input
|
||||||
|
type='password'
|
||||||
|
className='form-control'
|
||||||
|
name='password'
|
||||||
|
ref='password'
|
||||||
|
placeholder='Password'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{error}
|
||||||
|
<button
|
||||||
|
type='submit'
|
||||||
|
className='btn btn-primary'
|
||||||
|
>
|
||||||
|
Change my password
|
||||||
|
</button>
|
||||||
|
{updateText}
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PasswordResetForm.defaultProps = {
|
||||||
|
teamName: '',
|
||||||
|
teamDisplayName: '',
|
||||||
|
hash: '',
|
||||||
|
data: ''
|
||||||
|
};
|
||||||
|
PasswordResetForm.propTypes = {
|
||||||
|
teamName: React.PropTypes.string,
|
||||||
|
teamDisplayName: React.PropTypes.string,
|
||||||
|
hash: React.PropTypes.string,
|
||||||
|
data: React.PropTypes.string
|
||||||
|
};
|
||||||
98
web/react/components/password_reset_send_link.jsx
Обычный файл
98
web/react/components/password_reset_send_link.jsx
Обычный файл
@@ -0,0 +1,98 @@
|
|||||||
|
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
|
||||||
|
// See License.txt for license information.
|
||||||
|
|
||||||
|
var client = require('../utils/client.jsx');
|
||||||
|
|
||||||
|
export default class PasswordResetSendLink extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.handleSendLink = this.handleSendLink.bind(this);
|
||||||
|
|
||||||
|
this.state = {};
|
||||||
|
}
|
||||||
|
handleSendLink(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var state = {};
|
||||||
|
|
||||||
|
var email = React.findDOMNode(this.refs.email).value.trim();
|
||||||
|
if (!email) {
|
||||||
|
state.error = 'Please enter a valid email address.';
|
||||||
|
this.setState(state);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
state.error = null;
|
||||||
|
this.setState(state);
|
||||||
|
|
||||||
|
var data = {};
|
||||||
|
data.email = email;
|
||||||
|
data.name = this.props.teamName;
|
||||||
|
|
||||||
|
client.sendPasswordReset(data,
|
||||||
|
function passwordResetSent() {
|
||||||
|
this.setState({error: null, updateText: <p>A password reset link has been sent to <b>{email}</b> for your <b>{this.props.teamDisplayName}</b> team on {window.location.hostname}.</p>, moreUpdateText: 'Please check your inbox.'});
|
||||||
|
$(React.findDOMNode(this.refs.reset_form)).hide();
|
||||||
|
}.bind(this),
|
||||||
|
function passwordResetFailedToSend(err) {
|
||||||
|
this.setState({error: err.message, update_text: null, moreUpdateText: null});
|
||||||
|
}.bind(this)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
var updateText = null;
|
||||||
|
if (this.state.updateText) {
|
||||||
|
updateText = <div className='reset-form alert alert-success'>{this.state.updateText}{this.state.moreUpdateText}</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
var error = null;
|
||||||
|
if (this.state.error) {
|
||||||
|
error = <div className='form-group has-error'><label className='control-label'>{this.state.error}</label></div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
var formClass = 'form-group';
|
||||||
|
if (error) {
|
||||||
|
formClass += ' has-error';
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='col-sm-12'>
|
||||||
|
<div className='signup-team__container'>
|
||||||
|
<h3>Password Reset</h3>
|
||||||
|
{updateText}
|
||||||
|
<form
|
||||||
|
onSubmit={this.handleSendLink}
|
||||||
|
ref='reset_form'
|
||||||
|
>
|
||||||
|
<p>{'To reset your password, enter the email address you used to sign up for ' + this.props.teamDisplayName + '.'}</p>
|
||||||
|
<div className={formClass}>
|
||||||
|
<input
|
||||||
|
type='text'
|
||||||
|
className='form-control'
|
||||||
|
name='email'
|
||||||
|
ref='email'
|
||||||
|
placeholder='Email'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{error}
|
||||||
|
<button
|
||||||
|
type='submit'
|
||||||
|
className='btn btn-primary'
|
||||||
|
>
|
||||||
|
Reset my password
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PasswordResetSendLink.defaultProps = {
|
||||||
|
teamName: '',
|
||||||
|
teamDisplayName: ''
|
||||||
|
};
|
||||||
|
PasswordResetSendLink.propTypes = {
|
||||||
|
teamName: React.PropTypes.string,
|
||||||
|
teamDisplayName: React.PropTypes.string
|
||||||
|
};
|
||||||
@@ -3,34 +3,61 @@
|
|||||||
|
|
||||||
var UserStore = require('../stores/user_store.jsx');
|
var UserStore = require('../stores/user_store.jsx');
|
||||||
|
|
||||||
module.exports = React.createClass({
|
export default class PostDeletedModal extends React.Component {
|
||||||
getInitialState: function() {
|
constructor(props) {
|
||||||
return { };
|
super(props);
|
||||||
},
|
|
||||||
render: function() {
|
this.state = {};
|
||||||
var currentUser = UserStore.getCurrentUser()
|
}
|
||||||
|
render() {
|
||||||
|
var currentUser = UserStore.getCurrentUser();
|
||||||
|
|
||||||
if (currentUser != null) {
|
if (currentUser != null) {
|
||||||
return (
|
return (
|
||||||
<div className="modal fade" ref="modal" id="post_deleted" tabIndex="-1" role="dialog" aria-hidden="true">
|
<div
|
||||||
<div className="modal-dialog">
|
className='modal fade'
|
||||||
<div className="modal-content">
|
ref='modal'
|
||||||
<div className="modal-header">
|
id='post_deleted'
|
||||||
<button type="button" className="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
tabIndex='-1'
|
||||||
<h4 className="modal-title" id="myModalLabel">Comment could not be posted</h4>
|
role='dialog'
|
||||||
|
aria-hidden='true'
|
||||||
|
>
|
||||||
|
<div className='modal-dialog'>
|
||||||
|
<div className='modal-content'>
|
||||||
|
<div className='modal-header'>
|
||||||
|
<button
|
||||||
|
type='button'
|
||||||
|
className='close'
|
||||||
|
data-dismiss='modal'
|
||||||
|
aria-label='Close'
|
||||||
|
>
|
||||||
|
<span aria-hidden='true'>×</span>
|
||||||
|
</button>
|
||||||
|
<h4
|
||||||
|
className='modal-title'
|
||||||
|
id='myModalLabel'
|
||||||
|
>
|
||||||
|
Comment could not be posted
|
||||||
|
</h4>
|
||||||
</div>
|
</div>
|
||||||
<div className="modal-body">
|
<div className='modal-body'>
|
||||||
<p>Someone deleted the message on which you tried to post a comment.</p>
|
<p>Someone deleted the message on which you tried to post a comment.</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="modal-footer">
|
<div className='modal-footer'>
|
||||||
<button type="button" className="btn btn-primary" data-dismiss="modal">Okay</button>
|
<button
|
||||||
|
type='button'
|
||||||
|
className='btn btn-primary'
|
||||||
|
data-dismiss='modal'
|
||||||
|
>
|
||||||
|
Okay
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else {
|
}
|
||||||
|
|
||||||
return <div/>;
|
return <div/>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ var ChannelStore = require('../stores/channel_store.jsx');
|
|||||||
var UserProfile = require('./user_profile.jsx');
|
var UserProfile = require('./user_profile.jsx');
|
||||||
var UserStore = require('../stores/user_store.jsx');
|
var UserStore = require('../stores/user_store.jsx');
|
||||||
var AppDispatcher = require('../dispatcher/app_dispatcher.jsx');
|
var AppDispatcher = require('../dispatcher/app_dispatcher.jsx');
|
||||||
var utils = require('../utils/utils.jsx');
|
var Utils = require('../utils/utils.jsx');
|
||||||
var Constants = require('../utils/constants.jsx');
|
var Constants = require('../utils/constants.jsx');
|
||||||
var FileAttachmentList = require('./file_attachment_list.jsx');
|
var FileAttachmentList = require('./file_attachment_list.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 ActionTypes = Constants.ActionTypes;
|
var ActionTypes = Constants.ActionTypes;
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ export default class RhsComment extends React.Component {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
var post = this.props.post;
|
var post = this.props.post;
|
||||||
client.createPost(post, post.channel_id,
|
Client.createPost(post, post.channel_id,
|
||||||
function success(data) {
|
function success(data) {
|
||||||
AsyncClient.getPosts(post.channel_id);
|
AsyncClient.getPosts(post.channel_id);
|
||||||
|
|
||||||
@@ -52,7 +52,7 @@ export default class RhsComment extends React.Component {
|
|||||||
this.forceUpdate();
|
this.forceUpdate();
|
||||||
}
|
}
|
||||||
shouldComponentUpdate(nextProps) {
|
shouldComponentUpdate(nextProps) {
|
||||||
if (!utils.areStatesEqual(nextProps.post, this.props.post)) {
|
if (!Utils.areStatesEqual(nextProps.post, this.props.post)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@ export default class RhsComment extends React.Component {
|
|||||||
type = 'Comment';
|
type = 'Comment';
|
||||||
}
|
}
|
||||||
|
|
||||||
var message = utils.textToJsx(post.message);
|
var message = Utils.textToJsx(post.message);
|
||||||
var timestamp = UserStore.getCurrentUser().update_at;
|
var timestamp = UserStore.getCurrentUser().update_at;
|
||||||
|
|
||||||
var loading;
|
var loading;
|
||||||
@@ -182,7 +182,7 @@ export default class RhsComment extends React.Component {
|
|||||||
</li>
|
</li>
|
||||||
<li className='post-header-col'>
|
<li className='post-header-col'>
|
||||||
<time className='post-right-comment-time'>
|
<time className='post-right-comment-time'>
|
||||||
{utils.displayCommentDateTime(post.create_at)}
|
{Utils.displayCommentDateTime(post.create_at)}
|
||||||
</time>
|
</time>
|
||||||
</li>
|
</li>
|
||||||
<li className='post-header-col post-header__reply'>
|
<li className='post-header-col post-header__reply'>
|
||||||
|
|||||||
@@ -1,133 +1,25 @@
|
|||||||
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
|
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
|
||||||
// See License.txt for license information.
|
// See License.txt for license information.
|
||||||
|
|
||||||
var utils = require('../utils/utils.jsx');
|
var NavbarDropdown = require('./navbar_dropdown.jsx');
|
||||||
var client = require('../utils/client.jsx');
|
|
||||||
var UserStore = require('../stores/user_store.jsx');
|
var UserStore = require('../stores/user_store.jsx');
|
||||||
var TeamStore = require('../stores/team_store.jsx');
|
|
||||||
|
|
||||||
var Constants = require('../utils/constants.jsx');
|
export default class SidebarHeader extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
function getStateFromStores() {
|
this.toggleDropdown = this.toggleDropdown.bind(this);
|
||||||
return {teams: UserStore.getTeams(), currentTeam: TeamStore.getCurrent()};
|
|
||||||
}
|
|
||||||
|
|
||||||
var NavbarDropdown = React.createClass({
|
this.state = {};
|
||||||
handleLogoutClick: function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
client.logout();
|
|
||||||
},
|
|
||||||
blockToggle: false,
|
|
||||||
componentDidMount: function() {
|
|
||||||
UserStore.addTeamsChangeListener(this.onListenerChange);
|
|
||||||
TeamStore.addChangeListener(this.onListenerChange);
|
|
||||||
|
|
||||||
var self = this;
|
|
||||||
$(this.refs.dropdown.getDOMNode()).on('hide.bs.dropdown', function() {
|
|
||||||
self.blockToggle = true;
|
|
||||||
setTimeout(function() {
|
|
||||||
self.blockToggle = false;
|
|
||||||
}, 100);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
componentWillUnmount: function() {
|
|
||||||
UserStore.removeTeamsChangeListener(this.onListenerChange);
|
|
||||||
TeamStore.removeChangeListener(this.onListenerChange);
|
|
||||||
|
|
||||||
$(this.refs.dropdown.getDOMNode()).off('hide.bs.dropdown');
|
|
||||||
},
|
|
||||||
onListenerChange: function() {
|
|
||||||
if (this.isMounted()) {
|
|
||||||
var newState = getStateFromStores();
|
|
||||||
if (!utils.areStatesEqual(newState, this.state)) {
|
|
||||||
this.setState(newState);
|
|
||||||
}
|
}
|
||||||
}
|
toggleDropdown() {
|
||||||
},
|
|
||||||
getInitialState: function() {
|
|
||||||
return getStateFromStores();
|
|
||||||
},
|
|
||||||
render: function() {
|
|
||||||
var teamLink = '';
|
|
||||||
var inviteLink = '';
|
|
||||||
var manageLink = '';
|
|
||||||
var currentUser = UserStore.getCurrentUser();
|
|
||||||
var isAdmin = false;
|
|
||||||
var teamSettings = null;
|
|
||||||
|
|
||||||
if (currentUser != null) {
|
|
||||||
isAdmin = currentUser.roles.indexOf('admin') > -1;
|
|
||||||
|
|
||||||
inviteLink = (<li> <a href='#' data-toggle='modal' data-target='#invite_member'>Invite New Member</a> </li>);
|
|
||||||
|
|
||||||
if (this.props.teamType === 'O') {
|
|
||||||
teamLink = (
|
|
||||||
<li>
|
|
||||||
<a href='#' data-toggle='modal' data-target='#get_link' data-title='Team Invite' data-value={utils.getWindowLocationOrigin() + '/signup_user_complete/?id=' + currentUser.team_id}>Get Team Invite Link</a>
|
|
||||||
</li>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isAdmin) {
|
|
||||||
manageLink = (<li> <a href='#' data-toggle='modal' data-target='#team_members'>Manage Team</a> </li>);
|
|
||||||
teamSettings = (<li> <a href='#' data-toggle='modal' data-target='#team_settings'>Team Settings</a> </li>);
|
|
||||||
}
|
|
||||||
|
|
||||||
var teams = [];
|
|
||||||
|
|
||||||
teams.push(<li className='divider' key='div'></li>);
|
|
||||||
if (this.state.teams.length > 1 && this.state.currentTeam) {
|
|
||||||
var curTeamName = this.state.currentTeam.name;
|
|
||||||
this.state.teams.forEach(function(teamName) {
|
|
||||||
if (teamName !== curTeamName) {
|
|
||||||
teams.push(<li key={teamName}><a href={utils.getWindowLocationOrigin() + '/' + teamName}>Switch to {teamName}</a></li>);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
teams.push(<li key='newTeam_li'><a key='newTeam_a' target="_blank" href={utils.getWindowLocationOrigin() + '/signup_team' }>Create a New Team</a></li>);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ul className='nav navbar-nav navbar-right'>
|
|
||||||
<li ref='dropdown' className='dropdown'>
|
|
||||||
<a href='#' className='dropdown-toggle' data-toggle='dropdown' role='button' aria-expanded='false'>
|
|
||||||
<span className='dropdown__icon' dangerouslySetInnerHTML={{__html: Constants.MENU_ICON}} />
|
|
||||||
</a>
|
|
||||||
<ul className='dropdown-menu' role='menu'>
|
|
||||||
<li><a href='#' data-toggle='modal' data-target='#user_settings'>Account Settings</a></li>
|
|
||||||
{teamSettings}
|
|
||||||
{inviteLink}
|
|
||||||
{teamLink}
|
|
||||||
{manageLink}
|
|
||||||
<li><a href='#' onClick={this.handleLogoutClick}>Logout</a></li>
|
|
||||||
{teams}
|
|
||||||
<li className='divider'></li>
|
|
||||||
<li><a target='_blank' href={config.HelpLink}>Help</a></li>
|
|
||||||
<li><a target='_blank' href={config.ReportProblemLink}>Report a Problem</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = React.createClass({
|
|
||||||
displayName: 'SidebarHeader',
|
|
||||||
getDefaultProps: function() {
|
|
||||||
return {
|
|
||||||
teamDisplayName: config.SiteName
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
toggleDropdown: function() {
|
|
||||||
if (this.refs.dropdown.blockToggle) {
|
if (this.refs.dropdown.blockToggle) {
|
||||||
this.refs.dropdown.blockToggle = false;
|
this.refs.dropdown.blockToggle = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$('.team__header').find('.dropdown-toggle').dropdown('toggle');
|
$('.team__header').find('.dropdown-toggle').dropdown('toggle');
|
||||||
},
|
}
|
||||||
|
render() {
|
||||||
render: function() {
|
|
||||||
var me = UserStore.getCurrentUser();
|
var me = UserStore.getCurrentUser();
|
||||||
var profilePicture = null;
|
var profilePicture = null;
|
||||||
|
|
||||||
@@ -136,20 +28,38 @@ module.exports = React.createClass({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (me.last_picture_update) {
|
if (me.last_picture_update) {
|
||||||
profilePicture = (<img className='user__picture' src={'/api/v1/users/' + me.id + '/image?time=' + me.update_at} />);
|
profilePicture = (<img
|
||||||
|
className='user__picture'
|
||||||
|
src={'/api/v1/users/' + me.id + '/image?time=' + me.update_at}
|
||||||
|
/>);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='team__header theme'>
|
<div className='team__header theme'>
|
||||||
<a href='#' onClick={this.toggleDropdown}>
|
<a
|
||||||
|
href='#'
|
||||||
|
onClick={this.toggleDropdown}
|
||||||
|
>
|
||||||
{profilePicture}
|
{profilePicture}
|
||||||
<div className='header__info'>
|
<div className='header__info'>
|
||||||
<div className='user__name'>{'@' + me.username}</div>
|
<div className='user__name'>{'@' + me.username}</div>
|
||||||
<div className='team__name'>{this.props.teamDisplayName }</div>
|
<div className='team__name'>{this.props.teamDisplayName}</div>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
<NavbarDropdown ref='dropdown' teamType={this.props.teamType} />
|
<NavbarDropdown
|
||||||
|
ref='dropdown'
|
||||||
|
teamType={this.props.teamType}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
|
SidebarHeader.defaultProps = {
|
||||||
|
teamDisplayName: config.SiteName,
|
||||||
|
teamType: ''
|
||||||
|
};
|
||||||
|
SidebarHeader.propTypes = {
|
||||||
|
teamDisplayName: React.PropTypes.string,
|
||||||
|
teamType: React.PropTypes.string
|
||||||
|
};
|
||||||
|
|||||||
@@ -4,47 +4,49 @@
|
|||||||
var SearchResults = require('./search_results.jsx');
|
var SearchResults = require('./search_results.jsx');
|
||||||
var RhsThread = require('./rhs_thread.jsx');
|
var RhsThread = require('./rhs_thread.jsx');
|
||||||
var PostStore = require('../stores/post_store.jsx');
|
var PostStore = require('../stores/post_store.jsx');
|
||||||
var utils = require('../utils/utils.jsx');
|
var Utils = require('../utils/utils.jsx');
|
||||||
|
|
||||||
function getStateFromStores(from_search) {
|
function getStateFromStores() {
|
||||||
return { search_visible: PostStore.getSearchResults() != null, post_right_visible: PostStore.getSelectedPost() != null, is_mention_search: PostStore.getIsMentionSearch() };
|
return {search_visible: PostStore.getSearchResults() != null, post_right_visible: PostStore.getSelectedPost() != null, is_mention_search: PostStore.getIsMentionSearch()};
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = React.createClass({
|
export default class SidebarRight extends React.Component {
|
||||||
componentDidMount: function() {
|
constructor(props) {
|
||||||
PostStore.addSearchChangeListener(this._onSearchChange);
|
super(props);
|
||||||
PostStore.addSelectedPostChangeListener(this._onSelectedChange);
|
|
||||||
},
|
this.onSelectedChange = this.onSelectedChange.bind(this);
|
||||||
componentWillUnmount: function() {
|
this.onSearchChange = this.onSearchChange.bind(this);
|
||||||
PostStore.removeSearchChangeListener(this._onSearchChange);
|
this.resize = this.resize.bind(this);
|
||||||
PostStore.removeSelectedPostChangeListener(this._onSelectedChange);
|
|
||||||
},
|
this.state = getStateFromStores();
|
||||||
_onSelectedChange: function(from_search) {
|
}
|
||||||
if (this.isMounted()) {
|
componentDidMount() {
|
||||||
var newState = getStateFromStores(from_search);
|
PostStore.addSearchChangeListener(this.onSearchChange);
|
||||||
newState.from_search = from_search;
|
PostStore.addSelectedPostChangeListener(this.onSelectedChange);
|
||||||
if (!utils.areStatesEqual(newState, this.state)) {
|
}
|
||||||
|
componentWillUnmount() {
|
||||||
|
PostStore.removeSearchChangeListener(this.onSearchChange);
|
||||||
|
PostStore.removeSelectedPostChangeListener(this.onSelectedChange);
|
||||||
|
}
|
||||||
|
onSelectedChange(fromSearch) {
|
||||||
|
var newState = getStateFromStores(fromSearch);
|
||||||
|
newState.from_search = fromSearch;
|
||||||
|
if (!Utils.areStatesEqual(newState, this.state)) {
|
||||||
this.setState(newState);
|
this.setState(newState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
onSearchChange() {
|
||||||
_onSearchChange: function() {
|
|
||||||
if (this.isMounted()) {
|
|
||||||
var newState = getStateFromStores();
|
var newState = getStateFromStores();
|
||||||
if (!utils.areStatesEqual(newState, this.state)) {
|
if (!Utils.areStatesEqual(newState, this.state)) {
|
||||||
this.setState(newState);
|
this.setState(newState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
resize() {
|
||||||
resize: function() {
|
|
||||||
var postHolder = $('.post-list-holder-by-time');
|
var postHolder = $('.post-list-holder-by-time');
|
||||||
postHolder[0].scrollTop = postHolder[0].scrollHeight - 224;
|
postHolder[0].scrollTop = postHolder[0].scrollHeight - 224;
|
||||||
},
|
}
|
||||||
getInitialState: function() {
|
render() {
|
||||||
return getStateFromStores();
|
if (!(this.state.search_visible || this.state.post_right_visible)) {
|
||||||
},
|
|
||||||
render: function() {
|
|
||||||
if (! (this.state.search_visible || this.state.post_right_visible)) {
|
|
||||||
$('.inner__wrap').removeClass('move--left').removeClass('move--right');
|
$('.inner__wrap').removeClass('move--left').removeClass('move--right');
|
||||||
$('.sidebar--right').removeClass('move--left');
|
$('.sidebar--right').removeClass('move--left');
|
||||||
this.resize();
|
this.resize();
|
||||||
@@ -58,25 +60,27 @@ module.exports = React.createClass({
|
|||||||
$('.sidebar--right').addClass('move--left');
|
$('.sidebar--right').addClass('move--left');
|
||||||
$('.sidebar--right').prepend('<div class="sidebar__overlay"></div>');
|
$('.sidebar--right').prepend('<div class="sidebar__overlay"></div>');
|
||||||
this.resize();
|
this.resize();
|
||||||
setTimeout(function(){
|
setTimeout(function overlayTimer() {
|
||||||
$('.sidebar__overlay').fadeOut("200", function(){
|
$('.sidebar__overlay').fadeOut('200', function fadeOverlay() {
|
||||||
$(this).remove();
|
$(this).remove();
|
||||||
});
|
});
|
||||||
},500)
|
}, 500);
|
||||||
|
|
||||||
var content = "";
|
var content = '';
|
||||||
|
|
||||||
if (this.state.search_visible) {
|
if (this.state.search_visible) {
|
||||||
content = <SearchResults isMentionSearch={this.state.is_mention_search} />;
|
content = <SearchResults isMentionSearch={this.state.is_mention_search} />;
|
||||||
}
|
} else if (this.state.post_right_visible) {
|
||||||
else if (this.state.post_right_visible) {
|
content = (<RhsThread
|
||||||
content = <RhsThread fromSearch={this.state.from_search} isMentionSearch={this.state.is_mention_search} />;
|
fromSearch={this.state.from_search}
|
||||||
|
isMentionSearch={this.state.is_mention_search}
|
||||||
|
/>);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="sidebar-right-container">
|
<div className='sidebar-right-container'>
|
||||||
{ content }
|
{content}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|||||||
@@ -10,69 +10,99 @@ var UsernamePage = require('./team_signup_username_page.jsx');
|
|||||||
var PasswordPage = require('./team_signup_password_page.jsx');
|
var PasswordPage = require('./team_signup_password_page.jsx');
|
||||||
var BrowserStore = require('../stores/browser_store.jsx');
|
var BrowserStore = require('../stores/browser_store.jsx');
|
||||||
|
|
||||||
module.exports = React.createClass({
|
export default class SignupTeamComplete extends React.Component {
|
||||||
displayName: 'SignupTeamComplete',
|
constructor(props) {
|
||||||
propTypes: {
|
super(props);
|
||||||
hash: React.PropTypes.string,
|
|
||||||
email: React.PropTypes.string,
|
this.updateParent = this.updateParent.bind(this);
|
||||||
data: React.PropTypes.string
|
|
||||||
},
|
var initialState = BrowserStore.getGlobalItem(props.hash);
|
||||||
updateParent: function(state, skipSet) {
|
|
||||||
|
if (!initialState) {
|
||||||
|
initialState = {};
|
||||||
|
initialState.wizard = 'welcome';
|
||||||
|
initialState.team = {};
|
||||||
|
initialState.team.email = this.props.email;
|
||||||
|
initialState.team.allowed_domains = '';
|
||||||
|
initialState.invites = [];
|
||||||
|
initialState.invites.push('');
|
||||||
|
initialState.invites.push('');
|
||||||
|
initialState.invites.push('');
|
||||||
|
initialState.user = {};
|
||||||
|
initialState.hash = this.props.hash;
|
||||||
|
initialState.data = this.props.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.state = initialState;
|
||||||
|
}
|
||||||
|
updateParent(state, skipSet) {
|
||||||
BrowserStore.setGlobalItem(this.props.hash, state);
|
BrowserStore.setGlobalItem(this.props.hash, state);
|
||||||
|
|
||||||
if (!skipSet) {
|
if (!skipSet) {
|
||||||
this.setState(state);
|
this.setState(state);
|
||||||
}
|
}
|
||||||
},
|
|
||||||
getInitialState: function() {
|
|
||||||
var props = BrowserStore.getGlobalItem(this.props.hash);
|
|
||||||
|
|
||||||
if (!props) {
|
|
||||||
props = {};
|
|
||||||
props.wizard = 'welcome';
|
|
||||||
props.team = {};
|
|
||||||
props.team.email = this.props.email;
|
|
||||||
props.team.allowed_domains = '';
|
|
||||||
props.invites = [];
|
|
||||||
props.invites.push('');
|
|
||||||
props.invites.push('');
|
|
||||||
props.invites.push('');
|
|
||||||
props.user = {};
|
|
||||||
props.hash = this.props.hash;
|
|
||||||
props.data = this.props.data;
|
|
||||||
}
|
}
|
||||||
|
render() {
|
||||||
return props;
|
|
||||||
},
|
|
||||||
render: function() {
|
|
||||||
if (this.state.wizard === 'welcome') {
|
if (this.state.wizard === 'welcome') {
|
||||||
return <WelcomePage state={this.state} updateParent={this.updateParent} />;
|
return (<WelcomePage
|
||||||
|
state={this.state}
|
||||||
|
updateParent={this.updateParent}
|
||||||
|
/>);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.state.wizard === 'team_display_name') {
|
if (this.state.wizard === 'team_display_name') {
|
||||||
return <TeamDisplayNamePage state={this.state} updateParent={this.updateParent} />;
|
return (<TeamDisplayNamePage
|
||||||
|
state={this.state}
|
||||||
|
updateParent={this.updateParent}
|
||||||
|
/>);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.state.wizard === 'team_url') {
|
if (this.state.wizard === 'team_url') {
|
||||||
return <TeamURLPage state={this.state} updateParent={this.updateParent} />;
|
return (<TeamURLPage
|
||||||
|
state={this.state}
|
||||||
|
updateParent={this.updateParent}
|
||||||
|
/>);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.state.wizard === 'allowed_domains') {
|
if (this.state.wizard === 'allowed_domains') {
|
||||||
return <AllowedDomainsPage state={this.state} updateParent={this.updateParent} />;
|
return (<AllowedDomainsPage
|
||||||
|
state={this.state}
|
||||||
|
updateParent={this.updateParent}
|
||||||
|
/>);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.state.wizard === 'send_invites') {
|
if (this.state.wizard === 'send_invites') {
|
||||||
return <SendInivtesPage state={this.state} updateParent={this.updateParent} />;
|
return (<SendInivtesPage
|
||||||
|
state={this.state}
|
||||||
|
updateParent={this.updateParent}
|
||||||
|
/>);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.state.wizard === 'username') {
|
if (this.state.wizard === 'username') {
|
||||||
return <UsernamePage state={this.state} updateParent={this.updateParent} />;
|
return (<UsernamePage
|
||||||
|
state={this.state}
|
||||||
|
updateParent={this.updateParent}
|
||||||
|
/>);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.state.wizard === 'password') {
|
if (this.state.wizard === 'password') {
|
||||||
return <PasswordPage state={this.state} updateParent={this.updateParent} />;
|
return (<PasswordPage
|
||||||
|
state={this.state}
|
||||||
|
updateParent={this.updateParent}
|
||||||
|
/>);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (<div>You've already completed the signup process for this invitation or this invitation has expired.</div>);
|
return (<div>You've already completed the signup process for this invitation or this invitation has expired.</div>);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
|
SignupTeamComplete.defaultProps = {
|
||||||
|
hash: '',
|
||||||
|
email: '',
|
||||||
|
data: ''
|
||||||
|
};
|
||||||
|
SignupTeamComplete.propTypes = {
|
||||||
|
hash: React.PropTypes.string,
|
||||||
|
email: React.PropTypes.string,
|
||||||
|
data: React.PropTypes.string
|
||||||
|
};
|
||||||
|
|||||||
@@ -7,11 +7,31 @@ var UserStore = require('../stores/user_store.jsx');
|
|||||||
var BrowserStore = require('../stores/browser_store.jsx');
|
var BrowserStore = require('../stores/browser_store.jsx');
|
||||||
var Constants = require('../utils/constants.jsx');
|
var Constants = require('../utils/constants.jsx');
|
||||||
|
|
||||||
module.exports = React.createClass({
|
export default class SignupUserComplete extends React.Component {
|
||||||
handleSubmit: function(e) {
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.handleSubmit = this.handleSubmit.bind(this);
|
||||||
|
|
||||||
|
var initialState = BrowserStore.getGlobalItem(this.props.hash);
|
||||||
|
|
||||||
|
if (!initialState) {
|
||||||
|
initialState = {};
|
||||||
|
initialState.wizard = 'welcome';
|
||||||
|
initialState.user = {};
|
||||||
|
initialState.user.team_id = this.props.teamId;
|
||||||
|
initialState.user.email = this.props.email;
|
||||||
|
initialState.hash = this.props.hash;
|
||||||
|
initialState.data = this.props.data;
|
||||||
|
initialState.original_email = this.props.email;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.state = initialState;
|
||||||
|
}
|
||||||
|
handleSubmit(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
this.state.user.username = this.refs.name.getDOMNode().value.trim();
|
this.state.user.username = React.findDOMNode(this.refs.name).value.trim();
|
||||||
if (!this.state.user.username) {
|
if (!this.state.user.username) {
|
||||||
this.setState({nameError: 'This field is required', emailError: '', passwordError: '', serverError: ''});
|
this.setState({nameError: 'This field is required', emailError: '', passwordError: '', serverError: ''});
|
||||||
return;
|
return;
|
||||||
@@ -31,13 +51,13 @@ module.exports = React.createClass({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.state.user.email = this.refs.email.getDOMNode().value.trim();
|
this.state.user.email = React.findDOMNode(this.refs.email).value.trim();
|
||||||
if (!this.state.user.email) {
|
if (!this.state.user.email) {
|
||||||
this.setState({nameError: '', emailError: 'This field is required', passwordError: ''});
|
this.setState({nameError: '', emailError: 'This field is required', passwordError: ''});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.state.user.password = this.refs.password.getDOMNode().value.trim();
|
this.state.user.password = React.findDOMNode(this.refs.password).value.trim();
|
||||||
if (!this.state.user.password || this.state.user.password .length < 5) {
|
if (!this.state.user.password || this.state.user.password .length < 5) {
|
||||||
this.setState({nameError: '', emailError: '', passwordError: 'Please enter at least 5 characters', serverError: ''});
|
this.setState({nameError: '', emailError: '', passwordError: 'Please enter at least 5 characters', serverError: ''});
|
||||||
return;
|
return;
|
||||||
@@ -48,11 +68,11 @@ module.exports = React.createClass({
|
|||||||
this.state.user.allow_marketing = true;
|
this.state.user.allow_marketing = true;
|
||||||
|
|
||||||
client.createUser(this.state.user, this.state.data, this.state.hash,
|
client.createUser(this.state.user, this.state.data, this.state.hash,
|
||||||
function(data) {
|
function createUserSuccess() {
|
||||||
client.track('signup', 'signup_user_02_complete');
|
client.track('signup', 'signup_user_02_complete');
|
||||||
|
|
||||||
client.loginByEmail(this.props.teamName, this.state.user.email, this.state.user.password,
|
client.loginByEmail(this.props.teamName, this.state.user.email, this.state.user.password,
|
||||||
function(data) {
|
function emailLoginSuccess(data) {
|
||||||
UserStore.setLastEmail(this.state.user.email);
|
UserStore.setLastEmail(this.state.user.email);
|
||||||
UserStore.setCurrentUser(data);
|
UserStore.setCurrentUser(data);
|
||||||
if (this.props.hash > 0) {
|
if (this.props.hash > 0) {
|
||||||
@@ -60,7 +80,7 @@ module.exports = React.createClass({
|
|||||||
}
|
}
|
||||||
window.location.href = '/';
|
window.location.href = '/';
|
||||||
}.bind(this),
|
}.bind(this),
|
||||||
function(err) {
|
function emailLoginFailure(err) {
|
||||||
if (err.message === 'Login failed because email address has not been verified') {
|
if (err.message === 'Login failed because email address has not been verified') {
|
||||||
window.location.href = '/verify_email?email=' + encodeURIComponent(this.state.user.email) + '&teamname=' + encodeURIComponent(this.props.teamName);
|
window.location.href = '/verify_email?email=' + encodeURIComponent(this.state.user.email) + '&teamname=' + encodeURIComponent(this.props.teamName);
|
||||||
} else {
|
} else {
|
||||||
@@ -69,28 +89,12 @@ module.exports = React.createClass({
|
|||||||
}.bind(this)
|
}.bind(this)
|
||||||
);
|
);
|
||||||
}.bind(this),
|
}.bind(this),
|
||||||
function(err) {
|
function createUserFailure(err) {
|
||||||
this.setState({serverError: err.message});
|
this.setState({serverError: err.message});
|
||||||
}.bind(this)
|
}.bind(this)
|
||||||
);
|
);
|
||||||
},
|
|
||||||
getInitialState: function() {
|
|
||||||
var state = BrowserStore.getGlobalItem(this.props.hash);
|
|
||||||
|
|
||||||
if (!state) {
|
|
||||||
state = {};
|
|
||||||
state.wizard = 'welcome';
|
|
||||||
state.user = {};
|
|
||||||
state.user.team_id = this.props.teamId;
|
|
||||||
state.user.email = this.props.email;
|
|
||||||
state.hash = this.props.hash;
|
|
||||||
state.data = this.props.data;
|
|
||||||
state.original_email = this.props.email;
|
|
||||||
}
|
}
|
||||||
|
render() {
|
||||||
return state;
|
|
||||||
},
|
|
||||||
render: function() {
|
|
||||||
client.track('signup', 'signup_user_01_welcome');
|
client.track('signup', 'signup_user_01_welcome');
|
||||||
|
|
||||||
if (this.state.wizard === 'finished') {
|
if (this.state.wizard === 'finished') {
|
||||||
@@ -134,16 +138,24 @@ module.exports = React.createClass({
|
|||||||
yourEmailIs = <span>Your email address is {this.state.user.email}. You'll use this address to sign in to {config.SiteName}.</span>;
|
yourEmailIs = <span>Your email address is {this.state.user.email}. You'll use this address to sign in to {config.SiteName}.</span>;
|
||||||
}
|
}
|
||||||
|
|
||||||
var emailContainerStyle = "margin--extra";
|
var emailContainerStyle = 'margin--extra';
|
||||||
if (this.state.original_email) {
|
if (this.state.original_email) {
|
||||||
emailContainerStyle = "hidden";
|
emailContainerStyle = 'hidden';
|
||||||
}
|
}
|
||||||
|
|
||||||
var email = (
|
var email = (
|
||||||
<div className={emailContainerStyle}>
|
<div className={emailContainerStyle}>
|
||||||
<h5><strong>What's your email address?</strong></h5>
|
<h5><strong>What's your email address?</strong></h5>
|
||||||
<div className={emailDivStyle}>
|
<div className={emailDivStyle}>
|
||||||
<input type='email' ref='email' className='form-control' defaultValue={this.state.user.email} placeholder='' maxLength='128' autoFocus={true} />
|
<input
|
||||||
|
type='email'
|
||||||
|
ref='email'
|
||||||
|
className='form-control'
|
||||||
|
defaultValue={this.state.user.email}
|
||||||
|
placeholder=''
|
||||||
|
maxLength='128'
|
||||||
|
autoFocus={true}
|
||||||
|
/>
|
||||||
{emailError}
|
{emailError}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -155,7 +167,10 @@ module.exports = React.createClass({
|
|||||||
var signupMessage = [];
|
var signupMessage = [];
|
||||||
if (authServices.indexOf(Constants.GITLAB_SERVICE) >= 0) {
|
if (authServices.indexOf(Constants.GITLAB_SERVICE) >= 0) {
|
||||||
signupMessage.push(
|
signupMessage.push(
|
||||||
<a className='btn btn-custom-login gitlab' href={'/' + this.props.teamName + '/signup/gitlab' + window.location.search}>
|
<a
|
||||||
|
className='btn btn-custom-login gitlab'
|
||||||
|
href={'/' + this.props.teamName + '/signup/gitlab' + window.location.search}
|
||||||
|
>
|
||||||
<span className='icon' />
|
<span className='icon' />
|
||||||
<span>with GitLab</span>
|
<span>with GitLab</span>
|
||||||
</a>
|
</a>
|
||||||
@@ -172,7 +187,13 @@ module.exports = React.createClass({
|
|||||||
<div className='margin--extra'>
|
<div className='margin--extra'>
|
||||||
<h5><strong>Choose your username</strong></h5>
|
<h5><strong>Choose your username</strong></h5>
|
||||||
<div className={nameDivStyle}>
|
<div className={nameDivStyle}>
|
||||||
<input type='text' ref='name' className='form-control' placeholder='' maxLength='128' />
|
<input
|
||||||
|
type='text'
|
||||||
|
ref='name'
|
||||||
|
className='form-control'
|
||||||
|
placeholder=''
|
||||||
|
maxLength='128'
|
||||||
|
/>
|
||||||
{nameError}
|
{nameError}
|
||||||
<p className='form__hint'>Username must begin with a letter, and contain between 3 to 15 lowercase characters made up of numbers, letters, and the symbols '.', '-' and '_'</p>
|
<p className='form__hint'>Username must begin with a letter, and contain between 3 to 15 lowercase characters made up of numbers, letters, and the symbols '.', '-' and '_'</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -180,12 +201,26 @@ module.exports = React.createClass({
|
|||||||
<div className='margin--extra'>
|
<div className='margin--extra'>
|
||||||
<h5><strong>Choose your password</strong></h5>
|
<h5><strong>Choose your password</strong></h5>
|
||||||
<div className={passwordDivStyle}>
|
<div className={passwordDivStyle}>
|
||||||
<input type='password' ref='password' className='form-control' placeholder='' maxLength='128' />
|
<input
|
||||||
|
type='password'
|
||||||
|
ref='password'
|
||||||
|
className='form-control'
|
||||||
|
placeholder=''
|
||||||
|
maxLength='128'
|
||||||
|
/>
|
||||||
{passwordError}
|
{passwordError}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p className='margin--extra'><button type='submit' onClick={this.handleSubmit} className='btn-primary btn'>Create Account</button></p>
|
<p className='margin--extra'>
|
||||||
|
<button
|
||||||
|
type='submit'
|
||||||
|
onClick={this.handleSubmit}
|
||||||
|
className='btn-primary btn'
|
||||||
|
>
|
||||||
|
Create Account
|
||||||
|
</button>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -209,7 +244,10 @@ module.exports = React.createClass({
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<form>
|
<form>
|
||||||
<img className='signup-team-logo' src='/static/images/logo.png' />
|
<img
|
||||||
|
className='signup-team-logo'
|
||||||
|
src='/static/images/logo.png'
|
||||||
|
/>
|
||||||
<h5 className='margin--less'>Welcome to:</h5>
|
<h5 className='margin--less'>Welcome to:</h5>
|
||||||
<h2 className='signup-team__name'>{this.props.teamDisplayName}</h2>
|
<h2 className='signup-team__name'>{this.props.teamDisplayName}</h2>
|
||||||
<h2 className='signup-team__subdomain'>on {config.SiteName}</h2>
|
<h2 className='signup-team__subdomain'>on {config.SiteName}</h2>
|
||||||
@@ -222,6 +260,23 @@ module.exports = React.createClass({
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SignupUserComplete.defaultProps = {
|
||||||
|
teamName: '',
|
||||||
|
hash: '',
|
||||||
|
teamId: '',
|
||||||
|
email: '',
|
||||||
|
data: null,
|
||||||
|
authServices: '',
|
||||||
|
teamDisplayName: ''
|
||||||
|
};
|
||||||
|
SignupUserComplete.propTypes = {
|
||||||
|
teamName: React.PropTypes.string,
|
||||||
|
hash: React.PropTypes.string,
|
||||||
|
teamId: React.PropTypes.string,
|
||||||
|
email: React.PropTypes.string,
|
||||||
|
data: React.PropTypes.string,
|
||||||
|
authServices: React.PropTypes.string,
|
||||||
|
teamDisplayName: React.PropTypes.string
|
||||||
|
};
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
// See License.txt for license information.
|
// See License.txt for license information.
|
||||||
|
|
||||||
var EmailItem = require('./team_signup_email_item.jsx');
|
var EmailItem = require('./team_signup_email_item.jsx');
|
||||||
var utils = require('../utils/utils.jsx');
|
var Utils = require('../utils/utils.jsx');
|
||||||
var ConfigStore = require('../stores/config_store.jsx');
|
var ConfigStore = require('../stores/config_store.jsx');
|
||||||
var client = require('../utils/client.jsx');
|
var Client = require('../utils/client.jsx');
|
||||||
|
|
||||||
export default class TeamSignupSendInvitesPage extends React.Component {
|
export default class TeamSignupSendInvitesPage extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@@ -71,7 +71,7 @@ export default class TeamSignupSendInvitesPage extends React.Component {
|
|||||||
}
|
}
|
||||||
keySubmit(e) {
|
keySubmit(e) {
|
||||||
if (e && e.keyCode === 13) {
|
if (e && e.keyCode === 13) {
|
||||||
this.submitNext(e)
|
this.submitNext(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
@@ -92,7 +92,7 @@ export default class TeamSignupSendInvitesPage extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
render() {
|
render() {
|
||||||
client.track('signup', 'signup_team_05_send_invites');
|
Client.track('signup', 'signup_team_05_send_invites');
|
||||||
|
|
||||||
var content = null;
|
var content = null;
|
||||||
var bottomContent = null;
|
var bottomContent = null;
|
||||||
@@ -165,7 +165,7 @@ export default class TeamSignupSendInvitesPage extends React.Component {
|
|||||||
className='signup-team-logo'
|
className='signup-team-logo'
|
||||||
src='/static/images/logo.png'
|
src='/static/images/logo.png'
|
||||||
/>
|
/>
|
||||||
<h2>{'Invite ' + utils.toTitleCase(strings.Team) + ' Members'}</h2>
|
<h2>{'Invite ' + Utils.toTitleCase(strings.Team) + ' Members'}</h2>
|
||||||
{content}
|
{content}
|
||||||
<div className='form-group'>
|
<div className='form-group'>
|
||||||
<button
|
<button
|
||||||
@@ -190,6 +190,7 @@ export default class TeamSignupSendInvitesPage extends React.Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TeamSignupSendInvitesPage.propTypes = {
|
TeamSignupSendInvitesPage.propTypes = {
|
||||||
state: React.PropTypes.object.isRequired,
|
state: React.PropTypes.object.isRequired,
|
||||||
updateParent: React.PropTypes.func.isRequired
|
updateParent: React.PropTypes.func.isRequired
|
||||||
|
|||||||
@@ -1,26 +1,29 @@
|
|||||||
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
|
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
|
||||||
// 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 client = require('../utils/client.jsx');
|
var Client = require('../utils/client.jsx');
|
||||||
|
|
||||||
module.exports = React.createClass({
|
export default class TeamSignupUsernamePage extends React.Component {
|
||||||
displayName: 'TeamSignupUsernamePage',
|
constructor(props) {
|
||||||
propTypes: {
|
super(props);
|
||||||
state: React.PropTypes.object,
|
|
||||||
updateParent: React.PropTypes.func
|
this.submitBack = this.submitBack.bind(this);
|
||||||
},
|
this.submitNext = this.submitNext.bind(this);
|
||||||
submitBack: function(e) {
|
|
||||||
|
this.state = {};
|
||||||
|
}
|
||||||
|
submitBack(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.props.state.wizard = 'send_invites';
|
this.props.state.wizard = 'send_invites';
|
||||||
this.props.updateParent(this.props.state);
|
this.props.updateParent(this.props.state);
|
||||||
},
|
}
|
||||||
submitNext: function(e) {
|
submitNext(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
var name = this.refs.name.getDOMNode().value.trim();
|
var name = React.findDOMNode(this.refs.name).value.trim();
|
||||||
|
|
||||||
var usernameError = utils.isValidUsername(name);
|
var usernameError = Utils.isValidUsername(name);
|
||||||
if (usernameError === 'Cannot use a reserved word as a username.') {
|
if (usernameError === 'Cannot use a reserved word as a username.') {
|
||||||
this.setState({nameError: 'This username is reserved, please choose a new one.'});
|
this.setState({nameError: 'This username is reserved, please choose a new one.'});
|
||||||
return;
|
return;
|
||||||
@@ -32,12 +35,9 @@ module.exports = React.createClass({
|
|||||||
this.props.state.wizard = 'password';
|
this.props.state.wizard = 'password';
|
||||||
this.props.state.user.username = name;
|
this.props.state.user.username = name;
|
||||||
this.props.updateParent(this.props.state);
|
this.props.updateParent(this.props.state);
|
||||||
},
|
}
|
||||||
getInitialState: function() {
|
render() {
|
||||||
return {};
|
Client.track('signup', 'signup_team_06_username');
|
||||||
},
|
|
||||||
render: function() {
|
|
||||||
client.track('signup', 'signup_team_06_username');
|
|
||||||
|
|
||||||
var nameError = null;
|
var nameError = null;
|
||||||
var nameDivClass = 'form-group';
|
var nameDivClass = 'form-group';
|
||||||
@@ -49,7 +49,10 @@ module.exports = React.createClass({
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<form>
|
<form>
|
||||||
<img className='signup-team-logo' src='/static/images/logo.png' />
|
<img
|
||||||
|
className='signup-team-logo'
|
||||||
|
src='/static/images/logo.png'
|
||||||
|
/>
|
||||||
<h2 className='margin--less'>Your username</h2>
|
<h2 className='margin--less'>Your username</h2>
|
||||||
<h5 className='color--light'>{'Select a memorable username that makes it easy for ' + strings.Team + 'mates to identify you:'}</h5>
|
<h5 className='color--light'>{'Select a memorable username that makes it easy for ' + strings.Team + 'mates to identify you:'}</h5>
|
||||||
<div className='inner__content margin--extra'>
|
<div className='inner__content margin--extra'>
|
||||||
@@ -57,19 +60,47 @@ module.exports = React.createClass({
|
|||||||
<div className='row'>
|
<div className='row'>
|
||||||
<div className='col-sm-11'>
|
<div className='col-sm-11'>
|
||||||
<h5><strong>Choose your username</strong></h5>
|
<h5><strong>Choose your username</strong></h5>
|
||||||
<input autoFocus={true} type='text' ref='name' className='form-control' placeholder='' defaultValue={this.props.state.user.username} maxLength='128' />
|
<input
|
||||||
|
autoFocus={true}
|
||||||
|
type='text'
|
||||||
|
ref='name'
|
||||||
|
className='form-control'
|
||||||
|
placeholder=''
|
||||||
|
defaultValue={this.props.state.user.username}
|
||||||
|
maxLength='128'
|
||||||
|
/>
|
||||||
<div className='color--light form__hint'>Usernames must begin with a letter and contain 3 to 15 characters made up of lowercase letters, numbers, and the symbols '.', '-' and '_'</div>
|
<div className='color--light form__hint'>Usernames must begin with a letter and contain 3 to 15 characters made up of lowercase letters, numbers, and the symbols '.', '-' and '_'</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{nameError}
|
{nameError}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button type='submit' className='btn btn-primary margin--extra' onClick={this.submitNext}>Next<i className='glyphicon glyphicon-chevron-right'></i></button>
|
<button
|
||||||
|
type='submit'
|
||||||
|
className='btn btn-primary margin--extra'
|
||||||
|
onClick={this.submitNext}
|
||||||
|
>
|
||||||
|
Next
|
||||||
|
<i className='glyphicon glyphicon-chevron-right'></i>
|
||||||
|
</button>
|
||||||
<div className='margin--extra'>
|
<div className='margin--extra'>
|
||||||
<a href='#' onClick={this.submitBack}>Back to previous step</a>
|
<a
|
||||||
|
href='#'
|
||||||
|
onClick={this.submitBack}
|
||||||
|
>
|
||||||
|
Back to previous step
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
|
TeamSignupUsernamePage.defaultProps = {
|
||||||
|
state: null
|
||||||
|
};
|
||||||
|
TeamSignupUsernamePage.propTypes = {
|
||||||
|
state: React.PropTypes.object,
|
||||||
|
updateParent: React.PropTypes.func
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,17 +1,22 @@
|
|||||||
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
|
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
|
||||||
// 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 client = require('../utils/client.jsx');
|
var Client = require('../utils/client.jsx');
|
||||||
var BrowserStore = require('../stores/browser_store.jsx');
|
var BrowserStore = require('../stores/browser_store.jsx');
|
||||||
|
|
||||||
module.exports = React.createClass({
|
export default class TeamSignupWelcomePage extends React.Component {
|
||||||
displayName: 'TeamSignupWelcomePage',
|
constructor(props) {
|
||||||
propTypes: {
|
super(props);
|
||||||
state: React.PropTypes.object,
|
|
||||||
updateParent: React.PropTypes.func
|
this.submitNext = this.submitNext.bind(this);
|
||||||
},
|
this.handleDiffEmail = this.handleDiffEmail.bind(this);
|
||||||
submitNext: function(e) {
|
this.handleDiffSubmit = this.handleDiffSubmit.bind(this);
|
||||||
|
this.handleKeyPress = this.handleKeyPress.bind(this);
|
||||||
|
|
||||||
|
this.state = {useDiff: false};
|
||||||
|
}
|
||||||
|
submitNext(e) {
|
||||||
if (!BrowserStore.isLocalStorageSupported()) {
|
if (!BrowserStore.isLocalStorageSupported()) {
|
||||||
this.setState({storageError: 'This service requires local storage to be enabled. Please enable it or exit private browsing.'});
|
this.setState({storageError: 'This service requires local storage to be enabled. Please enable it or exit private browsing.'});
|
||||||
return;
|
return;
|
||||||
@@ -19,18 +24,18 @@ module.exports = React.createClass({
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.props.state.wizard = 'team_display_name';
|
this.props.state.wizard = 'team_display_name';
|
||||||
this.props.updateParent(this.props.state);
|
this.props.updateParent(this.props.state);
|
||||||
},
|
}
|
||||||
handleDiffEmail: function(e) {
|
handleDiffEmail(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.setState({useDiff: true});
|
this.setState({useDiff: true});
|
||||||
},
|
}
|
||||||
handleDiffSubmit: function(e) {
|
handleDiffSubmit(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
var state = {useDiff: true, serverError: ''};
|
var state = {useDiff: true, serverError: ''};
|
||||||
|
|
||||||
var email = this.refs.email.getDOMNode().value.trim().toLowerCase();
|
var email = React.findDOMNode(this.refs.email).value.trim().toLowerCase();
|
||||||
if (!email || !utils.isEmail(email)) {
|
if (!email || !Utils.isEmail(email)) {
|
||||||
state.emailError = 'Please enter a valid email address';
|
state.emailError = 'Please enter a valid email address';
|
||||||
this.setState(state);
|
this.setState(state);
|
||||||
return;
|
return;
|
||||||
@@ -41,7 +46,7 @@ module.exports = React.createClass({
|
|||||||
}
|
}
|
||||||
state.emailError = '';
|
state.emailError = '';
|
||||||
|
|
||||||
client.signupTeam(email,
|
Client.signupTeam(email,
|
||||||
function success(data) {
|
function success(data) {
|
||||||
if (data.follow_link) {
|
if (data.follow_link) {
|
||||||
window.location.href = data.follow_link;
|
window.location.href = data.follow_link;
|
||||||
@@ -56,23 +61,20 @@ module.exports = React.createClass({
|
|||||||
this.setState(this.state);
|
this.setState(this.state);
|
||||||
}.bind(this)
|
}.bind(this)
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
getInitialState: function() {
|
handleKeyPress(event) {
|
||||||
return {useDiff: false};
|
|
||||||
},
|
|
||||||
handleKeyPress: function(event) {
|
|
||||||
if (event.keyCode === 13) {
|
if (event.keyCode === 13) {
|
||||||
this.submitNext(event);
|
this.submitNext(event);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
componentWillMount: function() {
|
componentWillMount() {
|
||||||
document.addEventListener('keyup', this.handleKeyPress, false);
|
document.addEventListener('keyup', this.handleKeyPress, false);
|
||||||
},
|
}
|
||||||
componentWillUnmount: function() {
|
componentWillUnmount() {
|
||||||
document.removeEventListener('keyup', this.handleKeyPress, false);
|
document.removeEventListener('keyup', this.handleKeyPress, false);
|
||||||
},
|
}
|
||||||
render: function() {
|
render() {
|
||||||
client.track('signup', 'signup_team_01_welcome');
|
Client.track('signup', 'signup_team_01_welcome');
|
||||||
|
|
||||||
var storageError = null;
|
var storageError = null;
|
||||||
if (this.state.storageError) {
|
if (this.state.storageError) {
|
||||||
@@ -105,7 +107,10 @@ module.exports = React.createClass({
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<p>
|
<p>
|
||||||
<img className='signup-team-logo' src='/static/images/logo.png' />
|
<img
|
||||||
|
className='signup-team-logo'
|
||||||
|
src='/static/images/logo.png'
|
||||||
|
/>
|
||||||
<h3 className='sub-heading'>Welcome to:</h3>
|
<h3 className='sub-heading'>Welcome to:</h3>
|
||||||
<h1 className='margin--top-none'>{config.SiteName}</h1>
|
<h1 className='margin--top-none'>{config.SiteName}</h1>
|
||||||
</p>
|
</p>
|
||||||
@@ -121,7 +126,14 @@ module.exports = React.createClass({
|
|||||||
You can add other administrators later.
|
You can add other administrators later.
|
||||||
</p>
|
</p>
|
||||||
<div className='form-group'>
|
<div className='form-group'>
|
||||||
<button className='btn-primary btn form-group' type='submit' onClick={this.submitNext}><i className='glyphicon glyphicon-ok'></i>Yes, this address is correct</button>
|
<button
|
||||||
|
className='btn-primary btn form-group'
|
||||||
|
type='submit'
|
||||||
|
onClick={this.submitNext}
|
||||||
|
>
|
||||||
|
<i className='glyphicon glyphicon-ok'></i>
|
||||||
|
Yes, this address is correct
|
||||||
|
</button>
|
||||||
{storageError}
|
{storageError}
|
||||||
</div>
|
</div>
|
||||||
<hr />
|
<hr />
|
||||||
@@ -129,16 +141,42 @@ module.exports = React.createClass({
|
|||||||
<div className={emailDivClass}>
|
<div className={emailDivClass}>
|
||||||
<div className='row'>
|
<div className='row'>
|
||||||
<div className='col-sm-9'>
|
<div className='col-sm-9'>
|
||||||
<input type='email' ref='email' className='form-control' placeholder='Email Address' maxLength='128' />
|
<input
|
||||||
|
type='email'
|
||||||
|
ref='email'
|
||||||
|
className='form-control'
|
||||||
|
placeholder='Email Address'
|
||||||
|
maxLength='128'
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{emailError}
|
{emailError}
|
||||||
</div>
|
</div>
|
||||||
{serverError}
|
{serverError}
|
||||||
<button className='btn btn-md btn-primary' type='button' onClick={this.handleDiffSubmit}>Use this instead</button>
|
<button
|
||||||
|
className='btn btn-md btn-primary'
|
||||||
|
type='button'
|
||||||
|
onClick={this.handleDiffSubmit}
|
||||||
|
>
|
||||||
|
Use this instead
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<a href='#' onClick={this.handleDiffEmail} className={differentEmailLinkClass}>Use a different email</a>
|
<a
|
||||||
|
href='#'
|
||||||
|
onClick={this.handleDiffEmail}
|
||||||
|
className={differentEmailLinkClass}
|
||||||
|
>
|
||||||
|
Use a different email
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
|
TeamSignupWelcomePage.defaultProps = {
|
||||||
|
state: {}
|
||||||
|
};
|
||||||
|
TeamSignupWelcomePage.propTypes = {
|
||||||
|
updateParent: React.PropTypes.func.isRequired,
|
||||||
|
state: React.PropTypes.object
|
||||||
|
};
|
||||||
|
|||||||
@@ -4,51 +4,75 @@
|
|||||||
var SettingsSidebar = require('./settings_sidebar.jsx');
|
var SettingsSidebar = require('./settings_sidebar.jsx');
|
||||||
var UserSettings = require('./user_settings.jsx');
|
var UserSettings = require('./user_settings.jsx');
|
||||||
|
|
||||||
module.exports = React.createClass({
|
export default class UserSettingsModal extends React.Component {
|
||||||
componentDidMount: function() {
|
constructor(props) {
|
||||||
$('body').on('click', '.modal-back', function(){
|
super(props);
|
||||||
|
|
||||||
|
this.updateTab = this.updateTab.bind(this);
|
||||||
|
this.updateSection = this.updateSection.bind(this);
|
||||||
|
|
||||||
|
this.state = {active_tab: 'general', active_section: ''};
|
||||||
|
}
|
||||||
|
componentDidMount() {
|
||||||
|
$('body').on('click', '.modal-back', function changeDisplay() {
|
||||||
$(this).closest('.modal-dialog').removeClass('display--content');
|
$(this).closest('.modal-dialog').removeClass('display--content');
|
||||||
});
|
});
|
||||||
$('body').on('click', '.modal-header .close', function(){
|
$('body').on('click', '.modal-header .close', function closeModal() {
|
||||||
setTimeout(function() {
|
setTimeout(function finishClose() {
|
||||||
$('.modal-dialog.display--content').removeClass('display--content');
|
$('.modal-dialog.display--content').removeClass('display--content');
|
||||||
}, 500);
|
}, 500);
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
updateTab: function(tab) {
|
updateTab(tab) {
|
||||||
this.setState({ active_tab: tab });
|
this.setState({active_tab: tab});
|
||||||
},
|
}
|
||||||
updateSection: function(section) {
|
updateSection(section) {
|
||||||
this.setState({ active_section: section });
|
this.setState({active_section: section});
|
||||||
},
|
}
|
||||||
getInitialState: function() {
|
render() {
|
||||||
return { active_tab: "general", active_section: "" };
|
|
||||||
},
|
|
||||||
render: function() {
|
|
||||||
var tabs = [];
|
var tabs = [];
|
||||||
tabs.push({name: "general", uiName: "General", icon: "glyphicon glyphicon-cog"});
|
tabs.push({name: 'general', uiName: 'General', icon: 'glyphicon glyphicon-cog'});
|
||||||
tabs.push({name: "security", uiName: "Security", icon: "glyphicon glyphicon-lock"});
|
tabs.push({name: 'security', uiName: 'Security', icon: 'glyphicon glyphicon-lock'});
|
||||||
tabs.push({name: "notifications", uiName: "Notifications", icon: "glyphicon glyphicon-exclamation-sign"});
|
tabs.push({name: 'notifications', uiName: 'Notifications', icon: 'glyphicon glyphicon-exclamation-sign'});
|
||||||
tabs.push({name: "appearance", uiName: "Appearance", icon: "glyphicon glyphicon-wrench"});
|
tabs.push({name: 'appearance', uiName: 'Appearance', icon: 'glyphicon glyphicon-wrench'});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="modal fade" ref="modal" id="user_settings" role="dialog" tabIndex="-1" aria-hidden="true">
|
<div
|
||||||
<div className="modal-dialog settings-modal">
|
className='modal fade'
|
||||||
<div className="modal-content">
|
ref='modal'
|
||||||
<div className="modal-header">
|
id='user_settings'
|
||||||
<button type="button" className="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
role='dialog'
|
||||||
<h4 className="modal-title" ref="title">Account Settings</h4>
|
tabIndex='-1'
|
||||||
|
aria-hidden='true'
|
||||||
|
>
|
||||||
|
<div className='modal-dialog settings-modal'>
|
||||||
|
<div className='modal-content'>
|
||||||
|
<div className='modal-header'>
|
||||||
|
<button
|
||||||
|
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>
|
||||||
<div className="modal-body">
|
<div className='modal-body'>
|
||||||
<div className="settings-table">
|
<div className='settings-table'>
|
||||||
<div className="settings-links">
|
<div className='settings-links'>
|
||||||
<SettingsSidebar
|
<SettingsSidebar
|
||||||
tabs={tabs}
|
tabs={tabs}
|
||||||
activeTab={this.state.active_tab}
|
activeTab={this.state.active_tab}
|
||||||
updateTab={this.updateTab}
|
updateTab={this.updateTab}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="settings-content minimize-settings">
|
<div className='settings-content minimize-settings'>
|
||||||
<UserSettings
|
<UserSettings
|
||||||
activeTab={this.state.active_tab}
|
activeTab={this.state.active_tab}
|
||||||
activeSection={this.state.active_section}
|
activeSection={this.state.active_section}
|
||||||
@@ -63,4 +87,4 @@ module.exports = React.createClass({
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|||||||
@@ -163,15 +163,15 @@ export default class NotificationsTab extends React.Component {
|
|||||||
}
|
}
|
||||||
handleNotifyRadio(notifyLevel) {
|
handleNotifyRadio(notifyLevel) {
|
||||||
this.setState({notifyLevel: notifyLevel});
|
this.setState({notifyLevel: notifyLevel});
|
||||||
this.refs.wrapper.getDOMNode().focus();
|
React.findDOMNode(this.refs.wrapper).focus();
|
||||||
}
|
}
|
||||||
handleEmailRadio(enableEmail) {
|
handleEmailRadio(enableEmail) {
|
||||||
this.setState({enableEmail: enableEmail});
|
this.setState({enableEmail: enableEmail});
|
||||||
this.refs.wrapper.getDOMNode().focus();
|
React.findDOMNode(this.refs.wrapper).focus();
|
||||||
}
|
}
|
||||||
handleSoundRadio(enableSound) {
|
handleSoundRadio(enableSound) {
|
||||||
this.setState({enableSound: enableSound});
|
this.setState({enableSound: enableSound});
|
||||||
this.refs.wrapper.getDOMNode().focus();
|
React.findDOMNode(this.refs.wrapper).focus();
|
||||||
}
|
}
|
||||||
updateUsernameKey(val) {
|
updateUsernameKey(val) {
|
||||||
this.setState({usernameKey: val});
|
this.setState({usernameKey: val});
|
||||||
@@ -189,10 +189,10 @@ export default class NotificationsTab extends React.Component {
|
|||||||
this.setState({channelKey: val});
|
this.setState({channelKey: val});
|
||||||
}
|
}
|
||||||
updateCustomMentionKeys() {
|
updateCustomMentionKeys() {
|
||||||
var checked = this.refs.customcheck.getDOMNode().checked;
|
var checked = React.findDOMNode(this.refs.customcheck).checked;
|
||||||
|
|
||||||
if (checked) {
|
if (checked) {
|
||||||
var text = this.refs.custommentions.getDOMNode().value;
|
var text = React.findDOMNode(this.refs.custommentions).value;
|
||||||
|
|
||||||
// remove all spaces and split string into individual keys
|
// remove all spaces and split string into individual keys
|
||||||
this.setState({customKeys: text.replace(/ /g, ''), customKeysChecked: true});
|
this.setState({customKeys: text.replace(/ /g, ''), customKeysChecked: true});
|
||||||
@@ -201,7 +201,7 @@ export default class NotificationsTab extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
onCustomChange() {
|
onCustomChange() {
|
||||||
this.refs.customcheck.getDOMNode().checked = true;
|
React.findDOMNode(this.refs.customcheck).checked = true;
|
||||||
this.updateCustomMentionKeys();
|
this.updateCustomMentionKeys();
|
||||||
}
|
}
|
||||||
render() {
|
render() {
|
||||||
@@ -210,8 +210,6 @@ export default class NotificationsTab extends React.Component {
|
|||||||
serverError = this.state.serverError;
|
serverError = this.state.serverError;
|
||||||
}
|
}
|
||||||
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
var user = this.props.user;
|
var user = this.props.user;
|
||||||
|
|
||||||
var desktopSection;
|
var desktopSection;
|
||||||
@@ -229,12 +227,12 @@ export default class NotificationsTab extends React.Component {
|
|||||||
let inputs = [];
|
let inputs = [];
|
||||||
|
|
||||||
inputs.push(
|
inputs.push(
|
||||||
<div>
|
<div key='userNotificationLevelOption'>
|
||||||
<div className='radio'>
|
<div className='radio'>
|
||||||
<label>
|
<label>
|
||||||
<input type='radio'
|
<input type='radio'
|
||||||
checked={notifyActive[0]}
|
checked={notifyActive[0]}
|
||||||
onChange={self.handleNotifyRadio.bind(this, 'all')}
|
onChange={this.handleNotifyRadio.bind(this, 'all')}
|
||||||
>
|
>
|
||||||
For all activity
|
For all activity
|
||||||
</input>
|
</input>
|
||||||
@@ -246,7 +244,7 @@ export default class NotificationsTab extends React.Component {
|
|||||||
<input
|
<input
|
||||||
type='radio'
|
type='radio'
|
||||||
checked={notifyActive[1]}
|
checked={notifyActive[1]}
|
||||||
onChange={self.handleNotifyRadio.bind(this, 'mention')}
|
onChange={this.handleNotifyRadio.bind(this, 'mention')}
|
||||||
>
|
>
|
||||||
Only for mentions and private messages
|
Only for mentions and private messages
|
||||||
</input>
|
</input>
|
||||||
@@ -258,7 +256,7 @@ export default class NotificationsTab extends React.Component {
|
|||||||
<input
|
<input
|
||||||
type='radio'
|
type='radio'
|
||||||
checked={notifyActive[2]}
|
checked={notifyActive[2]}
|
||||||
onChange={self.handleNotifyRadio.bind(this, 'none')}
|
onChange={this.handleNotifyRadio.bind(this, 'none')}
|
||||||
>
|
>
|
||||||
Never
|
Never
|
||||||
</input>
|
</input>
|
||||||
@@ -268,15 +266,15 @@ export default class NotificationsTab extends React.Component {
|
|||||||
);
|
);
|
||||||
|
|
||||||
handleUpdateDesktopSection = function updateDesktopSection(e) {
|
handleUpdateDesktopSection = function updateDesktopSection(e) {
|
||||||
self.props.updateSection('');
|
this.props.updateSection('');
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
};
|
}.bind(this);
|
||||||
|
|
||||||
let extraInfo = (
|
let extraInfo = (
|
||||||
<div className='setting-list__hint'>
|
<div className='setting-list__hint'>
|
||||||
These settings will override the global notification settings for the <b>{this.state.curChannel}</b> channel
|
These settings will override the global notification settings for the <b>{this.state.curChannel}</b> channel
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
|
|
||||||
desktopSection = (
|
desktopSection = (
|
||||||
<SettingItemMax
|
<SettingItemMax
|
||||||
@@ -299,8 +297,8 @@ export default class NotificationsTab extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleUpdateDesktopSection = function updateDesktopSection() {
|
handleUpdateDesktopSection = function updateDesktopSection() {
|
||||||
self.props.updateSection('desktop');
|
this.props.updateSection('desktop');
|
||||||
};
|
}.bind(this);
|
||||||
|
|
||||||
desktopSection = (
|
desktopSection = (
|
||||||
<SettingItemMin
|
<SettingItemMin
|
||||||
@@ -324,13 +322,13 @@ export default class NotificationsTab extends React.Component {
|
|||||||
let inputs = [];
|
let inputs = [];
|
||||||
|
|
||||||
inputs.push(
|
inputs.push(
|
||||||
<div>
|
<div key='userNotificationSoundOptions'>
|
||||||
<div className='radio'>
|
<div className='radio'>
|
||||||
<label>
|
<label>
|
||||||
<input
|
<input
|
||||||
type='radio'
|
type='radio'
|
||||||
checked={soundActive[0]}
|
checked={soundActive[0]}
|
||||||
onChange={self.handleSoundRadio.bind(this, 'true')}
|
onChange={this.handleSoundRadio.bind(this, 'true')}
|
||||||
>
|
>
|
||||||
On
|
On
|
||||||
</input>
|
</input>
|
||||||
@@ -342,7 +340,7 @@ export default class NotificationsTab extends React.Component {
|
|||||||
<input
|
<input
|
||||||
type='radio'
|
type='radio'
|
||||||
checked={soundActive[1]}
|
checked={soundActive[1]}
|
||||||
onChange={self.handleSoundRadio.bind(this, 'false')}
|
onChange={this.handleSoundRadio.bind(this, 'false')}
|
||||||
>
|
>
|
||||||
Off
|
Off
|
||||||
</input>
|
</input>
|
||||||
@@ -353,9 +351,9 @@ export default class NotificationsTab extends React.Component {
|
|||||||
);
|
);
|
||||||
|
|
||||||
handleUpdateSoundSection = function updateSoundSection(e) {
|
handleUpdateSoundSection = function updateSoundSection(e) {
|
||||||
self.props.updateSection('');
|
this.props.updateSection('');
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
};
|
}.bind(this);
|
||||||
|
|
||||||
soundSection = (
|
soundSection = (
|
||||||
<SettingItemMax
|
<SettingItemMax
|
||||||
@@ -377,8 +375,8 @@ export default class NotificationsTab extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleUpdateSoundSection = function updateSoundSection() {
|
handleUpdateSoundSection = function updateSoundSection() {
|
||||||
self.props.updateSection('sound');
|
this.props.updateSection('sound');
|
||||||
};
|
}.bind(this);
|
||||||
|
|
||||||
soundSection = (
|
soundSection = (
|
||||||
<SettingItemMin
|
<SettingItemMin
|
||||||
@@ -403,13 +401,13 @@ export default class NotificationsTab extends React.Component {
|
|||||||
let inputs = [];
|
let inputs = [];
|
||||||
|
|
||||||
inputs.push(
|
inputs.push(
|
||||||
<div>
|
<div key='userNotificationEmailOptions'>
|
||||||
<div className='radio'>
|
<div className='radio'>
|
||||||
<label>
|
<label>
|
||||||
<input
|
<input
|
||||||
type='radio'
|
type='radio'
|
||||||
checked={emailActive[0]}
|
checked={emailActive[0]}
|
||||||
onChange={self.handleEmailRadio.bind(this, 'true')}
|
onChange={this.handleEmailRadio.bind(this, 'true')}
|
||||||
>
|
>
|
||||||
On
|
On
|
||||||
</input>
|
</input>
|
||||||
@@ -421,7 +419,7 @@ export default class NotificationsTab extends React.Component {
|
|||||||
<input
|
<input
|
||||||
type='radio'
|
type='radio'
|
||||||
checked={emailActive[1]}
|
checked={emailActive[1]}
|
||||||
onChange={self.handleEmailRadio.bind(this, 'false')}
|
onChange={this.handleEmailRadio.bind(this, 'false')}
|
||||||
>
|
>
|
||||||
Off
|
Off
|
||||||
</input>
|
</input>
|
||||||
@@ -433,9 +431,9 @@ export default class NotificationsTab extends React.Component {
|
|||||||
);
|
);
|
||||||
|
|
||||||
handleUpdateEmailSection = function updateEmailSection(e) {
|
handleUpdateEmailSection = function updateEmailSection(e) {
|
||||||
self.props.updateSection('');
|
this.props.updateSection('');
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
};
|
}.bind(this);
|
||||||
|
|
||||||
emailSection = (
|
emailSection = (
|
||||||
<SettingItemMax
|
<SettingItemMax
|
||||||
@@ -455,8 +453,8 @@ export default class NotificationsTab extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleUpdateEmailSection = function updateEmailSection() {
|
handleUpdateEmailSection = function updateEmailSection() {
|
||||||
self.props.updateSection('email');
|
this.props.updateSection('email');
|
||||||
};
|
}.bind(this);
|
||||||
|
|
||||||
emailSection = (
|
emailSection = (
|
||||||
<SettingItemMin
|
<SettingItemMin
|
||||||
@@ -480,10 +478,10 @@ export default class NotificationsTab extends React.Component {
|
|||||||
|
|
||||||
if (user.first_name) {
|
if (user.first_name) {
|
||||||
handleUpdateFirstNameKey = function handleFirstNameKeyChange(e) {
|
handleUpdateFirstNameKey = function handleFirstNameKeyChange(e) {
|
||||||
self.updateFirstNameKey(e.target.checked);
|
this.updateFirstNameKey(e.target.checked);
|
||||||
};
|
}.bind(this);
|
||||||
inputs.push(
|
inputs.push(
|
||||||
<div>
|
<div key='userNotificationFirstNameOption'>
|
||||||
<div className='checkbox'>
|
<div className='checkbox'>
|
||||||
<label>
|
<label>
|
||||||
<input
|
<input
|
||||||
@@ -500,10 +498,10 @@ export default class NotificationsTab extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleUpdateUsernameKey = function handleUsernameKeyChange(e) {
|
handleUpdateUsernameKey = function handleUsernameKeyChange(e) {
|
||||||
self.updateUsernameKey(e.target.checked);
|
this.updateUsernameKey(e.target.checked);
|
||||||
};
|
}.bind(this);
|
||||||
inputs.push(
|
inputs.push(
|
||||||
<div>
|
<div key='userNotificationUsernameOption'>
|
||||||
<div className='checkbox'>
|
<div className='checkbox'>
|
||||||
<label>
|
<label>
|
||||||
<input
|
<input
|
||||||
@@ -519,10 +517,10 @@ export default class NotificationsTab extends React.Component {
|
|||||||
);
|
);
|
||||||
|
|
||||||
handleUpdateMentionKey = function handleMentionKeyChange(e) {
|
handleUpdateMentionKey = function handleMentionKeyChange(e) {
|
||||||
self.updateMentionKey(e.target.checked);
|
this.updateMentionKey(e.target.checked);
|
||||||
};
|
}.bind(this);
|
||||||
inputs.push(
|
inputs.push(
|
||||||
<div>
|
<div key='userNotificationMentionOption'>
|
||||||
<div className='checkbox'>
|
<div className='checkbox'>
|
||||||
<label>
|
<label>
|
||||||
<input
|
<input
|
||||||
@@ -538,10 +536,10 @@ export default class NotificationsTab extends React.Component {
|
|||||||
);
|
);
|
||||||
|
|
||||||
handleUpdateAllKey = function handleAllKeyChange(e) {
|
handleUpdateAllKey = function handleAllKeyChange(e) {
|
||||||
self.updateAllKey(e.target.checked);
|
this.updateAllKey(e.target.checked);
|
||||||
};
|
}.bind(this);
|
||||||
inputs.push(
|
inputs.push(
|
||||||
<div>
|
<div key='userNotificationAllOption'>
|
||||||
<div className='checkbox'>
|
<div className='checkbox'>
|
||||||
<label>
|
<label>
|
||||||
<input
|
<input
|
||||||
@@ -557,10 +555,10 @@ export default class NotificationsTab extends React.Component {
|
|||||||
);
|
);
|
||||||
|
|
||||||
handleUpdateChannelKey = function handleChannelKeyChange(e) {
|
handleUpdateChannelKey = function handleChannelKeyChange(e) {
|
||||||
self.updateChannelKey(e.target.checked);
|
this.updateChannelKey(e.target.checked);
|
||||||
};
|
}.bind(this);
|
||||||
inputs.push(
|
inputs.push(
|
||||||
<div>
|
<div key='userNotificationChannelOption'>
|
||||||
<div className='checkbox'>
|
<div className='checkbox'>
|
||||||
<label>
|
<label>
|
||||||
<input
|
<input
|
||||||
@@ -576,7 +574,7 @@ export default class NotificationsTab extends React.Component {
|
|||||||
);
|
);
|
||||||
|
|
||||||
inputs.push(
|
inputs.push(
|
||||||
<div>
|
<div key='userNotificationCustomOption'>
|
||||||
<div className='checkbox'>
|
<div className='checkbox'>
|
||||||
<label>
|
<label>
|
||||||
<input
|
<input
|
||||||
@@ -600,9 +598,9 @@ export default class NotificationsTab extends React.Component {
|
|||||||
);
|
);
|
||||||
|
|
||||||
handleUpdateKeysSection = function updateKeysSection(e) {
|
handleUpdateKeysSection = function updateKeysSection(e) {
|
||||||
self.props.updateSection('');
|
this.props.updateSection('');
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
};
|
}.bind(this);
|
||||||
keysSection = (
|
keysSection = (
|
||||||
<SettingItemMax
|
<SettingItemMax
|
||||||
title='Words that trigger mentions'
|
title='Words that trigger mentions'
|
||||||
@@ -645,8 +643,8 @@ export default class NotificationsTab extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleUpdateKeysSection = function updateKeysSection() {
|
handleUpdateKeysSection = function updateKeysSection() {
|
||||||
self.props.updateSection('keys');
|
this.props.updateSection('keys');
|
||||||
};
|
}.bind(this);
|
||||||
|
|
||||||
keysSection = (
|
keysSection = (
|
||||||
<SettingItemMin
|
<SettingItemMin
|
||||||
|
|||||||
@@ -8,8 +8,7 @@ var Constants = require('../utils/constants.jsx');
|
|||||||
var PayloadSources = Constants.PayloadSources;
|
var PayloadSources = Constants.PayloadSources;
|
||||||
|
|
||||||
var AppDispatcher = assign(new Dispatcher(), {
|
var AppDispatcher = assign(new Dispatcher(), {
|
||||||
|
handleServerAction: function performServerAction(action) {
|
||||||
handleServerAction: function(action) {
|
|
||||||
var payload = {
|
var payload = {
|
||||||
source: PayloadSources.SERVER_ACTION,
|
source: PayloadSources.SERVER_ACTION,
|
||||||
action: action
|
action: action
|
||||||
@@ -17,14 +16,13 @@ var AppDispatcher = assign(new Dispatcher(), {
|
|||||||
this.dispatch(payload);
|
this.dispatch(payload);
|
||||||
},
|
},
|
||||||
|
|
||||||
handleViewAction: function(action) {
|
handleViewAction: function performViewAction(action) {
|
||||||
var payload = {
|
var payload = {
|
||||||
source: PayloadSources.VIEW_ACTION,
|
source: PayloadSources.VIEW_ACTION,
|
||||||
action: action
|
action: action
|
||||||
};
|
};
|
||||||
this.dispatch(payload);
|
this.dispatch(payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = AppDispatcher;
|
module.exports = AppDispatcher;
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user