Utiliser tag-chooser dans un plugin

Je travaille sur un plugin qui attribuera une balise par défaut aux nouveaux sujets créés dans une catégorie.

Le code ci-dessous « fonctionne » si je saisis des noms de balises séparés par « | », donc « tag1|tag2 » fonctionne. (J’ai du mal à y croire ! Mais je m’écarte du sujet.)

<h3>{{i18n 'topic_default_tag.title'}}</h3>
<section class='field default-tag'>
  <div class="default-tag">
  <label>
    {{input type="list" value=category.custom_fields.default_tag }}
    {{popup-input-tip validation=tagValidation}}
    {{i18n 'topic_default_tag.default_tag'}}
  </label>
  </div>
</section>

Ce que je souhaite maintenant, c’est avoir un vrai sélecteur de balises plutôt qu’une chaîne non validée. Il semble que le code ci-dessous devrait fonctionner :

<h3>{{i18n 'topic_default_tag.title'}}</h3>
<section class='field default-tag'>
  <div class="default-tag">
  <label>
    {{tag-chooser tags=category.custom_fields.default_tag tabindex="4" categoryId=category.id}}
    {{popup-input-tip validation=tagValidation}}
    {{i18n 'topic_default_tag.default_tag'}}
  </label>
  </div>
</section>

Mais ce n’est pas le cas. La base de mon problème est que je n’ai presque aucune idée de la façon dont fonctionne la magie de ces Handlebars. Par exemple, je suppose que la première section fonctionne parce qu’elle récupère magiquement le nom du champ depuis default-tag dans <section class='field default-tag'>, mais c’était de la chance. :slight_smile:

Lorsque j’utilise tag-chooser, les balises sont transmises à Rails sous forme de tableau, qu’il rejette avant que je puisse les convertir en une chaîne délimitée par | à insérer dans CategoryCustomField. Avec {{input type=list...}}, je peux saisir moi-même la chaîne délimitée par | et tout fonctionne parfaitement. Dois-je utiliser une sorte de magie Ember pour convertir le tableau en chaîne côté Ember ?

Peut-être que je dois faire quelque chose comme What's the best approach to access category specific settings? ?

EDIT : Pour ajouter des balises avant que le webhook ne soit appelé, utilisez after_create plutôt que DiscourseEvent.on(:post_created). Rails a maintenant du sens pour moi, mais Ember, JavaScript et CSS, pas vraiment.

Vous pouvez vérifier si les variables que vous utilisez contiennent les valeurs nécessaires en utilisant {{log variable_name}} et en consultant la console. Si les valeurs correctes ne sont pas transmises au composant, l’affichage ne sera pas correct.

Vous pouvez les vérifier en procédant de même dans le code principal pour confirmer que les valeurs sont bien transmises.

Veuillez m’excuser si cela vous semble naïf.

Non ! Je suis juste un homme des cavernes.

C’est très utile, car je ne savais pas comment faire cela. Il s’avère que je ai bien des données dans ces champs. ET, les données du nom de la balise sont bien dans category.custom_fields.default_tag et sont transmises au mini-tag-chooser. category.id contient bien l’ID d’une catégorie, mais le sélecteur ne propose aucune balise.

Je ne peux pas dire si, avec ces données, elles seraient bien injectées dans le champ.

EDIT : OOOOH ! Mais l’utilisation de tag-chooser au lieu de mini-tag-chooser fonctionne comme il se doit (je modifierai le code ci-dessus en conséquence). Le seul problème est que les données ne sont pas enregistrées lorsque je clique sur Enregistrer.

Cette ligne me paraît suspecte. Je pense que le paramètre tags attend un tableau, et il semble que vous passiez une valeur unique (vous devrez le confirmer). Si c’est bien le cas, transformez-la en tableau et réessayez.

Bon, côté Rails, c’est une chaîne délimitée par | et je vois, après avoir soumis, que les données que j’ai saisies sont bien envoyées, par exemple : "custom_fields"=>{"de fault_tag"=>["error", "high-availability", "best-practices"]}, et "custom_fields"=>{"de fault_tag"=>["health-checks"]},

Voici l’intégralité :

Started PUT "/categories/2" for 127.0.0.1 at 2019-08-01 13:56:13 -0700
Processing by CategoriesController#update as */*
  Parameters: {"name"=>"Lounge", "slug"=>"lounge", "color"=>"EEEEEE", "text_color"=>"652D90", "permissions"=>{"trus
t_level_3"=>"1"}, "auto_close_hours"=>"", "auto_close_based_on_last_post"=>"false", "position"=>"3", "email_in"=>""
, "email_in_allow_strangers"=>"false", "mailinglist_mirror"=>"false", "allow_badges"=>"true", "custom_fields"=>{"de
fault_tag"=>["error", "high-availability", "best-practices"]}, "topic_template"=>"", "suppress_from_latest"=>"false
", "all_topics_wiki"=>"false", "allow_global_tags"=>"false", "sort_order"=>"", "sort_ascending"=>"", "topic_feature
d_link_allowed"=>"true", "show_subcategory_list"=>"false", "num_featured_topics"=>"3", "default_view"=>"", "subcate
gory_list_style"=>"rows_with_featured_topics", "default_top_period"=>"all", "minimum_required_tags"=>"0", "navigate
_to_first_post_after_read"=>"false", "search_priority"=>"0", "id"=>"2"}

Donc, il semble que la bonne opération se déroule du côté mystérieux, mais que Rails ne met pas à jour le champ personnalisé de la catégorie. Je vais revenir à comparer ce que j’ai avec un autre plugin qui gère les CategoryCustomField.

Merci beaucoup, @fzngagan !

EDIT : Hmm. Je pense que le problème est :

Paramètre non autorisé : :default_tag

Vous apprécierez vraiment de trouver la réponse à cela. Néanmoins, si vous avez besoin d’aide, je serais plus qu’heureux de vous aider. :slight_smile:

Oui, c’est le cas. Rails ne sait pas encore quoi faire avec ce nouveau champ. Vous devez ajouter ce champ au sérialiseur à l’aide de la méthode add_to_serializer. Vous pouvez trouver des exemples de cela dans les plugins qui ajoutent des champs personnalisés.

Eh bien, plugin.rb inclut :

  Category.register_custom_field_type('default_tag', :list)
  Site.preloaded_category_custom_fields << 'default_tag' if Site.respond_to? :preloaded_category_custom_fields
  add_to_serializer(:basic_category, :default_tag) { object.custom_fields["default_tag"] }

Cela se trouve sur GitHub - pfaffman/discourse-topic-default-tag: Allow topics to include default tags · GitHub si vous souhaitez consulter.

Je suis confus car :

   {{input type="list" value=category.custom_fields.default_tag }}

fonctionne, mais

{{tag-chooser tags=category.custom_fields.default_tag tabindex="4" categoryId=category.id}}

ne fonctionne pas.

EDIT : Il semble qu’en utilisant tag-chooser, mon champ personnalisé soit envoyé à Rails sous forme de tableau, puis soit écarté avant d’être traité. En revanche, en utilisant un champ texte où je crée une chaîne délimitée par |, cela fonctionne parfaitement. (J’ai pensé que je pourrais peut-être corriger cela avec un before_validation côté Rails, mais sans succès.)

Donc, je suppose que j’ai besoin d’une magie côté Ember pour convertir le tableau en chaîne avant qu’il ne soit renvoyé ?

J’ai moi aussi utilisé tag-chooser sans paramètres et cela a récupéré tous les tags disponibles.

De plus, je pense avoir trouvé la raison pour laquelle ceux-ci ne sont pas enregistrés (voire même ne parviennent pas) côté Rails lors de l’utilisation de tag-chooser. Lorsque vous utilisez input type list et ajoutez un champ value, cela devient automatiquement une partie du formulaire.

Mais le balisage généré par le sélecteur de tags est un div. C’est pourquoi il n’est pas ajouté à la soumission du formulaire.

J’essaie de mettre au point une solution de contournement pour cela. Je soumettrai une PR une fois que cela fonctionnera.

J’ai parlé à @j.jaffeux hier et il travaille sur un changement.

C’est exactement sur cela que je travaille.

C’est super. En tant que nouveau venu, j’essaie d’en apprendre de plus en plus et cela m’aide beaucoup :slight_smile:

Bonjour @pfaffman.

J’ai réussi à mettre au point une correction. Je n’ai pas pu le faire côté Ember car tag-chooser semblait trop intéressant à abandonner, mais j’ai réussi à le faire côté Rails.

J’ai écrit une fonction simple dans le CategoriesController et je l’ai appelée :before_action. Dans celle-ci, j’ai converti le tableau default_tag en une chaîne délimitée par |.

Deuxièmement, j’ai remplacé before_update par before_commit, car les custom_fields semblent être définis à ce stade de l’exécution.

Hmm. Je croyais l’avoir déjà essayé, mais je regarderai quand j’arriverai au bureau. Merci !

Aha ! C’est exactement ce que je ne sais pas faire. Tu le places dans plugin.rb ?

Oui. Cela a fonctionné pour moi.

class ::ApplicationController
    def convert_default_tag
      return unless :topic_default_tag_enabled
      puts 'request'
     # Vérifiez simplement si le champ existe pour éviter les erreurs
      request.params["custom_fields"]["default_tag"] = request.params["custom_fields"]["default_tag"].join('|')
      p request.params["custom_fields"]["default_tag"]
    end
  end
  require 'categories_controller'
  class ::CategoriesController
     before_action :convert_default_tag , only: [:create]
  end

Je pense qu’il est possible d’avoir la méthode default_tag directement dans le contrôleur, mais je n’ai pas réussi à faire fonctionner cette approche. Comme ApplicationController est la classe dont hérite chaque contrôleur Discourse, la méthode est chargée dès l’extension de la classe à partir de ApplicationController, ce qui fait l’affaire.

@merefield
Est-il possible de définir une méthode appelée :before_action directement dans le contrôleur ?

Vous devez mettre trois accents graves avant et après le bloc de code.

```
 Le code va ici
  ```

J’ai hâte de l’essayer demain ! Merci beaucoup.

Merci. Je pensais qu’il s’agissait d’un seul accent grave, mais j’étais bloqué. J’ai donc utilisé les balises HTML classiques

 pour que cela fonctionne.

Oui, je le pense

C’est une grande aide. Maintenant, j’ai ceci :

  class ::CategoriesController
    before_action :default_tag_to_string, only: [:create, :update]

    def default_tag_to_string
      puts "CDT: #{params}"

      return unless :topic_default_tag_enabled
      # Vérifie simplement si le champ existe pour éviter des erreurs
      request.params["custom_fields"]["default_tag"] = request.params["custom_fields"]["default_tag"].join('|')
      p request.params["custom_fields"]["default_tag"]
    end

  end

Maintenant, les balises sélectionnées sont converties en chaîne de caractères avant que Rails ne tente de mettre à jour l’enregistrement, et cela fonctionne comme prévu.

MAINTENANT, le problème est que je dois déterminer où convertir la chaîne du côté Rails en tableau dont nous avons besoin du côté Javascript/Ember. @j.jaffeux, je ne me souviens pas (ou, plus probablement, je n’ai pas compris) si le problème que vous tentiez de résoudre consistait à réécrire cette valeur du côté Javascript vers Rails (résolu !) ou du côté Rails vers Javascript (toujours confus).

Ce qui a fonctionné pour moi, c’est que j’ai remplacé :before_update par :before_commit dans votre code lors de l’attribution des tags au sujet.

Deuxièmement, lorsque vous ouvrez la page de modification de la catégorie, le champ de configuration par défaut des tags nécessite un tableau dans son paramètre tags pour afficher les tags sélectionnés.