Theme-Component v Plugin: Was ist der Unterschied

Kann jemand den Unterschied zwischen diesen drei Discourse-Konzepten erklären: theme-component, plugin und pluginAPI?

Besonders zwischen theme-component und plugin. Wenn ich mein Forum anpassen möchte, wie weiß ich dann, was ich erstellen soll?

(Entschuldigung, falls ich diese Unterscheidung im Einführungstext übersehen habe, aber ich kann sie dort nicht finden)

Ich bin bei Discourse kein Anfänger, aber auch kein Experte.

  1. Ein Theme-Component verwendet HTML, CSS und JavaScript, um ein Basisthema zu erweitern.
    Ich erwähne das Basisthema, weil es üblicherweise einfach als „Theme

Um die Antwort von @EricGT, die bereits gut erklärt, zu ergänzen:

  • Ein Theme oder Theme-Komponente ist im Wesentlichen eine Möglichkeit, beliebige Teile der Discourse-Frontend-EmberJS-Anwendung zu ändern. Dies kann so einfach sein wie das Anpassen von HTML oder CSS, oder so komplex wie das Hinzufügen neuer Funktionen. Themes sind deutlich robuster, falls etwas schiefgeht; das bedeutet, dass Ihre gesamte Seite nicht unbedingt ausfällt, wenn etwas nicht funktioniert.
  • Ein Plugin wirkt sich hauptsächlich auf die Rails-Server-seitige Anwendung aus, bietet aber auch alle Möglichkeiten eines Themes und beeinflusst die EmberJS-Anwendung, ist jedoch deutlich komplexer. Plugin-Fehler sind oft weniger robust. Wenn Sie also etwas in einem Theme umsetzen können, beginnen Sie dort. Ein Plugin ist jedoch erforderlich, wenn Sie eine benutzerdefinierte Route benötigen oder Daten speichern möchten.
  • Die pluginAPI ist eine Client-seitige API, die Themes oder Theme-Komponenten nutzen können, um bestimmte Teile der Discourse-Client-Anwendung einfacher zu modifizieren.

Der beste Einstieg in die Anpassung Ihrer Seite ist ein Theme. Hier sind einige Ressourcen:

Designer’s Guide zu Discourse Themes
Entwicklerguide zu Discourse Themes
Anfängerleitfaden zur Verwendung von Theme Creator und Theme CLI zum Starten der Entwicklung eines Discourse-Themes

Danke, Leute. Das ist hilfreich. Ich glaube, der entscheidende Unterschied, den ich herausgelesen habe, ist:
– Wenn du etwas ändern möchtest, das nur die Frontend-Ansicht betrifft, erstelle ein Theme.
– Wenn du etwas ändern möchtest, das eine Interaktion mit dem Backend erfordert, erstelle ein Plugin.

Klingt das richtig?

Hier ist ein konkretes Beispiel, das ich im Kopf habe und an dem ich gerade arbeite: Ich möchte erreichen, dass jeder Kategorien-Moderator Themen in dieser Kategorie anpinnen kann. Die groben Schritte sind meiner Meinung nach:

  1. Prüfen, ob der Benutzer ein Moderator der Kategorie ist (dafür müssen Informationen über den Benutzer und die Kategorie aus dem Backend abgerufen werden).

  2. Wenn der Benutzer ein Moderator ist, die Pin-Schaltfläche anzeigen (dies ist Frontend).

  3. Wenn der Benutzer auf die Pin-Schaltfläche klickt, das Thema nach oben verschieben (ich bin mir nicht ganz sicher, wo dies im Discourse-Code passiert – vielleicht sowohl im Frontend als auch im Backend?).

Da ich hier mit dem Backend kommunizieren muss (wahrscheinlich bei Schritt 1, eventuell auch bei Schritt 3?), müsste ich ein Plugin verwenden. Klingt das richtig?

Der oberflächliche Teil mag zwar so sein, aber es wird das Backend betreffen, da es sich auf Rechte und Sicherheit bezieht. Man kann dem Frontend nicht die Entscheidung darüber überlassen, welche Berechtigungen jemand hat.

Meinst du, dass die programmatische Beantwortung der Frage „Ist dieser Benutzer ein Moderator dieser Kategorie

In einem Theme solltest du in der Lage sein, zu prüfen, ob ein Benutzer Moderator ist, und auch Backend-Aufrufe tätigen, wenn die Discourse-API einen Endpunkt bereitstellt, den du vom Frontend aus aufrufen kannst (schließlich kann das Theme JavaScript verwenden). Daher brauchst du für [1] wahrscheinlich kein Plugin. Ein Plugin wäre nur nötig, wenn du das Backend-Verhalten ändern oder eine API bereitstellen musst.

Für [3] brauchst du es wahrscheinlich jedoch, denn wie @merefield bereits sagte, geht es um Rechte und Sicherheit (wenn das Backend einem Moderator untersagt, ein Thema zu pinnen, müsstest du es ändern, um dies zu ermöglichen).

[quote=“JQ331, Beitrag:6, Thema:153951”]
Meinst du, dass die programmatische Antwort auf die Frage „Ist dieser Benutzer Moderator dieser Kategorie

Das ist bezüglich Themes vs. Plugins und auch in Bezug auf das spezifische Beispiel, das ich erwähnt habe, sehr hilfreich. Danke.

Bisher habe ich Änderungen vorgenommen, indem ich mich durch die Details des Discourse-Codes gearbeitet habe (wo ist dieses Objekt definiert, was steuert diese Vorlage, wo befindet sich die Logik, die diese Aktion verarbeitet usw.). Das war jedoch langsam voranschreitend.

Ich denke, ein effizienterer Weg wäre, mich auf die API zu konzentrieren. Auf diese Weise muss ich mich nicht durch alle Details des ausgereiften Discourse-Codes arbeiten und kann mich stattdessen auf den Aufbau eines Themes anstelle eines Plugins konzentrieren – oder vielleicht einfach Änderungen im „Anpassen“-Dashboard vornehmen.

Grundsätzlich scheint es viel überschaubarer zu sein, herauszufinden, wie die API funktioniert, als sich durch die Discourse-Codebasis zu arbeiten.

Um beim genannten Beispiel zu bleiben: Wenn ein Benutzer ein Moderator einer Kategorie ist, soll dieser Benutzer Themen auf der Kategorie-Seite anpinnen können.

Könnte ich das ohne ein Plugin umsetzen? Lassen Sie mich versuchen, es zu skizzieren:

1. Ist ein Benutzer ein Moderator einer Kategorie?

Ich sehe derzeit nichts in der API, das mir mitteilen würde, ob ein Benutzer ein Moderator einer Kategorie ist. Ich würde erwarten, dass dies in einem GET-Aufruf zum Abrufen einer Kategorie zu finden ist, aber ich sehe dort keinen solchen Aufruf. Oder vielleicht im GET-Aufruf zum Abrufen eines Benutzers, aber dort sehe ich keine Auflistung der Kategorien, für die der Benutzer ein Moderator ist.

Könnte ich diese hinzufügen?

Alternativ könnte ich vielleicht ein benutzerdefiniertes Feld (custom_field) für den Benutzer oder die Kategorie erstellen, um die Moderatorrolle zu identifizieren, und dann beim Laden einer Kategorie-Seite einen API-Aufruf für dieses benutzerdefinierte Feld tätigen.

2. Wenn der Benutzer ein Moderator ist, die Pin-Schaltfläche anzeigen.

Wenn ich Frage (1) beantworten kann, gehe ich davon aus, dass ich diese Schaltfläche einfach mit Frontend-JavaScript und CSS hinzufügen kann, wobei sie nur angezeigt wird, wenn der Benutzer ein Moderator ist.

3. Benutzer (der Moderator ist) klickt auf die Schaltfläche, und das pinnt das Thema.

In der API scheinen Themen tatsächlich ein Merkmal „pinned“ (boolean) zu haben. Ich nehme an, dies korreliert damit, ob sie in ihrer Kategorie angepinnt sind, da es so aussieht, als ob jedes Thema nur eine Kategorie hat.

Also könnte ich hier, wenn der Moderator auf die „Pin“-Schaltfläche klickt, den Status „pinned“ des Themas auf True aktualisieren. Falls das nicht funktioniert, könnten auch benutzerdefinierte Felder eine Lösung sein (obwohl ich nicht sehe, wie man benutzerdefinierte Felder zu einem Thema hinzufügt).


Mit diesem Ansatz oder etwas Ähnlichem scheint es mir also möglich, diese Aufgabe mit der API zu erledigen, wofür ich, wenn ich ein Plugin verwenden würde, viele Dateien der Discourse-Codebasis durchsuchen müsste.

Klingt das richtig?

Haben Sie folgendes gefunden: So reverse-engineern Sie die Discourse-API

Das habe ich bereits zuvor gesehen, aber ich schaue mir das jetzt genauer an. Danke für die Erinnerung.

Ich versuche, folgende Punkte zu klären:
–Wo in der API kann ich Informationen darüber erhalten, wer der Moderator einer bestimmten Kategorie ist? (Ich sehe es nicht in den zurückgegebenen Informationen über Kategorien oder Benutzer – es muss offensichtlich irgendwo sein)

–Kann man über die API neue Felder zu einem Eintrag hinzufügen? Zum Beispiel: Könnte ich die API nutzen, um ein benutzerdefiniertes Feld zu einem Thema hinzuzufügen? (Ich glaube nicht, dass Themen im Allgemeinen mit benutzerdefinierten Feldern ausgestattet sind)

Ich würde in der Datenbank nachsehen.

Die Datenbank verfügt über eine Tabelle namens posts, und du könntest dort ein Feld hinzufügen. Du würdest dich dann aber außerhalb des offiziellen Rahmens bewegen und keinen Support erhalten.

Danke – das ist alles sehr hilfreich.

Welche Datenbank meinst du?


Zur Bestätigung: Meine Idee dabei ist, die API zu nutzen, um einige dieser Aufgaben zu erledigen, die sonst vielleicht ein Plugin erfordern würden. Mein eigener Standort würde also beispielsweise eine API-Anfrage stellen, um festzustellen, ob ein Benutzer (oder eine Gruppe, je nach Fall) Moderator einer Kategorie ist. Der Aufruf wäre im Anpassungsbereich, in einem Theme oder in einem Plugin fest codiert.

Um solche Aufrufe zu tätigen, muss ich authentifiziert sein. Dafür ist meines Erachtens die Erstellung eines API-Schlüssels im Admin-Bereich erforderlich. Der Prozess zur Erstellung eines API-Schlüssels im Admin-Bereich erfordert eine „Beschreibung

Wenn Discourse gemäß der Standardanleitung installiert wird, läuft es in einem Docker-Container. Die Persistenz der Daten wird über eine PostgreSQL-Datenbank gewährleistet.

Siehe: Data Explorer-Plugin

Wenn du Administratorrechte hast, kannst du eine der Backups herunterladen; diese sind als SQL in eine tar.gz-Datei komprimiert. Du kannst die SQL-Daten verwenden, um die Daten in eine andere PostgreSQL-Datenbank neu zu laden und noch mehr damit anzufangen.

Ich habe noch nie ein Theme oder Plugin erstellt und die API weder aus Ruby noch mit einer anderen Programmiersprache verwendet. Ich habe jedoch Admin-Zugriff auf einer Live-Seite, wodurch ich auf das Backup zugreifen konnte. Ich programmiere zudem in Prolog, womit ich auf die Daten zugreife und sie verwende, um die Beiträge mit DCGs zu parsen. Wenn du BNF kennst, sind DCGs nicht weit davon entfernt, aber für die fortgeschritteneren Teile musst du syntaktische Unifikation und Rückwärtsverkettung verstehen.

Danke. Ich werde diesen Punkt separat weiterverfolgen.

Nein, da die Zugriffsrechte für jede Aktion vom Server durchgesetzt werden.

Sie sollten sich ansehen, wie man die Funktionen in lib/guardian/ und lib/guardian.rb überschreibt, um kategorien-spezifischen Moderatoren das Anpinnen von Themen zu ermöglichen. Anschließend nutzen Sie dieselben Mechanismen wie beim Theme-JS (allerdings in einem Plugin), um die Benutzeroberfläche so anzupassen, dass die Option „Thema anpinnen

Ahh – das ergibt Sinn. Es klingt also, als würde die Nutzung der API dafür nicht funktionieren (deine Antwort spart mir wahrscheinlich viel Zeit).

Ich werde es vielleicht etwas anders als das übliche Pinning-Verhalten umsetzen. Statt dessen würde ich bestimmten Benutzern „Eigentümerrechte

Lieber @JQ331,

Meine aktuelle Frage lautet also: Funktioniert diese Art der Nutzung der JSON-API – insbesondere zum Erstellen und Abrufen benutzerdefinierter Felder innerhalb meiner Discourse-App?

Es gab bereits hervorragende Antworten auf Ihre Fragen zum Unterschied zwischen einer Theme-Komponente, einem Plugin und der Discourse-API. Ich bezweifle, dass ich noch viel mehr beitragen kann. Hier ist jedoch eine weitere Perspektive, die Ihnen vielleicht – oder auch nicht – weiterhilft:

Sowohl Theme-Komponenten als auch Plugins verwenden Template-Hooks (Plugin-Hooks), um Code im Ember.js-Lebenszyklus auszuführen (was übrigens gut zu lernen ist).

Zusätzlich steht sowohl Theme-Komponenten als auch Plugins die Discourse-API zur Verfügung.

Die API macht im Wesentlichen eine Teilmenge – aber nicht alle – der Daten der zugrunde liegenden PostgreSQL-Datenbank verfügbar.

Wenn Sie Funktionen entwickeln, ist es ratsam, zunächst mit der API zu beginnen und zu prüfen, ob die benötigten Daten über die API verfügbar sind.

Falls es Daten gibt, die Sie benötigen, die jedoch nicht in der API enthalten sind, müssen Sie die PostgreSQL-Datenbank untersuchen, um festzustellen, ob diese Daten in der Datenbank vorhanden sind.

Sind die zusätzlichen benötigten Daten in der Datenbank vorhanden, müssen Sie diese Daten verfügbar machen. In der Regel bedeutet dies, dass Sie Daten zum Discourse-Daten-Serializer hinzufügen und die API erweitern.

Der Daten-Serializer ist lediglich der Prozess, bei dem das JSON-Objekt erstellt wird, das über die API bereitgestellt wird. Dies kann erweitert werden, um weitere Objekte hinzuzufügen.

Um die PostgreSQL-Datenbank zu untersuchen, gehe ich davon aus, dass es viele Möglichkeiten gibt (z. B. durch Lesen des Codes auf GitHub). Ich tue dies jedoch, indem ich mich direkt in die Datenbank einlogge, die Tabellen in der Datenbank ansehe und die Struktur dieser Tabellen sowie die Felder in jeder Tabelle analysiere (unter Verwendung von grundlegendem SQL).

Zusammenfassend (und kurz gehalten): Wir benötigen sowohl die API als auch die Datenbanktabellen als Referenz. Im Allgemeinen erstellen wir, wenn wir die API erweitern möchten, indem wir Daten hinzufügen, die standardmäßig (OOTB) nicht von der API bereitgestellt werden, ein Plugin dafür. Anschließend werden diese Daten zusammen mit der (erweiterten) API verfügbar gemacht, und wir können diese Daten sowohl in Theme-Komponenten als auch in Plugins verwenden.

Ich hoffe, diese Perspektive war auf irgendeine kleine Weise nützlich oder hilfreich.

Hervorragende Erklärung. Vielen Dank für diese Antwort. Sie hebt etwas hervor, das mir bisher nicht bewusst war:

Aus diesen Antworten entnehme ich, dass (wie Sie sagen) die Interaktion mit der JSON-API in vielen Fällen ein guter Ausgangspunkt sein kann, der die Notwendigkeit, ein neues Theme oder Plugin zu programmieren, vermeiden könnte. Es gibt jedoch einige Datentypen, die von der API nicht bereitgestellt werden. Um auf diese Datentypen zuzugreifen und damit arbeiten zu können, müssten Sie den Discourse-Datenserialisierer verwenden, um diese Daten offenzulegen; und für diese Serialisierung benötigen Sie ein Plugin.

Ein gutes Beispiel für Daten, die über die API nicht verfügbar sind, scheinen die Gruppeninhaber einer Gruppe zu sein. Ich sage das, weil (in Bezug auf den Zugriff auf Gruppeninhaber):

Ein Punkt der Verwirrung – in der Discourse-API wird, wenn Sie eine bestimmte Gruppe abrufen, eines der zurückgegebenen Merkmale als "is_group_owner": true aufgeführt, also bin ich mir nicht sicher, was das bedeuten soll…

Aber es scheint, dass ich den Gruppeninhaber erhalten müsste, indem ich das Merkmal des Gruppeninhabers serialisiere.


Gibt es gute Beispiele für die Verwendung des Discourse-Serializers? Ich habe dieses gesehen, aber angesichts seiner Wichtigkeit wäre eine Schritt-für-Schritt-Anleitung mit ein paar Beispielen äußerst hilfreich.

Das nächste Beispiel, das ich habe, ist:

Das ist hilfreich, aber nicht ganz richtig (zumindest erhalte ich Fehlermeldungen wie „ungültiges Plugin"). Ich bin mir nicht sicher, wie ich es anpassen soll, damit ich auf der Gruppenindexseite auf die Gruppeninhaber für jede Gruppe zugreifen kann.

Ich bin mir nicht sicher, wie Sie versucht haben, das Plugin-Beispiel zu verwenden, aber es lief auf einer Entwicklungsumgebung erfolgreich, als ich die Dateistruktur und den Code benutzte, die ich in Ihrem anderen Thema gepostet habe.

is_group_owner wird im Kontext verwendet, wenn der aktuelle Benutzer die Gruppen betrachtet.

Sie können die Besitzerinformationen über einen Ajax-Aufruf erhalten, aber soweit ich weiß, müsste dies für jede einzelne Gruppe in der Liste durchgeführt werden, was potenziell zu vielen Anfragen führen könnte. Ich denke, insgesamt wäre es schwierig, diese Methode zum Funktionieren zu bringen. In jedem Fall können Sie, wenn Sie experimentieren möchten, den folgenden Proof-of-Concept-Code-Schnipsel in einem Theme ausprobieren. Ersetzen Sie einfach GROUP_NAME durch den Namen einer Ihrer Gruppen. (EDIT: Hier ist auch eine Theme-Komponente mit einem Beispiel, wie ein Ajax-Aufruf genutzt werden kann: discourse-featured-topics/common/head_tag.html at master · awesomerobot/discourse-featured-topics · GitHub)

<script type="text/discourse-plugin" version="0.8.40">
  const { ajax } = require("discourse/lib/ajax");
  ajax(`/groups/GROUP_NAME/members.json`).then(response => {
    console.log(response.owners.map(owner => owner.username))
  });
</script>

Mit all dem gesagt, wäre die Verwendung eines Plugins definitiv die einfachste und sauberste Lösung.