Can someone please explain to me how the User Card pop-up works?

Guys, i’m trying to work out how the code for User Card works.

How does it create a pop-up and then escalate to a new page?

<a href="/u/postinguser" data-user-card="postinguser" class=""><img alt="" src="/letter_avatar_proxy/v2/letter/m/bbce88/50.png" class="avatar" title="User - Frequent Poster" width="25" height="25"></a>

I can see how it is constructed from the .hbs template file, but not how the action of clicking it causes the user card to appear …

<a href="{{poster.user.path}}" data-user-card="{{poster.user.username}}" class="{{poster.extraClasses}}">{{avatar poster avatarTemplatePath="user.avatar_template" usernamePath="user.username" imageSize="small"}}</a>

But how does the javascript fit together?

What code is causing the user card to load instead of going to the user route?

I see:

/app/assets/javascripts/discourse/widgets/poster-name.js.es6

and specifically:

export default createWidget("poster-name", {
  tagName: "div.names.trigger-user-card",

  settings: {
    showNameAndGroup: true,
    showGlyph: true
  },

  // TODO: Allow extensibility
  posterGlyph(attrs) {
    if (attrs.moderator) {
      return iconNode("shield", { title: I18n.t("user.moderator_tooltip") });
    }
  },

  userLink(attrs, text) {
    return h(
      "a",
      {
        attributes: {
          href: attrs.usernameUrl,
          "data-user-card": attrs.username
        }
      },
      formatUsername(text)
    );
  },

  html(attrs) {
    const username = attrs.username;
    const name = attrs.name;
    const nameFirst =
      this.siteSettings.display_name_on_posts &&
      !this.siteSettings.prioritize_username_in_ux &&
      name &&
      name.trim().length > 0;
    const classNames = nameFirst
      ? ["first", "full-name"]
      : ["first", "username"];

    if (attrs.staff) {
      classNames.push("staff");
    }
    if (attrs.admin) {
      classNames.push("admin");
    }
    if (attrs.moderator) {
      classNames.push("moderator");
    }
    if (attrs.new_user) {
      classNames.push("new-user");
    }

    let afterNameContents =
      applyDecorators(this, "after-name", attrs, this.state) || [];

    const primaryGroupName = attrs.primary_group_name;
    if (primaryGroupName && primaryGroupName.length) {
      classNames.push(primaryGroupName);
    }
    let nameContents = [this.userLink(attrs, nameFirst ? name : username)];

    if (this.settings.showGlyph) {
      const glyph = this.posterGlyph(attrs);
      if (glyph) {
        nameContents.push(glyph);
      }
    }
    nameContents = nameContents.concat(afterNameContents);

    const contents = [
      h("span", { className: classNames.join(" ") }, nameContents)
    ];

    if (!this.settings.showNameAndGroup) {
      return contents;
    }

    if (
      name &&
      this.siteSettings.display_name_on_posts &&
      sanitizeName(name) !== sanitizeName(username)
    ) {
      contents.push(
        h(
          "span.second." + (nameFirst ? "username" : "full-name"),
          [this.userLink(attrs, nameFirst ? username : name)].concat(
            afterNameContents
          )
        )
      );
    }

    const title = attrs.user_title;
    if (title && title.length) {
      contents.push(
        this.attach("poster-name-title", { title, primaryGroupName })
      );
    }

    return contents;
  }

Can someone talk me through this latter code wrt to launching the user card in a state which will permit a further click to the user’s profile?

إعجاب واحد (1)

I think you’re looking for card-contents-base.js.es6, which defines a series of events which point to the _show method.

# card-contents-base.js.es6#103
$("#main-outlet").on(clickDataExpand, `[data-${id}]`, e => {});

$("#main-outlet").on(clickMention, `a.${triggeringLinkClass}`, e => {});

this.appEvents.on(previewClickEvent, $target => {});
# card-contents-base.js.es6#20
_show(username, $target) {}
6 إعجابات

Thanks James! I’ll have a read through that code … head spinning already though … :slight_smile:

إعجاب واحد (1)

What is the thing that you’re trying to do?

إعجاب واحد (1)

Trying to understand how the user card is wired in so I can ultimately code the same behaviour in a plug-in.

إعجابَين (2)

@merefield هل تمكنت من معرفة كيفية القيام بذلك؟

أحاول معرفة كيفية إنشاء مكون سمة لتعديل خريطة المستخدم لمكون الإضافات للمواقع بحيث عند النقر عليها، تعرض بطاقة الملف الشخصي بدلاً من الانتقال مباشرة إلى صفحة الملف الشخصي، ولكن ليس لدي أي فكرة من أين أبدأ أو أبحث.

أوه، هذا عمره 5 سنوات… لا أستطيع التذكر :sweat_smile: … أتخيل أن الكود مختلف جدًا الآن.

أود أن أقبل هذه الوظيفة كـ PR (طلب سحب) إلى Locations حيث تم طلبها مرات عديدة من قبل.

إعجابَين (2)

نعم، هذا منطقي. قد أتعمق في الأمر قريبًا، وإذا اكتشفت كيفية تقديم طلبات سحب (PR) للإضافات، فسأقوم بذلك :folded_hands:t2:

إعجاب واحد (1)