Discourse incluye cientos de ‘Plugin Outlets’ (Salidas de Complemento) que se pueden usar para inyectar contenido nuevo o reemplazar contenido existente en la interfaz de usuario de Discourse. Los ‘Argumentos de Salida’ (‘Outlet arguments’) se ponen a disposición para que el contenido pueda personalizarse según el contexto.
Elección de una salida
Para encontrar el nombre de una salida de complemento, busca en el núcleo de Discourse "<code><PluginOutlet</code>", o utiliza el componente de tema ubicaciones de salidas de complemento. (ej. topic-above-posts).
Salidas envolventes (Wrapper outlets)
Algunas salidas en el núcleo se ven como <code><PluginOutlet @name="foo" /></code>. Estas te permiten inyectar contenido nuevo. Otras salidas ‘envolverán’ una implementación del núcleo existente de esta manera:
<PluginOutlet @name="foo">
implementación del núcleo
</PluginOutlet>
Definir un conector para este tipo de salida de complemento ‘envolvente’ reemplazará la implementación del núcleo. Solo un tema/complemento activo puede contribuir con un conector para una salida de complemento envolvente.
Para las salidas de complemento envolventes, puedes renderizar la implementación original del núcleo usando la palabra clave {{yield}}. Esto puede ser útil si solo deseas reemplazar la implementación del núcleo bajo ciertas condiciones, o si deseas envolverla en algo.
Definición de la plantilla
Una vez que hayas elegido una salida, decide un nombre para tu conector. Este debe ser único en todos los temas/complementos instalados en una comunidad determinada. ej. brand-official-topics
En tu tema/complemento, define una nueva plantilla handlebars con una ruta formateada de esta manera:
![]()
{theme}/javascripts/discourse/connectors/{outlet-name}/{connector-name}.hbs
![]()
{plugin}/assets/javascripts/discourse/connectors/{outlet-name}/{connector-name}.hbs
El contenido de estos archivos se renderizará como un Componente Ember. Para obtener información general sobre Ember/Handlebars, consulta las guías de Ember.
Para nuestro hipotético conector de “temas oficiales de la marca”, la plantilla podría verse así:
<div class="alert alert-info">
Este tema fue creado por un miembro del
<a href="https://discourse.org/team">Equipo de Discourse</a>
</div>
Algunas salidas de complemento envolverán automáticamente tu contenido en un elemento HTML. El tipo de elemento se define mediante @connectorTagName en el <code><PluginOutlet></code>.
Uso de argumentos de salida
Las Salidas de Complemento proporcionan información sobre el contexto circundante a través de @outletArgs. Los argumentos pasados a cada salida varían. Una forma fácil de ver los argumentos es agregar esto a tu plantilla:
{{log @outletArgs}}
Esto registrará los argumentos en la consola de desarrollador de tu navegador. Aparecerán como un objeto Proxy - para explorar la lista de argumentos, expande el [[Target]] del proxy.
En nuestro ejemplo topic-above-posts, el tema renderizado está disponible bajo @outletArgs.model. Por lo tanto, podemos agregar el nombre de usuario del miembro del equipo de esta manera:
<div class="alert alert-info">
Este tema fue creado por
{{@outletArgs.model.details.created_by.username}}
(un miembro del
<a href="https://discourse.org/team">Equipo de Discourse</a>)
</div>
Adición de lógica más compleja
A veces, una plantilla handlebars simple no es suficiente. Para agregar lógica Javascript a tu conector, puedes definir un archivo Javascript adyacente a tu plantilla handlebars. Este archivo debe exportar una definición de componente. Esto funciona igual que cualquier otra definición de componente y puede incluir inyecciones de servicio.
Definir un componente de esta manera eliminará el elemento envolvente automático connectorTagName, por lo que es posible que desees reintroducir un elemento del mismo tipo en tu archivo hbs.
En nuestro ejemplo topic-above-posts, es posible que queramos renderizar al usuario de manera diferente según la configuración del sitio ‘prioritize username in ux’ (priorizar nombre de usuario en la experiencia de usuario). Una definición de componente para eso podría verse algo así:
.../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;
}
}
}
Luego podemos actualizar la plantilla para hacer referencia al nuevo getter:
<div class="alert alert-info">
Este tema fue creado por
{{this.displayName}}
(un miembro del
<a href="https://discourse.org/team">Equipo de Discourse</a>)
</div>
Renderizado condicional
Si solo deseas que tu contenido se renderice bajo ciertas condiciones, a menudo es suficiente envolver tu plantilla con un bloque {{#if}} de handlebars. Si eso no es suficiente, es posible que desees usar el hook shouldRender para controlar si tu plantilla de conector se renderiza o no.
Primero, asegúrate de tener una definición de conector .js como se describe anteriormente. Luego, agrega una función estática static shouldRender(). Extendiendo nuestro ejemplo:
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";
}
// ... (cualquier otra lógica)
}
Ahora el conector solo se renderizará cuando la primera publicación del tema haya sido creada por un miembro del equipo.
shouldRender se evalúa en un contexto de autoseguimiento de Glimmer. Los cambios futuros en cualquier propiedad referenciada (ej. outletArgs) harán que la función se reevalúe.
Introducción de nuevas salidas
Si necesitas una salida que aún no existe, no dudes en hacer una solicitud de extracción (pull request) o abrir un tema en Dev.
Este documento está controlado por versiones: sugiere cambios en github.