Incorporare un elenco di argomenti Discourse in un altro sito

Se scarichi le ultime build di Discourse, otterrai la possibilità di incorporare elenchi di argomenti in altri siti tramite un semplice JavaScript e HTML.

Il caso d’uso tipico è un blog o un altro sito basato sui contenuti, dove desideri un widget sul lato dello schermo che elenchi gli argomenti. Puoi filtrare per categoria, tag o qualsiasi altra opzione di filtro pubblica disponibile.

Come incorporare un elenco di argomenti

Per prima cosa, devi abilitare l’impostazione del sito embed topics list.

Successivamente, nel tuo HTML aggiungi un tag <script> che includa il JavaScript necessario per incorporare gli argomenti di Discourse. Puoi aggiungerlo ovunque aggiungi normalmente gli script. Ad esempio:

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

Sostituisci URL con l’indirizzo del forum, inclusa la sottocartella se esiste.

Dopo di ciò, nel <body> del tuo documento HTML, aggiungi un tag d-topics-list per indicare l’elenco degli argomenti che desideri incorporare. Anche qui dovrai sostituire URL con il tuo URL di base:

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

Qualsiasi attributo che fornisci (tranne discourse-url, che è obbligatorio) verrà convertito nei parametri di query per la ricerca degli argomenti. Quindi, se volessi cercare argomenti per tag, potresti fare così:

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

Se un parametro di query contiene caratteri di sottolineatura, convertili in trattini. Nell’esempio sopra, avrai probabilmente notato che per_page è diventato per-page.

In contesti SameSite (cioè quando il sito che incorpora e il tuo forum condividono un dominio padre), Discourse saprà se hai effettuato l’accesso al forum e mostrerà i risultati di conseguenza. Non sorprenderti se vedi categorie sicure e simili quando sei loggato: gli utenti anonimi non potranno farlo!

Elenco dei parametri

template: Può essere complete o basic (predefinito). Mentre basic è solo un elenco di titoli degli argomenti, complete include titolo, nome utente, avatar dell’utente, data di creazione e miniatura dell’argomento.

per-page: Numero. Controlla quanti argomenti restituire.

category: Numero. Restringe gli argomenti a una singola categoria. Passa l’id della categoria di destinazione.

allow-create: Booleano. Se abilitato, l’incorporamento avrà un pulsante “Nuovo argomento”.

tags: Stringa. Restringe gli argomenti a quelli associati a questo tag.

top_period: Uno tra all, yearly, quarterly, monthly, weekly, daily. Se abilitato, restituirà gli argomenti “Top” del periodo.

Esempi

Ho creato un sito di esempio qui:

https://embed.eviltrout.com

Dovresti essere in grado di visualizzare il codice sorgente nel tuo browser per vedere il codice, ma anche l’intero sorgente è su GitHub:

Questa è una funzionalità nuovissima, quindi qualsiasi feedback o richiesta sarebbe apprezzato.

Stile dell’elenco

Puoi utilizzare la nostra funzionalità tema esistente per aggiungere stili personalizzati per l’elenco incorporato.

Ad esempio, per impostazione predefinita, il nostro elenco incorporato che utilizza il modello complete appare così:

Se desideri che appaia, ad esempio, come una griglia, puoi aggiungere SCSS personalizzato a Tema > Comune > CSS incorporato:

.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%;
      }
    }
  }
}

Il che lo farà apparire così:

95 Mi Piace

Ehi ragazzi! Stiamo cercando di far sì che i link si aprano in una nuova scheda (quindi target=“_blank” invece di target=“_parent”). C’è un modo semplice per farlo dato l’iframe?

2 Mi Piace

Non so se sia quello che stai cercando, ma qualcosa di simile dovrebbe funzionare per aprire i link in nuove schede. È necessario abilitare CORS per il dominio esterno. L’ho provato in questo modo perché volevo filtrare un argomento fissato.

// `fetch` potrebbe richiedere un 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>`;
}

// aggiungi `.json` a qualsiasi elenco di argomenti
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 Mi Piace

Grazie! Mi piace questa idea, ma basandomi su questo post What are the risks of enabling Cross-origin resource sharing (DISCOURSE_ENABLE_CORS), penso che abilitare CORS non sia la scelta migliore.

2 Mi Piace

Dovresti abilitare CORS solo per i siti di cui ti fidi. Abilitare CORS per ogni origine vanifica lo scopo stesso.

6 Mi Piace

Ho abilitato CORS solo per gli altri siti di mia proprietà. L’obiettivo era caricare un elenco di argomenti del forum sui nostri altri siti tramite codice frontend. Quel metodo probabilmente non funzionerebbe per permettere a siti casuali di incorporare i post.

Modifica: se copi/incollate quel codice, fate attenzione a .slice(1, 6) perché rimuove uno degli argomenti. (Credo che fosse l’argomento fissato che volevo eliminare.)

3 Mi Piace

Bene, allora possiamo provare questa opzione. Al momento non ho nessun sito oltre a localhost (durante i test), ed è per questo che esitavo ad aggiungerlo. Ma se riesco a trovare qualcuno che abbia un posto a disposizione, possiamo provare. Grazie per il tuo aiuto!

4 Mi Piace

Ciao @j127,

stiamo affrontando lo stesso problema e vogliamo aprire i link in una nuova scheda.
Solo una domanda veloce.

Dove inserisci esattamente il codice che hai fornito?

@eviltrout Hai idea del motivo per cui, nel mio caso, gli stili CSS non vengono visualizzati?

2 Mi Piace

Quel codice è solo un esempio rapido dell’idea generale. Non credo che fetch funzioni in tutti i browser. Posso riscriverlo in ES5 se preferisci.

Il tuo sito è WordPress o una sorta di WordPress headless?

4 Mi Piace

Sembra funzionare su tutti i browser moderni e Discourse non supporta più IE11.

4 Mi Piace

Il mio sito è semplicemente WordPress standard, non headless.

1 Mi Piace

Posso usare questo per incorporare un elenco di argomenti di Discourse in un’altra istanza di Discourse? O esiste un modo più intelligente per farlo?

Il mio caso d’uso è creare un “ponte” tra due istanze come misura temporanea fino a quando non potranno essere unite in futuro. Sarebbe ideale automatizzare e rendere dinamico questo processo.

2 Mi Piace

Se non ti importa di IE, quel frammento dovrebbe funzionare. (CORS deve essere abilitato per il dominio esterno nelle impostazioni di Discourse.)

Per provarlo, apri una qualsiasi pagina di questo forum e incolla il frammento sottostante nella console del browser. Ho modificato l’elemento di destinazione in document.body, così sostituirà l’intera pagina con l’elenco dei argomenti del forum. Per un sito reale, modifica semplicemente l’elemento di destinazione in document.getElementById("#someId") e inserisci un div con quell’ID da qualche parte nella pagina. Lo script lo riempirà con l’elenco degli argomenti.

// `fetch` potrebbe richiedere un polyfill a meno che non ti interessi di IE
// const targetEl = document.getElementById("forumTopics");

// questo sostituisce il body della pagina, solo come esempio
const targetEl = document.body;

// inserisci qui l'URL del tuo forum per provarlo sul tuo forum
const baseForumURL = `https://meta.discourse.org`;

// quanti argomenti vuoi mostrare
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>`;
}

// aggiungi `.json` a qualsiasi elenco di argomenti
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);
    });

Esempio: se il div di destinazione da qualche parte sul tuo sito WP appare così

<div id="forumTopics">
    <!-- gli argomenti del forum appariranno qui -->
</div>

allora il JavaScript può puntare a quell’ID in questo modo:

// cerca questa riga nell'esempio originale che ho pubblicato
const targetEl = document.getElementById("forumTopics");
4 Mi Piace

Con questo intendi il codice nel primo post o il frammento nel post 50? E no, non mi interessa IE. Non c’è bisogno di adattarsi a quel dinosauro :).
Nel mio caso il CSS non viene caricato per il mio frammento in nessun browser.

Quindi questo è JS e devo mettere il tag <script> intorno ad esso quando lo implemento su WordPress, corretto?

2 Mi Piace

È passato un po’ di tempo dall’ultima volta che ho usato WordPress. Si tratta di qualcosa che stai aggiungendo all’HTML del tema? Se sì, allora avvolgi il mio codice in un tag script e inserisci il div dove vuoi che appaiano i post.

Penso che tu possa inserire direttamente il codice qui sotto nell’HTML di un template di WordPress, nel punto in cui desideri che i post siano visualizzati. Assicurati di aggiornare la riga contenente l’URL del forum. Se non funziona, fammelo sapere. (Non è stato testato.)

Clicca qui per il codice
<div id="forumTopics"></div>
<script>
// inserisci qui l'URL del tuo forum per testarlo sul tuo forum
const baseForumURL = `https://forum.example.com`;

// quanti argomenti vuoi mostrare
const numTopics = 6;

const targetEl = document.getElementById("forumTopics");
// Se i post non vengono caricati per qualche motivo, puoi mostrare un link al forum
targetEl.innerHTML = `<a class="link-to-discourse" href="${baseForumURL}/">Visualizza gli ultimi post del forum</a>`;

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

// aggiungi `.json` alla fine di qualsiasi elenco di argomenti
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 Mi Piace

Grazie, apprezzo il frammento completo

Dopo il test iniziale, viene visualizzato solo un link. Ma credo che CORS sia disabilitato, quindi chiederò al mio host di abilitarlo.
Nel frattempo, come posso fare in modo che lo script mostri solo i post con un tag specifico e da una categoria specifica?

2 Mi Piace

Non sono sicuro, ma penso che il formato sia
https://forum.example.com/tags/c/<nome_categoria>/<nome_tag>

Esempio: la categoria è “supporto” e il tag è “css”:
https://meta.discourse.org/tags/c/supporto/css

Per convertirlo in JSON, aggiungi .json alla fine:
https://meta.discourse.org/tags/c/supporto/css.json

Quindi nella funzione fetch, invece di /latest.json, usa qualcosa come /tags/c/supporto/css.json.

(Non testato.)

3 Mi Piace

E se volessi incorporare 5 argomenti nell’istanza di Discourse stessa?

Creo un argomento, lo impostò come wiki e lo pubblico come pagina. Come posso incorporare i cinque argomenti più recenti da una categoria o tag specifico, oppure utilizzare il modello supportato da questa funzione?

Grazie.

1 Mi Piace

Qual è il parametro di query per gli argomenti principali? Ho provato order="top", ma non restituisce gli argomenti principali nello stesso modo in cui fa il forum in base a un determinato periodo. Come posso replicare il risultato del filtro del forum? Dove posso consultare i valori degli attributi che le opzioni di filtro di Discourse accettano? Grazie!

2 Mi Piace

È possibile modificare lo stile del font del contenuto incorporato? Ho provato selettori CSS come d-topics-list iframe html .topics-list .topic-list-item senza successo. Grazie in anticipo per il consiglio!

2 Mi Piace