Discourse включает сотни плагинов-выходов (Plugin Outlets), которые можно использовать для вставки нового контента или замены существующего контента в интерфейсе Discourse. Аргументы выхода (Outlet arguments) становятся доступными для настройки контента в зависимости от контекста.
Выбор выхода
Чтобы найти имя плагина-выхода, выполните поиск по ядру Discourse по строке “<PluginOutlet” или используйте тему-компонент расположения плагинов-выходов (например, topic-above-posts).
Выходы-обертки
Некоторые выходы в ядре выглядят как <PluginOutlet @name="foo" />. Они позволяют вставлять новый контент. Другие выходы «оборачивают» существующую реализацию ядра следующим образом:
<PluginOutlet @name="foo">
реализация ядра
</PluginOutlet>
Определение коннектора для такого типа «оберточного» выхода заменит реализацию ядра. Только одна активная тема/плагин может предоставлять коннектор для оберточного плагина-выхода.
Для оберточных плагинов-выходов вы можете отрендерить исходную реализацию ядра, используя ключевое слово {{yield}}. Это может быть полезно, если вы хотите заменить реализацию ядра только при определенных условиях или если хотите обернуть её во что-то еще.
Определение коннектора
После выбора выхода определите имя для вашего коннектора. Оно должно быть уникальным среди всех установленных тем/плагинов в данном сообществе. Например: brand-official-topics.
В вашей теме/плагине определите новый коннектор .gjs с путем в формате:
![]()
{theme}/javascripts/discourse/connectors/{outlet-name}/{connector-name}.gjs
![]()
{plugin}/assets/javascripts/discourse/connectors/{outlet-name}/{connector-name}.gjs
Содержимое этих файлов будет рендериться как компонент Ember. Общую информацию об Ember и формате .gjs можно найти в руководствах Ember.
Для нашего гипотетического коннектора “brand official topics” файл может выглядеть так:
<template>
<div class="alert alert-info">
Эта тема была создана участником
<a href="https://discourse.org/team">команды Discourse</a>
</div>
</template>
Использование аргументов выхода
Плагины-выходы предоставляют информацию о окружающем контексте через @outletArgs. Аргументы, передаваемые каждому выходу, различаются. Простой способ просмотреть аргументы — добавить это в ваш шаблон:
{{log @outletArgs}}
Это выведет аргументы в консоль разработчика вашего браузера. Они появятся как объект Proxy — чтобы просмотреть список аргументов, раскройте [[Target]] прокси.
В нашем примере topic-above-posts рендеримая тема доступна в @outletArgs.model. Таким образом, мы можем добавить имя пользователя участника команды следующим образом:
<template>
<div class="alert alert-info">
Эта тема была создана
{{@outletArgs.model.details.created_by.username}}
(участником
<a href="https://discourse.org/team">команды Discourse</a>)
</div>
</template>
Добавление более сложной логики
Иногда простого шаблона недостаточно. Чтобы добавить логику JavaScript в ваш коннектор, обновите ваш файл .gjs, экспортировав компонент на основе класса. Он работает так же, как и любое другое определение компонента, и может включать внедрение сервисов.
В нашем примере topic-above-posts мы можем захотеть отображать пользователя по-разному в зависимости от настройки сайта «приоритет имени пользователя в UX». Файл .gjs может выглядеть примерно так:
.../connectors/topic-above-posts/brand-official-topic.gjs:
import Component from "@glimmer/component";
import { service } from "@ember/service";
export default class BrandOfficialTopics extends Component {
@service siteSettings;
get displayName() {
const user = this.args.outletArgs.model.details.created_by;
if (this.siteSettings.prioritize_username_in_ux) {
return user.username;
} else {
return user.name;
}
}
<template>
<div class="alert alert-info">
Эта тема была создана
{{this.displayName}}
(участником
<a href="https://discourse.org/team">команды Discourse</a>)
</div>
</template>
}
Условный рендеринг
Если вы хотите, чтобы ваш контент рендерился только при определенных условиях, часто достаточно обернуть ваш шаблон в блок Handlebars {{#if}}. Если этого недостаточно, вы можете использовать хук shouldRender, чтобы контролировать, будет ли ваш шаблон коннектора рендериться вообще.
Сначала убедитесь, что у вас есть коннектор .gjs на основе класса, как описано выше. Затем добавьте статическую функцию static shouldRender(). Расширяя наш пример:
import Component from "@glimmer/component";
export default class BrandOfficialTopics extends Component {
static shouldRender(outletArgs, helper) {
const firstPost = outletArgs.model.postStream.posts[0];
return firstPost.primary_group_name === "team";
}
// ... (любая другая логика)
<template>{{! ... }}</template>
}
Теперь коннектор будет рендериться только в том случае, если первый пост темы был создан участником команды.
shouldRender оценивается в контексте автотрекинга Glimmer. Будущие изменения любых ссылаемых свойств (например, outletArgs) вызовут повторную оценку функции.
Создание новых выходов
Если вам нужен выход, которого еще не существует, пожалуйста, создайте pull request или откройте тему в канале Development.
Этот документ находится под версионным контролем — предложите изменения на GitHub.