Discourse enthält hunderte von Plugin-Outlets, mit denen neue Inhalte in die Discourse-Oberfläche eingefügt oder vorhandene Inhalte ersetzt werden können. „Outlet-Argumente“ stehen zur Verfügung, damit Inhalte basierend auf dem Kontext angepasst werden können.
Auswahl eines Outlets
Um den Namen eines Plugin-Outlets zu finden, durchsuche den Discourse-Kern nach “<PluginOutlet” oder verwende das plugin outlet locations Theme-Component. (z. B. topic-above-posts).
Wrapper-Outlets
Einige Outlets im Kern sehen so aus: <PluginOutlet @name="foo" />. Mit diesen kannst du neue Inhalte einfügen. Andere Outlets „wrappen“ (umhüllen) eine vorhandene Kern-Implementierung, zum Beispiel so:
<PluginOutlet @name="foo">
core implementation
</PluginOutlet>
Die Definition eines Connectors für diese Art von „Wrapper“-Outlet ersetzt die Kern-Implementierung. Nur ein aktives Theme/Plugin kann einen Connector für ein Wrapper-Plugin-Outlet bereitstellen.
Bei Wrapper-Plugin-Outlets kannst du die ursprüngliche Kern-Implementierung mit dem {{yield}}-Schlüsselwort rendern. Dies kann hilfreich sein, wenn du die Kern-Implementierung nur unter bestimmten Bedingungen ersetzen möchtest oder sie in etwas anderes einbetten willst.
Definition des Connectors
Sobald du ein Outlet ausgewählt hast, entscheide dich für einen Namen für deinen Connector. Dieser muss über alle auf einer bestimmten Community installierten Themes/Plugins hinweg eindeutig sein. z. B. brand-official-topics
Definiere in deinem Theme/Plugin einen neuen .gjs-Connector mit einem Pfad in folgendem Format:
![]()
{theme}/javascripts/discourse/connectors/{outlet-name}/{connector-name}.gjs
![]()
{plugin}/assets/javascripts/discourse/connectors/{outlet-name}/{connector-name}.gjs
Der Inhalt dieser Dateien wird als Ember-Komponente gerendert. Für allgemeine Informationen zu Ember und dem .gjs-Format schau dir die Ember-Guides an.
Für unseren hypothetischen „brand official topics“-Connector könnte die Datei so aussehen:
<template>
<div class="alert alert-info">
This topic was created by a member of the
<a href="https://discourse.org/team">Discourse Team</a>
</div>
</template>
Verwendung von Outlet-Argumenten
Plugin-Outlets stellen Informationen über den umgebenden Kontext über @outletArgs bereit. Die an jedes Outlet übergebenen Argumente variieren. Ein einfacher Weg, die Argumente anzuzeigen, ist es, Folgendes in deine Vorlage einzufügen:
{{log @outletArgs}}
Dies protokolliert die Argumente in der Entwickler-Konsole deines Browsers. Sie erscheinen als Proxy-Objekt – um die Liste der Argumente zu erkunden, klappst du das [[Target]] des Proxys auf.
In unserem topic-above-posts-Beispiel ist das gerenderte Thema unter @outletArgs.model verfügbar. So können wir den Benutzernamen des Teammitglieds hinzufügen:
<template>
<div class="alert alert-info">
This topic was created by
{{@outletArgs.model.details.created_by.username}}
(a member of the
<a href="https://discourse.org/team">Discourse Team</a>)
</div>
</template>
Hinzufügen komplexerer Logik
Manchmal reicht eine einfache Vorlage nicht aus. Um Javascript-Logik zu deinem Connector hinzuzufügen, wandle deine .gjs-Datei in eine exportierende class-basierte Komponente um. Dies funktioniert genauso wie jede andere Komponenten-Definition und kann Service-Injektionen enthalten.
In unserem topic-above-posts-Beispiel möchten wir den Benutzer möglicherweise basierend auf der „prioritize username in ux“-Site-Einstellung unterschiedlich rendern. Die .gjs-Datei könnte so aussehen:
.../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 topic was created by
{{this.displayName}}
(a member of the
<a href="https://discourse.org/team">Discourse Team</a>)
</div>
</template>
}
Konditionales Rendering
Wenn du deinen Inhalt nur unter bestimmten Bedingungen gerendert haben möchtest, reicht es oft aus, deine Vorlage mit einem Handlebars-{{#if}}-Block zu umhüllen. Wenn das nicht ausreicht, möchtest du möglicherweise den shouldRender-Hook verwenden, um zu steuern, ob deine Connector-Vorlage überhaupt gerendert wird.
Stelle zunächst sicher, dass du einen class-basierten .gjs-Connector hast, wie oben beschrieben. Füge dann eine static shouldRender()-Funktion hinzu. Unsere Beispiel-Erweiterung:
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";
}
// ... (any other logic)
<template>
{{! ... }}
</template>
}
Nun wird der Connector nur gerendert, wenn der erste Beitrag des Themas von einem Teammitglied erstellt wurde.
shouldRender wird in einem Glimmer-Autotracking-Kontext ausgewertet. Zukünftige Änderungen an referenzierten Eigenschaften (z. B. outletArgs) führen dazu, dass die Funktion neu ausgewertet wird.
Einführung neuer Outlets
Wenn du ein Outlet benötigst, das noch nicht existiert, zögere nicht, einen Pull Request zu erstellen oder ein Thema in Development zu eröffnen.
Dieses Dokument wird versioniert verwaltet – schlage Änderungen auf github vor.