diff --git a/webapp/.eslintrc.json b/webapp/.eslintrc.json index dada7f16441b1..ad28561f1c801 100644 --- a/webapp/.eslintrc.json +++ b/webapp/.eslintrc.json @@ -59,6 +59,7 @@ "keyword-spacing": [2, {"before": true, "after": true, "overrides": {}}], "linebreak-style": 2, "lines-around-comment": [2, { "beforeBlockComment": true, "beforeLineComment": true, "allowBlockStart": true, "allowBlockEnd": true }], + "max-lines": [1, {"max": 450, "skipBlankLines": true, "skipComments": false}], "max-nested-callbacks": [1, {"max":1}], "max-nested-callbacks": [2, {"max":2}], "max-statements-per-line": [2, {"max": 1}], @@ -92,6 +93,7 @@ "no-extend-native": 2, "no-extra-bind": 2, "no-extra-label": 2, + "no-extra-parens": 0, "no-extra-semi": 2, "no-fallthrough": 2, "no-floating-decimal": 2, @@ -107,6 +109,7 @@ "no-lonely-if": 2, "no-loop-func": 2, "no-magic-numbers": [1, { "ignore": [-1, 0, 1, 2], "enforceConst": true, "detectObjects": true } ], + "no-mixed-operators": [2, {"allowSamePrecedence": false}], "no-mixed-spaces-and-tabs": 2, "no-multi-spaces": [2, { "exceptions": { "Property": false } }], "no-multi-str": 0, @@ -152,13 +155,16 @@ "no-useless-concat": 2, "no-useless-constructor": 2, "no-useless-escape": 2, + "no-useless-rename": 2, "no-var": 0, "no-void": 2, "no-warning-comments": 1, "no-whitespace-before-property": 2, "no-with": 2, + "object-curly-newline": 0, "object-curly-spacing": [2, "never"], - "object-shorthand": [1, "always"], + "object-property-newline": [2, {"allowMultiplePropertiesPerLine": true}], + "object-shorthand": [2, "always"], "one-var": [2, "never"], "one-var-declaration-per-line": 0, "operator-linebreak": [2, "after"], @@ -189,9 +195,11 @@ "react/jsx-no-target-blank": 2, "react/jsx-no-undef": 2, "react/jsx-pascal-case": 2, + "react/jsx-filename-extension": 2, "react/jsx-space-before-closing": [2, "never"], "react/jsx-uses-react": 2, "react/jsx-uses-vars": 2, + "react/no-comment-textnodes": 2, "react/no-danger": 0, "react/no-deprecated": 2, "react/no-did-mount-set-state": 2, @@ -199,17 +207,20 @@ "react/no-direct-mutation-state": 2, "react/no-is-mounted": 2, "react/no-multi-comp": [2, { "ignoreStateless": true }], + "react/no-render-return-value": 2, "react/no-set-state": 0, "react/no-string-refs": 0, "react/no-unknown-property": 2, "react/prefer-es6-class": 2, "react/prefer-stateless-function": 0, "react/prop-types": 2, + "react/require-optimization": 1, "react/require-render-return": 2, "react/self-closing-comp": 2, "react/sort-comp": 0, "react/wrap-multilines": 2, "require-yield": 2, + "rest-spread-spacing": [2, "never"], "semi": [2, "always"], "semi-spacing": [2, {"before": false, "after": true}], "sort-imports": 0, diff --git a/webapp/components/admin_console/admin_settings.jsx b/webapp/components/admin_console/admin_settings.jsx index e11d843a7e04e..e29be33d1788e 100644 --- a/webapp/components/admin_console/admin_settings.jsx +++ b/webapp/components/admin_console/admin_settings.jsx @@ -106,11 +106,6 @@ export default class AdminSettings extends React.Component { } render() { - let saveClass = 'btn'; - if (this.state.saveNeeded) { - saveClass += 'btn-primary'; - } - return (
{this.renderTitle()} diff --git a/webapp/components/create_comment.jsx b/webapp/components/create_comment.jsx index f7564f3965535..1f21febf1c50d 100644 --- a/webapp/components/create_comment.jsx +++ b/webapp/components/create_comment.jsx @@ -181,7 +181,7 @@ class CreateComment extends React.Component { } commentMsgKeyPress(e) { - if (this.state.ctrlSend && e.ctrlKey || !this.state.ctrlSend) { + if ((this.state.ctrlSend && e.ctrlKey) || !this.state.ctrlSend) { if (e.which === KeyCodes.ENTER && !e.shiftKey && !e.altKey) { e.preventDefault(); ReactDOM.findDOMNode(this.refs.textbox).blur(); @@ -313,7 +313,7 @@ class CreateComment extends React.Component { draft.uploadsInProgress = uploadsInProgress; PostStore.storeCommentDraft(this.props.rootId, draft); - this.setState({previews: previews, uploadsInProgress: uploadsInProgress}); + this.setState({previews, uploadsInProgress}); } componentWillReceiveProps(newProps) { diff --git a/webapp/components/create_post.jsx b/webapp/components/create_post.jsx index 508fb36cb77f7..5101c751d3613 100644 --- a/webapp/components/create_post.jsx +++ b/webapp/components/create_post.jsx @@ -212,7 +212,7 @@ class CreatePost extends React.Component { } postMsgKeyPress(e) { - if (this.state.ctrlSend && e.ctrlKey || !this.state.ctrlSend) { + if ((this.state.ctrlSend && e.ctrlKey) || !this.state.ctrlSend) { if (e.which === KeyCodes.ENTER && !e.shiftKey && !e.altKey) { e.preventDefault(); ReactDOM.findDOMNode(this.refs.textbox).blur(); diff --git a/webapp/components/file_upload.jsx b/webapp/components/file_upload.jsx index 2f485d4d387be..1a3c6eadc87c3 100644 --- a/webapp/components/file_upload.jsx +++ b/webapp/components/file_upload.jsx @@ -282,7 +282,8 @@ class FileUpload extends React.Component { keyUpload(e) { if (Utils.cmdOrCtrlPressed(e) && e.keyCode === Constants.KeyCodes.U) { e.preventDefault(); - if (this.props.postType === 'post' && document.activeElement.id === 'post_textbox' || this.props.postType === 'comment' && document.activeElement.id === 'reply_textbox') { + if ((this.props.postType === 'post' && document.activeElement.id === 'post_textbox') || + (this.props.postType === 'comment' && document.activeElement.id === 'reply_textbox')) { $(this.refs.fileInput).focus().trigger('click'); } } diff --git a/webapp/components/invite_member_modal.jsx b/webapp/components/invite_member_modal.jsx index 265a421b600f3..68a7b7b15a726 100644 --- a/webapp/components/invite_member_modal.jsx +++ b/webapp/components/invite_member_modal.jsx @@ -131,7 +131,7 @@ class InviteMemberModal extends React.Component { invites.push(invite); } - this.setState({emailErrors: emailErrors, firstNameErrors: firstNameErrors, lastNameErrors: lastNameErrors}); + this.setState({emailErrors, firstNameErrors, lastNameErrors}); if (!valid || invites.length === 0) { return; @@ -151,7 +151,7 @@ class InviteMemberModal extends React.Component { (err) => { if (err.id === 'api.team.invite_members.already.app_error') { emailErrors[err.detailed_error] = err.message; - this.setState({emailErrors: emailErrors}); + this.setState({emailErrors}); } else { this.setState({serverError: err.message}); } @@ -193,7 +193,7 @@ class InviteMemberModal extends React.Component { var count = this.state.idCount + 1; var inviteIds = this.state.inviteIds; inviteIds.push(count); - this.setState({inviteIds: inviteIds, idCount: count}); + this.setState({inviteIds, idCount: count}); } clearFields() { @@ -225,7 +225,7 @@ class InviteMemberModal extends React.Component { if (!inviteIds.length) { inviteIds.push(++count); } - this.setState({inviteIds: inviteIds, idCount: count}); + this.setState({inviteIds, idCount: count}); } showGetTeamInviteLinkModal() { @@ -435,7 +435,7 @@ class InviteMemberModal extends React.Component { id='invite_member.teamInviteLink' defaultMessage='You can also invite people using the {link}.' values={{ - link: (link) + link }} />

diff --git a/webapp/components/msg_typing.jsx b/webapp/components/msg_typing.jsx index 631eea78dbe9c..f6a6d12b28121 100644 --- a/webapp/components/msg_typing.jsx +++ b/webapp/components/msg_typing.jsx @@ -71,7 +71,7 @@ class MsgTyping extends React.Component { defaultMessage='{users} and {last} are typing...' values={{ users: (users.join(', ')), - last: (last) + last }} /> ); diff --git a/webapp/components/navbar.jsx b/webapp/components/navbar.jsx index 44730f4e271cc..c2d262819c276 100644 --- a/webapp/components/navbar.jsx +++ b/webapp/components/navbar.jsx @@ -636,7 +636,7 @@ export default class Navbar extends React.Component { defaultMessage='No channel header yet.{newline}{link} to add one.' values={{ newline: (
), - link: (link) + link }} />
diff --git a/webapp/components/removed_from_channel_modal.jsx b/webapp/components/removed_from_channel_modal.jsx index 3164e4e3ff425..3bdceadf715fc 100644 --- a/webapp/components/removed_from_channel_modal.jsx +++ b/webapp/components/removed_from_channel_modal.jsx @@ -116,7 +116,7 @@ export default class RemovedFromChannelModal extends React.Component { id='removed_channel.remover' defaultMessage='{remover} removed you from {channel}' values={{ - remover: (remover), + remover, channel: (channelName) }} /> diff --git a/webapp/components/rename_channel_modal.jsx b/webapp/components/rename_channel_modal.jsx index df08bdbc6374e..4dc84d9716dd7 100644 --- a/webapp/components/rename_channel_modal.jsx +++ b/webapp/components/rename_channel_modal.jsx @@ -203,7 +203,7 @@ export default class RenameChannelModal extends React.Component { const displayName = ReactDOM.findDOMNode(this.refs.displayName).value.trim(); const channelName = Utils.cleanUpUrlable(displayName); ReactDOM.findDOMNode(this.refs.channelName).value = channelName; - this.setState({channelName: channelName}); + this.setState({channelName}); } } diff --git a/webapp/components/suggestion/suggestion_list.jsx b/webapp/components/suggestion/suggestion_list.jsx index f1cccf8aa4e1d..52b85b2f563de 100644 --- a/webapp/components/suggestion/suggestion_list.jsx +++ b/webapp/components/suggestion/suggestion_list.jsx @@ -87,7 +87,7 @@ export default class SuggestionList extends React.Component { content.scrollTop(itemTop - contentTopPadding); } else if (itemBottom + contentTopPadding + contentBottomPadding > contentTop + visibleContentHeight) { // the item has gone off the bottom of the visible space - content.scrollTop(itemBottom - visibleContentHeight + contentTopPadding + contentBottomPadding); + content.scrollTop((itemBottom - visibleContentHeight) + contentTopPadding + contentBottomPadding); } } } diff --git a/webapp/components/user_settings/user_settings_general.jsx b/webapp/components/user_settings/user_settings_general.jsx index a449c7d013fb5..9b0e6a204380d 100644 --- a/webapp/components/user_settings/user_settings_general.jsx +++ b/webapp/components/user_settings/user_settings_general.jsx @@ -295,8 +295,17 @@ class UserSettingsGeneralTab extends React.Component { setupInitialState(props) { const user = props.user; - return {username: user.username, firstName: user.first_name, lastName: user.last_name, nickname: user.nickname, - email: user.email, confirmEmail: '', picture: null, loadingPicture: false, emailChangeInProgress: false}; + return { + username: user.username, + firstName: user.first_name, + lastName: user.last_name, + nickname: user.nickname, + email: user.email, + confirmEmail: '', + picture: null, + loadingPicture: false, + emailChangeInProgress: false + }; } createEmailSection() { diff --git a/webapp/package.json b/webapp/package.json index 984affd08afe8..fbf877e56044f 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -35,7 +35,7 @@ "velocity-animate": "1.2.3" }, "devDependencies": { - "babel-eslint": "6.0.4", + "babel-eslint": "6.1.2", "babel-loader": "6.2.4", "babel-plugin-transform-runtime": "6.8.0", "babel-polyfill": "6.8.0", @@ -44,8 +44,8 @@ "babel-preset-stage-0": "6.5.0", "copy-webpack-plugin": "2.1.3", "css-loader": "0.23.1", - "eslint": "2.9.0", - "eslint-plugin-react": "5.1.1", + "eslint": "3.0.1", + "eslint-plugin-react": "5.2.2", "exports-loader": "0.6.3", "extract-text-webpack-plugin": "1.0.1", "file-loader": "0.8.5", diff --git a/webapp/utils/channel_intro_messages.jsx b/webapp/utils/channel_intro_messages.jsx index 9a232dbc01d4a..6418615a4b095 100644 --- a/webapp/utils/channel_intro_messages.jsx +++ b/webapp/utils/channel_intro_messages.jsx @@ -194,7 +194,7 @@ export function createStandardIntroMessage(channel, centeredIntro) { values={{ name: (uiName), type: (uiType), - date: (date) + date }} /> ); @@ -207,7 +207,7 @@ export function createStandardIntroMessage(channel, centeredIntro) { values={{ name: (uiName), type: (uiType), - date: (date), + date, creator: creatorName }} /> diff --git a/webapp/utils/utils.jsx b/webapp/utils/utils.jsx index bb17c2fdc0188..c3e55a64f0c17 100644 --- a/webapp/utils/utils.jsx +++ b/webapp/utils/utils.jsx @@ -139,7 +139,7 @@ export function notifyMe(title, body, channel, teamId) { Notification.requestPermission((permission) => { if (permission === 'granted') { try { - var notification = new Notification(title, {body: body, tag: body, icon: icon50}); + var notification = new Notification(title, {body, tag: body, icon: icon50}); notification.onclick = () => { window.focus(); if (channel) { @@ -413,7 +413,7 @@ export function insertHtmlEntities(text) { export function searchForTerm(term) { AppDispatcher.handleServerAction({ type: ActionTypes.RECEIVED_SEARCH_TERM, - term: term, + term, do_search: true }); } @@ -494,7 +494,7 @@ export function splitFileLocation(fileLocation) { var filePath = fileSplit.join('.'); var filename = filePath.split('/')[filePath.split('/').length - 1]; - return {ext: ext, name: filename, path: filePath}; + return {ext, name: filename, path: filePath}; } export function getPreviewImagePath(filename) { @@ -1079,7 +1079,7 @@ export function generateId() { if (c === 'x') { v = r; } else { - v = r & 0x3 | 0x8; + v = (r & 0x3) | 0x8; } return v.toString(16);