mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
DEV: refactor topic-map participants into glimmer component (#25350)
* DEV: refactor topic-map participants into glimmer components
This commit is contained in:
parent
04d2ec45b4
commit
8b44270929
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class={{this.participantClasses}}>
|
||||||
|
<a
|
||||||
|
class={{this.linkClasses}}
|
||||||
|
data-user-card={{@participant.username}}
|
||||||
|
title={{@participant.username}}
|
||||||
|
href={{this.userUrl}}
|
||||||
|
>
|
||||||
|
{{this.avatarImage}}
|
||||||
|
{{#if (gt @participant.post_count 1)}}
|
||||||
|
<span class="post-count">{{@participant.post_count}}</span>
|
||||||
|
{{/if}}
|
||||||
|
<UserAvatarFlair @user={{@participant}} />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
}
|
@ -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);
|
||||||
|
|
||||||
|
<template>
|
||||||
|
{{@title}}
|
||||||
|
{{#each @participants as |participant|}}
|
||||||
|
<TopicParticipant
|
||||||
|
@participant={{participant}}
|
||||||
|
@toggledUsers={{this.toggledUsers}}
|
||||||
|
/>
|
||||||
|
{{/each}}
|
||||||
|
</template>
|
||||||
|
}
|
@ -26,6 +26,7 @@ import {
|
|||||||
import { addOnKeyUpCallback } from "discourse/components/search-menu/search-term";
|
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 { 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 { forceDropdownForMenuPanels } from "discourse/components/site-header";
|
||||||
|
import { addTopicParticipantClassesCallback } from "discourse/components/topic-map/topic-participant";
|
||||||
import { setDesktopScrollAreaHeight } from "discourse/components/topic-timeline/container";
|
import { setDesktopScrollAreaHeight } from "discourse/components/topic-timeline/container";
|
||||||
import { addTopicTitleDecorator } from "discourse/components/topic-title";
|
import { addTopicTitleDecorator } from "discourse/components/topic-title";
|
||||||
import { setNotificationsLimit as setUserMenuNotificationsLimit } from "discourse/components/user-menu/notifications-list";
|
import { setNotificationsLimit as setUserMenuNotificationsLimit } from "discourse/components/user-menu/notifications-list";
|
||||||
@ -122,7 +123,6 @@ import {
|
|||||||
addSearchSuggestion,
|
addSearchSuggestion,
|
||||||
removeDefaultQuickSearchRandomTips as removeWidgetDefaultQuickSearchRandomTips,
|
removeDefaultQuickSearchRandomTips as removeWidgetDefaultQuickSearchRandomTips,
|
||||||
} from "discourse/widgets/search-menu-results";
|
} from "discourse/widgets/search-menu-results";
|
||||||
import { addTopicParticipantClassesCallback } from "discourse/widgets/topic-map";
|
|
||||||
import {
|
import {
|
||||||
changeSetting,
|
changeSetting,
|
||||||
createWidget,
|
createWidget,
|
||||||
|
@ -1,27 +1,30 @@
|
|||||||
|
import { htmlSafe } from "@ember/template";
|
||||||
import { hbs } from "ember-cli-htmlbars";
|
import { hbs } from "ember-cli-htmlbars";
|
||||||
import { h } from "virtual-dom";
|
import { h } from "virtual-dom";
|
||||||
import { dateNode, numberNode } from "discourse/helpers/node";
|
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 { 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 RenderGlimmer from "discourse/widgets/render-glimmer";
|
||||||
import { createWidget } from "discourse/widgets/widget";
|
import { createWidget } from "discourse/widgets/widget";
|
||||||
import I18n from "discourse-i18n";
|
import I18n from "discourse-i18n";
|
||||||
|
|
||||||
const LINKS_SHOWN = 5;
|
const LINKS_SHOWN = 5;
|
||||||
|
|
||||||
function renderParticipants(userFilters, participants) {
|
function renderParticipants(wrapperElement, title, userFilters, participants) {
|
||||||
if (!participants) {
|
return new RenderGlimmer(
|
||||||
return;
|
this,
|
||||||
}
|
wrapperElement,
|
||||||
|
hbs`<TopicMap::TopicParticipants
|
||||||
userFilters = userFilters || [];
|
@title={{@data.title}}
|
||||||
return participants.map((p) => {
|
@participants={{@data.participants}}
|
||||||
return this.attach("topic-participant", p, {
|
@userFilters={{@data.userFilters}}
|
||||||
state: { toggled: userFilters.includes(p.username) },
|
/>`,
|
||||||
});
|
{
|
||||||
});
|
title,
|
||||||
|
userFilters,
|
||||||
|
participants,
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
createWidget("topic-map-show-links", {
|
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", {
|
createWidget("topic-map-summary", {
|
||||||
tagName: "section.map",
|
tagName: "section.map",
|
||||||
|
|
||||||
@ -245,10 +184,12 @@ createWidget("topic-map-summary", {
|
|||||||
) {
|
) {
|
||||||
const participants = renderParticipants.call(
|
const participants = renderParticipants.call(
|
||||||
this,
|
this,
|
||||||
|
"li.avatars",
|
||||||
|
"",
|
||||||
attrs.userFilters,
|
attrs.userFilters,
|
||||||
attrs.participants.slice(0, 3)
|
attrs.participants.slice(0, 3)
|
||||||
);
|
);
|
||||||
contents.push(h("li.avatars", participants));
|
contents.push(participants);
|
||||||
}
|
}
|
||||||
|
|
||||||
const nav = h(
|
const nav = h(
|
||||||
@ -313,10 +254,13 @@ createWidget("topic-map-expanded", {
|
|||||||
let avatars;
|
let avatars;
|
||||||
|
|
||||||
if (attrs.participants && attrs.participants.length > 0) {
|
if (attrs.participants && attrs.participants.length > 0) {
|
||||||
avatars = h("section.avatars", [
|
avatars = renderParticipants.call(
|
||||||
h("h3", I18n.t("topic_map.participants_title")),
|
this,
|
||||||
renderParticipants.call(this, attrs.userFilters, attrs.participants),
|
"section.avatars",
|
||||||
]);
|
htmlSafe(`<h3>${I18n.t("topic_map.participants_title")}</h3>`),
|
||||||
|
attrs.userFilters,
|
||||||
|
attrs.participants
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = [avatars];
|
const result = [avatars];
|
||||||
|
@ -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`<TopicMap::TopicParticipant @participant={{this.args}}/>`);
|
||||||
|
|
||||||
|
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`<TopicMap::TopicParticipant @participant={{this.args}}/>`);
|
||||||
|
|
||||||
|
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();
|
||||||
|
});
|
||||||
|
});
|
@ -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`<MountWidget @widget="topic-participant" @args={{this.args}} />`
|
|
||||||
);
|
|
||||||
|
|
||||||
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`<MountWidget @widget="topic-participant" @args={{this.args}} />`
|
|
||||||
);
|
|
||||||
|
|
||||||
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"
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
Loading…
Reference in New Issue
Block a user