Adicionar um botão direto para respostas pré-definidas no editor

Clique duas vezes não é realmente muito trabalho, mas esta é uma boa oportunidade para uma explicação geral que documenta como trabalhar com botões do composer, com foco no que você está tentando fazer.

Adicionar botões à barra de ferramentas é feito com um método diferente da API de plugins.

A barra de ferramentas usa este método plugin-api.js.es6#L375-L391, enquanto o menu pop-up usa este plugin-api.js.es6#L396-L411.

O plugin de respostas prontas usa o método de menu pop-up da seguinte forma:

https://github.com/discourse/discourse-canned-replies/blob/master/assets/javascripts/initializers/add-canned-replies-ui-builder.js.es6#L18-L25

Você não pode mover o botão a menos que faça um fork do plugin — altamente não recomendado.

O que você pode fazer é adicionar outro botão na barra de ferramentas que faça a mesma coisa e ocultar o antigo. Para criar um botão na barra de ferramentas, você precisará ver como outros botões são adicionados.

Existem dois tipos de botões na barra de ferramentas. O primeiro tipo são botões que lidam com formatação, como Negrito e Itálico. Como eles não são semelhantes ao que você deseja alcançar, vamos ignorá-los por enquanto.

O outro tipo são botões que inserem coisas como datas e emojis. Vamos olhar para o botão de data - calendário.

Agora temos um exemplo para recorrer. Então, vamos tentar criar o novo botão.

Começamos com isso:

api.onToolbarCreate(toolbar => {
  toolbar.addButton({
  
  });
});

e adicionamos os atributos do botão de resposta pronta um por um. Para referência, eles são:

id: "canned_replies_button",
icon: "far-clipboard",
action: "showCannedRepliesButton",
label: "canned_replies.composer_button_text"

id: isso permite que você adicione classes CSS ao botão — usaremos custom-canned-button.

icon: o ícone que o botão usará — manteremos o mesmo.

label: os botões de pop-up têm texto, enquanto os botões do composer não, então precisamos mudar isso para title e usar o mesmo valor.

action: é aqui que você define o que o botão faz. Vamos colocar tudo junto:

api.onToolbarCreate(toolbar => {
  toolbar.addButton({
    id: "custom-canned-replies",
    icon: "far-clipboard",
    action: "showCannedRepliesButton",
    title: "canned_replies.composer_button_text"
  });
});

Se você tentar isso, obterá um botão na barra de ferramentas, mas clicar nele não fará nada. Isso acontece porque a ação showCannedRepliesButton não está definida. Isso ocorre devido ao contexto diferente — já que você está fazendo isso em um tema.

Se você olhar para o plugin de respostas prontas, notará que essa ação é definida no controlador do composer:

https://github.com/discourse/discourse-canned-replies/blob/master/assets/javascripts/initializers/add-canned-replies-ui-builder.js.es6#L5-L16

Então, o próximo passo é referenciar o controlador do composer para poder enviar essa ação quando o botão for clicado. Você pode fazer isso assim:

const composerController = api.container.lookup("controller:composer");

api.onToolbarCreate(toolbar => {
  toolbar.addButton({
    title: "canned_replies.composer_button_text",
    id: "custom-canned-replies",
    group: "extras",
    icon: "far-clipboard",
    sendAction: () => composerController.send("showCannedRepliesButton")
  });
});

Note que usamos o mesmo padrão do botão de calendário para sendAction. As únicas duas exceções são: em vez de toolbar.context.send, usamos composerController.send.

e não estamos passando o evento, pois não acho que seja necessário.

Isso deve fornecer um botão totalmente funcional na barra de ferramentas:

mas ainda não terminamos, pois este botão agora é visível para todos os membros. As permissões de uso ainda se aplicam e, se um usuário sem permissão tentar clicar nele, receberá apenas um erro. No entanto, um botão quebrado não é bom, então vamos corrigir isso.

As permissões para usar respostas prontas estão aqui:

https://github.com/discourse/discourse-canned-replies/blob/master/assets/javascripts/initializers/add-canned-replies-ui-builder.js.es6#L34-L38

Então, precisamos apenas replicar essas condições para o botão ser adicionado. Algo assim:

const currentUser = api.getCurrentUser();
const canUseCannedReplies = currentUser
  ? currentUser.can_use_canned_replies
  : false;

if (!canUseCannedReplies) return;

e isso garantiria que o botão seja exibido apenas se você tiver as permissões necessárias.

Então, vamos colocar tudo junto:

import { withPluginApi } from "discourse/lib/plugin-api";

export default {
  name: "move-canned-button",
  initialize() {
    withPluginApi("0.8.7", api => {
      const currentUser = api.getCurrentUser();
      const canUseCannedReplies = currentUser
        ? currentUser.can_use_canned_replies
        : false;

      if (!canUseCannedReplies) return;

      const composerController = api.container.lookup("controller:composer");

      api.onToolbarCreate(toolbar => {
        toolbar.addButton({
          title: "canned_replies.composer_button_text",
          id: "custom-canned-replies",
          group: "extras",
          icon: "far-clipboard",
          sendAction: () => composerController.send("showCannedRepliesButton")
        });
      });
    });
  }
};

Isso vai para este arquivo em um componente de tema:

javascripts/discourse/initializers/move-canned-button.js.es6

se você estiver usando o novo recurso Split up theme Javascript into multiple files — altamente recomendado.

Ou você pode apenas adicionar este script na aba de cabeçalho do seu tema se estiver fazendo isso no admin.

Sintaxe antiga
<script type="text/discourse-plugin"
        version="0.8">
const currentUser = api.getCurrentUser();
const canUseCannedReplies = currentUser
  ? currentUser.can_use_canned_replies
  : false;

if (!canUseCannedReplies) return;

const composerController = api.container.lookup("controller:composer");

api.onToolbarCreate(toolbar => {
  toolbar.addButton({
    title: "canned_replies.composer_button_text",
    id: "custom-canned-replies",
    group: "extras",
    icon: "far-clipboard",
    sendAction: () => composerController.send("showCannedRepliesButton")
  });
});
</script>

A última coisa que você precisa é ocultar o botão antigo e você pode fazer isso assim:

.toolbar-popup-menu-options {
  [data-name="Canned replies"] {
    display: none;
  }
}