REFACTOR: topic model (#7020)

REFACTOR: topic model (#7020)

diff --git a/app/assets/javascripts/discourse/models/topic.js.es6 b/app/assets/javascripts/discourse/models/topic.js.es6
index 489333e..70ae169 100644
--- a/app/assets/javascripts/discourse/models/topic.js.es6
+++ b/app/assets/javascripts/discourse/models/topic.js.es6
@@ -1,30 +1,34 @@
 import { ajax } from "discourse/lib/ajax";
 import { flushMap } from "discourse/models/store";
 import RestModel from "discourse/models/rest";
-import { propertyEqual } from "discourse/lib/computed";
+import { propertyEqual, fmt } from "discourse/lib/computed";
 import { longDate } from "discourse/lib/formatter";
 import { isRTL } from "discourse/lib/text-direction";
-import computed from "ember-addons/ember-computed-decorators";
 import ActionSummary from "discourse/models/action-summary";
 import { popupAjaxError } from "discourse/lib/ajax-error";
 import { censor } from "pretty-text/censored-words";
 import { emojiUnescape } from "discourse/lib/text";
 import PreloadStore from "preload-store";
 import { userPath } from "discourse/lib/url";
+import {
+  default as computed,
+  observes,
+  on
+} from "ember-addons/ember-computed-decorators";
 
 export function loadTopicView(topic, args) {
   const topicId = topic.get("id");
   const data = _.merge({}, args);
-  const url = Discourse.getURL("/t/") + topicId;
+  const url = `${Discourse.getURL("/t/")}${topicId}`;
   const jsonUrl = (data.nearPost ? `${url}/${data.nearPost}` : url) + ".json";
 
   delete data.nearPost;
   delete data.__type;
   delete data.store;
 
-  return PreloadStore.getAndRemove(`topic_${topicId}`, () => {
-    return ajax(jsonUrl, { data });
-  }).then(json => {
+  return PreloadStore.getAndRemove(`topic_${topicId}`, () =>
+    ajax(jsonUrl, { data })
+  ).then(json => {
     topic.updateFromJson(json);
     return json;
   });
@@ -101,44 +105,44 @@ const Topic = RestModel.extend({
     );
 
     if (Discourse.SiteSettings.support_mixed_text_direction) {
-      let titleDir = isRTL(title) ? "rtl" : "ltr";
+      const titleDir = isRTL(title) ? "rtl" : "ltr";
       return `<span dir="${titleDir}">${fancyTitle}</span>`;
     }
     return fancyTitle;
   },
 
   // returns createdAt if there's no bumped date
-  bumpedAt: function() {
-    const bumpedAt = this.get("bumped_at");
-    if (bumpedAt) {
-      return new Date(bumpedAt);
+  @computed("bumped_at", "createdAt")
+  bumpedAt(bumped_at, createdAt) {
+    if (bumped_at) {
+      return new Date(bumped_at);
     } else {
-      return this.get("createdAt");
+      return createdAt;
     }
-  }.property("bumped_at", "createdAt"),
-
-  bumpedAtTitle: function() {
-    return (
-      I18n.t("first_post") +
-      ": " +
-      longDate(this.get("createdAt")) +
-      "\n" +
-      I18n.t("last_post") +
-      ": " +
-      longDate(this.get("bumpedAt"))
-    );
-  }.property("bumpedAt"),
+  },
 
-  createdAt: function() {
-    return new Date(this.get("created_at"));
-  }.property("created_at"),
+  @computed("bumpedAt", "createdAt")
+  bumpedAtTitle(bumpedAt, createdAt) {
+    const firstPost = I18n.t("first_post");
+    const lastPost = I18n.t("last_post");
+    const createdAtDate = longDate(createdAt);
+    const bumpedAtDate = longDate(bumpedAt);
+
+    return `${firstPost}: ${createdAtDate}\n${lastPost}: ${bumpedAtDate}`;
+  },
 
-  postStream: function() {
+  @computed("created_at")
+  createdAt(created_at) {
+    return new Date(created_at);
+  },
+
+  @computed
+  postStream() {
     return this.store.createRecord("postStream", {
       id: this.get("id"),
       topic: this
     });
-  }.property(),
+  },
 
   @computed("tags")
   visibleListTags(tags) {
@@ -165,9 +169,7 @@ const Topic = RestModel.extend({
 
       return this.set(
         "related_messages",
-        relatedMessages.map(st => {
-          return store.createRecord("topic", st);
-        })
+        relatedMessages.map(st => store.createRecord("topic", st))
       );
     }
   },
@@ -179,115 +181,116 @@ const Topic = RestModel.extend({
 
       return this.set(
         "suggested_topics",
-        suggestedTopics.map(st => {
-          return store.createRecord("topic", st);
-        })
+        suggestedTopics.map(st => store.createRecord("topic", st))
       );
     }
   },
 
-  replyCount: function() {
-    return this.get("posts_count") - 1;
-  }.property("posts_count"),
+  @computed("posts_count")
+  replyCount(postsCount) {
+    return postsCount - 1;
+  },
 
-  details: function() {
+  @computed
+  details() {
     return this.store.createRecord("topicDetails", {
       id: this.get("id"),
       topic: this
     });
-  }.property(),
+  },
 
   invisible: Ember.computed.not("visible"),
   deleted: Ember.computed.notEmpty("deleted_at"),
 
-  searchContext: function() {
-    return { type: "topic", id: this.get("id") };
-  }.property("id"),
+  @computed("id")
+  searchContext(id) {
+    return { type: "topic", id };
+  },
 
-  _categoryIdChanged: function() {
+  @on("init")
+  @observes("category_id")
+  _categoryIdChanged() {
     this.set("category", Discourse.Category.findById(this.get("category_id")));
-  }
-    .observes("category_id")
-    .on("init"),
+  },
 
-  _categoryNameChanged: function() {
+  @observes("categoryName")
+  _categoryNameChanged() {
     const categoryName = this.get("categoryName");
     let category;
     if (categoryName) {
       category = this.site.get("categories").findBy("name", categoryName);
     }
     this.set("category", category);
-  }.observes("categoryName"),
-
-  categoryClass: function() {
-    return "category-" + this.get("category.fullSlug");
-  }.property("category.fullSlug"),
+  },
 
-  shareUrl: function() {
-    const user = Discourse.User.current();
-    return this.get("url") + (user ? "?u=" + user.get("username_lower") : "");
-  }.property("url"),
+  categoryClass: fmt("category.fullSlug", "category-%@"),
 
   @computed("url")
-  printUrl(url) {
-    return url + "/print";
+  shareUrl(url) {
+    const user = Discourse.User.current();
+    const userQueryString = user ? `?u=${user.get("username_lower")}` : "";
+    return `${url}${userQueryString}`;
   },
 
-  url: function() {
-    let slug = this.get("slug") || "";
+  printUrl: fmt("url", "%@/print"),
+
+  @computed("id", "slug")
+  url(id, slug) {
+    slug = slug || "";
     if (slug.trim().length === 0) {
       slug = "topic";
     }
-    return Discourse.getURL("/t/") + slug + "/" + this.get("id");
-  }.property("id", "slug"),
+    return `${Discourse.getURL("/t/")}${slug}/${id}`;
+  },
 
   // Helper to build a Url with a post number
   urlForPostNumber(postNumber) {
     let url = this.get("url");
     if (postNumber && postNumber > 0) {
-      url += "/" + postNumber;
+      url += `/${postNumber}`;
     }
     return url;
   },
 
-  totalUnread: function() {
-    const count = (this.get("unread") || 0) + (this.get("new_posts") || 0);
+  @computed("new_posts", "unread")
+  totalUnread(newPosts, unread) {
+    const count = (unread || 0) + (newPosts || 0);
     return count > 0 ? count : null;
-  }.property("new_posts", "unread"),
-
-  lastReadUrl: function() {
-    return this.urlForPostNumber(this.get("last_read_post_number"));
-  }.property("url", "last_read_post_number"),
+  },
 
-  lastUnreadUrl: function() {
-    const highest = this.get("highest_post_number");
-    const lastRead = this.get("last_read_post_number");
+  @computed("last_read_post_number", "url")
+  lastReadUrl(lastReadPostNumber) {
+    return this.urlForPostNumber(lastReadPostNumber);
+  },
 
-    if (highest <= lastRead) {
+  @computed("last_read_post_number", "highest_post_number", "url")
+  lastUnreadUrl(lastReadPostNumber, highestPostNumber) {
+    if (highestPostNumber <= lastReadPostNumber) {
       if (this.get("category.navigate_to_first_post_after_read")) {
         return this.urlForPostNumber(1);
       } else {
-        return this.urlForPostNumber(lastRead + 1);
+        return this.urlForPostNumber(lastReadPostNumber + 1);
       }
     } else {

[... diff too long, it was truncated ...]

GitHub sha: 8a4cd15e