Использование коннекторов плагина Outlet из темы или плагина

Discourse включает в себя сотни Plugin Outlets, которые можно использовать для вставки нового контента или замены существующего контента в интерфейсе Discourse. Аргументы аутлета (Outlet arguments) доступны для того, чтобы контент мог быть настроен в зависимости от контекста.

Выбор аутлета

Чтобы найти имя плагин-аутлета, выполните поиск по ядру Discourse на строку “<PluginOutlet” или используйте компонент темы plugin outlet locations. (например, topic-above-posts).

Обёрточные аутлеты (Wrapper outlets)

Некоторые аутлеты в ядре выглядят как <PluginOutlet @name="foo" />. Они позволяют вставлять новый контент. Другие аутлеты «обёртывают» существующую реализацию в ядре, как показано ниже:

<PluginOutlet @name="foo">
  реализация в ядре
</PluginOutlet>

Определение коннектора для такого «обёрточного» аутлета заменит реализацию в ядре. Только одна активная тема или плагин может предоставлять коннектор для обёрточного плагин-аутлета.

Для обёрточных плагин-аутлетов вы можете отобразить исходную реализацию в ядре, используя ключевое слово {{yield}}. Это может быть полезно, если вы хотите заменить реализацию в ядре только при определённых условиях или если вы хотите обернуть её в что-то другое.

Определение коннектора

После того как вы выбрали аутлет, придумайте имя для вашего коннектора. Оно должно быть уникальным среди всех тем и плагинов, установленных в данном сообществе. Например: brand-official-topics

В вашей теме или плагине определите новый коннектор .gjs с путём, оформленным следующим образом:

:art: {theme}/javascripts/discourse/connectors/{outlet-name}/{connector-name}.gjs

:electric_plug: {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>

Использование аргументов аутлета

Plugin Outlets предоставляют информацию об окружающем контексте через @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 мы можем захотеть отображать пользователя по-разному в зависимости от настройки сайта «prioritize username in 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>
}

Условное отображение

Если вы хотите, чтобы ваш контент отображался только при определённых условиях, часто достаточно обернуть ваш шаблон в блок {{#if}} handlebars. Если этого недостаточно, вы можете использовать хук 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.

39 лайков
Using discourse's plugin outlets
Add HTML (Link) Next To Logo
What is the best way to integrate member applications?
Group Semantics
Can I put the search form at the top of our 404 page?
Native theme support
How to show user total post count beside name
Developing Discourse Plugins - Part 2 - Connect to a plugin outlet
Feedback on "on-discourse" javascript for setting up custom JS for each page?
Topic-timeline api.decorateWidget call has stopped working
Developing Discourse Plugins - Part 2 - Connect to a plugin outlet
Developing Discourse Themes & Theme Components
How to add btn before "sign in"
Minimizing Maintenance on Theme Customizations
How to add custom fields to models
Tags at the top of the topic list in a Category
I want to insert images (banner) between the topic answers. How do I start?
How to add a link shortcut to the area under the title
Baidu Search
Add Banner/HTML (Widget) before reply button
Upcoming Header Changes - Preparing Themes and Plugins
Upgrading Discourse to Ember 4
Converting modals from legacy controllers to new DModal component API
Need help integrating code wrote on Edittext to the Discourse
Settings not appearing
Add link to external SSO profile to profile page
How to add a custom button in user profile card?
(not recommended) Overriding Discourse templates from a Theme or Plugin
How to override the site-header.hbs file from custom theme?
Upcoming topic-list changes - how to prepare themes and plugins
Working with .erb templates in a plugin
How to Integrate a Custom Plugin in discourse UI
Templating of my "component" broke. How do I fix it?
Templating of my "component" broke. How do I fix it?
Modernizing inline script tags for templates & JS API
Custom Components -- add button or text at any plugin outlet
(not recommended) Overriding Discourse templates from a Theme or Plugin
Adding "latest topics" header in the main interface
Display Tags inline with thread title, instead of being on the bottom line
How to add a custom button in user profile card?
Discourse view file update does not reflect in browser
Discourse view file update does not reflect in browser
Add likes and views to search display
Using template hbs to add HTML content to a plugin outlet
Adding a billing section in the member section
Adding a billing section in the member section
How to modify the header HTML, but still remaining the default founctions
Removing support for "template overrides" and mobile-specific templates
How can i add image in login and register box
Most “traditional” or classic forum Category listing
Newbie help accessing code
How to add custom html next to logo using discourse plugin methods
Using the DModal API to render Modal windows (aka popups/dialogs) in Discourse
Air Theme
How to create a plugin with backend API calls to populate composer while drafting?
How to add a custom url text link on the login page
Add Text In Header Beside Logo
Split up theme Javascript into multiple files