O Discourse inclui centenas de Plugin Outlets (Pontos de Extensão de Plugin) que podem ser usados para injetar novo conteúdo ou substituir conteúdo existente na interface do Discourse. Os ‘argumentos de outlet’ são disponibilizados para que o conteúdo possa ser personalizado com base no contexto.
Escolhendo um outlet
Para encontrar o nome de um plugin outlet, procure no código-fonte do Discourse por “<PluginOutlet”, ou use o componente de tema plugin outlet locations. (por exemplo, topic-above-posts).
Wrapper outlets (Outlets de encapsulamento)
Alguns outlets no núcleo do Discourse parecem com <PluginOutlet @name="foo" />. Eles permitem que você injete novo conteúdo. Outros outlets vão ‘encapsular’ uma implementação existente do núcleo, como esta:
<PluginOutlet @name="foo">
implementação do núcleo
</PluginOutlet>
Definir um conector para esse tipo de outlet de ‘encapsulamento’ substituirá a implementação do núcleo. Apenas um tema/plugin ativo pode fornecer um conector para um plugin outlet de encapsulamento.
Para plugin outlets de encapsulamento, você pode renderizar a implementação original do núcleo usando a palavra-chave {{yield}}. Isso pode ser útil se você quiser substituir a implementação do núcleo apenas sob certas condições, ou se desejar encapsulá-la em algo.
Definindo o conector
Depois de escolher um outlet, decida um nome para seu conector. Este nome precisa ser único entre todos os temas/plugins instalados em uma determinada comunidade. por exemplo, brand-official-topics
Em seu tema/plugin, defina um novo conector .gjs com um caminho formatado assim:
![]()
{theme}/javascripts/discourse/connectors/{outlet-name}/{connector-name}.gjs
![]()
{plugin}/assets/javascripts/discourse/connectors/{outlet-name}/{connector-name}.gjs
O conteúdo desses arquivos será renderizado como um Componente Ember. Para informações gerais sobre Ember e o formato .gjs, confira os guias do Ember.
Para nosso conector hipotético “brand official topics”, o arquivo pode parecer com:
<template>
<div class="alert alert-info">
Este tópico foi criado por um membro da
<a href="https://discourse.org/team">Equipe Discourse</a>
</div>
</template>
Usando argumentos de outlet
Os Plugin Outlets fornecem informações sobre o contexto circundante via @outletArgs. Os argumentos passados para cada outlet variam. Uma maneira fácil de visualizar os argumentos é adicionar isso ao seu template:
{{log @outletArgs}}
Isso registrará os argumentos no console de desenvolvedor do seu navegador. Eles aparecerão como um objeto Proxy - para explorar a lista de argumentos, expanda o [[Target]] do proxy.
Em nosso exemplo topic-above-posts, o tópico renderizado está disponível em @outletArgs.model. Então, podemos adicionar o nome de usuário do membro da equipe assim:
<template>
<div class="alert alert-info">
Este tópico foi criado por
{{@outletArgs.model.details.created_by.username}}
(um membro da
<a href="https://discourse.org/team">Equipe Discourse</a>)
</div>
</template>
Adicionando lógica mais complexa
Às vezes, um template simples não é suficiente. Para adicionar lógica JavaScript ao seu conector, atualize seu arquivo .gjs para exportar um componente baseado em classe. Isso funciona exatamente como qualquer outra definição de componente e pode incluir injeções de serviço.
Em nosso exemplo topic-above-posts, podemos querer renderizar o usuário de forma diferente com base na configuração do site ‘prioritize username in ux’. O arquivo .gjs pode parecer com algo assim:
.../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 tópico foi criado por
{{this.displayName}}
(um membro da
<a href="https://discourse.org/team">Equipe Discourse</a>)
</div>
</template>
}
Renderização condicional
Se você quiser que seu conteúdo seja renderizado apenas sob certas condições, geralmente basta encapsular seu template com um bloco {{#if}} do Handlebars. Se isso não for suficiente, você pode querer usar o hook shouldRender para controlar se o template do seu conector será renderizado de qualquer forma.
Primeiro, certifique-se de ter um conector .gjs baseado em classe conforme descrito acima. Então, adicione uma função static shouldRender(). Expandindo nosso exemplo:
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";
}
// ... (qualquer outra lógica)
<template>
{{! ... }}
</template>
}
Agora o conector será renderizado apenas quando o primeiro post do tópico foi criado por um membro da equipe.
shouldRender é avaliado em um contexto de autotracking do Glimmer. Mudanças futuras em qualquer propriedade referenciada (por exemplo, outletArgs) farão com que a função seja reavaliada.
Introduzindo novos outlets
Se você precisar de um outlet que ainda não exista, sinta-se à vontade para fazer um pull request ou abrir um tópico em Development.
Este documento é controlado por versão - sugira alterações no github.