Wie man ein super einfaches Thema benutzerdefiniertes Feld hinzufügt

Ich versuche zu verstehen, wie man ein benutzerdefiniertes Feld zu Themen hinzufügt, und arbeite mich durch ein sehr einfaches Beispiel durch. Ziel: Ein benutzerdefiniertes Feld namens “sample_field” zu jedem erstellten Thema hinzufügen, mit einem einfachen String-Wert.

Ich habe verschiedene Beispiele durchgesehen, wie das Poll-Plugin und das solved-Plugin sowie diese Diskussion, aber diese Plugins machen mit ihren benutzerdefinierten Feldern so viel mehr, dass ich den grundlegenden Code, den man dafür braucht, noch nicht ganz durchschaut habe.

Also bin ich noch nicht so weit – meine Datei plugin.rb fehlt etwas (glaube ich), und ich habe noch nicht herausgefunden, wie man den String-Wert zum Zeitpunkt der Erstellung des Themas an das benutzerdefinierte Feld bindet.

Was muss ich tun, damit das funktioniert?

Jede Hilfe wird geschätzt. Danke!

Hier ist, was ich bisher habe:

plugin.rb:
//Erstelle das benutzerdefinierte Feld:

  after_initialize do
     Topic.register_custom_field_type('sample_field', :string)
     add_to_serializer(:topic_view, :custom_fields) { object.custom_fields } //Wenn ich das benutzerdefinierte Feld auf der Client-Seite anzeigen möchte
  end

assets/javascripts/initializers/topic-custom-field.js.es6:
//Initialisiere das benutzerdefinierte Feld-Objekt und stelle sicher, dass es an den Server gesendet werden kann:

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
          });
        }
      })
    })
  }
}

Wie füge ich dann den Wert des benutzerdefinierten Feldes zum Zeitpunkt des Speicherns zum Thema hinzu?

Ich glaube, die Schlüsselaktion “save” für ein Thema findet hier im Codebase statt:

app/templates/composer.hbs:

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

Wie mache ich etwas (in diesem Fall einen Wert zum benutzerdefinierten Feld hinzufügen), wenn diese “save”-Aktion auftritt?

Ich habe versucht, eine JS-Datei unter initializers zu erstellen, in der ich etwas wie folgendes tun könnte:

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

Aber ich muss in der Lage sein, dieses “topic.set” mit der “save”-Aktion in composer.hbs zu verknüpfen, und ich weiß nicht, wie ich das mache.


Und falls es einen einfacheren Weg gibt, dies zu tun, würde ich mich freuen, davon zu hören!

2 „Gefällt mir“

Mir ist kein perfektes Beispiel bekannt, aber ich werde vielleicht irgendwann versuchen, eines zu entwickeln.

Du könntest dir einige andere Plugins ansehen, um Beispiele zu finden. Ich bin mir im Moment nicht sicher, welches genau. Es gibt ein Discourse-Repository mit einem Namen wie „all-the-plugins“, das ich oft durchsuche, um nach bestimmten Dingen zu suchen.

Ich wette, dass das Reaktionen-Plugin, das derzeit hier getestet wird, ein gutes Beispiel ist. Schau dir das Banner an und wirf einen Blick darauf.

2 „Gefällt mir“

Ja, schauen Sie sich immer bestehende Plugins an.

Hier ist ein Beispiel:

Dieses setzt auf diesen Connector und diese Komponente:

2 „Gefällt mir“

Danke an alle – ich werde mir das ansehen. Ich habe im ursprünglichen Beitrag erwähnt, dass ich bereits eine Reihe anderer Beispiele geprüft habe. Habt ihr Gedanken zum Code, den ich bereitgestellt habe?

2 „Gefällt mir“

Entschuldigung. Ich habe keine offensichtlichen (für mich) Probleme festgestellt. Obwohl ich mich bei der Plugin-Entwicklung immer besser auskenne, habe ich oft das Gefühl, nur gerade so viel zu wissen, um gefährlich zu sein.

2 „Gefällt mir“

Möglicherweise zu kompliziert, wenn du dich mit der „Discourse-Art des Vorgehens

2 „Gefällt mir“

Hier ist ein weiteres Beispiel mit einem leicht anderen Eingabeszenario, das jedoch dieselben Mechanismen und Hooks nutzt:

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

4 „Gefällt mir“

Danke. Ich bin mit PostRevisor nicht vertraut. Ich schaue mir das gerade an.

Ich bin mir nicht sicher, was du mit dem Bereich Topic Meta meinst. Ist das eine Datei, die du im Sinn hast? (Was die Benutzeroberfläche angeht, kenne ich den Composer zum Erstellen mit dem d-Editor darin und dann die Topic-Ansicht selbst. Ich bin mir nicht sicher, wo sich dort der Bereich “Meta” befindet.)

2 „Gefällt mir“

Ich betrachte die Informationen zu Kategorien und Tags als Metadaten.

2 „Gefällt mir“

Hier ist ein aktuell funktionierendes Basisbeispiel zum Erstellen eines benutzerdefinierten Themenfelds und zum Setzen dieses Felds. Dies setzt das Feld, wenn der Benutzer auf einen bestimmten Button auf der Themenansichtseite klickt.

Ich stelle fest, dass in Plugins, die benutzerdefinierte Themenfelder verwenden, in plugin.rb häufig PostRevisor (wie PostRevisor.track_topic_field) und DiscourseEvent.on(:topic_created) do |topic|... zum Einsatz kommen. Diese könnten es ermöglichen, das benutzerdefinierte Feld ohne Buttonklick zu setzen – beispielsweise beim Erstellen des Themas. Das habe ich jedoch noch nicht herausgefunden.

[EDIT: Falls jemand Code für plugin.rb vorschlagen möchte, um den Wert des benutzerdefinierten Felds zum Zeitpunkt der Themenerstellung hinzuzufügen (anstatt einen separaten Button zu benötigen, der geklickt werden muss), dann bitte gerne! :slight_smile: ]

Hier ist also ein einfaches Beispiel, das ohne diese ausgefallenen Dinge funktioniert:

plugin.rb

Topic.register_custom_field_type('sample_field', :string)
add_to_class(:topic, :sample_field) { self.custom_fields['sample_field'] } ##vielleicht nicht notwendig, basierend auf Zeile 83 der plugin.rb von discourse-locations
	
add_to_serializer(:topic_view, :sample_field, false) { object.topic.sample_field } ##wahrscheinlich nur notwendig, wenn Sie das Ergebnis des benutzerdefinierten Felds dem Benutzer anzeigen möchten

connector/[add-button].hbs

//Beispiel hier: Der Connector ist topic-above-post-stream, der ein Modell (topic) im Plugin-Ausgang übergibt

<button {{action "setThatTopic" model}}>Hier klicken</button>

connector/[add-button].js.es6

import Topic from 'discourse/models/topic';  //vielleicht nicht notwendig

export default {			
    actions: {
       setThatTopic(model){
           model.set('custom_fields.sample_field', 'newValue123')
           console.log('Test, ob das benutzerdefinierte Feld vorhanden ist = ' + JSON.stringify(model.custom_fields))
        }
     }
}

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

//Dies ist vielleicht nicht notwendig. Die Idee ist jedoch, das Objekt für benutzerdefinierte Felder zu initialisieren und sicherzustellen, dass es an den Server gesendet werden kann:

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 „Gefällt mir“

Ich habe gerade ein „Bildungs-Plugin

9 „Gefällt mir“

Danke, @angus. Das ist unglaublich hilfreich und genau das Richtige, um die Arbeit mit Discourse zu erleichtern. Ich würde persönlich gerne mehr von dieser Art von Ressource sehen – klare, minimalistische Codebeispiele zur schrittweisen Implementierung einzelner Funktionen – für verschiedene Aufgaben mit Discourse. Zum Beispiel auch für benutzerdefinierte Felder bei Kategorien und Gruppen. Eine solche Ressource spart enorm viel Zeit.

3 „Gefällt mir“