Discourse incluye cientos de Plugin Outlets que se pueden utilizar para inyectar nuevo contenido o reemplazar contenido existente en la interfaz de Discourse. Se ponen a disposición los ‘argumentos del outlet’ para que el contenido pueda personalizarse según el contexto.
Elegir un outlet
Para encontrar el nombre de un plugin outlet, busca en el núcleo de Discourse por “<PluginOutlet”, o utiliza el componente de tema ubicaciones de plugin outlets. (p. ej. topic-above-posts).
Outlets de envoltura (Wrapper outlets)
Algunos outlets en el núcleo se ven como <PluginOutlet @name="foo" />. Estos permiten inyectar nuevo contenido. Otros outlets ‘envuelven’ una implementación existente del núcleo de la siguiente manera:
<PluginOutlet @name="foo">
implementación del núcleo
</PluginOutlet>
Definir un conector para este tipo de outlet de ‘envoltura’ reemplazará la implementación del núcleo. Solo un tema/plugin activo puede contribuir con un conector para un plugin outlet de envoltura.
Para los plugin outlets de envoltura, puedes renderizar la implementación original del núcleo utilizando 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.
Definiendo el conector
Una vez que hayas elegido un outlet, decide un nombre para tu conector. Este debe ser único entre todos los temas/plugins instalados en una comunidad dada. p. ej. brand-official-topics
En tu tema/plugin, define un nuevo conector .gjs con una ruta con el siguiente formato:
![]()
{theme}/javascripts/discourse/connectors/{outlet-name}/{connector-name}.gjs
![]()
{plugin}/assets/javascripts/discourse/connectors/{outlet-name}/{connector-name}.gjs
El contenido de estos archivos se renderizará como un Componente de Ember. Para información general sobre Ember y el formato .gjs, consulta las guías de Ember.
Para nuestro conector hipotético “brand official topics”, el archivo podría verse así:
<template>
<div class="alert alert-info">
Este tema fue creado por un miembro del
<a href="https://discourse.org/team">Equipo de Discourse</a>
</div>
</template>
Usando argumentos de outlet
Los Plugin Outlets proporcionan información sobre el contexto circundante a través de @outletArgs. Los argumentos pasados a cada outlet varían. Una forma fácil de ver los argumentos es añadir 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 de topic-above-posts, el tema renderizado está disponible bajo @outletArgs.model. Por lo tanto, podemos añadir el nombre de usuario del miembro del equipo de la siguiente manera:
<template>
<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>
</template>
Añadiendo lógica más compleja
A veces, una plantilla simple no es suficiente. Para añadir lógica de Javascript a tu conector, actualiza tu archivo .gjs para exportar un componente basado en clase. Esto funciona de la misma manera que cualquier otra definición de componente y puede incluir inyecciones de servicios.
En nuestro ejemplo de topic-above-posts, es posible que deseemos renderizar al usuario de manera diferente según la configuración del sitio ‘prioritize username in ux’. El archivo .gjs podría verse así:
.../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">
Este tema fue creado por
{{this.displayName}}
(un miembro del
<a href="https://discourse.org/team">Equipo de Discourse</a>)
</div>
</template>
}
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 gancho shouldRender para controlar si la plantilla de tu conector se renderiza o no.
En primer lugar, asegúrate de tener un conector .gjs basado en clase como se describió anteriormente. Luego, añade una función static shouldRender(). Extendiendo nuestro ejemplo:
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";
}
// ... (cualquier otra lógica)
<template>
{{! ... }}
</template>
}
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 autotracking de Glimmer. Los cambios futuros en cualquier propiedad referenciada (p. ej. outletArgs) causarán que la función se reevalúe.
Introduciendo nuevos outlets
Si necesitas un outlet que aún no existe, no dudes en enviar una solicitud de extracción (pull request) o abrir un tema en Development.
Este documento está bajo control de versiones - sugiere cambios en github.