summaryrefslogtreecommitdiffstats
path: root/web/react
diff options
context:
space:
mode:
author=Corey Hulen <corey@hulen.com>2015-09-01 17:06:31 -0700
committer=Corey Hulen <corey@hulen.com>2015-09-01 17:06:31 -0700
commitf578bb1e48ec4d97bca92c7faf0dd8ed5aeceb39 (patch)
tree8b4f68e847984949b8362a30d40f13db2c4bcd52 /web/react
parent72575ac7bdd5bfe7bd544ba238f8d1c0126635aa (diff)
downloadchat-f578bb1e48ec4d97bca92c7faf0dd8ed5aeceb39.tar.gz
chat-f578bb1e48ec4d97bca92c7faf0dd8ed5aeceb39.tar.bz2
chat-f578bb1e48ec4d97bca92c7faf0dd8ed5aeceb39.zip
MM-2065 style refactoring
Diffstat (limited to 'web/react')
-rw-r--r--web/react/components/channel_info_modal.jsx97
-rw-r--r--web/react/components/channel_invite_modal.jsx38
-rw-r--r--web/react/components/command_list.jsx97
-rw-r--r--web/react/components/file_upload.jsx102
-rw-r--r--web/react/components/find_team.jsx64
-rw-r--r--web/react/components/invite_member_modal.jsx188
-rw-r--r--web/react/components/member_list.jsx33
-rw-r--r--web/react/components/more_direct_channels.jsx60
-rw-r--r--web/react/components/msg_typing.jsx85
-rw-r--r--web/react/components/post_list.jsx25
-rw-r--r--web/react/components/removed_from_channel_modal.jsx129
-rw-r--r--web/react/components/rhs_thread.jsx17
-rw-r--r--web/react/components/setting_picture.jsx84
-rw-r--r--web/react/components/setting_upload.jsx64
-rw-r--r--web/react/components/sidebar_right_menu.jsx76
-rw-r--r--web/react/components/team_import_tab.jsx83
-rw-r--r--web/react/components/team_members.jsx140
-rw-r--r--web/react/components/user_settings.jsx76
18 files changed, 1001 insertions, 457 deletions
diff --git a/web/react/components/channel_info_modal.jsx b/web/react/components/channel_info_modal.jsx
index 6d999870a..b658dbe6e 100644
--- a/web/react/components/channel_info_modal.jsx
+++ b/web/react/components/channel_info_modal.jsx
@@ -3,57 +3,86 @@
var ChannelStore = require('../stores/channel_store.jsx');
-module.exports = React.createClass({
- componentDidMount: function() {
+export default class CommandList extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ channel_id: ChannelStore.getCurrentId()
+ };
+ }
+
+ componentDidMount() {
var self = this;
- if(this.refs.modal) {
- $(this.refs.modal.getDOMNode()).on('show.bs.modal', function(e) {
- var button = e.relatedTarget;
- self.setState({ channel_id: $(button).attr('data-channelid') });
- });
+ if (this.refs.modal) {
+ $(this.refs.modal.getDOMNode()).on('show.bs.modal', function show(e) {
+ var button = e.relatedTarget;
+ self.setState({channel_id: $(button).attr('data-channelid')});
+ });
}
- },
- getInitialState: function() {
- return { channel_id: ChannelStore.getCurrentId() };
- },
- render: function() {
+ }
+
+ render() {
var channel = ChannelStore.get(this.state.channel_id);
if (!channel) {
channel = {};
- channel.display_name = "No Channel Found";
- channel.name = "No Channel Found";
- channel.id = "No Channel Found";
+ channel.display_name = 'No Channel Found';
+ channel.name = 'No Channel Found';
+ channel.id = 'No Channel Found';
}
return (
- <div className="modal fade" ref="modal" id="channel_info" 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"><span className="name">{channel.display_name}</span></h4>
+ <div
+ className='modal fade'
+ ref='modal'
+ id='channel_info'
+ 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'
+ >
+ <span className='name'>{channel.display_name}</span>
+ </h4>
</div>
- <div className="modal-body">
- <div className="row form-group">
- <div className="col-sm-3 info__label">Channel Name: </div>
- <div className="col-sm-9">{channel.display_name}</div>
+ <div className='modal-body'>
+ <div className='row form-group'>
+ <div className='col-sm-3 info__label'>Channel Name: </div>
+ <div className='col-sm-9'>{channel.display_name}</div>
</div>
- <div className="row form-group">
- <div className="col-sm-3 info__label">Channel Handle:</div>
- <div className="col-sm-9">{channel.name}</div>
+ <div className='row form-group'>
+ <div className='col-sm-3 info__label'>Channel Handle:</div>
+ <div className='col-sm-9'>{channel.name}</div>
</div>
- <div className="row">
- <div className="col-sm-3 info__label">Channel ID:</div>
- <div className="col-sm-9">{channel.id}</div>
+ <div className='row'>
+ <div className='col-sm-3 info__label'>Channel ID:</div>
+ <div className='col-sm-9'>{channel.id}</div>
</div>
</div>
- <div className="modal-footer">
- <button type="button" className="btn btn-default" data-dismiss="modal">Close</button>
+ <div className='modal-footer'>
+ <button
+ type='button'
+ className='btn btn-default'
+ data-dismiss='modal'
+ >Close</button>
</div>
</div>
</div>
</div>
);
}
-});
+}
diff --git a/web/react/components/channel_invite_modal.jsx b/web/react/components/channel_invite_modal.jsx
index b70811db1..f76ede604 100644
--- a/web/react/components/channel_invite_modal.jsx
+++ b/web/react/components/channel_invite_modal.jsx
@@ -9,7 +9,6 @@ var utils = require('../utils/utils.jsx');
var client = require('../utils/client.jsx');
var AsyncClient = require('../utils/async_client.jsx');
-
export default class ChannelInviteModal extends React.Component {
constructor() {
super();
@@ -129,15 +128,37 @@ export default class ChannelInviteModal extends React.Component {
if (this.state.loading) {
content = (<LoadingScreen />);
} else {
- content = (<MemberList memberList={this.state.nonmembers} isAdmin={isAdmin} handleInvite={this.handleInvite} />);
+ content = (
+ <MemberList
+ memberList={this.state.nonmembers}
+ isAdmin={isAdmin}
+ handleInvite={this.handleInvite}
+ />
+ );
}
return (
- <div className='modal fade' id='channel_invite' tabIndex='-1' role='dialog' aria-hidden='true'>
- <div className='modal-dialog' role='document'>
+ <div
+ className='modal fade'
+ id='channel_invite'
+ tabIndex='-1'
+ role='dialog'
+ aria-hidden='true'
+ >
+ <div
+ className='modal-dialog'
+ role='document'
+ >
<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>
+ <button
+ type='button'
+ className='close'
+ data-dismiss='modal'
+ aria-label='Close'
+ >
+ <span aria-hidden='true'>&times;</span>
+ </button>
<h4 className='modal-title'>Add New Members to <span className='name'>{this.state.channelName}</span></h4>
</div>
<div className='modal-body'>
@@ -145,7 +166,11 @@ export default class ChannelInviteModal extends React.Component {
{content}
</div>
<div className='modal-footer'>
- <button type='button' className='btn btn-default' data-dismiss='modal'>Close</button>
+ <button
+ type='button'
+ className='btn btn-default'
+ data-dismiss='modal'
+ >Close</button>
</div>
</div>
</div>
@@ -153,4 +178,3 @@ export default class ChannelInviteModal extends React.Component {
);
}
}
-ChannelInviteModal.displayName = 'ChannelInviteModal';
diff --git a/web/react/components/command_list.jsx b/web/react/components/command_list.jsx
index 27264ff6e..63bd57c2a 100644
--- a/web/react/components/command_list.jsx
+++ b/web/react/components/command_list.jsx
@@ -3,25 +3,40 @@
var client = require('../utils/client.jsx');
-module.exports = React.createClass({
- getInitialState: function() {
- return { suggestions: [ ], cmd: "" };
- },
- handleClick: function(i) {
- this.props.addCommand(this.state.suggestions[i].suggestion)
- this.setState({ suggestions: [ ], cmd: "" });
- },
- addFirstCommand: function() {
- if (this.state.suggestions.length == 0) return;
+export default class CommandList extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.handleClick = this.handleClick.bind(this);
+ this.addFirstCommand = this.addFirstCommand.bind(this);
+ this.isEmpty = this.isEmpty.bind(this);
+ this.getSuggestedCommands = this.getSuggestedCommands.bind(this);
+
+ this.state = {
+ suggestions: [ ],
+ cmd: ''
+ };
+ }
+
+ handleClick(i) {
+ this.props.addCommand(this.state.suggestions[i].suggestion);
+ this.setState({suggestions: [ ], cmd: ''});
+ }
+
+ addFirstCommand() {
+ if (this.state.suggestions.length === 0) {
+ return;
+ }
this.handleClick(0);
- },
- isEmpty: function() {
- return this.state.suggestions.length == 0;
- },
- getSuggestedCommands: function(cmd) {
+ }
- if (!cmd || cmd.charAt(0) != '/') {
- this.setState({ suggestions: [ ], cmd: "" });
+ isEmpty() {
+ return this.state.suggestions.length === 0;
+ }
+
+ getSuggestedCommands(cmd) {
+ if (!cmd || cmd.charAt(0) !== '/') {
+ this.setState({suggestions: [ ], cmd: ''});
return;
}
@@ -29,36 +44,56 @@ module.exports = React.createClass({
this.props.channelId,
cmd,
true,
- function(data) {
+ function success(data) {
if (data.suggestions.length === 1 && data.suggestions[0].suggestion === cmd) {
data.suggestions = [];
}
- this.setState({ suggestions: data.suggestions, cmd: cmd });
+ this.setState({suggestions: data.suggestions, cmd: cmd});
}.bind(this),
- function(err){
- }
+ function fail() {
+ }
);
- },
- render: function() {
- if (this.state.suggestions.length == 0) return (<div/>);
+ }
+
+ render() {
+ if (this.state.suggestions.length === 0) {
+ return (<div/>);
+ }
var suggestions = [];
for (var i = 0; i < this.state.suggestions.length; i++) {
- if (this.state.suggestions[i].suggestion != this.state.cmd) {
+ if (this.state.suggestions[i].suggestion !== this.state.cmd) {
suggestions.push(
- <div key={i} className="command-name" onClick={this.handleClick.bind(this, i)}>
- <div className="command__title"><strong>{ this.state.suggestions[i].suggestion }</strong></div>
- <div className="command__desc">{ this.state.suggestions[i].description }</div>
+ <div
+ key={i}
+ className='command-name'
+ onClick={this.handleClick.bind(this, i)}
+ >
+ <div className='command__title'><strong>{this.state.suggestions[i].suggestion}</strong></div>
+ <div className='command__desc'>{this.state.suggestions[i].description}</div>
</div>
);
}
}
return (
- <div ref="mentionlist" className="command-box" style={{height:(this.state.suggestions.length*56)+2}}>
- { suggestions }
+ <div
+ ref='mentionlist'
+ className='command-box'
+ style={{height: (this.state.suggestions.length * 56) + 2}}
+ >
+ {suggestions}
</div>
);
}
-});
+}
+
+CommandList.defaultProps = {
+ channelId: null
+};
+
+CommandList.propTypes = {
+ addCommand: React.PropTypes.func,
+ channelId: React.PropTypes.string
+}; \ No newline at end of file
diff --git a/web/react/components/file_upload.jsx b/web/react/components/file_upload.jsx
index e77982559..460d91cc8 100644
--- a/web/react/components/file_upload.jsx
+++ b/web/react/components/file_upload.jsx
@@ -6,20 +6,19 @@ var Constants = require('../utils/constants.jsx');
var ChannelStore = require('../stores/channel_store.jsx');
var utils = require('../utils/utils.jsx');
-module.exports = React.createClass({
- displayName: 'FileUpload',
- propTypes: {
- onUploadError: React.PropTypes.func,
- getFileCount: React.PropTypes.func,
- onFileUpload: React.PropTypes.func,
- onUploadStart: React.PropTypes.func,
- channelId: React.PropTypes.string,
- postType: React.PropTypes.string
- },
- getInitialState: function() {
- return {requests: {}};
- },
- handleChange: function() {
+export default class FileUpload extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.handleChange = this.handleChange.bind(this);
+ this.handleDrop = this.handleDrop.bind(this);
+
+ this.state = {
+ requests: {}
+ };
+ }
+
+ handleChange() {
var element = $(this.refs.fileInput.getDOMNode());
var files = element.prop('files');
@@ -30,7 +29,7 @@ module.exports = React.createClass({
// This looks redundant, but must be done this way due to
// setState being an asynchronous call
var numFiles = 0;
- for (var i = 0; i < files.length; i++) {
+ for (let i = 0; i < files.length; i++) {
if (files[i].size <= Constants.MAX_FILE_SIZE) {
numFiles++;
}
@@ -42,7 +41,7 @@ module.exports = React.createClass({
this.props.onUploadError('Uploads limited to ' + Constants.MAX_UPLOAD_FILES + ' files maximum. Please use additional posts for more files.');
}
- for (var i = 0; i < files.length && i < numToUpload; i++) {
+ for (let i = 0; i < files.length && i < numToUpload; i++) {
if (files[i].size > Constants.MAX_FILE_SIZE) {
this.props.onUploadError('Files must be no more than ' + Constants.MAX_FILE_SIZE / 1000000 + ' MB');
continue;
@@ -58,7 +57,7 @@ module.exports = React.createClass({
formData.append('client_ids', clientId);
var request = client.uploadFile(formData,
- function(data) {
+ function success(data) {
var parsedData = $.parseJSON(data);
this.props.onFileUpload(parsedData.filenames, parsedData.client_ids, channelId);
@@ -68,7 +67,7 @@ module.exports = React.createClass({
}
this.setState({requests: requests});
}.bind(this),
- function(err) {
+ function fail(err) {
this.props.onUploadError(err, clientId);
}.bind(this)
);
@@ -87,9 +86,12 @@ module.exports = React.createClass({
element[0].type = 'text';
element[0].type = 'file';
}
- } catch(e) {}
- },
- handleDrop: function(e) {
+ } catch(e) {
+ // Do nothing
+ }
+ }
+
+ handleDrop(e) {
this.props.onUploadError(null);
var files = e.originalEvent.dataTransfer.files;
@@ -120,7 +122,7 @@ module.exports = React.createClass({
formData.append('client_ids', clientId);
var request = client.uploadFile(formData,
- function(data) {
+ function success(data) {
var parsedData = $.parseJSON(data);
this.props.onFileUpload(parsedData.filenames, parsedData.client_ids, channelId);
@@ -130,7 +132,7 @@ module.exports = React.createClass({
}
this.setState({requests: requests});
}.bind(this),
- function(err) {
+ function fail(err) {
this.props.onUploadError(err, clientId);
}.bind(this)
);
@@ -144,40 +146,41 @@ module.exports = React.createClass({
} else {
this.props.onUploadError('Invalid file upload', -1);
}
- },
- componentDidMount: function() {
+ }
+
+ componentDidMount() {
var inputDiv = this.refs.input.getDOMNode();
var self = this;
if (this.props.postType === 'post') {
$('.row.main').dragster({
- enter: function() {
+ enter() {
$('.center-file-overlay').removeClass('hidden');
},
- leave: function() {
+ leave() {
$('.center-file-overlay').addClass('hidden');
},
- drop: function(dragsterEvent, e) {
+ drop(dragsterEvent, e) {
$('.center-file-overlay').addClass('hidden');
self.handleDrop(e);
}
});
} else if (this.props.postType === 'comment') {
$('.post-right__container').dragster({
- enter: function() {
+ enter() {
$('.right-file-overlay').removeClass('hidden');
},
- leave: function() {
+ leave() {
$('.right-file-overlay').addClass('hidden');
},
- drop: function(dragsterEvent, e) {
+ drop(dragsterEvent, e) {
$('.right-file-overlay').addClass('hidden');
self.handleDrop(e);
}
});
}
- document.addEventListener('paste', function(e) {
+ document.addEventListener('paste', function handlePaste(e) {
var textarea = $(inputDiv.parentNode.parentNode).find('.custom-textarea')[0];
if (textarea !== e.target && !$.contains(textarea, e.target)) {
@@ -191,7 +194,7 @@ module.exports = React.createClass({
var items = e.clipboardData.items;
var numItems = 0;
if (items) {
- for (var i = 0; i < items.length; i++) {
+ for (let i = 0; i < items.length; i++) {
if (items[i].type.indexOf('image') !== -1) {
var testExt = items[i].type.split('/')[1].toLowerCase();
@@ -269,8 +272,9 @@ module.exports = React.createClass({
}
}
});
- },
- cancelUpload: function(clientId) {
+ }
+
+ cancelUpload(clientId) {
var requests = this.state.requests;
var request = requests[clientId];
@@ -280,15 +284,33 @@ module.exports = React.createClass({
delete requests[clientId];
this.setState({requests: requests});
}
- },
- render: function() {
+ }
+
+ render() {
return (
- <span ref='input' className='btn btn-file'>
+ <span
+ ref='input'
+ className='btn btn-file'
+ >
<span>
<i className='glyphicon glyphicon-paperclip' />
</span>
- <input ref='fileInput' type='file' onChange={this.handleChange} multiple/>
+ <input
+ ref='fileInput'
+ type='file'
+ onChange={this.handleChange}
+ multiple='true'
+ />
</span>
);
}
-});
+}
+
+FileUpload.propTypes = {
+ onUploadError: React.PropTypes.func,
+ getFileCount: React.PropTypes.func,
+ onFileUpload: React.PropTypes.func,
+ onUploadStart: React.PropTypes.func,
+ channelId: React.PropTypes.string,
+ postType: React.PropTypes.string
+};
diff --git a/web/react/components/find_team.jsx b/web/react/components/find_team.jsx
index d896a1f12..b70c98d47 100644
--- a/web/react/components/find_team.jsx
+++ b/web/react/components/find_team.jsx
@@ -1,53 +1,57 @@
// 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');
-module.exports = React.createClass({
- handleSubmit: function(e) {
+export default class FindTeam extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {};
+
+ this.handleSubmit = this.handleSubmit.bind(this);
+ }
+
+ handleSubmit(e) {
e.preventDefault();
var state = { };
var email = this.refs.email.getDOMNode().value.trim().toLowerCase();
if (!email || !utils.isEmail(email)) {
- state.email_error = "Please enter a valid email address";
+ state.email_error = 'Please enter a valid email address';
this.setState(state);
return;
}
- else {
- state.email_error = "";
- }
+
+ state.email_error = '';
client.findTeamsSendEmail(email,
- function(data) {
+ function success() {
state.sent = true;
this.setState(state);
}.bind(this),
- function(err) {
+ function fail(err) {
state.email_error = err.message;
this.setState(state);
}.bind(this)
);
- },
- getInitialState: function() {
- return { };
- },
- render: function() {
+ }
- var email_error = this.state.email_error ? <label className='control-label'>{ this.state.email_error }</label> : null;
+ render() {
+ var emailError = null;
+ var emailErrorClass = 'form-group';
- var divStyle = {
- "marginTop": "50px",
+ if (this.state.email_error) {
+ emailError = <label className='control-label'>{this.state.email_error}</label>;
+ emailErrorClass = 'form-group has-error';
}
if (this.state.sent) {
return (
<div>
- <h4>{"Find Your " + utils.toTitleCase(strings.Team)}</h4>
- <p>{"An email was sent with links to any " + strings.TeamPlural + " to which you are a member."}</p>
+ <h4>{'Find Your ' + utils.toTitleCase(strings.Team)}</h4>
+ <p>{'An email was sent with links to any ' + strings.TeamPlural + ' to which you are a member.'}</p>
</div>
);
}
@@ -56,17 +60,25 @@ module.exports = React.createClass({
<div>
<h4>Find Your Team</h4>
<form onSubmit={this.handleSubmit}>
- <p>{"Get an email with links to any " + strings.TeamPlural + " to which you are a member."}</p>
- <div className="form-group">
+ <p>{'Get an email with links to any ' + strings.TeamPlural + ' to which you are a member.'}</p>
+ <div className='form-group'>
<label className='control-label'>Email</label>
- <div className={ email_error ? "form-group has-error" : "form-group" }>
- <input type="text" ref="email" className="form-control" placeholder="you@domain.com" maxLength="128" />
- { email_error }
+ <div className={emailErrorClass}>
+ <input
+ type='text'
+ ref='email'
+ className='form-control'
+ placeholder='you@domain.com'
+ maxLength='128'
+ />
+ {emailError}
</div>
</div>
- <button className="btn btn-md btn-primary" type="submit">Send</button>
+ <button
+ className='btn btn-md btn-primary'
+ type='submit'>Send</button>
</form>
</div>
);
}
-});
+}
diff --git a/web/react/components/invite_member_modal.jsx b/web/react/components/invite_member_modal.jsx
index 5b6924891..3440232f1 100644
--- a/web/react/components/invite_member_modal.jsx
+++ b/web/react/components/invite_member_modal.jsx
@@ -7,10 +7,28 @@ var Client = require('../utils/client.jsx');
var UserStore = require('../stores/user_store.jsx');
var ConfirmModal = require('./confirm_modal.jsx');
-module.exports = React.createClass({
- componentDidMount: function() {
+export default class InviteMemberModal extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.handleSubmit = this.handleSubmit.bind(this);
+ this.addInviteFields = this.addInviteFields.bind(this);
+ this.clearFields = this.clearFields.bind(this);
+ this.removeInviteFields = this.removeInviteFields.bind(this);
+
+ this.state = {
+ inviteIds: [0],
+ idCount: 0,
+ emailErrors: {},
+ firstNameErrors: {},
+ lastNameErrors: {},
+ emailEnabled: !ConfigStore.getSettingAsBoolean('ByPassEmail', false)
+ };
+ }
+
+ componentDidMount() {
var self = this;
- $('#invite_member').on('hide.bs.modal', function(e) {
+ $('#invite_member').on('hide.bs.modal', function hide(e) {
if ($('#invite_member').attr('data-confirm') === 'true') {
$('#invite_member').attr('data-confirm', 'false');
return;
@@ -31,11 +49,12 @@ module.exports = React.createClass({
}
});
- $('#invite_member').on('hidden.bs.modal', function() {
+ $('#invite_member').on('hidden.bs.modal', function show() {
self.clearFields();
});
- },
- handleSubmit: function(e) {
+ }
+
+ handleSubmit() {
if (!this.state.emailEnabled) {
return;
}
@@ -90,11 +109,11 @@ module.exports = React.createClass({
data.invites = invites;
Client.inviteMembers(data,
- function() {
+ function success() {
$(this.refs.modal.getDOMNode()).attr('data-confirm', 'true');
$(this.refs.modal.getDOMNode()).modal('hide');
}.bind(this),
- function(err) {
+ function fail(err) {
if (err.message === 'This person is already on your team') {
emailErrors[err.detailed_error] = err.message;
this.setState({emailErrors: emailErrors});
@@ -103,18 +122,21 @@ module.exports = React.createClass({
}
}.bind(this)
);
- },
- componentDidUpdate: function() {
+ }
+
+ componentDidUpdate() {
$(this.refs.modalBody.getDOMNode()).css('max-height', $(window).height() - 200);
$(this.refs.modalBody.getDOMNode()).css('overflow-y', 'scroll');
- },
- addInviteFields: function() {
+ }
+
+ addInviteFields() {
var count = this.state.idCount + 1;
var inviteIds = this.state.inviteIds;
inviteIds.push(count);
this.setState({inviteIds: inviteIds, idCount: count});
- },
- clearFields: function() {
+ }
+
+ clearFields() {
var inviteIds = this.state.inviteIds;
for (var i = 0; i < inviteIds.length; i++) {
@@ -133,8 +155,9 @@ module.exports = React.createClass({
firstNameErrors: {},
lastNameErrors: {}
});
- },
- removeInviteFields: function(index) {
+ }
+
+ removeInviteFields(index) {
var count = this.state.idCount;
var inviteIds = this.state.inviteIds;
var i = inviteIds.indexOf(index);
@@ -145,24 +168,10 @@ module.exports = React.createClass({
inviteIds.push(++count);
}
this.setState({inviteIds: inviteIds, idCount: count});
- },
- getInitialState: function() {
- return {
- inviteIds: [0],
- idCount: 0,
- emailErrors: {},
- firstNameErrors: {},
- lastNameErrors: {},
- emailEnabled: !ConfigStore.getSettingAsBoolean('ByPassEmail', false)
- };
- },
- render: function() {
- var currentUser = UserStore.getCurrentUser();
+ }
- var inputDisabled = '';
- if (!this.state.emailEnabled) {
- inputDisabled = 'disabled';
- }
+ render() {
+ var currentUser = UserStore.getCurrentUser();
if (currentUser != null) {
var inviteSections = [];
@@ -185,7 +194,13 @@ module.exports = React.createClass({
var removeButton = null;
if (index) {
removeButton = (<div>
- <button type='button' className='btn btn-link remove__member' onClick={this.removeInviteFields.bind(this, index)}><span className='fa fa-trash'></span></button>
+ <button
+ type='button'
+ className='btn btn-link remove__member'
+ onClick={this.removeInviteFields.bind(this, index)}
+ >
+ <span className='fa fa-trash'></span>
+ </button>
</div>);
}
var emailClass = 'form-group invite';
@@ -206,13 +221,27 @@ module.exports = React.createClass({
nameFields = (<div className='row--invite'>
<div className='col-sm-6'>
<div className={firstNameClass}>
- <input type='text' className='form-control' ref={'first_name' + index} placeholder='First name' maxLength='64' disabled={!this.state.emailEnabled}/>
+ <input
+ type='text'
+ className='form-control'
+ ref={'first_name' + index}
+ placeholder='First name'
+ maxLength='64'
+ disabled={!this.state.emailEnabled}
+ />
{firstNameError}
</div>
</div>
<div className='col-sm-6'>
<div className={lastNameClass}>
- <input type='text' className='form-control' ref={'last_name' + index} placeholder='Last name' maxLength='64' disabled={!this.state.emailEnabled}/>
+ <input
+ type='text'
+ className='form-control'
+ ref={'last_name' + index}
+ placeholder='Last name'
+ maxLength='64'
+ disabled={!this.state.emailEnabled}
+ />
{lastNameError}
</div>
</div>
@@ -223,7 +252,15 @@ module.exports = React.createClass({
<div key={'key' + index}>
{removeButton}
<div className={emailClass}>
- <input onKeyUp={this.displayNameKeyUp} type='text' ref={'email' + index} className='form-control' placeholder='email@domain.com' maxLength='64' disabled={!this.state.emailEnabled}/>
+ <input
+ onKeyUp={this.displayNameKeyUp}
+ type='text'
+ ref={'email' + index}
+ className='form-control'
+ placeholder='email@domain.com'
+ maxLength='64'
+ disabled={!this.state.emailEnabled}
+ />
{emailError}
</div>
{nameFields}
@@ -242,23 +279,44 @@ module.exports = React.createClass({
content = (
<div>
{serverError}
- <button type='button' className='btn btn-default' onClick={this.addInviteFields}>Add another</button>
+ <button
+ type='button'
+ className='btn btn-default'
+ onClick={this.addInviteFields}
+ >Add another</button>
<br/>
<br/>
<span>People invited automatically join Town Square channel.</span>
</div>
);
- sendButton = <button onClick={this.handleSubmit} type='button' className='btn btn-primary'>Send Invitations</button>
+ sendButton =
+ (
+ <button
+ onClick={this.handleSubmit}
+ type='button'
+ className='btn btn-primary'
+ >Send Invitations</button>
+ );
} else {
var teamInviteLink = null;
if (currentUser && this.props.teamType === 'O') {
var linkUrl = utils.getWindowLocationOrigin() + '/signup_user_complete/?id=' + currentUser.team_id;
- var link = <a href='#' data-toggle='modal' data-target='#get_link' data-title='Team Invite' data-value={linkUrl} onClick={
- function() {
- $('#invite_member').modal('hide');
- }
- }>Team Invite Link</a>;
+ var link =
+ (
+ <a
+ href='#'
+ data-toggle='modal'
+ data-target='#get_link'
+ data-title='Team Invite'
+ data-value={linkUrl}
+ onClick={
+ function click() {
+ $('#invite_member').modal('hide');
+ }
+ }
+ >Team Invite Link</a>
+ );
teamInviteLink = (
<p>
@@ -277,22 +335,46 @@ module.exports = React.createClass({
return (
<div>
- <div className='modal fade' ref='modal' id='invite_member' tabIndex='-1' role='dialog' aria-hidden='true'>
+ <div
+ className='modal fade'
+ ref='modal'
+ id='invite_member'
+ 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' data-reactid='.5.0.0.0.0'><span aria-hidden='true' data-reactid='.5.0.0.0.0.0'>×</span></button>
- <h4 className='modal-title' id='myModalLabel'>Invite New Member</h4>
+ <button
+ type='button'
+ className='close'
+ data-dismiss='modal'
+ aria-label='Close'
+ >
+ <span aria-hidden='true'>×</span>
+ </button>
+ <h4
+ className='modal-title'
+ id='myModalLabel'
+ >Invite New Member</h4>
</div>
- <div ref='modalBody' className='modal-body'>
+ <div
+ ref='modalBody'
+ className='modal-body'
+ >
<form role='form'>
{inviteSections}
</form>
{content}
</div>
<div className='modal-footer'>
- <button type='button' className='btn btn-default' data-dismiss='modal'>Cancel</button>
- {sendButton}
+ <button
+ type='button'
+ className='btn btn-default'
+ data-dismiss='modal'
+ >Cancel</button>
+ {sendButton}
</div>
</div>
</div>
@@ -309,4 +391,8 @@ module.exports = React.createClass({
}
return <div/>;
}
-});
+}
+
+InviteMemberModal.propTypes = {
+ teamType: React.PropTypes.string
+};
diff --git a/web/react/components/member_list.jsx b/web/react/components/member_list.jsx
index 69da5cfc3..f8b07e05b 100644
--- a/web/react/components/member_list.jsx
+++ b/web/react/components/member_list.jsx
@@ -3,32 +3,45 @@
var MemberListItem = require('./member_list_item.jsx');
-module.exports = React.createClass({
- render: function() {
+export default class MemberList extends React.Component {
+ constructor(props) {
+ super(props);
+ }
+
+ render() {
var members = [];
- if (this.props.memberList != null) {
+ if (this.props.memberList !== null) {
members = this.props.memberList;
}
- var message = "";
- if (members.length === 0)
+ var message = '';
+ if (members.length === 0) {
message = <span>No users to add.</span>;
+ }
return (
- <div className="member-list-holder">
- {members.map(function(member) {
- return <MemberListItem
+ <div className='member-list-holder'>
+ {members.map(function mymembers(member) {
+ return (<MemberListItem
key={member.id}
member={member}
isAdmin={this.props.isAdmin}
handleInvite={this.props.handleInvite}
handleRemove={this.props.handleRemove}
handleMakeAdmin={this.props.handleMakeAdmin}
- />;
+ />);
}, this)}
{message}
</div>
);
}
-});
+}
+
+MemberList.propTypes = {
+ memberList: React.PropTypes.array,
+ isAdmin: React.PropTypes.bool,
+ handleInvite: React.PropTypes.func,
+ handleRemove: React.PropTypes.func,
+ handleMakeAdmin: React.PropTypes.func
+};
diff --git a/web/react/components/more_direct_channels.jsx b/web/react/components/more_direct_channels.jsx
index 11ddbcbd1..5741f6e45 100644
--- a/web/react/components/more_direct_channels.jsx
+++ b/web/react/components/more_direct_channels.jsx
@@ -7,19 +7,22 @@ var Client = require('../utils/client.jsx');
var AsyncClient = require('../utils/async_client.jsx');
var utils = require('../utils/utils.jsx');
-module.exports = React.createClass({
- displayName: 'MoreDirectChannels',
- componentDidMount: function() {
+export default class MoreDirectChannels extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.state = {channels: [], loadingDMChannel: -1};
+ }
+
+ componentDidMount() {
var self = this;
$(this.refs.modal.getDOMNode()).on('show.bs.modal', function showModal(e) {
var button = e.relatedTarget;
self.setState({channels: $(button).data('channels')});
});
- },
- getInitialState: function() {
- return {channels: [], loadingDMChannel: -1};
- },
- render: function() {
+ }
+
+ render() {
var self = this;
var directMessageItems = this.state.channels.map(function mapActivityToChannel(channel, index) {
@@ -48,7 +51,12 @@ module.exports = React.createClass({
var otherUserId = utils.getUserIdFromChannelName(channel);
if (self.state.loadingDMChannel === index) {
- badge = <img className='channel-loading-gif pull-right' src='/static/images/load.gif'/>;
+ badge = (
+ <img
+ className='channel-loading-gif pull-right'
+ src='/static/images/load.gif'
+ />
+ );
}
if (self.state.loadingDMChannel === -1) {
@@ -73,16 +81,36 @@ module.exports = React.createClass({
}
return (
- <li key={channel.name} className={active}><a className={'sidebar-channel ' + titleClass} href='#' onClick={handleClick}>{badge}{channel.display_name}</a></li>
+ <li
+ key={channel.name}
+ className={active}
+ >
+ <a
+ className={'sidebar-channel ' + titleClass}
+ href='#'
+ onClick={handleClick}
+ >{badge}{channel.display_name}</a>
+ </li>
);
});
return (
- <div className='modal fade' id='more_direct_channels' ref='modal' tabIndex='-1' role='dialog' aria-hidden='true'>
+ <div
+ className='modal fade'
+ id='more_direct_channels'
+ ref='modal'
+ 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'>
+ <button
+ type='button'
+ className='close'
+ data-dismiss='modal'
+ >
<span aria-hidden='true'>&times;</span>
<span className='sr-only'>Close</span>
</button>
@@ -94,11 +122,15 @@ module.exports = React.createClass({
</ul>
</div>
<div className='modal-footer'>
- <button type='button' className='btn btn-default' data-dismiss='modal'>Close</button>
+ <button
+ type='button'
+ className='btn btn-default'
+ data-dismiss='modal'
+ >Close</button>
</div>
</div>
</div>
</div>
);
}
-});
+}
diff --git a/web/react/components/msg_typing.jsx b/web/react/components/msg_typing.jsx
index aacb315dd..d9823c3cf 100644
--- a/web/react/components/msg_typing.jsx
+++ b/web/react/components/msg_typing.jsx
@@ -1,57 +1,70 @@
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
// See License.txt for license information.
-
var SocketStore = require('../stores/socket_store.jsx');
var UserStore = require('../stores/user_store.jsx');
-module.exports = React.createClass({
- timer: null,
- lastTime: 0,
- componentDidMount: function() {
- SocketStore.addChangeListener(this._onChange);
- },
- componentWillReceiveProps: function(newProps) {
- if(this.props.channelId !== newProps.channelId) {
- this.setState({text:""});
+export default class MsgTyping extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.timer = null;
+ this.lastTime = 0;
+
+ this.onChange = this.onChange.bind(this);
+
+ this.state = {
+ text: ''
+ };
+ }
+
+ componentDidMount() {
+ SocketStore.addChangeListener(this.onChange);
+ }
+
+ componentWillReceiveProps(newProps) {
+ if (this.props.channelId !== newProps.channelId) {
+ this.setState({text: ''});
}
- },
- componentWillUnmount: function() {
- SocketStore.removeChangeListener(this._onChange);
- },
- _onChange: function(msg) {
- if (msg.action == "typing" &&
- this.props.channelId == msg.channel_id &&
- this.props.parentId == msg.props.parent_id) {
+ }
+
+ componentWillUnmount() {
+ SocketStore.removeChangeListener(this.onChange);
+ }
+ onChange(msg) {
+ if (msg.action === 'typing' &&
+ this.props.channelId === msg.channel_id &&
+ this.props.parentId === msg.props.parent_id) {
this.lastTime = new Date().getTime();
- var username = "Someone";
+ var username = 'Someone';
if (UserStore.hasProfile(msg.user_id)) {
username = UserStore.getProfile(msg.user_id).username;
}
- this.setState({ text: username + " is typing..." });
+ this.setState({text: username + ' is typing...'});
if (!this.timer) {
- var outer = this;
- outer.timer = setInterval(function() {
- if ((new Date().getTime() - outer.lastTime) > 8000) {
- outer.setState({ text: "" });
- }
- }, 3000);
+ this.timer = setInterval(function myTimer() {
+ if ((new Date().getTime() - this.lastTime) > 8000) {
+ this.setState({text: ''});
+ }
+ }.bind(this), 3000);
}
+ } else if (msg.action === 'posted' && msg.channel_id === this.props.channelId) {
+ this.setState({text: ''});
}
- else if (msg.action == "posted" && msg.channel_id === this.props.channelId) {
- this.setState({text:""})
- }
- },
- getInitialState: function() {
- return { text: "" };
- },
- render: function() {
+ }
+
+ render() {
return (
- <span className="msg-typing">{ this.state.text }</span>
+ <span className='msg-typing'>{this.state.text}</span>
);
}
-});
+}
+
+MsgTyping.propTypes = {
+ channelId: React.PropTypes.string,
+ parentId: React.PropTypes.string
+};
diff --git a/web/react/components/post_list.jsx b/web/react/components/post_list.jsx
index c1e6e490d..8587b981d 100644
--- a/web/react/components/post_list.jsx
+++ b/web/react/components/post_list.jsx
@@ -51,8 +51,10 @@ export default class PostList extends React.Component {
if (deletedPosts && Object.keys(deletedPosts).length > 0) {
for (var pid in deletedPosts) {
- postList.posts[pid] = deletedPosts[pid];
- postList.order.unshift(pid);
+ if (deletedPosts.hasOwnProperty(pid)) {
+ postList.posts[pid] = deletedPosts[pid];
+ postList.order.unshift(pid);
+ }
}
postList.order.sort(function postSort(a, b) {
@@ -71,7 +73,9 @@ export default class PostList extends React.Component {
if (pendingPostList) {
postList.order = pendingPostList.order.concat(postList.order);
for (var ppid in pendingPostList.posts) {
- postList.posts[ppid] = pendingPostList.posts[ppid];
+ if (pendingPostList.posts.hasOwnProperty(ppid)) {
+ postList.posts[ppid] = pendingPostList.posts[ppid];
+ }
}
}
}
@@ -267,7 +271,6 @@ export default class PostList extends React.Component {
}
}
onSocketChange(msg) {
- var postList;
var post;
if (msg.action === 'posted' || msg.action === 'post_edited') {
post = JSON.parse(msg.props.post);
@@ -280,7 +283,6 @@ export default class PostList extends React.Component {
}
post = JSON.parse(msg.props.post);
- postList = this.state.postList;
PostStore.storeUnseenDeletedPost(post);
PostStore.removePost(post, true);
@@ -644,11 +646,18 @@ export default class PostList extends React.Component {
if (posts && this.state.isFirstLoadComplete) {
postCtls = this.createPosts(posts, order);
} else {
- postCtls.push(<LoadingScreen position='absolute' />);
+ postCtls.push(
+ <LoadingScreen
+ position='absolute'
+ key='loading'
+ />);
}
return (
- <div ref='postlist' className='post-list-holder-by-time'>
+ <div
+ ref='postlist'
+ className='post-list-holder-by-time'
+ >
<div className='post-list__table'>
<div className='post-list__content'>
{moreMessages}
@@ -658,4 +667,4 @@ export default class PostList extends React.Component {
</div>
);
}
-}
+} \ No newline at end of file
diff --git a/web/react/components/removed_from_channel_modal.jsx b/web/react/components/removed_from_channel_modal.jsx
index 4a49e1c98..b7ec85457 100644
--- a/web/react/components/removed_from_channel_modal.jsx
+++ b/web/react/components/removed_from_channel_modal.jsx
@@ -3,62 +3,99 @@
var ChannelStore = require('../stores/channel_store.jsx');
var UserStore = require('../stores/user_store.jsx');
-var BrowserStore = require('../stores/browser_store.jsx')
+var BrowserStore = require('../stores/browser_store.jsx');
var utils = require('../utils/utils.jsx');
-module.exports = React.createClass({
- handleShow: function() {
- var newState = {};
- if(BrowserStore.getItem("channel-removed-state")) {
- newState = BrowserStore.getItem("channel-removed-state");
- BrowserStore.removeItem("channel-removed-state");
- }
+export default class RemovedFromChannelModal extends React.Component {
+ constructor(props) {
+ super(props);
- this.setState(newState);
- },
- handleClose: function() {
- var townSquare = ChannelStore.getByName("town-square");
- utils.switchChannel(townSquare);
+ this.handleShow = this.handleShow.bind(this);
+ this.handleClose = this.handleClose.bind(this);
- this.setState({channelName: "", remover: ""});
- },
- componentDidMount: function() {
- $(this.getDOMNode()).on('show.bs.modal',this.handleShow);
- $(this.getDOMNode()).on('hidden.bs.modal',this.handleClose);
- },
- componentWillUnmount: function() {
- $(this.getDOMNode()).off('show.bs.modal',this.handleShow);
- $(this.getDOMNode()).off('hidden.bs.modal',this.handleClose);
- },
- getInitialState: function() {
- return {channelName: "", remover: ""}
- },
- render: function() {
+ this.state = {
+ channelName: '',
+ remover: ''
+ };
+ }
+
+ handleShow() {
+ var newState = {};
+ if (BrowserStore.getItem('channel-removed-state')) {
+ newState = BrowserStore.getItem('channel-removed-state');
+ BrowserStore.removeItem('channel-removed-state');
+ }
+
+ this.setState(newState);
+ }
+
+ handleClose() {
+ var townSquare = ChannelStore.getByName('town-square');
+ utils.switchChannel(townSquare);
+
+ this.setState({channelName: '', remover: ''});
+ }
+
+ componentDidMount() {
+ $(React.findDOMNode(this)).on('show.bs.modal', this.handleShow);
+ $(React.findDOMNode(this)).on('hidden.bs.modal', this.handleClose);
+ }
+
+ componentWillUnmount() {
+ $(React.findDOMNode(this)).off('show.bs.modal', this.handleShow);
+ $(React.findDOMNode(this)).off('hidden.bs.modal', this.handleClose);
+ }
+
+ render() {
var currentUser = UserStore.getCurrentUser();
- var channelName = this.state.channelName ? this.state.channelName : "the channel"
- var remover = this.state.remover ? this.state.remover : "Someone"
+
+ var channelName = 'the channel';
+ if (this.state.channelName) {
+ channelName = this.state.channelName;
+ }
+
+ var remover = 'Someone';
+ if (this.state.remover) {
+ remover = this.state.remover;
+ }
if (currentUser != null) {
return (
- <div className='modal fade' ref='modal' id='removed_from_channel' 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'>Removed from <span className='name'>{channelName}</span></h4>
- </div>
- <div className='modal-body'>
- <p>{remover} removed you from {channelName}</p>
+ <div
+ className='modal fade'
+ ref='modal'
+ id='removed_from_channel'
+ 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'>Removed from <span className='name'>{channelName}</span></h4>
+ </div>
+ <div className='modal-body'>
+ <p>{remover} removed you from {channelName}</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/>;
}
-}); \ No newline at end of file
+} \ No newline at end of file
diff --git a/web/react/components/rhs_thread.jsx b/web/react/components/rhs_thread.jsx
index adddeccf0..dbb16872e 100644
--- a/web/react/components/rhs_thread.jsx
+++ b/web/react/components/rhs_thread.jsx
@@ -33,7 +33,9 @@ export default class RhsThread extends React.Component {
if (pendingPostList) {
for (var pid in pendingPostList.posts) {
- postList.posts[pid] = pendingPostList.posts[pid];
+ if (pendingPostList.posts.hasOwnProperty(pid)) {
+ postList.posts[pid] = pendingPostList.posts[pid];
+ }
}
}
@@ -81,7 +83,9 @@ export default class RhsThread extends React.Component {
if (currentPosts.posts[currentPosts.order[0]].channel_id === currentSelected.posts[currentSelected.order[0]].channel_id) {
currentSelected.posts = {};
for (var postId in currentPosts.posts) {
- currentSelected.posts[postId] = currentPosts.posts[postId];
+ if (currentPosts.posts.hasOwnProperty(postId)) {
+ currentSelected.posts[postId] = currentPosts.posts[postId];
+ }
}
PostStore.storeSelectedPost(currentSelected);
@@ -128,9 +132,11 @@ export default class RhsThread extends React.Component {
var postsArray = [];
for (var postId in postList.posts) {
- var cpost = postList.posts[postId];
- if (cpost.root_id === rootPost.id) {
- postsArray.push(cpost);
+ if (postList.posts.hasOwnProperty(postId)) {
+ var cpost = postList.posts[postId];
+ if (cpost.root_id === rootPost.id) {
+ postsArray.push(cpost);
+ }
}
}
@@ -209,6 +215,7 @@ RhsThread.defaultProps = {
fromSearch: '',
isMentionSearch: false
};
+
RhsThread.propTypes = {
fromSearch: React.PropTypes.string,
isMentionSearch: React.PropTypes.bool
diff --git a/web/react/components/setting_picture.jsx b/web/react/components/setting_picture.jsx
index 5b12ad7e9..eaa839733 100644
--- a/web/react/components/setting_picture.jsx
+++ b/web/react/components/setting_picture.jsx
@@ -1,25 +1,33 @@
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
// See License.txt for license information.
-module.exports = React.createClass({
- setPicture: function(file) {
+export default class SettingPicture extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.setPicture = this.setPicture.bind(this);
+ }
+
+ setPicture(file) {
if (file) {
var reader = new FileReader();
var img = this.refs.image.getDOMNode();
- reader.onload = function(e) {
+ reader.onload = function load(e) {
$(img).attr('src', e.target.result);
};
reader.readAsDataURL(file);
}
- },
- componentWillReceiveProps: function(nextProps) {
+ }
+
+ componentWillReceiveProps(nextProps) {
if (nextProps.picture) {
this.setPicture(nextProps.picture);
}
- },
- render: function() {
+ }
+
+ render() {
var clientError = null;
if (this.props.client_error) {
clientError = <div className='form-group has-error'><label className='control-label'>{this.props.client_error}</label></div>;
@@ -31,14 +39,31 @@ module.exports = React.createClass({
var img = null;
if (this.props.picture) {
- img = (<img ref='image' className='profile-img' src=''/>);
+ img = (
+ <img
+ ref='image'
+ className='profile-img'
+ src=''
+ />
+ );
} else {
- img = (<img ref='image' className='profile-img' src={this.props.src}/>);
+ img = (
+ <img
+ ref='image'
+ className='profile-img'
+ src={this.props.src}
+ />
+ );
}
var confirmButton;
if (this.props.loadingPicture) {
- confirmButton = <img className='spinner' src='/static/images/load.gif'/>;
+ confirmButton = (
+ <img
+ className='spinner'
+ src='/static/images/load.gif'
+ />
+ );
} else {
var confirmButtonClass = 'btn btn-sm';
if (this.props.submitActive) {
@@ -46,9 +71,15 @@ module.exports = React.createClass({
} else {
confirmButtonClass += ' btn-inactive disabled';
}
- confirmButton = <a className={confirmButtonClass} onClick={this.props.submit}>Save</a>;
+
+ confirmButton = (
+ <a
+ className={confirmButtonClass}
+ onClick={this.props.submit}
+ >Save</a>
+ );
}
- var helpText = 'Upload a profile picture in either JPG or PNG format, at least ' + config.ProfileWidth + 'px in width and ' + config.ProfileHeight + 'px height.'
+ var helpText = 'Upload a profile picture in either JPG or PNG format, at least ' + config.ProfileWidth + 'px in width and ' + config.ProfileHeight + 'px height.';
var self = this;
return (
@@ -65,13 +96,36 @@ module.exports = React.createClass({
<li className='setting-list-item'>
{serverError}
{clientError}
- <span className='btn btn-sm btn-primary btn-file sel-btn'>Select<input ref='input' accept='.jpg,.png,.bmp' type='file' onChange={this.props.pictureChange}/></span>
+ <span className='btn btn-sm btn-primary btn-file sel-btn'
+ >Select<input
+ ref='input'
+ accept='.jpg,.png,.bmp'
+ type='file'
+ onChange={this.props.pictureChange}
+ />
+ </span>
{confirmButton}
- <a className='btn btn-sm theme' href='#' onClick={self.props.updateSection}>Cancel</a>
+ <a
+ className='btn btn-sm theme'
+ href='#'
+ onClick={self.props.updateSection}
+ >Cancel</a>
</li>
</ul>
</li>
</ul>
);
}
-});
+}
+
+SettingPicture.propTypes = {
+ client_error: React.PropTypes.string,
+ server_error: React.PropTypes.string,
+ src: React.PropTypes.string,
+ picture: React.PropTypes.object,
+ loadingPicture: React.PropTypes.bool,
+ submitActive: React.PropTypes.bool,
+ submit: React.PropTypes.func,
+ title: React.PropTypes.string,
+ pictureChange: React.PropTypes.func
+}; \ No newline at end of file
diff --git a/web/react/components/setting_upload.jsx b/web/react/components/setting_upload.jsx
index 596324308..a7ab03018 100644
--- a/web/react/components/setting_upload.jsx
+++ b/web/react/components/setting_upload.jsx
@@ -1,36 +1,37 @@
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
// See License.txt for license information.
-module.exports = React.createClass({
- displayName: 'Setting Upload',
- propTypes: {
- title: React.PropTypes.string.isRequired,
- submit: React.PropTypes.func.isRequired,
- fileTypesAccepted: React.PropTypes.string.isRequired,
- clientError: React.PropTypes.string,
- serverError: React.PropTypes.string,
- helpText: React.PropTypes.string
- },
- getInitialState: function() {
- return {
+export default class SettingsUpload extends React.Component {
+
+ constructor(props) {
+ super(props);
+
+ this.doFileSelect = this.doFileSelect.bind(this);
+ this.doSubmit = this.doSubmit.bind(this);
+ this.onFileSelect = this.onFileSelect.bind(this);
+
+ this.state = {
clientError: this.props.clientError,
serverError: this.props.serverError
};
- },
- componentWillReceiveProps: function() {
+ }
+
+ componentWillReceiveProps() {
this.setState({
clientError: this.props.clientError,
serverError: this.props.serverError
});
- },
- doFileSelect: function(e) {
+ }
+
+ doFileSelect(e) {
e.preventDefault();
this.setState({
clientError: '',
serverError: ''
});
- },
- doSubmit: function(e) {
+ }
+
+ doSubmit(e) {
e.preventDefault();
var inputnode = this.refs.uploadinput.getDOMNode();
if (inputnode.files && inputnode.files[0]) {
@@ -38,16 +39,18 @@ module.exports = React.createClass({
} else {
this.setState({clientError: 'No file selected.'});
}
- },
- onFileSelect: function(e) {
+ }
+
+ onFileSelect(e) {
var filename = $(e.target).val();
if (filename.substring(3, 11) === 'fakepath') {
filename = filename.substring(12);
}
$(e.target).closest('li').find('.file-status').addClass('hide');
$(e.target).closest('li').find('.file-name').removeClass('hide').html(filename);
- },
- render: function() {
+ }
+
+ render() {
var clientError = null;
if (this.state.clientError) {
clientError = (
@@ -67,7 +70,11 @@ module.exports = React.createClass({
<li className='col-xs-offset-3 col-xs-8'>
<ul className='setting-list'>
<li className='setting-list-item'>
- <span className='btn btn-sm btn-primary btn-file sel-btn'>Select file<input ref='uploadinput' accept={this.props.fileTypesAccepted} type='file' onChange={this.onFileSelect}/></span>
+ <span className='btn btn-sm btn-primary btn-file sel-btn'>Select file<input
+ ref='uploadinput'
+ accept={this.props.fileTypesAccepted}
+ type='file'
+ onChange={this.onFileSelect}/></span>
<a
className={'btn btn-sm btn-primary'}
onClick={this.doSubmit}>
@@ -82,4 +89,13 @@ module.exports = React.createClass({
</ul>
);
}
-});
+}
+
+SettingsUpload.propTypes = {
+ title: React.PropTypes.string.isRequired,
+ submit: React.PropTypes.func.isRequired,
+ fileTypesAccepted: React.PropTypes.string.isRequired,
+ clientError: React.PropTypes.string,
+ serverError: React.PropTypes.string,
+ helpText: React.PropTypes.object
+}; \ No newline at end of file
diff --git a/web/react/components/sidebar_right_menu.jsx b/web/react/components/sidebar_right_menu.jsx
index 615bc4ef2..fea889b33 100644
--- a/web/react/components/sidebar_right_menu.jsx
+++ b/web/react/components/sidebar_right_menu.jsx
@@ -5,12 +5,19 @@ var UserStore = require('../stores/user_store.jsx');
var client = require('../utils/client.jsx');
var utils = require('../utils/utils.jsx');
-module.exports = React.createClass({
- handleLogoutClick: function(e) {
+export default class SidebarRightMenu extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.handleLogoutClick = this.handleLogoutClick.bind(this);
+ }
+
+ handleLogoutClick(e) {
e.preventDefault();
client.logout();
- },
- render: function() {
+ }
+
+ render() {
var teamLink = '';
var inviteLink = '';
var teamSettingsLink = '';
@@ -23,14 +30,22 @@ module.exports = React.createClass({
inviteLink = (
<li>
- <a href='#' data-toggle='modal' data-target='#invite_member'><i className='glyphicon glyphicon-user'></i>Invite New Member</a>
+ <a href='#'
+ data-toggle='modal'
+ data-target='#invite_member'
+ ><i className='glyphicon glyphicon-user'></i>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}><i className='glyphicon glyphicon-link'></i>Get Team Invite Link</a>
+ <a href='#'
+ data-toggle='modal'
+ data-target='#get_link'
+ data-title='Team Invite'
+ data-value={utils.getWindowLocationOrigin() + '/signup_user_complete/?id=' + currentUser.team_id}
+ ><i className='glyphicon glyphicon-link'></i>Get Team Invite Link</a>
</li>
);
}
@@ -39,12 +54,20 @@ module.exports = React.createClass({
if (isAdmin) {
teamSettingsLink = (
<li>
- <a href='#' data-toggle='modal' data-target='#team_settings'><i className='glyphicon glyphicon-globe'></i>Team Settings</a>
+ <a
+ href='#'
+ data-toggle='modal'
+ data-target='#team_settings'
+ ><i className='glyphicon glyphicon-globe'></i>Team Settings</a>
</li>
);
manageLink = (
<li>
- <a href='#' data-toggle='modal' data-target='#team_members'><i className='glyphicon glyphicon-wrench'></i>Manage Team</a>
+ <a
+ href='#'
+ data-toggle='modal'
+ data-target='#team_members'
+ ><i className='glyphicon glyphicon-wrench'></i>Manage Team</a>
</li>
);
}
@@ -61,23 +84,48 @@ module.exports = React.createClass({
return (
<div>
<div className='team__header theme'>
- <a className='team__name' href='/channels/town-square'>{teamDisplayName}</a>
+ <a
+ className='team__name'
+ href='/channels/town-square'
+ >{teamDisplayName}</a>
</div>
<div className='nav-pills__container'>
<ul className='nav nav-pills nav-stacked'>
- <li><a href='#' data-toggle='modal' data-target='#user_settings'><i className='glyphicon glyphicon-cog'></i>Account Settings</a></li>
+ <li>
+ <a
+ href='#'
+ data-toggle='modal'
+ data-target='#user_settings'
+ ><i className='glyphicon glyphicon-cog'></i>Account Settings</a></li>
{teamSettingsLink}
{inviteLink}
{teamLink}
{manageLink}
- <li><a href='#' onClick={this.handleLogoutClick}><i className='glyphicon glyphicon-log-out'></i>Logout</a></li>
+ <li>
+ <a
+ href='#'
+ onClick={this.handleLogoutClick}
+ ><i className='glyphicon glyphicon-log-out'></i>Logout</a></li>
<li className='divider'></li>
- <li><a target='_blank' href='/static/help/configure_links.html'><i className='glyphicon glyphicon-question-sign'></i>Help</a></li>
- <li><a target='_blank' href='/static/help/configure_links.html'><i className='glyphicon glyphicon-earphone'></i>Report a Problem</a></li>
+ <li>
+ <a
+ target='_blank'
+ href='/static/help/configure_links.html'
+ ><i className='glyphicon glyphicon-question-sign'></i>Help</a></li>
+ <li>
+ <a
+ target='_blank'
+ href='/static/help/configure_links.html'
+ ><i className='glyphicon glyphicon-earphone'></i>Report a Problem</a></li>
</ul>
</div>
</div>
);
}
-});
+}
+
+SidebarRightMenu.propTypes = {
+ teamType: React.PropTypes.string,
+ teamDisplayName: React.PropTypes.string
+}; \ No newline at end of file
diff --git a/web/react/components/team_import_tab.jsx b/web/react/components/team_import_tab.jsx
index e3415d7f4..627ff85f4 100644
--- a/web/react/components/team_import_tab.jsx
+++ b/web/react/components/team_import_tab.jsx
@@ -4,26 +4,38 @@
var utils = require('../utils/utils.jsx');
var SettingUpload = require('./setting_upload.jsx');
-module.exports = React.createClass({
- displayName: 'Import Tab',
- getInitialState: function() {
- return {status: 'ready', link: ''};
- },
- onImportFailure: function() {
+export default class TeamImportTab extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.onImportFailure = this.onImportFailure.bind(this);
+ this.onImportSuccess = this.onImportSuccess.bind(this);
+ this.doImportSlack = this.doImportSlack.bind(this);
+
+ this.state = {
+ status: 'ready',
+ link: ''
+ };
+ }
+
+ onImportFailure() {
this.setState({status: 'fail', link: ''});
- },
- onImportSuccess: function(data) {
+ }
+
+ onImportSuccess(data) {
this.setState({status: 'done', link: 'data:application/octet-stream;charset=utf-8,' + encodeURIComponent(data)});
- },
- doImportSlack: function(file) {
+ }
+
+ doImportSlack(file) {
this.setState({status: 'in-progress', link: ''});
utils.importSlack(file, this.onImportSuccess, this.onImportFailure);
- },
- render: function() {
+ }
+
+ render() {
var uploadHelpText = (
<div>
<br/>
- Slack does not allow you to export files, images, private groups or direct messages stored in Slack. Therefore, Slack import to Mattermost only supports importing of text messages in your Slack team's public channels.
+ Slack does not allow you to export files, images, private groups or direct messages stored in Slack. Therefore, Slack import to Mattermost only supports importing of text messages in your Slack team's public channels.
<br/><br/>
The Slack import to Mattermost is in "Preview". Slack bot posts and channels with underscores do not yet import.
<br/><br/>
@@ -39,22 +51,25 @@ module.exports = React.createClass({
var messageSection;
switch (this.state.status) {
- case 'ready':
- messageSection = '';
+
+ case 'ready':
+ messageSection = '';
break;
- case 'in-progress':
- messageSection = (
- <p className="confirm-import alert alert-warning"><i className="fa fa-spinner fa-pulse"></i> Importing...</p>
+ case 'in-progress':
+ messageSection = (
+ <p className='confirm-import alert alert-warning'><i className='fa fa-spinner fa-pulse'></i> Importing...</p>
);
break;
- case 'done':
- messageSection = (
- <p className="confirm-import alert alert-success"><i className="fa fa-check"></i> Import successful: <a href={this.state.link} download='MattermostImportSummary.txt'>View Summary</a></p>
+ case 'done':
+ messageSection = (
+ <p className='confirm-import alert alert-success'><i className='fa fa-check'></i> Import successful: <a href={this.state.link}
+ download='MattermostImportSummary.txt'>View Summary</a></p>
);
break;
- case 'fail':
- messageSection = (
- <p className="confirm-import alert alert-warning"><i className="fa fa-warning"></i> Import failure: <a href={this.state.link} download='MattermostImportSummary.txt'>View Summary</a></p>
+ case 'fail':
+ messageSection = (
+ <p className='confirm-import alert alert-warning'><i className='fa fa-warning'></i> Import failure: <a href={this.state.link}
+ download='MattermostImportSummary.txt'>View Summary</a></p>
);
break;
}
@@ -62,10 +77,22 @@ module.exports = React.createClass({
return (
<div>
<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'><i className='modal-back'></i>Import</h4>
+ <button type='button'
+ className='close'
+ data-dismiss='modal'
+ aria-label='Close'
+ >
+ <span aria-hidden='true'>&times;</span>
+ </button>
+ <h4
+ className='modal-title'
+ ref='title'
+ ><i className='modal-back'></i>Import</h4>
</div>
- <div ref='wrapper' className='user-settings'>
+ <div
+ ref='wrapper'
+ className='user-settings'
+ >
<h3 className='tab-header'>Import</h3>
<div className='divider-dark first'/>
{uploadSection}
@@ -75,4 +102,4 @@ module.exports = React.createClass({
</div>
);
}
-});
+}
diff --git a/web/react/components/team_members.jsx b/web/react/components/team_members.jsx
index 616fd2c99..86c321d06 100644
--- a/web/react/components/team_members.jsx
+++ b/web/react/components/team_members.jsx
@@ -2,77 +2,131 @@
// See License.txt for license information.
var UserStore = require('../stores/user_store.jsx');
-var ChannelStore = require('../stores/channel_store.jsx');
var MemberListTeam = require('./member_list_team.jsx');
-var Client = require('../utils/client.jsx');
var utils = require('../utils/utils.jsx');
function getStateFromStores() {
var users = UserStore.getProfiles();
- var member_list = [];
- for (var id in users) member_list.push(users[id]);
+ var memberList = [];
+ for (var id in users) {
+ if (users.hasOwnProperty(id)) {
+ memberList.push(users[id]);
+ }
+ }
+
+ memberList.sort(function sort(a, b) {
+ if (a.username < b.username) {
+ return -1;
+ }
+
+ if (a.username > b.username) {
+ return 1;
+ }
- member_list.sort(function(a,b) {
- if (a.username < b.username) return -1;
- if (a.username > b.username) return 1;
return 0;
});
return {
- member_list: member_list
+ member_list: memberList
};
}
-module.exports = React.createClass({
- componentDidMount: function() {
- UserStore.addChangeListener(this._onChange);
+export default class TeamMembers extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.onChange = this.onChange.bind(this);
+
+ this.state = getStateFromStores();
+ }
+
+ componentDidMount() {
+ UserStore.addChangeListener(this.onChange);
var self = this;
- $(this.refs.modal.getDOMNode()).on('hidden.bs.modal', function(e) {
- self.setState({ render_members: false });
+ $(this.refs.modal.getDOMNode()).on('hidden.bs.modal', function show() {
+ self.setState({render_members: false});
});
- $(this.refs.modal.getDOMNode()).on('show.bs.modal', function(e) {
- self.setState({ render_members: true });
+ $(this.refs.modal.getDOMNode()).on('show.bs.modal', function hide() {
+ self.setState({render_members: true});
});
- },
- componentWillUnmount: function() {
- UserStore.removeChangeListener(this._onChange);
- },
- _onChange: function() {
+ }
+
+ componentWillUnmount() {
+ UserStore.removeChangeListener(this.onChange);
+ }
+
+ onChange() {
var newState = getStateFromStores();
if (!utils.areStatesEqual(newState, this.state)) {
this.setState(newState);
}
- },
- getInitialState: function() {
- return getStateFromStores();
- },
- render: function() {
- var server_error = this.state.server_error ? <label className='has-error control-label'>{this.state.server_error}</label> : null;
+ }
+
+ render() {
+ var serverError = null;
+
+ if (this.state.server_error) {
+ serverError = <label className='has-error control-label'>{this.state.server_error}</label>;
+ }
+
+ var renderMembers = '';
+
+ if (this.state.render_members) {
+ renderMembers = <MemberListTeam users={this.state.member_list} />;
+ }
return (
- <div className="modal fade" ref="modal" id="team_members" 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" data-reactid=".5.0.0.0.0"><span aria-hidden="true" data-reactid=".5.0.0.0.0.0">×</span></button>
- <h4 className="modal-title" id="myModalLabel">{this.props.teamDisplayName + " Members"}</h4>
- </div>
- <div ref="modalBody" className="modal-body">
- <div className="channel-settings">
- <div className="team-member-list">
- { this.state.render_members ? <MemberListTeam users={this.state.member_list} /> : "" }
+ <div
+ className='modal fade'
+ ref='modal'
+ id='team_members'
+ tabIndex='-1'
+ role='dialog'
+ aria-hidden='true'
+ >
+ <div className='modal-dialog'>
+ <div className='modal-content'>
+ <div className='modal-header'>
+ <button
+ type='button'
+ className='close'
+ data-dismiss='modal'
+ aria-label='Close'
+ >
+ <span aria-hidden='true'>×</span>
+ </button>
+ <h4
+ className='modal-title'
+ id='myModalLabel'
+ >{this.props.teamDisplayName + ' Members'}</h4>
+ </div>
+ <div
+ ref='modalBody'
+ className='modal-body'
+ >
+ <div className='channel-settings'>
+ <div className='team-member-list'>
+ {renderMembers}
+ </div>
+ {serverError}
</div>
- { server_error }
+ </div>
+ <div className='modal-footer'>
+ <button
+ type='button'
+ className='btn btn-default'
+ data-dismiss='modal'
+ >Close</button>
</div>
</div>
- <div className="modal-footer">
- <button type="button" className="btn btn-default" data-dismiss="modal">Close</button>
- </div>
- </div>
</div>
</div>
);
}
-});
+}
+
+TeamMembers.propTypes = {
+ teamDisplayName: React.PropTypes.string
+};
diff --git a/web/react/components/user_settings.jsx b/web/react/components/user_settings.jsx
index 9b0e906c5..282fb7681 100644
--- a/web/react/components/user_settings.jsx
+++ b/web/react/components/user_settings.jsx
@@ -8,56 +8,82 @@ var SecurityTab = require('./user_settings_security.jsx');
var GeneralTab = require('./user_settings_general.jsx');
var AppearanceTab = require('./user_settings_appearance.jsx');
-module.exports = React.createClass({
- displayName: 'UserSettings',
- propTypes: {
- activeTab: React.PropTypes.string,
- activeSection: React.PropTypes.string,
- updateSection: React.PropTypes.func,
- updateTab: React.PropTypes.func
- },
- componentDidMount: function() {
+export default class UserSettings extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.onListenerChange = this.onListenerChange.bind(this);
+
+ this.state = {user: UserStore.getCurrentUser()};
+ }
+
+ componentDidMount() {
UserStore.addChangeListener(this.onListenerChange);
- },
- componentWillUnmount: function() {
+ }
+
+ componentWillUnmount() {
UserStore.removeChangeListener(this.onListenerChange);
- },
- onListenerChange: function () {
+ }
+
+ onListenerChange() {
var user = UserStore.getCurrentUser();
if (!utils.areStatesEqual(this.state.user, user)) {
this.setState({user: user});
}
- },
- getInitialState: function() {
- return {user: UserStore.getCurrentUser()};
- },
- render: function() {
+ }
+
+ render() {
if (this.props.activeTab === 'general') {
return (
<div>
- <GeneralTab user={this.state.user} activeSection={this.props.activeSection} updateSection={this.props.updateSection} />
+ <GeneralTab
+ user={this.state.user}
+ activeSection={this.props.activeSection}
+ updateSection={this.props.updateSection}
+ />
</div>
);
} else if (this.props.activeTab === 'security') {
return (
<div>
- <SecurityTab user={this.state.user} activeSection={this.props.activeSection} updateSection={this.props.updateSection} updateTab={this.props.updateTab} />
+ <SecurityTab
+ user={this.state.user}
+ activeSection={this.props.activeSection}
+ updateSection={this.props.updateSection}
+ updateTab={this.props.updateTab}
+ />
</div>
);
} else if (this.props.activeTab === 'notifications') {
return (
<div>
- <NotificationsTab user={this.state.user} activeSection={this.props.activeSection} updateSection={this.props.updateSection} updateTab={this.props.updateTab} />
+ <NotificationsTab
+ user={this.state.user}
+ activeSection={this.props.activeSection}
+ updateSection={this.props.updateSection}
+ updateTab={this.props.updateTab}
+ />
</div>
);
} else if (this.props.activeTab === 'appearance') {
return (
<div>
- <AppearanceTab activeSection={this.props.activeSection} updateSection={this.props.updateSection} updateTab={this.props.updateTab} />
+ <AppearanceTab
+ activeSection={this.props.activeSection}
+ updateSection={this.props.updateSection}
+ updateTab={this.props.updateTab}
+ />
</div>
);
- } else {
- return <div/>;
}
+
+ return <div/>;
}
-});
+}
+
+UserSettings.propTypes = {
+ activeTab: React.PropTypes.string,
+ activeSection: React.PropTypes.string,
+ updateSection: React.PropTypes.func,
+ updateTab: React.PropTypes.func
+}; \ No newline at end of file