diff --git a/app/assets/javascripts/admin/controllers/admin-user-badges.js.es6 b/app/assets/javascripts/admin/controllers/admin-user-badges.js.es6 index 5e6bb325f..523668556 100644 --- a/app/assets/javascripts/admin/controllers/admin-user-badges.js.es6 +++ b/app/assets/javascripts/admin/controllers/admin-user-badges.js.es6 @@ -1,12 +1,3 @@ -/** - This controller supports the interface for granting and revoking badges from - individual users. - - @class AdminUserBadgesController - @extends Ember.ArrayController - @namespace Discourse - @module Discourse -**/ export default Ember.ArrayController.extend({ needs: ["adminUser"], user: Em.computed.alias('controllers.adminUser'), @@ -14,12 +5,12 @@ export default Ember.ArrayController.extend({ sortAscending: false, groupedBadges: function(){ - const badges = this.get('model'); + const allBadges = this.get('model'); - var grouped = _.groupBy(badges, badge => badge.badge_id); + var grouped = _.groupBy(allBadges, badge => badge.badge_id); var expanded = []; - const expandedBadges = badges.get('expandedBadges'); + const expandedBadges = allBadges.get('expandedBadges'); _(grouped).each(function(badges){ var lastGranted = badges[0].granted_at; diff --git a/app/assets/javascripts/discourse/components/navigation-bar.js.es6 b/app/assets/javascripts/discourse/components/navigation-bar.js.es6 index a7ceba10c..46fc846db 100644 --- a/app/assets/javascripts/discourse/components/navigation-bar.js.es6 +++ b/app/assets/javascripts/discourse/components/navigation-bar.js.es6 @@ -8,8 +8,8 @@ export default Ember.Component.extend({ const filterMode = this.get('filterMode'), navItems = this.get('navItems'); - var item = navItems.find(function(item){ - return item.get('filterMode').indexOf(filterMode) === 0; + var item = navItems.find(function(i){ + return i.get('filterMode').indexOf(filterMode) === 0; }); return item || navItems[0]; diff --git a/app/assets/javascripts/discourse/components/topic-list.js.es6 b/app/assets/javascripts/discourse/components/topic-list.js.es6 index 865f5fb9a..2cc0747b0 100644 --- a/app/assets/javascripts/discourse/components/topic-list.js.es6 +++ b/app/assets/javascripts/discourse/components/topic-list.js.es6 @@ -45,8 +45,8 @@ export default Ember.Component.extend({ this.rerender(); }); - on('th.sortable', function(e){ - this.sendAction('changeSort', e.data('sort-order')); + on('th.sortable', function(e2){ + this.sendAction('changeSort', e2.data('sort-order')); this.rerender(); }); } diff --git a/app/assets/javascripts/discourse/helpers/application.js.es6 b/app/assets/javascripts/discourse/helpers/application.js.es6 index 35c4f6493..cac2ea1f0 100644 --- a/app/assets/javascripts/discourse/helpers/application.js.es6 +++ b/app/assets/javascripts/discourse/helpers/application.js.es6 @@ -19,8 +19,8 @@ Em.Handlebars.helper('bound-avatar', function(user, size, uploadId) { /* * Used when we only have a template */ -Em.Handlebars.helper('bound-avatar-template', function(avatarTemplate, size) { - return new safe(Discourse.Utilities.avatarImg({ size: size, avatarTemplate: avatarTemplate })); +Em.Handlebars.helper('bound-avatar-template', function(at, size) { + return new safe(Discourse.Utilities.avatarImg({ size: size, avatarTemplate: at })); }); registerUnbound('raw-date', function(dt) { diff --git a/app/assets/javascripts/discourse/initializers/banner.js.es6 b/app/assets/javascripts/discourse/initializers/banner.js.es6 index a7dd7b61e..f8bf99e55 100644 --- a/app/assets/javascripts/discourse/initializers/banner.js.es6 +++ b/app/assets/javascripts/discourse/initializers/banner.js.es6 @@ -12,8 +12,8 @@ export default { const messageBus = container.lookup('message-bus:main'); if (!messageBus) { return; } - messageBus.subscribe("/site/banner", function (banner) { - site.set("banner", Em.Object.create(banner)); + messageBus.subscribe("/site/banner", function (ban) { + site.set("banner", Em.Object.create(ban)); }); } }; diff --git a/app/assets/javascripts/discourse/lib/after-transition.js.es6 b/app/assets/javascripts/discourse/lib/after-transition.js.es6 index 30cc3054f..11fe20b5e 100644 --- a/app/assets/javascripts/discourse/lib/after-transition.js.es6 +++ b/app/assets/javascripts/discourse/lib/after-transition.js.es6 @@ -12,7 +12,7 @@ var dummy = document.createElement("div"), ms: "MSTransitionEnd" }; -var transitionEnd = function() { +var transitionEnd = (function() { var retValue; retValue = "transitionend"; Object.keys(eventNameHash).some(function(vendor) { @@ -22,7 +22,7 @@ var transitionEnd = function() { } }); return retValue; -}(); +})(); export default function (element, callback) { return $(element).on(transitionEnd, callback); diff --git a/app/assets/javascripts/discourse/lib/autocomplete.js.es6 b/app/assets/javascripts/discourse/lib/autocomplete.js.es6 index d3f2ea0d1..aeca46186 100644 --- a/app/assets/javascripts/discourse/lib/autocomplete.js.es6 +++ b/app/assets/javascripts/discourse/lib/autocomplete.js.es6 @@ -290,7 +290,7 @@ export default function(options) { }); $(this).on('keydown.autocomplete', function(e) { - var c, caretPosition, i, initial, next, prev, prevIsGood, stopFound, term, total, userToComplete; + var c, caretPosition, i, initial, prev, prevIsGood, stopFound, term, total, userToComplete; if(e.ctrlKey || e.altKey || e.metaKey){ return true; @@ -322,7 +322,6 @@ export default function(options) { if (e.which === keys.shift) return; if ((completeStart === null) && e.which === keys.backSpace && options.key) { c = Discourse.Utilities.caretPosition(me[0]); - next = me[0].value[c]; c -= 1; initial = c; prevIsGood = true; diff --git a/app/assets/javascripts/discourse/lib/avatar-template.js.es6 b/app/assets/javascripts/discourse/lib/avatar-template.js.es6 index 28032d2a4..16b70cadc 100644 --- a/app/assets/javascripts/discourse/lib/avatar-template.js.es6 +++ b/app/assets/javascripts/discourse/lib/avatar-template.js.es6 @@ -1,3 +1,4 @@ +/*eslint no-bitwise:0 */ let _splitAvatars; function defaultAvatar(username) { diff --git a/app/assets/javascripts/discourse/lib/emoji/emoji-toolbar.js.es6 b/app/assets/javascripts/discourse/lib/emoji/emoji-toolbar.js.es6 index c5b731da0..7ea7a7b02 100644 --- a/app/assets/javascripts/discourse/lib/emoji/emoji-toolbar.js.es6 +++ b/app/assets/javascripts/discourse/lib/emoji/emoji-toolbar.js.es6 @@ -186,8 +186,8 @@ var bindEvents = function(page,offset){ }); $('.emoji-modal .toolbar a').click(function(){ - var page = parseInt($(this).data('group-id')); - render(page,0); + var p = parseInt($(this).data('group-id')); + render(p, 0); return false; }); }; diff --git a/app/assets/javascripts/discourse/models/post-stream.js.es6 b/app/assets/javascripts/discourse/models/post-stream.js.es6 index d8549b4ba..9f625f347 100644 --- a/app/assets/javascripts/discourse/models/post-stream.js.es6 +++ b/app/assets/javascripts/discourse/models/post-stream.js.es6 @@ -234,12 +234,12 @@ const PostStream = RestModel.extend({ this.set('gaps', this.get('gaps') || {before: {}, after: {}}); const before = this.get('gaps.before'); - const post = posts.find(function(post){ - return post.get('post_number') > to; + const post = posts.find(function(p){ + return p.get('post_number') > to; }); - before[post.get('id')] = remove.map(function(post){ - return post.get('id'); + before[post.get('id')] = remove.map(function(p){ + return p.get('id'); }); post.set('hasGap', true); @@ -491,8 +491,8 @@ const PostStream = RestModel.extend({ // we need to zip this into the stream let index = 0; - stream.forEach(function(postId){ - if(postId < p.id){ + stream.forEach(function(pid){ + if (pid < p.id){ index+= 1; } }); diff --git a/app/assets/javascripts/discourse/models/post.js.es6 b/app/assets/javascripts/discourse/models/post.js.es6 index 878ce21c0..c8c4b400f 100644 --- a/app/assets/javascripts/discourse/models/post.js.es6 +++ b/app/assets/javascripts/discourse/models/post.js.es6 @@ -3,6 +3,7 @@ import { popupAjaxError } from 'discourse/lib/ajax-error'; import ActionSummary from 'discourse/models/action-summary'; import { url, fmt, propertyEqual } from 'discourse/lib/computed'; import Quote from 'discourse/lib/quote'; +import computed from 'ember-addons/ember-computed-decorators'; const Post = RestModel.extend({ @@ -54,10 +55,10 @@ const Post = RestModel.extend({ }.property('post_number', 'topic_id', 'topic.slug'), // Don't drop the /1 - urlWithNumber: function() { - const url = this.get('url'); - return (this.get('post_number') === 1) ? url + "/1" : url; - }.property('post_number', 'url'), + @computed('post_number', 'url') + urlWithNumber(postNumber, postUrl) { + return postNumber === 1 ? postUrl + "/1" : postUrl; + }, usernameUrl: url('username', '/users/%@'), diff --git a/app/assets/javascripts/discourse/models/user-stream.js.es6 b/app/assets/javascripts/discourse/models/user-stream.js.es6 index 71d1bba89..fe20fe7c5 100644 --- a/app/assets/javascripts/discourse/models/user-stream.js.es6 +++ b/app/assets/javascripts/discourse/models/user-stream.js.es6 @@ -54,18 +54,18 @@ export default RestModel.extend({ findItems() { const self = this; - let url = this.get('baseUrl'); + let findUrl = this.get('baseUrl'); if (this.get('filterParam')) { - url += "&filter=" + this.get('filterParam'); + findUrl += "&filter=" + this.get('filterParam'); } // Don't load the same stream twice. We're probably at the end. const lastLoadedUrl = this.get('lastLoadedUrl'); - if (lastLoadedUrl === url) { return Ember.RSVP.resolve(); } + if (lastLoadedUrl === findUrl) { return Ember.RSVP.resolve(); } if (this.get('loading')) { return Ember.RSVP.resolve(); } this.set('loading', true); - return Discourse.ajax(url, {cache: 'false'}).then( function(result) { + return Discourse.ajax(findUrl, {cache: 'false'}).then( function(result) { if (result && result.user_actions) { const copy = Em.A(); result.user_actions.forEach(function(action) { @@ -81,7 +81,7 @@ export default RestModel.extend({ } }).finally(function() { self.set('loading', false); - self.set('lastLoadedUrl', url); + self.set('lastLoadedUrl', findUrl); }); } diff --git a/app/assets/javascripts/discourse/models/user.js.es6 b/app/assets/javascripts/discourse/models/user.js.es6 index 669a3853b..e270aaff7 100644 --- a/app/assets/javascripts/discourse/models/user.js.es6 +++ b/app/assets/javascripts/discourse/models/user.js.es6 @@ -5,6 +5,7 @@ import UserStream from 'discourse/models/user-stream'; import UserPostsStream from 'discourse/models/user-posts-stream'; import Singleton from 'discourse/mixins/singleton'; import { longDate } from 'discourse/lib/formatter'; +import computed from 'ember-addons/ember-computed-decorators'; const User = RestModel.extend({ @@ -53,17 +54,11 @@ const User = RestModel.extend({ return this.get('username'); }.property('username', 'name'), - /** - This user's profile background(in CSS). - - @property profileBackground - @type {String} - **/ - profileBackground: function() { - var url = this.get('profile_background'); - if (Em.isEmpty(url) || !Discourse.SiteSettings.allow_profile_backgrounds) { return; } - return ('background-image: url(' + Discourse.getURLWithCDN(url) + ')').htmlSafe(); - }.property('profile_background'), + @computed('profile_background') + profileBackground(bgUrl) { + if (Em.isEmpty(bgUrl) || !Discourse.SiteSettings.allow_profile_backgrounds) { return; } + return ('background-image: url(' + Discourse.getURLWithCDN(bgUrl) + ')').htmlSafe(); + }, /** Path to this user. @@ -206,10 +201,10 @@ const User = RestModel.extend({ return Discourse.ajax("/users/" + this.get('username_lower'), { data: data, type: 'PUT' - }).then(function(data) { - self.set('bio_excerpt',data.user.bio_excerpt); + }).then(function(result) { + self.set('bio_excerpt', result.user.bio_excerpt); - var userProps = self.getProperties('enable_quoting', 'external_links_in_new_tab', 'dynamic_favicon'); + const userProps = self.getProperties('enable_quoting', 'external_links_in_new_tab', 'dynamic_favicon'); Discourse.User.current().setProperties(userProps); }).finally(() => { this.set('isSaving', false); diff --git a/app/assets/javascripts/discourse/routes/build-topic-route.js.es6 b/app/assets/javascripts/discourse/routes/build-topic-route.js.es6 index 69cd2e5c2..185c2fd52 100644 --- a/app/assets/javascripts/discourse/routes/build-topic-route.js.es6 +++ b/app/assets/javascripts/discourse/routes/build-topic-route.js.es6 @@ -86,9 +86,9 @@ export default function(filter, extras) { ScreenTrack.current().stop(); const findOpts = filterQueryParams(transition.queryParams), - extras = { cached: this.isPoppedState(transition) }; + findExtras = { cached: this.isPoppedState(transition) }; - return findTopicList(this.store, filter, findOpts, extras); + return findTopicList(this.store, filter, findOpts, findExtras); }, titleToken() { diff --git a/app/assets/javascripts/discourse/routes/discourse.js.es6 b/app/assets/javascripts/discourse/routes/discourse.js.es6 index a6bba2cb6..20ce38f40 100644 --- a/app/assets/javascripts/discourse/routes/discourse.js.es6 +++ b/app/assets/javascripts/discourse/routes/discourse.js.es6 @@ -13,7 +13,7 @@ const DiscourseRoute = Ember.Route.extend({ params = this.controller.getProperties(Object.keys(this.queryParams)); model.set('loading', true); - this.model(params).then(model => this.setupController(controller, model)); + this.model(params).then(m => this.setupController(controller, m)); } }, diff --git a/app/assets/javascripts/discourse/routes/user.js.es6 b/app/assets/javascripts/discourse/routes/user.js.es6 index 832e1cb0e..cfbbf173e 100644 --- a/app/assets/javascripts/discourse/routes/user.js.es6 +++ b/app/assets/javascripts/discourse/routes/user.js.es6 @@ -31,7 +31,7 @@ export default Discourse.Route.extend({ willTransition(transition) { // will reset the indexStream when transitioning to routes that aren't "indexStream" // otherwise the "header" will jump - const isIndexStream = ~INDEX_STREAM_ROUTES.indexOf(transition.targetName); + const isIndexStream = INDEX_STREAM_ROUTES.indexOf(transition.targetName) !== -1; this.controllerFor('user').set('indexStream', isIndexStream); return true; } diff --git a/app/assets/javascripts/discourse/views/cloaked-collection.js.es6 b/app/assets/javascripts/discourse/views/cloaked-collection.js.es6 index 03a121efe..f65666c78 100644 --- a/app/assets/javascripts/discourse/views/cloaked-collection.js.es6 +++ b/app/assets/javascripts/discourse/views/cloaked-collection.js.es6 @@ -1,3 +1,4 @@ +/*eslint no-bitwise:0 */ import CloakedView from 'discourse/views/cloaked'; const CloakedCollectionView = Ember.CollectionView.extend({ diff --git a/app/assets/javascripts/discourse/views/composer.js.es6 b/app/assets/javascripts/discourse/views/composer.js.es6 index b48964e27..22ab46f0f 100644 --- a/app/assets/javascripts/discourse/views/composer.js.es6 +++ b/app/assets/javascripts/discourse/views/composer.js.es6 @@ -217,7 +217,7 @@ const ComposerView = Ember.View.extend(Ember.Evented, { initEditor() { // not quite right, need a callback to pass in, meaning this gets called once, // but if you start replying to another topic it will get the avatars wrong - let $wmdInput, editor; + let $wmdInput; const self = this; this.wmdInput = $wmdInput = this.$('.wmd-input'); if ($wmdInput.length === 0 || $wmdInput.data('init') === true) return; @@ -243,7 +243,7 @@ const ComposerView = Ember.View.extend(Ember.Evented, { } }); - this.editor = editor = Discourse.Markdown.createEditor({ + this.editor = Discourse.Markdown.createEditor({ containerElement: this.element, lookupAvatarByPostNumber(postNumber, topicId) { const posts = self.get('controller.controllers.topic.model.postStream.posts'); diff --git a/app/assets/javascripts/discourse/views/header.js.es6 b/app/assets/javascripts/discourse/views/header.js.es6 index 281f6bd86..310a06604 100644 --- a/app/assets/javascripts/discourse/views/header.js.es6 +++ b/app/assets/javascripts/discourse/views/header.js.es6 @@ -55,7 +55,6 @@ export default Ember.View.extend({ $li.removeClass('active'); $html.data('hide-dropdown', null); - const controller = self.get('controller'); if (controller && !controller.isDestroyed){ controller.set('visibleDropdown', null); } diff --git a/app/assets/javascripts/discourse/views/post.js.es6 b/app/assets/javascripts/discourse/views/post.js.es6 index eff4293ba..ad9963aab 100644 --- a/app/assets/javascripts/discourse/views/post.js.es6 +++ b/app/assets/javascripts/discourse/views/post.js.es6 @@ -256,8 +256,8 @@ const PostView = Discourse.GroupedView.extend(Ember.Evented, { // Unless it's a full quote, allow click to expand if (!($aside.data('full') || $title.data('has-quote-controls'))) { - $title.on('click', function(e) { - if ($(e.target).is('a')) return true; + $title.on('click', function(e2) { + if ($(e2.target).is('a')) return true; self._toggleQuote($aside); }); $title.data('has-quote-controls', true); diff --git a/lib/tasks/docker.rake b/lib/tasks/docker.rake index 66f0660ca..c53ade086 100644 --- a/lib/tasks/docker.rake +++ b/lib/tasks/docker.rake @@ -34,8 +34,10 @@ task 'docker:test' do @good &&= run_or_fail("bundle exec rspec") end unless ENV["RUBY_ONLY"] + @good &&= run_or_fail("eslint app/assets/javascripts") @good &&= run_or_fail("eslint --ext \".es6\" app/assets/javascripts") @good &&= run_or_fail("eslint --ext \".es6\" test/javascripts") + @good &&= run_or_fail("eslint test/javascripts") @good &&= run_or_fail("bundle exec rake qunit:test") end diff --git a/test/javascripts/components/keyboard-shortcuts-test.js.es6 b/test/javascripts/components/keyboard-shortcuts-test.js.es6 index 40753a347..c21b8038c 100644 --- a/test/javascripts/components/keyboard-shortcuts-test.js.es6 +++ b/test/javascripts/components/keyboard-shortcuts-test.js.es6 @@ -93,8 +93,8 @@ _.each(clickBindings, function(selector, binding) { ok(true, selector + " was clicked"); }); - _.each(bindings, function(binding) { - testMouseTrap.trigger(binding); + _.each(bindings, function(b) { + testMouseTrap.trigger(b); }, this); }); }); diff --git a/test/javascripts/controllers/create-account-test.js.es6 b/test/javascripts/controllers/create-account-test.js.es6 index ab3244915..4c202880a 100644 --- a/test/javascripts/controllers/create-account-test.js.es6 +++ b/test/javascripts/controllers/create-account-test.js.es6 @@ -37,10 +37,10 @@ test('passwordValidation', function() { equal(controller.get('passwordValidation.reason'), I18n.t('user.password.ok'), 'Password is valid'); var testInvalidPassword = function(password, expectedReason) { - var controller = subject(); - controller.set('accountPassword', password); - equal(controller.get('passwordValidation.failed'), true, 'password should be invalid: ' + password); - equal(controller.get('passwordValidation.reason'), expectedReason, 'password validation reason: ' + password + ', ' + expectedReason); + var c = subject(); + c.set('accountPassword', password); + equal(c.get('passwordValidation.failed'), true, 'password should be invalid: ' + password); + equal(c.get('passwordValidation.reason'), expectedReason, 'password validation reason: ' + password + ', ' + expectedReason); }; testInvalidPassword('', undefined);