Skip to Content
DocumentationRecettesAjout d'un panneau gauche

Ajout d’un panneau gauche

Le panneau gauche  permet de naviguer dans une app O3. Il est basé sur le UI shell left panel de Carbon  et se place sous l’en-tête, fixé au bord gauche de la page.

Ce guide utilise l’application Bed Management  du monorepo O3 Patient Management comme implémentation de référence. Bed Management contient plusieurs écrans liés, ce qui en fait un bon exemple d’utilisation d’un panneau gauche au niveau d’une app.

Exemple: ajouter un panneau gauche à l’app Bed Management

L’app Bed Management contient les écrans suivants:

  • Un écran d’accueil qui résume les lits par emplacement.
  • Un écran de détail pour un emplacement spécifique.
  • Un écran d’administration pour l’allocation des lits.
  • Des écrans d’administration pour les types de lits et les étiquettes de lits.

Le panneau gauche expose ces liens:

  • Summary pour l’écran d’accueil et l’écran de détail d’un emplacement.
  • Bed allocation pour l’administration des lits.
  • Bed types pour l’administration des types de lits.
  • Bed tags pour l’administration des étiquettes de lits.

Voici une capture d’écran de l’app:


Capture d'ecran de la page d'accueil de Bed Management montrant le panneau gauche

Pour obtenir ce résultat, suivez les étapes ci-dessous:

Étape 1: Enregistrer le panneau gauche depuis la racine de page

Commencez par mettre à jour le composant racine de l’app qui configure le routage:

src/root.component.tsx
import React from "react"; import { BrowserRouter, Route, Routes } from "react-router-dom"; import { useLeftNav, WorkspaceContainer } from "@openmrs/esm-framework"; import BedAdministrationTable from "./bed-administration/bed-administration-table.component"; import BedTagAdministrationTable from "./bed-tag/bed-tag-administration-table.component"; import BedTypeAdministrationTable from "./bed-type/bed-type-administration-table.component"; import Home from "./home.component"; import LeftPanel from "./left-panel/left-panel.component"; import WardWithBeds from "./ward-with-beds/ward-with-beds.component"; import styles from "./root.scss"; function Root() { const spaBasePath = window.spaBase; const bedManagementBasename = window.getOpenmrsSpaBase() + "bed-management"; useLeftNav({ name: "bed-management-left-panel-slot", basePath: spaBasePath }); return ( <BrowserRouter basename={bedManagementBasename}> <LeftPanel /> <main className={styles.container}> <Routes> <Route path="/" element={<Home />} /> <Route path="/location/:location" element={<WardWithBeds />} /> <Route path="/bed-administration" element={<BedAdministrationTable />} /> <Route path="/bed-tags" element={<BedTagAdministrationTable />} /> <Route path="/bed-types" element={<BedTypeAdministrationTable />} /> </Routes> </main> <WorkspaceContainer contextKey="bed-management" /> </BrowserRouter> ); } export default Root;

Points importants:

  • useLeftNav() enregistre le slot de navigation gauche actif tant que la page est montée, puis le désenregistre au démontage. Utilisez ce hook dans les composants de page, pas dans les composants d’extension.
  • name est le slot d’extension qui recevra les liens du panneau gauche. Le même nom de slot est utilisé dans routes.json.
  • basePath est le chemin de base de la SPA, /openmrs/spa par défaut.
  • L’app rend son propre composant LeftPanel au lieu de rendre LeftNavMenu directement. L’utilisation directe de LeftNavMenu en dehors de l’en-tête du shell est dépréciée dans le framework.
  • WorkspaceContainer garde les workspaces de Bed Management dans le contexte de cette page.

Étape 2: Rendre une SideNav Carbon avec un slot d’extension

Créez un composant LeftPanel qui s’affiche sur les layouts desktop et fournit le slot dans lequel les extensions de liens seront rendues:

src/left-panel/left-panel.component.tsx
import React from "react"; import { useTranslation } from "react-i18next"; import { SideNav } from "@carbon/react"; import { attach, ExtensionSlot, isDesktop, useLayoutType } from "@openmrs/esm-framework"; import styles from "./left-panel.scss"; attach("nav-menu-slot", "bed-management-left-panel"); function LeftPanel() { const { t } = useTranslation(); const layout = useLayoutType(); return ( isDesktop(layout) && ( <SideNav aria-label={t("bedManagementLeftPanel", "Bed management left panel")} className={styles.leftPanel} expanded > <ExtensionSlot name="bed-management-left-panel-slot" /> </SideNav> ) ); } export default LeftPanel;

Le nom de ExtensionSlot doit correspondre au slot enregistré avec useLeftNav() et au slot utilisé par les extensions de liens dans routes.json.

Étape 3: Câbler la page racine

Exportez le composant racine depuis index.ts et enregistrez le schéma de configuration pendant le démarrage:

src/index.ts
import { defineConfigSchema, getAsyncLifecycle } from "@openmrs/esm-framework"; import { configSchema } from "./config-schema"; const moduleName = "@openmrs/esm-bed-management-app"; const options = { featureName: "bed-management", moduleName, }; export const importTranslation = require.context("../translations", false, /.json$/, "lazy"); export function startupApp() { defineConfigSchema(moduleName, configSchema); } export const root = getAsyncLifecycle(() => import("./root.component"), options);

Ajoutez ensuite la route de page dans routes.json:

src/routes.json
{ "$schema": "https://json.openmrs.org/routes.schema.json", "backendDependencies": { "fhir2": ">=1.2", "webservices.rest": ">=2.2.0" }, "pages": [ { "component": "root", "route": "bed-management" } ] }

Cette définition indique à O3 de rendre le lifecycle root lorsque vous naviguez vers /openmrs/spa/bed-management.

Étape 4: Ajouter les liens au panneau gauche

Créez un export de lifecycle pour chaque lien:

src/index.ts
import { getSyncLifecycle } from "@openmrs/esm-framework"; import { createLeftPanelLink } from "./left-panel-link.component"; export const summaryLeftPanelLink = getSyncLifecycle( createLeftPanelLink({ name: "bed-management", // t("summary", "Summary") title: "Summary", }), options ); export const adminLeftPanelLink = getSyncLifecycle( createLeftPanelLink({ name: "bed-administration", // t("bedAllocation", "Bed allocation") title: "Bed allocation", }), options ); export const bedTypeLeftPanelLink = getSyncLifecycle( createLeftPanelLink({ name: "bed-types", // t("bedTypes", "Bed types") title: "Bed types", }), options ); export const bedTagLeftPanelLink = getSyncLifecycle( createLeftPanelLink({ name: "bed-tags", // t("bedTags", "Bed tags") title: "Bed tags", }), options );
ℹ️

Conservez les commentaires t() près des titres statiques afin que l’extraction des traductions puisse les trouver. Si un lien doit utiliser une traduction à l’exécution, gérez useTranslation() dans le composant de lien rendu plutôt que dans getSyncLifecycle().

Le helper createLeftPanelLink rend un ConfigurableLink et le marque comme actif lorsque son name correspond au segment courant de l’URL:

src/left-panel-link.component.tsx
import React, { useMemo } from "react"; import classNames from "classnames"; import { last } from "lodash-es"; import { BrowserRouter, useLocation } from "react-router-dom"; import { ConfigurableLink } from "@openmrs/esm-framework"; export interface LinkConfig { name: string; title: string; } function LinkExtension({ config }: { config: LinkConfig }) { const { name, title } = config; const location = useLocation(); let urlSegment = useMemo(() => decodeURIComponent(last(location.pathname.split("/"))), [location.pathname]); const isUUID = (value) => { const regex = /^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/; return regex.test(value); }; if (isUUID(urlSegment)) { urlSegment = "bed-management"; } return ( <ConfigurableLink to={`${window.getOpenmrsSpaBase()}bed-management${name && name !== "bed-management" ? `/${name}` : ""}`} className={classNames("cds--side-nav__link", name === urlSegment && "active-left-nav-link")} > {title} </ConfigurableLink> ); } export const createLeftPanelLink = (config: LinkConfig) => () => ( <BrowserRouter> <LinkExtension config={config} /> </BrowserRouter> );

Lorsque le dernier segment de l’URL est un UUID d’emplacement, le helper traite la section courante comme bed-management afin que le lien Summary reste actif sur les pages de détail.

Étape 5: Ajouter les extensions de liens à routes.json

Ajoutez les exports de liens au tableau extensions:

src/routes.json
"extensions": [ { "component": "adminCardLink", "name": "bed-management-admin-card-link", "slot": "system-admin-page-card-link-slot" }, { "component": "adminLeftPanelLink", "name": "bed-administration-left-panel-link", "slot": "bed-management-left-panel-slot" }, { "component": "bedTypeLeftPanelLink", "name": "bed-type-left-panel-link", "slot": "bed-management-left-panel-slot" }, { "component": "bedTagLeftPanelLink", "name": "bed-tag-left-panel-link", "slot": "bed-management-left-panel-slot" }, { "component": "summaryLeftPanelLink", "name": "bed-management-home-dashboard-link", "slot": "bed-management-left-panel-slot", "order": 0 } ]

Étape 6: Essayer le résultat

Naviguez vers /openmrs/spa/bed-management. Vous devriez voir l’écran d’accueil de Bed Management avec le panneau gauche:


Capture d'ecran de la page d'accueil de Bed Management montrant le panneau gauche

Cliquer sur une carte d’emplacement ouvre une page de détail et garde le lien Summary actif:


Capture d'ecran de la page de detail d'un emplacement dans Bed Management

Cliquer sur Bed allocation ouvre la page d’administration:


Capture d'ecran de la page d'administration de l'allocation des lits
Dernière mise à jour le