أيقونات المستخدم لترويسة السمة المركزية

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

إذا أردت فعل الشيء نفسه، ما هي الملفات التي سأحتاج إلى تعديلها، وهل من الأفضل وضع الملف في السمة الخاصة بي أو إعادة إنشائه باستخدام مكون سمة؟

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

إذا قمت بفحص صفحة وتحققت من علامة التبويب “المصادر”، يمكنك الاطلاع على كيفية إنشائها.

بشكل أساسي:

  • تم إنشاء قائمة المستخدم الجديدة باستخدام عنصر واجهة مستخدم (widget)، تمت إضافته باستخدام api.addToHeaderIcons
  • قائمة الإشعارات:
    • تم استبدال الصورة الرمزية بأيقونة جرس عن طريق استبدال محتواها من عنصر واجهة المستخدم header-notifications.
    • تم إخفاء أيقونة الوصول السريع لقائمة المستخدم باستخدام CSS.
5 إعجابات

شكرا للمساعدة كالعادة، سأقوم بإنشاء بيئة تجريبية للعمل عليها. شكرا مرة أخرى.

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

مرحباً @digitaldominica! أعتذر لعدم تفقد الموضوع منذ فترة حيث أنني بصدد طرح التحديث القادم قريباً. لدى الجميع ملاحظات قيمة، ولكن إذا لم أنظر بعيداً، فسأميل إلى إضافتها إلى قائمتي الحالية بدلاً من حفظها للتحديث الذي يليه. :sweat_smile:

@Arkshine على حق. إنها طريقة ملتوية تعمل ضمن قيود السمة (الكثير من Central هو مجرد نماذج أولية حيث أنني مصمم أولاً وثانياً وثالثاً، ومطور رابعاً).

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


الخطوة 1: إنشاء مكون قائمة مستخدم مخصص

قم بإنشاء هذه الملفات -

:page_facing_up: /javascripts/discourse/components/header-user-new.js
:page_facing_up: /javascripts/discourse/components/header-user-new.hbs

import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";
import { action } from "@ember/object";
import { inject as service } from "@ember/service";

export default class HeaderUserNew extends Component {
  @service currentUser;
  @tracked isActive = false;

  constructor() {
    super(...arguments);
    this.handleDocumentClick = this.handleDocumentClick.bind(this);
  }

  @action
  toggleDropdown() {
    this.isActive = !this.isActive;

    if (this.isActive) {
      setTimeout(() => {
        document.addEventListener("click", this.handleDocumentClick);
      }, 0);
    } else {
      document.removeEventListener("click", this.handleDocumentClick);
    }
  }

  handleDocumentClick(event) {
    const dropdown = document.querySelector(".header-user-new__menu");
    const isClickInside = dropdown.contains(event.target);

    if (!isClickInside) {
      this.isActive = false;
      document.removeEventListener("click", this.handleDocumentClick);
    }
  }

  willDestroy() {
    super.willDestroy();
    document.removeEventListener("click", this.handleDocumentClick);
  }
}
<div class={{concatClass "header-user-new" (if isActive "active")}}>
  <button class="header-user-new__button" type="button" {{on "click" this.toggleDropdown}}>
    {{avatar currentUser}}
  </button>

  <div class="header-user-new__menu">
    <LinkTo class="header-user-new__profile" @route="user.summary" @model={{this.currentUser}}>
      {{avatar currentUser}}
      <div class="header-user-new__profile-info">
        <span class="header-user-new__profile-name">
          {{#if currentUser.name}}
            {{currentUser.name}}
          {{else}}
            {{currentUser.username}}
          {{/if}}
        </span>
        <span class="header-user-new__profile-view">
          View Profile
        </span>
      </div>
    </LinkTo>

    <ul>
      <li>
        <LinkTo @route="userActivity.bookmarks" @model={{this.currentUser}}>
          {{d-icon "bookmark"}}
          <span>
            {{i18n "js.user.bookmarks"}}
          </span>
        </LinkTo>
      </li>
      <li>
        <LinkTo @route="preferences" @model={{this.currentUser}}>
          {{d-icon "cog"}}
          <span>
            {{i18n "user.preferences"}}
          </span>
        </LinkTo>
      </li>
      <li>
        <DButton @action={{route-action "logout"}}>
          {{d-icon "sign-out-alt"}}
          <span>
            {{i18n "user.log_out"}}
          </span>
        </DButton>
      </li>
    </ul>
  </div>
</div>

حتى الآن، سأترك التصميم باستخدام CSS لك، ولكن من المهم تضمين هذه الجزئية لتأثير التبديل -

.header-user-new {
  &.active {
    .header-user-new__menu {
      display: flex;
    }
  }
  .header-user-new__menu {
    display: none;
  }
}

الخطوة 2: تسجيل المكون كـ widget

قم بإنشاء هذا الملف -

:page_facing_up: /javascripts/discourse/widgets/header-user-new.js

import { hbs } from "ember-cli-htmlbars";
import RenderGlimmer from "discourse/widgets/render-glimmer";
import { createWidget } from "discourse/widgets/widget";

export default createWidget("header-user-new", {
  tagName: "li.header-dropdown-toggle.header-user-new",

  html() {
    return [new RenderGlimmer(this, "div", hbs`<HeaderUserNew />`)];
  },
});

الخطوة 3: إضافة الـ widget إلى الرأس، استبدال أيقونة المستخدم الحالية بأيقونة جرس الإشعارات

قم بإنشاء هذا الملف -

:page_facing_up: /javascripts/discourse/initializers/header-edit.js

import { h } from "virtual-dom";
import { withPluginApi } from "discourse/lib/plugin-api";
import { iconNode } from "discourse-common/lib/icon-library";
import I18n from "discourse-i18n";

export default {
  initialize() {
    withPluginApi("0.8", (api) => {
      api.reopenWidget("header-notifications", {
        html(attrs) {
          const { user } = attrs;

          let avatarAttrs = {
            template: user.get("avatar_template"),
            username: user.get("username"),
          };

          if (this.siteSettings.enable_names) {
            avatarAttrs.name = user.get("name");
          }

          const contents = [h("div", iconNode("bell"))];

          if (this.currentUser.status) {
            contents.push(this.attach("user-status-bubble", this.currentUser.status));
          }

          if (user.isInDoNotDisturb()) {
            contents.push(h("div.do-not-disturb-background", iconNode("moon")));
          } else {
            if (user.new_personal_messages_notifications_count) {
              contents.push(
                this.attach("link", {
                  action: attrs.action,
                  className: "badge-notification with-icon new-pms",
                  icon: "envelope",
                  omitSpan: true,
                  title: "notifications.tooltip.new_message_notification",
                  titleOptions: {
                    count: user.new_personal_messages_notifications_count,
                  },
                  attributes: {
                    "aria-label": I18n.t(
                      "notifications.tooltip.new_message_notification",
                      {
                        count: user.new_personal_messages_notifications_count,
                      }
                    ),
                  },
                })
              );
            } else if (user.unseen_reviewable_count) {
              contents.push(
                this.attach("link", {
                  action: attrs.action,
                  className: "badge-notification with-icon new-reviewables",
                  icon: "flag",
                  omitSpan: true,
                  title: "notifications.tooltip.new_reviewable",
                  titleOptions: { count: user.unseen_reviewable_count },
                  attributes: {
                    "aria-label": I18n.t(
                      "notifications.tooltip.new_reviewable",
                      {
                        count: user.unseen_reviewable_count,
                      }
                    ),
                  },
                })
              );
            } else if (user.all_unread_notifications_count) {
              contents.push(
                this.attach("link", {
                  action: attrs.action,
                  className: "badge-notification unread-notifications",
                  rawLabel: user.all_unread_notifications_count,
                  omitSpan: true,
                  title: "notifications.tooltip.regular",
                  titleOptions: { count: user.all_unread_notifications_count },
                  attributes: {
                    "aria-label": I18n.t("user.notifications"),
                  },
                })
              );
            }
          }
          return contents;
        },
      });

      const currentUser = api.container.lookup("service:current-user");
      if (currentUser !== null) {
        api.addToHeaderIcons("header-user-new");
      }
    });
  },
};

التغيير الرئيسي كان استبدال avatarImg(…) بـ iconNode لاستخدام أيقونة الإشعارات بدلاً من صورة المستخدم عن طريق تعديل (أو “إعادة فتح”) الـ widget الحالي header-notifications.
كما ذكر @Arkshine، قمت بإخفاء قسم المستخدم في قائمة الإشعارات باستخدام CSS.

.d-header .panel {
  .user-menu.revamped .bottom-tabs, #user-menu-button-profile {
    display: none;
  }
}
7 إعجابات

مرحباً، لقد تمكنت من استبدال صورة المستخدم (avatarImg) بأيقونة الجرس، ولكن الأمر التالي:

api.addToHeaderIcons("new-user-icon");

يزيل الرأس بأكمله بدلاً من عرض صورة المستخدم مع القائمة المنسدلة.

إعجابَين (2)

سهو مني، كان هناك خطأ إملائي في هذا الرمز، يجب أن يكون—

api.addToHeaderIcons("header-user-new");

لأن الأداة مسجلة باسم header-user-new في الخطوة 2.

3 إعجابات

شكراً، لقد نجح هذا.

إذا كان بإمكاني طرح سؤال آخر حول شيء منفصل؛

كيف يتناوب قالب قائمة الموضوعات المركزية بين
ما نشره المستخدم وما رد عليه المستخدم
؟

لقد جربت {{#if topic.replies}} و {{#if topic.posters.[0]}}
لكن ذلك لم ينجح.

لا مشكلة! topic.posters.1.user هو ما تبحث عنه (الرد الأول). إذا كان موجودًا، استخدمه، وإلا فاستخدم الافتراضي من OP.

هذه هي الطريقة التي تم تنظيمها حاليًا في Central—

{{#if topic.posters.1.user}}
  <span class="tli__last-reply">
    {{d-icon "reply"}}
    <a href="{{topic.lastPoster.user.userPath}}" data-user-card="{{topic.lastPoster.user.username}}">
      {{~topic.lastPoster.user.username~}}
    </a>
    {{theme-i18n "topic_list_item.replied"}}
    <a href={{topic.lastPostUrl}}>
      {{format-date topic.bumpedAt format="medium" leaveAgo="true"}}
    </a>
  </span>
{{else}}
  <span class="tli__last-reply">
    {{d-icon "m-post_add"}}
    <a href="{{topic.posters.0.user.userPath}}" data-user-card="{{topic.posters.0.user.username}}">
      {{~topic.posters.0.user.username~}}
    </a>
    posted
    <a href={{topic.lastPostUrl}}>
      {{format-date topic.bumpedAt format="medium" leaveAgo="true"}}
    </a>
  </span>
{{/if}}
إعجاب واحد (1)

إذًا topic.posters.1.user يعمل كمؤلف المنشور؟

أوه لا topic.posters.0.user هو المؤلف، topic.posters.1.user هو أول مستخدم يرد (إذا كان موجودًا). :ضحك:

3 إعجابات

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.