← Voir tous les articlesGrégory TAUDINGrégory TAUDIN - 19 avr. 2022

Strapi: Comment créer un service pour gérer les documents d'aide ?

Strapi market logo

Bon retour parmi nous !

Nos données sont maintenant prêtes à être importées dans la collection "Help". Nous devons créer un nouveau service pour gérer les opérations de création, lecture, mise à jour et suppression (C.R.U.D). C'est parti !

Collection update

La première étape consiste à mettre à jour le fichier "schema.json" de la collection "Help" pour y ajouter des propriétés utiles. Ouvrez-le dans "api/src/plugins/awesome-help/server/content-types/help" et ajoutez les propriétés suivantes :

Github code
  • La propriété "contentType" représente le Content-Type exploré, par exemple : "api::article.article".
  • La propriété "path" définit le chemin actuel du champ exploré. Il s'agit d'un champ calculé.
  • La propriété "helpContent" contiendra votre texte d'aide contextuelle.
  • La propriété "fieldName" est le nom du champ exploré.
  • La propriété "containerType" définit le type de conteneur actuel du champ exploré (voir les valeurs ci-dessous).
  • La propriété "zoneName" définit le nom de la zone actuelle du champ exploré.
  • La propriété "componentName" définit le nom du composant du champ exploré.

Pour comprendre comment fonctionne le service "parser", prenons un exemple simple :

Le champ "title" dans la collection Article

Le champ "title" sera analysé par le service "parser" de la manière suivante :

  • contentType: "api::article.article"
  • fieldName: "title"
  • containerType: "default"
  • zoneName: null
  • component: null
  • path : "api::article.article/title" (champ calculé)

Prenons un exemple plus complexe :

Le champ "metaTile" dans la collection Article/seo

Le champ "metaTitle" sera analysé par le service "parser" de la manière suivante :

  • contentType: "api::article.article"
  • fieldName: "metaTitle"
  • containerType: "component" (il s'agit d'un composant à l'intérieur du Content-Type)
  • zoneName: null
  • component: "seo" (le nom du composant)
  • path : "api::article.article/seo/metaTitle" (champ calculé)

Enfin, prenons un exemple complet et complexe :

Le champ "label" dans le bloc Zone, à l'intérieur du composant "relatedArticles", lui-même à l'intérieur du composant "header"

Le champ "label" sera analysé par le service "parser" de la manière suivante :

  • contentType: "api::article.article"
  • fieldName: "label"
  • containerType: "nestedComponentInComponentInZone" (il s'agit d'un composant à l'intérieur d'un composant lui-même dans une zone)
  • zoneName: "blocks"
  • component: "header" (le nom du composant)
  • path : "api::article.article/blocks/related-articles/header/label" (champ calculé)

Le champ "containerType" utilise différentes valeurs pour identifier l'emplacement des champs :

  • "default": le champ est présent à la racine du Content-Type
  • "component": le champ est présent dans un composant situé à la racine du Content-Type
  • "componentInZone": le champ est présent dans un composant d'une zone
  • "nestedComponentInComponentInZone": le champ est présent dans un composant imbriqué à l'intérieur d'un autre composant, lui-même dans une zone

Le parser ne traite pas d'imbrications plus complexes. La détection maximale se limite à zone/component/component.

Help Service

Dans "api/src/plugins/awesome-help/server/services", ouvrez le fichier "help.js". Si vous vous souvenez, nous avons déjà créé une fonction "findMany"à l'intérieur. Prenez le code ci-dessous et collez-le dans le fichier :

Github code

Nous créons une nouvelle constante "query" pour faire directement référence à l'instance du service "query".

strapi.db.query('plugin::awesome-help.help');

Cette instance permet d'interroger la base de données de Strapi pour effectuer des requêtes de données.

Notez la mise à jour de la fonction "findMany" : nous ajoutons un tri par défaut à la requête en insérant cette instruction avant chaque appel de requête, afin de trier les résultats par "Content-Type" :

params["orderBy"] = "contentType";

Toutes les autres fonctions sont auto-documentées et nous utilisons directement le service "query" pour effectuer l'appel ciblé :

  • "findOne" récupère une seule entité d'aide,
  • "count" compte les entités d'aide,
  • "createMany" crée plusieurs entités d'aide en un seul appel,
  • "create" crée une seule entité d'aide,
  • "update" met à jour une entité d'aide,
  • "deleteAll" supprime toutes les entités d'aide (notez la construction de la condition where),
  • "deleteOne" supprime une entité d'aide.

Pour la partie interface d'administration, nous devons exposer uniquement deux fonctions : "findMany" et "update". La première sert à remplir la liste, et la seconde à mettre à jour les entités depuis la fenêtre modale.

Le code mis à jour du contrôleur :

Github code

Comme le service fait référence à l'objet d'instance "query"", nous ajoutons une constante pour référencer le service "Help". Remarquez la gestion des erreurs dans la fonction "update" avec cette instruction :

ctx.throw(500, err);

Le code mis à jour de la route :

Github code

La route doit être mise à jour : le type de route doit passer de "content-api" à "admin" pour pouvoir être appelée depuis l'interface d'administration.

L'API d'aide est terminée !

Service de parsing

Nous avons mis à jour le service "Parser" :

Github code

Nous avons effectué du refactoring et renommé certaines fonctions afin de maximiser la responsabilité unique de chacune. Une fonction bien nommée vaut mieux que 10 lignes de commentaires. Enfin, nous avons ajouté de nouvelles fonctions :

  • "checkStructureHasChanged" : vérifie si la structure du Content-Type de Strapi a changé
  • "checkFieldsToDelete": vérifie si certains anciens champs du Content-Type doivent être supprimés.
  • "checkFieldsToCreate": vérifie si de nouveaux champs doivent être créés dans le Content-Type.
  • "synchronize": synchronise la structure du Content-Type de Strapi à partir des éléments stockés avec les nouveaux éléments extraits (en s'appuyant sur les fonctions "checkFieldsToDelete" et "checkFieldsToDelete").
  • "mapHelpEntitiesFromAnalysedResults": mappe les objets issus de l'analyse du Content-Type vers des objets "Help".
  • "createHelpEntities": crée dans la base de données Strapi les nouvelles entités "Help". On utilise ici la nouvelle fonction "createMany" du service "Help" pour stocker les éléments en base.
  • "getPath": cette fonction utilitaire crée le chemin relatif d'un champ afin de le mémoriser dans les entités "Help".

Si vous regardez la mise à jour de la fonction principale "parse" : nous parcourons les champs du Content-Type et les stockons dans la collection "Help".

Désormais, deux fonctions sont exposées via le service "Parser" : "parse" et "checkStructureHasChanged".

Plus tard dans cette étape, nous utiliserons la nouvelle fonction "checkStructureHasChanged" pour faire des trucs sympas.

Nous avons également mis à jour le contrôleur "Parser" ainsi que la route "Parser" pour exposer la nouvelle fonction "checkStructureHasChanged".

Enfin, les API "Help" et "Parser" sont maintenant prêtes à être utilisées par l'interface d'administration : il est temps de passer à la partie Admin API pour mettre à jour l'interface et utiliser de vrais appels API !

'Iterface d'administration

Les premières actions à effectuer sont de mettre à jour le proxy de l'API "Parser" avec la fonction "check", et de créer le nouveau proxy de l'API "Help".

Github code

Ouvrez le fichier "api/src/plugins/awesome-help/admin/src/pages/HomePage/index.js" et insérez le code ci-dessous :

Github code

Nous ajoutons le hook "useEffect" pour :

  • Récupérer toutes les entités d'aide depuis la collection help et remplir l'état REACT results avec la fonction "setResults".
  • Vérifier si la structure de Strapi a changé. Dans ce cas, un panneau <BOX> ffiche un message d'avertissement.

La fonction "handleSubmit" est également mise à jour pour appeler la fonction "parse" de l'API "Parser" et afficher le résultat dans le composant <HelpTable> via l'affectation de l'état REACT results avec la fonction "setResults".

Mise à jour du composant <HelpTable> :

Github code

Nous avons implémenté une nouvelle fonction "refreshDataGrid" pour rafraîchir le DataGrid après la mise à jour d'une entité "Help".

La fonction "handleSave" utilise le proxy "Help" pour mettre à jour l'entité "Help" depuis le composant <ModalForm>. Notez l'utilisation de la fonction "toggleNotification" de Strapi pour afficher un retour visuel dans l'interface.

Il est temps de tester la nouvelle interface ! Compilez le projet et lancez-le avec :

yarn admin

Ouvrez le plugin Awesome Help et cliquez sur "Scan your Strapi internal structure" :

Avant le scan

Après le scan

Le DataGrid est maintenant rempli avec tous les champs des Content-Types détectés.

Cliquez sur le bouton "edit" d'une ligne, remplissez le champ "Contextual help content" et cliquez sur "Save".

Le composant ModalForm en action

L'entité "help" est maintenant enregistrée dans la base de données Strapi !

Beau travail ! L'entité "Help" est désormais stockée dans la base de données de Strapi. Pour vérifier, allez dans le Content Manager, cliquez sur la collection "Help" et vérifiez si votre modification apparaît également à cet endroit !

Nous devons également vérifier que si un content manager ou un développeur modifie la structure de Strapi, les changements sont bien appliqués à la collection.

Allez dans le "Content-Type" builder, sélectionnez la collection "Article", puis ajoutez un champ avec "Add another field" :

Ajout d'un champ dans le ContentType Article

Sélectionnez le champ "Text" et nommez-le "myTextField".

modale de création de champ dans Strapi

Vous pouvez ajouter autant de champs que vous le souhaitez.

Maintenant, allez dans le plugin "Awesome Help" :

Structure de Strapi modifiée !

Vous êtes notifié que la structure de Strapi a changé. Cliquez à nouveau sur le bouton "Scan your Strapi internal structure".

Mon nouveau champ est là !

Retournez dans le "Content builder" et supprimez les champs ajoutés. Si vous retournez dans le plugin, la modification de structure sera détectée !

Mission accomplie !

Nous avons finalisé les APIs "Help" et "Parser"", la structure de Strapi est maintenant analysée et enregistrée, et nous pouvons ajouter de l'aide contextuelle !

Et n’oubliez pas notre dépôt GIT pour récupérer le code : https://github.com/ExFabrica/strapi-stories/tree/develop/part-5

À bientôt !