O Discourse inclui centenas de Plugin Outlets (Pontos de Saída de Plugin) que podem ser usados para injetar novo conteúdo ou substituir conteúdo existente na interface do usuário do Discourse. ‘Argumentos do 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 localizações de plugin outlet. (ex: topic-above-posts).
Wrapper outlets
Alguns outlets no núcleo se parecem com <PluginOutlet @name="foo" />. Estes permitem que você injete novo conteúdo. Outros outlets irão ‘envolver’ uma implementação de núcleo existente como esta
<PluginOutlet @name="foo">
implementação do núcleo
</PluginOutlet>
Definir um conector para este 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 você gostaria de envolvê-la em algo.
Definindo o template
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. ex: brand-official-topics
No seu tema/plugin, defina um novo template handlebars com um caminho formatado assim:
![]()
{theme}/javascripts/discourse/connectors/{outlet-name}/{connector-name}.hbs
![]()
{plugin}/assets/javascripts/discourse/connectors/{outlet-name}/{connector-name}.hbs
O conteúdo desses arquivos será renderizado como um Componente Ember. Para informações gerais sobre Ember/Handlebars, consulte os guias do Ember.
Para nosso hipotético conector “brand official topics”, o template pode se parecer com
<div class="alert alert-info">
Este tópico foi criado por um membro da
<a href="https://discourse.org/team">Equipe Discourse</a>
</div>
Alguns plugin outlets envolverão automaticamente seu conteúdo em um elemento HTML. O tipo de elemento é definido por @connectorTagName no <PluginOutlet>.
Usando argumentos do outlet
Plugin Outlets fornecem informações sobre o contexto circundante via @outletArgs. Os argumentos passados para cada outlet variam. Uma maneira fácil de ver os argumentos é adicionar isto ao seu template:
{{log @outletArgs}}
Isso registrará os argumentos no console do 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 sob @outletArgs.model. Então podemos adicionar o nome de usuário do membro da equipe assim:
<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>
Adicionando lógica mais complexa
Às vezes, um template handlebars simples não é suficiente. Para adicionar lógica Javascript ao seu conector, você pode definir um arquivo Javascript adjacente ao seu template handlebars. Este arquivo deve exportar uma definição de componente. Isso funciona exatamente como qualquer outra definição de componente, e pode incluir injeções de serviço.
Definir um componente assim removerá o elemento wrapper automático connectorTagName, então você pode querer reintroduzir um elemento do mesmo tipo no seu arquivo hbs.
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’. Uma definição de componente para isso pode se parecer com isto:
.../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;
}
}
}
Podemos então atualizar o template para referenciar o novo getter:
<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>
Renderização condicional
Se você deseja que seu conteúdo seja renderizado apenas sob certas condições, geralmente é suficiente envolver 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 é renderizado.
Primeiro, certifique-se de ter uma definição de conector .js como descrito acima. Em seguida, adicione uma função estática static shouldRender(). Estendendo nosso exemplo:
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";
}
// ... (qualquer outra lógica)
}
Agora o conector só será renderizado quando o primeiro post do tópico foi criado por um membro da equipe.
shouldRender é avaliado em um contexto de autotracking Glimmer. Mudanças em quaisquer propriedades referenciadas (ex: 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 Dev.
Este documento é controlado por versão - sugira alterações no github.