O Discourse inclui centenas de Plugin Outlets que podem ser usados para injetar novo conteúdo ou substituir conteúdo existente na interface do usuário do Discourse. ‘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, pesquise no núcleo do Discourse por “<PluginOutlet”, ou use o componente de tema plugin outlet locations. (por exemplo, topic-above-posts).
Outlets wrapper
Alguns outlets no núcleo se parecem com <PluginOutlet @name="foo" />. Eles permitem que você injete novo conteúdo. Outros outlets ‘envolverão’ uma implementação existente do núcleo, assim:
<PluginOutlet @name="foo">
implementação do núcleo
</PluginOutlet>
Definir um conector para esse tipo de outlet ‘wrapper’ substituirá a implementação do núcleo. Apenas um tema/plugin ativo pode contribuir com um conector para um plugin outlet wrapper.
Para plugin outlets wrapper, 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 envolvê-la em algo.
Definindo o conector
Depois de escolher um outlet, decida um nome para seu conector. Este precisa ser único em 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, consulte os guias do Ember.
Para nosso conector hipotético “brand official topics”, o arquivo pode parecer assim:
<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
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 da mesma forma que qualquer outra definição de componente e pode incluir injeção de serviços.
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 se 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, muitas vezes basta envolver seu template em 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 ou não.
Primeiro, certifique-se de ter um conector .gjs baseado em classe como descrito acima. Em seguida, adicione uma função static shouldRender(). Estendendo 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 a primeira postagem do tópico tiver sido criada por um membro da equipe.
shouldRender é avaliado em um contexto de autotracking do Glimmer. Alterações 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 existe, sinta-se à vontade para fazer um pull request ou abrir um tópico em Development.
Este documento está sob controle de versão — sugira alterações no GitHub.