Utilizzo di tag-chooser in un plugin

Sto lavorando a un plugin che assegnerà un tag predefinito ai nuovi argomenti creati in una categoria.

Il codice sottostante “funziona” se inserisco i nomi dei tag separati da “|”, quindi “tag1|tag2” funziona. (Faticavo a crederci! Ma lasciamo perdere.)

<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>

Ora vorrei avere un selettore di tag appropriato invece di una stringa non validata. Sembra che il codice sottostante dovrebbe funzionare:

<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>

Ma non funziona. Il problema di fondo è che ho quasi zero idea di come funzioni la magia di quelle handlebars. Immagino che la prima sezione funzioni perché sta estraendo magicamente il nome del campo da default-tag nel <section class='field default-tag'>, ma è stata fortuna. :slight_smile:

Quando uso tag-chooser, i tag vengono passati a Rails come un array, che lui scarta prima che io possa convertirli in una stringa delimitata da | da inserire in CategoryCustomField. Con {{input type=list...}} posso inserire manualmente la stringa delimitata da | e funziona perfettamente. Ho bisogno di qualche tipo di magia Ember per convertire l’array in una stringa lato Ember?

Forse devo fare qualcosa come What's the best approach to access category specific settings??

EDIT: Per aggiungere i tag prima che venga chiamato il webhook, usa after_create invece di DiscourseEvent.on(:post_created). Rails ora ha quasi senso per me, ma Ember, Javascript e CSS, meno.

Puoi verificare se le variabili che stai utilizzando contengono i valori necessari utilizzando {{log variable_name}} e controllando la console. Se i valori corretti non vengono passati al componente, questo non mostrerà l’output corretto.

Puoi verificarli facendo la stessa cosa nel codice principale per confermare se i valori vengono passati correttamente.

Scusa se può sembrare ingenuo.

No! Sono solo un cavernicolo.

È molto utile, perché non sapevo come farlo. A quanto pare, ho davvero dati in quei campi. E i dati del nome del tag sono in category.custom_fields.default_tag e vengono passati a mini-tag-chooser. category.id contiene l’ID di una categoria, ma il selettore non propone alcun tag.

Non riesco a capire se, con quei dati, verrebbero inseriti nel campo.

EDIT: OOOOH! Ma usando tag-chooser invece di mini-tag-chooser funziona come dovrebbe (modificherò di conseguenza il codice sopra). L’unico problema è che i dati non vengono salvati quando faccio clic su Salva.

Questa riga mi insospettisce. Credo che ‘tags’ possa accettare un array e, a quanto mi sembra, stai passando un singolo valore (devi confermarlo). Se viene passato come singolo valore, rendilo un array e riprova.

Beh, lato Rails, si tratta di una stringa delimitata da | e vedo che, dopo l’invio, i dati inseriti vengono effettivamente inviati, ad esempio: "custom_fields"=>{"de fault_tag"=>["error", "high-availability", "best-practices"]}, e "custom_fields"=>{"de fault_tag"=>["health-checks"]},

Ecco tutto il log:

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"}

Quindi sembra che sul lato misterioso stia accadendo la cosa giusta, ma che Rails non stia aggiornando il campo personalizzato della categoria. Tornerò a confrontare quello che ho con un altro plugin che gestisce CategoryCustomField.

Grazie mille, @fzngagan!

EDIT: Mmm. Penso che il problema sia:

Unpermitted parameter: :default_tag

Ti piacerà davvero trovare la risposta a quella domanda. Tuttavia, se hai bisogno di aiuto, sarò più che felice di darti una mano. :slight_smile:

Sì, è così. Rails non sa ancora cosa fare con questo nuovo campo. Devi add_to_serializer il nuovo campo. Puoi vedere degli esempi di questo nei plugin che aggiungono campi personalizzati.

Bene, plugin.rb include:

  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"] }

È disponibile su GitHub - pfaffman/discourse-topic-default-tag: Allow topics to include default tags · GitHub se vuoi dare un’occhiata.

Sono confuso perché questo codice:

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

funzionava, mentre:

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

non funziona.

EDIT: Sembra che usando tag-chooser il mio campo personalizzato venga inviato a Rails come un array e poi venga scartato prima dell’elaborazione, mentre usando un text field in cui creo una stringa delimitata da |, funziona perfettamente. (Pensavo di poterlo risolvere con un before_validation lato Rails, ma senza successo.)

Quindi immagino di aver bisogno di qualche magia lato Ember per convertire l’array in una stringa prima di inviarlo indietro?

Anch’io ho usato tag-chooser senza parametri e ha recuperato tutti i tag disponibili.

Inoltre, credo di aver trovato il motivo per cui non vengono salvati (o addirittura non arrivano) :wink: sul lato Rails quando si usa tag-chooser. Quando si usa input type list e si aggiunge un campo value, questo diventa automaticamente parte del modulo.

Ma il markup generato da tag chooser è un div. Ecco perché non viene aggiunto all’invio del modulo.

Sto cercando di mettere insieme una soluzione alternativa. Invierò una PR non appena riuscirò a farla funzionare.

Ho parlato con @j.jaffeux ieri e sta lavorando per apportare una modifica.

È esattamente su questo che sto lavorando.

Ottimo. Da principiante, sto cercando di imparare sempre di più e questo aiuta molto :slight_smile:

Ciao @pfaffman.

Sono riuscito a preparare una soluzione. Non sono riuscito a farlo dal lato di Ember perché tag-chooser mi sembrava troppo utile da eliminare, ma sono riuscito a farlo dal lato Rails.

Ho scritto una semplice funzione nel CategoriesController e l’ho chiamata :before_action; al suo interno ho convertito l’array default_tag in una stringa delimitata da |.

In secondo luogo, ho modificato before_update in before_commit, poiché i custom_fields sembrano essere impostati in quel punto dell’esecuzione.

Hmm. Pensavo di averlo già provato, ma darò un’occhiata quando arriverò in ufficio. Grazie!

Aha! È proprio quello che non so fare. Lo inserisci in plugin.rb?

Sì. Questo ha risolto il problema per me.

class ::ApplicationController
    def convert_default_tag
      return unless :topic_default_tag_enabled
      puts 'request'
     #Controlla solo se il campo esiste per evitare errori
      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

Penso che sia possibile definire il metodo default_tag direttamente nel controller, ma non sono riuscito a farlo funzionare in quel modo. Poiché ApplicationController è la classe da cui eredita ogni controller di Discourse, il metodo viene caricato al momento dell’estensione della classe da ApplicationController, il che risolve il problema.

@merefield
È possibile definire un metodo da chiamare :before_action direttamente nel controller?

Dovresti inserire tre backtick prima e dopo il blocco di codice.

```
 Il codice va qui
  ```

Non vedo l’ora di provarlo domani! Grazie mille.

Grazie. Pensavo fosse il backtick singolo, ma ero bloccato. Quindi ho usato i vecchi tag HTML standard

 per far funzionare.

Sì, credo di sì

È un grande aiuto. Ora ho questo:

  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
      #Basta controllare se il campo esiste per evitare errori
      request.params["custom_fields"]["default_tag"] = request.params["custom_fields"]["default_tag"].join('|')
      p request.params["custom_fields"]["default_tag"]
    end

  end

Ora i tag selezionati vengono convertiti in una stringa prima che Rails tenti di aggiornare il record e funziona come previsto.

ORA il problema è che devo capire dove convertire la stringa sul sito Rails nell’array di cui abbiamo bisogno sul lato Javascript/Ember. @j.jaffeux, non ricordo (o, più probabilmente, non ho capito) se il problema che stavi cercando di risolvere riguardasse la riscrittura di questo valore dal lato Javascript-a-Rails (risolto!) o dal lato Rails-a-Javascript (ancora confuso).

Quello che ha funzionato per me è stato cambiare :before_update in :before_commit nel tuo codice durante l’assegnazione dei tag all’argomento.

In secondo luogo, quando apri la pagina di modifica della categoria, il campo predefinito per l’impostazione dei tag richiede un array nel parametro tags per visualizzare i tag selezionati.