إنشاء واجهات إدارة متسقة

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

ملاحظة: المصطلحات المستخدمة هنا مُعرَّفة في قاموس واجهة المسؤول.

0. مقدمة - هيكل صفحة الإعدادات وروابط الشريط الجانبي

عند إضافة صفحات إعدادات جديدة في واجهة المسؤول، ستحتاج كل صفحة إلى رابط للشريط الجانبي، وستحتاج كل صفحة إلى عنوان ووصف للعنوان. وذلك لضمان اتساقنا في كل مكان، ولتمكين التحسينات المستقبلية في بحث المسؤول من عرض هيكل واجهة المسؤول بالكامل.

بشكل عام، يبدو هيكل واجهة المسؤول كما يلي:

  • واجهة المسؤول
    • صفحة الإعدادات (معروضة في الشريط الجانبي)
      • علامة تبويب الإعدادات
      • علامات تبويب اختيارية من المستوى الثالث
        • صفحة تعديل/إضافة من المستوى الثالث للموارد

في النهاية، سيتم إدراج “نظرة عامة على القسم” بين الواجهة الجذرية وصفحات الإعدادات.

روابط الشريط الجانبي

يجب إضافة جميع صفحات المسؤول إلى ADMIN_NAV_MAP في discourse/frontend/discourse/app/lib/sidebar/admin-nav-map.js at main · discourse/discourse · GitHub . يجب أن يحتوي كل عنصر على الأقل على هذه المفاتيح:

  • name - معرّف فريد للرابط، ويجب أن يكون بصيغة snake_case
  • route OR href - route هو معرّف مسار Ember، مثل adminUsers. للمسؤولين، يتم تعريف هذه في خريطة مسارات المسؤول . يمكن استخدام href بدلاً من ذلك، لكن يُفضل استخدام route.
  • label OR text - label هو مفتاح I18n، ويجب أن يكون عادةً admin.config.page_name.title (انظر قسم الترجمات أدناه). إذا تم استخدام text، فسيكون النص مترجماً بالفعل.

يمكن أيضاً توفير هذه المفاتيح الاختيارية:

  • description - يُنصح بتوفير هذا أيضاً. إنه مفتاح I18n، ويجب أن يكون عادةً admin.config.page_name.header_description.
  • icon - موصى به أيضاً، يتم عرضه بجوار الرابط في الشريط الجانبي.
  • routeModels - مصفوفة من بيانات URL لحالة معلمات المسار. على سبيل المثال، يحتوي adminCustomizeThemes على معلمة مسار :type، لذا يمكنك تمرير routeModels: ["components"]. تُستخدم عناصر المصفوفة بنفس الترتيب الذي تظهر به معلمات المسار.
  • moderator: اضبط هذا على true إذا كان يجب على المشرفين رؤية هذه الصفحة في الشريط الجانبي.
  • keywords: مفتاح I18n، مع قائمة مفاتيح بحث مفصولة بـ | لرابط الشريط الجانبي، تُستخدم لإضافة “وزن بحث” إضافي عند تصفية/البحث في الصفحات.
  • links: قائمة بمسارات المستوى الثالث الموجودة أسفل الصفحة في الشريط الجانبي. لا يتم عرضها في الشريط الجانبي نفسه. سيتم استخدامها لميزات بحث المسؤول المستقبلية.
  • settings_area و settings_category: إذا كانت الصفحة تعرض قائمة فقط بإعدادات الموقع المفلترة، فيجب ملء أحد هذين. إذا كان لإعداد الموقع area مُعرَّف، والذي يُستخدم في AdminAreaSettings، فيجب استخدام settings_area. إذا تم عرض فئة كاملة من الإعدادات في الصفحة، واستُخدمت أيضاً في AdminAreaSettings، فيجب استخدام settings_category.
  • multi_tabbed: إذا كانت الصفحة تحتوي على علامة تبويب للإعدادات و علامات تبويب أخرى، فيجب ضبط هذا على true. يساعد في إنشاء روابط لنظام بحث المسؤول.

الترجمات

يجب أن يكون عنوان كل صفحة إعدادات ووصف العنوان تحت:

  • admin
    • config
      • page_name
        • title: “عنوان الصفحة”
        • header_description: “هذه الصفحة مخصصة لـ xyz”

يمكنك رؤية أمثلة على ذلك هنا:

1. المسار (Breadcrumbs)

تعمل المسارات كأداة تنقل، تساعد المستخدمين على فهم موقعهم الحالي وهيكل المحتوى والتسلسل الهرمي داخل واجهة المسؤول.

المسؤول > المسار > الأثر
عنوان الصفحة

:art: التصميم

الهيكل

  1. المسؤول: بادئة ثابتة تظهر في بداية كل مسار، تربط إلى /admin
  2. الرابط: يفتح الصفحة في نفس النافذة
  3. الفاصل: أيقونة angle-right تفصل بين كل رابط

الاستخدام

متى يجب الاستخدام:

  • موجودة في كل صفحة مسؤول
  • تقع فوق المحتوى (العنوان، الوصف، علامات التبويب)
  • تعرض الصفحة المحددة حالياً

متى لا يجب الاستخدام:

  • عند زيارة مسار جديد أو تعديل

المحتوى

  • يتضمن كل عنصر رابطاً إلى صفحته ذات الصلة
  • يعرض الصفحة المحددة حالياً

إمكانية الوصول

  • عنصر nav مع aria-label="Breadcrumb" يلف قائمة مرتبة لتوفير معلم تنقل
  • طبّق aria-current="page" على الرابط الأخير للإشارة إلى أنه الصفحة الحالية
  • لمزيد من التفاصيل، انظر مثال مسار ممارسات تأليف WAI-ARIA

:hammer_and_wrench: التنفيذ

يجب وضع مكون DBreadcrumbsContainer في مكان ما في الصفحة:

<DBreadcrumbsContainer />

ثم، سيتم عرض كل عنصر DBreadcrumbsItem المضاف إلى أي مكون في مسار أو مسار فرعي في هذا الحاوية. كل DBreadcrumbsItem يحتوي على @label و @path يجب توفيرهما:

<DBreadcrumbsItem @path="/admin" @label={{i18n "admin_title"}} />
<DBreadcrumbsItem
  @path="/admin/plugins"
  @label={{i18n "admin.plugins.title"}}
/>
<DBreadcrumbsItem
  @path="/admin/plugins/{{@plugin.name}}"
  @label={{@plugin.nameTitleized}}
/>

كيف يبدو هذا بمثال مرئي، باستخدام إضافة Discourse AI:

2. عنوان الصفحة والرأس

القسم العلوي لصفحة المسؤول، الذي يحتوي على عنوان الصفحة، بالإضافة إلى الإجراءات والوصف الاختياري.

:art: التصميم

الهيكل

  • عنوان الصفحة: عنوان الصفحة

  • وصف الصفحة: مقدمة أو وصف لما يغطيه المحتوى (اختياري)

  • الإجراء الأساسي: الإجراء الأساسي لعنوان الصفحة (اختياري)

  • الإجراء الثانوي: إعدادات زر الإجراء الثانوي لعنوان الصفحة (اختياري)

الاستخدام والمحتوى

  • عنوان الصفحة: استخدم مستوى العنوان 1 لشرح الموضوع الرئيسي للصفحة بحالة الجملة. عادةً يجب أن يكون ترجمة I18n تحت admin.config.your_page.title.

  • وصف الصفحة: يدعم عقد Markdown الأساسية مثل _مائل_، **غامق**، و [اسم الرابط](url)

  • الإجراء الأساسي: استخدم btn-primary. لا تتضمن أيقونة. عادةً يجب أن تكون ترجمة I18n تحت admin.config.your_page.header_description.

  • الإجراء الثانوي: استخدم إعدادات زر btn-default، مرئية فقط إذا كان هناك إجراء أساسي. لا تتضمن أيقونة.

    :point_right: كن واضحاً مع أزرار الإجراءات. على سبيل المثال، استخدم تسميات وصفية مثل “إضافة إيموجي” بدلاً من مجرد “إضافة” لتقليل الغموض.

:hammer_and_wrench: التنفيذ

يتم استخدام مكون DPageHeader هنا. يقبل هذا الحجج لـ @titleLabel، @descriptionLabel، @learnMoreUrl، و @shouldDisplay. يستخدم هذا yields المسماة في Ember لتوفير 5 كتل مسماة للمحتوى:

  1. breadcrumbs - يجب وضع أي مكونات DBreadcrumbsItem إضافية للصفحة هنا.
  2. actions - يُستخدم لتحديد الأزرار إلى يمين العنوان. هذا ينتج كائناً يسمى actions يمكن استخدامه لعرض أزرار Default، Primary، Danger، و Wrapped.
  3. title - بديل لـ @titleLabel، يسمح بوضع تعليمات مخصصة داخل العنوان.
  4. drawer - قسم درج قابل للطي اختياري، يظهر عندما يكون @showDrawer صحيحاً.
  5. tabs - يُستخدم لتحديد علامات التبويب للصفحة باستخدام مكونات NavItem. يمكن استخدام @hideTabs لإزالة هذا الجزء من الرأس إذا لم يكن ضرورياً.

مثال كامل أدناه:

<DPageHeader
  @titleLabel={{i18n "admin.config.backups.title"}}
  @descriptionLabel={{i18n "admin.config.backups.header_description"}}
  @learnMoreUrl="https://meta.discourse.org/t/create-download-and-restore-a-backup-of-your-discourse-database/122710"
>
  <:breadcrumbs>
    <DBreadcrumbsItem
      @path="/admin/backups"
      @label={{i18n "admin.backups.title"}}
    />
  </:breadcrumbs>
  <:actions as |actions|>
    <actions.Primary
      @action={{routeAction "showStartBackupModal"}}
      @title="admin.backups.operations.backup.title"
      @label="admin.backups.operations.backup.label"
      class="admin-backups__start"
    />
  </:actions>
  <:tabs>
    <NavItem
      @route="admin.backups.settings"
      @label="settings"
      class="admin-backups-tabs__settings"
    />
    <NavItem
      @route="admin.backups.index"
      @label="admin.backups.menu.backup_files"
      class="admin-backups-tabs__files"
    />
    <NavItem
      @route="admin.backups.logs"
      @label="admin.backups.menu.logs"
      class="admin-backups-tabs__logs"
    />
    <PluginOutlet @name="downloader" @connectorTagName="div" />
  </:tabs>
</DPageHeader>

يتم التعامل مع عناوين الصفحات لتبويب المتصفح في مسارات Ember باستخدام وظيفة titleToken. في كل مرة يتم استخدام هذا في مسار، يضيف الرمز إلى نهاية عنوان تبويب المتصفح. انتبه إلى أنه يجب استخدام فئة DiscourseRoute لتوسيع مسارك، وليس Route العادية من ember لكي يعمل هذا:

titleToken() {
  return i18n("admin.config.backups.title");
}

:point_right: يتم إخفاء رأس الصفحة تلقائياً لمسارات /new و /edit لدعم مسارات المستوى الثالث. يمكن تجاوز ذلك باستخدام حجة @shouldDisplay.

3. علامات التبويب

تنقل اختياري يوفر الوصول إلى مستويات أعمق من الإعدادات أو الميزات. نطلق على هذا أيضاً صفحات أو تنقل “من المستوى الثالث”.

:art: التصميم

نستخدم علامات التبويب للتبديل بين عروض مختلفة ولكنها ذات صلة ضمن نفس السياق.

الاستخدام

  • لا تُستخدم للتنقل الأساسي
  • نشطة واحدة فقط في كل مرة

:hammer_and_wrench: التنفيذ

انظر تفاصيل رأس الصفحة، يتم تعريف علامات التبويب في مكون DPageHeader.

:white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square:

4. صفحة الهبوط العامة/للقسم

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

:art: التصميم

الهيكل
استخدم تخطيط ثلاثة أعمدة متساوية باستخدام نظام الشبكة. على الشاشات الصغيرة، ستترتب هذه الأعمدة عمودياً.

التصميم والاستخدام

  • يمكن الوصول إليها عبر المسارات (المسؤول > المجتمع > نظرة عامة)
  • يجب أن يكون لكل قسم واحدة، باستثناء الإضافات (التي تعرض المثبتة) والتقارير (صفحة واحدة فقط)
  • يحتوي العنصر على:
    • الاسم - نفس رابط القسم
    • الوصف - وصف قصير لما تدور حوله الصفحة
    • الأيقونة - نفس الأيقونة المستخدمة للشريط الجانبي

:hammer_and_wrench: التنفيذ

مقاطع شفرة أو رابط إلى موضوع/GitHub

5. محتوى الصفحة

المنطقة الرئيسية لصفحة المسؤول حيث يتم عرض الإعدادات والتكوينات والمحتوى الآخر والتفاعل معها.

:art: التصميم

الهيكل
استخدم تخطيط 2/3 + 1/3 باستخدام نظام الشبكة. تشغل المنطقة الأساسية ثلثي المساحة وتشغل المنطقة الثانوية ثلث المساحة. على الشاشات الصغيرة، ستترتب هذه الأعمدة عمودياً.

  • منطقة التكوين: قسم محدد داخل محتوى الصفحة مخصص للإعدادات والتكوينات.
  • المساعدة/المرجع/الإدراج: منطقة داخل محتوى الصفحة توفر أدلة أو وثائق أو معلومات سياقية إضافية. (اختياري)

التصميم والاستخدام

  • اجمع الإعدادات والإجراءات المماثلة معاً في بطاقات
  • نظم التخطيطات الأساسية/الثانوية بحيث تُستخدم المنطقة الأساسية (2/3) للإعدادات الرئيسية، والمنطقة الثانوية (1/3) للمعلومات الإضافية أو السياق المفيد
  • إذا لم تكن المنطقة الثانوية متاحة، حافظ على عرض المنطقة الأساسية كما هو

المحتوى

:hammer_and_wrench: التنفيذ

مقاطع شفرة أو روابط GitHub

5.أ. العنوان الفرعي

العنوان الفرعي هو عنوان ثانوي يُستخدم لتقسيم المحتوى تحت قسم، عادةً أسفل علامات التبويب.

الهيكل

  • العنوان الفرعي: عنوان فرعي لما يغطيه المحتوى (اختياري)
  • الإجراء الأساسي: الإجراء الأساسي للعنوان الفرعي (اختياري)
  • الإجراء الثانوي: إعدادات زر الإجراء الثانوي للعنوان الفرعي (اختياري)

الاستخدام والمحتوى

  • العنوان الفرعي: استخدم مستوى العنوان 2 لشرح الموضوع الرئيسي للمحتوى ذي الصلة. قم بالتضمين فقط إذا:

    • كان هناك زر إجراء أساسي، أو
    • كان هناك وصف يشرح القسم.
  • الإجراء الأساسي: استخدم btn-primary. لا تتضمن أيقونة.

  • الإجراء الثانوي: استخدم إعدادات زر btn-default، مرئية فقط إذا كان هناك إجراء أساسي. لا تتضمن أيقونة.

    :point_right: كن واضحاً مع أزرار الإجراءات. على سبيل المثال، استخدم تسميات وصفية مثل “إضافة إيموجي” بدلاً من مجرد “إضافة” لتقليل الغموض.

:hammer_and_wrench: التنفيذ

هذا مشابه لـ DPageHeader، يوجد مكون DPageSubheader. الفرق الرئيسي هو أن هناك yield مسماة واحدة فقط لـ actions.

  1. actions - يُستخدم لتحديد الأزرار إلى يمين العنوان. هذا ينتج كائناً يسمى actions يمكن استخدامه لعرض أزرار Default، Primary، Danger، و Wrapped.
<DPageSubheader @titleLabel="admin.config.backups.subheader.title">
  <:actions>
    <actions.Primary
      @action={{routeAction "showStartBackupModal"}}
      @title="admin.backups.operations.backup.title"
      @label="admin.backups.operations.backup.label"
      class="admin-backups__start"
    />
  </:actions>
</DPageSubheader>

5.ب. منطقة التكوين

تتكون منطقة التكوين من بطاقات أو أقسام. البطاقات رائعة لتجميع المعلومات والمهام ذات الصلة، مما يساعد المستخدمين على مسح المحتوى وتحديد الأولويات بسهولة أكبر.

:art: التصميم

بطاقة

تم إعداد البطاقات بنصف قطر حدود 2 بكسل وتستخدم خلفية من --secondary. كما لها حدود صلبة 1 بكسل مع --primary-low وحوامل 20 بكسل حول المحتوى.

تباين افتراضي

تباين الأكورديون

التصميم والاستخدام

  • اجمع المعلومات ذات الصلة
  • اعرض المعلومات بحيث يرى المسؤولون والمشرفون أهم الأشياء أولاً
  • استخدم عناوين تشرح بوضوح الغرض من البطاقة
  • قسّم المعقدة إلى أقسام متعددة، إذا لزم الأمر

تباين افتراضي

  • التزم بإجراء دعوة أساسي واحد لكل بطاقة
  • ضع إجراء الدعوة الأساسي في أسفل البطاقة للخطوات التالية

تباين الأكورديون

  • استخدم الزاوية العلوية اليمنى من البطاقة للإجراءات الاختيارية مثل “عرض الكل”

المحتوى

  • يجب أن تستخدم جميع النماذج مكونات FormKit ember في النواة الموصوفة في الوثائق

  • يجب أن تكون تسميات البطاقات بحالة الجملة

    :white_check_mark: افعل :cross_mark: لا تفعل
    الإعدادات العامة الإعدادات العامة
    معلومات الاتصال معلومات الاتصال

:hammer_and_wrench: التنفيذ

لدينا مكون AdminConfigAreaCard يجب استخدامه لجميع هذه البطاقات. حالياً يحتوي هذا فقط على حجج @translatedHeading و @heading، في المستقبل يمكننا إضافة إجراءات وجعلها قابلة للطي وهلم جرا:

<AdminConfigAreaCard
  @heading="admin.config_areas.about.general_settings"
  class="admin-config-area-about__general-settings-section"
>
  <AdminConfigAreasAboutGeneralSettings
    @generalSettings={{this.generalSettings}}
    @setGlobalSavingStatus={{this.setSavingStatus}}
    @globalSavingStatus={{this.saving}}
  />
</AdminConfigAreaCard>

إعدادات الموقع المضمنة

هذا القسم قيد التطوير.

5.ج. إدراج المساعدة

يوفر هذا القسم إرشادات إضافية أو وثائق أو سياقاً داخل محتوى الصفحة.

الإصدار 1

:art: التصميم

التصميم والاستخدام

  • اعرض الوثائق أو الأدلة ذات الصلة حول محتوى الصفحة لتوفير معلومات مفيدة
  • ضمّن أيقونة في العنوان لجعله سهل التعرف
  • ضع هذا القسم في منطقة التخطيط الثانوية (1/3)

المحتوى

  • يجب أن تكون التسميات بحالة الجملة

:hammer_and_wrench: التنفيذ

مقاطع شفرة أو رابط إلى موضوع/GitHub

5.د. الجدول

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

:art: التصميم

الاستخدام

  • استخدم الجداول لعرض محتوى منظم حيث تشارك كل إدخال نفس السمات.
  • اسمح للمسؤولين بمراجعة وتمكين/تعطيل وتعديل وحذف مجموعات البيانات.
  • مناسب لمجموعات البيانات التي ستستمر في النمو مع مرور الوقت.

التصميم

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

إجراءات إضافية

  • إجراءات الصف: ضمّن إجراءات إضافية في العمود الأيمن لكل صف في الجدول.
    • إذا كان هناك عنصران تفاعليان أو أكثر، يجب أن يكون الإجراء الأساسي (مثل “تعديل”) زر نصي، ويجب تجميع جميع إجراءات الصف الأخرى بما في ذلك “حذف” في قائمة منسدلة [...]. تشجيع استخدام الأيقونات في قوائم التنقل المنسدلة لتقسيم الأشياء بصرياً.
    • إذا كان هناك إجراء “حذف” فقط ولا يوجد إجراء أساسي، استخدم زر نصي “حذف” مضمن مُنسق كـ btn-default.
    • يجب أن تغلف نص العمود الرئيسي (عادةً d-table__cell --overview) برابط يأخذ المسؤول مباشرة إلى صفحة عرض/تعديل المقابلة للصف للوصول السريع.
  • تأكيد الحذف: يجب أن تعرض جميع أزرار “حذف” تأكيداً قبل تنفيذ الإجراء.

المحتوى

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

:hammer_and_wrench: التنفيذ

هناك مجموعة صغيرة من فئات CSS التي يجب استخدامها مع الجداول لجعلها تعمل بشكل جيد على الهاتف المحمول وسطح المكتب.

يجب تطبيق فئة d-table على عناصر <table>.

يجب تطبيق فئة d-table__header على عناصر <thead>.

يجب تطبيق فئة d-table__row على عناصر <tr>.

يجب أن تستخدم عناصر <td> التي تحتوي على الكثير من النص الوصفي (عادةً العمود الأيسر) فئات d-table__cell --overview. يجب أن تستخدم جميع الخلايا الأخرى d-table__cell --detail.

يمكن لعناصر <td> مع فئات d-table__cell --overview تغليف محتوى الصف الداخلي برابط يأخذ المسؤول مباشرة إلى صفحة تعديل/عرض للصف. يجب أن يتبع هذا الرابط هذا الهيكل ويجب تطبيق فئة CSS d-table__overview-link عليه. بشكل مثالي يجب استخدام مكون LinkTo لكن <a> جيد أيضاً طالما تم استخدام getURL معه.

يجب تطبيق فئة d-table__overview-name على جزء الاسم هنا، ولكن ليس الوصف.

<td class="d-table__cell --overview">
  <LinkTo
    class="d-table__overview-link"
    @route="adminPlugins.show.explorer.details"
    @model={{query.id}}
  >
    <strong class="query-name d-table__overview-name">{{query.name}}</strong>
    {{#if query.is_default}}
      <span class="query-badge">{{i18n
          "explorer.default_query"
        }}</span>
    {{/if}}
    <div class="query-desc">{{query.description}}</div>
  </LinkTo>
</td>
<td class="d-table__cell --overview">
  <a class="d-table__overview-name admin-flag-item__name d-table__overview-link" href={{this.editUrl}}>
    {{@flag.name}}
  </a>
</td>

يجب أن تحتوي عناصر <td> التي تغلف الأزرار في كل صف على فئات CSS d-table-cell --controls. هذا يضمن محاذاة الأزرار. يجب أن تحتوي كل زر أيضاً على فئة btn-small.

للجوال، يجب أن يتضمن كل عنصر <td> باستثناء d-table-cell --overview أيضاً <div> مع الفئة d-table__mobile-label، الذي يحتوي على تسمية I18n هي نفسها الموجودة في <th> لتلك العمود:

<td class="d-table__cell --detail">
  <div class="d-table__mobile-label">
    {{i18n "chat.incoming_webhooks.emoji"}}
  </div>
  {{replaceEmoji webhook.emoji}}
</td>

هذا يعرض صف الجدول بتنسيق قائم على البطاقات أسهل القراءة على الهاتف المحمول:

لقوائم التنقل المنسدلة [...]، يجب استخدام DMenu مع DropdownMenu، هنا مثال:

<DMenu
  @identifier="backup-item-menu"
  @title={{i18n "more_options"}}
  @icon="ellipsis-vertical"
  class="btn-small"
>
  <:content>
    <DropdownMenu as |dropdown|>
      <dropdown.item>
        <DButton ...[button args here] />
      </dropdown.item>
      <dropdown.item>
        <DButton ...[button args here] />
      </dropdown.item>
    </DropdownMenu>
  </:content>
</DMenu>

يتم التعامل مع المفاتيح في صف الجدول باستخدام مكون DToggleSwitch:

<DToggleSwitch
  @state={{this.enabled}}
  class="admin-flag-item__toggle {{@flag.name_key}}"
  {{on "click" (fn this.toggleFlagEnabled @flag)}}
/>

بجمع كل ذلك معاً، إليك مثال بسيط لجدول المسؤول:

 <table class="d-table">
    <thead class="d-table__header">
      <tr>
        <th>الاسم</th>
        <th>الوصف</th>
        <th></th>
      </tr>
    </thead>
    <tbody>
      <tr class="d-table__row">
        <td class="d-table__cell --overview">
          <LinkTo @route="admin.exampleRoute" class="d-table__overview-link">
            <span class="d-table__overview-name">عنصر مثال</span>
            <span class="d-table__overview-about">وصف قصير</span>
          </LinkTo>
        </td>
        <td class="d-table__cell --detail">
          <span class="d-table__mobile-label">الوصف</span>
          بعض محتوى التفاصيل هنا
        </td>
        <td class="d-table__cell --controls">
          <div class="d-table__cell-actions">
            <button class="btn btn-default btn-small">تعديل</button>
          </div>
        </td>
      </tr>
    </tbody>
  </table>

5.هـ مسار المستوى الثالث

مسار المستوى الثالث هو مسار يمكن الوصول إليه فقط من منطقة التكوين. هذه تأتي عادةً في شكل مسارات تعديل/إضافة مثل هذا للأعلام:

هنا سيتم وضع النماذج التي تستخدم FormKit في معظم الحالات.

استخدم مسارات RESTful القياسية لهذه:

الإجراء المسار
جديد <resource>/new
تعديل <resource>/:id/edit

وتأكد من أن المسارات موجهة أيضاً في الخلفية. (إعادة تحميل صفحة new- أو edit يجب ألا تؤدي إلى خطأ.)

:art: التصميم

الاستخدام

  • تفضيل وجود هذه المسارات من المستوى الثالث بدلاً من وجود نماذج مضمنة في المسار الرئيسي أو داخل جدول. مسارات التعديل والإضافة المستقلة هي الأفضل، لأنها يمكن ربطها بسهولة.
  • لا تعرض الجزء العلوي من واجهة المستخدم للصفحة (المسارات، رأس الصفحة والعنوان الفرعي)
  • بدلاً من ذلك، اعرض رابطاً واحداً “العودة إلى X” يسمح للمسؤول بالوصول إلى منطقة التكوين الرئيسية
  • يجب تغليف محتوى الصفحة في مكون AdminConfigAreaCard واحد على الأقل
  • يجب تنفيذ أي عناوين فرعية في الصفحة باستخدام بطاقات منطقة التكوين

:hammer_and_wrench: التنفيذ

هناك مكون BackButton بسيط يمكن استخدامه في أعلى الصفحة للعودة:

<BackButton
  @route="adminConfig.flags"
  @label="admin.config_areas.flags.back"
/>

6. صفحات إعدادات التكوين المفلترة

العديد من صفحات إعدادات واجهة المسؤول لدينا هي قوائم بسيطة لإعدادات الموقع المفلترة. هذا يسمح للمسؤولين بإيجاد مجموعات ذات صلة من الإعدادات دون أن يغرقوا في قائمة “جميع إعدادات الموقع” الكاملة، حتى نخلق صفحات إعدادات متخصصة أكثر مثل /admin/config/about/.

:hammer_and_wrench: التنفيذ

هناك بعض الأشياء التي تحتاجها لإضافة واحد من هذه المسارات. أولاً، يمكنك إما عرض category كامل لإعدادات الموقع وهي المفاتيح العليا في site_settings.yml (على سبيل المثال branding:)، أو يمكنك استخدام area الإعداد.

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

  1. أضف مساراً إلى خريطة مسارات المسؤول تحت adminConfig، على سبيل المثال:
this.route("trustLevels", { path: "/trust-levels" }, function () {
  this.route("settings", {
    path: "/",
  });
});
  1. أضف ملف .js لمسار جديد، سيطابق الملف مساراً مثل frontend/discourse/admin/routes/admin-config/localization.js اعتماداً على اسم مسارك الجديد. يجب أن يرث من AdminConfigWithSettingsRoute ويتضمن titleToken().
import { i18n } from "discourse-i18n";
import AdminConfigWithSettingsRoute from "../admin-config-with-settings-route";

export default class AdminConfigLocalizationRoute extends AdminConfigWithSettingsRoute {
  titleToken() {
    return i18n("admin.config.localization.title");
  }
}
  1. أضف متحكم، هذا بشكل أساسي لتمكين بحث وتصفية الإعدادات. يجب أن يرث من AdminAreaSettingsBaseController:
import AdminAreaSettingsBaseController from "discourse/admin/controllers/admin-area-settings-base";

export default class AdminConfigLocalizationSettingsController extends AdminAreaSettingsBaseController {}
  1. أخيراً، أضف ملف قالب مسار بتنسيق .gjs، في مسار مثل frontend/discourse/admin/templates/admin-config/localization/settings.gjs. يجب أن يحتوي على DPageHeader والمسارات العادية، ولكن لعرض الإعدادات تحتاج AdminAreaSettings.
<div class="admin-config-page__main-area">
  <AdminAreaSettings
    @showBreadcrumb={{false}}
    @area="localization"
    @path="/admin/config/localization"
    @filter={{@controller.filter}}
    @adminSettingsFilterChangedCallback={{@controller.adminSettingsFilterChangedCallback}}
  />
</div>

الأشياء المهمة لتغييرها هنا هي @path، و @area (أو بدلاً من ذلك استخدم @categories). كما ذكرنا سابقاً، املأ هذا إما بمساحة إعدادات الموقع التي تريد عرضها، أو الفئات.

7. إرشادات عامة

  • يجب أن تستخدم رموز URL السلبية (-) للإشارة إلى المسافات في الكلمات، بدلاً من underscores (_).

  • يجب أن يتبع جميع النصوص في واجهات المسؤول إرشادات تنسيق النص الموضحة هنا:

8. الإضافات

بعض الإضافات تحتاج إلى واجهة مستخدم للتكوين متعمقة لإضافتها (على سبيل المثال الذكاء الاصطناعي، الأتمتة، التلعيب) بدلاً من مجرد وجود مجموعة من إعدادات الموقع. على سبيل المثال، هنا Discourse AI:

بعض الأمثلة على الإضافات التي تستخدم هذا هي:

:art: التصميم

الاستخدام

  • يجب اتباع إرشادات واجهة المستخدم الإدارية العامة عند إنشاء واجهات مستخدم مستقلة للإضافات.

:hammer_and_wrench: التنفيذ

توجيه Ember

  • ستكون جميع قوالب المسارات تحت
    admin/assets/javascripts/discourse/templates/admin-plugins/show/
  • ستكون جميع ملفات js للمسارات تحت admin/assets/javascripts/discourse/routes/ و
    تبدأ بـ admin-plugins-show-
  • يجب أن تكون خريطة مسارات المسؤول في ملف مثل admin-PLUGIN-NAME-plugin-route-map.js
  • يجب أن تكون خريطة المسارات لها هيكل مثل هذا. الجزء المهم هو أننا نستخدم admin.adminPlugins.show كـ resource.
export default {
  resource: "admin.adminPlugins.show",

  path: "/plugins",

  map() {
    this.route("discourse-ai-personas", { path: "ai-personas" }, function () {
      this.route("new");
      this.route("show", { path: "/:id" });
    });
  },
};
  • المثال الحالي لكيفية عمل كل هذا مرئي في إضافة Discourse AI، إذا ذهبت إلى /admin/plugins/discourse-ai/ai-personas
  • إذا كان لديك فقط مسار “مستوى علوي”، على سبيل المثال واحد لا يحدد مسارات فرعية، فسيكون مسار القالب شيئاً مثل admin/assets/javascripts/discourse/templates/admin-plugins/show/your-route-name.gjs. إذا كانت هناك مسارات فرعية فإنك تدخل في مجال الحاجة إلى قوالب index.gjs، show.gjs، و new.gjs وهلم جرا.

التنقل

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

  • يجب تعريف أي روابط سيتم عرضها إما في الشريط العلوي أو الشريط الجانبي الداخلي لصفحة عرض الإضافة في مهيئ (على سبيل المثال assets/javascripts/initializers/admin-plugin-configuration-nav.js) باستخدام api.addAdminPluginConfigurationNav . تحتاج الروابط إلى label، route، و description (الذي يُستخدم لبحث المسؤول)
  • يجب أن يعمل هذا المهيئ فقط إذا كان المستخدم مسؤولاً.
  • يتم إنشاء رابط إعدادات الموقع للإضافة تلقائياً، لا حاجة لتضمينه هنا.
  • يمكن رؤية مثال هنا discourse-ai/assets/javascripts/initializers/admin-plugin-configuration-nav.js at ab4544d8977ec0e9d6aa42b4551df8317aa9b365 · discourse/discourse-ai · GitHub .

جانب الخادم

  • لا يزال add_admin_route يُستخدم لعرض مسارات المسؤول المخصصة في الشريط الجانبي للمسؤول ومن فهرس /plugins مع علامات التبويب على طول الأعلى. بشكل أساسي، هذا يحدد الصفحة الجذرية لواجهة مستخدم إضافتك.
    • يجب تمرير use_new_show_route: true كحجة إضافية هنا حتى يتم استخدام صفحة عرض الإضافة الجديدة.

اصطلاحات واجهة المستخدم

  • يجب أن تعرض كل مسار فهرس للإضافة مكون DPageSubheader لوصف نية ذلك المسار ولإضافة أي أزرار إجراءات ذات صلة.
  • يجب أن تستخدم أزرار الإجراءات التي تحتاج إلى عرض في رأس صفحة الإضافة الرئيسية منفذ admin-plugin-config-page-actions مع مكون مخصص. أفضل مكان للقيام بذلك هو في نفس المهيئ حيث يُستخدم addAdminPluginConfigurationNav.
    • يتم تمرير plugin و actions كـ outletArgs. plugin هو تمثيل النموذج للإضافة الحالية بحيث يمكن الوصول إلى اسم الإضافة وأشياء أخرى، actions هي مكونات أزرار الإجراءات الناتجة من DPageHeader.
api.renderInOutlet(
  "admin-plugin-config-page-actions",
  ChatAdminPluginActions
);

مواضيع ذات صلة:

10 إعجابات

و

لا يزالان لا يعملان. أعتقد أن الثاني هو -23 بدلاً من -24

5 إعجابات

يسعدني جدًا رؤية هذا منشورًا على ميتا أخيرًا. لقد استغرقت شهورًا من العمل في هذا، وسنستخدمه لتوحيد واجهة المستخدم والتنقل في كل صفحة في واجهة المسؤول.

هل يجب علينا إزالة جدول المحتويات هذا والاعتماد على “ديسكتوك” بدلاً من ذلك؟ أعتقد أن هذا سيكون أقل هشاشة، على الرغم من أنني أحب رؤية جدول المحتويات في أعلى المنشور.

7 إعجابات

شكراً @Moin - تم الإصلاح!

لقد أجريت هذا التغيير، وإلا فهو مجرد تكرار لجدول المحتويات.

4 إعجابات

تم تقسيم منشور إلى موضوع جديد: عرض اسم المستخدم في علامة تبويب المتصفح عند مسؤول المستخدم