Customize template used by post widget

On the pre-v2 installs I used to override the post hbs templates. I noticed in the github notes that the Discourse team converted this into a widget to enhance performance and it’s very noticeable in the browser. Within the widget layout the following looks interesting to me:

app/assets/javascripts/discourse/widgets/post-placeholder.js.es6


import { createWidget } from "discourse/widgets/widget";
import hbs from "discourse/widgets/hbs-compiler";

export default createWidget("post-placeholder", {
  tagName: "article.placeholder",
  template: hbs`
    <div class='row'>
      <div class='topic-avatar'>
        <div class='placeholder-avatar'></div>
      </div>
      <div class='topic-body'>
        <div class='placeholder-text'></div>
        <div class='placeholder-text'></div>
        <div class='placeholder-text'></div>
      </div>
    </div>
  `
});

app/assets/javascripts/discourse/widgets/post.js.es6



 createWidget("post-article", {
  tagName: "article.boxed.onscreen-post",
  buildKey: attrs => `post-article-${attrs.id}`,

  defaultState() {
    return { repliesAbove: [] };
  },

  buildId(attrs) {
    return `post_${attrs.post_number}`;
  },

  buildClasses(attrs) {
    let classNames = [];
    if (attrs.via_email) {
      classNames.push("via-email");
    }
    if (attrs.isAutoGenerated) {
      classNames.push("is-auto-generated");
    }
    return classNames;
  },

  buildAttributes(attrs) {
    return { "data-post-id": attrs.id, "data-user-id": attrs.user_id };
  },

  html(attrs, state) {
    const rows = [h("a.tabLoc", { attributes: { href: "" } })];
    if (state.repliesAbove.length) {
      const replies = state.repliesAbove.map(p => {
        return this.attach("embedded-post", p, {
          model: this.store.createRecord("post", p),
          state: { above: true }
        });
      });

      rows.push(
        h(
          "div.row",
          h("section.embedded-posts.top.topic-body.offset2", [
            this.attach("button", {
              title: "post.collapse",
              icon: "chevron-down",
              action: "toggleReplyAbove",
              actionParam: "true",
              className: "btn collapse-down"
            }),
            replies
          ])
        )
      );
    }

    rows.push(
      h("div.row", [
        this.attach("post-avatar", attrs),
        this.attach("post-body", attrs)
      ])
    );
    return rows;
  },

  _getTopicUrl() {
    const post = this.findAncestorModel();
    return post ? post.get("topic.url") : null;
  },

  toggleReplyAbove(goToPost = "false") {
    const replyPostNumber = this.attrs.reply_to_post_number;

    // jump directly on mobile
    if (this.attrs.mobileView) {
      const topicUrl = this._getTopicUrl();
      if (topicUrl) {
        DiscourseURL.routeTo(`${topicUrl}/${replyPostNumber}`);
      }
      return Ember.RSVP.Promise.resolve();
    }

    if (this.state.repliesAbove.length) {
      this.state.repliesAbove = [];
      if (goToPost === "true") {
        DiscourseURL.routeTo(
          `${this.attrs.topicUrl}/${this.attrs.post_number}`
        );
      }
      return Ember.RSVP.Promise.resolve();
    } else {
      const topicUrl = this._getTopicUrl();
      return this.store
        .find("post-reply-history", { postId: this.attrs.id })
        .then(posts => {
          this.state.repliesAbove = posts.map(p => {
            p.shareUrl = `${topicUrl}/${p.post_number}`;
            return transformBasicPost(p);
          });
        });
    }
  }
});

But I am not sure how or where to customize the post .row and dont want to go the hackish route if I don’t have to. Do I want to reopen the widget and Customize it through the Header tab in the admin interface or would it be better to use a plugin to override the files? Any nudges in the right direction would be much appreciated I basically want to make slight rearrangements/additions to the post layout.

Thank you and sorry if this is a duplicate topic.

Edited: because mobile device butchered my spelling

4 Likes

The best way to modify the post templates is to use the decorateWidget method in the plugin API. You can use that to add content before/after the built-in template. There are some brief instructions here for doing that in a theme.

To fully override the template you would use reopenWidget to override the html() method. Some instructions are here.

Adding things before/after is a far more ‘future proof’ way to work, so try and do that if you can. If you have some specifics on what you want to change about the post layout, I’m sure someone will be able to give some more specific advice.

11 Likes