Создание последовательных административных интерфейсов

Эти руководства направлены на создание согласованного интерфейса администратора, с акцентом на удобство использования, доступность и структурированную разметку. Ознакомьтесь с содержанием, чтобы узнать, что включено, и легко перейти к нужному разделу.

Примечание: Терминология, используемая здесь, определена в глоссарии интерфейса администратора.

0. Предисловие — Структура страницы настроек и ссылки в боковой панели

При добавлении новых страниц настроек в интерфейс администратора, для каждой страницы потребуется ссылка в боковой панели, а также заголовок и описание. Это необходимо для обеспечения единообразия повсеместно, а также для того, чтобы будущие улучшения поиска в панели администратора могли отображать всю структуру интерфейса.

Обычно структура интерфейса администратора выглядит следующим образом:

  • Интерфейс администратора
    • Страница настроек (отображается в боковой панели)
      • Вкладка «Настройки»
      • Дополнительные вкладки третьего уровня (опционально)
        • Страница редактирования/создания ресурса третьего уровня

В конечном итоге между корневым интерфейсом и страницами настроек будет добавлена «страница обзора раздела».

Ссылки в боковой панели

Все страницы администратора должны быть добавлены в ADMIN_NAV_MAP в discourse/frontend/discourse/app/lib/sidebar/admin-nav-map.js at main · discourse/discourse · GitHub . Каждый элемент должен содержать как минимум следующие ключи:

  • name — Уникальный идентификатор ссылки, должен быть в формате snake_case
  • route ИЛИ hrefroute — это идентификатор маршрута Ember, например adminUsers. Для администраторов они определены в карте маршрутов администратора . Можно использовать href, но предпочтительнее route.
  • label ИЛИ textlabel — это ключ 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 равно true.
  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.a. Подзаголовок

Подзаголовок — это вторичный заголовок, используемый для разделения контента в разделе, обычно под вкладками.

Структура

  • Подзаголовок: Подзаголовок того, о чем идет речь (необязательно)
  • Основное действие: Основное действие подзаголовка (необязательно)
  • Вторичное действие: Настройки кнопки вторичного действия подзаголовка (необязательно)

Использование и содержание

  • Подзаголовок: Используйте заголовок уровня 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.b. Область настроек

Область настроек состоит из карточек или секций. Карточки отлично подходят для группировки связанной информации и задач, помогая пользователям быстрее просматривать и расставлять приоритеты.

:art: Дизайн

Карточка

Карточки настроены с радиусом скругления 2px и используют фон --secondary. Также у них есть сплошная граница 1px с --primary-low и отступ 20px вокруг контента.

Вариация по умолчанию

Вариация аккордеона

Дизайн и использование

  • Группируйте связанную информацию
  • Отображайте информацию так, чтобы администраторы и модераторы видели самое важное первым
  • Используйте заголовки, которые четко объясняют назначение карточки
  • Разбивайте сложные на несколько секций, если необходимо

вариация по умолчанию

  • Ограничивайтесь одним основным призывом к действию на карточку
  • Размещайте основной призыв к действию в нижней части карточки для следующих шагов

вариация аккордеона

  • Используйте верхний правый угол карточки для необязательных действий, таких как “Просмотреть все”

Содержание

  • Все формы должны использовать компоненты 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.c. Вставка справки

Этот раздел предоставляет дополнительные руководства, документацию или контекст внутри содержимого страницы.

v1

:art: Дизайн

Дизайн и использование

  • Показывайте связанную документацию или руководства по содержимому страницы, чтобы предоставить полезную информацию
  • Включайте иконку в заголовок, чтобы его было легко распознать
  • Размещайте этот раздел во вторичной (1/3) области макета

Содержание

  • Заголовки должны быть в регистре предложений

:hammer_and_wrench: Реализация

Фрагменты кода или ссылка на тему/GitHub

5.d. Таблица

Таблицы отображают информацию в виде сетки ячеек, столбцов и строк, что позволяет администраторам быстро просматривать элементы и выполнять действия.

:art: Дизайн

Использование

  • Используйте таблицы для отображения структурированного контента, где каждая запись имеет одинаковые атрибуты.
  • Позволяйте администраторам просматривать, включать/отключать, редактировать и удалять наборы данных.
  • Подходит для наборов данных, которые будут продолжать расти со временем.

Дизайн

  • Используйте горизонтальные линии между строками для визуального разделения контента, включая последнюю строку. Избегайте использования границ или рамок вокруг таблицы, чтобы она не выглядела как сетка.
  • Не применяйте вертикальные линии между столбцами. Таблицы без вертикальных линий обычно легче просматривать и читать.

Дополнительные действия

  • Действия со строкой: Включайте дополнительные действия в крайнем правом столбце каждой строки таблицы.
    • Если есть два или более интерактивных элемента, основное действие (например, “Редактировать”) должно быть текстовой кнопкой, а все остальные действия со строкой, включая “Удалить”, должны быть сгруппированы в выпадающем меню [...]. Иконки в выпадающих меню приветствуются для визуального разделения.
    • Если есть только действие “Удалить” и нет основного действия, используйте встроенную текстовую кнопку “Удалить” со стилем btn-default.
    • Вы должны обернуть текст основного столбца (обычно d-table__cell --overview) ссылкой, которая ведет администратора напрямую на страницу просмотра/редактирования, соответствующую строке, для быстрого доступа.
  • Подтверждение удаления: Все кнопки “Удалить” должны показывать подтверждение перед выполнением действия.

Содержание

  • Заголовок: Заголовок таблицы — это верхняя строка, которая идентифицирует столбцы ниже. Он обеспечивает ясность, особенно если данные неочевидны или неоднозначны. Заголовки должны быть короткими, описательными и релевантными, используя регистр заголовков. Избегайте заголовков, которые слишком длинные для контента в строках ниже.
  • Столбцы: Располагайте столбцы по приоритету или таким образом, чтобы они рассказывали связную историю с данными. Размер столбцов должен соответствовать их содержимому, с узкими столбцами для малого контента и более широкими для абзацев.
  • Строки: Строки должны поддерживать текст, кнопки, ссылки и иконки для улучшения представления данных.
  • Нет данных: Пустые списки должны использовать компонент AdminConfigAreaEmptyList с кнопкой CTA и меткой, чтобы направить пользователя к созданию новых записей

:hammer_and_wrench: Реализация

Существует небольшой набор CSS-классов, которые необходимо использовать с таблицами, чтобы они хорошо работали на мобильных и настольных устройствах.

Элементам <table> следует применить класс d-table.

Элементам <thead> следует применить класс d-table__header.

Элементам <tr> следует применить класс d-table__row.

Элементам <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.e Маршрут третьего уровня

Маршрут третьего уровня — это тот, к которому можно добраться только из области настроек. Обычно они имеют вид маршрутов редактирования/создания, как этот для флагов:

Здесь в большинстве случаев будут размещены формы, использующие FormKit.

Используйте стандартные RESTful маршруты для них:

Действие Путь
Новый <resource>/new
Редактировать <resource>/:id/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 настройки.

Настройки сайта могут находиться в нескольких areas, и вы можете отображать одну или несколько на одной странице.

  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. Общие рекомендации

  • Slug-адреса URL должны использовать дефисы (-) для обозначения пробелов в словах, а не подчеркивания (_).

  • Весь текст в интерфейсах администратора должен следовать руководствам по форматированию текста, приведенным здесь:

8. Плагины

Некоторым плагинам нужен подробный пользовательский интерфейс конфигурации для их плагина (например, AI, Автоматизация, Гамификация), а не только набор настроек сайта. Например, вот 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, чтобы описать назначение этого маршрута и добавить любые связанные кнопки действий.
  • Кнопки действий, которые нужно отобразить в основном заголовке страницы плагина, должны использовать outlet admin-plugin-config-page-actions с выделенным компонентом. Лучшее место для этого — в том же инициализаторе, где используется addAdminPluginConfigurationNav.
    • plugin и actions передаются как outletArgs. plugin — это модель текущего плагина, чтобы можно было получить доступ к имени плагина и другим вещам, actions — это возвращаемые компоненты кнопок действий из DPageHeader.
api.renderInOutlet(
  "admin-plugin-config-page-actions",
  ChatAdminPluginActions
);

Связанные темы:

10 лайков

И

всё ещё не работают. Я думаю, что во втором случае должно быть -23 вместо -24.

5 лайков

Наконец-то так приятно увидеть это на meta. На это ушли месяцы работы, и мы будем использовать его для стандартизации интерфейса и навигации на каждой странице административной панели.

Может, стоит просто убрать это оглавление и полагаться на discotoc? Думаю, это было бы менее хрупким решением, хотя мне нравится видеть оглавление в начале поста.

7 лайков

Спасибо @Moin — всё исправлено!

Я внёс это изменение, иначе получается просто дублирующееся оглавление.

4 лайка

Пост был перемещен в новую тему: Отображение имени пользователя во вкладке браузера при просмотре страницы администратора пользователя