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 Mi Piace

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 Mi Piace

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

1 Mi Piace

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

1 Mi Piace

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

2 Mi Piace

@merefield sei mai riuscito a capire come fare?\n\nSto cercando di capire come creare un componente tema per modificare la Mappa Utente del plugin Posizioni in modo che, quando cliccato, mostri la scheda del profilo invece di andare direttamente alla pagina del profilo, ma anch’io non ho idea da dove iniziare o dove cercare.

oooh questo ha 5 anni… non ricordo :sweat_smile: … immagino che il codice sia molto diverso ora.

Accetterei tale funzionalità come una PR a Locations poiché è stata richiesta molte volte in precedenza.

2 Mi Piace

haha sì, ha senso. Potrei approfondire presto e poi, se scoprissi come fare il PR per i plugin, lo pubblicherei :folded_hands:t2:

1 Mi Piace