DEV: Export the default behaviour of a topic-list-item so it can be reused by the discourse-assign plugin (#7433)

DEV: Export the default behaviour of a topic-list-item so it can be reused by the discourse-assign plugin (#7433)

diff --git a/app/assets/javascripts/discourse/components/topic-list-item.js.es6 b/app/assets/javascripts/discourse/components/topic-list-item.js.es6
index 19065d4..0549660 100644
--- a/app/assets/javascripts/discourse/components/topic-list-item.js.es6
+++ b/app/assets/javascripts/discourse/components/topic-list-item.js.es6
@@ -29,175 +29,176 @@ export function navigateToTopic(topic, href) {
   return false;
 }
 
-export default Ember.Component.extend(
-  bufferedRender({
-    rerenderTriggers: ["bulkSelectEnabled", "topic.pinned"],
-    tagName: "tr",
-    classNameBindings: [
-      ":topic-list-item",
-      "unboundClassNames",
-      "topic.visited"
-    ],
-    attributeBindings: ["data-topic-id"],
-    "data-topic-id": Ember.computed.alias("topic.id"),
+export const ListItemDefaults = {
+  tagName: "tr",
+
+  @computed
+  newDotText() {
+    return this.currentUser && this.currentUser.trust_level > 0
+      ? ""
+      : I18n.t("filters.new.lower_title");
+  },
+
+  @computed("topic", "lastVisitedTopic")
+  unboundClassNames(topic, lastVisitedTopic) {
+    let classes = [];
+
+    if (topic.get("category")) {
+      classes.push("category-" + topic.get("category.fullSlug"));
+    }
 
-    @computed
-    newDotText() {
-      return this.currentUser && this.currentUser.trust_level > 0
-        ? ""
-        : I18n.t("filters.new.lower_title");
-    },
+    if (topic.get("tags")) {
+      topic.get("tags").forEach(tagName => classes.push("tag-" + tagName));
+    }
 
-    actions: {
-      toggleBookmark() {
-        this.get("topic")
-          .toggleBookmark()
-          .finally(() => this.rerenderBuffer());
-      }
-    },
+    if (topic.get("hasExcerpt")) {
+      classes.push("has-excerpt");
+    }
 
-    buildBuffer(buffer) {
-      const template = findRawTemplate("list/topic-list-item");
-      if (template) {
-        buffer.push(template(this));
-      }
-    },
+    if (topic.get("unseen")) {
+      classes.push("unseen-topic");
+    }
 
-    @computed("topic", "lastVisitedTopic")
-    unboundClassNames(topic, lastVisitedTopic) {
-      let classes = [];
+    if (topic.get("displayNewPosts")) {
+      classes.push("new-posts");
+    }
 
-      if (topic.get("category")) {
-        classes.push("category-" + topic.get("category.fullSlug"));
+    ["liked", "archived", "bookmarked", "pinned", "closed"].forEach(name => {
+      if (topic.get(name)) {
+        classes.push(name);
       }
+    });
 
-      if (topic.get("tags")) {
-        topic.get("tags").forEach(tagName => classes.push("tag-" + tagName));
-      }
+    if (topic === lastVisitedTopic) {
+      classes.push("last-visit");
+    }
 
-      if (topic.get("hasExcerpt")) {
-        classes.push("has-excerpt");
-      }
+    return classes.join(" ");
+  },
 
-      if (topic.get("unseen")) {
-        classes.push("unseen-topic");
-      }
+  hasLikes: function() {
+    return this.get("topic.like_count") > 0;
+  },
 
-      if (topic.get("displayNewPosts")) {
-        classes.push("new-posts");
-      }
+  hasOpLikes: function() {
+    return this.get("topic.op_like_count") > 0;
+  },
 
-      ["liked", "archived", "bookmarked", "pinned", "closed"].forEach(name => {
-        if (topic.get(name)) {
-          classes.push(name);
-        }
-      });
+  @computed
+  expandPinned: function() {
+    const pinned = this.get("topic.pinned");
+    if (!pinned) {
+      return false;
+    }
 
-      if (topic === lastVisitedTopic) {
-        classes.push("last-visit");
+    if (this.site.mobileView) {
+      if (!this.siteSettings.show_pinned_excerpt_mobile) {
+        return false;
       }
+    } else {
+      if (!this.siteSettings.show_pinned_excerpt_desktop) {
+        return false;
+      }
+    }
 
-      return classes.join(" ");
-    },
+    if (this.get("expandGloballyPinned") && this.get("topic.pinned_globally")) {
+      return true;
+    }
 
-    hasLikes: function() {
-      return this.get("topic.like_count") > 0;
-    },
+    if (this.get("expandAllPinned")) {
+      return true;
+    }
 
-    hasOpLikes: function() {
-      return this.get("topic.op_like_count") > 0;
-    },
+    return false;
+  },
 
-    @computed
-    expandPinned: function() {
-      const pinned = this.get("topic.pinned");
-      if (!pinned) {
-        return false;
-      }
+  showEntrance,
 
-      if (this.site.mobileView) {
-        if (!this.siteSettings.show_pinned_excerpt_mobile) {
-          return false;
-        }
-      } else {
-        if (!this.siteSettings.show_pinned_excerpt_desktop) {
-          return false;
-        }
-      }
+  click(e) {
+    const result = this.showEntrance(e);
+    if (result === false) {
+      return result;
+    }
 
-      if (
-        this.get("expandGloballyPinned") &&
-        this.get("topic.pinned_globally")
-      ) {
-        return true;
+    const topic = this.get("topic");
+    const target = $(e.target);
+    if (target.hasClass("bulk-select")) {
+      const selected = this.get("selected");
+
+      if (target.is(":checked")) {
+        selected.addObject(topic);
+      } else {
+        selected.removeObject(topic);
       }
+    }
 
-      if (this.get("expandAllPinned")) {
+    if (target.hasClass("raw-topic-link")) {
+      if (wantsNewWindow(e)) {
         return true;
       }
+      return this.navigateToTopic(topic, target.attr("href"));
+    }
 
+    if (target.closest("a.topic-status").length === 1) {
+      this.get("topic").togglePinnedForUser();
       return false;
-    },
-
-    showEntrance,
-
-    click(e) {
-      const result = this.showEntrance(e);
-      if (result === false) {
-        return result;
-      }
+    }
 
-      const topic = this.get("topic");
-      const target = $(e.target);
-      if (target.hasClass("bulk-select")) {
-        const selected = this.get("selected");
+    return this.unhandledRowClick(e, topic);
+  },
+
+  navigateToTopic,
+
+  highlight(opts = { isLastViewedTopic: false }) {
+    const $topic = this.$();
+    $topic
+      .addClass("highlighted")
+      .attr("data-islastviewedtopic", opts.isLastViewedTopic);
+
+    $topic.on("animationend", () => $topic.removeClass("highlighted"));
+  },
+
+  _highlightIfNeeded: function() {
+    // highlight the last topic viewed
+    if (this.session.get("lastTopicIdViewed") === this.get("topic.id")) {
+      this.session.set("lastTopicIdViewed", null);
+      this.highlight({ isLastViewedTopic: true });
+    } else if (this.get("topic.highlight")) {
+      // highlight new topics that have been loaded from the server or the one we just created
+      this.set("topic.highlight", false);
+      this.highlight();
+    }
+  }.on("didInsertElement")
+};
 
-        if (target.is(":checked")) {
-          selected.addObject(topic);
-        } else {
-          selected.removeObject(topic);
-        }
-      }
+export default Ember.Component.extend(
+  ListItemDefaults,
+  bufferedRender({
+    rerenderTriggers: ["bulkSelectEnabled", "topic.pinned"],
+    classNameBindings: [
+      ":topic-list-item",
+      "unboundClassNames",
+      "topic.visited"
+    ],
+    attributeBindings: ["data-topic-id"],
+    "data-topic-id": Ember.computed.alias("topic.id"),
 
-      if (target.hasClass("raw-topic-link")) {
-        if (wantsNewWindow(e)) {
-          return true;
-        }
-        return this.navigateToTopic(topic, target.attr("href"));
+    actions: {
+      toggleBookmark() {
+        this.get("topic")
+          .toggleBookmark()
+          .finally(() => this.rerenderBuffer());
       }
+    },
 
-      if (target.closest("a.topic-status").length === 1) {
-        this.get("topic").togglePinnedForUser();
-        return false;
+    buildBuffer(buffer) {
+      const template = findRawTemplate("list/topic-list-item");
+      if (template) {
+        buffer.push(template(this));
       }
-
-      return this.unhandledRowClick(e, topic);
     },
 
-    navigateToTopic,
-
     // Can be overwritten by plugins to handle clicks on other parts of the row
-    unhandledRowClick() {},
-
-    highlight(opts = { isLastViewedTopic: false }) {

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

GitHub sha: 404666c9