J’ai décidé de créer le plugin. Le composant de formulaire lui-même est correctement rendu via api.renderInOutlet. Cependant, les données ne sont pas sauvegardées en backend dans la table personnalisée.
Configuration Frontend :
J’utilise api.renderInOutlet("composer-fields", MyOutletConnectorComponent) pour rendre un composant GJS (MyOutletConnectorComponent) lorsqu’un nouveau sujet est créé dans une catégorie désignée.
Ce MyOutletConnectorComponent rend ensuite mon composant de formulaire GJS principal (MyMarketFormComponenent).
À l’intérieur de MyMarketFormComponenent, les entrées utilisateur mettent à jour un objet JavaScript qui est ensuite défini comme une propriété de niveau supérieur sur le composerModel fourni par les arguments de l’outlet. Par exemple :
Dans mon initialiseur de plugin (tecenc-market-composer.js), j’utilise api.serializeOnCreate("market_listing_data", "market_listing_data"); pour essayer de passer ces données au backend. J’utilise également api.serializeToDraft("market_listing_data", "market_listing_data");.
Problème Backend :
Dans mon plugin.rb, au sein du gestionnaire DiscourseEvent.on(:topic_created) do |topic, opts, user| ... end :
Je vérifie si le sujet est dans la bonne catégorie (cela fonctionne).
J’essaie ensuite d’accéder aux données sérialisées en utilisant market_data = opts[:market_listing_data] (ou opts["market_listing_data"]).
Le problème est que opts[:market_listing_data] est systématiquement nil.
La journalisation de opts.keys confirme que ma clé market_listing_data n’est pas présente au niveau supérieur du hash opts. Le hash opts lui-même contient des clés standard comme :raw, :title, :category, :archetype, etc.
Extrait de mon plugin.rb pour l’événement :
# plugin.rb
# ...
module ::TecencMarket
SERIALIZED_DATA_KEY = "market_listing_data".freeze
end
# ...
after_initialize do
# ...
DiscourseEvent.on(:topic_created) do |topic, opts, user|
# ... (logique de vérification de catégorie) ...
# C'est ici que market_data est 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)
# ... traiter et sauvegarder les données dans la table personnalisée ...
else
Rails.logger.warn "[MyPlugin] Market data not found in opts as expected."
end
end
# ...
end
Question :
Quelle est la manière correcte et la plus fiable de s’assurer qu’un objet JavaScript défini comme propriété de niveau supérieur sur le composerModel (par exemple, composerModel.set("my_plugin_data_key", { ... });) à l’aide de composants GJS est correctement sérialisé par api.serializeOnCreate et rendu disponible dans le hash opts de l’événement :topic_created en backend ?
Est-ce que api.serializeOnCreate("my_key", "my_key") est censé fonctionner pour des clés arbitraires de niveau supérieur définies sur le composerModel à partir d’un contexte GJS, ou la sérialisation via custom_fields (par exemple, en définissant composerModel.custom_fields.my_plugin_key = {...} et en utilisant api.serializeOnCreate("custom_fields.my_plugin_key")) est-elle la seule approche robuste/recommandée pour ce type de transfert de données pour les nouveaux sujets ?
Y a-t-il des considérations spécifiques ou des pièges courants lors de l’utilisation de api.serializeOnCreate avec des données gérées par des composants GJS qui pourraient empêcher les données d’être incluses dans le hash opts ?
J’ai confirmé que le formulaire frontend collecte correctement les données et les définit sur la propriété composerModel.market_listing_data. Le problème semble être purement dans la manière d’obtenir ces données sérialisées et transmises à l’événement backend.
Toute aide ou exemple du modèle recommandé pour cela dans Discourse moderne serait grandement apprécié !
Suite à mon problème précédent concernant le fait que les données ne parvenaient pas à la clé opts, j’ai changé ma stratégie pour utiliser la voie recommandée custom_fields pour sérialiser les données à partir du formulaire du compositeur de mon plugin.
Approche actuelle :
Initialiseur frontend :
Je tente de m’assurer que composerModel.custom_fields et composerModel.custom_fields["tecenc_market_data"] (la clé de données de mon plugin) sont initialisés en tant qu’objets. Ma dernière tentative consiste à utiliser api.modifyClass("model:composer", ...) pour ajouter une logique d’initialisation à init() et clearState() :
J’utilise ensuite api.serializeOnCreate('custom_fields.tecenc_market_data'); et api.serializeToDraft('custom_fields.tecenc_market_data');.
Mon composant de formulaire GJS met à jour composerModel.custom_fields.tecenc_market_data.my_field = value; (en affectant un nouvel objet custom_fields pour la réactivité).
Backend plugin.rb :
Topic.register_custom_field_type("tecenc_market_data", :json) est appelé.
Le gestionnaire d’événements topic_created doit lire les données de topic.custom_fields["tecenc_market_data"].
Nouvelle erreur bloquante :
Malgré ces tentatives d’initialisation de custom_fields sur le composerModel, je rencontre maintenant de manière constante l’erreur JavaScript suivante lorsque j’ouvre le compositeur pour un nouveau sujet (en cliquant sur le bouton “Créer un sujet”) :
Uncaught (in promise) Error: Échec de la propriété lors de la définition : l’objet dans le chemin "custom_fields" n’a pas pu être trouvé.
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
```Cette erreur indique que `this.model.custom_fields` (sur le `composerModel`) est `undefined` ou `null` lorsque le code principal de Discourse à `composer.js:1010` (dans la méthode `open`, appelée par `openNewTopic`) tente de définir une propriété imbriquée dessus. Cela se produit *avant* même que le formulaire de mon plugin ne soit rendu.
**Questions :**
1. Étant donné que le modèle `Composer` principal devrait initialiser `custom_fields : {}`, pourquoi `composerModel.custom_fields` pourrait-il encore être indéfini à `composer.js:1010` lors de la séquence `openNewTopic` dans cette version de Discourse ?
2. L’approche `api.modifyClass("model:composer", ...)` dans un initialiseur est-elle la méthode correcte/la plus efficace pour s’assurer que `custom_fields` (et les clés imbriquées du plugin à l’intérieur) soient initialisées en tant qu’objets suffisamment tôt pour éviter cette erreur principale ? Sinon, quel est le pattern recommandé ?
3. Peut-il y avoir un problème de synchronisation où les étapes d'initialisation du composant principal sont en train de s’exécuter et attendent que `custom_fields` soit défini avant que les initialisateurs du plugin utilisant `api.modifyClass` aient complètement pris effet sur le prototype ou les instances du `Composer` ?
Toute insight sur cette erreur “Property set failed” dans le cœur de composer et sur les meilleures pratiques pour que les plugins puissent interagir en toute sécurité avec `composerModel.custom_fields` lors de l’initialisation serait extrêmement utile.
Merci pour votre temps !
J’enregistre les données dans une table de base de données personnalisée.
addToSerializer sert à déplacer des données du serveur vers le client, n’est-ce pas ?
Mon problème est de déplacer des données du client vers le serveur afin de pouvoir les enregistrer. J’utilise donc serializeOnCreate. Mais le problème est que les données ne parviennent pas au hash opts. Donc, actuellement, la réponse est non, les données personnalisées n’arrivent pas dans le hash opts comme prévu. Elles n’arrivent pas dans Rails.
J’ai examiné ce plugin éducatif mais je n’arrive pas à le faire fonctionner pour 6 champs personnalisés.