Merge pull request #922 from mattermost/plt-360

PLT-360 Upgrade and changes to ESLint
This commit is contained in:
Harrison Healey
2015-10-05 16:02:09 -04:00
33 changed files with 351 additions and 309 deletions

View File

@@ -42,12 +42,13 @@
"valid-typeof": 2,
"block-scoped-var": 2,
"complexity": [1, 8],
"complexity": [0, 8],
"consistent-return": 2,
"curly": [2, "all"],
"dot-location": [2, "object"],
"dot-notation": 2,
"eqeqeq": [2, "smart"],
"global-require": 2,
"guard-for-in": 2,
"no-alert": 2,
"no-array-constructor": 2,
@@ -109,30 +110,34 @@
"func-names": 2,
"func-style": [2, "declaration"],
"indent": [2, 4, {"SwitchCase": 0}],
"jsx-quotes": [2, "prefer-single"],
"key-spacing": [2, {"beforeColon": false, "afterColon": true}],
"lines-around-comment": [2, { "beforeBlockComment": true, "beforeLineComment": true, "allowBlockStart": true, "allowBlockEnd": true }],
"linebreak-style": 2,
"lines-around-comment": [2, { "beforeBlockComment": true, "beforeLineComment": true, "allowBlockStart": true, "allowBlockEnd": true }],
"new-cap": 2,
"new-parens": 2,
"no-lonely-if": 2,
"no-mixed-spaces-and-tabs": 2,
"no-multiple-empty-lines": [2, {"max": 1}],
"no-negated-condition": 2,
"no-nested-ternary": 2,
"no-spaced-func": 2,
"no-ternary": 2,
"no-ternary": 0,
"no-trailing-spaces": [2, { "skipBlankLines": false }],
"no-underscore-dangle": 2,
"no-unneeded-ternary": 2,
"no-unneeded-ternary": [2, {"defaultAssignment": false}],
"object-curly-spacing": [2, "never"],
"one-var": [2, "never"],
"operator-linebreak": [2, "after"],
"padded-blocks": [2, "never"],
"quote-props": [2, "as-needed"],
"quotes": [2, "single", "avoid-escape"],
"semi-spacing": [2, {"before": false, "after": true}],
"semi": [2, "always"],
"semi-spacing": [2, {"before": false, "after": true}],
"space-after-keywords": [2, "always"],
"space-before-blocks": [2, "always"],
"space-before-function-paren": [2, "never"],
"space-before-keywords": [2, "always"],
"space-in-parens": [2, "never"],
"space-infix-ops": 2,
"space-return-throw-case": 2,
@@ -167,7 +172,6 @@
"react/jsx-no-duplicate-props": [2, { "ignoreCase": false }],
"react/jsx-no-literals": 1,
"react/jsx-no-undef": 2,
"react/jsx-quotes": [2, "single", "avoid-escape"],
"react/jsx-uses-react": 2,
"react/jsx-uses-vars": 2,
"react/no-danger": 0,
@@ -179,6 +183,7 @@
"react/prop-types": 2,
"react/self-closing-comp": 2,
"react/sort-comp": 0,
"react/wrap-multilines": 2
"react/wrap-multilines": 2,
"react/no-direct-mutation-state": 2
}
}

View File

@@ -12,25 +12,31 @@ export default class AccessHistoryModal extends React.Component {
this.onAuditChange = this.onAuditChange.bind(this);
this.handleMoreInfo = this.handleMoreInfo.bind(this);
this.onHide = this.onHide.bind(this);
this.onShow = this.onShow.bind(this);
this.state = this.getStateFromStoresForAudits();
this.state.moreInfo = [];
let state = this.getStateFromStoresForAudits();
state.moreInfo = [];
this.state = state;
}
getStateFromStoresForAudits() {
return {
audits: UserStore.getAudits()
};
}
onShow() {
AsyncClient.getAudits();
}
onHide() {
$('#user_settings').modal('show');
this.setState({moreInfo: []});
}
componentDidMount() {
UserStore.addAuditsChangeListener(this.onAuditChange);
$(React.findDOMNode(this.refs.modal)).on('shown.bs.modal', function show() {
AsyncClient.getAudits();
});
$(React.findDOMNode(this.refs.modal)).on('shown.bs.modal', this.onShow);
$(React.findDOMNode(this.refs.modal)).on('hidden.bs.modal', function hide() {
$('#user_settings').modal('show');
this.setState({moreInfo: []});
}.bind(this));
$(React.findDOMNode(this.refs.modal)).on('hidden.bs.modal', this.onHide);
}
componentWillUnmount() {
UserStore.removeAuditsChangeListener(this.onAuditChange);

View File

@@ -14,9 +14,13 @@ export default class ActivityLogModal extends React.Component {
this.submitRevoke = this.submitRevoke.bind(this);
this.onListenerChange = this.onListenerChange.bind(this);
this.handleMoreInfo = this.handleMoreInfo.bind(this);
this.onHide = this.onHide.bind(this);
this.onShow = this.onShow.bind(this);
this.state = this.getStateFromStores();
this.state.moreInfo = [];
let state = this.getStateFromStores();
state.moreInfo = [];
this.state = state;
}
getStateFromStores() {
return {
@@ -38,16 +42,18 @@ export default class ActivityLogModal extends React.Component {
}.bind(this)
);
}
onShow() {
AsyncClient.getSessions();
}
onHide() {
$('#user_settings').modal('show');
this.setState({moreInfo: []});
}
componentDidMount() {
UserStore.addSessionsChangeListener(this.onListenerChange);
$(React.findDOMNode(this.refs.modal)).on('shown.bs.modal', function handleShow() {
AsyncClient.getSessions();
});
$(React.findDOMNode(this.refs.modal)).on('shown.bs.modal', this.onShow);
$(React.findDOMNode(this.refs.modal)).on('hidden.bs.modal', function handleHide() {
$('#user_settings').modal('show');
this.setState({moreInfo: []});
}.bind(this));
$(React.findDOMNode(this.refs.modal)).on('hidden.bs.modal', this.onHide);
}
componentWillUnmount() {
UserStore.removeSessionsChangeListener(this.onListenerChange);

View File

@@ -132,7 +132,26 @@ export default class ChannelHeader extends React.Component {
}
let dropdownContents = [];
if (!isDirect) {
if (isDirect) {
dropdownContents.push(
<li
key='edit_description_direct'
role='presentation'
>
<a
role='menuitem'
href='#'
data-toggle='modal'
data-target='#edit_channel'
data-desc={channel.description}
data-title={channel.display_name}
data-channelid={channel.id}
>
Set Channel Description...
</a>
</li>
);
} else {
dropdownContents.push(
<li
key='view_info'
@@ -276,25 +295,6 @@ export default class ChannelHeader extends React.Component {
</li>
);
}
} else {
dropdownContents.push(
<li
key='edit_description_direct'
role='presentation'
>
<a
role='menuitem'
href='#'
data-toggle='modal'
data-target='#edit_channel'
data-desc={channel.description}
data-title={channel.display_name}
data-channelid={channel.id}
>
Set Channel Description...
</a>
</li>
);
}
return (

View File

@@ -15,6 +15,8 @@ export default class ChannelMembers extends React.Component {
this.getStateFromStores = this.getStateFromStores.bind(this);
this.onChange = this.onChange.bind(this);
this.handleRemove = this.handleRemove.bind(this);
this.onHide = this.onHide.bind(this);
this.onShow = this.onShow.bind(this);
this.state = this.getStateFromStores();
}
@@ -63,16 +65,18 @@ export default class ChannelMembers extends React.Component {
channelName: channelName
};
}
onHide() {
this.setState({renderMembers: false});
}
onShow() {
this.setState({renderMembers: true});
}
componentDidMount() {
ChannelStore.addExtraInfoChangeListener(this.onChange);
ChannelStore.addChangeListener(this.onChange);
$(React.findDOMNode(this.refs.modal)).on('hidden.bs.modal', function handleHide() {
this.setState({renderMembers: false});
}.bind(this));
$(React.findDOMNode(this.refs.modal)).on('hidden.bs.modal', this.onHide);
$(React.findDOMNode(this.refs.modal)).on('show.bs.modal', function handleShow() {
this.setState({renderMembers: true});
}.bind(this));
$(React.findDOMNode(this.refs.modal)).on('show.bs.modal', this.onShow);
}
componentWillUnmount() {
ChannelStore.removeExtraInfoChangeListener(this.onChange);

View File

@@ -23,6 +23,7 @@ export default class ChannelNotifications extends React.Component {
this.handleSubmitMarkUnreadLevel = this.handleSubmitMarkUnreadLevel.bind(this);
this.handleUpdateMarkUnreadLevel = this.handleUpdateMarkUnreadLevel.bind(this);
this.createMarkUnreadLevelSection = this.createMarkUnreadLevelSection.bind(this);
this.onShow = this.onShow.bind(this);
this.state = {
notifyLevel: '',
@@ -32,30 +33,29 @@ export default class ChannelNotifications extends React.Component {
activeSection: ''
};
}
onShow(e) {
var button = e.relatedTarget;
var channelId = button.getAttribute('data-channelid');
const member = ChannelStore.getMember(channelId);
var notifyLevel = member.notify_props.desktop;
var markUnreadLevel = member.notify_props.mark_unread;
this.setState({
notifyLevel,
markUnreadLevel,
title: button.getAttribute('data-title'),
channelId
});
}
componentDidMount() {
ChannelStore.addChangeListener(this.onListenerChange);
$(React.findDOMNode(this.refs.modal)).on('show.bs.modal', function showModal(e) {
var button = e.relatedTarget;
var channelId = button.getAttribute('data-channelid');
const member = ChannelStore.getMember(channelId);
var notifyLevel = member.notify_props.desktop;
var markUnreadLevel = member.notify_props.mark_unread;
this.setState({
notifyLevel,
markUnreadLevel,
title: button.getAttribute('data-title'),
channelId: channelId
});
}.bind(this));
$(React.findDOMNode(this.refs.modal)).on('show.bs.modal', this.onShow);
}
componentWillUnmount() {
ChannelStore.removeChangeListener(this.onListenerChange);
}
onListenerChange() {
if (!this.state.channelId) {
return;
@@ -76,7 +76,6 @@ export default class ChannelNotifications extends React.Component {
updateSection(section) {
this.setState({activeSection: section});
}
handleSubmitNotifyLevel() {
var channelId = this.state.channelId;
var notifyLevel = this.state.notifyLevel;
@@ -103,12 +102,10 @@ export default class ChannelNotifications extends React.Component {
}
);
}
handleUpdateNotifyLevel(notifyLevel) {
this.setState({notifyLevel});
React.findDOMNode(this.refs.modal).focus();
}
createNotifyLevelSection(serverError) {
var handleUpdateSection;

View File

@@ -51,7 +51,7 @@ export default class CommandList extends React.Component {
this.setState({suggestions: data.suggestions, cmd: cmd});
}.bind(this),
function fail() {
}
}
);
}

View File

@@ -170,7 +170,9 @@ export default class CreateComment extends React.Component {
this.setState({uploadsInProgress: draft.uploadsInProgress, previews: draft.previews});
}
handleUploadError(err, clientId) {
if (clientId !== -1) {
if (clientId === -1) {
this.setState({serverError: err});
} else {
let draft = PostStore.getCommentDraft(this.props.rootId);
const index = draft.uploadsInProgress.indexOf(clientId);
@@ -181,8 +183,6 @@ export default class CreateComment extends React.Component {
PostStore.storeCommentDraft(this.props.rootId, draft);
this.setState({uploadsInProgress: draft.uploadsInProgress, serverError: err});
} else {
this.setState({serverError: err});
}
}
handleTextDrop(text) {
@@ -196,15 +196,15 @@ export default class CreateComment extends React.Component {
// id can either be the path of an uploaded file or the client id of an in progress upload
let index = previews.indexOf(id);
if (index !== -1) {
previews.splice(index, 1);
} else {
if (index === -1) {
index = uploadsInProgress.indexOf(id);
if (index !== -1) {
uploadsInProgress.splice(index, 1);
this.refs.fileUpload.cancelUpload(id);
}
} else {
previews.splice(index, 1);
}
let draft = PostStore.getCommentDraft(this.props.rootId);

View File

@@ -222,7 +222,9 @@ export default class CreatePost extends React.Component {
this.setState({uploadsInProgress: draft.uploadsInProgress, previews: draft.previews});
}
handleUploadError(err, clientId) {
if (clientId !== -1) {
if (clientId === -1) {
this.setState({serverError: err});
} else {
const draft = PostStore.getDraft(this.state.channelId);
const index = draft.uploadsInProgress.indexOf(clientId);
@@ -233,8 +235,6 @@ export default class CreatePost extends React.Component {
PostStore.storeDraft(this.state.channelId, draft);
this.setState({uploadsInProgress: draft.uploadsInProgress, serverError: err});
} else {
this.setState({serverError: err});
}
}
handleTextDrop(text) {
@@ -248,15 +248,15 @@ export default class CreatePost extends React.Component {
// id can either be the path of an uploaded file or the client id of an in progress upload
let index = previews.indexOf(id);
if (index !== -1) {
previews.splice(index, 1);
} else {
if (index === -1) {
index = uploadsInProgress.indexOf(id);
if (index !== -1) {
uploadsInProgress.splice(index, 1);
this.refs.fileUpload.cancelUpload(id);
}
} else {
previews.splice(index, 1);
}
const draft = PostStore.getCurrentDraft();

View File

@@ -11,6 +11,7 @@ export default class DeleteChannelModal extends React.Component {
super(props);
this.handleDelete = this.handleDelete.bind(this);
this.onShow = this.onShow.bind(this);
this.state = {
title: '',
@@ -32,14 +33,15 @@ export default class DeleteChannelModal extends React.Component {
}
);
}
onShow(e) {
var button = $(e.relatedTarget);
this.setState({
title: button.attr('data-title'),
channelId: button.attr('data-channelid')
});
}
componentDidMount() {
$(React.findDOMNode(this.refs.modal)).on('show.bs.modal', function handleShow(e) {
var button = $(e.relatedTarget);
this.setState({
title: button.attr('data-title'),
channelId: button.attr('data-channelid')
});
}.bind(this));
$(React.findDOMNode(this.refs.modal)).on('show.bs.modal', this.onShow);
}
render() {
const channel = ChannelStore.getCurrent();

View File

@@ -16,6 +16,7 @@ export default class DeletePostModal extends React.Component {
this.handleDelete = this.handleDelete.bind(this);
this.onListenerChange = this.onListenerChange.bind(this);
this.onShow = this.onShow.bind(this);
this.state = {title: '', postId: '', channelId: '', selectedList: PostStore.getSelectedPost(), comments: 0};
}
@@ -60,18 +61,19 @@ export default class DeletePostModal extends React.Component {
}
);
}
onShow(e) {
var newState = {};
if (BrowserStore.getItem('edit_state_transfer')) {
newState = BrowserStore.getItem('edit_state_transfer');
BrowserStore.removeItem('edit_state_transfer');
} else {
var button = e.relatedTarget;
newState = {title: $(button).attr('data-title'), channelId: $(button).attr('data-channelid'), postId: $(button).attr('data-postid'), comments: $(button).attr('data-comments')};
}
this.setState(newState);
}
componentDidMount() {
$(React.findDOMNode(this.refs.modal)).on('show.bs.modal', function freshOpen(e) {
var newState = {};
if (BrowserStore.getItem('edit_state_transfer')) {
newState = BrowserStore.getItem('edit_state_transfer');
BrowserStore.removeItem('edit_state_transfer');
} else {
var button = e.relatedTarget;
newState = {title: $(button).attr('data-title'), channelId: $(button).attr('data-channelid'), postId: $(button).attr('data-postid'), comments: $(button).attr('data-comments')};
}
this.setState(newState);
}.bind(this));
$(React.findDOMNode(this.refs.modal)).on('show.bs.modal', this.onShow);
PostStore.addSelectedPostChangeListener(this.onListenerChange);
}
componentWillUnmount() {

View File

@@ -11,6 +11,7 @@ export default class EditChannelModal extends React.Component {
this.handleEdit = this.handleEdit.bind(this);
this.handleUserInput = this.handleUserInput.bind(this);
this.handleClose = this.handleClose.bind(this);
this.onShow = this.onShow.bind(this);
this.state = {
description: '',
@@ -50,11 +51,12 @@ export default class EditChannelModal extends React.Component {
handleClose() {
this.setState({description: '', serverError: ''});
}
onShow(e) {
const button = e.relatedTarget;
this.setState({description: $(button).attr('data-desc'), title: $(button).attr('data-title'), channelId: $(button).attr('data-channelid'), serverError: ''});
}
componentDidMount() {
$(React.findDOMNode(this.refs.modal)).on('show.bs.modal', function handleShow(e) {
const button = e.relatedTarget;
this.setState({description: $(button).attr('data-desc'), title: $(button).attr('data-title'), channelId: $(button).attr('data-channelid'), serverError: ''});
}.bind(this));
$(React.findDOMNode(this.refs.modal)).on('show.bs.modal', this.onShow);
$(React.findDOMNode(this.refs.modal)).on('hidden.bs.modal', this.handleClose);
}
componentWillUnmount() {

View File

@@ -97,7 +97,7 @@ export default class FileUpload extends React.Component {
element[0].type = 'text';
element[0].type = 'file';
}
} catch(e) {
} catch (e) {
// Do nothing
}
}

View File

@@ -8,18 +8,22 @@ export default class GetLinkModal extends React.Component {
super(props);
this.handleClick = this.handleClick.bind(this);
this.onShow = this.onShow.bind(this);
this.onHide = this.onHide.bind(this);
this.state = {copiedLink: false};
}
onShow(e) {
var button = e.relatedTarget;
this.setState({title: $(button).attr('data-title'), value: $(button).attr('data-value')});
}
onHide() {
this.setState({copiedLink: false});
}
componentDidMount() {
if (this.refs.modal) {
$(React.findDOMNode(this.refs.modal)).on('show.bs.modal', function show(e) {
var button = e.relatedTarget;
this.setState({title: $(button).attr('data-title'), value: $(button).attr('data-value')});
}.bind(this));
$(React.findDOMNode(this.refs.modal)).on('hide.bs.modal', function hide() {
this.setState({copiedLink: false});
}.bind(this));
$(React.findDOMNode(this.refs.modal)).on('show.bs.modal', this.onShow);
$(React.findDOMNode(this.refs.modal)).on('hide.bs.modal', this.onShow);
}
}
handleClick() {

View File

@@ -88,10 +88,10 @@ export default class Login extends React.Component {
let focusEmail = false;
let focusPassword = false;
if (priorEmail !== '') {
focusPassword = true;
} else {
if (priorEmail === '') {
focusEmail = true;
} else {
focusPassword = true;
}
let loginMessage = [];

View File

@@ -18,7 +18,9 @@ export default class Mention extends React.Component {
var timestamp = UserStore.getCurrentUser().update_at;
if (this.props.id === 'allmention' || this.props.id === 'channelmention') {
icon = <span><i className='mention-img fa fa-users fa-2x'></i></span>;
} else if (this.props.id != null) {
} else if (this.props.id == null) {
icon = <span><i className='mention-img fa fa-users fa-2x'></i></span>;
} else {
icon = (
<span>
<img
@@ -27,8 +29,6 @@ export default class Mention extends React.Component {
/>
</span>
);
} else {
icon = <span><i className='mention-img fa fa-users fa-2x'></i></span>;
}
return (
<div

View File

@@ -26,53 +26,64 @@ export default class MentionList extends React.Component {
this.addFirstMention = this.addFirstMention.bind(this);
this.isEmpty = this.isEmpty.bind(this);
this.scrollToMention = this.scrollToMention.bind(this);
this.onScroll = this.onScroll.bind(this);
this.onMentionListKey = this.onMentionListKey.bind(this);
this.onClick = this.onClick.bind(this);
this.state = {excludeUsers: [], mentionText: '-1', selectedMention: 0, selectedUsername: ''};
}
onScroll() {
if ($('.mentions--top').length) {
$('#reply_mention_tab .mentions--top').css({bottom: $(window).height() - $('.post-right__scroll #reply_textbox').offset().top});
}
}
onMentionListKey(e) {
if (!this.isEmpty() && this.state.mentionText !== '-1' && (e.which === 13 || e.which === 9)) {
e.stopPropagation();
e.preventDefault();
this.addCurrentMention();
} else if (!this.isEmpty() && this.state.mentionText !== '-1' && (e.which === 38 || e.which === 40)) {
e.stopPropagation();
e.preventDefault();
if (e.which === 38) {
if (this.getSelection(this.state.selectedMention - 1)) {
this.setState({selectedMention: this.state.selectedMention - 1, selectedUsername: this.refs['mention' + (this.state.selectedMention - 1)].props.username});
}
} else if (e.which === 40) {
if (this.getSelection(this.state.selectedMention + 1)) {
this.setState({selectedMention: this.state.selectedMention + 1, selectedUsername: this.refs['mention' + (this.state.selectedMention + 1)].props.username});
}
}
this.scrollToMention(e.which);
}
}
onClick(e) {
if (!($('#' + this.props.id).is(e.target) || $('#' + this.props.id).has(e.target).length ||
('mentionlist' in this.refs && $(React.findDOMNode(this.refs.mentionlist)).has(e.target).length))) {
this.setState({mentionText: '-1'});
}
}
componentDidMount() {
PostStore.addMentionDataChangeListener(this.onListenerChange);
$('.post-right__scroll').scroll(function onScroll() {
if ($('.mentions--top').length) {
$('#reply_mention_tab .mentions--top').css({bottom: $(window).height() - $('.post-right__scroll #reply_textbox').offset().top});
}
});
$('.post-right__scroll').scroll(this.onScroll);
$('body').on('keydown.mentionlist', '#' + this.props.id,
function onMentionListKey(e) {
if (!this.isEmpty() && this.state.mentionText !== '-1' && (e.which === 13 || e.which === 9)) {
e.stopPropagation();
e.preventDefault();
this.addCurrentMention();
} else if (!this.isEmpty() && this.state.mentionText !== '-1' && (e.which === 38 || e.which === 40)) {
e.stopPropagation();
e.preventDefault();
if (e.which === 38) {
if (this.getSelection(this.state.selectedMention - 1)) {
this.setState({selectedMention: this.state.selectedMention - 1, selectedUsername: this.refs['mention' + (this.state.selectedMention - 1)].props.username});
}
} else if (e.which === 40) {
if (this.getSelection(this.state.selectedMention + 1)) {
this.setState({selectedMention: this.state.selectedMention + 1, selectedUsername: this.refs['mention' + (this.state.selectedMention + 1)].props.username});
}
}
this.scrollToMention(e.which);
}
}.bind(this)
);
$(document).click(function onClick(e) {
if (!($('#' + this.props.id).is(e.target) || $('#' + this.props.id).has(e.target).length ||
('mentionlist' in this.refs && $(React.findDOMNode(this.refs.mentionlist)).has(e.target).length))) {
this.setState({mentionText: '-1'});
}
}.bind(this));
$('body').on('keydown.mentionlist', '#' + this.props.id, this.onMentionListKey);
$(document).click(this.onClick);
}
componentWillUnmount() {
PostStore.removeMentionDataChangeListener(this.onListenerChange);
$('body').off('keydown.mentionlist', '#' + this.props.id);
}
/*
* This component is poorly designed, nessesitating some state modification
* in the componentDidUpdate function. This is generally discouraged as it
* is a performance issue and breaks with good react design. This component
* should be redesigned.
*/
componentDidUpdate() {
if (this.state.mentionText !== '-1') {
if (this.state.selectedUsername !== '' && (!this.getSelection(this.state.selectedMention) || this.state.selectedUsername !== this.refs['mention' + this.state.selectedMention].props.username)) {
@@ -80,17 +91,17 @@ export default class MentionList extends React.Component {
var foundMatch = false;
while (tempSelectedMention < this.state.selectedMention && this.getSelection(++tempSelectedMention)) {
if (this.state.selectedUsername === this.refs['mention' + tempSelectedMention].props.username) {
this.setState({selectedMention: tempSelectedMention});
this.setState({selectedMention: tempSelectedMention}); //eslint-disable-line react/no-did-update-set-state
foundMatch = true;
break;
}
}
if (this.getSelection(0) && !foundMatch) {
this.setState({selectedMention: 0, selectedUsername: this.refs.mention0.props.username});
this.setState({selectedMention: 0, selectedUsername: this.refs.mention0.props.username}); //eslint-disable-line react/no-did-update-set-state
}
}
} else if (this.state.selectedMention !== 0) {
this.setState({selectedMention: 0, selectedUsername: ''});
this.setState({selectedMention: 0, selectedUsername: ''}); //eslint-disable-line react/no-did-update-set-state
}
}
onListenerChange(id, mentionText) {
@@ -124,10 +135,10 @@ export default class MentionList extends React.Component {
return true;
}
addCurrentMention() {
if (!this.getSelection(this.state.selectedMention)) {
this.addFirstMention();
} else {
if (this.getSelection(this.state.selectedMention)) {
this.refs['mention' + this.state.selectedMention].handleClick();
} else {
this.addFirstMention();
}
}
addFirstMention() {

View File

@@ -60,9 +60,7 @@ export default class MoreChannels extends React.Component {
this.setState({joiningChannel: -1});
}.bind(this),
function joinFail(err) {
this.setState({joiningChannel: -1});
this.state.serverError = err.message;
this.setState(this.state);
this.setState({joiningChannel: -1, serverError: err.message});
}.bind(this)
);
}
@@ -81,56 +79,54 @@ export default class MoreChannels extends React.Component {
if (this.state.channels != null) {
var channels = this.state.channels;
if (!channels.loading) {
if (channels.length) {
moreChannels = (
<table className='more-channel-table table'>
<tbody>
{channels.map(function cMap(channel, index) {
var joinButton;
if (self.state.joiningChannel === index) {
joinButton = (
<img
className='join-channel-loading-gif'
src='/static/images/load.gif'
/>
);
} else {
joinButton = (
<button
onClick={self.handleJoin.bind(self, channel, index)}
className='btn btn-primary'
>
Join
</button>
);
}
return (
<tr key={channel.id}>
<td>
<p className='more-channel-name'>{channel.display_name}</p>
<p className='more-channel-description'>{channel.description}</p>
</td>
<td className='td--action'>
{joinButton}
</td>
</tr>
);
})}
</tbody>
</table>
);
} else {
moreChannels = (
<div className='no-channel-message'>
<p className='primary-message'>No more channels to join</p>
<p className='secondary-message'>Click 'Create New Channel' to make a new one</p>
</div>
);
}
} else {
if (channels.loading) {
moreChannels = <LoadingScreen />;
} else if (channels.length) {
moreChannels = (
<table className='more-channel-table table'>
<tbody>
{channels.map(function cMap(channel, index) {
var joinButton;
if (self.state.joiningChannel === index) {
joinButton = (
<img
className='join-channel-loading-gif'
src='/static/images/load.gif'
/>
);
} else {
joinButton = (
<button
onClick={self.handleJoin.bind(self, channel, index)}
className='btn btn-primary'
>
Join
</button>
);
}
return (
<tr key={channel.id}>
<td>
<p className='more-channel-name'>{channel.display_name}</p>
<p className='more-channel-description'>{channel.description}</p>
</td>
<td className='td--action'>
{joinButton}
</td>
</tr>
);
})}
</tbody>
</table>
);
} else {
moreChannels = (
<div className='no-channel-message'>
<p className='primary-message'>No more channels to join</p>
<p className='secondary-message'>Click 'Create New Channel' to make a new one</p>
</div>
);
}
}

View File

@@ -31,22 +31,7 @@ export default class MoreDirectChannels extends React.Component {
var active = '';
var handleClick = null;
if (!channel.fake) {
if (channel.id === ChannelStore.getCurrentId()) {
active = 'active';
}
if (channel.unread) {
badge = <span className='badge pull-right small'>{channel.unread}</span>;
titleClass = 'unread-title';
}
handleClick = function clickHandler(e) {
e.preventDefault();
utils.switchChannel(channel);
$(React.findDOMNode(self.refs.modal)).modal('hide');
};
} else {
if (channel.fake) {
// It's a direct message channel that doesn't exist yet so let's create it now
var otherUserId = utils.getUserIdFromChannelName(channel);
@@ -78,6 +63,21 @@ export default class MoreDirectChannels extends React.Component {
);
};
}
} else {
if (channel.id === ChannelStore.getCurrentId()) {
active = 'active';
}
if (channel.unread) {
badge = <span className='badge pull-right small'>{channel.unread}</span>;
titleClass = 'unread-title';
}
handleClick = function clickHandler(e) {
e.preventDefault();
utils.switchChannel(channel);
$(React.findDOMNode(self.refs.modal)).modal('hide');
};
}
return (

View File

@@ -37,9 +37,11 @@ export default class PostList extends React.Component {
this.deactivate = this.deactivate.bind(this);
this.resize = this.resize.bind(this);
this.state = this.getStateFromStores(props.channelId);
this.state.numToDisplay = Constants.POST_CHUNK_SIZE;
this.state.isFirstLoadComplete = false;
const state = this.getStateFromStores(props.channelId);
state.numToDisplay = Constants.POST_CHUNK_SIZE;
state.isFirstLoadComplete = false;
this.state = state;
}
getStateFromStores(id) {
var postList = PostStore.getPosts(id);
@@ -449,10 +451,10 @@ export default class PostList extends React.Component {
}
var createMessage;
if (creatorName !== '') {
createMessage = (<span>This is the start of the <strong>{uiName}</strong> {uiType}, created by <strong>{creatorName}</strong> on <strong>{utils.displayDate(channel.create_at)}</strong></span>);
} else {
if (creatorName === '') {
createMessage = 'This is the start of the ' + uiName + ' ' + uiType + ', created on ' + utils.displayDate(channel.create_at) + '.';
} else {
createMessage = (<span>This is the start of the <strong>{uiName}</strong> {uiType}, created by <strong>{creatorName}</strong> on <strong>{utils.displayDate(channel.create_at)}</strong></span>);
}
return (

View File

@@ -15,6 +15,7 @@ export default class RenameChannelModal extends React.Component {
this.onDisplayNameChange = this.onDisplayNameChange.bind(this);
this.displayNameKeyUp = this.displayNameKeyUp.bind(this);
this.handleClose = this.handleClose.bind(this);
this.handleShow = this.handleShow.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.state = {
@@ -59,11 +60,11 @@ export default class RenameChannelModal extends React.Component {
state.invalid = true;
} else {
let cleanedName = Utils.cleanUpUrlable(channel.name);
if (cleanedName !== channel.name) {
if (cleanedName === channel.name) {
state.nameError = '';
} else {
state.nameError = 'Must be lowercase alphanumeric characters';
state.invalid = true;
} else {
state.nameError = '';
}
}
@@ -103,7 +104,7 @@ export default class RenameChannelModal extends React.Component {
this.setState({channelName: channelName});
}
handleClose() {
this.state = {
this.setState({
displayName: '',
channelName: '',
channelId: '',
@@ -111,13 +112,14 @@ export default class RenameChannelModal extends React.Component {
nameError: '',
displayNameError: '',
invalid: false
};
});
}
handleShow(e) {
const button = $(e.relatedTarget);
this.setState({displayName: button.attr('data-display'), channelName: button.attr('data-name'), channelId: button.attr('data-channelid')});
}
componentDidMount() {
$(React.findDOMNode(this.refs.modal)).on('show.bs.modal', function handleShow(e) {
const button = $(e.relatedTarget);
this.setState({displayName: button.attr('data-display'), channelName: button.attr('data-name'), channelId: button.attr('data-channelid')});
}.bind(this));
$(React.findDOMNode(this.refs.modal)).on('show.bs.modal', this.handleShow);
$(React.findDOMNode(this.refs.modal)).on('hidden.bs.modal', this.handleClose);
}
componentWillUnmount() {

View File

@@ -29,9 +29,11 @@ export default class Sidebar extends React.Component {
this.updateUnreadIndicators = this.updateUnreadIndicators.bind(this);
this.createChannelElement = this.createChannelElement.bind(this);
this.state = this.getStateFromStores();
this.state.modal = '';
this.state.loadingDMChannel = -1;
const state = this.getStateFromStores();
state.modal = '';
state.loadingDMChannel = -1;
this.state = state;
}
getStateFromStores() {
var members = ChannelStore.getAllMembers();
@@ -65,7 +67,18 @@ export default class Sidebar extends React.Component {
var channel = ChannelStore.getByName(channelName);
if (channel != null) {
if (channel == null) {
var tempChannel = {};
tempChannel.fake = true;
tempChannel.name = channelName;
tempChannel.display_name = teammate.username;
tempChannel.teammate_username = teammate.username;
tempChannel.status = UserStore.getStatus(teammate.id);
tempChannel.last_post_at = 0;
tempChannel.total_msg_count = 0;
tempChannel.type = 'D';
readDirectChannels.push(tempChannel);
} else {
channel.display_name = teammate.username;
channel.teammate_username = teammate.username;
@@ -80,17 +93,6 @@ export default class Sidebar extends React.Component {
} else {
readDirectChannels.push(channel);
}
} else {
var tempChannel = {};
tempChannel.fake = true;
tempChannel.name = channelName;
tempChannel.display_name = teammate.username;
tempChannel.teammate_username = teammate.username;
tempChannel.status = UserStore.getStatus(teammate.id);
tempChannel.last_post_at = 0;
tempChannel.total_msg_count = 0;
tempChannel.type = 'D';
readDirectChannels.push(tempChannel);
}
}

View File

@@ -30,11 +30,11 @@ export default class SidebarRight extends React.Component {
PostStore.removeSelectedPostChangeListener(this.onSelectedChange);
}
componentDidUpdate() {
if (!this.plScrolledToBottom) {
$('.top-visible-post')[0].scrollIntoView();
} else {
if (this.plScrolledToBottom) {
var postHolder = $('.post-list-holder-by-time').not('.inactive');
postHolder.scrollTop(postHolder[0].scrollHeight);
} else {
$('.top-visible-post')[0].scrollIntoView();
}
}
onSelectedChange(fromSearch) {

View File

@@ -41,15 +41,13 @@ export default class SignupUserComplete extends React.Component {
return;
}
this.state.user.email = providedEmail;
this.state.user.username = React.findDOMNode(this.refs.name).value.trim().toLowerCase();
if (!this.state.user.username) {
const providedUsername = React.findDOMNode(this.refs.name).value.trim().toLowerCase();
if (!providedUsername) {
this.setState({nameError: 'This field is required', emailError: '', passwordError: '', serverError: ''});
return;
}
var usernameError = Utils.isValidUsername(this.state.user.username);
const usernameError = Utils.isValidUsername(this.state.user.username);
if (usernameError === 'Cannot use a reserved word as a username.') {
this.setState({nameError: 'This username is reserved, please choose a new one.', emailError: '', passwordError: '', serverError: ''});
return;
@@ -63,15 +61,24 @@ export default class SignupUserComplete extends React.Component {
return;
}
this.state.user.password = React.findDOMNode(this.refs.password).value.trim();
if (!this.state.user.password || this.state.user.password .length < 5) {
const providedPassword = React.findDOMNode(this.refs.password).value.trim();
if (!providedPassword || providedPassword.length < 5) {
this.setState({nameError: '', emailError: '', passwordError: 'Please enter at least 5 characters', serverError: ''});
return;
}
this.setState({nameError: '', emailError: '', passwordError: '', serverError: ''});
this.state.user.allow_marketing = true;
this.setState({
user: {
email: providedEmail,
username: providedUsername,
password: providedPassword,
allow_marketing: true
},
nameError: '',
emailError: '',
passwordError: '',
serverError: ''
});
client.createUser(this.state.user, this.state.data, this.state.hash,
function createUserSuccess() {

View File

@@ -23,17 +23,14 @@ export default class TeamSignupEmailItem extends React.Component {
}
if (!Utils.isEmail(email)) {
this.state.emailError = 'Please enter a valid email address';
this.setState(this.state);
this.setState({emailError: 'Please enter a valid email address'});
return false;
} else if (email === teamEmail) {
this.state.emailError = 'Please use a different email than the one used at signup';
this.setState(this.state);
this.setState({emailError: 'Please use a different email than the one used at signup'});
return false;
}
this.state.emailError = '';
this.setState(this.state);
this.setState({emailError: ''});
return true;
}
render() {

View File

@@ -36,10 +36,10 @@ export default class TeamSignupSendInvitesPage extends React.Component {
var emails = [];
for (var i = 0; i < this.props.state.invites.length; i++) {
if (!this.refs['email_' + i].validate(this.props.state.team.email)) {
valid = false;
} else {
if (this.refs['email_' + i].validate(this.props.state.team.email)) {
emails.push(this.refs['email_' + i].getValue());
} else {
valid = false;
}
}

View File

@@ -48,22 +48,20 @@ export default class TeamSignupUrlPage extends React.Component {
}
Client.findTeamByName(name,
function success(data) {
if (!data) {
this.props.state.wizard = 'send_invites';
this.props.state.team.type = 'O';
(data) => {
if (data) {
this.setState({nameError: 'This URL is unavailable. Please try another.'});
} else {
this.props.state.wizard = 'send_invites';
this.props.state.team.type = 'O';
this.props.state.team.name = name;
this.props.updateParent(this.props.state);
} else {
this.state.nameError = 'This URL is unavailable. Please try another.';
this.setState(this.state);
}
}.bind(this),
function error(err) {
this.state.nameError = err.message;
this.setState(this.state);
}.bind(this)
this.props.state.team.name = name;
this.props.updateParent(this.props.state);
}
},
(err) => {
this.setState({nameError: err.message});
}
);
}
handleFocus(e) {

View File

@@ -59,8 +59,7 @@ export default class TeamSignupWelcomePage extends React.Component {
}
}.bind(this),
function error(err) {
this.state.serverError = err.message;
this.setState(this.state);
this.setState({serverError: err.message});
}.bind(this)
);
}

View File

@@ -19,8 +19,8 @@
"babelify": "6.1.3",
"uglify-js": "2.4.24",
"watchify": "3.3.1",
"eslint": "1.3.1",
"eslint-plugin-react": "3.3.1"
"eslint": "1.6.0",
"eslint-plugin-react": "3.5.1"
},
"scripts": {
"start": "watchify --extension=jsx -o ../static/js/bundle.js -v -d ./**/*.jsx",

View File

@@ -4,7 +4,7 @@
var UserStore;
function getPrefix() {
if (!UserStore) {
UserStore = require('./user_store.jsx');
UserStore = require('./user_store.jsx'); //eslint-disable-line global-require
}
return UserStore.getCurrentId() + '_';
}

View File

@@ -10,12 +10,12 @@ var BrowserStore = require('../stores/browser_store.jsx');
var CHANGE_EVENT = 'change';
var utils;
var Utils;
function getWindowLocationOrigin() {
if (!utils) {
utils = require('../utils/utils.jsx');
if (!Utils) {
Utils = require('../utils/utils.jsx'); //eslint-disable-line global-require
}
return utils.getWindowLocationOrigin();
return Utils.getWindowLocationOrigin();
}
class TeamStoreClass extends EventEmitter {

View File

@@ -15,7 +15,7 @@ function handleError(methodName, xhr, status, err) {
var e = null;
try {
e = JSON.parse(xhr.responseText);
} catch(parseError) {
} catch (parseError) {
e = null;
}

View File

@@ -231,10 +231,10 @@ function testUrlMatch(text) {
var matchText = match.getMatchedText();
linkData.text = matchText;
if (matchText.trim().indexOf('http') !== 0) {
linkData.link = 'http://' + matchText;
} else {
if (matchText.trim().indexOf('http') === 0) {
linkData.link = matchText;
} else {
linkData.link = 'http://' + matchText;
}
result.push(linkData);
@@ -640,7 +640,7 @@ export function isValidUsername(name) {
error = 'Must be between 3 and 15 characters';
} else if (!(/^[a-z0-9\.\-\_]+$/).test(name)) {
error = "Must contain only letters, numbers, and the symbols '.', '-', and '_'.";
} else if (!(/[a-z]/).test(name.charAt(0))) {
} else if (!(/[a-z]/).test(name.charAt(0))) { //eslint-disable-line no-negated-condition
error = 'First character must be a letter.';
} else {
for (var i = 0; i < Constants.RESERVED_USERNAMES.length; i++) {