FEATURE: Display avatars of PM recepients in small topic header when scrolling down

FEATURE: Display avatars of PM recepients in small topic header when scrolling down

diff --git a/app/assets/javascripts/discourse/mixins/card-contents-base.js.es6 b/app/assets/javascripts/discourse/mixins/card-contents-base.js.es6
index d757fad..7c00979 100644
--- a/app/assets/javascripts/discourse/mixins/card-contents-base.js.es6
+++ b/app/assets/javascripts/discourse/mixins/card-contents-base.js.es6
@@ -121,6 +121,10 @@ export default Ember.Mixin.create({
       this.set("isFixed", true);
       return this._show($target.text().replace(/^@/, ""), $target);
     });
+
+    this.appEvents.on(`topic-header:trigger-${id}`, (username, $target) => {
+      return this._show(username, $target);
+    });
   },
 
   _positionCard(target) {
diff --git a/app/assets/javascripts/discourse/widgets/header-topic-info.js.es6 b/app/assets/javascripts/discourse/widgets/header-topic-info.js.es6
index def3708..26d54b7 100644
--- a/app/assets/javascripts/discourse/widgets/header-topic-info.js.es6
+++ b/app/assets/javascripts/discourse/widgets/header-topic-info.js.es6
@@ -5,6 +5,53 @@ import DiscourseURL from "discourse/lib/url";
 import RawHtml from "discourse/widgets/raw-html";
 import renderTags from "discourse/lib/render-tags";
 import { topicFeaturedLinkNode } from "discourse/lib/render-topic-featured-link";
+import { avatarImg } from "discourse/widgets/post";
+
+createWidget("topic-header-participant", {
+  tagName: "span",
+
+  buildClasses(attrs) {
+    return `trigger-${attrs.type}-card`;
+  },
+
+  html(attrs) {
+    const { user, group } = attrs;
+    let avatar, url;
+
+    if (attrs.type === "user") {
+      avatar = avatarImg("tiny", {
+        template: user.avatar_template,
+        username: user.username
+      });
+      url = user.get("path");
+    } else {
+      avatar = iconNode("users");
+      url = Discourse.getURL(`/groups/${group.name}`);
+    }
+
+    return h(
+      "a.icon",
+      {
+        attributes: {
+          href: url,
+          "data-auto-route": true,
+          title: attrs.username
+        }
+      },
+      avatar
+    );
+  },
+
+  click(e) {
+    const $target = $(e.target);
+    this.appEvents.trigger(
+      `topic-header:trigger-${this.attrs.type}-card`,
+      this.attrs.username,
+      $target
+    );
+    e.preventDefault();
+  }
+});
 
 export default createWidget("header-topic-info", {
   tagName: "div.extra-info-wrapper",
@@ -73,6 +120,58 @@ export default createWidget("header-topic-info", {
         extra.push(new RawHtml({ html: tags }));
       }
 
+      if (showPM) {
+        const maxHeaderParticipants = extra.length > 0 ? 5 : 10;
+        const participants = [];
+        const topicDetails = topic.get("details");
+        const totalParticipants =
+          topicDetails.allowed_users.length +
+          topicDetails.allowed_groups.length;
+
+        topicDetails.allowed_users.some(user => {
+          if (participants.length >= maxHeaderParticipants) {
+            return true;
+          }
+
+          participants.push(
+            this.attach("topic-header-participant", {
+              type: "user",
+              user: user,
+              username: user.username
+            })
+          );
+        });
+
+        topicDetails.allowed_groups.some(group => {
+          if (participants.length >= maxHeaderParticipants) {
+            return true;
+          }
+
+          participants.push(
+            this.attach("topic-header-participant", {
+              type: "group",
+              group: group,
+              username: group.name
+            })
+          );
+        });
+
+        if (totalParticipants > maxHeaderParticipants) {
+          const remaining = totalParticipants - maxHeaderParticipants;
+          participants.push(
+            this.attach("link", {
+              className: "more-participants",
+              action: "jumpToTopPost",
+              href,
+              attributes: { "data-topic-id": topic.get("id") },
+              contents: () => `+${remaining}`
+            })
+          );
+        }
+
+        extra.push(h("div.topic-header-participants", participants));
+      }
+
       extra = extra.concat(applyDecorators(this, "after-tags", attrs, state));
 
       if (this.siteSettings.topic_featured_link_enabled) {
diff --git a/app/assets/stylesheets/common/base/header.scss b/app/assets/stylesheets/common/base/header.scss
index cf921b1..0e49474 100644
--- a/app/assets/stylesheets/common/base/header.scss
+++ b/app/assets/stylesheets/common/base/header.scss
@@ -299,3 +299,27 @@
     min-width: 0;
   }
 }
+
+.topic-header-participants {
+  &:not(:first-child) {
+    margin-left: 4px;
+  }
+
+  > span {
+    margin: 0 2px;
+    display: inline-block;
+    height: 20px;
+  }
+
+  .trigger-group-card {
+    line-height: 20px;
+    margin: 0 4px;
+  }
+
+  .more-participants {
+    display: inline-block;
+    color: $header_primary-high;
+    line-height: 20px;
+    padding: 0 4px;
+  }
+}

GitHub
sha: 021f11b6

1 Like

I believe only user should suffice here by the virtue of ES6 property value shorthand ?

1 Like

Same here.

1 Like

Thanks @techAPJ . I made the changes in commit UX: Add group name next to PM recipient avatar · discourse/discourse@0884cd2 · GitHub

2 Likes