Discourse comprend des centaines de Plugin Outlet (points de sortie de plugin) qui peuvent être utilisés pour injecter du nouveau contenu ou remplacer le contenu existant dans l’interface utilisateur de Discourse. Les « arguments de l’outlet » (Outlet arguments) sont mis à disposition afin que le contenu puisse être personnalisé en fonction du contexte.
Choisir un outlet
Pour trouver le nom d’un plugin outlet, recherchez dans le cœur de Discourse « <PluginOutlet », ou utilisez le composant de thème plugin outlet locations. (par exemple, topic-above-posts).
Wrapper outlets
Certains outlets dans le cœur ressemblent à ceci : <PluginOutlet @name="foo" />. Ceux-ci vous permettent d’injecter du nouveau contenu. D’autres outlets « envelopperont » (wrap) une implémentation de base existante comme ceci :
<PluginOutlet @name="foo">
core implementation
</PluginOutlet>
Définir un connecteur pour ce type d’« outlet enveloppant » remplacera l’implémentation de base. Un seul thème/plugin actif peut fournir un connecteur pour un plugin outlet enveloppant.
Pour les plugin outlets enveloppants, vous pouvez rendre l’implémentation de base originale en utilisant le mot-clé {{yield}}. Ceci peut être utile si vous souhaitez uniquement remplacer l’implémentation de base sous certaines conditions, ou si vous souhaitez l’envelopper dans quelque chose.
Définir le template
Une fois que vous avez choisi un outlet, décidez d’un nom pour votre connecteur. Celui-ci doit être unique parmi tous les thèmes/plugins installés sur une communauté donnée. Par exemple : brand-official-topics
Dans votre thème/plugin, définissez un nouveau template Handlebars avec un chemin formaté comme ceci :
![]()
{theme}/javascripts/discourse/connectors/{outlet-name}/{connector-name}.hbs
![]()
{plugin}/assets/javascripts/discourse/connectors/{outlet-name}/{connector-name}.hbs
Le contenu de ces fichiers sera rendu comme un Composant Ember. Pour des informations générales sur Ember/Handlebars, consultez les guides Ember.
Pour notre connecteur hypothétique « brand official topics », le template pourrait ressembler à ceci :
<div class="alert alert-info">
This topic was created by a member of the
<a href="https://discourse.org/team">Discourse Team</a>
</div>
Certains plugin outlets envelopperont automatiquement votre contenu dans un élément HTML. Le type d’élément est défini par @connectorTagName sur le <PluginOutlet>.
Utilisation des arguments de l’outlet
Les Plugin Outlets fournissent des informations sur le contexte environnant via @outletArgs. Les arguments passés à chaque outlet varient. Un moyen simple de visualiser les arguments est d’ajouter ceci à votre template :
{{log @outletArgs}}
Ceci affichera les arguments dans la console de développement de votre navigateur. Ils apparaîtront comme un objet Proxy — pour explorer la liste des arguments, développez le [[Target]] du proxy.
Dans notre exemple topic-above-posts, le sujet rendu est disponible sous @outletArgs.model. Nous pouvons donc ajouter le nom d’utilisateur du membre de l’équipe comme ceci :
<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>
Ajout d’une logique plus complexe
Parfois, un simple template Handlebars ne suffit pas. Pour ajouter une logique Javascript à votre connecteur, vous pouvez définir un fichier Javascript adjacent à votre template Handlebars. Ce fichier doit exporter une définition de composant. Cela fonctionne exactement comme toute autre définition de composant, et peut inclure des injections de service.
Définir un composant de cette manière supprimera l’élément enveloppant automatique connectorTagName, vous voudrez donc peut-être réintroduire un élément du même type dans votre fichier hbs.
Dans notre exemple topic-above-posts, nous pourrions vouloir afficher l’utilisateur différemment en fonction du paramètre du site « prioritize username in ux ». Une définition de composant pour cela pourrait ressembler à ceci :
.../connectors/topic-above-posts/brand-official-topic.js :
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;
}
}
}
Nous pouvons ensuite mettre à jour le template pour faire référence au nouveau getter :
<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>
Rendu conditionnel
Si vous souhaitez que votre contenu ne soit rendu que sous certaines conditions, il suffit souvent d’envelopper votre template avec un bloc {{#if}} Handlebars. Si cela ne suffit pas, vous voudrez peut-être utiliser le hook shouldRender pour contrôler si votre template de connecteur doit être rendu ou non.
Tout d’abord, assurez-vous d’avoir une définition de connecteur .js comme décrit ci-dessus. Ensuite, ajoutez une fonction statique static shouldRender(). En étendant notre exemple :
import Component from "@glimmer/component";
import { getOwner } from "discourse-common/lib/get-owner";
export default class BrandOfficialTopics extends Component {
static shouldRender(outletArgs, helper) {
const firstPost = outletArgs.model.postStream.posts[0];
return firstPost.primary_group_name === "team";
}
// ... (toute autre logique)
}
Maintenant, le connecteur ne sera rendu que lorsque le premier message du sujet a été créé par un membre de l’équipe.
shouldRender est évalué dans un contexte d’autotrace (autotracking) Glimmer. Les changements futurs sur toute propriété référencée (par exemple, outletArgs) provoqueront la réévaluation de la fonction.
Introduction de nouveaux outlets
Si vous avez besoin d’un outlet qui n’existe pas encore, n’hésitez pas à créer une pull request, ou à ouvrir un sujet dans Dev.
Ce document est contrôlé par version — suggérez des modifications sur github.