Obtenir l'ID du sujet lorsque la page d'affichage du sujet se charge

Dans mon thème, lorsqu’une page d’affichage d’un sujet est chargée, je dois récupérer l’ID de ce sujet (et son nom si possible, mais l’ID suffirait).

J’utilise ensuite ces informations dans mon thème pour effectuer un appel API afin d’obtenir des informations sur le sujet (via un appel à un endpoint du type nom-du-forum/t/nom-du-sujet/id.json…)

Comment puis-je récupérer l’ID du sujet lorsque la page d’affichage du sujet se charge ?

Les méthodes évidentes ne suffisent pas

La solution évidente consiste à utiliser window.location.href ou window.location.pathname pour extraire les informations de l’URL. Le problème est que l’URL de la page d’affichage d’un sujet peut prendre différentes formes. Souvent, elle ressemble à ceci :
nom-du-forum/t/nom-du-sujet/id-du-sujet

Si c’était toujours le cas, l’utilisation de window.location.pathname fonctionnerait bien, me donnant “t/nom-du-sujet/id-du-sujet”.

MAIS, parfois, l’URL de la page d’affichage d’un sujet ajoute également l’ordre de la catégorie du sujet, de sorte que l’URL devient : nom-du-forum/t/nom-du-sujet/id-du-sujet/index-de-la-catégorie

L’utilisation de window.location.pathname est donc insuffisante, car je ne sais pas programmatiquement si le dernier paramètre sera l’ID du sujet ou l’index de la catégorie.

Il pourrait exister une solution en utilisant des expressions régulières, mais cela nécessite une maîtrise avancée de ces dernières. Il pourrait aussi y avoir une façon de résoudre ce problème avec jQuery en examinant les éléments de la page qui pourraient fournir l’ID, mais je n’ai pas encore réussi à faire fonctionner cette approche.

Quand et où cela se produit-il ? Je n’ai pas réussi à le trouver.

Quoi qu’il en soit, lorsque ce sujet se charge, il possède un élément link :

<link rel="canonical" href="https://meta.discourse.org/t/get-topic-id-when-the-topic-show-page-loads/155620" />

Peut-être pouvez-vous le récupérer à partir de là. :slight_smile:

Sur mon forum, cela se produit en fait la plupart du temps lorsque vous cliquez sur un sujet. La dernière partie de l’URL correspond au numéro du sujet dans la catégorie, si vous avez cliqué sur le sujet depuis une catégorie. Peut-être s’agit-il d’un paramètre dans Discourse ? Cela ne semble pas se produire sur Meta-, mais je ne pense pas que je fasse quoi que ce soit de spécial pour provoquer cela sur mon forum.

Je ne peux pas toujours compter sur ce comportement, car si un sujet est le premier de la catégorie, l’index de la catégorie n’est pas ajouté. Donc, autant que je puisse en juger, il n’existe pas actuellement de bonne méthode pour savoir s’il apparaîtra dans l’index de la catégorie ou non.

Récupérer l’ID depuis un div fonctionne, mais c’est malheureusement beaucoup plus lent que de pouvoir l’obtenir directement depuis l’URL ou par un autre moyen direct. Au cas où il n’existerait pas d’autre solution, connaissez-vous la syntaxe jQuery pour récupérer la valeur de ce lien (href) ?

Essayez

api.onPageChange((url, title) => {
    var res = url.match(/\/t\/(.*?)\/(\w+)/);
    if (res && res[2] > 0) {
        console.log(res[2]);
    }
});
2 « J'aime »

Que cherchez-vous à accomplir ?

Cela pourrait fonctionner, mais ce n’est pas très efficace, car vous effectuez une requête AJAX supplémentaire pour chaque affichage de page de sujet par chaque utilisateur, y compris les anonymes. Cela générera donc une charge inutile importante sur votre serveur.

Pas vraiment. L’URL d’un sujet ressemble à ceci :

votre.site.com/t/titre_sujet/id_sujet/numero_post_lien(optionnel)

Il n’y a pas d’ordre de catégorie dans l’URL dans une installation Discourse par défaut.

Nous pouvons vous aider si vous décrivez le problème que vous essayez de résoudre plutôt que de décrire vos solutions pour y parvenir.

3 « J'aime »

Cela fonctionne ! Merci beaucoup. Je comprends que, grâce à la méthode match ici, vous parcourez l’URL pour obtenir, je suppose, la 3e occurrence du “/”, car l’ID se produit toujours après le troisième “/” dans l’URL, qui renvoie le format “/t/nom/id/autrechose”. Pouvez-vous fournir quelques informations sur la façon dont votre expression régulière fait cela ? Cela serait très utile dans mon apprentissage des expressions régulières.

Merci pour l’information. C’est donc le “numero_post_lien” qui semble apparaître parfois et perturbe mon appel API. Vous dites ici qu’il est “optionnel”—y a-t-il un moyen de s’assurer qu’il ne s’affiche jamais ?

Lorsqu’un utilisateur visite la page d’affichage d’un sujet, je souhaite :

  1. Connaître programmatiquement tous les tags associés à ce sujet. Notez que certains tags sont masqués de la vue de l’utilisateur.
  2. Avoir un bouton sur la page du sujet qui ajoute un certain tag masqué au sujet lorsqu’il est cliqué (si le tag masqué n’est pas encore présent), et supprime le tag masqué lorsqu’il est cliqué (si le tag masqué est déjà présent).

Tout cela est simple à réaliser en utilisant l’API Admin et javascript/jquery (en supposant que je puisse obtenir la bonne URL de sujet à utiliser dans les appels API).

Je pense que la seule autre façon de faire ce genre de chose serait de créer un plugin où je plonge profondément dans 1. ember, 2. rails et 3. la base de code de Discourse. J’ai examiné les principaux articles et documents de Discourse sur la façon de faire cela, mais j’ai trouvé cela lent car il faut vraiment comprendre ces 3 éléments. Donc, pour l’instant, je me suis concentré sur l’approche API.

Je serais intéressé d’entendre s’il existe une autre façon de faire cela qui réduirait la charge du serveur.

J’aurais certainement pu vous aider avec le code s’il s’agissait d’une solution en une seule étape, mais plusieurs étapes sont nécessaires. Si vous avez besoin d’aide sous forme de consultation pour réaliser un travail ou apprendre à écrire vous-même des composants de thème, veuillez publier sur le marketplace et je vous contacterai.

Merci, mais il est utile de recevoir des conseils à chaque étape. Par exemple, en dehors de l’utilisation de l’API, comment puis-je connaître tous les tags associés à un sujet ?

1 « J'aime »

Un objet de sujet complet est chargé côté client lorsque vous chargez la page du sujet. Maintenant, si vous souhaitez l’utiliser, vous devez ajouter votre propre code au modèle pour exploiter ces données, ou « réouvrir » des classes pour utiliser les données chargées (c’est-à-dire essentiellement créer vos propres propriétés calculées et les utiliser dans le modèle). Il contient la plupart des données dont vous avez besoin (probablement même plus que nécessaire) chargées côté client sans appels API supplémentaires. Vous aurez également besoin de plugin-outlet pour insérer votre propre balisage dans les modèles existants.

Il serait utile que vous parcouriez la base de code/métadonnées pour les termes que j’ai utilisés ci-dessus. Je serai heureux de vous aider ici si vous êtes bloqué, dans la mesure du possible en termes de temps. Salutations.

Merci. Je connais déjà certains des concepts de base que vous mentionnez, mais il y a un point qui me bloque (et je parie que ce genre de problème bloque beaucoup de gens) :

Sur la page d’affichage du sujet, le modèle /templates/components/topic-category.hbs est chargé. C’est ce qui affiche la catégorie ainsi que l’étiquette sous le titre du sujet.

Dans topic-category, il liste topic.tags. C’est donc l’élément clé dont j’ai besoin pour démarrer.

Voici où je bloque : Comment puis-je récupérer ces informations topic.tags dans mon JavaScript ?

Par exemple, si je voulais simplement faire un console.log du contenu de topic.tags, comment procéder ?


Je sais comment surcharger les modèles. Par exemple, dans un thème, je pourrais placer un fichier à l’adresse discourse/templates/components/topic-category.hbs et y réimprimer le modèle, en ajoutant les modifications que je souhaite apporter à la vue. (J’utilise la structure de fichiers séparés décrite ici).

Dans mon thème, je sais aussi comment placer du JavaScript à l’adresse theme/initializers/initializer-file.js.es6.

Et je peux faire interagir les deux avec un peu de jQuery. Par exemple, je pourrais placer topic.tags dans une div du modèle, puis y accéder dans mon initialiseur avec jQuery en récupérant le contenu de cette div.

Mais c’est une solution détournée. Comment puis-je obtenir directement les informations topic.tags pour pouvoir les analyser et les manipuler ?

1 « J'aime »

Je ferais un console.log de l’ensemble de topic et je trouverais quelle clé est nécessaire. Pour les interactions avec jQuery, elles doivent être effectuées depuis l’intérieur des composants. didInsertElement est le hook du composant qui est utile ici.

À en juger par ce que vous dites, il semble que vous ayez besoin d’une propriété calculée dépendant de topic.tags qui renvoie votre manipulation de celle-ci dans le contrôleur ou le composant concerné. Elle est utilisable directement dans le modèle. De plus, ne lâchez pas prise avec ces éléments. Cela prendra du temps, mais cela en vaudra vraiment la peine, et bien au-delà de ce que vous pourriez espérer.

Que voulez-vous dire par « à l’intérieur des composants » — quel fichier dois-je utiliser pour le code jQuery ? (Dans mon thème, je peux utiliser jQuery dans le fichier theme/intializers/intializer-file.js.es6, mais cela ne semble pas être « à l’intérieur » du composant)

Dans quel fichier placer le code didInsertElement ?

1 « J'aime »

À ce stade, vous devriez vraiment consulter les guides Ember. Un composant est un ensemble de fonctionnalités que vous pouvez déployer et attacher à d’autres éléments.

2 « J'aime »

Merci, les gars, toutes ces informations sont utiles. J’examine les guides et la documentation générale. Il serait également très utile de savoir quel est le nom du fichier dans lequel je dois placer le code (i) jQuery et (ii) didInsertElement. Avoir ce genre d’informations concrètes serait d’une grande aide pour orienter la suite de l’examen.

1 « J'aime »

Components = composants Ember.

Vous pouvez reopen toutes sortes de classes Ember et y injecter votre code. Vous devrez consulter des plugins ou des thèmes qui le font pour mieux comprendre.

@JQ331 Comme tu le sais probablement, j’ai trouvé des expressions rationnelles sur Google et je les ai essayées ici ! Tu peux entrer des variantes pour obtenir les meilleurs résultats.

1 « J'aime »

Cela ressemble à du domaine d’extension pour moi.

Si les tags sont masqués pour l’utilisateur normal, comment un appel supplémentaire aiderait-il ? Le sérialiseur devrait dans tous les cas masquer ces tags à l’utilisateur normal. Sinon, vous exposez une faille de sécurité du contenu.

Si vous prenez tout ce mal pour contourner les limitations des modifications uniquement côté front-end, je vous suggère de mordre la balle et de regarder la possibilité de construire cela dans une extension où vous pourriez sérialiser en une seule fois au lieu d’avoir une configuration désordonnée avec des appels supplémentaires.

1 « J'aime »

Cela a du sens. J’aimerais en savoir plus sur l’utilisation du sérialiseur : bien que le sérialiseur soit l’une des étapes les plus importantes dans un plugin Discourse, je n’ai pas encore trouvé de documentation présentant des exemples de base de son utilisation. Connaissez-vous une telle documentation ?

Lorsque vous dites qu’un sérialiseur devrait masquer ces balises, pourriez-vous fournir un peu de pseudo-code pour illustrer ce que vous voulez dire ? (Ce n’est pas grave si cela ne fonctionne pas parfaitement ; je cherche simplement à comprendre le concept.)

Voici :

C’est un peu comme la musique jazz : les meilleures pratiques existent déjà dans le paysage des plugins open source, tout comme les enregistrements. Ne vous attendez pas à un guide parfait expliquant comment tout faire ; vous devez souvent vous mettre dans le bain (euh) en apprenant des œuvres antérieures.

Trouvez un plugin dans #plugin qui réalise quelque chose de fonctionnellement similaire, ou un élément de ce que vous souhaitez faire, et examinez le code pour voir comment il procède. Il en va de même pour le code source de Discourse, que vous pouvez utiliser comme référence ultime en matière de « meilleures pratiques », notamment en ce qui concerne Discourse.

Clonez un plugin existant localement et essayez de modifier quelques éléments pour expérimenter.

Les sérialiseurs se contentent de filtrer ce qui est envoyé depuis les contrôleurs/modèles et peuvent également effectuer certaines manipulations de base.

1 « J'aime »

Voici un exemple tiré de la source : discourse/app/serializers/concerns/topic_tags_mixin.rb at 888e68a1637ca784a7bf51a6bbb524dcf7413b13 · discourse/discourse · GitHub

  def tags
    # L'appel de la méthode `pluck` avec `includes` provoque des requêtes N+1
    tags = topic.tags.map(&:name)

    if scope.is_staff?
      tags
    else
      tags - scope.hidden_tag_names
    end
  end

Vous pouvez voir ici qu’il exclut les balises masquées pour les utilisateurs non membres du personnel.

2 « J'aime »