diff --git a/app/assets/javascripts/discourse/app/components/topic-map/topic-participant.gjs b/app/assets/javascripts/discourse/app/components/topic-map/topic-participant.gjs
new file mode 100644
index 00000000000..2d9de5debb3
--- /dev/null
+++ b/app/assets/javascripts/discourse/app/components/topic-map/topic-participant.gjs
@@ -0,0 +1,70 @@
+import Component from "@glimmer/component";
+import { htmlSafe } from "@ember/template";
+import UserAvatarFlair from "discourse/components/user-avatar-flair";
+import { userPath } from "discourse/lib/url";
+import { avatarImg } from "discourse-common/lib/avatar-utils";
+import gt from "truth-helpers/helpers/gt";
+
+const addTopicParticipantClassesCallbacks = [];
+
+export function addTopicParticipantClassesCallback(callback) {
+ addTopicParticipantClassesCallbacks.push(callback);
+}
+
+export default class TopicParticipant extends Component {
+ get avatarImage() {
+ return htmlSafe(
+ avatarImg({
+ avatarTemplate: this.args.participant.avatar_template,
+ size: "medium",
+ title: this.args.participant.name || this.args.participant.username,
+ })
+ );
+ }
+
+ get participantClasses() {
+ const { primary_group_name } = this.args.participant;
+ return [
+ primary_group_name ? `group-${primary_group_name}` : null,
+ addTopicParticipantClassesCallbacks.map((callback) =>
+ callback(this.args.participant)
+ ),
+ ]
+ .filter(Boolean)
+ .flat(3)
+ .join(" ");
+ }
+
+ get linkClasses() {
+ return [
+ "poster",
+ "trigger-user-card",
+ this.args.toggledUsers?.has(this.args.participant.username)
+ ? "toggled"
+ : null,
+ ]
+ .filter(Boolean)
+ .join(" ");
+ }
+
+ get userUrl() {
+ userPath(this.args.participant);
+ }
+
+
+
+
+}
diff --git a/app/assets/javascripts/discourse/app/components/topic-map/topic-participants.gjs b/app/assets/javascripts/discourse/app/components/topic-map/topic-participants.gjs
new file mode 100644
index 00000000000..a8bfe728bef
--- /dev/null
+++ b/app/assets/javascripts/discourse/app/components/topic-map/topic-participants.gjs
@@ -0,0 +1,17 @@
+import Component from "@glimmer/component";
+import TopicParticipant from "discourse/components/topic-map/topic-participant";
+
+export default class TopicParticipants extends Component {
+ // prettier-ignore
+ toggledUsers = new Set(this.args.userFilters);
+
+
+ {{@title}}
+ {{#each @participants as |participant|}}
+
+ {{/each}}
+
+}
diff --git a/app/assets/javascripts/discourse/app/lib/plugin-api.js b/app/assets/javascripts/discourse/app/lib/plugin-api.js
index 78b209919bf..ea3457b5a24 100644
--- a/app/assets/javascripts/discourse/app/lib/plugin-api.js
+++ b/app/assets/javascripts/discourse/app/lib/plugin-api.js
@@ -26,6 +26,7 @@ import {
import { addOnKeyUpCallback } from "discourse/components/search-menu/search-term";
import { REFRESH_COUNTS_APP_EVENT_NAME as REFRESH_USER_SIDEBAR_CATEGORIES_SECTION_COUNTS_APP_EVENT_NAME } from "discourse/components/sidebar/user/categories-section";
import { forceDropdownForMenuPanels } from "discourse/components/site-header";
+import { addTopicParticipantClassesCallback } from "discourse/components/topic-map/topic-participant";
import { setDesktopScrollAreaHeight } from "discourse/components/topic-timeline/container";
import { addTopicTitleDecorator } from "discourse/components/topic-title";
import { setNotificationsLimit as setUserMenuNotificationsLimit } from "discourse/components/user-menu/notifications-list";
@@ -122,7 +123,6 @@ import {
addSearchSuggestion,
removeDefaultQuickSearchRandomTips as removeWidgetDefaultQuickSearchRandomTips,
} from "discourse/widgets/search-menu-results";
-import { addTopicParticipantClassesCallback } from "discourse/widgets/topic-map";
import {
changeSetting,
createWidget,
diff --git a/app/assets/javascripts/discourse/app/widgets/topic-map.js b/app/assets/javascripts/discourse/app/widgets/topic-map.js
index 52d7ebb2ed4..e32ed95cba8 100644
--- a/app/assets/javascripts/discourse/app/widgets/topic-map.js
+++ b/app/assets/javascripts/discourse/app/widgets/topic-map.js
@@ -1,27 +1,30 @@
+import { htmlSafe } from "@ember/template";
import { hbs } from "ember-cli-htmlbars";
import { h } from "virtual-dom";
import { dateNode, numberNode } from "discourse/helpers/node";
-import autoGroupFlairForUser from "discourse/lib/avatar-flair";
-import { userPath } from "discourse/lib/url";
import { replaceEmoji } from "discourse/widgets/emoji";
-import { avatarFor, avatarImg } from "discourse/widgets/post";
+import { avatarFor } from "discourse/widgets/post";
import RenderGlimmer from "discourse/widgets/render-glimmer";
import { createWidget } from "discourse/widgets/widget";
import I18n from "discourse-i18n";
const LINKS_SHOWN = 5;
-function renderParticipants(userFilters, participants) {
- if (!participants) {
- return;
- }
-
- userFilters = userFilters || [];
- return participants.map((p) => {
- return this.attach("topic-participant", p, {
- state: { toggled: userFilters.includes(p.username) },
- });
- });
+function renderParticipants(wrapperElement, title, userFilters, participants) {
+ return new RenderGlimmer(
+ this,
+ wrapperElement,
+ hbs``,
+ {
+ title,
+ userFilters,
+ participants,
+ }
+ );
}
createWidget("topic-map-show-links", {
@@ -43,70 +46,6 @@ createWidget("topic-map-show-links", {
},
});
-let addTopicParticipantClassesCallbacks = null;
-export function addTopicParticipantClassesCallback(callback) {
- addTopicParticipantClassesCallbacks =
- addTopicParticipantClassesCallbacks || [];
- addTopicParticipantClassesCallbacks.push(callback);
-}
-createWidget("topic-participant", {
- buildClasses(attrs) {
- const classNames = [];
- if (attrs.primary_group_name) {
- classNames.push(`group-${attrs.primary_group_name}`);
- }
- if (addTopicParticipantClassesCallbacks) {
- for (let i = 0; i < addTopicParticipantClassesCallbacks.length; i++) {
- let pluginClasses = addTopicParticipantClassesCallbacks[i].call(
- this,
- attrs
- );
- if (pluginClasses) {
- classNames.push.apply(classNames, pluginClasses);
- }
- }
- }
- return classNames;
- },
-
- html(attrs, state) {
- const linkContents = [
- avatarImg("medium", {
- username: attrs.username,
- template: attrs.avatar_template,
- name: attrs.name,
- }),
- ];
-
- if (attrs.post_count > 1) {
- linkContents.push(h("span.post-count", attrs.post_count.toString()));
- }
-
- if (attrs.flair_group_id) {
- if (attrs.flair_url || attrs.flair_bg_color) {
- linkContents.push(this.attach("avatar-flair", attrs));
- } else {
- const autoFlairAttrs = autoGroupFlairForUser(this.site, attrs);
- if (autoFlairAttrs) {
- linkContents.push(this.attach("avatar-flair", autoFlairAttrs));
- }
- }
- }
- return h(
- "a.poster.trigger-user-card",
- {
- className: state.toggled ? "toggled" : null,
- attributes: {
- title: attrs.username,
- "data-user-card": attrs.username,
- href: userPath(attrs.username),
- },
- },
- linkContents
- );
- },
-});
-
createWidget("topic-map-summary", {
tagName: "section.map",
@@ -245,10 +184,12 @@ createWidget("topic-map-summary", {
) {
const participants = renderParticipants.call(
this,
+ "li.avatars",
+ "",
attrs.userFilters,
attrs.participants.slice(0, 3)
);
- contents.push(h("li.avatars", participants));
+ contents.push(participants);
}
const nav = h(
@@ -313,10 +254,13 @@ createWidget("topic-map-expanded", {
let avatars;
if (attrs.participants && attrs.participants.length > 0) {
- avatars = h("section.avatars", [
- h("h3", I18n.t("topic_map.participants_title")),
- renderParticipants.call(this, attrs.userFilters, attrs.participants),
- ]);
+ avatars = renderParticipants.call(
+ this,
+ "section.avatars",
+ htmlSafe(`
${I18n.t("topic_map.participants_title")}
`),
+ attrs.userFilters,
+ attrs.participants
+ );
}
const result = [avatars];
@@ -408,7 +352,7 @@ export default createWidget("topic-map", {
"section.information.toggle-summary",
hbs``,
{
postAttrs: attrs,
diff --git a/app/assets/javascripts/discourse/tests/integration/components/topic-participant-test.js b/app/assets/javascripts/discourse/tests/integration/components/topic-participant-test.js
new file mode 100644
index 00000000000..51a2e83f0b4
--- /dev/null
+++ b/app/assets/javascripts/discourse/tests/integration/components/topic-participant-test.js
@@ -0,0 +1,42 @@
+import { render } from "@ember/test-helpers";
+import { hbs } from "ember-cli-htmlbars";
+import { module, test } from "qunit";
+import { setupRenderingTest } from "discourse/tests/helpers/component-test";
+
+module("Integration | Component | topic-participant", function (hooks) {
+ setupRenderingTest(hooks);
+
+ test("one post", async function (assert) {
+ this.set("args", {
+ username: "test",
+ avatar_template: "/images/avatar.png",
+ post_count: 1,
+ });
+
+ await render(hbs``);
+
+ assert.dom("a.poster.trigger-user-card").exists();
+ assert.dom("span.post-count").doesNotExist();
+ assert.dom(".avatar-flair").doesNotExist();
+ });
+
+ test("many posts, a primary group with flair", async function (assert) {
+ this.set("args", {
+ username: "test",
+ avatar_template: "/images/avatar.png",
+ post_count: 2,
+ primary_group_name: "devs",
+ flair_name: "devs",
+ flair_url: "/images/d-logo-sketch-small.png",
+ flair_bg_color: "222",
+ flair_group_id: "41",
+ });
+
+ await render(hbs``);
+
+ assert.dom("a.poster.trigger-user-card").exists();
+ assert.dom("span.post-count").exists();
+ assert.dom(".group-devs a.poster").exists();
+ assert.dom(".avatar-flair.avatar-flair-devs").exists();
+ });
+});
diff --git a/app/assets/javascripts/discourse/tests/integration/components/widgets/topic-participant-test.js b/app/assets/javascripts/discourse/tests/integration/components/widgets/topic-participant-test.js
deleted file mode 100644
index d3e8bab7d1b..00000000000
--- a/app/assets/javascripts/discourse/tests/integration/components/widgets/topic-participant-test.js
+++ /dev/null
@@ -1,56 +0,0 @@
-import { render } from "@ember/test-helpers";
-import { hbs } from "ember-cli-htmlbars";
-import { module, test } from "qunit";
-import { setupRenderingTest } from "discourse/tests/helpers/component-test";
-import { exists } from "discourse/tests/helpers/qunit-helpers";
-
-module(
- "Integration | Component | Widget | topic-participant",
- function (hooks) {
- setupRenderingTest(hooks);
-
- test("one post", async function (assert) {
- this.set("args", {
- username: "test",
- avatar_template: "/images/avatar.png",
- post_count: 1,
- });
-
- await render(
- hbs``
- );
-
- assert.ok(exists("a.poster.trigger-user-card"));
- assert.ok(!exists("span.post-count"), "don't show count for only 1 post");
- assert.ok(!exists(".avatar-flair"), "no avatar flair");
- });
-
- test("many posts, a primary group with flair", async function (assert) {
- this.set("args", {
- username: "test",
- avatar_template: "/images/avatar.png",
- post_count: 2,
- primary_group_name: "devs",
- flair_name: "devs",
- flair_url: "/images/d-logo-sketch-small.png",
- flair_bg_color: "222",
- flair_group_id: "41",
- });
-
- await render(
- hbs``
- );
-
- assert.ok(exists("a.poster.trigger-user-card"));
- assert.ok(exists("span.post-count"), "show count for many posts");
- assert.ok(
- exists(".group-devs a.poster"),
- "add class for the group outside the link"
- );
- assert.ok(
- exists(".avatar-flair.avatar-flair-devs"),
- "show flair with group class"
- );
- });
- }
-);