Come aggiungere un campo personalizzato di argomento super base

Sto cercando di capire come aggiungere un campo personalizzato ai topic, lavorando su un esempio molto basilare. Obiettivo: aggiungere un campo personalizzato chiamato “sample_field” a ogni topic creato, con un valore stringa semplice.

Ho esaminato diversi esempi, come il plugin poll e il plugin solved e questa discussione, ma questi plugin fanno molto di più con i loro campi personalizzati, quindi non ho ancora capito il codice di base necessario.

Quindi non ci sono ancora arrivato: il mio file plugin.rb manca di qualcosa (credo), e non ho ancora capito come associare il valore stringa al campo personalizzato al momento della creazione del topic.

Cosa mi serve per far funzionare tutto questo?

Qualsiasi aiuto è apprezzato. Grazie!

Ecco cosa ho finora

plugin.rb:
//crea il campo personalizzato:

  after_initialize do
     Topic.register_custom_field_type('sample_field', :string)
     add_to_serializer(:topic_view, :custom_fields) { object.custom_fields } //se voglio mostrare il campo personalizzato sul lato client
  end

assets/javascripts/initializers/topic-custom-field.js.es6:
//inizializza l’oggetto dei campi personalizzati e rendilo possibile inviarlo al server:

import { withPluginApi } from 'discourse/lib/plugin-api';

export default {
  name: 'topic-custom-field',
  initialize() {
    withPluginApi('0.8.31', api => {
      api.modifyClass('model:topic', {
        custom_fields: {},
        asJSON() {
          return Object.assign(this._super(), {
            custom_fields: this.custom_fields
          });
        }
      })
    })
  }
}

Quindi, come aggiungo il valore del campo personalizzato al topic al momento del salvataggio?

Credo che l’azione chiave “save” per un topic avvenga qui nel codice:

app/templates/composer.hbs:

  <div class="save-or-cancel">
            {{#unless model.viewFullscreen}}
              {{composer-save-button action=(action "save")
                                     icon=saveIcon
                                     label=saveLabel
                                     disableSubmit=disableSubmit}}
...

Come faccio a eseguire un’azione (in questo caso, aggiungere un valore al campo personalizzato) quando si verifica quell’azione “save”?

Ho provato a creare un file js sotto initializers, dove potrei fare qualcosa come:

api.modifyClass('component:composer-save-button', {
   actions: {
       topic.set('custom_fields.sample_field', 'here's a value for the sample_field')
   }
}

Ma devo essere in grado di collegare quel “topic.set” all’azione “save” in composer.hbs, e non so come farlo.


E se ci fosse un modo più semplice per farlo, sono felice di sentirlo!

2 Mi Piace

Non sono a conoscenza di un esempio perfetto, ma potrei provare a svilupparne uno in futuro.

Potresti dare un’occhiata ad altri plugin per trovare esempi. Non sono sicuro di quale sia quello giusto al momento. C’è un repository Discourse chiamato qualcosa come all-the-plugins; spesso lo cerco con grep per trovare materiale.

Scommetto che il plugin delle reazioni attualmente in fase di test qui sia un buon esempio. Guarda il banner e dai un’occhiata.

2 Mi Piace

Sì, guarda sempre i plugin esistenti.

Ecco un esempio:

Che si basa su questo connettore e componente:

2 Mi Piace

Grazie a tutti: darò un’occhiata a questi. Ho già menzionato nel post originale di aver esaminato molti altri esempi. Avete qualche osservazione sul codice che ho fornito?

2 Mi Piace

Scusa. Non ho notato problemi evidenti (per me). Anche se sto migliorando nello sviluppo di plugin, spesso sento di sapere appena abbastanza da essere pericoloso.

2 Mi Piace

Potrebbe essere eccessivamente complicato se puoi accontentarti del “modo Discourse di fare le cose”, ovvero: modifica i dati nell’area Meta del Topic e solo in seguito, quando viene cliccata l’icona della matita.

Ti basta renderizzare una casella di input correttamente collegata e assicurarti di aver serializzato il valore nella Vista del Topic.

Il codice di PostRevisor farà la magia di aggiornare il campo personalizzato.

Dai un’occhiata all’esempio del plugin Locations. Anche quello è più di quanto ti serva.

Assicurati di eseguire anche il plugin Locations per vedere come appare.

2 Mi Piace

Ecco un altro esempio, con uno scenario di input leggermente diverso, ma che sfrutta comunque gli stessi meccanismi e hook:

https://github.com/paviliondev/discourse-topic-previews/blob/master/assets/javascripts/discourse/connectors/edit-topic/select-thumbnail-connector.hbs

4 Mi Piace

Grazie. Non conosco PostRevisor. Sto dando un’occhiata ora.

Non sono sicuro di cosa intendi per area Topic Meta. È un file a cui pensi? (Per quanto riguarda l’interfaccia utente, so che c’è il compositore per la creazione, con l’editor d all’interno, e poi c’è la visualizzazione del topic stesso. Non sono sicuro di dove si trovi l’area “Meta” lì dentro.)

2 Mi Piace

Considero le informazioni su Categoria e Tag come metadati.

2 Mi Piace

Ecco un esempio di base attualmente funzionante per creare un campo personalizzato per un argomento e impostarlo. Questo imposta il campo quando l’utente clicca su un pulsante specifico nella pagina di visualizzazione dell’argomento.

Ho notato che nei plugin che utilizzano campi personalizzati per gli argomenti, è comune trovare in plugin.rb l’uso di PostRevisor (come PostRevisor.track_topic_field) e DiscourseEvent.on(:topic_created) do |topic|.... Questi potrebbero permettere di impostare il campo personalizzato senza dover cliccare un pulsante, ad esempio impostandolo al momento della creazione dell’argomento. Ma non sono ancora riuscito a capire come fare.

[EDIT: Se qualcuno volesse suggerire codice per plugin.rb da aggiungere per impostare il valore del campo personalizzato su un argomento al momento della sua creazione (invece di avere un pulsante separato da cliccare), si prega di farlo! :slight_smile: ]

Quindi ecco un esempio di base che funziona senza quelle funzionalità avanzate:

plugin.rb

Topic.register_custom_field_type('sample_field', :string)
add_to_class(:topic, :sample_field) { self.custom_fields['sample_field'] } ##forse non necessario. basato sulla riga 83 del plugin discourse-locations plugin.rb
	
add_to_serializer(:topic_view, :sample_field, false) { object.topic.sample_field } ##probabilmente necessario solo se si vuole mostrare il risultato del campo personalizzato all'utente

connector/[add-button].hbs

//esempio qui: il connettore è topic-above-post-stream, che passa un modello (topic) nell’outlet del plugin

<button {{action "setThatTopic" model}}>Clicca qui</button>

connector/[add-button].js.es6

import Topic from 'discourse/models/topic';  //forse non necessario

export default {			
    actions: {
       setThatTopic(model){
           model.set('custom_fields.sample_field', 'newValue123')
           console.log('test per verificare che il campo personalizzato sia presente = ' + JSON.stringify(model.custom_fields))
        }
     }
}

assets/javascripts/initializers/topic-custom-field.js.es6

//questo potrebbe non essere necessario. Ma l’idea è di inizializzare l’oggetto custom_fields e renderlo possibile da inviare al server:

import { withPluginApi } from 'discourse/lib/plugin-api';

export default {
    name: 'topic-custom-field',
     initialize() {
	   withPluginApi('0.8.31', api => {
		 api.modifyClass('model:topic', {
			custom_fields: {},
			asJSON() {
			    return Object.assign(this._super(), {
				custom_fields: this.custom_fields
			   });
			}
	     })
	   })
    }
}
6 Mi Piace

Ho appena pubblicato un “plugin educativo” che dimostra come si fa

9 Mi Piace

Grazie, @angus. Questo è estremamente utile ed è proprio il tipo di risorsa che rende più semplice lo sviluppo con Discourse. Personalmente, mi piacerebbe vedere questo tipo di risorsa—esempi di codice diretti e essenziali per implementare una singola funzionalità alla volta—per una varietà di attività con Discourse. Ad esempio, campi personalizzati per categorie e gruppi, anch’essi. Questo tipo di risorsa fa risparmiare un sacco di tempo.

3 Mi Piace