diff --git a/Gemfile b/Gemfile index 9d85677d9d8..5673b004978 100644 --- a/Gemfile +++ b/Gemfile @@ -49,7 +49,7 @@ gem 'onebox', '1.8.86' gem 'http_accept_language', '~>2.0.5', require: false gem 'ember-rails', '0.18.5' -gem 'discourse-ember-source', '~> 3.7.0' +gem 'discourse-ember-source', '~> 3.8.0' gem 'ember-handlebars-template', '0.8.0' gem 'barber' diff --git a/Gemfile.lock b/Gemfile.lock index ba914300e7f..8f7e311e88c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -108,7 +108,7 @@ GEM terminal-table (~> 1) debug_inspector (0.0.3) diff-lcs (1.3) - discourse-ember-source (3.7.0.2) + discourse-ember-source (3.8.0.1) discourse_image_optim (0.26.2) exifr (~> 1.2, >= 1.2.2) fspath (~> 3.0) @@ -472,7 +472,7 @@ DEPENDENCIES colored2 cppjieba_rb danger - discourse-ember-source (~> 3.7.0) + discourse-ember-source (~> 3.8.0) discourse_image_optim email_reply_trimmer (~> 0.1) ember-handlebars-template (= 0.8.0) diff --git a/app/assets/javascripts/admin/components/resumable-upload.js.es6 b/app/assets/javascripts/admin/components/resumable-upload.js.es6 index e462d9e32c4..c097a713dc9 100644 --- a/app/assets/javascripts/admin/components/resumable-upload.js.es6 +++ b/app/assets/javascripts/admin/components/resumable-upload.js.es6 @@ -1,5 +1,6 @@ import { iconHTML } from "discourse-common/lib/icon-library"; import { bufferedRender } from "discourse-common/lib/buffered-render"; +import computed from "ember-addons/ember-computed-decorators"; /*global Resumable:true */ @@ -27,18 +28,19 @@ export default Ember.Component.extend( rerenderTriggers: ["isUploading", "progress"], - translatedTitle: function() { - const title = this.get("title"); - return title ? I18n.t(title) : this.get("text"); - }.property("title", "text"), + @computed("title", "text") + translatedTitle(title, text) { + return title ? I18n.t(title) : text; + }, - text: function() { - if (this.get("isUploading")) { - return this.get("progress") + " %"; + @computed("isUploading", "progress") + text(isUploading, progress) { + if (isUploading) { + return progress + " %"; } else { return this.get("uploadText"); } - }.property("isUploading", "progress"), + }, buildBuffer(buffer) { const icon = this.get("isUploading") ? "times" : "upload"; diff --git a/app/assets/javascripts/admin/controllers/admin-badges-show.js.es6 b/app/assets/javascripts/admin/controllers/admin-badges-show.js.es6 index 5bf29b07883..d7e80054325 100644 --- a/app/assets/javascripts/admin/controllers/admin-badges-show.js.es6 +++ b/app/assets/javascripts/admin/controllers/admin-badges-show.js.es6 @@ -1,6 +1,7 @@ import { popupAjaxError } from "discourse/lib/ajax-error"; import { bufferedProperty } from "discourse/mixins/buffered-content"; import { propertyNotEqual } from "discourse/lib/computed"; +import computed from "ember-addons/ember-computed-decorators"; export default Ember.Controller.extend(bufferedProperty("model"), { adminBadges: Ember.inject.controller(), @@ -17,14 +18,13 @@ export default Ember.Controller.extend(bufferedProperty("model"), { readOnly: Ember.computed.alias("buffered.system"), showDisplayName: propertyNotEqual("name", "displayName"), - hasQuery: function() { - const bQuery = this.get("buffered.query"); - if (bQuery) { - return bQuery.trim().length > 0; + @computed("model.query", "buffered.query") + hasQuery(modelQuery, bufferedQuery) { + if (bufferedQuery) { + return bufferedQuery.trim().length > 0; } - const mQuery = this.get("model.query"); - return mQuery && mQuery.trim().length > 0; - }.property("model.query", "buffered.query"), + return modelQuery && modelQuery.trim().length > 0; + }, _resetSaving: function() { this.set("saving", false); diff --git a/app/assets/javascripts/admin/controllers/admin-customize-email-templates-edit.js.es6 b/app/assets/javascripts/admin/controllers/admin-customize-email-templates-edit.js.es6 index 5a20a94cbfb..3fafd28e557 100644 --- a/app/assets/javascripts/admin/controllers/admin-customize-email-templates-edit.js.es6 +++ b/app/assets/javascripts/admin/controllers/admin-customize-email-templates-edit.js.es6 @@ -1,17 +1,18 @@ import { popupAjaxError } from "discourse/lib/ajax-error"; import { bufferedProperty } from "discourse/mixins/buffered-content"; +import computed from "ember-addons/ember-computed-decorators"; export default Ember.Controller.extend(bufferedProperty("emailTemplate"), { saved: false, - hasMultipleSubjects: function() { - const buffered = this.get("buffered"); + @computed("buffered") + hasMultipleSubjects(buffered) { if (buffered.getProperties("subject")["subject"]) { return false; } else { return buffered.getProperties("id")["id"]; } - }.property("buffered"), + }, actions: { saveChanges() { diff --git a/app/assets/javascripts/admin/controllers/admin-logs-staff-action-logs.js.es6 b/app/assets/javascripts/admin/controllers/admin-logs-staff-action-logs.js.es6 index 16ed12e987c..9a596ad70f8 100644 --- a/app/assets/javascripts/admin/controllers/admin-logs-staff-action-logs.js.es6 +++ b/app/assets/javascripts/admin/controllers/admin-logs-staff-action-logs.js.es6 @@ -1,6 +1,7 @@ import { exportEntity } from "discourse/lib/export-csv"; import { outputExportResult } from "discourse/lib/export-result"; import StaffActionLog from "admin/models/staff-action-log"; +import computed from "ember-addons/ember-computed-decorators"; export default Ember.Controller.extend({ loading: false, @@ -20,14 +21,14 @@ export default Ember.Controller.extend({ } }.observes("filterActionId"), - actionFilter: function() { - var name = this.get("filters.action_name"); + @computed("filters.action_name") + actionFilter(name) { if (name) { return I18n.t("admin.logs.staff_actions.actions." + name); } else { return null; } - }.property("filters.action_name"), + }, showInstructions: Ember.computed.gt("model.length", 0), diff --git a/app/assets/javascripts/admin/controllers/admin-plugins.js.es6 b/app/assets/javascripts/admin/controllers/admin-plugins.js.es6 index 5e91ad297da..2e34bfc7f79 100644 --- a/app/assets/javascripts/admin/controllers/admin-plugins.js.es6 +++ b/app/assets/javascripts/admin/controllers/admin-plugins.js.es6 @@ -1,4 +1,7 @@ +import computed from "ember-addons/ember-computed-decorators"; + export default Ember.Controller.extend({ + @computed adminRoutes: function() { return this.get("model") .map(p => { @@ -7,7 +10,8 @@ export default Ember.Controller.extend({ } }) .compact(); - }.property(), + }, + actions: { clearFilter() { this.setProperties({ filter: "", onlyOverridden: false }); 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 06cec9f53d8..06832ca0b60 100644 --- a/app/assets/javascripts/admin/controllers/admin-user-badges.js.es6 +++ b/app/assets/javascripts/admin/controllers/admin-user-badges.js.es6 @@ -1,5 +1,6 @@ import GrantBadgeController from "discourse/mixins/grant-badge-controller"; import { popupAjaxError } from "discourse/lib/ajax-error"; +import computed from "ember-addons/ember-computed-decorators"; export default Ember.Controller.extend(GrantBadgeController, { adminUser: Ember.inject.controller(), @@ -10,7 +11,8 @@ export default Ember.Controller.extend(GrantBadgeController, { sortedBadges: Ember.computed.sort("model", "badgeSortOrder"), badgeSortOrder: ["granted_at:desc"], - groupedBadges: function() { + @computed("model", "model.[]", "model.expandedBadges.[]") + groupedBadges() { const allBadges = this.get("model"); var grouped = _.groupBy(allBadges, badge => badge.badge_id); @@ -46,7 +48,7 @@ export default Ember.Controller.extend(GrantBadgeController, { .sortBy(group => group.granted_at) .reverse() .value(); - }.property("model", "model.[]", "model.expandedBadges.[]"), + }, actions: { expandGroup: function(userBadge) { diff --git a/app/assets/javascripts/admin/controllers/admin-users-list-show.js.es6 b/app/assets/javascripts/admin/controllers/admin-users-list-show.js.es6 index b5b0c5b08ae..f23fa949579 100644 --- a/app/assets/javascripts/admin/controllers/admin-users-list-show.js.es6 +++ b/app/assets/javascripts/admin/controllers/admin-users-list-show.js.es6 @@ -2,6 +2,7 @@ import debounce from "discourse/lib/debounce"; import { i18n } from "discourse/lib/computed"; import AdminUser from "admin/models/admin-user"; import CanCheckEmails from "discourse/mixins/can-check-emails"; +import computed from "ember-addons/ember-computed-decorators"; export default Ember.Controller.extend(CanCheckEmails, { model: null, @@ -14,9 +15,10 @@ export default Ember.Controller.extend(CanCheckEmails, { selectAll: false, searchHint: i18n("search_hint"), - title: function() { - return I18n.t("admin.users.titles." + this.get("query")); - }.property("query"), + @computed("query") + title(query) { + return I18n.t("admin.users.titles." + query); + }, _filterUsers: debounce(function() { this._refreshUsers(); diff --git a/app/assets/javascripts/admin/mixins/setting-object.js.es6 b/app/assets/javascripts/admin/mixins/setting-object.js.es6 index 48c9528af78..ce3a217a98a 100644 --- a/app/assets/javascripts/admin/mixins/setting-object.js.es6 +++ b/app/assets/javascripts/admin/mixins/setting-object.js.es6 @@ -1,19 +1,20 @@ -export default Ember.Mixin.create({ - overridden: function() { - let val = this.get("value"), - defaultVal = this.get("default"); +import computed from "ember-addons/ember-computed-decorators"; +export default Ember.Mixin.create({ + @computed("value", "default") + overridden(val, defaultVal) { if (val === null) val = ""; if (defaultVal === null) defaultVal = ""; return val.toString() !== defaultVal.toString(); - }.property("value", "default"), + }, - validValues: function() { + @computed("valid_values") + validValues(validValues) { const vals = [], translateNames = this.get("translate_names"); - this.get("valid_values").forEach(v => { + validValues.forEach(v => { if (v.name && v.name.length > 0 && translateNames) { vals.addObject({ name: I18n.t(v.name), value: v.value }); } else { @@ -21,12 +22,12 @@ export default Ember.Mixin.create({ } }); return vals; - }.property("valid_values"), + }, - allowsNone: function() { - const validValues = this.get("valid_values"); + @computed("valid_values") + allowsNone(validValues) { if (validValues && validValues.indexOf("") >= 0) { return "admin.settings.none"; } - }.property("valid_values") + } }); diff --git a/app/assets/javascripts/admin/models/admin-user.js.es6 b/app/assets/javascripts/admin/models/admin-user.js.es6 index bc1cba2f411..64c11cb108f 100644 --- a/app/assets/javascripts/admin/models/admin-user.js.es6 +++ b/app/assets/javascripts/admin/models/admin-user.js.es6 @@ -293,17 +293,19 @@ const AdminUser = Discourse.User.extend({ }); }, - canLockTrustLevel: function() { - return this.get("trust_level") < 4; - }.property("trust_level"), + @computed("trust_level") + canLockTrustLevel(trustLevel) { + return trustLevel < 4; + }, canSuspend: Ember.computed.not("staff"), - suspendDuration: function() { - const suspended_at = moment(this.suspended_at), - suspended_till = moment(this.suspended_till); - return suspended_at.format("L") + " - " + suspended_till.format("L"); - }.property("suspended_till", "suspended_at"), + @computed("suspended_till", "suspended_at") + suspendDuration(suspendedTill, suspendedAt) { + suspendedAt = moment(suspendedAt); + suspendedTill = moment(suspendedTill); + return suspendedAt.format("L") + " - " + suspendedTill.format("L"); + }, suspend(data) { return ajax(`/admin/users/${this.id}/suspend`, { diff --git a/app/assets/javascripts/admin/models/color-scheme.js.es6 b/app/assets/javascripts/admin/models/color-scheme.js.es6 index e7fbe31f235..1e2d10869eb 100644 --- a/app/assets/javascripts/admin/models/color-scheme.js.es6 +++ b/app/assets/javascripts/admin/models/color-scheme.js.es6 @@ -1,5 +1,6 @@ import { ajax } from "discourse/lib/ajax"; import ColorSchemeColor from "admin/models/color-scheme-color"; +import computed from "ember-addons/ember-computed-decorators"; const ColorScheme = Discourse.Model.extend(Ember.Copyable, { init: function() { @@ -7,9 +8,10 @@ const ColorScheme = Discourse.Model.extend(Ember.Copyable, { this.startTrackingChanges(); }, - description: function() { + @computed + description() { return "" + this.name; - }.property(), + }, startTrackingChanges: function() { this.set("originals", { @@ -44,7 +46,8 @@ const ColorScheme = Discourse.Model.extend(Ember.Copyable, { return newScheme; }, - changed: function() { + @computed("name", "colors.@each.changed", "saving") + changed() { if (!this.originals) return false; if (this.originals["name"] !== this.get("name")) return true; if ( @@ -54,24 +57,23 @@ const ColorScheme = Discourse.Model.extend(Ember.Copyable, { ) return true; return false; - }.property("name", "colors.@each.changed", "saving"), + }, - disableSave: function() { + @computed("changed") + disableSave(changed) { if (this.get("theme_id")) { return false; } return ( - !this.get("changed") || + !changed || this.get("saving") || _.any(this.get("colors"), function(c) { return !c.get("valid"); }) ); - }.property("changed"), + }, - newRecord: function() { - return !this.get("id"); - }.property("id"), + newRecord: Ember.computed.not("id"), save: function(opts) { if (this.get("is_base") || this.get("disableSave")) return; diff --git a/app/assets/javascripts/admin/models/report.js.es6 b/app/assets/javascripts/admin/models/report.js.es6 index aff881dd2d9..19a1579e5db 100644 --- a/app/assets/javascripts/admin/models/report.js.es6 +++ b/app/assets/javascripts/admin/models/report.js.es6 @@ -76,25 +76,35 @@ const Report = Discourse.Model.extend({ } }, - todayCount: function() { + @computed("data", "average") + todayCount() { return this.valueAt(0); - }.property("data", "average"), - yesterdayCount: function() { - return this.valueAt(1); - }.property("data", "average"), - sevenDaysAgoCount: function() { - return this.valueAt(7); - }.property("data", "average"), - thirtyDaysAgoCount: function() { - return this.valueAt(30); - }.property("data", "average"), + }, - lastSevenDaysCount: function() { + @computed("data", "average") + yesterdayCount() { + return this.valueAt(1); + }, + + @computed("data", "average") + sevenDaysAgoCount() { + return this.valueAt(7); + }, + + @computed("data", "average") + thirtyDaysAgoCount() { + return this.valueAt(30); + }, + + @computed("data", "average") + lastSevenDaysCount() { return this.averageCount(7, this.valueFor(1, 7)); - }.property("data", "average"), - lastThirtyDaysCount: function() { + }, + + @computed("data", "average") + lastThirtyDaysCount() { return this.averageCount(30, this.valueFor(1, 30)); - }.property("data", "average"), + }, averageCount(count, value) { return this.get("average") ? value / count : value; diff --git a/app/assets/javascripts/admin/models/screened-email.js.es6 b/app/assets/javascripts/admin/models/screened-email.js.es6 index 1f1590baa00..23b4ec28c79 100644 --- a/app/assets/javascripts/admin/models/screened-email.js.es6 +++ b/app/assets/javascripts/admin/models/screened-email.js.es6 @@ -1,8 +1,11 @@ import { ajax } from "discourse/lib/ajax"; +import computed from "ember-addons/ember-computed-decorators"; + const ScreenedEmail = Discourse.Model.extend({ - actionName: function() { - return I18n.t("admin.logs.screened_actions." + this.get("action")); - }.property("action"), + @computed("action") + actionName(action) { + return I18n.t("admin.logs.screened_actions." + action); + }, clearBlock: function() { return ajax("/admin/logs/screened_emails/" + this.get("id"), { diff --git a/app/assets/javascripts/admin/models/screened-url.js.es6 b/app/assets/javascripts/admin/models/screened-url.js.es6 index 06dc94f7d44..b899c619623 100644 --- a/app/assets/javascripts/admin/models/screened-url.js.es6 +++ b/app/assets/javascripts/admin/models/screened-url.js.es6 @@ -1,8 +1,11 @@ import { ajax } from "discourse/lib/ajax"; +import computed from "ember-addons/ember-computed-decorators"; + const ScreenedUrl = Discourse.Model.extend({ - actionName: function() { - return I18n.t("admin.logs.screened_actions." + this.get("action")); - }.property("action") + @computed("action") + actionName(action) { + return I18n.t("admin.logs.screened_actions." + action); + } }); ScreenedUrl.reopenClass({ diff --git a/app/assets/javascripts/admin/models/tl3-requirements.js.es6 b/app/assets/javascripts/admin/models/tl3-requirements.js.es6 index 2b49e660919..c30bc0404d5 100644 --- a/app/assets/javascripts/admin/models/tl3-requirements.js.es6 +++ b/app/assets/javascripts/admin/models/tl3-requirements.js.es6 @@ -11,36 +11,7 @@ export default Discourse.Model.extend({ return Math.round((minDaysVisited * 100) / timePeriod); }, - met: function() { - return { - days_visited: this.get("days_visited") >= this.get("min_days_visited"), - topics_replied_to: - this.get("num_topics_replied_to") >= this.get("min_topics_replied_to"), - topics_viewed: this.get("topics_viewed") >= this.get("min_topics_viewed"), - posts_read: this.get("posts_read") >= this.get("min_posts_read"), - topics_viewed_all_time: - this.get("topics_viewed_all_time") >= - this.get("min_topics_viewed_all_time"), - posts_read_all_time: - this.get("posts_read_all_time") >= this.get("min_posts_read_all_time"), - flagged_posts: - this.get("num_flagged_posts") <= this.get("max_flagged_posts"), - flagged_by_users: - this.get("num_flagged_by_users") <= this.get("max_flagged_by_users"), - likes_given: this.get("num_likes_given") >= this.get("min_likes_given"), - likes_received: - this.get("num_likes_received") >= this.get("min_likes_received"), - likes_received_days: - this.get("num_likes_received_days") >= - this.get("min_likes_received_days"), - likes_received_users: - this.get("num_likes_received_users") >= - this.get("min_likes_received_users"), - level_locked: this.get("trust_level_locked"), - silenced: this.get("penalty_counts.silenced") === 0, - suspended: this.get("penalty_counts.suspended") === 0 - }; - }.property( + @computed( "days_visited", "min_days_visited", "num_topics_replied_to", @@ -71,4 +42,34 @@ export default Discourse.Model.extend({ "penalty_counts.silenced", "penalty_counts.suspended" ) + met() { + return { + days_visited: this.get("days_visited") >= this.get("min_days_visited"), + topics_replied_to: + this.get("num_topics_replied_to") >= this.get("min_topics_replied_to"), + topics_viewed: this.get("topics_viewed") >= this.get("min_topics_viewed"), + posts_read: this.get("posts_read") >= this.get("min_posts_read"), + topics_viewed_all_time: + this.get("topics_viewed_all_time") >= + this.get("min_topics_viewed_all_time"), + posts_read_all_time: + this.get("posts_read_all_time") >= this.get("min_posts_read_all_time"), + flagged_posts: + this.get("num_flagged_posts") <= this.get("max_flagged_posts"), + flagged_by_users: + this.get("num_flagged_by_users") <= this.get("max_flagged_by_users"), + likes_given: this.get("num_likes_given") >= this.get("min_likes_given"), + likes_received: + this.get("num_likes_received") >= this.get("min_likes_received"), + likes_received_days: + this.get("num_likes_received_days") >= + this.get("min_likes_received_days"), + likes_received_users: + this.get("num_likes_received_users") >= + this.get("min_likes_received_users"), + level_locked: this.get("trust_level_locked"), + silenced: this.get("penalty_counts.silenced") === 0, + suspended: this.get("penalty_counts.suspended") === 0 + }; + } }); diff --git a/app/assets/javascripts/discourse/components/badge-button.js.es6 b/app/assets/javascripts/discourse/components/badge-button.js.es6 index 443bf28e09e..d0c2708b662 100644 --- a/app/assets/javascripts/discourse/components/badge-button.js.es6 +++ b/app/assets/javascripts/discourse/components/badge-button.js.es6 @@ -1,3 +1,5 @@ +import computed from "ember-addons/ember-computed-decorators"; + export default Ember.Component.extend({ tagName: "span", classNameBindings: [ @@ -5,9 +7,12 @@ export default Ember.Component.extend({ "badge.badgeTypeClassName", "badge.enabled::disabled" ], - title: function() { - return $("
" + this.get("badge.description") + "
").text(); - }.property("badge.description"), + + @computed("badge.description") + title(badgeDescription) { + return $("
" + badgeDescription + "
").text(); + }, + attributeBindings: ["data-badge-name", "title"], "data-badge-name": Ember.computed.alias("badge.name") }); diff --git a/app/assets/javascripts/discourse/components/basic-topic-list.js.es6 b/app/assets/javascripts/discourse/components/basic-topic-list.js.es6 index e5660aa98e4..651dac43278 100644 --- a/app/assets/javascripts/discourse/components/basic-topic-list.js.es6 +++ b/app/assets/javascripts/discourse/components/basic-topic-list.js.es6 @@ -1,15 +1,18 @@ +import computed from "ember-addons/ember-computed-decorators"; + export default Ember.Component.extend({ loadingMore: Ember.computed.alias("topicList.loadingMore"), loading: Ember.computed.not("loaded"), - loaded: function() { + @computed("topicList.loaded") + loaded() { var topicList = this.get("topicList"); if (topicList) { return topicList.get("loaded"); } else { return true; } - }.property("topicList.loaded"), + }, _topicListChanged: function() { this._initFromTopicList(this.get("topicList")); @@ -27,9 +30,6 @@ export default Ember.Component.extend({ const topicList = this.get("topicList"); if (topicList) { this._initFromTopicList(topicList); - } else { - // Without a topic list, we assume it's loaded always. - this.set("loaded", true); } }, diff --git a/app/assets/javascripts/discourse/components/d-button.js.es6 b/app/assets/javascripts/discourse/components/d-button.js.es6 index 7fbf32bc184..30ae320f089 100644 --- a/app/assets/javascripts/discourse/components/d-button.js.es6 +++ b/app/assets/javascripts/discourse/components/d-button.js.es6 @@ -30,13 +30,25 @@ export default Ember.Component.extend({ noText: Ember.computed.empty("translatedLabel"), @computed("title") - translatedTitle(title) { - if (title) return I18n.t(title); + translatedTitle: { + get() { + if (this._translatedTitle) return this._translatedTitle; + if (this.title) return I18n.t(this.title); + }, + set(value) { + return (this._translatedTitle = value); + } }, @computed("label") - translatedLabel(label) { - if (label) return I18n.t(label); + translatedLabel: { + get() { + if (this._translatedLabel) return this._translatedLabel; + if (this.label) return I18n.t(this.label); + }, + set(value) { + return (this._translatedLabel = value); + } }, click() { diff --git a/app/assets/javascripts/discourse/components/discourse-banner.js.es6 b/app/assets/javascripts/discourse/components/discourse-banner.js.es6 index e737d476437..80997b4c9cb 100644 --- a/app/assets/javascripts/discourse/components/discourse-banner.js.es6 +++ b/app/assets/javascripts/discourse/components/discourse-banner.js.es6 @@ -1,9 +1,10 @@ +import computed from "ember-addons/ember-computed-decorators"; + export default Ember.Component.extend({ - visible: function() { - var bannerKey = this.get("banner.key"), - dismissedBannerKey = - this.get("user.dismissed_banner_key") || - this.keyValueStore.get("dismissed_banner_key"); + @computed("user.dismissed_banner_key", "banner.key", "hide") + visible(dismissedBannerKey, bannerKey, hide) { + dismissedBannerKey = + dismissedBannerKey || this.keyValueStore.get("dismissed_banner_key"); if (bannerKey) { bannerKey = parseInt(bannerKey, 10); @@ -12,8 +13,8 @@ export default Ember.Component.extend({ dismissedBannerKey = parseInt(dismissedBannerKey, 10); } - return !this.get("hide") && bannerKey && dismissedBannerKey !== bannerKey; - }.property("user.dismissed_banner_key", "banner.key", "hide"), + return !hide && bannerKey && dismissedBannerKey !== bannerKey; + }, actions: { dismiss() { diff --git a/app/assets/javascripts/discourse/components/discourse-tag-bound.js.es6 b/app/assets/javascripts/discourse/components/discourse-tag-bound.js.es6 index c422c5dd0e7..9f151dc1fe3 100644 --- a/app/assets/javascripts/discourse/components/discourse-tag-bound.js.es6 +++ b/app/assets/javascripts/discourse/components/discourse-tag-bound.js.es6 @@ -1,13 +1,17 @@ +import computed from "ember-addons/ember-computed-decorators"; + export default Ember.Component.extend({ tagName: "a", classNameBindings: [":discourse-tag", "style", "tagClass"], attributeBindings: ["href"], - tagClass: function() { - return "tag-" + this.get("tagRecord.id"); - }.property("tagRecord.id"), + @computed("tagRecord.id") + tagClass(tagRecordId) { + return "tag-" + tagRecordId; + }, - href: function() { - return Discourse.getURL("/tags/" + this.get("tagRecord.id")); - }.property("tagRecord.id") + @computed("tagRecord.id") + href(tagRecordId) { + return Discourse.getURL("/tags/" + tagRecordId); + } }); diff --git a/app/assets/javascripts/discourse/components/edit-category-tab.js.es6 b/app/assets/javascripts/discourse/components/edit-category-tab.js.es6 index 7c2509f0680..50fd860f2b2 100644 --- a/app/assets/javascripts/discourse/components/edit-category-tab.js.es6 +++ b/app/assets/javascripts/discourse/components/edit-category-tab.js.es6 @@ -1,18 +1,21 @@ import { propertyEqual } from "discourse/lib/computed"; +import computed from "ember-addons/ember-computed-decorators"; export default Ember.Component.extend({ tagName: "li", classNameBindings: ["active", "tabClassName"], - tabClassName: function() { - return "edit-category-" + this.get("tab"); - }.property("tab"), + @computed("tab") + tabClassName(tab) { + return "edit-category-" + tab; + }, active: propertyEqual("selectedTab", "tab"), - title: function() { - return I18n.t("category." + this.get("tab").replace("-", "_")); - }.property("tab"), + @computed("tab") + title(tab) { + return I18n.t("category." + tab.replace("-", "_")); + }, didInsertElement() { this._super(...arguments); diff --git a/app/assets/javascripts/discourse/components/preference-checkbox.js.es6 b/app/assets/javascripts/discourse/components/preference-checkbox.js.es6 index 6088f4a4a6b..1b858735a24 100644 --- a/app/assets/javascripts/discourse/components/preference-checkbox.js.es6 +++ b/app/assets/javascripts/discourse/components/preference-checkbox.js.es6 @@ -1,9 +1,12 @@ +import computed from "ember-addons/ember-computed-decorators"; + export default Ember.Component.extend({ classNames: ["controls"], - label: function() { - return I18n.t(this.get("labelKey")); - }.property("labelKey"), + @computed("labelKey") + label(labelKey) { + return I18n.t(labelKey); + }, change() { const warning = this.get("warning"); diff --git a/app/assets/javascripts/discourse/components/tag-drop-link.js.es6 b/app/assets/javascripts/discourse/components/tag-drop-link.js.es6 index 55de68c4145..099f2b8449a 100644 --- a/app/assets/javascripts/discourse/components/tag-drop-link.js.es6 +++ b/app/assets/javascripts/discourse/components/tag-drop-link.js.es6 @@ -1,4 +1,5 @@ import DiscourseURL from "discourse/lib/url"; +import computed from "ember-addons/ember-computed-decorators"; export default Ember.Component.extend({ tagName: "a", @@ -10,17 +11,19 @@ export default Ember.Component.extend({ ], attributeBindings: ["href"], - href: function() { + @computed("tagId", "category") + href(tagId, category) { var url = "/tags"; - if (this.get("category")) { - url += this.get("category.url"); + if (category) { + url += category.url; } - return url + "/" + this.get("tagId"); - }.property("tagId", "category"), + return url + "/" + tagId; + }, - tagClass: function() { - return "tag-" + this.get("tagId"); - }.property("tagId"), + @computed("tagId") + tagClass(tagId) { + return "tag-" + tagId; + }, click(e) { e.preventDefault(); diff --git a/app/assets/javascripts/discourse/components/text-field.js.es6 b/app/assets/javascripts/discourse/components/text-field.js.es6 index 908e52389e4..eca66af1d36 100644 --- a/app/assets/javascripts/discourse/components/text-field.js.es6 +++ b/app/assets/javascripts/discourse/components/text-field.js.es6 @@ -38,7 +38,13 @@ export default Ember.TextField.extend({ }, @computed("placeholderKey") - placeholder(placeholderKey) { - return placeholderKey ? I18n.t(placeholderKey) : ""; + placeholder: { + get() { + if (this._placeholder) return this._placeholder; + return this.placeholderKey ? I18n.t(this.placeholderKey) : ""; + }, + set(value) { + return (this._placeholder = value); + } } }); diff --git a/app/assets/javascripts/discourse/components/top-period-buttons.js.es6 b/app/assets/javascripts/discourse/components/top-period-buttons.js.es6 index 237a4c6cfe0..059b1a1468c 100644 --- a/app/assets/javascripts/discourse/components/top-period-buttons.js.es6 +++ b/app/assets/javascripts/discourse/components/top-period-buttons.js.es6 @@ -1,10 +1,12 @@ +import computed from "ember-addons/ember-computed-decorators"; + export default Ember.Component.extend({ classNames: ["top-title-buttons"], - periods: function() { - const period = this.get("period"); + @computed("period") + periods(period) { return this.site.get("periods").filter(p => p !== period); - }.property("period"), + }, actions: { changePeriod(p) { diff --git a/app/assets/javascripts/discourse/components/topic-list.js.es6 b/app/assets/javascripts/discourse/components/topic-list.js.es6 index a91ee52c0b8..f08140142f0 100644 --- a/app/assets/javascripts/discourse/components/topic-list.js.es6 +++ b/app/assets/javascripts/discourse/components/topic-list.js.es6 @@ -1,4 +1,7 @@ -import { observes } from "ember-addons/ember-computed-decorators"; +import { + default as computed, + observes +} from "ember-addons/ember-computed-decorators"; export default Ember.Component.extend({ tagName: "table", @@ -16,25 +19,25 @@ export default Ember.Component.extend({ this.refreshLastVisited(); }.on("init"), - toggleInTitle: function() { - return !this.get("bulkSelectEnabled") && this.get("canBulkSelect"); - }.property("bulkSelectEnabled"), + @computed("bulkSelectEnabled") + toggleInTitle(bulkSelectEnabled) { + return !bulkSelectEnabled && this.get("canBulkSelect"); + }, - sortable: function() { + @computed + sortable() { return !!this.get("changeSort"); - }.property(), + }, - skipHeader: function() { - return this.site.mobileView; - }.property(), + @computed("order") + showLikes(order) { + return order === "likes"; + }, - showLikes: function() { - return this.get("order") === "likes"; - }.property("order"), - - showOpLikes: function() { - return this.get("order") === "op_likes"; - }.property("order"), + @computed("order") + showOpLikes(order) { + return order === "op_likes"; + }, @observes("topics.[]") topicsAdded() { diff --git a/app/assets/javascripts/discourse/components/topic-status.js.es6 b/app/assets/javascripts/discourse/components/topic-status.js.es6 index 9e92561ea6f..866ed66f879 100644 --- a/app/assets/javascripts/discourse/components/topic-status.js.es6 +++ b/app/assets/javascripts/discourse/components/topic-status.js.es6 @@ -2,6 +2,7 @@ import { iconHTML } from "discourse-common/lib/icon-library"; import { bufferedRender } from "discourse-common/lib/buffered-render"; import { escapeExpression } from "discourse/lib/utilities"; import TopicStatusIcons from "discourse/helpers/topic-status-icons"; +import computed from "ember-addons/ember-computed-decorators"; export default Ember.Component.extend( bufferedRender({ @@ -26,9 +27,10 @@ export default Ember.Component.extend( return false; }, - canAct: function() { - return Discourse.User.current() && !this.get("disableActions"); - }.property("disableActions"), + @computed("disableActions") + canAct(disableActions) { + return Discourse.User.current() && !disableActions; + }, buildBuffer(buffer) { const canAct = this.get("canAct"); diff --git a/app/assets/javascripts/discourse/components/user-badge.js.es6 b/app/assets/javascripts/discourse/components/user-badge.js.es6 index 70636d347fd..bca90d4435a 100644 --- a/app/assets/javascripts/discourse/components/user-badge.js.es6 +++ b/app/assets/javascripts/discourse/components/user-badge.js.es6 @@ -1,14 +1,18 @@ +import computed from "ember-addons/ember-computed-decorators"; + export default Ember.Component.extend({ tagName: "span", - showGrantCount: function() { - return this.get("count") && this.get("count") > 1; - }.property("count"), + @computed("count") + showGrantCount(count) { + return count && count > 1; + }, - badgeUrl: function() { + @computed("badge", "user") + badgeUrl() { // NOTE: I tried using a link-to helper here but the queryParams mean it fails var username = this.get("user.username_lower") || ""; username = username !== "" ? "?username=" + username : ""; return this.get("badge.url") + username; - }.property("badge", "user") + } }); diff --git a/app/assets/javascripts/discourse/components/user-field.js.es6 b/app/assets/javascripts/discourse/components/user-field.js.es6 index 79a19c20467..1585e9a3a5a 100644 --- a/app/assets/javascripts/discourse/components/user-field.js.es6 +++ b/app/assets/javascripts/discourse/components/user-field.js.es6 @@ -1,10 +1,12 @@ import { fmt } from "discourse/lib/computed"; +import computed from "ember-addons/ember-computed-decorators"; export default Ember.Component.extend({ classNameBindings: [":user-field", "field.field_type"], layoutName: fmt("field.field_type", "components/user-fields/%@"), - noneLabel: function() { + @computed + noneLabel() { return "user_fields.none"; - }.property() + } }); diff --git a/app/assets/javascripts/discourse/controllers/about.js.es6 b/app/assets/javascripts/discourse/controllers/about.js.es6 index a3c77bbaea8..f17aac609be 100644 --- a/app/assets/javascripts/discourse/controllers/about.js.es6 +++ b/app/assets/javascripts/discourse/controllers/about.js.es6 @@ -1,7 +1,10 @@ +import computed from "ember-addons/ember-computed-decorators"; + export default Ember.Controller.extend({ faqOverriden: Ember.computed.gt("siteSettings.faq_url.length", 0), - contactInfo: function() { + @computed + contactInfo() { if (this.siteSettings.contact_url) { return I18n.t("about.contact_info", { contact_info: @@ -18,5 +21,5 @@ export default Ember.Controller.extend({ } else { return null; } - }.property() + } }); diff --git a/app/assets/javascripts/discourse/controllers/badges/index.js.es6 b/app/assets/javascripts/discourse/controllers/badges/index.js.es6 index 6da107ec568..eb36dbe5219 100644 --- a/app/assets/javascripts/discourse/controllers/badges/index.js.es6 +++ b/app/assets/javascripts/discourse/controllers/badges/index.js.es6 @@ -1,6 +1,9 @@ +import computed from "ember-addons/ember-computed-decorators"; + export default Ember.Controller.extend({ - badgeGroups: function() { - var sorted = _.sortBy(this.get("model"), function(badge) { + @computed("model") + badgeGroups(model) { + var sorted = _.sortBy(model, function(badge) { var pos = badge.get("badge_grouping.position"); var type = badge.get("badge_type_id"); var name = badge.get("name"); @@ -31,5 +34,5 @@ export default Ember.Controller.extend({ } return grouped; - }.property("model") + } }); diff --git a/app/assets/javascripts/discourse/controllers/badges/show.js.es6 b/app/assets/javascripts/discourse/controllers/badges/show.js.es6 index a5273c253b1..1fcda3adf7c 100644 --- a/app/assets/javascripts/discourse/controllers/badges/show.js.es6 +++ b/app/assets/javascripts/discourse/controllers/badges/show.js.es6 @@ -12,9 +12,10 @@ export default Ember.Controller.extend(BadgeSelectController, { application: Ember.inject.controller(), hiddenSetTitle: true, - filteredList: function() { - return this.get("userBadgesAll").filterBy("badge.allow_title", true); - }.property("userBadgesAll"), + @computed("userBadgesAll") + filteredList(userBadgesAll) { + return userBadgesAll.filterBy("badge.allow_title", true); + }, @computed("username") user(username) { diff --git a/app/assets/javascripts/discourse/controllers/composer.js.es6 b/app/assets/javascripts/discourse/controllers/composer.js.es6 index be239a81e73..9a370cee026 100644 --- a/app/assets/javascripts/discourse/controllers/composer.js.es6 +++ b/app/assets/javascripts/discourse/controllers/composer.js.es6 @@ -39,6 +39,7 @@ function loadDraft(store, opts) { ((draft.title && draft.title !== "") || (draft.reply && draft.reply !== "")) ) { const composer = store.createRecord("composer"); + composer.open({ draftKey, draftSequence, @@ -301,14 +302,12 @@ export default Ember.Controller.extend({ } }, - showWarning: function() { + @computed("model.creatingPrivateMessage", "model.targetUsernames") + showWarning(creatingPrivateMessage, usernames) { if (!Discourse.User.currentProp("staff")) { return false; } - - var usernames = this.get("model.targetUsernames"); var hasTargetGroups = this.get("model.hasTargetGroups"); - // We need exactly one user to issue a warning if ( Ember.isEmpty(usernames) || @@ -317,8 +316,8 @@ export default Ember.Controller.extend({ ) { return false; } - return this.get("model.creatingPrivateMessage"); - }.property("model.creatingPrivateMessage", "model.targetUsernames"), + return creatingPrivateMessage; + }, @computed("model.topic") draftTitle(topic) { @@ -1102,15 +1101,13 @@ export default Ember.Controller.extend({ $(".d-editor-input").autocomplete({ cancel: true }); }, - canEdit: function() { - return ( - this.get("model.action") === "edit" && - Discourse.User.current().get("can_edit") - ); - }.property("model.action"), + @computed("model.action") + canEdit(action) { + return action === "edit" && Discourse.User.current().get("can_edit"); + }, - visible: function() { - var state = this.get("model.composeState"); + @computed("model.composeState") + visible(state) { return state && state !== "closed"; - }.property("model.composeState") + } }); diff --git a/app/assets/javascripts/discourse/controllers/create-account.js.es6 b/app/assets/javascripts/discourse/controllers/create-account.js.es6 index cb38b10d30c..7b88f79927e 100644 --- a/app/assets/javascripts/discourse/controllers/create-account.js.es6 +++ b/app/assets/javascripts/discourse/controllers/create-account.js.es6 @@ -1,7 +1,10 @@ import { ajax } from "discourse/lib/ajax"; import ModalFunctionality from "discourse/mixins/modal-functionality"; import { setting } from "discourse/lib/computed"; -import { on } from "ember-addons/ember-computed-decorators"; +import { + default as computed, + on +} from "ember-addons/ember-computed-decorators"; import { emailValid } from "discourse/lib/utilities"; import InputValidation from "discourse/models/input-validation"; import PasswordValidation from "discourse/mixins/password-validation"; @@ -51,7 +54,16 @@ export default Ember.Controller.extend( this._createUserFields(); }, - submitDisabled: function() { + @computed( + "passwordRequired", + "nameValidation.failed", + "emailValidation.failed", + "usernameValidation.failed", + "passwordValidation.failed", + "userFieldsValidation.failed", + "formSubmitted" + ) + submitDisabled() { if (!this.get("emailValidation.failed") && !this.get("passwordRequired")) return false; // 3rd party auth if (this.get("formSubmitted")) return true; @@ -62,51 +74,44 @@ export default Ember.Controller.extend( if (this.get("userFieldsValidation.failed")) return true; return false; - }.property( - "passwordRequired", - "nameValidation.failed", - "emailValidation.failed", - "usernameValidation.failed", - "passwordValidation.failed", - "userFieldsValidation.failed", - "formSubmitted" - ), + }, usernameRequired: Ember.computed.not("authOptions.omit_username"), - fullnameRequired: function() { + @computed + fullnameRequired() { return ( this.get("siteSettings.full_name_required") || this.get("siteSettings.enable_names") ); - }.property(), + }, - passwordRequired: function() { - return Ember.isEmpty(this.get("authOptions.auth_provider")); - }.property("authOptions.auth_provider"), + @computed("authOptions.auth_provider") + passwordRequired(authProvider) { + return Ember.isEmpty(authProvider); + }, - disclaimerHtml: function() { + @computed + disclaimerHtml() { return I18n.t("create_account.disclaimer", { tos_link: this.get("siteSettings.tos_url") || Discourse.getURL("/tos"), privacy_link: this.get("siteSettings.privacy_policy_url") || Discourse.getURL("/privacy") }); - }.property(), + }, // Check the email address - emailValidation: function() { + @computed("accountEmail", "rejectedEmails.[]") + emailValidation(email, rejectedEmails) { // If blank, fail without a reason - let email; - if (Ember.isEmpty(this.get("accountEmail"))) { + if (Ember.isEmpty(email)) { return InputValidation.create({ failed: true }); } - email = this.get("accountEmail"); - - if (this.get("rejectedEmails").includes(email)) { + if (rejectedEmails.includes(email)) { return InputValidation.create({ failed: true, reason: I18n.t("user.email.invalid") @@ -138,14 +143,15 @@ export default Ember.Controller.extend( failed: true, reason: I18n.t("user.email.invalid") }); - }.property("accountEmail", "rejectedEmails.[]"), + }, - emailValidated: function() { + @computed("accountEmail", "authOptions.email", "authOptions.email_valid") + emailValidated() { return ( this.get("authOptions.email") === this.get("accountEmail") && this.get("authOptions.email_valid") ); - }.property("accountEmail", "authOptions.email", "authOptions.email_valid"), + }, authProviderDisplayName(providerName) { const matchingProvider = findAll().find(provider => { @@ -178,9 +184,10 @@ export default Ember.Controller.extend( }.observes("emailValidation", "accountEmail"), // Determines whether at least one login button is enabled - hasAtLeastOneLoginButton: function() { + @computed + hasAtLeastOneLoginButton() { return findAll(this.siteSettings).length > 0; - }.property(), + }, @on("init") fetchConfirmationValue() { diff --git a/app/assets/javascripts/discourse/controllers/discovery/topics.js.es6 b/app/assets/javascripts/discourse/controllers/discovery/topics.js.es6 index 709deffbaa1..3f64d5984eb 100644 --- a/app/assets/javascripts/discourse/controllers/discovery/topics.js.es6 +++ b/app/assets/javascripts/discourse/controllers/discovery/topics.js.es6 @@ -5,6 +5,7 @@ import { endWith } from "discourse/lib/computed"; import showModal from "discourse/lib/show-modal"; import { userPath } from "discourse/lib/url"; import TopicList from "discourse/models/topic-list"; +import computed from "ember-addons/ember-computed-decorators"; const controllerOpts = { discovery: Ember.inject.controller(), @@ -96,26 +97,24 @@ const controllerOpts = { return filter.match(new RegExp(filterType + "$", "gi")) ? true : false; }, - showDismissRead: function() { - return ( - this.isFilterPage(this.get("model.filter"), "unread") && - this.get("model.topics.length") > 0 - ); - }.property("model.filter", "model.topics.length"), + @computed("model.filter", "model.topics.length") + showDismissRead(filter, topicsLength) { + return this.isFilterPage(filter, "unread") && topicsLength > 0; + }, - showResetNew: function() { - return ( - this.get("model.filter") === "new" && this.get("model.topics.length") > 0 - ); - }.property("model.filter", "model.topics.length"), + @computed("model.filter", "model.topics.length") + showResetNew(filter, topicsLength) { + return filter === "new" && topicsLength > 0; + }, - showDismissAtTop: function() { + @computed("model.filter", "model.topics.length") + showDismissAtTop(filter, topicsLength) { return ( - (this.isFilterPage(this.get("model.filter"), "new") || - this.isFilterPage(this.get("model.filter"), "unread")) && - this.get("model.topics.length") >= 15 + (this.isFilterPage(filter, "new") || + this.isFilterPage(filter, "unread")) && + topicsLength >= 15 ); - }.property("model.filter", "model.topics.length"), + }, hasTopics: Ember.computed.gt("model.topics.length", 0), allLoaded: Ember.computed.empty("model.more_topics_url"), @@ -128,10 +127,9 @@ const controllerOpts = { weekly: Ember.computed.equal("period", "weekly"), daily: Ember.computed.equal("period", "daily"), - footerMessage: function() { - if (!this.get("allLoaded")) { - return; - } + @computed("allLoaded", "model.topics.length") + footerMessage(allLoaded, topicsLength) { + if (!allLoaded) return; const category = this.get("category"); if (category) { @@ -140,7 +138,7 @@ const controllerOpts = { }); } else { const split = (this.get("model.filter") || "").split("/"); - if (this.get("model.topics.length") === 0) { + if (topicsLength === 0) { return I18n.t("topics.none." + split[0], { category: split[1] }); @@ -150,14 +148,11 @@ const controllerOpts = { }); } } - }.property("allLoaded", "model.topics.length"), + }, - footerEducation: function() { - if ( - !this.get("allLoaded") || - this.get("model.topics.length") > 0 || - !this.currentUser - ) { + @computed("allLoaded", "model.topics.length") + footerEducation(allLoaded, topicsLength) { + if (!allLoaded || topicsLength > 0 || !this.currentUser) { return; } @@ -173,7 +168,7 @@ const controllerOpts = { `${this.currentUser.get("username_lower")}/preferences` ) }); - }.property("allLoaded", "model.topics.length") + } }; Object.keys(queryParams).forEach(function(p) { diff --git a/app/assets/javascripts/discourse/controllers/edit-category.js.es6 b/app/assets/javascripts/discourse/controllers/edit-category.js.es6 index d474c9b6e51..fc616f19d96 100644 --- a/app/assets/javascripts/discourse/controllers/edit-category.js.es6 +++ b/app/assets/javascripts/discourse/controllers/edit-category.js.es6 @@ -1,6 +1,7 @@ import ModalFunctionality from "discourse/mixins/modal-functionality"; import DiscourseURL from "discourse/lib/url"; import { extractError } from "discourse/lib/ajax-error"; +import computed from "ember-addons/ember-computed-decorators"; // Modal for editing / creating a category export default Ember.Controller.extend(ModalFunctionality, { @@ -28,39 +29,44 @@ export default Ember.Controller.extend(ModalFunctionality, { } }.observes("model.description"), - title: function() { - if (this.get("model.id")) { + @computed("model.id", "model.name") + title(id, name) { + if (id) { return I18n.t("category.edit_dialog_title", { - categoryName: this.get("model.name") + categoryName: name }); } return I18n.t("category.create"); - }.property("model.id", "model.name"), + }, titleChanged: function() { this.set("modal.title", this.get("title")); }.observes("title"), - disabled: function() { - if (this.get("saving") || this.get("deleting")) return true; - if (!this.get("model.name")) return true; - if (!this.get("model.color")) return true; + @computed("saving", "model.name", "model.color", "deleting") + disabled(saving, name, color, deleting) { + if (saving || deleting) return true; + if (!name) return true; + if (!color) return true; return false; - }.property("saving", "model.name", "model.color", "deleting"), + }, - deleteDisabled: function() { - return this.get("deleting") || this.get("saving") || false; - }.property("disabled", "saving", "deleting"), + @computed("saving", "deleting") + deleteDisabled(saving, deleting) { + return deleting || saving || false; + }, - categoryName: function() { - const name = this.get("name") || ""; + @computed("name") + categoryName(name) { + name = name || ""; return name.trim().length > 0 ? name : I18n.t("preview"); - }.property("name"), + }, - saveLabel: function() { - if (this.get("saving")) return "saving"; - return this.get("model.id") ? "category.save" : "category.create"; - }.property("saving", "model.id"), + @computed("saving", "model.id") + saveLabel(saving, id) { + if (saving) return "saving"; + return id ? "category.save" : "category.create"; + }, actions: { saveCategory() { diff --git a/app/assets/javascripts/discourse/controllers/exception.js.es6 b/app/assets/javascripts/discourse/controllers/exception.js.es6 index 331dc5e6947..0009df44ed7 100644 --- a/app/assets/javascripts/discourse/controllers/exception.js.es6 +++ b/app/assets/javascripts/discourse/controllers/exception.js.es6 @@ -1,3 +1,5 @@ +import computed from "ember-addons/ember-computed-decorators"; + var ButtonBackBright = { classes: "btn-primary", action: "back", @@ -25,13 +27,14 @@ export default Ember.Controller.extend({ thrown: null, lastTransition: null, + @computed isNetwork: function() { // never made it on the wire if (this.get("thrown.readyState") === 0) return true; // timed out if (this.get("thrown.jqTextStatus") === "timeout") return true; return false; - }.property(), + }, isNotFound: Ember.computed.equal("thrown.status", 404), isForbidden: Ember.computed.equal("thrown.status", 403), @@ -48,7 +51,8 @@ export default Ember.Controller.extend({ this.set("loading", false); }.on("init"), - reason: function() { + @computed("isNetwork", "isServer", "isUnknown") + reason() { if (this.get("isNetwork")) { return I18n.t("errors.reasons.network"); } else if (this.get("isServer")) { @@ -61,11 +65,12 @@ export default Ember.Controller.extend({ // TODO return I18n.t("errors.reasons.unknown"); } - }.property("isNetwork", "isServer", "isUnknown"), + }, requestUrl: Ember.computed.alias("thrown.requestedUrl"), - desc: function() { + @computed("networkFixed", "isNetwork", "isServer", "isUnknown") + desc() { if (this.get("networkFixed")) { return I18n.t("errors.desc.network_fixed"); } else if (this.get("isNetwork")) { @@ -80,9 +85,10 @@ export default Ember.Controller.extend({ // TODO return I18n.t("errors.desc.unknown"); } - }.property("networkFixed", "isNetwork", "isServer", "isUnknown"), + }, - enabledButtons: function() { + @computed("networkFixed", "isNetwork", "isServer", "isUnknown") + enabledButtons() { if (this.get("networkFixed")) { return [ButtonLoadPage]; } else if (this.get("isNetwork")) { @@ -90,7 +96,7 @@ export default Ember.Controller.extend({ } else { return [ButtonBackBright, ButtonTryAgain]; } - }.property("networkFixed", "isNetwork", "isServer", "isUnknown"), + }, actions: { back: function() { diff --git a/app/assets/javascripts/discourse/controllers/flag.js.es6 b/app/assets/javascripts/discourse/controllers/flag.js.es6 index a6fbef909e6..2c0fd7704c5 100644 --- a/app/assets/javascripts/discourse/controllers/flag.js.es6 +++ b/app/assets/javascripts/discourse/controllers/flag.js.es6 @@ -39,7 +39,8 @@ export default Ember.Controller.extend(ModalFunctionality, { return flagTopic ? "flagging_topic.title" : "flagging.title"; }, - flagsAvailable: function() { + @computed("post", "flagTopic", "model.actions_summary.@each.can_act") + flagsAvailable() { if (!this.get("flagTopic")) { // flagging post let flagsAvailable = this.get("model.flagsAvailable"); @@ -71,16 +72,18 @@ export default Ember.Controller.extend(ModalFunctionality, { }); }); } - }.property("post", "flagTopic", "model.actions_summary.@each.can_act"), + }, - staffFlagsAvailable: function() { + @computed("post", "flagTopic", "model.actions_summary.@each.can_act") + staffFlagsAvailable() { return ( this.get("model.flagsAvailable") && this.get("model.flagsAvailable").length > 1 ); - }.property("post", "flagTopic", "model.actions_summary.@each.can_act"), + }, - submitEnabled: function() { + @computed("selected.is_custom_flag", "message.length") + submitEnabled() { const selected = this.get("selected"); if (!selected) return false; @@ -92,7 +95,7 @@ export default Ember.Controller.extend(ModalFunctionality, { ); } return true; - }.property("selected.is_custom_flag", "message.length"), + }, submitDisabled: Ember.computed.not("submitEnabled"), diff --git a/app/assets/javascripts/discourse/controllers/login.js.es6 b/app/assets/javascripts/discourse/controllers/login.js.es6 index 1be438faea9..bba1b31bcf8 100644 --- a/app/assets/javascripts/discourse/controllers/login.js.es6 +++ b/app/assets/javascripts/discourse/controllers/login.js.es6 @@ -284,17 +284,18 @@ export default Ember.Controller.extend(ModalFunctionality, { } }, - authMessage: function() { - if (Ember.isEmpty(this.get("authenticate"))) return ""; + @computed("authenticate") + authMessage(authenticate) { + if (Ember.isEmpty(authenticate)) return ""; const method = findAll( this.siteSettings, this.capabilities, this.isMobileDevice - ).findBy("name", this.get("authenticate")); + ).findBy("name", authenticate); if (method) { return method.get("message"); } - }.property("authenticate"), + }, authenticationComplete(options) { const self = this; diff --git a/app/assets/javascripts/discourse/controllers/navigation/categories.js.es6 b/app/assets/javascripts/discourse/controllers/navigation/categories.js.es6 index acaa6d5458c..ee6066f1863 100644 --- a/app/assets/javascripts/discourse/controllers/navigation/categories.js.es6 +++ b/app/assets/javascripts/discourse/controllers/navigation/categories.js.es6 @@ -1,9 +1,11 @@ import NavigationDefaultController from "discourse/controllers/navigation/default"; +import computed from "ember-addons/ember-computed-decorators"; export default NavigationDefaultController.extend({ discoveryCategories: Ember.inject.controller("discovery/categories"), - draft: function() { + @computed("discoveryCategories.model", "discoveryCategories.model.draft") + draft() { return this.get("discoveryCategories.model.draft"); - }.property("discoveryCategories.model", "discoveryCategories.model.draft") + } }); diff --git a/app/assets/javascripts/discourse/controllers/navigation/default.js.es6 b/app/assets/javascripts/discourse/controllers/navigation/default.js.es6 index f8d0b330853..0ad18786224 100644 --- a/app/assets/javascripts/discourse/controllers/navigation/default.js.es6 +++ b/app/assets/javascripts/discourse/controllers/navigation/default.js.es6 @@ -1,8 +1,11 @@ +import computed from "ember-addons/ember-computed-decorators"; + export default Ember.Controller.extend({ discovery: Ember.inject.controller(), discoveryTopics: Ember.inject.controller("discovery/topics"), + @computed("discoveryTopics.model", "discoveryTopics.model.draft") draft: function() { return this.get("discoveryTopics.model.draft"); - }.property("discoveryTopics.model", "discoveryTopics.model.draft") + } }); diff --git a/app/assets/javascripts/discourse/controllers/preferences/about.js.es6 b/app/assets/javascripts/discourse/controllers/preferences/about.js.es6 index cd1392f1a39..37e7247a8ab 100644 --- a/app/assets/javascripts/discourse/controllers/preferences/about.js.es6 +++ b/app/assets/javascripts/discourse/controllers/preferences/about.js.es6 @@ -1,8 +1,11 @@ +import computed from "ember-addons/ember-computed-decorators"; + export default Ember.Controller.extend({ saving: false, newBio: null, - saveButtonText: function() { - return this.get("saving") ? I18n.t("saving") : I18n.t("user.change"); - }.property("saving") + @computed("saving") + saveButtonText(saving) { + return saving ? I18n.t("saving") : I18n.t("user.change"); + } }); diff --git a/app/assets/javascripts/discourse/controllers/preferences/interface.js.es6 b/app/assets/javascripts/discourse/controllers/preferences/interface.js.es6 index 8629f612556..ed36721e386 100644 --- a/app/assets/javascripts/discourse/controllers/preferences/interface.js.es6 +++ b/app/assets/javascripts/discourse/controllers/preferences/interface.js.es6 @@ -77,9 +77,10 @@ export default Ember.Controller.extend(PreferencesTabController, { }); }, - userSelectableThemes: function() { + @computed + userSelectableThemes() { return listThemes(this.site); - }.property(), + }, @computed("userSelectableThemes") showThemeSelector(themes) { diff --git a/app/assets/javascripts/discourse/controllers/reorder-categories.js.es6 b/app/assets/javascripts/discourse/controllers/reorder-categories.js.es6 index f3cac072d79..a3ccdf3bce2 100644 --- a/app/assets/javascripts/discourse/controllers/reorder-categories.js.es6 +++ b/app/assets/javascripts/discourse/controllers/reorder-categories.js.es6 @@ -26,13 +26,14 @@ export default Ember.Controller.extend(ModalFunctionality, Ember.Evented, { "categoriesSorting" ), - showApplyAll: function() { + @computed("categoriesBuffered.@each.hasBufferedChanges") + showApplyAll() { let anyChanged = false; this.get("categoriesBuffered").forEach(bc => { anyChanged = anyChanged || bc.get("hasBufferedChanges"); }); return anyChanged; - }.property("categoriesBuffered.@each.hasBufferedChanges"), + }, moveDir(cat, dir) { const cats = this.get("categoriesOrdered"); diff --git a/app/assets/javascripts/discourse/controllers/search-help.js.es6 b/app/assets/javascripts/discourse/controllers/search-help.js.es6 index efbb4663243..be04358f4bf 100644 --- a/app/assets/javascripts/discourse/controllers/search-help.js.es6 +++ b/app/assets/javascripts/discourse/controllers/search-help.js.es6 @@ -1,7 +1,9 @@ import ModalFunctionality from "discourse/mixins/modal-functionality"; +import computed from "ember-addons/ember-computed-decorators"; export default Ember.Controller.extend(ModalFunctionality, { - showGoogleSearch: function() { + @computed + showGoogleSearch() { return !Discourse.SiteSettings.login_required; - }.property() + } }); diff --git a/app/assets/javascripts/discourse/controllers/user-private-messages.js.es6 b/app/assets/javascripts/discourse/controllers/user-private-messages.js.es6 index 6091a569c06..917f552709b 100644 --- a/app/assets/javascripts/discourse/controllers/user-private-messages.js.es6 +++ b/app/assets/javascripts/discourse/controllers/user-private-messages.js.es6 @@ -16,12 +16,12 @@ export default Ember.Controller.extend({ pmTaggingEnabled: Ember.computed.alias("site.can_tag_pms"), tagId: null, - showNewPM: function() { + @computed("user.viewingSelf") + showNewPM(viewingSelf) { return ( - this.get("user.viewingSelf") && - Discourse.User.currentProp("can_send_private_messages") + viewingSelf && Discourse.User.currentProp("can_send_private_messages") ); - }.property("user.viewingSelf"), + }, @computed("selected.[]", "bulkSelectEnabled") hasSelection(selected, bulkSelectEnabled) { diff --git a/app/assets/javascripts/discourse/lib/computed.js.es6 b/app/assets/javascripts/discourse/lib/computed.js.es6 index c70d80d5150..52788ddca9b 100644 --- a/app/assets/javascripts/discourse/lib/computed.js.es6 +++ b/app/assets/javascripts/discourse/lib/computed.js.es6 @@ -1,4 +1,5 @@ import addonFmt from "ember-addons/fmt"; + /** Returns whether two properties are equal to each other. @@ -7,10 +8,11 @@ import addonFmt from "ember-addons/fmt"; @params {String} p2 the second property @return {Function} computedProperty function **/ + export function propertyEqual(p1, p2) { - return Ember.computed(function() { + return Ember.computed(p1, p2, function() { return this.get(p1) === this.get(p2); - }).property(p1, p2); + }); } /** @@ -22,21 +24,21 @@ export function propertyEqual(p1, p2) { @return {Function} computedProperty function **/ export function propertyNotEqual(p1, p2) { - return Ember.computed(function() { + return Ember.computed(p1, p2, function() { return this.get(p1) !== this.get(p2); - }).property(p1, p2); + }); } export function propertyGreaterThan(p1, p2) { - return Ember.computed(function() { + return Ember.computed(p1, p2, function() { return this.get(p1) > this.get(p2); - }).property(p1, p2); + }); } export function propertyLessThan(p1, p2) { - return Ember.computed(function() { + return Ember.computed(p1, p2, function() { return this.get(p1) < this.get(p2); - }).property(p1, p2); + }); } /** diff --git a/app/assets/javascripts/discourse/mixins/badge-select-controller.js.es6 b/app/assets/javascripts/discourse/mixins/badge-select-controller.js.es6 index 671de5801b5..b4d61fcbba5 100644 --- a/app/assets/javascripts/discourse/mixins/badge-select-controller.js.es6 +++ b/app/assets/javascripts/discourse/mixins/badge-select-controller.js.es6 @@ -1,11 +1,12 @@ import Badge from "discourse/models/badge"; +import computed from "ember-addons/ember-computed-decorators"; export default Ember.Mixin.create({ saving: false, saved: false, - selectableUserBadges: function() { - let items = this.get("filteredList"); + @computed("filteredList") + selectableUserBadges(items) { items = _.uniq(items, false, function(e) { return e.get("badge.name"); }); @@ -15,18 +16,16 @@ export default Ember.Mixin.create({ }) ); return items; - }.property("filteredList"), + }, - savingStatus: function() { - if (this.get("saving")) { - return I18n.t("saving"); - } else { - return I18n.t("save"); - } - }.property("saving"), + @computed("saving") + savingStatus(saving) { + return saving ? I18n.t("saving") : I18n.t("save"); + }, - selectedUserBadge: function() { - const selectedUserBadgeId = parseInt(this.get("selectedUserBadgeId")); + @computed("selectedUserBadgeId") + selectedUserBadge(selectedUserBadgeId) { + selectedUserBadgeId = parseInt(selectedUserBadgeId); let selectedUserBadge = null; this.get("selectableUserBadges").forEach(function(userBadge) { if (userBadge.get("id") === selectedUserBadgeId) { @@ -34,7 +33,7 @@ export default Ember.Mixin.create({ } }); return selectedUserBadge; - }.property("selectedUserBadgeId"), + }, disableSave: Ember.computed.alias("saving") }); diff --git a/app/assets/javascripts/discourse/models/action-summary.js.es6 b/app/assets/javascripts/discourse/models/action-summary.js.es6 index 6a2f26e2ee1..683f340be4f 100644 --- a/app/assets/javascripts/discourse/models/action-summary.js.es6 +++ b/app/assets/javascripts/discourse/models/action-summary.js.es6 @@ -3,9 +3,7 @@ import RestModel from "discourse/models/rest"; import { popupAjaxError } from "discourse/lib/ajax-error"; export default RestModel.extend({ - canToggle: function() { - return this.get("can_undo") || this.get("can_act"); - }.property("can_undo", "can_act"), + canToggle: Ember.computed.or("can_undo", "can_act"), // Remove it removeAction: function() { diff --git a/app/assets/javascripts/discourse/models/badge.js.es6 b/app/assets/javascripts/discourse/models/badge.js.es6 index 0658bd631f6..fc66d409668 100644 --- a/app/assets/javascripts/discourse/models/badge.js.es6 +++ b/app/assets/javascripts/discourse/models/badge.js.es6 @@ -1,13 +1,15 @@ import { ajax } from "discourse/lib/ajax"; import BadgeGrouping from "discourse/models/badge-grouping"; import RestModel from "discourse/models/rest"; +import computed from "ember-addons/ember-computed-decorators"; const Badge = RestModel.extend({ newBadge: Ember.computed.none("id"), - url: function() { + @computed + url() { return Discourse.getURL(`/badges/${this.get("id")}/${this.get("slug")}`); - }.property(), + }, /** Update this badge with the response returned by the server on save. @@ -31,10 +33,11 @@ const Badge = RestModel.extend({ } }, - badgeTypeClassName: function() { - const type = this.get("badge_type.name") || ""; + @computed("badge_type.name") + badgeTypeClassName(type) { + type = type || ""; return "badge-type-" + type.toLowerCase(); - }.property("badge_type.name"), + }, /** Save and update the badge from the server's response. diff --git a/app/assets/javascripts/discourse/models/composer.js.es6 b/app/assets/javascripts/discourse/models/composer.js.es6 index be08943e030..f68352e513b 100644 --- a/app/assets/javascripts/discourse/models/composer.js.es6 +++ b/app/assets/javascripts/discourse/models/composer.js.es6 @@ -77,9 +77,10 @@ const Composer = RestModel.extend({ draftSaving: false, draftSaved: false, - archetypes: function() { + @computed + archetypes() { return this.site.get("archetypes"); - }.property(), + }, @computed("action") sharedDraft: action => action === CREATE_SHARED_DRAFT, @@ -184,9 +185,10 @@ const Composer = RestModel.extend({ .property() .volatile(), - archetype: function() { - return this.get("archetypes").findBy("id", this.get("archetypeId")); - }.property("archetypeId"), + @computed("archetypeId") + archetype(archetypeId) { + return this.get("archetypes").findBy("id", archetypeId); + }, archetypeChanged: function() { return this.set("metaData", Ember.Object.create()); @@ -377,30 +379,27 @@ const Composer = RestModel.extend({ ); }, - titleLengthValid: function() { - if ( - this.user.get("admin") && - this.get("post.static_doc") && - this.get("titleLength") > 0 - ) - return true; - if (this.get("titleLength") < this.get("minimumTitleLength")) return false; - return this.get("titleLength") <= this.siteSettings.max_topic_title_length; - }.property("minimumTitleLength", "titleLength", "post.static_doc"), + @computed("minimumTitleLength", "titleLength", "post.static_doc") + titleLengthValid(minTitleLength, titleLength, staticDoc) { + if (this.user.get("admin") && staticDoc && titleLength > 0) return true; + if (titleLength < minTitleLength) return false; + return titleLength <= this.siteSettings.max_topic_title_length; + }, - hasMetaData: function() { - const metaData = this.get("metaData"); + @computed("metaData") + hasMetaData(metaData) { return metaData ? Ember.isEmpty(Ember.keys(this.get("metaData"))) : false; - }.property("metaData"), + }, /** Did the user make changes to the reply? @property replyDirty **/ - replyDirty: function() { - return this.get("reply") !== this.get("originalText"); - }.property("reply", "originalText"), + @computed("reply", "originalText") + replyDirty(reply, originalText) { + return reply !== originalText; + }, /** Did the user make changes to the topic title? @@ -417,9 +416,10 @@ const Composer = RestModel.extend({ @property missingTitleCharacters **/ - missingTitleCharacters: function() { - return this.get("minimumTitleLength") - this.get("titleLength"); - }.property("minimumTitleLength", "titleLength"), + @computed("minimumTitleLength", "titleLength") + missingTitleCharacters(minimumTitleLength, titleLength) { + return minimumTitleLength - titleLength; + }, /** Minimum number of characters for a title to be valid. @@ -474,23 +474,25 @@ const Composer = RestModel.extend({ @property titleLength **/ - titleLength: function() { - const title = this.get("title") || ""; + @computed("title") + titleLength(title) { + title = title || ""; return title.replace(/\s+/gim, " ").trim().length; - }.property("title"), + }, /** Computes the length of the reply minus the quote(s) and non-significant whitespaces @property replyLength **/ - replyLength: function() { - let reply = this.get("reply") || ""; + @computed("reply") + replyLength(reply) { + reply = reply || ""; while (Quote.REGEXP.test(reply)) { reply = reply.replace(Quote.REGEXP, ""); } return reply.replace(/\s+/gim, " ").trim().length; - }.property("reply"), + }, _setupComposer: function() { this.set("archetypeId", this.site.get("default_archetype")); diff --git a/app/assets/javascripts/discourse/models/permission-type.js.es6 b/app/assets/javascripts/discourse/models/permission-type.js.es6 index 08d15a66d8e..858be5722f3 100644 --- a/app/assets/javascripts/discourse/models/permission-type.js.es6 +++ b/app/assets/javascripts/discourse/models/permission-type.js.es6 @@ -1,8 +1,11 @@ +import computed from "ember-addons/ember-computed-decorators"; + const PermissionType = Discourse.Model.extend({ - description: function() { + @computed("id") + description(id) { var key = ""; - switch (this.get("id")) { + switch (id) { case 1: key = "full"; break; @@ -14,7 +17,7 @@ const PermissionType = Discourse.Model.extend({ break; } return I18n.t("permission_types." + key); - }.property("id") + } }); PermissionType.FULL = 1; diff --git a/app/assets/javascripts/discourse/models/post.js.es6 b/app/assets/javascripts/discourse/models/post.js.es6 index ac60a212461..b1a3d893168 100644 --- a/app/assets/javascripts/discourse/models/post.js.es6 +++ b/app/assets/javascripts/discourse/models/post.js.es6 @@ -17,16 +17,17 @@ const Post = RestModel.extend({ return Discourse.SiteSettings; }, - shareUrl: function() { + @computed("url") + shareUrl(url) { const user = Discourse.User.current(); const userSuffix = user ? "?u=" + user.get("username_lower") : ""; if (this.get("firstPost")) { return this.get("topic.url") + userSuffix; } else { - return this.get("url") + userSuffix; + return url + userSuffix; } - }.property("url"), + }, new_user: Ember.computed.equal("trust_level", 0), firstPost: Ember.computed.equal("post_number", 1), @@ -36,36 +37,31 @@ const Post = RestModel.extend({ deleted: Ember.computed.or("deleted_at", "deletedViaTopic"), notDeleted: Ember.computed.not("deleted"), - showName: function() { - const name = this.get("name"); + @computed("name", "username") + showName(name, username) { return ( - name && - name !== this.get("username") && - Discourse.SiteSettings.display_name_on_posts + name && name !== username && Discourse.SiteSettings.display_name_on_posts ); - }.property("name", "username"), + }, - postDeletedBy: function() { - if (this.get("firstPost")) { - return this.get("topic.deleted_by"); - } - return this.get("deleted_by"); - }.property("firstPost", "deleted_by", "topic.deleted_by"), + @computed("firstPost", "deleted_by", "topic.deleted_by") + postDeletedBy(firstPost, deletedBy, topicDeletedBy) { + return firstPost ? topicDeletedBy : deletedBy; + }, - postDeletedAt: function() { - if (this.get("firstPost")) { - return this.get("topic.deleted_at"); - } - return this.get("deleted_at"); - }.property("firstPost", "deleted_at", "topic.deleted_at"), + @computed("firstPost", "deleted_at", "topic.deleted_at") + postDeletedAt(firstPost, deletedAt, topicDeletedAt) { + return firstPost ? topicDeletedAt : deletedAt; + }, - url: function() { + @computed("post_number", "topic_id", "topic.slug") + url(postNr, topicId, slug) { return postUrl( - this.get("topic.slug") || this.get("topic_slug"), - this.get("topic_id") || this.get("topic.id"), - this.get("post_number") + slug || this.get("topic_slug"), + topicId || this.get("topic.id"), + postNr ); - }.property("post_number", "topic_id", "topic.slug"), + }, // Don't drop the /1 @computed("post_number", "url") diff --git a/app/assets/javascripts/discourse/models/result-set.js.es6 b/app/assets/javascripts/discourse/models/result-set.js.es6 index bc36f23f76d..91101bce9d5 100644 --- a/app/assets/javascripts/discourse/models/result-set.js.es6 +++ b/app/assets/javascripts/discourse/models/result-set.js.es6 @@ -1,3 +1,5 @@ +import computed from "ember-addons/ember-computed-decorators"; + export default Ember.ArrayProxy.extend({ loading: false, loadingMore: false, @@ -12,9 +14,10 @@ export default Ember.ArrayProxy.extend({ __type: null, resultSetMeta: null, - canLoadMore: function() { - return this.get("length") < this.get("totalRows"); - }.property("totalRows", "length"), + @computed("totalRows", "length") + canLoadMore(totalRows, length) { + return length < totalRows; + }, loadMore() { const loadMoreUrl = this.get("loadMoreUrl"); diff --git a/app/assets/javascripts/discourse/models/topic-details.js.es6 b/app/assets/javascripts/discourse/models/topic-details.js.es6 index c86b93f2ba0..01b31d5ddd1 100644 --- a/app/assets/javascripts/discourse/models/topic-details.js.es6 +++ b/app/assets/javascripts/discourse/models/topic-details.js.es6 @@ -1,4 +1,6 @@ import { ajax } from "discourse/lib/ajax"; +import computed from "ember-addons/ember-computed-decorators"; + /** A model representing a Topic's details that aren't always present, such as a list of participants. When showing topics in lists and such this information should not be required. @@ -29,15 +31,15 @@ const TopicDetails = RestModel.extend({ this.set("loaded", true); }, - notificationReasonText: function() { - let level = this.get("notification_level"); + @computed("notification_level", "notifications_reason_id") + notificationReasonText(level, reason) { if (typeof level !== "number") { level = 1; } let localeString = `topic.notifications.reasons.${level}`; - if (typeof this.get("notifications_reason_id") === "number") { - const tmp = localeString + "_" + this.get("notifications_reason_id"); + if (typeof reason === "number") { + const tmp = localeString + "_" + reason; // some sane protection for missing translations of edge cases if (I18n.lookup(tmp)) { localeString = tmp; @@ -55,7 +57,7 @@ const TopicDetails = RestModel.extend({ basePath: Discourse.BaseUri }); } - }.property("notification_level", "notifications_reason_id"), + }, updateNotifications(v) { this.set("notification_level", v); diff --git a/app/assets/javascripts/discourse/models/user-action-stat.js.es6 b/app/assets/javascripts/discourse/models/user-action-stat.js.es6 index 089225b2a4e..fd531cde9ad 100644 --- a/app/assets/javascripts/discourse/models/user-action-stat.js.es6 +++ b/app/assets/javascripts/discourse/models/user-action-stat.js.es6 @@ -1,23 +1,24 @@ import RestModel from "discourse/models/rest"; import UserAction from "discourse/models/user-action"; import { i18n } from "discourse/lib/computed"; +import computed from "ember-addons/ember-computed-decorators"; export default RestModel.extend({ - isPM: function() { - const actionType = this.get("action_type"); + @computed("action_type") + isPM(actionType) { return ( actionType === UserAction.TYPES.messages_sent || actionType === UserAction.TYPES.messages_received ); - }.property("action_type"), + }, description: i18n("action_type", "user_action_groups.%@"), - isResponse: function() { - const actionType = this.get("action_type"); + @computed("action_type") + isResponse(actionType) { return ( actionType === UserAction.TYPES.replies || actionType === UserAction.TYPES.quotes ); - }.property("action_type") + } }); diff --git a/app/assets/javascripts/discourse/models/user-action.js.es6 b/app/assets/javascripts/discourse/models/user-action.js.es6 index 8f2d6986a01..db3a357530a 100644 --- a/app/assets/javascripts/discourse/models/user-action.js.es6 +++ b/app/assets/javascripts/discourse/models/user-action.js.es6 @@ -164,16 +164,7 @@ const UserAction = RestModel.extend({ } }, - children: function() { - const g = this.get("childGroups"); - let rval = []; - if (g) { - rval = [g.likes, g.stars, g.edits, g.bookmarks].filter(function(i) { - return i.get("items") && i.get("items").length > 0; - }); - } - return rval; - }.property( + @computed( "childGroups", "childGroups.likes.items", "childGroups.likes.items.[]", @@ -183,7 +174,17 @@ const UserAction = RestModel.extend({ "childGroups.edits.items.[]", "childGroups.bookmarks.items", "childGroups.bookmarks.items.[]" - ), + ) + children() { + const g = this.get("childGroups"); + let rval = []; + if (g) { + rval = [g.likes, g.stars, g.edits, g.bookmarks].filter(function(i) { + return i.get("items") && i.get("items").length > 0; + }); + } + return rval; + }, switchToActing() { this.setProperties({ diff --git a/app/assets/javascripts/discourse/models/user-badge.js.es6 b/app/assets/javascripts/discourse/models/user-badge.js.es6 index d746efc2b80..7022a1d8fbe 100644 --- a/app/assets/javascripts/discourse/models/user-badge.js.es6 +++ b/app/assets/javascripts/discourse/models/user-badge.js.es6 @@ -1,12 +1,14 @@ import { ajax } from "discourse/lib/ajax"; import Badge from "discourse/models/badge"; +import computed from "ember-addons/ember-computed-decorators"; const UserBadge = Discourse.Model.extend({ + @computed postUrl: function() { if (this.get("topic_title")) { return "/t/-/" + this.get("topic_id") + "/" + this.get("post_number"); } - }.property(), // avoid the extra bindings for now + }, // avoid the extra bindings for now revoke() { return ajax("/user_badges/" + this.get("id"), { diff --git a/app/assets/javascripts/discourse/models/user-stream.js.es6 b/app/assets/javascripts/discourse/models/user-stream.js.es6 index bca6e7c0bc6..ee2efcd1c05 100644 --- a/app/assets/javascripts/discourse/models/user-stream.js.es6 +++ b/app/assets/javascripts/discourse/models/user-stream.js.es6 @@ -3,6 +3,7 @@ import { url } from "discourse/lib/computed"; import RestModel from "discourse/models/rest"; import UserAction from "discourse/models/user-action"; import { emojiUnescape } from "discourse/lib/text"; +import computed from "ember-addons/ember-computed-decorators"; export default RestModel.extend({ loaded: false, @@ -11,8 +12,8 @@ export default RestModel.extend({ this.setProperties({ itemsLoaded: 0, content: [] }); }.on("init"), - filterParam: function() { - const filter = this.get("filter"); + @computed("filter") + filterParam(filter) { if (filter === Discourse.UserAction.TYPES.replies) { return [UserAction.TYPES.replies, UserAction.TYPES.quotes].join(","); } @@ -22,7 +23,7 @@ export default RestModel.extend({ } return filter; - }.property("filter"), + }, baseUrl: url( "itemsLoaded", @@ -45,9 +46,10 @@ export default RestModel.extend({ return this.findItems(); }, - noContent: function() { + @computed("loaded", "content.[]") + noContent() { return this.get("loaded") && this.get("content").length === 0; - }.property("loaded", "content.[]"), + }, remove(userAction) { // 1) remove the user action from the child groups diff --git a/app/assets/javascripts/discourse/raw-views/list/visited-line.js.es6 b/app/assets/javascripts/discourse/raw-views/list/visited-line.js.es6 index 0f928e3f3a7..b276022a1d6 100644 --- a/app/assets/javascripts/discourse/raw-views/list/visited-line.js.es6 +++ b/app/assets/javascripts/discourse/raw-views/list/visited-line.js.es6 @@ -1,5 +1,8 @@ +import computed from "ember-addons/ember-computed-decorators"; + export default Ember.Object.extend({ + @computed isLastVisited: function() { return this.get("lastVisitedTopic") === this.get("topic"); - }.property() + } }); diff --git a/app/assets/javascripts/discourse/templates/components/basic-topic-list.hbs b/app/assets/javascripts/discourse/templates/components/basic-topic-list.hbs index d1d105121ef..727715048ee 100644 --- a/app/assets/javascripts/discourse/templates/components/basic-topic-list.hbs +++ b/app/assets/javascripts/discourse/templates/components/basic-topic-list.hbs @@ -17,7 +17,7 @@ bulkSelectEnabled=bulkSelectEnabled canBulkSelect=canBulkSelect selected=selected - skipHeader=skipHeader + skipHeader=site.mobileView tagsForUser=tagsForUser}} {{else}} {{#unless loadingMore}} diff --git a/app/assets/javascripts/discourse/templates/components/topic-list.hbs b/app/assets/javascripts/discourse/templates/components/topic-list.hbs index 46e05f4e4d6..cb9d4ab320e 100644 --- a/app/assets/javascripts/discourse/templates/components/topic-list.hbs +++ b/app/assets/javascripts/discourse/templates/components/topic-list.hbs @@ -1,4 +1,4 @@ -{{#unless skipHeader}} +{{#unless site.mobileView}} {{raw "topic-list-header" canBulkSelect=canBulkSelect