summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorReed Garmsen <rgarmsen2295@gmail.com>2015-08-31 09:35:31 -0700
committerReed Garmsen <rgarmsen2295@gmail.com>2015-09-02 08:30:23 -0700
commite2a24f40b750886156cef33a38218315c06aef35 (patch)
treee9aca4d43db86b78e3bb0e646dfe303ddc909565
parent5b81125e4db03753c6a2b6076e8303b252e7232c (diff)
downloadchat-e2a24f40b750886156cef33a38218315c06aef35.tar.gz
chat-e2a24f40b750886156cef33a38218315c06aef35.tar.bz2
chat-e2a24f40b750886156cef33a38218315c06aef35.zip
Cosmetic reformatting of multiple jsx files
-rw-r--r--web/react/components/channel_loader.jsx45
-rw-r--r--web/react/components/confirm_modal.jsx83
-rw-r--r--web/react/components/delete_post_modal.jsx143
-rw-r--r--web/react/components/email_verify.jsx65
-rw-r--r--web/react/components/file_preview.jsx106
-rw-r--r--web/react/components/mention.jsx61
-rw-r--r--web/react/components/message_wrapper.jsx27
-rw-r--r--web/react/components/navbar_dropdown.jsx210
-rw-r--r--web/react/components/notify_counts.jsx29
-rw-r--r--web/react/components/password_reset.jsx164
-rw-r--r--web/react/components/password_reset_form.jsx100
-rw-r--r--web/react/components/password_reset_send_link.jsx98
-rw-r--r--web/react/components/post_deleted_modal.jsx73
-rw-r--r--web/react/components/rhs_comment.jsx12
-rw-r--r--web/react/components/sidebar_header.jsx154
-rw-r--r--web/react/components/sidebar_right.jsx92
-rw-r--r--web/react/components/signup_team_complete.jsx106
-rw-r--r--web/react/components/signup_user_complete.jsx125
-rw-r--r--web/react/components/team_signup_send_invites_page.jsx11
-rw-r--r--web/react/components/team_signup_username_page.jsx77
-rw-r--r--web/react/components/team_signup_welcome_page.jsx104
-rw-r--r--web/react/components/user_settings_modal.jsx86
-rw-r--r--web/react/components/user_settings_notifications.jsx20
-rw-r--r--web/react/dispatcher/app_dispatcher.jsx30
24 files changed, 1324 insertions, 697 deletions
diff --git a/web/react/components/channel_loader.jsx b/web/react/components/channel_loader.jsx
index 0fa433383..8e8ed3f73 100644
--- a/web/react/components/channel_loader.jsx
+++ b/web/react/components/channel_loader.jsx
@@ -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/>;
}
-});
+}
diff --git a/web/react/components/confirm_modal.jsx b/web/react/components/confirm_modal.jsx
index 3be13cf9b..cb3b9c5e3 100644
--- a/web/react/components/confirm_modal.jsx
+++ b/web/react/components/confirm_modal.jsx
@@ -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>
- <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
+ 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>
- </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
+};
diff --git a/web/react/components/delete_post_modal.jsx b/web/react/components/delete_post_modal.jsx
index 55d6f509c..41ffe678b 100644
--- a/web/react/components/delete_post_modal.jsx
+++ b/web/react/components/delete_post_modal.jsx
@@ -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">&times;</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'>&times;</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>
);
}
-});
+}
diff --git a/web/react/components/email_verify.jsx b/web/react/components/email_verify.jsx
index 678eb9928..f2e91dd98 100644
--- a/web/react/components/email_verify.jsx
+++ b/web/react/components/email_verify.jsx
@@ -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
+};
diff --git a/web/react/components/file_preview.jsx b/web/react/components/file_preview.jsx
index d1b2f734a..33382a439 100644
--- a/web/react/components/file_preview.jsx
+++ b/web/react/components/file_preview.jsx
@@ -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);
+ 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];
+
+ if (filename.indexOf('/api/v1/files/get') !== -1) {
+ filename = filename.split('/api/v1/files/get')[1];
}
- filename = utils.getWindowLocationOrigin() + "/api/v1/files/get" + filename;
+ filename = Utils.getWindowLocationOrigin() + '/api/v1/files/get' + filename;
- if (type === "image") {
+ 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
+};
diff --git a/web/react/components/mention.jsx b/web/react/components/mention.jsx
index 114dc183f..72a2a6251 100644
--- a/web/react/components/mention.jsx
+++ b/web/react/components/mention.jsx
@@ -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
+};
diff --git a/web/react/components/message_wrapper.jsx b/web/react/components/message_wrapper.jsx
index 5fc88a61b..bce305853 100644
--- a/web/react/components/message_wrapper.jsx
+++ b/web/react/components/message_wrapper.jsx
@@ -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
+};
diff --git a/web/react/components/navbar_dropdown.jsx b/web/react/components/navbar_dropdown.jsx
new file mode 100644
index 000000000..7ffaeb712
--- /dev/null
+++ b/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
+};
diff --git a/web/react/components/notify_counts.jsx b/web/react/components/notify_counts.jsx
index ebc49882b..0b7c41b62 100644
--- a/web/react/components/notify_counts.jsx
+++ b/web/react/components/notify_counts.jsx
@@ -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;
}
-});
+}
diff --git a/web/react/components/password_reset.jsx b/web/react/components/password_reset.jsx
index b2edea620..399d3b7b9 100644
--- a/web/react/components/password_reset.jsx
+++ b/web/react/components/password_reset.jsx
@@ -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") {
- return (
- <SendResetPasswordLink
- teamDisplayName={this.props.teamDisplayName}
- teamName={this.props.teamName}
- />
- );
- } else {
+ render() {
+ if (this.props.isReset === 'false') {
return (
- <ResetPassword
+ <PasswordResetSendLink
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
+};
diff --git a/web/react/components/password_reset_form.jsx b/web/react/components/password_reset_form.jsx
new file mode 100644
index 000000000..3daf45ca3
--- /dev/null
+++ b/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
+};
diff --git a/web/react/components/password_reset_send_link.jsx b/web/react/components/password_reset_send_link.jsx
new file mode 100644
index 000000000..9c5401b59
--- /dev/null
+++ b/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
+};
diff --git a/web/react/components/post_deleted_modal.jsx b/web/react/components/post_deleted_modal.jsx
index 83b007bad..d284a9d1b 100644
--- a/web/react/components/post_deleted_modal.jsx
+++ b/web/react/components/post_deleted_modal.jsx
@@ -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">&times;</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
+ 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'>&times;</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-footer">
- <button type="button" className="btn btn-primary" data-dismiss="modal">Okay</button>
- </div>
- </div>
- </div>
+ </div>
</div>
);
- } else {
- return <div/>;
}
+
+ return <div/>;
}
-});
+}
diff --git a/web/react/components/rhs_comment.jsx b/web/react/components/rhs_comment.jsx
index 7df2fed9e..e74ab7f13 100644
--- a/web/react/components/rhs_comment.jsx
+++ b/web/react/components/rhs_comment.jsx
@@ -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'>
diff --git a/web/react/components/sidebar_header.jsx b/web/react/components/sidebar_header.jsx
index af65b7e1d..6e219cc6c 100644
--- a/web/react/components/sidebar_header.jsx
+++ b/web/react/components/sidebar_header.jsx
@@ -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()};
-}
-
-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>);
- }
+ this.toggleDropdown = this.toggleDropdown.bind(this);
- 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
+};
diff --git a/web/react/components/sidebar_right.jsx b/web/react/components/sidebar_right.jsx
index df75e3adf..9aeda6626 100644
--- a/web/react/components/sidebar_right.jsx
+++ b/web/react/components/sidebar_right.jsx
@@ -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>
);
}
-});
+}
diff --git a/web/react/components/signup_team_complete.jsx b/web/react/components/signup_team_complete.jsx
index 756aae638..1d45548da 100644
--- a/web/react/components/signup_team_complete.jsx
+++ b/web/react/components/signup_team_complete.jsx
@@ -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
+};
diff --git a/web/react/components/signup_user_complete.jsx b/web/react/components/signup_user_complete.jsx
index 2080cc191..c19cac95d 100644
--- a/web/react/components/signup_user_complete.jsx
+++ b/web/react/components/signup_user_complete.jsx
@@ -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
+};
diff --git a/web/react/components/team_signup_send_invites_page.jsx b/web/react/components/team_signup_send_invites_page.jsx
index 646a742ba..6d9b0ec03 100644
--- a/web/react/components/team_signup_send_invites_page.jsx
+++ b/web/react/components/team_signup_send_invites_page.jsx
@@ -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
diff --git a/web/react/components/team_signup_username_page.jsx b/web/react/components/team_signup_username_page.jsx
index 56882e6a1..40eb3558e 100644
--- a/web/react/components/team_signup_username_page.jsx
+++ b/web/react/components/team_signup_username_page.jsx
@@ -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
+};
diff --git a/web/react/components/team_signup_welcome_page.jsx b/web/react/components/team_signup_welcome_page.jsx
index f0c680bd8..f90fe2a2e 100644
--- a/web/react/components/team_signup_welcome_page.jsx
+++ b/web/react/components/team_signup_welcome_page.jsx
@@ -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
+};
diff --git a/web/react/components/user_settings_modal.jsx b/web/react/components/user_settings_modal.jsx
index f5a555951..7ec75e000 100644
--- a/web/react/components/user_settings_modal.jsx
+++ b/web/react/components/user_settings_modal.jsx
@@ -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">&times;</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'>&times;</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>
);
}
-});
+}
diff --git a/web/react/components/user_settings_notifications.jsx b/web/react/components/user_settings_notifications.jsx
index ba0bda78e..a6cbe533e 100644
--- a/web/react/components/user_settings_notifications.jsx
+++ b/web/react/components/user_settings_notifications.jsx
@@ -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
diff --git a/web/react/dispatcher/app_dispatcher.jsx b/web/react/dispatcher/app_dispatcher.jsx
index 4ae28e8eb..04e026f46 100644
--- a/web/react/dispatcher/app_dispatcher.jsx
+++ b/web/react/dispatcher/app_dispatcher.jsx
@@ -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;