Skip to content

Latest commit

 

History

History
343 lines (291 loc) · 13.2 KB

File metadata and controls

343 lines (291 loc) · 13.2 KB
i18nReady true
title Rendre les modules d’extension utiles
description Découvrez les modules d’extension de StudioCMS et leur fonctionnement.
sidebar
order
2

import ReadMore from '~/components/ReadMore.astro' import { FileTree } from '@astrojs/starlight/components'

Présentation

Construire un module d’extension pour StudioCMS est un moyen puissant d’étendre les fonctionnalités de StudioCMS. Il offre une solution simple et flexible pour ajouter de nouvelles fonctionnalités à votre projet StudioCMS. Voici un exemple simple de création et de fonctionnement d’un module d’extension pour StudioCMS.

Mise en route

Pour commencer, vous devez créer un nouveau module d’extension pour StudioCMS. Voici un exemple de structure de fichier pour un module d’extension pour StudioCMS :

  • package.json
  • src
    • index.ts
    • routes
      • [...slug].astro
    • dashboard-grid-items
      • MyPluginGridItem.astro

Création du module d’extension

Dans le fichier principal src/index.ts, vous définirez le module d’extension pour StudioCMS. Voici un exemple de définition d’un module d’extension pour StudioCMS incluant une intégration Astro pour créer un blog simple :

import { definePlugin } from 'studiocms/plugins';
import { AstroIntegration } from 'astro';
import { addVirtualImports, createResolver } from 'astro-integration-kit';

// Définir les options du module d’extension et de l’intégration
interface Options {
  route: string;
}

export function studioCMSPageInjector(options: Options) {
  // Résoudre le chemin d’accès au fichier actuel
  const { resolve } = createResolver(import.meta.url);

  // Définir l’intégration Astro
  function monIntegration(options: Options): AstroIntegration {
    const route = `/${options?.route || 'mon-module-extension'}`;

    return {
      name: 'mon-integration-astro',
      hooks: {
        "astro:config:setup": (params) => {
          const { injectRoute } = params;

          // Injecter la route pour le module d’extension
          injectRoute({
            entrypoint: resolve('./routes/[...slug].astro'),
            pattern: `/${route}/[...slug]`,
            prerender: false,
          })

          addVirtualImports(params, {
            name: 'mon-integration-astro',
            imports: {
              'myplugin:config': `
                export const options = ${JSON.stringify({ route })};
                export default options;
              `,
            }
          })
        }
      }
    }
  }

  // Définir le module d’extension pour StudioCMS
  return definePlugin({
    identifier: 'mon-module-extension',
    name: "Mon module d'extension",
    hooks: {
      'studiocms:astro-config': ({ addIntegrations }) => {
        addIntegrations(monIntegration(options));  // Facultatif, mais recommandé
      },
      'studiocms:dashboard': ({ setDashboard }) => {
        setDashboard({
          translations: {
            en: {
              example: {
                title: 'Example',
                'other-text': 'Some other text',
              }
            },
            fr: {
              example: {
                title: 'Exemple',
                'other-text': 'Un autre texte',
              }
            }
          },

          // Définir les éléments de la grille pour le tableau de bord
          // Voici les éléments qui seront affichés dans le tableau de bord de StudioCMS
          // Vous pouvez définir autant d’éléments que vous le souhaitez
          // Dans cet exemple, nous définissons un seul élément, qui a une étendue de 2, qui nécessite l’autorisation `editor` et qui injecte un composant Astro qui remplace l’élément personnalisé HTML simple.
          dashboardGridItems: [
            {
              name: 'exemple',
              span: 2,
              variant: 'default',
              requiresPermission: 'editor',
              header: { title: 'Exemple', icon: 'heroicons:bolt' },
              body: {
                // Utilisez toujours du HTML brut sans `-` ni caractères spéciaux dans les balises, ils seront remplacés par le composant Astro et ce HTML ne sera jamais affiché
                html: '<examplegriditem></examplegriditem>',
                components: {
                  // Injecter le composant Astro pour remplacer l’élément personnalisé HTML brut
                  examplegriditem: resolve('./dashboard-grid-items/MyPluginGridItem.astro')
                }
              }
            }
          ],
        });
      },

      'studiocms:frontend': ({ setFrontend }) => {
        setFrontend({
          // Définir les liens de navigation frontend pour le module d’extension
          // Ceci est utile si vous utilisez les assistants de navigation intégrés de StudioCMS dans votre mise en page,
          // comme lors de l’utilisation du module d’extension `@studiocms/blog`.
          frontendNavigationLinks: [{ label: "Mon module d'extension", href: options?.route || 'mon-module-extension' }],
        });
      },
      'studiocms:rendering': ({ setRendering }) => {
        setRendering({
          // Lors de la création de pagesTypes, vous pouvez également définir un `pageContentComponent` si votre module d’extension nécessite un éditeur de contenu personnalisé.
          // pageTypes: [{ identifier: 'mon-module-extension', label: "Article de blog (Mon module d’extension)", pageContentComponent: resolve('./components/MyContentEditor.astro') }],
          // Dans cet exemple, nous pouvons utiliser l’éditeur de contenu par défaut (Markdown).
          pageTypes: [{ identifier: 'mon-module-extension', label: "Article de blog (Mon module d'extension)" }],
        });
      }
    }
  });
}

L’exemple ci-dessus définit un module d’extension pour StudioCMS incluant une intégration Astro et permettant de créer un exemple de blog simple. Le module d’extension inclut une route injectée dans le projet StudioCMS et un élément de grille affiché dans le tableau de bord de StudioCMS.

Pour plus d’informations sur la création d’une intégration Astro, consultez Astro Integration Kit et la documentation des intégrations Astro.

Exemple de route

Dans le fichier src/routes/[...slug].astro, vous définirez la route du module d’extension. Voici un exemple de définition d’une route pour le module d’extension. Nous la diviserons en deux parties : la première est le frontmatter (entre les barrières ---), et la seconde est le modèle HTML placé sous la seconde barrière ---.

// @noErrors
// @filename: plugin.d.ts
declare module 'myplugin:config' {
    export const options: { route: string };
    export default options;
}
// ---cut---
// @filename: Frontmatter.ts
/// <reference types="studiocms/v/types" />
/// <reference types="./plugin.d.ts" />
import type { AstroGlobal } from 'astro';
const Astro: AstroGlobal = {};
// ---cut---
import { StudioCMSRenderer } from 'studiocms:renderer';
import { SDKCoreJs, runSDK } from 'studiocms:sdk';
import config from 'myplugin:config';

const makeRoute = (slug: string) => {
    return `/${config.route}/${slug}`;
}

// 'mon-module-extension' est ici utilisé comme identifiant pour
// le type de page de la définition du module d’extension
const pages = await runSDK(SDKCoreJs.GET.packagePages('mon-module-extension')); 

const { slug } = Astro.params;

const page = pages.find((page) => page.slug === slug || '');
{
    slug && page ? (
        <div>
            <h1>{page.title}</h1>
            <StudioCMSRenderer content={page.defaultContent?.content || ''} />
        </div>
    ) : (
        <div>
            <h1>Mon module d’extension</h1>
            <ul>
                {pages.length > 0 && pages.map((page) => (
                    <li>
                        <a href={makeRoute(page.slug)}>{page.title}</a>
                    </li>
                ))}
            </ul>
        </div>
    )
}

L’exemple ci-dessus définit une route dynamique pour le module d’extension qui affiche une liste d’articles de blog lorsqu’aucun slug n’est fourni et affiche le contenu d’un article de blog lorsqu’un slug est fourni.

Exemple d’élément de grille

Dans le fichier src/dashboard-grid-items/MyPluginGridItem.astro, vous définirez l’élément de grille du module d’extension. Voici un exemple de définition d’un élément de grille pour le module d’extension :

---
import { SDKCoreJs, runSDK } from 'studiocms:sdk';

// 'mon-module-extension' est ici utilisé comme identifiant pour
// le type de page à partir de la définition du module d’extension
const pages = await runSDK(SDKCoreJs.GET.packagePages('mon-module-extension')); 

// Obtenir les 5 pages les plus récemment mises à jour au cours des 30 derniers jours
const recentlyUpdatedPages = pages
    .filter((page) => {
        const now = new Date();
        const thirtyDaysAgo = new Date(now.setDate(now.getDate() - 30));
        return new Date(page.updatedAt) > thirtyDaysAgo;
    })
    .sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime())
    .slice(0, 5);
---

<div>
    <h2>Pages récemment mises à jour</h2>
    <ul>
        {recentlyUpdatedPages.length > 0 && recentlyUpdatedPages.map((page) => (
            <li>
                <a href={Astro.locals.routeMap.mainLinks.contentManagementEdit + `?edit=${page.id}`}>{page.title}</a>
            </li>
        ))}
    </ul>
</div>

L’exemple ci-dessus définit un élément de grille pour le module d’extension qui affiche les 5 pages les plus récemment mises à jour au cours des 30 derniers jours. Cet élément inclut une liste de liens vers la page de modification de la gestion de contenu pour chaque page.

Intégration avec les assistants FrontendNavigationLinks

Si vous souhaitez utiliser les assistants de navigation intégrés de StudioCMS dans votre projet, de la même manière que le fait le module d’extension @studiocms/blog, vous pouvez créer un composant Navigation.astro personnalisé :

---
import { frontendNavigation } from 'studiocms:plugin-helpers';

// Définir les props pour le composant Navigation
interface Props {
	topLevelLinkCount?: number;
};

// Obtenir le nombre de liens de niveau supérieur à partir des props
const { topLevelLinkCount = 3 } = Astro.props;

// Obtenir la configuration du site et la liste des pages
const config = Astro.locals.siteConfig.data;

// Récupérer le titre du site à partir de la configuration
const { title } = config || { title: 'StudioCMS' };

// Obtenir l’URL du site principal
const {
	mainLinks: { baseSiteURL },
} = Astro.locals.routeMap;

// Définir les props de lien pour la navigation
type LinkProps = {
	text: string;
	href: string;
};

// Définir les liens pour la navigation
const links: LinkProps[] = await frontendNavigation();
---
{/* S’il n’y a pas d’éléments déroulants */}
{ ( links.length < topLevelLinkCount || links.length === topLevelLinkCount ) && (
    <div class="navigation">
        <div class="title"><a href={baseSiteURL}>{title}</a></div>
        <div class="mini-nav">
            <button>Menu</button>
            <div class="mini-nav-content">
            { 
                links.map(({ text, href }) => (
                    <a {href}>{text}</a>
                )) 
            }
            </div>
        </div>
        { 
            links.map(({ text, href }) => (
                <a class="links" {href}>{text}</a>
            )) 
        }
    </div> 
) }

{/* S’il y a des éléments déroulants */}
{ links.length > topLevelLinkCount && (
    <div class="navigation">
        <div class="title"><a href={baseSiteURL}>{title}</a></div>

        <div class="mini-nav">
            <button>Menu</button>
            <div class="mini-nav-content">
            { 
                links.map(({ text, href }) => (
                    <a {href}>{text}</a>
                )) 
            }
            </div>
        </div>
        { 
            links.slice(0, topLevelLinkCount).map(({ text, href }) => (
                    <a class="links" {href}>{text}</a>
            ))
        }
            <div class="dropdown">
                <button>Plus ▼</button>
                <div class="dropdown-content">
                    { links.slice(topLevelLinkCount).map(({ text, href }) => (
                        <a {href}>{text}</a>
                    )) }
                </div>
            </div>
    </div>
) }

L’exemple ci-dessus définit un composant personnalisé Navigation.astro qui utilise les assistants de navigation intégrés de StudioCMS pour créer un menu de navigation pour le projet. Ce composant inclut des liens vers l’URL du site principal, la page d’index et toutes les autres pages configurées pour s’afficher dans la navigation.

Il vous suffit d’ajouter quelques styles et vous disposez d’un menu de navigation entièrement fonctionnel qui fonctionne avec les assistants de navigation intégrés de StudioCMS.