Intégration d'une liste de sujets Discourse dans un autre site

Si vous téléchargez les dernières versions de Discourse, vous bénéficierez de la possibilité d’intégrer des listes de sujets sur d’autres sites grâce à quelques lignes simples de JavaScript et HTML.

Le cas d’usage typique est un blog ou tout autre site axé sur le contenu, où vous souhaitez un widget sur le côté de l’écran listant des sujets. Vous pouvez filtrer par catégorie, par tag, ou par l’une des autres options de filtrage publiques disponibles.

Comment intégrer une liste de sujets

Tout d’abord, vous devez activer le paramètre du site embed topics list.

Ensuite, dans votre HTML, ajoutez une balise <script> incluant le JavaScript nécessaire à l’intégration des sujets Discourse. Vous pouvez l’ajouter là où vous ajoutez habituellement vos scripts. Par exemple :

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

Remplacez URL par l’adresse du forum, en incluant le sous-dossier s’il existe.

Après cela, dans le <body> de votre document HTML, ajoutez une balise d-topics-list pour indiquer la liste des sujets que vous souhaitez intégrer. Vous devrez également remplacer URL par votre URL de base ici :

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

Tous les attributs que vous fournissez (à l’exception de discourse-url qui est obligatoire) seront convertis en paramètres de requête pour la recherche de sujets. Ainsi, si vous souhaitez rechercher des sujets par tag, vous pouvez faire ceci :

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

Si un paramètre de requête contient des underscores, convertissez-les en tirets. Dans l’exemple ci-dessus, vous avez probablement remarqué que per_page est devenu per-page.

Dans les contextes SameSite (c’est-à-dire lorsque le site d’intégration et votre forum partagent un domaine parent), Discourse saura si vous êtes connecté au forum et affichera les résultats en conséquence. Ne soyez pas surpris de voir des catégories sécurisées et autres lorsque vous êtes connecté — les utilisateurs anonymes n’y auront pas accès !

Liste des paramètres

template : Soit complete ou basic (par défaut). Alors que basic n’affiche qu’une liste de titres de sujets, complete ajoute le titre, le nom d’utilisateur, l’avatar de l’utilisateur, la date de création et la miniature du sujet.

per-page : Nombre. Contrôle le nombre de sujets à retourner.

category : Nombre. Restreint les sujets à une seule catégorie. Passez l’id de la catégorie cible.

allow-create : Booléen. Si activé, l’intégration affichera un bouton « Nouveau sujet ».

tags : Chaîne de caractères. Restreint les sujets à ceux associés à ce tag.

top_period : L’un de all, yearly, quarterly, monthly, weekly, daily. Si activé, retourne les sujets « Top » de la période.

Exemples

J’ai créé un site d’exemple ici :

https://embed.eviltrout.com

Vous devriez pouvoir afficher le code source dans votre navigateur pour voir le code, mais l’intégralité du code source est également disponible sur GitHub :

Il s’agit d’une toute nouvelle fonctionnalité, donc tout retour ou demande est apprécié.

Styliser la liste

Vous pouvez utiliser notre fonctionnalité de thème existante pour ajouter des styles personnalisés à la liste intégrée.

Par exemple, par défaut, notre liste intégrée utilisant le modèle complete ressemble à ceci :

Si vous souhaitez qu’elle ressemble, par exemple, à une grille, vous pouvez ajouter du SCSS personnalisé dans Thème > Commun > CSS intégré :

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

Ce qui donnera un résultat semblable à ceci :

95 « J'aime »

Salut les amis ! Nous souhaitons que les liens s’ouvrent dans un nouvel onglet (c’est-à-dire target=“_blank” au lieu de target=“_parent”). Existe-t-il un moyen simple de le faire étant donné l’iframe ?

2 « J'aime »

Je ne sais pas si c’est ce que vous cherchez, mais quelque chose comme ceci devrait fonctionner pour ouvrir les liens dans de nouveaux onglets. Le CORS doit être activé pour le domaine externe. Je l’ai fait de cette manière car je voulais filtrer un sujet épinglé.

// `fetch` peut nécessiter un polyfill
const targetEl = document.getElementById("forumTopics");

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

// ajoutez `.json` à n'importe quelle liste de sujets
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 « J'aime »

Merci ! J’aime bien cette idée, mais d’après ce post What are the risks of enabling Cross-origin resource sharing (DISCOURSE_ENABLE_CORS), je pense que l’activation de CORS n’est pas la meilleure solution.

2 « J'aime »

Vous ne devez activer CORS que pour les sites de confiance. L’activation de CORS pour toutes les sources va à l’encontre de son objectif.

6 « J'aime »

J’ai activé CORS uniquement pour les autres sites que je contrôle. L’objectif était d’afficher une liste de sujets de forum sur nos autres sites à l’aide de code frontend. Cette méthode ne fonctionnerait probablement pas pour permettre à des sites aléatoires d’intégrer les publications.

Édition : si vous copiez/collez ce code, faites attention à .slice(1, 6) car il supprime l’un des sujets. (Je pense qu’il s’agissait du sujet épinglé que je voulais retirer.)

3 « J'aime »

Super, c’est quelque chose qu’on peut essayer alors – pour l’instant, je n’ai pas de site autre que localhost (pendant les tests), c’est pourquoi j’hésitais à l’ajouter. Mais si je trouve quelqu’un qui a un endroit, on peut essayer. Merci pour ton aide !

4 « J'aime »

Salut @j127,

nous rencontrons actuellement le même problème et souhaitons ouvrir les liens dans un nouvel onglet.
Une petite question rapide.

Où exactement placez-vous le code que vous avez fourni ?

@eviltrout, avez-vous une idée de pourquoi, dans mon cas, les styles CSS n’apparaissent pas ?

2 « J'aime »

Ce code n’est qu’un exemple rapide de l’idée générale. Je ne pense pas que fetch fonctionne dans tous les navigateurs. Je peux le réécrire en ES5 si tu le souhaites.

Ton site est-il WordPress ou une sorte de WordPress headless ?

4 « J'aime »

Cela semble fonctionner sur tous les navigateurs modernes, et Discourse ne prend plus en charge IE11.

4 « J'aime »

Mon site est un WordPress classique, pas en headless.

1 « J'aime »

Puis-je utiliser cela pour intégrer une liste de sujets Discourse dans une autre instance Discourse ? Ou existe-t-il une méthode plus intelligente pour le faire ?

Mon cas d’usage consiste à créer un « pont » entre deux instances à titre temporaire, en attendant qu’elles puissent être fusionnées à l’avenir. Il serait idéal que ce processus soit automatisé et dynamique.

2 « J'aime »

Si vous ne vous souciez pas d’IE, ce bout de code devrait fonctionner. (CORS doit être activé pour le domaine externe dans les paramètres de Discourse.)

Pour le tester, ouvrez n’importe quelle page de ce forum et collez le bout de code ci-dessous dans la console du navigateur. J’ai modifié l’élément cible en document.body, de sorte qu’il remplacera toute la page par la liste des sujets du forum. Pour un vrai site, modifiez simplement l’élément cible en document.getElementById("#someId") et ajoutez un div avec cet ID quelque part sur la page. Le script le remplira avec la liste des sujets.

// `fetch` peut nécessiter un polyfill sauf si vous ne vous souciez pas d'IE
// const targetEl = document.getElementById("forumTopics");

// ceci remplace le corps de la page, juste à titre d'exemple
const targetEl = document.body;

// mettez l'URL de votre forum ici pour le tester sur votre propre forum
const baseForumURL = `https://meta.discourse.org`;

// nombre de sujets à afficher
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>`;
}

// ajoutez `.json` à n'importe quelle liste de sujets
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);
    });

Exemple : si le div cible quelque part sur votre site WP ressemble à ceci

<div id="forumTopics">
    <!-- les posts du forum apparaîtront ici -->
</div>

alors le JavaScript peut cibler cet ID comme ceci :

// cherchez cette ligne dans l'exemple original que j'ai posté
const targetEl = document.getElementById("forumTopics");
4 « J'aime »

Par là, vous voulez dire le code du premier message ou l’extrait du message 50 ? Et non, je ne me soucie pas d’IE. Inutile de s’adapter à ce dinosaure :).
Dans mon cas, le CSS n’est chargé pour aucun navigateur pour mon extrait.

Donc c’est du JS et je dois l’entourer de la balise <script> lors de son implémentation dans WordPress, c’est bien ça ?

2 « J'aime »

Ça fait un moment que je n’ai pas utilisé WordPress. Est-ce que vous l’ajoutez au HTML d’un thème ? Si oui, enveloppez mon code dans une balise script et placez le <div> où vous voulez que les publications apparaissent.

Je pense que vous pouvez intégrer directement le code ci-dessous dans le HTML d’un modèle WordPress à l’endroit où vous souhaitez voir les publications. Assurez-vous de mettre à jour la ligne contenant l’URL du forum. Si cela ne fonctionne pas, faites-le-moi savoir. (C’est non testé.)

Cliquez ici pour le code
<div id="forumTopics"></div>
<script>
// Remplacez l'URL de votre forum pour tester sur votre propre instance
const baseForumURL = `https://forum.example.com`;

// Nombre de sujets à afficher
const numTopics = 6;

const targetEl = document.getElementById("forumTopics");
// Si les publications ne se chargent pas, vous pouvez afficher un lien vers le forum
targetEl.innerHTML = `<a class="link-to-discourse" href="${baseForumURL}/">Voir les dernières publications du 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>`;
}

// Ajoutez `.json` à la liste des sujets
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 « J'aime »

Merci, j’apprécie le code complet.

Après le test initial, seul un lien s’affiche. Mais je pense que CORS est désactivé, donc je vais demander à mon hébergeur de l’activer.
En attendant, comment puis-je faire en sorte que le script n’affiche que les articles avec un tag spécifique et d’une catégorie spécifique ?

2 « J'aime »

Je ne suis pas sûr, mais je pense que le format est
https://forum.example.com/tags/c/<catgory_name>/<tag_name>

Exemple : la catégorie est « support » et l’étiquette est « css » :
https://meta.discourse.org/tags/c/support/css

Pour le convertir en JSON, ajoutez .json à la fin :
https://meta.discourse.org/tags/c/support/css.json

Ainsi, dans la fonction fetch, au lieu de /latest.json, utilisez quelque chose comme /tags/c/support/css.json.

(Non testé.)

3 « J'aime »

Et si je veux intégrer 5 sujets directement dans l’instance Discourse ?

Je crée un sujet, je le transforme en wiki, puis je le publie en tant que page. Comment puis-je intégrer les cinq derniers sujets d’une catégorie ou d’un tag spécifique, ou utiliser le modèle que cette fonctionnalité prend en charge ?

Merci.

1 « J'aime »

Quel est le paramètre de requête pour les sujets principaux ? J’ai essayé order="top", mais cela ne renvoie pas les sujets principaux de la même manière que le forum, selon une période donnée. Comment puis-je reproduire le résultat du filtre du forum ? Où puis-je consulter les valeurs d’attribut que prennent les options de filtre de Discourse ? Merci !

2 « J'aime »

Est-il possible de modifier le style de police du contenu intégré ? J’ai essayé des sélecteurs CSS comme d-topics-list iframe html .topics-list .topic-list-item sans succès. Merci d’avance pour votre aide !

2 « J'aime »