Decidi criar o plugin. O próprio componente de formulário está sendo renderizado corretamente via api.renderInOutlet. No entanto, os dados não estão sendo salvos no backend em uma tabela personalizada.
Configuração do Frontend:
Estou usando api.renderInOutlet("composer-fields", MyOutletConnectorComponent) para renderizar um componente GJS (MyOutletConnectorComponent) quando um novo tópico está sendo criado em uma categoria designada.
Este MyOutletConnectorComponent então renderiza meu componente de formulário GJS principal (MyMarketFormComponenent).
Dentro de MyMarketFormComponenent, a entrada do usuário atualiza um objeto JavaScript que é então definido como uma propriedade de nível superior no composerModel fornecido pelos argumentos do outlet. Por exemplo:
No meu inicializador de plugin (tecenc-market-composer.js), estou usando api.serializeOnCreate("market_listing_data", "market_listing_data"); para tentar passar esses dados para o backend. Eu também uso api.serializeToDraft("market_listing_data", "market_listing_data");.
Problema no Backend:
No meu plugin.rb, dentro do manipulador DiscourseEvent.on(:topic_created) do |topic, opts, user| ... end:
Verifico se o tópico está na categoria correta (isso funciona).
Em seguida, tento acessar os dados serializados usando market_data = opts[:market_listing_data] (ou opts["market_listing_data"]).
O problema é que opts[:market_listing_data] é consistentemente nil.
Registrar opts.keys confirma que minha chave market_listing_data não está presente no nível superior do hash opts. O próprio hash opts contém chaves padrão como :raw, :title, :category, :archetype, etc.
Meu trecho de plugin.rb para o evento:
# plugin.rb
# ...
module ::TecencMarket
SERIALIZED_DATA_KEY = "market_listing_data".freeze
end
# ...
after_initialize do
# ...
DiscourseEvent.on(:topic_created) do |topic, opts, user|
# ... (lógica de verificação de categoria) ...
# É aqui que market_data é nil
market_data = opts[TecencMarket::SERIALIZED_DATA_KEY.to_sym]
Rails.logger.info "[MyPlugin] Opts keys: #{opts.keys.inspect}"
Rails.logger.info "[MyPlugin] market_data from opts: #{market_data.inspect}"
if market_data.present? && market_data.is_a?(Hash)
# ... processar e salvar dados na tabela personalizada ...
else
Rails.logger.warn "[MyPlugin] Market data not found in opts as expected."
end
end
# ...
end
Pergunta:
Qual é a maneira correta e mais confiável de garantir que um objeto JavaScript definido como uma propriedade de nível superior no composerModel (por exemplo, composerModel.set("my_plugin_data_key", { ... });) usando componentes GJS seja devidamente serializado por api.serializeOnCreate e disponibilizado no hash opts do evento :topic_created no backend?
api.serializeOnCreate("my_key", "my_key") é esperado funcionar para chaves arbitrárias de nível superior definidas no composerModel a partir de um contexto GJS, ou a serialização via custom_fields (por exemplo, definir composerModel.custom_fields.my_plugin_key = {...} e usar api.serializeOnCreate("custom_fields.my_plugin_key")) é a única abordagem robusta/recomendada para esse tipo de transferência de dados para novos tópicos?
Existem considerações específicas ou armadilhas comuns ao usar api.serializeOnCreate com dados gerenciados por componentes GJS que podem fazer com que os dados não sejam incluídos no hash opts?
Confirmei que o formulário frontend está coletando dados corretamente e definindo-os na propriedade composerModel.market_listing_data. O problema parece ser puramente em obter esses dados serializados e passados para o evento de backend.
Qualquer orientação ou exemplos do padrão recomendado para isso no Discourse moderno seriam muito apreciados!
Seguindo meu problema anterior sobre os dados não chegarem ao hash opts, mudei minha estratégia para usar o caminho recomendado custom_fields para serializar os dados do formulário do meu plugin no compositor.
Abordagem Atual:
Inicializador do Frontend:
Estou tentando garantir que composerModel.custom_fields e composerModel.custom_fields["tecenc_market_data"] (a chave de dados do meu plugin) sejam inicializados como objetos. Minha última tentativa envolve usar api.modifyClass("model:composer", ...) para adicionar a lógica de inicialização aos métodos init() e clearState():
Depois uso api.serializeOnCreate('custom_fields.tecenc_market_data'); e api.serializeToDraft('custom_fields.tecenc_market_data');.
Meu componente de formulário GJS atualiza composerModel.custom_fields.tecenc_market_data.my_field = value; (definindo um novo objeto custom_fields para reatividade).
Backend plugin.rb:
Topic.register_custom_field_type("tecenc_market_data", :json) é chamado.
O manipulador de evento topic_created espera ler dados de topic.custom_fields["tecenc_market_data"].
Novo Erro Bloqueante:
Apesar dessas tentativas de inicializar custom_fields no composerModel, estou agora enfrentando consistentemente o seguinte erro em JavaScript ao tentar abrir o compositor para um novo tópico (clicando no botão “Criar Tópico”):
Error não capturado (em promessa): Falha ao definir propriedade: objeto na rota "custom_fields" não pôde ser encontrado.
Ember 3
open composer.js:1010
open composer.js:1009
_setModel composer.js:1451
open composer.js:1401
openNewTopic composer.js:1410
createTopic list.js:167
clickCreateTopicButton d-navigation.gjs:224
_triggerAction d-button.gjs:138
Ember 11
_triggerAction d-button.gjs:135
click d-button.gjs:93
source chunk.8d6366d70b85d1b69fdc.d41d8cd9.js:94366
Ember 2
source chunk.8d6366d70b85d1b69fdc.d41d8cd9.js:94040
Ember 26 property_set-BapAkp3X.js:79:10
```Este erro indica que `this.model.custom_fields` (no `composerModel`) está `undefined` ou `null` quando o código principal do Discourse em `composer.js:1010` (dentro do método `open`, chamado por `openNewTopic`) tenta definir uma propriedade aninhada nele. Isso acontece *antes* de o formulário do meu plugin ser sequer renderizado.
**Perguntas:**
1. Considerando que o modelo `Composer` principal deve inicializar `custom_fields: {}`, por que `composerModel.custom_fields` ainda pode estar indefinido em `composer.js:1010` durante a sequência `openNewTopic` nesta versão do Discourse?
2. A abordagem `api.modifyClass("model:composer", ...)` em um inicializador é a maneira correta/mais eficaz de garantir que `custom_fields` (e chaves aninhadas do plugin dentro dela) sejam inicializados como objetos cedo o suficiente para evitar esse erro principal? Se não, qual é o padrão recomendado?
3. Poderia haver um problema de sincronização, onde passos de inicialização do composer principal estão sendo executados e esperando por `custom_fields` antes que os inicializadores do plugin usando `api.modifyClass` tenham tido efeito completo no protótipo ou instâncias do modelo `Composer`?
Qualquer insight sobre esse erro de “Falha ao definir propriedade” no núcleo do composer e as melhores práticas para plugins interagirem com segurança com `composerModel.custom_fields` durante a inicialização seriam extremamente úteis.
Obrigado pelo seu tempo!
Estou salvando os dados em uma tabela de banco de dados personalizada.
addToSerializer serve para mover dados do servidor para o cliente, não é?
Meu problema é mover dados do cliente para o servidor para que eu possa salvá-los. Então, estou usando serializeOnCreate. Mas o problema é que os dados não estão fluindo para o hash opts. Portanto, atualmente, a resposta é não, os dados personalizados não estão chegando ao hash opts como esperado. Eles não estão chegando ao Rails.
Eu dei uma olhada neste plugin educacional, mas não consegui fazê-lo funcionar para 6 campos personalizados.