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 me gusta

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 Me gusta

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

1 me gusta

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

1 me gusta

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

2 Me gusta

@merefield ¿alguna vez pudiste averiguar cómo hacer esto?

Estoy tratando de averiguar cómo crear un componente temático para modificar el Mapa de Usuarios del plugin Ubicaciones para que, al hacer clic, muestre la tarjeta de perfil en lugar de ir directamente a la página de perfil, pero tampoco tengo idea de por dónde empezar o buscar.

oooh esto tiene 5 años… No me acuerdo :sweat_smile: … Me imagino que el código es muy diferente ahora.

Aceptaría esa funcionalidad como una PR a Ubicaciones ya que se ha solicitado muchas veces antes.

2 Me gusta

jaja sí, tiene sentido. Puede que lo investigue pronto y luego, si descubro cómo hacer PR de plugins, lo subiré :folded_hands:t2:

1 me gusta