Einbetten einer Liste von Discourse-Themen auf einer anderen Website

Wenn Sie die neuesten Builds von Discourse herunterladen, erhalten Sie die Möglichkeit, Themenlisten in anderen Websites über einfaches JavaScript und HTML einzubetten.

Der typische Anwendungsfall dafür ist ein Blog oder eine andere inhaltsorientierte Website, auf der Sie ein Widget am Rand des Bildschirms haben möchten, das Themen auflistet. Sie können nach Kategorie, Tag oder einer der anderen öffentlichen Filteroptionen filtern.

So betten Sie eine Liste von Themen ein

Zunächst müssen Sie die Site-Einstellung „Themenliste einbetten" aktivieren.

Fügen Sie dann in Ihrem HTML ein <script>-Tag hinzu, das das erforderliche JavaScript zum Einbetten der Discourse-Themen enthält. Sie können dies dort hinzufügen, wo Sie normalerweise Skripte einfügen. Zum Beispiel:

<script src="http://URL/javascripts/embed-topics.js"></script>

Ersetzen Sie URL durch die Forum-Adresse, einschließlich des Unterordners, falls vorhanden.

Anschließend fügen Sie im <body> Ihres HTML-Dokuments ein d-topics-list-Tag hinzu, um die Liste der Themen anzugeben, die Sie einbetten möchten. Auch hier müssen Sie URL durch Ihre Basis-URL ersetzen:

<d-topics-list discourse-url="URL" category="1234" per-page="5"></d-topics-list>

Alle von Ihnen angegebenen Attribute (außer discourse-url, das erforderlich ist) werden in die Abfrageparameter für die Themensuche umgewandelt. Wenn Sie also nach Tags suchen möchten, können Sie Folgendes tun:

<d-topics-list discourse-url="URL" tags="cool"></d-topics-list>

Wenn ein Abfrageparameter Unterstriche enthält, wandeln Sie diese in Bindestriche um. Im obigen Beispiel haben Sie wahrscheinlich bemerkt, dass per_page zu per-page wurde.

In SameSite-Kontexten (d. h. die einbettende Website und Ihr Forum teilen sich eine übergeordnete Domain) erkennt Discourse, ob Sie im Forum angemeldet sind, und zeigt die Ergebnisse entsprechend an. Lassen Sie sich nicht überraschen, wenn Sie als angemeldeter Benutzer sichere Kategorien und dergleichen sehen – anonyme Benutzer können dies nicht!

Liste der Parameter

template: Entweder complete oder basic (Standard). Während basic nur eine Liste von Titelnamen ist, umfasst complete Titel, Benutzernamen, Benutzer-Avatar, Erstellungsdatum und Themen-Miniaturansicht.

per-page: Zahl. Steuert, wie viele Themen zurückgegeben werden sollen.

category: Zahl. Beschränkt Themen auf eine einzelne Kategorie. Geben Sie die id der Zielkategorie an.

allow-create: Boolean. Wenn aktiviert, enthält die Einbettung eine Schaltfläche „Neues Thema".

tags: String. Beschränkt Themen auf solche, die mit diesem Tag verknüpft sind.

top_period: Einer von all, yearly, quarterly, monthly, weekly, daily. Wenn aktiviert, werden die „Top"-Themen des jeweiligen Zeitraums zurückgegeben.

Beispiele

Ich habe hier eine Beispielwebsite erstellt:

https://embed.eviltrout.com

Sie sollten den Quellcode in Ihrem Browser einsehen können, um den Code zu sehen. Der gesamte Quellcode befindet sich jedoch auch auf GitHub:

Dies ist eine brandneue Funktion, daher wäre jedes Feedback oder jede Anfrage willkommen.

Styling der Liste

Sie können unsere vorhandene Theme-Funktion verwenden, um benutzerdefinierte Stile für die eingebettete Liste hinzuzufügen.

Standardmäßig sieht unsere eingebettete Liste mit der complete-Vorlage beispielsweise so aus:

Wenn Sie möchten, dass sie beispielsweise wie ein Raster aussieht, können Sie benutzerdefiniertes SCSS zu Theme > Common > Embedded CSS hinzufügen:

.topics-list {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  
  .topic-list-item { 
    .main-link {
      border: 1px dotted gray;
      padding: 0;
    }
  
    .topic-column-wrapper {
      flex-direction: column-reverse;
      
      .topic-column.details-column {
        width: 100%;
      }
        
      .topic-column.featured-image-column .topic-featured-image img {
        max-width: initial;
        max-height: initial;
        width: 100%;
      }
    }
  }
}

Dadurch sieht es so aus:

95 „Gefällt mir“

Hallo zusammen! Wir möchten, dass die Links in einem neuen Tab geöffnet werden (also target=“_blank” statt target=“_parent”). Gibt es eine einfache Möglichkeit, das im Rahmen eines Iframes umzusetzen?

2 „Gefällt mir“

Ich weiß nicht, ob das ist, wonach du suchst, aber so etwas sollte funktionieren, um Links in neuen Tabs zu öffnen. CORS muss für die externe Domain aktiviert sein. Ich habe es so versucht, weil ich ein angeheftetes Thema ausschließen wollte.

// `fetch` benötigt möglicherweise einen Polyfill
const targetEl = document.getElementById("forumTopics");

function renderTemplate(topicsArr) {
    const items = topicsArr.map(
        (topic) => `<li><a href="${topic[1]}" target="_blank">${topic[0]}</a></li>`
    );

    targetEl.innerHTML = `<ul>${items.join("\n")}</ul>`;
}

// Füge `.json` an jede Themenliste an
fetch("https://forum.example.com/latest.json")
    .then((res) => res.json())
    .then((json) => {
        const topics = json.topic_list.topics
            .slice(1, 6)
            .map((t) => [
                t.title,
                `https://forum.example.com/t/${t.slug}/${t.id}`,
            ]);

        renderTemplate(topics);
    });
3 „Gefällt mir“

Danke! Die Idee gefällt mir, aber basierend auf diesem Beitrag What are the risks of enabling Cross-origin resource sharing (DISCOURSE_ENABLE_CORS) denke ich, dass die Aktivierung von CORS nicht die beste Lösung ist.

2 „Gefällt mir“

Du solltest CORS nur für vertrauenswürdige Seiten aktivieren. Wenn du CORS für jede Quelle aktivierst, wird der Zweck davon zunichte gemacht.

6 „Gefällt mir“

Ich habe CORS nur für andere von mir kontrollierte Seiten aktiviert. Das Ziel war es, eine Liste von Forumsthemen auf unseren anderen Seiten mit Frontend-Code zu laden. Diese Methode würde wahrscheinlich nicht funktionieren, um beliebigen Seiten das Einbetten von Beiträgen zu ermöglichen.

Bearbeitung: Falls Sie diesen Code kopieren/einfügen, achten Sie bitte auf .slice(1, 6), da dies eines der Themen entfernt. (Ich glaube, das war das angepinnte Thema, das ich entfernen wollte.)

3 „Gefällt mir“

Cool, das können wir dann ausprobieren – ich habe derzeit außer localhost keine andere Seite (während des Testens), weshalb ich zögerte, sie hinzuzufügen. Wenn ich jedoch jemanden finde, der einen Platz hat, können wir es versuchen. Vielen Dank für deine Hilfe!

4 „Gefällt mir“

Hey @j127,

wir haben aktuell das gleiche Problem und möchten Links in einem neuen Tab öffnen.
Nur eine kurze Frage:

Wo genau fügst du den bereitgestellten Code ein?

@eviltrout, hast du eine Idee, warum die CSS-Stile in meinem Fall nicht angezeigt werden?

2 „Gefällt mir“

Dieser Code ist nur ein schnelles Beispiel für die allgemeine Idee. Ich glaube nicht, dass fetch in allen Browsern funktioniert. Ich kann ihn gerne in ES5 umschreiben, wenn du möchtest.

Ist deine Seite WordPress oder eine Art Headless WordPress?

4 „Gefällt mir“

Es scheint in allen modernen Browsern zu funktionieren, und Discourse unterstützt IE11 nicht mehr.

4 „Gefällt mir“

Meine Seite ist ganz normales WordPress, nicht headless.

1 „Gefällt mir“

Kann ich das verwenden, um eine Liste von Discourse-Themen in eine andere Discourse-Instanz einzubetten? Oder gibt es eine intelligentere Methode dafür?

Mein Anwendungsfall ist eine ‘Brücke’ zwischen zwei Instanzen als vorübergehende Lösung, bis sie in Zukunft zusammengeführt werden können. Es wäre schön, wenn dies automatisiert und dynamisch erfolgen könnte.

2 „Gefällt mir“

Wenn dir Internet Explorer egal ist, sollte dieses Code-Snippet funktionieren. (CORS muss in den Discourse-Einstellungen für die externe Domain aktiviert sein.)

Zum Testen öffne eine beliebige Seite in diesem Forum und füge das folgende Snippet in die Browserkonsole ein. Ich habe das Ziel-Element auf document.body geändert, sodass die gesamte Seite durch die Liste der Forumsthemen ersetzt wird. Für eine echte Seite ändere einfach das Ziel-Element zu document.getElementById("#someId") und füge irgendwo auf der Seite ein div mit dieser ID hinzu. Das Skript wird es dann mit der Themenliste füllen.

// `fetch` benötigt möglicherweise einen Polyfill, es sei denn, dir ist Internet Explorer egal
// const targetEl = document.getElementById("forumTopics");

// Dies ersetzt den Body der Seite, nur als Beispiel
const targetEl = document.body;

// Füge hier die URL deines Forums ein, um es auf deinem eigenen Forum zu testen
const baseForumURL = `https://meta.discourse.org`;

// Wie viele Themen angezeigt werden sollen
const numTopics = 6;

function renderTemplate(topicsArr) {
    const items = topicsArr.map(
        (topic) => `<li><a href="${topic[1]}" target="_blank">${topic[0]}</li>`
    );

    targetEl.innerHTML = `<ul>${items.join("\n")}</ul>`;
}

// Füge `.json` an jede Themenliste an
fetch(`${baseForumURL}/latest.json`)
    .then((res) => res.json())
    .then((json) => {
        const topics = json.topic_list.topics
            .slice(0, numTopics)
            .map((t) => [
                t.title,
                `${baseForumURL}/t/${t.slug}/${t.id}`,
            ]);

        renderTemplate(topics);
    });

Beispiel: Wenn das Ziel-div irgendwo auf deiner WP-Seite so aussieht:

<div id="forumTopics">
    <!-- Die Forenbeiträge erscheinen hier -->
</div>

dann könnte das JavaScript diese ID so ansprechen:

// Suche nach dieser Zeile im ursprünglichen Beispiel, das ich gepostet habe
const targetEl = document.getElementById("forumTopics");
4 „Gefällt mir“

Meinst du damit den Code im ersten Beitrag oder das Snippet in Beitrag 50? Und nein, mir ist IE egal. Keine Notwendigkeit, uns diesem Dinosaurier anzupassen :).
In meinem Fall wird das CSS für mein Snippet in keinem Browser geladen.

Das ist also JS, und ich muss beim Einbinden in WordPress ein <script>-Tag darum herumsetzen, richtig?

2 „Gefällt mir“

Es ist eine Weile her, seit ich WordPress benutzt habe. Fügen Sie dies zum HTML eines Themes hinzu? Falls ja, dann umschließen Sie meinen Code mit einem script-Tag und platzieren Sie das <div> dort, wo die Beiträge erscheinen sollen.

Ich denke, Sie können den folgenden Code direkt in das HTML einer WordPress-Vorlage einfügen, und zwar genau dort, wo die Beiträge angezeigt werden sollen. Vergessen Sie nicht, die Zeile mit der URL des Forums zu aktualisieren. Falls es nicht funktioniert, lassen Sie es mich wissen. (Es wurde nicht getestet.)

Klicken Sie hier für den Code
<div id="forumTopics"></div>
<script>
// Geben Sie hier die URL Ihres Forums ein, um es auf Ihrem eigenen Forum zu testen
const baseForumURL = `https://forum.example.com`;

// Wie viele Themen angezeigt werden sollen
const numTopics = 6;

const targetEl = document.getElementById("forumTopics");
// Falls die Beiträge aus irgendeinem Grund nicht geladen werden, können Sie einen Link zum Forum anzeigen
targetEl.innerHTML = `<a class="link-to-discourse" href="${baseForumURL}/">Neueste Forenbeiträge anzeigen</a>`;

function renderTemplate(topicsArr) {
    const items = topicsArr.map(
        (topic) => `<li><a href="${topic[1]}" target="_blank">${topic[0]}</a></li>`
    );

    targetEl.innerHTML = `<ul>${items.join("\n")}</ul>`;
}

// Fügen Sie `.json` an jede Themenliste an
fetch(`${baseForumURL}/latest.json`)
    .then((res) => res.json())
    .then((json) => {
        const topics = json.topic_list.topics
            .slice(0, numTopics)
            .map((t) => [
                t.title,
                `${baseForumURL}/t/${t.slug}/${t.id}`,
            ]);

        renderTemplate(topics);
    });
</script>
3 „Gefällt mir“

Danke, ich schätze den vollständigen Code-Auszug.

Nach dem ersten Test wird nur ein Link angezeigt. Ich vermute jedoch, dass CORS deaktiviert ist, daher werde ich meinen Host bitten, dies zu aktivieren.

Wie kann ich das Skript meanwhile so einstellen, dass es nur Beiträge mit einem bestimmten Tag und aus einer bestimmten Kategorie anzeigt?

2 „Gefällt mir“

Ich bin mir nicht sicher, aber ich denke, das Format lautet:
https://forum.example.com/tags/c/<category_name>/<tag_name>

Beispiel: Die Kategorie ist „support

3 „Gefällt mir“

Und wenn ich 5 Themen direkt in die Discourse-Instanz einbetten möchte?

Ich erstelle ein Thema, mache es zu einem Wiki und veröffentliche es als Seite. Wie kann ich die fünf neuesten Themen aus einer bestimmten Kategorie/einem bestimmten Tag einbetten oder die Vorlage verwenden, die diese Funktion unterstützt?

Vielen Dank.

1 „Gefällt mir“

Wie lautet der Query-Parameter für Top-Themen? Ich habe order="top" versucht, aber es werden nicht dieselben Top-Themen zurückgegeben wie im Forum für einen bestimmten Zeitraum. Wie kann ich das Forum-Filterergebnis replizieren? Wo kann ich nach den Attributwerten nachschauen, die die Filteroptionen von Discourse annehmen? Danke!

2 „Gefällt mir“

Ist es möglich, den Schriftstil des eingebetteten Inhalts zu ändern? Ich habe CSS-Selektoren wie d-topics-list iframe html .topics-list .topic-list-item ausprobiert, aber ohne Erfolg. Ich danke im Voraus für einen Hinweis!

2 „Gefällt mir“