Cosmetic reformatting of multiple jsx files
Этот коммит содержится в:
@@ -10,13 +10,18 @@ var SocketStore = require('../stores/socket_store.jsx');
|
||||
var ChannelStore = require('../stores/channel_store.jsx');
|
||||
var PostStore = require('../stores/post_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({
|
||||
componentDidMount: function() {
|
||||
export default class ChannelLoader extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.onSocketChange = this.onSocketChange.bind(this);
|
||||
|
||||
this.state = {};
|
||||
}
|
||||
componentDidMount() {
|
||||
/* Initial aysnc loads */
|
||||
AsyncClient.getMe();
|
||||
AsyncClient.getPosts(ChannelStore.getCurrentId());
|
||||
@@ -60,32 +65,32 @@ module.exports = React.createClass({
|
||||
var user = UserStore.getCurrentUser();
|
||||
|
||||
if (user.props && user.props.theme) {
|
||||
utils.changeCss('div.theme', 'background-color:' + user.props.theme + ';');
|
||||
utils.changeCss('.btn.btn-primary', 'background: ' + user.props.theme + ';');
|
||||
utils.changeCss('.modal .modal-header', 'background: ' + user.props.theme + ';');
|
||||
utils.changeCss('.mention', 'background: ' + 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('.search-item-container:hover', 'background: ' + utils.changeOpacity(user.props.theme, 0.05) + ';');
|
||||
Utils.changeCss('div.theme', 'background-color:' + user.props.theme + ';');
|
||||
Utils.changeCss('.btn.btn-primary', 'background: ' + user.props.theme + ';');
|
||||
Utils.changeCss('.modal .modal-header', 'background: ' + user.props.theme + ';');
|
||||
Utils.changeCss('.mention', 'background: ' + 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('.search-item-container:hover', 'background: ' + Utils.changeOpacity(user.props.theme, 0.05) + ';');
|
||||
}
|
||||
|
||||
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('a.theme', 'color:' + user.props.theme + '; fill:' + user.props.theme + '!important;');
|
||||
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;');
|
||||
} 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');
|
||||
} 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');
|
||||
}
|
||||
},
|
||||
onSocketChange: function(msg) {
|
||||
}
|
||||
onSocketChange(msg) {
|
||||
if (msg && msg.user_id && msg.user_id !== UserStore.getCurrentId()) {
|
||||
UserStore.setStatus(msg.user_id, 'online');
|
||||
}
|
||||
},
|
||||
render: function() {
|
||||
}
|
||||
render() {
|
||||
return <div/>;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,31 +1,70 @@
|
||||
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
module.exports = React.createClass({
|
||||
handleConfirm: function() {
|
||||
$('#'+this.props.parent_id).attr('data-confirm', 'true');
|
||||
$('#'+this.props.parent_id).modal('hide');
|
||||
$('#'+this.props.id).modal('hide');
|
||||
},
|
||||
render: function() {
|
||||
export default class ConfirmModal extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.handleConfirm = this.handleConfirm.bind(this);
|
||||
|
||||
this.state = {};
|
||||
}
|
||||
handleConfirm() {
|
||||
$('#' + this.props.parent_id).attr('data-confirm', 'true');
|
||||
$('#' + this.props.parent_id).modal('hide');
|
||||
$('#' + this.props.id).modal('hide');
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div className="modal fade" id={this.props.id} tabIndex="-1" 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
|
||||
className='modal fade'
|
||||
id={this.props.id}
|
||||
tabIndex='-1'
|
||||
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 className='modal-body'>
|
||||
{this.props.message}
|
||||
</div>
|
||||
<div className='modal-footer'>
|
||||
<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 className="modal-body">
|
||||
{this.props.message}
|
||||
</div>
|
||||
<div className="modal-footer">
|
||||
<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>
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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 PostStore = require('../stores/post_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 AppDispatcher = require('../dispatcher/app_dispatcher.jsx');
|
||||
var Constants = require('../utils/constants.jsx');
|
||||
var ActionTypes = Constants.ActionTypes;
|
||||
|
||||
module.exports = React.createClass({
|
||||
handleDelete: function(e) {
|
||||
Client.deletePost(this.state.channel_id, this.state.post_id,
|
||||
function(data) {
|
||||
var selected_list = this.state.selectedList;
|
||||
if (selected_list && selected_list.order && selected_list.order.length > 0) {
|
||||
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) {
|
||||
export default class DeletePostModal extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.handleDelete = this.handleDelete.bind(this);
|
||||
this.onListenerChange = this.onListenerChange.bind(this);
|
||||
|
||||
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({
|
||||
type: ActionTypes.RECIEVED_SEARCH,
|
||||
results: null
|
||||
@@ -27,14 +35,14 @@ module.exports = React.createClass({
|
||||
type: ActionTypes.RECIEVED_POST_SELECTED,
|
||||
results: null
|
||||
});
|
||||
} else if (selected_post.id === this.state.post_id && this.state.title === "Comment") {
|
||||
if (selected_post.root_id && selected_post.root_id.length > 0 && selected_list.posts[selected_post.root_id]) {
|
||||
selected_list.order = [selected_post.root_id];
|
||||
delete selected_list.posts[selected_post.id];
|
||||
} else if (selectedPost.id === this.state.postId && this.state.title === 'Comment') {
|
||||
if (selectedPost.root_id && selectedPost.root_id.length > 0 && selectedList.posts[selectedPost.root_id]) {
|
||||
selectedList.order = [selectedPost.root_id];
|
||||
delete selectedList.posts[selectedPost.id];
|
||||
|
||||
AppDispatcher.handleServerAction({
|
||||
type: ActionTypes.RECIEVED_POST_SELECTED,
|
||||
post_list: selected_list
|
||||
post_list: selectedList
|
||||
});
|
||||
|
||||
AppDispatcher.handleServerAction({
|
||||
@@ -44,67 +52,98 @@ module.exports = React.createClass({
|
||||
}
|
||||
}
|
||||
}
|
||||
PostStore.removePost(this.state.post_id, this.state.channel_id);
|
||||
AsyncClient.getPosts(this.state.channel_id);
|
||||
PostStore.removePost(this.state.postId, this.state.channelId);
|
||||
AsyncClient.getPosts(this.state.channelId);
|
||||
}.bind(this),
|
||||
function(err) {
|
||||
AsyncClient.dispatchError(err, "deletePost");
|
||||
}.bind(this)
|
||||
function deleteFailed(err) {
|
||||
AsyncClient.dispatchError(err, 'deletePost');
|
||||
}
|
||||
);
|
||||
},
|
||||
componentDidMount: function() {
|
||||
}
|
||||
componentDidMount() {
|
||||
var self = this;
|
||||
$(this.refs.modal.getDOMNode()).on('show.bs.modal', function(e) {
|
||||
$(this.refs.modal.getDOMNode()).on('show.bs.modal', function freshOpen(e) {
|
||||
var newState = {};
|
||||
if(BrowserStore.getItem('edit_state_transfer')) {
|
||||
if (BrowserStore.getItem('edit_state_transfer')) {
|
||||
newState = BrowserStore.getItem('edit_state_transfer');
|
||||
BrowserStore.removeItem('edit_state_transfer');
|
||||
} else {
|
||||
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);
|
||||
});
|
||||
PostStore.addSelectedPostChangeListener(this._onChange);
|
||||
},
|
||||
componentWillUnmount: function() {
|
||||
PostStore.removeSelectedPostChangeListener(this._onChange);
|
||||
},
|
||||
_onChange: function() {
|
||||
PostStore.addSelectedPostChangeListener(this.onListenerChange);
|
||||
}
|
||||
componentWillUnmount() {
|
||||
PostStore.removeSelectedPostChangeListener(this.onListenerChange);
|
||||
}
|
||||
onListenerChange() {
|
||||
var newList = PostStore.getSelectedPost();
|
||||
if (!utils.areStatesEqual(this.state.selectedList, newList)) {
|
||||
this.setState({ selectedList: newList });
|
||||
if (!Utils.areStatesEqual(this.state.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 (
|
||||
<div className="modal fade" id="delete_post" ref="modal" role="dialog" 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
|
||||
className='modal fade'
|
||||
id='delete_post'
|
||||
ref='modal'
|
||||
role='dialog'
|
||||
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 className="modal-body">
|
||||
<div className='modal-body'>
|
||||
Are you sure you want to delete the {this.state.title.toLowerCase()}?
|
||||
<br/>
|
||||
<br/>
|
||||
{ this.state.comments > 0 ?
|
||||
"This post has " + this.state.comments + " comment(s) on it."
|
||||
: "" }
|
||||
{commentWarning}
|
||||
</div>
|
||||
<div className="modal-footer">
|
||||
<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>
|
||||
{error}
|
||||
<div className='modal-footer'>
|
||||
<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>
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,35 +1,58 @@
|
||||
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
module.exports = React.createClass({
|
||||
handleResend: function() {
|
||||
window.location.href = window.location.href + "&resend=true"
|
||||
},
|
||||
render: function() {
|
||||
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>;
|
||||
export default class EmailVerify extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.handleResend = this.handleResend.bind(this);
|
||||
|
||||
this.state = {};
|
||||
}
|
||||
handleResend() {
|
||||
window.location.href = window.location.href + '&resend=true';
|
||||
}
|
||||
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 {
|
||||
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>;
|
||||
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 (
|
||||
<div className="col-sm-offset-4 col-sm-4">
|
||||
<div className="panel panel-default">
|
||||
<div className="panel-heading">
|
||||
<h3 className="panel-title">{ title }</h3>
|
||||
<div className='col-sm-offset-4 col-sm-4'>
|
||||
<div className='panel panel-default'>
|
||||
<div className='panel-heading'>
|
||||
<h3 className='panel-title'>{title}</h3>
|
||||
</div>
|
||||
<div className="panel-body">
|
||||
{ body }
|
||||
{ resend }
|
||||
<div className='panel-body'>
|
||||
{body}
|
||||
{resend}
|
||||
</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.
|
||||
// See License.txt for license information.
|
||||
|
||||
var UserStore = require('../stores/user_store.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');
|
||||
var Utils = require('../utils/utils.jsx');
|
||||
|
||||
module.exports = React.createClass({
|
||||
handleRemove: function(e) {
|
||||
export default class FilePreview extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.handleRemove = this.handleRemove.bind(this);
|
||||
|
||||
this.state = {};
|
||||
}
|
||||
handleRemove(e) {
|
||||
var previewDiv = e.target.parentNode.parentNode;
|
||||
|
||||
if (previewDiv.hasAttribute('data-filename')) {
|
||||
@@ -16,51 +19,96 @@ module.exports = React.createClass({
|
||||
} else if (previewDiv.hasAttribute('data-client-id')) {
|
||||
this.props.onRemove(previewDiv.getAttribute('data-client-id'));
|
||||
}
|
||||
},
|
||||
render: function() {
|
||||
}
|
||||
render() {
|
||||
var previews = [];
|
||||
this.props.files.forEach(function(filename) {
|
||||
|
||||
this.props.files.forEach(function setupPreview(fullFilename) {
|
||||
var filename = fullFilename;
|
||||
var originalFilename = filename;
|
||||
var filenameSplit = filename.split('.');
|
||||
var ext = filenameSplit[filenameSplit.length-1];
|
||||
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;
|
||||
var ext = filenameSplit[filenameSplit.length - 1];
|
||||
var type = Utils.getFileType(ext);
|
||||
|
||||
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(
|
||||
<div key={filename} 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
|
||||
key={filename}
|
||||
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>
|
||||
);
|
||||
} else {
|
||||
previews.push(
|
||||
<div key={filename} 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
|
||||
key={filename}
|
||||
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>
|
||||
);
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
this.props.uploadsInProgress.forEach(function(clientId) {
|
||||
this.props.uploadsInProgress.forEach(function addUploadsInProgress(clientId) {
|
||||
previews.push(
|
||||
<div 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
|
||||
key={clientId}
|
||||
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>
|
||||
);
|
||||
}.bind(this));
|
||||
|
||||
return (
|
||||
<div className="preview-container">
|
||||
<div className='preview-container'>
|
||||
{previews}
|
||||
</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.
|
||||
// See License.txt for license information.
|
||||
var UserStore = require("../stores/user_store.jsx");
|
||||
var UserStore = require('../stores/user_store.jsx');
|
||||
|
||||
module.exports = React.createClass({
|
||||
handleClick: function() {
|
||||
export default class Mention extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.handleClick = this.handleClick.bind(this);
|
||||
|
||||
this.state = null;
|
||||
}
|
||||
handleClick() {
|
||||
this.props.handleClick(this.props.username);
|
||||
},
|
||||
getInitialState: function() {
|
||||
return null;
|
||||
},
|
||||
render: function() {
|
||||
var self = this;
|
||||
}
|
||||
render() {
|
||||
var icon;
|
||||
var timestamp = UserStore.getCurrentUser().update_at;
|
||||
if (this.props.id === "allmention" || this.props.id === "channelmention") {
|
||||
icon = <span><i className="mention-img fa fa-users fa-2x"></i></span>;
|
||||
if (this.props.id === 'allmention' || this.props.id === 'channelmention') {
|
||||
icon = <span><i className='mention-img fa fa-users fa-2x'></i></span>;
|
||||
} 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 {
|
||||
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 (
|
||||
<div className={"mentions-name " + this.props.isFocused} 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
|
||||
className={'mentions-name ' + this.props.isFocused}
|
||||
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>
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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.
|
||||
// See License.txt for license information.
|
||||
|
||||
var utils = require('../utils/utils.jsx');
|
||||
var Utils = require('../utils/utils.jsx');
|
||||
|
||||
module.exports = React.createClass({
|
||||
render: function() {
|
||||
export default class MessageWrapper extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {};
|
||||
}
|
||||
render() {
|
||||
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 (
|
||||
<div>{inner}</div>
|
||||
);
|
||||
} else {
|
||||
return <div/>
|
||||
}
|
||||
|
||||
return <div/>;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
MessageWrapper.defaultProps = {
|
||||
message: null,
|
||||
options: null
|
||||
};
|
||||
MessageWrapper.propTypes = {
|
||||
message: React.PropTypes.string,
|
||||
options: React.PropTypes.object
|
||||
};
|
||||
|
||||
210
web/react/components/navbar_dropdown.jsx
Обычный файл
210
web/react/components/navbar_dropdown.jsx
Обычный файл
@@ -0,0 +1,210 @@
|
||||
// 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);
|
||||
|
||||
var self = this;
|
||||
$(this.refs.dropdown.getDOMNode()).on('hide.bs.dropdown', function resetDropdown() {
|
||||
self.blockToggle = true;
|
||||
setTimeout(function blockTimeout() {
|
||||
self.blockToggle = false;
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
componentWillUnmount() {
|
||||
UserStore.removeTeamsChangeListener(this.onListenerChange);
|
||||
TeamStore.removeChangeListener(this.onListenerChange);
|
||||
|
||||
$(this.refs.dropdown.getDOMNode()).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};
|
||||
}
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'NotifyCounts',
|
||||
componentDidMount: function() {
|
||||
export default class NotifyCounts extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.onListenerChange = this.onListenerChange.bind(this);
|
||||
|
||||
this.state = getCountsStateFromStores();
|
||||
}
|
||||
componentDidMount() {
|
||||
ChannelStore.addChangeListener(this.onListenerChange);
|
||||
},
|
||||
componentWillUnmount: function() {
|
||||
}
|
||||
componentWillUnmount() {
|
||||
ChannelStore.removeChangeListener(this.onListenerChange);
|
||||
},
|
||||
onListenerChange: function() {
|
||||
}
|
||||
onListenerChange() {
|
||||
var newState = getCountsStateFromStores();
|
||||
if (!utils.areStatesEqual(newState, this.state)) {
|
||||
this.setState(newState);
|
||||
}
|
||||
},
|
||||
getInitialState: function() {
|
||||
return getCountsStateFromStores();
|
||||
},
|
||||
render: function() {
|
||||
}
|
||||
render() {
|
||||
if (this.state.count) {
|
||||
return <span className='badge badge-notify'>{this.state.count}</span>;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,143 +1,47 @@
|
||||
// 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 PasswordResetSendLink = require('./password_reset_send_link.jsx');
|
||||
var PasswordResetForm = require('./password_reset_form.jsx');
|
||||
|
||||
SendResetPasswordLink = React.createClass({
|
||||
handleSendLink: function(e) {
|
||||
e.preventDefault();
|
||||
var state = {};
|
||||
export default class PasswordReset extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
var email = this.refs.email.getDOMNode().value.trim();
|
||||
if (!email) {
|
||||
state.error = "Please enter a valid email address."
|
||||
this.setState(state);
|
||||
return;
|
||||
}
|
||||
|
||||
state.error = null;
|
||||
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 (
|
||||
<div className="col-sm-12">
|
||||
<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>
|
||||
);
|
||||
this.state = {};
|
||||
}
|
||||
});
|
||||
|
||||
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") {
|
||||
render() {
|
||||
if (this.props.isReset === 'false') {
|
||||
return (
|
||||
<SendResetPasswordLink
|
||||
<PasswordResetSendLink
|
||||
teamDisplayName={this.props.teamDisplayName}
|
||||
teamName={this.props.teamName}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<ResetPassword
|
||||
teamDisplayName={this.props.teamDisplayName}
|
||||
teamName={this.props.teamName}
|
||||
hash={this.props.hash}
|
||||
data={this.props.data}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<PasswordResetForm
|
||||
teamDisplayName={this.props.teamDisplayName}
|
||||
teamName={this.props.teamName}
|
||||
hash={this.props.hash}
|
||||
data={this.props.data}
|
||||
/>
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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 = 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);
|
||||
|
||||
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 = this.refs.email.getDOMNode().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.'});
|
||||
$(this.refs.reset_form.getDOMNode()).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');
|
||||
|
||||
module.exports = React.createClass({
|
||||
getInitialState: function() {
|
||||
return { };
|
||||
},
|
||||
render: function() {
|
||||
var currentUser = UserStore.getCurrentUser()
|
||||
export default class PostDeletedModal extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {};
|
||||
}
|
||||
render() {
|
||||
var currentUser = UserStore.getCurrentUser();
|
||||
|
||||
if (currentUser != null) {
|
||||
return (
|
||||
<div className="modal fade" ref="modal" id="post_deleted" tabIndex="-1" 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
|
||||
className='modal fade'
|
||||
ref='modal'
|
||||
id='post_deleted'
|
||||
tabIndex='-1'
|
||||
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 className='modal-body'>
|
||||
<p>Someone deleted the message on which you tried to post a comment.</p>
|
||||
</div>
|
||||
<div className='modal-footer'>
|
||||
<button
|
||||
type='button'
|
||||
className='btn btn-primary'
|
||||
data-dismiss='modal'
|
||||
>
|
||||
Okay
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-body">
|
||||
<p>Someone deleted the message on which you tried to post a comment.</p>
|
||||
</div>
|
||||
<div className="modal-footer">
|
||||
<button type="button" className="btn btn-primary" data-dismiss="modal">Okay</button>
|
||||
</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 UserStore = require('../stores/user_store.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 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 ActionTypes = Constants.ActionTypes;
|
||||
|
||||
@@ -25,7 +25,7 @@ export default class RhsComment extends React.Component {
|
||||
e.preventDefault();
|
||||
|
||||
var post = this.props.post;
|
||||
client.createPost(post, post.channel_id,
|
||||
Client.createPost(post, post.channel_id,
|
||||
function success(data) {
|
||||
AsyncClient.getPosts(post.channel_id);
|
||||
|
||||
@@ -52,7 +52,7 @@ export default class RhsComment extends React.Component {
|
||||
this.forceUpdate();
|
||||
}
|
||||
shouldComponentUpdate(nextProps) {
|
||||
if (!utils.areStatesEqual(nextProps.post, this.props.post)) {
|
||||
if (!Utils.areStatesEqual(nextProps.post, this.props.post)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ export default class RhsComment extends React.Component {
|
||||
type = 'Comment';
|
||||
}
|
||||
|
||||
var message = utils.textToJsx(post.message);
|
||||
var message = Utils.textToJsx(post.message);
|
||||
var timestamp = UserStore.getCurrentUser().update_at;
|
||||
|
||||
var loading;
|
||||
@@ -182,7 +182,7 @@ export default class RhsComment extends React.Component {
|
||||
</li>
|
||||
<li className='post-header-col'>
|
||||
<time className='post-right-comment-time'>
|
||||
{utils.displayCommentDateTime(post.create_at)}
|
||||
{Utils.displayCommentDateTime(post.create_at)}
|
||||
</time>
|
||||
</li>
|
||||
<li className='post-header-col post-header__reply'>
|
||||
|
||||
@@ -1,133 +1,25 @@
|
||||
// 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 NavbarDropdown = require('./navbar_dropdown.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() {
|
||||
return {teams: UserStore.getTeams(), currentTeam: TeamStore.getCurrent()};
|
||||
}
|
||||
this.toggleDropdown = this.toggleDropdown.bind(this);
|
||||
|
||||
var NavbarDropdown = React.createClass({
|
||||
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);
|
||||
}
|
||||
}
|
||||
},
|
||||
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>
|
||||
);
|
||||
this.state = {};
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'SidebarHeader',
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
teamDisplayName: config.SiteName
|
||||
};
|
||||
},
|
||||
|
||||
toggleDropdown: function() {
|
||||
toggleDropdown() {
|
||||
if (this.refs.dropdown.blockToggle) {
|
||||
this.refs.dropdown.blockToggle = false;
|
||||
return;
|
||||
}
|
||||
$('.team__header').find('.dropdown-toggle').dropdown('toggle');
|
||||
},
|
||||
|
||||
render: function() {
|
||||
}
|
||||
render() {
|
||||
var me = UserStore.getCurrentUser();
|
||||
var profilePicture = null;
|
||||
|
||||
@@ -136,20 +28,38 @@ module.exports = React.createClass({
|
||||
}
|
||||
|
||||
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 (
|
||||
<div className='team__header theme'>
|
||||
<a href='#' onClick={this.toggleDropdown}>
|
||||
<a
|
||||
href='#'
|
||||
onClick={this.toggleDropdown}
|
||||
>
|
||||
{profilePicture}
|
||||
<div className='header__info'>
|
||||
<div className='user__name'>{'@' + me.username}</div>
|
||||
<div className='team__name'>{this.props.teamDisplayName }</div>
|
||||
<div className='team__name'>{this.props.teamDisplayName}</div>
|
||||
</div>
|
||||
</a>
|
||||
<NavbarDropdown ref='dropdown' teamType={this.props.teamType} />
|
||||
<NavbarDropdown
|
||||
ref='dropdown'
|
||||
teamType={this.props.teamType}
|
||||
/>
|
||||
</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 RhsThread = require('./rhs_thread.jsx');
|
||||
var PostStore = require('../stores/post_store.jsx');
|
||||
var utils = require('../utils/utils.jsx');
|
||||
var Utils = require('../utils/utils.jsx');
|
||||
|
||||
function getStateFromStores(from_search) {
|
||||
return { search_visible: PostStore.getSearchResults() != null, post_right_visible: PostStore.getSelectedPost() != null, is_mention_search: PostStore.getIsMentionSearch() };
|
||||
function getStateFromStores() {
|
||||
return {search_visible: PostStore.getSearchResults() != null, post_right_visible: PostStore.getSelectedPost() != null, is_mention_search: PostStore.getIsMentionSearch()};
|
||||
}
|
||||
|
||||
module.exports = React.createClass({
|
||||
componentDidMount: function() {
|
||||
PostStore.addSearchChangeListener(this._onSearchChange);
|
||||
PostStore.addSelectedPostChangeListener(this._onSelectedChange);
|
||||
},
|
||||
componentWillUnmount: function() {
|
||||
PostStore.removeSearchChangeListener(this._onSearchChange);
|
||||
PostStore.removeSelectedPostChangeListener(this._onSelectedChange);
|
||||
},
|
||||
_onSelectedChange: function(from_search) {
|
||||
if (this.isMounted()) {
|
||||
var newState = getStateFromStores(from_search);
|
||||
newState.from_search = from_search;
|
||||
if (!utils.areStatesEqual(newState, this.state)) {
|
||||
this.setState(newState);
|
||||
}
|
||||
export default class SidebarRight extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.onSelectedChange = this.onSelectedChange.bind(this);
|
||||
this.onSearchChange = this.onSearchChange.bind(this);
|
||||
this.resize = this.resize.bind(this);
|
||||
|
||||
this.state = getStateFromStores();
|
||||
}
|
||||
componentDidMount() {
|
||||
PostStore.addSearchChangeListener(this.onSearchChange);
|
||||
PostStore.addSelectedPostChangeListener(this.onSelectedChange);
|
||||
}
|
||||
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);
|
||||
}
|
||||
},
|
||||
_onSearchChange: function() {
|
||||
if (this.isMounted()) {
|
||||
var newState = getStateFromStores();
|
||||
if (!utils.areStatesEqual(newState, this.state)) {
|
||||
this.setState(newState);
|
||||
}
|
||||
}
|
||||
onSearchChange() {
|
||||
var newState = getStateFromStores();
|
||||
if (!Utils.areStatesEqual(newState, this.state)) {
|
||||
this.setState(newState);
|
||||
}
|
||||
},
|
||||
resize: function() {
|
||||
}
|
||||
resize() {
|
||||
var postHolder = $('.post-list-holder-by-time');
|
||||
postHolder[0].scrollTop = postHolder[0].scrollHeight - 224;
|
||||
},
|
||||
getInitialState: function() {
|
||||
return getStateFromStores();
|
||||
},
|
||||
render: function() {
|
||||
if (! (this.state.search_visible || this.state.post_right_visible)) {
|
||||
}
|
||||
render() {
|
||||
if (!(this.state.search_visible || this.state.post_right_visible)) {
|
||||
$('.inner__wrap').removeClass('move--left').removeClass('move--right');
|
||||
$('.sidebar--right').removeClass('move--left');
|
||||
this.resize();
|
||||
@@ -58,25 +60,27 @@ module.exports = React.createClass({
|
||||
$('.sidebar--right').addClass('move--left');
|
||||
$('.sidebar--right').prepend('<div class="sidebar__overlay"></div>');
|
||||
this.resize();
|
||||
setTimeout(function(){
|
||||
$('.sidebar__overlay').fadeOut("200", function(){
|
||||
setTimeout(function overlayTimer() {
|
||||
$('.sidebar__overlay').fadeOut('200', function fadeOverlay() {
|
||||
$(this).remove();
|
||||
});
|
||||
},500)
|
||||
}, 500);
|
||||
|
||||
var content = "";
|
||||
var content = '';
|
||||
|
||||
if (this.state.search_visible) {
|
||||
content = <SearchResults isMentionSearch={this.state.is_mention_search} />;
|
||||
}
|
||||
else if (this.state.post_right_visible) {
|
||||
content = <RhsThread fromSearch={this.state.from_search} isMentionSearch={this.state.is_mention_search} />;
|
||||
} else if (this.state.post_right_visible) {
|
||||
content = (<RhsThread
|
||||
fromSearch={this.state.from_search}
|
||||
isMentionSearch={this.state.is_mention_search}
|
||||
/>);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="sidebar-right-container">
|
||||
{ content }
|
||||
<div className='sidebar-right-container'>
|
||||
{content}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -10,69 +10,99 @@ var UsernamePage = require('./team_signup_username_page.jsx');
|
||||
var PasswordPage = require('./team_signup_password_page.jsx');
|
||||
var BrowserStore = require('../stores/browser_store.jsx');
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'SignupTeamComplete',
|
||||
propTypes: {
|
||||
hash: React.PropTypes.string,
|
||||
email: React.PropTypes.string,
|
||||
data: React.PropTypes.string
|
||||
},
|
||||
updateParent: function(state, skipSet) {
|
||||
export default class SignupTeamComplete extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.updateParent = this.updateParent.bind(this);
|
||||
|
||||
var initialState = BrowserStore.getGlobalItem(props.hash);
|
||||
|
||||
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);
|
||||
|
||||
if (!skipSet) {
|
||||
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;
|
||||
}
|
||||
|
||||
return props;
|
||||
},
|
||||
render: function() {
|
||||
}
|
||||
render() {
|
||||
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') {
|
||||
return <TeamDisplayNamePage state={this.state} updateParent={this.updateParent} />;
|
||||
return (<TeamDisplayNamePage
|
||||
state={this.state}
|
||||
updateParent={this.updateParent}
|
||||
/>);
|
||||
}
|
||||
|
||||
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') {
|
||||
return <AllowedDomainsPage state={this.state} updateParent={this.updateParent} />;
|
||||
return (<AllowedDomainsPage
|
||||
state={this.state}
|
||||
updateParent={this.updateParent}
|
||||
/>);
|
||||
}
|
||||
|
||||
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') {
|
||||
return <UsernamePage state={this.state} updateParent={this.updateParent} />;
|
||||
return (<UsernamePage
|
||||
state={this.state}
|
||||
updateParent={this.updateParent}
|
||||
/>);
|
||||
}
|
||||
|
||||
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>);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
SignupTeamComplete.defaultProps = {
|
||||
hash: '',
|
||||
email: '',
|
||||
data: ''
|
||||
};
|
||||
SignupTeamComplete.propTypes = {
|
||||
hash: React.PropTypes.string,
|
||||
email: React.PropTypes.string,
|
||||
data: React.PropTypes.string
|
||||
};
|
||||
|
||||
@@ -7,8 +7,28 @@ var UserStore = require('../stores/user_store.jsx');
|
||||
var BrowserStore = require('../stores/browser_store.jsx');
|
||||
var Constants = require('../utils/constants.jsx');
|
||||
|
||||
module.exports = React.createClass({
|
||||
handleSubmit: function(e) {
|
||||
export default class SignupUserComplete extends React.Component {
|
||||
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();
|
||||
|
||||
this.state.user.username = this.refs.name.getDOMNode().value.trim();
|
||||
@@ -38,7 +58,7 @@ module.exports = React.createClass({
|
||||
}
|
||||
|
||||
this.state.user.password = this.refs.password.getDOMNode().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: ''});
|
||||
return;
|
||||
}
|
||||
@@ -48,11 +68,11 @@ module.exports = React.createClass({
|
||||
this.state.user.allow_marketing = true;
|
||||
|
||||
client.createUser(this.state.user, this.state.data, this.state.hash,
|
||||
function(data) {
|
||||
function createUserSuccess() {
|
||||
client.track('signup', 'signup_user_02_complete');
|
||||
|
||||
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.setCurrentUser(data);
|
||||
if (this.props.hash > 0) {
|
||||
@@ -60,7 +80,7 @@ module.exports = React.createClass({
|
||||
}
|
||||
window.location.href = '/';
|
||||
}.bind(this),
|
||||
function(err) {
|
||||
function emailLoginFailure(err) {
|
||||
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);
|
||||
} else {
|
||||
@@ -69,28 +89,12 @@ module.exports = React.createClass({
|
||||
}.bind(this)
|
||||
);
|
||||
}.bind(this),
|
||||
function(err) {
|
||||
function createUserFailure(err) {
|
||||
this.setState({serverError: err.message});
|
||||
}.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;
|
||||
}
|
||||
|
||||
return state;
|
||||
},
|
||||
render: function() {
|
||||
}
|
||||
render() {
|
||||
client.track('signup', 'signup_user_01_welcome');
|
||||
|
||||
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>;
|
||||
}
|
||||
|
||||
var emailContainerStyle = "margin--extra";
|
||||
var emailContainerStyle = 'margin--extra';
|
||||
if (this.state.original_email) {
|
||||
emailContainerStyle = "hidden";
|
||||
emailContainerStyle = 'hidden';
|
||||
}
|
||||
|
||||
var email = (
|
||||
<div className={emailContainerStyle}>
|
||||
<h5><strong>What's your email address?</strong></h5>
|
||||
<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}
|
||||
</div>
|
||||
</div>
|
||||
@@ -155,7 +167,10 @@ module.exports = React.createClass({
|
||||
var signupMessage = [];
|
||||
if (authServices.indexOf(Constants.GITLAB_SERVICE) >= 0) {
|
||||
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>with GitLab</span>
|
||||
</a>
|
||||
@@ -172,7 +187,13 @@ module.exports = React.createClass({
|
||||
<div className='margin--extra'>
|
||||
<h5><strong>Choose your username</strong></h5>
|
||||
<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}
|
||||
<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>
|
||||
@@ -180,12 +201,26 @@ module.exports = React.createClass({
|
||||
<div className='margin--extra'>
|
||||
<h5><strong>Choose your password</strong></h5>
|
||||
<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}
|
||||
</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>
|
||||
);
|
||||
}
|
||||
@@ -209,7 +244,10 @@ module.exports = React.createClass({
|
||||
return (
|
||||
<div>
|
||||
<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>
|
||||
<h2 className='signup-team__name'>{this.props.teamDisplayName}</h2>
|
||||
<h2 className='signup-team__subdomain'>on {config.SiteName}</h2>
|
||||
@@ -222,6 +260,23 @@ module.exports = React.createClass({
|
||||
</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.
|
||||
|
||||
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 client = require('../utils/client.jsx');
|
||||
var Client = require('../utils/client.jsx');
|
||||
|
||||
export default class TeamSignupSendInvitesPage extends React.Component {
|
||||
constructor(props) {
|
||||
@@ -71,7 +71,7 @@ export default class TeamSignupSendInvitesPage extends React.Component {
|
||||
}
|
||||
keySubmit(e) {
|
||||
if (e && e.keyCode === 13) {
|
||||
this.submitNext(e)
|
||||
this.submitNext(e);
|
||||
}
|
||||
}
|
||||
componentWillMount() {
|
||||
@@ -92,7 +92,7 @@ export default class TeamSignupSendInvitesPage extends React.Component {
|
||||
}
|
||||
}
|
||||
render() {
|
||||
client.track('signup', 'signup_team_05_send_invites');
|
||||
Client.track('signup', 'signup_team_05_send_invites');
|
||||
|
||||
var content = null;
|
||||
var bottomContent = null;
|
||||
@@ -165,7 +165,7 @@ export default class TeamSignupSendInvitesPage extends React.Component {
|
||||
className='signup-team-logo'
|
||||
src='/static/images/logo.png'
|
||||
/>
|
||||
<h2>{'Invite ' + utils.toTitleCase(strings.Team) + ' Members'}</h2>
|
||||
<h2>{'Invite ' + Utils.toTitleCase(strings.Team) + ' Members'}</h2>
|
||||
{content}
|
||||
<div className='form-group'>
|
||||
<button
|
||||
@@ -190,6 +190,7 @@ export default class TeamSignupSendInvitesPage extends React.Component {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
TeamSignupSendInvitesPage.propTypes = {
|
||||
state: React.PropTypes.object.isRequired,
|
||||
updateParent: React.PropTypes.func.isRequired
|
||||
|
||||
@@ -1,26 +1,29 @@
|
||||
// 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 Utils = require('../utils/utils.jsx');
|
||||
var Client = require('../utils/client.jsx');
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'TeamSignupUsernamePage',
|
||||
propTypes: {
|
||||
state: React.PropTypes.object,
|
||||
updateParent: React.PropTypes.func
|
||||
},
|
||||
submitBack: function(e) {
|
||||
export default class TeamSignupUsernamePage extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.submitBack = this.submitBack.bind(this);
|
||||
this.submitNext = this.submitNext.bind(this);
|
||||
|
||||
this.state = {};
|
||||
}
|
||||
submitBack(e) {
|
||||
e.preventDefault();
|
||||
this.props.state.wizard = 'send_invites';
|
||||
this.props.updateParent(this.props.state);
|
||||
},
|
||||
submitNext: function(e) {
|
||||
}
|
||||
submitNext(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var name = this.refs.name.getDOMNode().value.trim();
|
||||
|
||||
var usernameError = utils.isValidUsername(name);
|
||||
var usernameError = Utils.isValidUsername(name);
|
||||
if (usernameError === 'Cannot use a reserved word as a username.') {
|
||||
this.setState({nameError: 'This username is reserved, please choose a new one.'});
|
||||
return;
|
||||
@@ -32,12 +35,9 @@ module.exports = React.createClass({
|
||||
this.props.state.wizard = 'password';
|
||||
this.props.state.user.username = name;
|
||||
this.props.updateParent(this.props.state);
|
||||
},
|
||||
getInitialState: function() {
|
||||
return {};
|
||||
},
|
||||
render: function() {
|
||||
client.track('signup', 'signup_team_06_username');
|
||||
}
|
||||
render() {
|
||||
Client.track('signup', 'signup_team_06_username');
|
||||
|
||||
var nameError = null;
|
||||
var nameDivClass = 'form-group';
|
||||
@@ -49,7 +49,10 @@ module.exports = React.createClass({
|
||||
return (
|
||||
<div>
|
||||
<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>
|
||||
<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'>
|
||||
@@ -57,19 +60,47 @@ module.exports = React.createClass({
|
||||
<div className='row'>
|
||||
<div className='col-sm-11'>
|
||||
<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>
|
||||
</div>
|
||||
{nameError}
|
||||
</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'>
|
||||
<a href='#' onClick={this.submitBack}>Back to previous step</a>
|
||||
<a
|
||||
href='#'
|
||||
onClick={this.submitBack}
|
||||
>
|
||||
Back to previous step
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</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.
|
||||
// See License.txt for license information.
|
||||
|
||||
var utils = require('../utils/utils.jsx');
|
||||
var client = require('../utils/client.jsx');
|
||||
var Utils = require('../utils/utils.jsx');
|
||||
var Client = require('../utils/client.jsx');
|
||||
var BrowserStore = require('../stores/browser_store.jsx');
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'TeamSignupWelcomePage',
|
||||
propTypes: {
|
||||
state: React.PropTypes.object,
|
||||
updateParent: React.PropTypes.func
|
||||
},
|
||||
submitNext: function(e) {
|
||||
export default class TeamSignupWelcomePage extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.submitNext = this.submitNext.bind(this);
|
||||
this.handleDiffEmail = this.handleDiffEmail.bind(this);
|
||||
this.handleDiffSubmit = this.handleDiffSubmit.bind(this);
|
||||
this.handleKeyPress = this.handleKeyPress.bind(this);
|
||||
|
||||
this.state = {useDiff: false};
|
||||
}
|
||||
submitNext(e) {
|
||||
if (!BrowserStore.isLocalStorageSupported()) {
|
||||
this.setState({storageError: 'This service requires local storage to be enabled. Please enable it or exit private browsing.'});
|
||||
return;
|
||||
@@ -19,18 +24,18 @@ module.exports = React.createClass({
|
||||
e.preventDefault();
|
||||
this.props.state.wizard = 'team_display_name';
|
||||
this.props.updateParent(this.props.state);
|
||||
},
|
||||
handleDiffEmail: function(e) {
|
||||
}
|
||||
handleDiffEmail(e) {
|
||||
e.preventDefault();
|
||||
this.setState({useDiff: true});
|
||||
},
|
||||
handleDiffSubmit: function(e) {
|
||||
}
|
||||
handleDiffSubmit(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var state = {useDiff: true, serverError: ''};
|
||||
|
||||
var email = this.refs.email.getDOMNode().value.trim().toLowerCase();
|
||||
if (!email || !utils.isEmail(email)) {
|
||||
if (!email || !Utils.isEmail(email)) {
|
||||
state.emailError = 'Please enter a valid email address';
|
||||
this.setState(state);
|
||||
return;
|
||||
@@ -41,7 +46,7 @@ module.exports = React.createClass({
|
||||
}
|
||||
state.emailError = '';
|
||||
|
||||
client.signupTeam(email,
|
||||
Client.signupTeam(email,
|
||||
function success(data) {
|
||||
if (data.follow_link) {
|
||||
window.location.href = data.follow_link;
|
||||
@@ -56,23 +61,20 @@ module.exports = React.createClass({
|
||||
this.setState(this.state);
|
||||
}.bind(this)
|
||||
);
|
||||
},
|
||||
getInitialState: function() {
|
||||
return {useDiff: false};
|
||||
},
|
||||
handleKeyPress: function(event) {
|
||||
}
|
||||
handleKeyPress(event) {
|
||||
if (event.keyCode === 13) {
|
||||
this.submitNext(event);
|
||||
}
|
||||
},
|
||||
componentWillMount: function() {
|
||||
}
|
||||
componentWillMount() {
|
||||
document.addEventListener('keyup', this.handleKeyPress, false);
|
||||
},
|
||||
componentWillUnmount: function() {
|
||||
}
|
||||
componentWillUnmount() {
|
||||
document.removeEventListener('keyup', this.handleKeyPress, false);
|
||||
},
|
||||
render: function() {
|
||||
client.track('signup', 'signup_team_01_welcome');
|
||||
}
|
||||
render() {
|
||||
Client.track('signup', 'signup_team_01_welcome');
|
||||
|
||||
var storageError = null;
|
||||
if (this.state.storageError) {
|
||||
@@ -105,7 +107,10 @@ module.exports = React.createClass({
|
||||
return (
|
||||
<div>
|
||||
<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>
|
||||
<h1 className='margin--top-none'>{config.SiteName}</h1>
|
||||
</p>
|
||||
@@ -121,7 +126,14 @@ module.exports = React.createClass({
|
||||
You can add other administrators later.
|
||||
</p>
|
||||
<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}
|
||||
</div>
|
||||
<hr />
|
||||
@@ -129,16 +141,42 @@ module.exports = React.createClass({
|
||||
<div className={emailDivClass}>
|
||||
<div className='row'>
|
||||
<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>
|
||||
{emailError}
|
||||
</div>
|
||||
{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>
|
||||
<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>
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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 UserSettings = require('./user_settings.jsx');
|
||||
|
||||
module.exports = React.createClass({
|
||||
componentDidMount: function() {
|
||||
$('body').on('click', '.modal-back', function(){
|
||||
export default class UserSettingsModal extends React.Component {
|
||||
constructor(props) {
|
||||
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');
|
||||
});
|
||||
$('body').on('click', '.modal-header .close', function(){
|
||||
setTimeout(function() {
|
||||
$('body').on('click', '.modal-header .close', function closeModal() {
|
||||
setTimeout(function finishClose() {
|
||||
$('.modal-dialog.display--content').removeClass('display--content');
|
||||
}, 500);
|
||||
});
|
||||
},
|
||||
updateTab: function(tab) {
|
||||
this.setState({ active_tab: tab });
|
||||
},
|
||||
updateSection: function(section) {
|
||||
this.setState({ active_section: section });
|
||||
},
|
||||
getInitialState: function() {
|
||||
return { active_tab: "general", active_section: "" };
|
||||
},
|
||||
render: function() {
|
||||
}
|
||||
updateTab(tab) {
|
||||
this.setState({active_tab: tab});
|
||||
}
|
||||
updateSection(section) {
|
||||
this.setState({active_section: section});
|
||||
}
|
||||
render() {
|
||||
var tabs = [];
|
||||
tabs.push({name: "general", uiName: "General", icon: "glyphicon glyphicon-cog"});
|
||||
tabs.push({name: "security", uiName: "Security", icon: "glyphicon glyphicon-lock"});
|
||||
tabs.push({name: "notifications", uiName: "Notifications", icon: "glyphicon glyphicon-exclamation-sign"});
|
||||
tabs.push({name: "appearance", uiName: "Appearance", icon: "glyphicon glyphicon-wrench"});
|
||||
tabs.push({name: 'general', uiName: 'General', icon: 'glyphicon glyphicon-cog'});
|
||||
tabs.push({name: 'security', uiName: 'Security', icon: 'glyphicon glyphicon-lock'});
|
||||
tabs.push({name: 'notifications', uiName: 'Notifications', icon: 'glyphicon glyphicon-exclamation-sign'});
|
||||
tabs.push({name: 'appearance', uiName: 'Appearance', icon: 'glyphicon glyphicon-wrench'});
|
||||
|
||||
return (
|
||||
<div className="modal fade" ref="modal" id="user_settings" role="dialog" 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
|
||||
className='modal fade'
|
||||
ref='modal'
|
||||
id='user_settings'
|
||||
role='dialog'
|
||||
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 className="modal-body">
|
||||
<div className="settings-table">
|
||||
<div className="settings-links">
|
||||
<div className='modal-body'>
|
||||
<div className='settings-table'>
|
||||
<div className='settings-links'>
|
||||
<SettingsSidebar
|
||||
tabs={tabs}
|
||||
activeTab={this.state.active_tab}
|
||||
updateTab={this.updateTab}
|
||||
/>
|
||||
</div>
|
||||
<div className="settings-content minimize-settings">
|
||||
<div className='settings-content minimize-settings'>
|
||||
<UserSettings
|
||||
activeTab={this.state.active_tab}
|
||||
activeSection={this.state.active_section}
|
||||
@@ -63,4 +87,4 @@ module.exports = React.createClass({
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -229,7 +229,7 @@ export default class NotificationsTab extends React.Component {
|
||||
let inputs = [];
|
||||
|
||||
inputs.push(
|
||||
<div>
|
||||
<div key='userNotificationLevelOption'>
|
||||
<div className='radio'>
|
||||
<label>
|
||||
<input type='radio'
|
||||
@@ -276,7 +276,7 @@ export default class NotificationsTab extends React.Component {
|
||||
<div className='setting-list__hint'>
|
||||
These settings will override the global notification settings for the <b>{this.state.curChannel}</b> channel
|
||||
</div>
|
||||
)
|
||||
);
|
||||
|
||||
desktopSection = (
|
||||
<SettingItemMax
|
||||
@@ -324,7 +324,7 @@ export default class NotificationsTab extends React.Component {
|
||||
let inputs = [];
|
||||
|
||||
inputs.push(
|
||||
<div>
|
||||
<div key='userNotificationSoundOptions'>
|
||||
<div className='radio'>
|
||||
<label>
|
||||
<input
|
||||
@@ -403,7 +403,7 @@ export default class NotificationsTab extends React.Component {
|
||||
let inputs = [];
|
||||
|
||||
inputs.push(
|
||||
<div>
|
||||
<div key='userNotificationEmailOptions'>
|
||||
<div className='radio'>
|
||||
<label>
|
||||
<input
|
||||
@@ -483,7 +483,7 @@ export default class NotificationsTab extends React.Component {
|
||||
self.updateFirstNameKey(e.target.checked);
|
||||
};
|
||||
inputs.push(
|
||||
<div>
|
||||
<div key='userNotificationFirstNameOption'>
|
||||
<div className='checkbox'>
|
||||
<label>
|
||||
<input
|
||||
@@ -503,7 +503,7 @@ export default class NotificationsTab extends React.Component {
|
||||
self.updateUsernameKey(e.target.checked);
|
||||
};
|
||||
inputs.push(
|
||||
<div>
|
||||
<div key='userNotificationUsernameOption'>
|
||||
<div className='checkbox'>
|
||||
<label>
|
||||
<input
|
||||
@@ -522,7 +522,7 @@ export default class NotificationsTab extends React.Component {
|
||||
self.updateMentionKey(e.target.checked);
|
||||
};
|
||||
inputs.push(
|
||||
<div>
|
||||
<div key='userNotificationMentionOption'>
|
||||
<div className='checkbox'>
|
||||
<label>
|
||||
<input
|
||||
@@ -541,7 +541,7 @@ export default class NotificationsTab extends React.Component {
|
||||
self.updateAllKey(e.target.checked);
|
||||
};
|
||||
inputs.push(
|
||||
<div>
|
||||
<div key='userNotificationAllOption'>
|
||||
<div className='checkbox'>
|
||||
<label>
|
||||
<input
|
||||
@@ -560,7 +560,7 @@ export default class NotificationsTab extends React.Component {
|
||||
self.updateChannelKey(e.target.checked);
|
||||
};
|
||||
inputs.push(
|
||||
<div>
|
||||
<div key='userNotificationChannelOption'>
|
||||
<div className='checkbox'>
|
||||
<label>
|
||||
<input
|
||||
@@ -576,7 +576,7 @@ export default class NotificationsTab extends React.Component {
|
||||
);
|
||||
|
||||
inputs.push(
|
||||
<div>
|
||||
<div key='userNotificationCustomOption'>
|
||||
<div className='checkbox'>
|
||||
<label>
|
||||
<input
|
||||
|
||||
@@ -8,23 +8,21 @@ var Constants = require('../utils/constants.jsx');
|
||||
var PayloadSources = Constants.PayloadSources;
|
||||
|
||||
var AppDispatcher = assign(new Dispatcher(), {
|
||||
handleServerAction: function performServerAction(action) {
|
||||
var payload = {
|
||||
source: PayloadSources.SERVER_ACTION,
|
||||
action: action
|
||||
};
|
||||
this.dispatch(payload);
|
||||
},
|
||||
|
||||
handleServerAction: function(action) {
|
||||
var payload = {
|
||||
source: PayloadSources.SERVER_ACTION,
|
||||
action: action
|
||||
};
|
||||
this.dispatch(payload);
|
||||
},
|
||||
|
||||
handleViewAction: function(action) {
|
||||
var payload = {
|
||||
source: PayloadSources.VIEW_ACTION,
|
||||
action: action
|
||||
};
|
||||
this.dispatch(payload);
|
||||
}
|
||||
|
||||
handleViewAction: function performViewAction(action) {
|
||||
var payload = {
|
||||
source: PayloadSources.VIEW_ACTION,
|
||||
action: action
|
||||
};
|
||||
this.dispatch(payload);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = AppDispatcher;
|
||||
|
||||
Ссылка в новой задаче
Block a user