Obtenha acesso ao componente glimmer para coisas do pai

Estou adicionando um componente a before-topic-list-body. Preciso que ele obtenha alguns dados da categoria ou do tópico (e adicionarei os dados que desejo a qualquer serializador que faça mais sentido).

Passei algumas horas nisso e decidi que estou perdido e há uma boa chance de que este seja um problema de 2 a 5 minutos para me dar uma dica que preciso.

Lembro-me vagamente de ter pensado ou ouvido algo sobre isso antes, mas estou preso.

2 curtidas

:thinking: hmmm

talvez este tópico tenha algo que possa ajudar?

Obrigado, @Lilly! Não é uma má ideia, mas eu estava com medo de que currentUser fosse algo que se aplicasse a toda a página, e não apenas onde o componente está sendo inserido, e acho que estou certo. Para ver o que estava disponível dessa forma, eu procurei nos plugins oficiais e obtive esta lista de serviços (se eu fosse esperto, saberia como encontrá-los no código-fonte do Discourse, mas não sou):

  @service adminPluginNavManager;
  @service appEvents;
  @service capabilities;
  @service chatApi;
  @service composer;
      @service currentUser;
  @service currentUser;
  @service dialog;
  @service dTemplatesModal;
  @service encryptWidgetStore;
  @service hCaptchaService;
  @service imageCaptionPopup;
  @service menu;
  @service messageBus;
  @service modal;
  @service moreTopicsPreferenceTracking;
  @service presence;
  @service quickSearch;
  @service router;
  @service search;
  @service searchPreferencesManager;
  @service session;
  @service site;
  @service siteSettings;
  @service store;
  @service taskActions;
  @service toasts;
  @service upgradeStore;
  @service userFieldValidations;
  @service whosOnline;
2 curtidas

Eu encontrei. Aqui está de onde obtê-lo do meu contexto:

<RatingOne @scaleValue={{this.scaleValue}} @topic={{this.parentView._parentView.topic}} />

Então, sou capaz de usar parentView e _parentView para voltar ao tópico! Essa é a mágica que estou procurando (o que acho que também resolverá outro problema em outro projeto). Agora, tudo o que preciso fazer é colocar as coisas no controlador de tópico, o que espero que sejam coisas que eu (pelo menos na maior parte) sei como fazer!

1 curtida

Isso imprimiu uma mensagem de depreciação no console? Deveria ter feito, porque removeremos o acesso a parentView de PluginOutlet iminentemente. Na verdade, é tão não recomendado que deve causar um banner de aviso para ser mostrado aos administradores na interface do usuário :sweat_smile:

Se você não viu nenhum aviso, por favor nos avise!

(parentView faz parte do sistema de componentes clássico do Ember, do qual estamos nos afastando)

Se você quiser acessar informações de níveis mais altos na árvore, isso precisa ser passado como um argumento para o Plugin Outlet, ou você precisa usar um dos serviços disponíveis (como currentUser ou router)

2 curtidas

Ah, entendi o que aconteceu. Você está usando ._parentView, não .parentView. A versão com sublinhado permite que você ignore a mensagem de depreciação. Mas, ainda assim, ela deixará de funcionar nas próximas semanas.

Este PR impede esse tipo de solução alternativa, então .parentView e ._parentView levantarão a depreciação:

2 curtidas

Obrigado, @david!

Não. Nem mesmo depois de eu procurar por um tempo. Estou em 27eea3250cbde2e8bca754f445bee403c059eba3

<RatingOne @scaleValue={{this.scaleValue}} @topic={{this.parentView._parentView.topic}} />
<td class="rating-one">
  <span class="rating-title">{{this.ratingName}}</span> 
  Este é o tópico {{this.topic.id}}
  Esta é a categoria {{this.topic.category.title}} (id da categoria: {{this.topic.category_id}})
  {{log "classificando isto" this}}
  {{log "valor da escala" this.scaleValue}}
  {{log "valor da classificação" this.ratingValue}}
  {{log "categoria" this.topic.category_id}}
    <form>
        {{!-- {{this.ratingLow}} --}}
       {{#each this.ratingOptions as |option|}}
            <input type="radio" name="rating" value={{option.value}} checked={{if (eq option.value this.ratingValue) "checked"}}> <span class="rotated-label">{{option.label}}</span>
        {{/each}}
        {{!-- {{this.ratingHigh}} --}}
    </form>
</td>

Ah. Ok. Então posso usar router para chegar ao tópico ou categoria? O que eu (acho que) preciso fazer é obter essas ratingOptions no serializador do tópico ou categoria para que eu possa adicionar essas classificações de múltiplos tópicos à lista de tópicos para que essas coisas possam ser classificadas sem entrar nos tópicos (supostamente as pessoas já estarão familiarizadas com elas, então não precisarão entrar no tópico para saber no que estão votando).

Hmm. Não parece que sim.

2 curtidas

Ok, isso deve ser corrigido por este commit. Você pode confirmar que vê o aviso agora?

Idealmente, essas coisas estariam disponíveis como argumentos no plugin outlet.

Você mencionou ‘before-topic-list-body’ acima. Isso tem todos esses argumentos:

2 curtidas
{{log "rating this parent" this.parentView._parentView.topic}}

gera um erro feio.


<RatingOne @scaleValue={{this.scaleValue}} @passedRouter={{this.router}} @topic={{this.parentView}} />

parece não gerar um erro.

Eu realmente preciso de above-topic-list-item, mas graças ao seu ótimo exemplo, consegui descobrir que ele deve ter o tópico em outletArgs,

https://github.com/discourse/discourse/blob/main/app/assets/javascripts/discourse/app/components/topic-list/topic-list-item.gjs#L284

Ha! Vou conseguir!

Então outletArgs significa que agora está no this da coisa? (É o que parece - pensei que precisaria procurar em args de alguma forma…)

Então, no meu conector hbs, posso acessar this.topic e então posso chamar meu componente assim:

<RatingOne @name="one" @topic={{this.topic}}/>

E então no hbs para o componente RatingOne (um dia será renomeado apenas rating, já que descobri como passar coisas para ele) eu posso

  Este é o tópico {{this.topic.id}} {{this.topic.title}}
  Este é o id da categoria: {{this.topic.category_id}})

e obter as coisas do tópico!

E agora eu vejo o tópico, agora posso ir adicionar meus args ao serializador do tópico, certo? (Pode ser melhor passá-lo apenas para a categoria. . . ou talvez eu apenas passe um valor “doTheThing” no serializador e obtenha as coisas reais de SiteSettings, já que acho que eles querem isso no nível do site e não no nível da categoria).

A menos que eu tenha tropeçado em algo mais obsoleto, parece que você conseguiu. Muito obrigado. :beer: :beers: :clinking_glasses: :moneybag:

3 curtidas

Isto está relacionado a "como faço as coisas funcionarem no glimmer, então estou mantendo isto aqui.

Preciso chamar este código depois que cada tópico for renderizado para reordenar os itens <td>. Usei above-topic-item, que coloca as classificações antes do título do tópico. Este hack selvagem reordena os itens <td> com a ajuda de algum javascript.

// document.addEventListener("DOMContentLoaded", function() {
//   const table = document.querySelector('table.topic-list.ember-view');
//   const rows = table.getElementsByTagName('tr');

//   // todo: isso precisa ser chamado ao carregar a página 
//   for (let row of rows) {
//     const cells = Array.from(row.getElementsByTagName('td'));
//     cells.sort((a, b) => {
//       const orderA = parseInt(window.getComputedStyle(a).order, 10);
//       const orderB = parseInt(window.getComputedStyle(b).order, 10);
//       return orderA - orderB;    });

//     for (let cell of cells) {
//       row.appendChild(cell);
//     }
//   }
// });

Acho que eu “apenas” preciso chamar algum afterRender ou outra coisa em vez da coisa em nível de documento que eu tenho. Talvez o roteador?"

2 curtidas

Você sabe que tenho que me perguntar, Jay, se sua última pergunta foi a inspiração para isto: Upcoming topic-list changes - how to prepare themes and plugins :thinking: ;)\n\nE eu acredito que a resposta para sua última pergunta é, em última análise, "confira a nova API! :rocket:"

3 curtidas

Engraçado. E a pessoa que queria o trabalho que exigia isso acabou de reaparecer. Talvez agora seja mais fácil!

2 curtidas