);
}
-});
+}
+
+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 114dc183f7..72a2a6251a 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 =
;
+ if (this.props.id === 'allmention' || this.props.id === 'channelmention') {
+ icon =
-
{icon}
-
@{this.props.username}{this.props.secondary_text}
+
+
{icon}
+
@{this.props.username}{this.props.secondary_text}
);
}
-});
+}
+
+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 5fc88a61b4..bce305853a 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 (
{inner}
);
- } else {
- return
}
+
+ return
;
}
-});
+}
+
+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 0000000000..7ffaeb7129
--- /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 = (
+
+ Invite New Member
+
+ );
+
+ if (this.props.teamType === 'O') {
+ teamLink = (
+
+
+ Get Team Invite Link
+
+
+ );
+ }
+ }
+
+ if (isAdmin) {
+ manageLink = (
+
+ Manage Team
+
+ );
+ teamSettings = (
+
+ Team Settings
+
+ );
+ }
+
+ var teams = [];
+
+ teams.push(
+ );
+ 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(
Switch to {teamName});
+ }
+ });
+ }
+ teams.push(
+
+ Create a New Team
+
+ );
+
+ return (
+
+ );
+ }
+}
+
+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 ebc49882b5..0b7c41b621 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
{this.state.count};
}
return null;
}
-});
+}
diff --git a/web/react/components/password_reset.jsx b/web/react/components/password_reset.jsx
index b2edea6208..399d3b7b93 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:
A password reset link has been sent to {email} for your {this.props.teamDisplayName} team on {window.location.hostname}.
, 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 ?
{this.state.update_text}{this.state.more_update_text}
: null;
- var error = this.state.error ?
: null;
-
- return (
-
-
-
Password Reset
- { update_text }
-
-
-
- );
+ 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 ?
: null;
- var error = this.state.error ?
: null;
-
- return (
-
- );
- }
-});
-
-module.exports = React.createClass({
- getInitialState: function() {
- return {};
- },
- render: function() {
-
- if (this.props.isReset === "false") {
+ render() {
+ if (this.props.isReset === 'false') {
return (
-
);
- } else {
- return (
-
- );
}
+
+ return (
+
+ );
}
-});
+}
+
+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 0000000000..3daf45ca30
--- /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 =
;
+ }
+
+ var error = null;
+ if (this.state.error) {
+ error =
;
+ }
+
+ var formClass = 'form-group';
+ if (error) {
+ formClass += ' has-error';
+ }
+
+ return (
+
+ );
+ }
+}
+
+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 0000000000..9c5401b599
--- /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:
A password reset link has been sent to {email} for your {this.props.teamDisplayName} team on {window.location.hostname}.
, 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 =
{this.state.updateText}{this.state.moreUpdateText}
;
+ }
+
+ var error = null;
+ if (this.state.error) {
+ error =
;
+ }
+
+ var formClass = 'form-group';
+ if (error) {
+ formClass += ' has-error';
+ }
+
+ return (
+
+
+
Password Reset
+ {updateText}
+
+
+
+ );
+ }
+}
+
+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 83b007badc..d284a9d1b1 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 (
-
-
-
-
-
-
Comment could not be posted
+
+
+
+
+
+
+ Comment could not be posted
+
+
+
+
Someone deleted the message on which you tried to post a comment.
+
+
+
+
-
-
Someone deleted the message on which you tried to post a comment.
-
-
-
-
-
-
+
);
- } else {
- return
;
}
+
+ return
;
}
-});
+}
diff --git a/web/react/components/rhs_comment.jsx b/web/react/components/rhs_comment.jsx
index 7df2fed9eb..e74ab7f138 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 {
diff --git a/web/react/components/sidebar_header.jsx b/web/react/components/sidebar_header.jsx
index af65b7e1d6..6e219cc6cf 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()};
-}
+ 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 = ( Invite New Member );
-
- if (this.props.teamType === 'O') {
- teamLink = (
-
- Get Team Invite Link
-
- );
- }
- }
-
- if (isAdmin) {
- manageLink = (
Manage Team );
- teamSettings = (
Team Settings );
- }
-
- var teams = [];
-
- teams.push(
);
- 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(
Switch to {teamName});
- }
- });
- }
- teams.push(
Create a New Team);
-
- return (
-
- );
+ 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 = (

);
+ profilePicture = (

);
}
return (
);
}
-});
+}
+
+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 df75e3adf6..9aeda6626a 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('');
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 =
;
- }
- else if (this.state.post_right_visible) {
- content =
;
+ } else if (this.state.post_right_visible) {
+ content = (
);
}
return (
-
- { content }
+
+ {content}
);
}
-});
+}
diff --git a/web/react/components/signup_team_complete.jsx b/web/react/components/signup_team_complete.jsx
index 756aae638b..1d45548dad 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
;
+ return (
);
}
if (this.state.wizard === 'team_display_name') {
- return
;
+ return (
);
}
if (this.state.wizard === 'team_url') {
- return
;
+ return (
);
}
if (this.state.wizard === 'allowed_domains') {
- return
;
+ return (
);
}
if (this.state.wizard === 'send_invites') {
- return
;
+ return (
);
}
if (this.state.wizard === 'username') {
- return
;
+ return (
);
}
if (this.state.wizard === 'password') {
- return
;
+ return (
);
}
return (
You've already completed the signup process for this invitation or this invitation has expired.
);
}
-});
+}
+
+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 2080cc1913..c19cac95d7 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 =
Your email address is {this.state.user.email}. You'll use this address to sign in to {config.SiteName}.;
}
- var emailContainerStyle = "margin--extra";
+ var emailContainerStyle = 'margin--extra';
if (this.state.original_email) {
- emailContainerStyle = "hidden";
+ emailContainerStyle = 'hidden';
}
var email = (
@@ -155,7 +167,10 @@ module.exports = React.createClass({
var signupMessage = [];
if (authServices.indexOf(Constants.GITLAB_SERVICE) >= 0) {
signupMessage.push(
-
+
with GitLab
@@ -172,7 +187,13 @@ module.exports = React.createClass({
Choose your username
@@ -180,12 +201,26 @@ module.exports = React.createClass({
-
+
+
+
);
}
@@ -209,7 +244,10 @@ module.exports = React.createClass({
return (
);
}
-});
-
+}
+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 646a742ba8..6d9b0ec03d 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'
/>
-
{'Invite ' + utils.toTitleCase(strings.Team) + ' Members'}
+
{'Invite ' + Utils.toTitleCase(strings.Team) + ' Members'}
{content}
-
+
);
}
-});
+}
+
+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 f0c680bd87..f90fe2a2e4 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 (
-
+
Welcome to:
{config.SiteName}
@@ -121,7 +126,14 @@ module.exports = React.createClass({
You can add other administrators later.
-
+
{storageError}
@@ -129,16 +141,42 @@ module.exports = React.createClass({
{serverError}
-
+
-
Use a different email
+
+ Use a different email
+
);
}
-});
+}
+
+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 f5a5559514..7ec75e0005 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 (
-
-
-
-
-
-
Account Settings
+
+
+
+
+
+
+ Account Settings
+
-
-
-
+
+
+
-
+
);
}
-});
+}
diff --git a/web/react/components/user_settings_notifications.jsx b/web/react/components/user_settings_notifications.jsx
index ba0bda78e9..a6cbe533ed 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(
-