Vues de niveau supérieur
Si vous avez besoin de développer une vue personnalisée qui ne correspond pas directement à une collection de source de données, vous pouvez l’implémenter en tant que composant React. C’est utile pour implémenter des tableaux de bord personnalisés, des visualisations de données, ou toute autre fonctionnalité personnalisée dont vous avez besoin.
Les vues de niveau supérieur peuvent être personnalisées en fonction de l’utilisateur connecté, vous pouvez donc implémenter des vues personnalisées pour différents rôles d’utilisateurs, ou même les masquer complètement pour les utilisateurs non authentifiés.
Vous pouvez utiliser tous les composants et hooks fournis par FireCMS. Consultez la galerie de composants pour plus d’informations.
Vous pouvez également utiliser tous les hooks, y compris l’authentification, la navigation, la source de données (Firestore), le stockage, etc.
Vous pouvez également inclure des vues de collection dans vos vues personnalisées, ou utiliser le panneau latéral pour voir les détails d’entités, ou utiliser des composants entièrement personnalisés.
Vous devez définir le nom, la route et le composant, et l’ajouter à la navigation principale, comme dans l’exemple ci-dessous.
Par défaut, il s’affichera dans la vue de navigation principale.
Pour les vues personnalisées, vous pouvez définir les props suivantes :
path: string
Chemin CMS à partir duquel vous pouvez atteindre cette vue. Si vous incluez plusieurs chemins, seul le premier sera inclus dans le menu principal.
name: string
Nom de cette vue.
description? : string
Description optionnelle de cette vue. Vous pouvez utiliser le Markdown.
hideFromNavigation? : boolean
Cette vue doit-elle être masquée du panneau de navigation principal. Elle sera toujours accessible si vous atteignez le chemin spécifié.
view: React.ReactNode
Composant à rendre. Il peut s’agir de n’importe quel composant React, et peut utiliser n’importe lequel des hooks fournis.
group? : string
Champ optionnel utilisé pour regrouper les entrées de navigation de niveau supérieur sous une vue de navigation.
Exemple FireCMS auto-hébergé
Section intitulée « Exemple FireCMS auto-hébergé »Pour FireCMS auto-hébergé, vous pouvez définir vos vues de niveau supérieur personnalisées en les ajoutant dans votre composant useBuildNavigationController. Vous pouvez les passer comme un tableau d’objets CMSView ou une fonction de callback qui retourne un tableau d’objets CMSView.
import {CMSView, useBuildNavigationController} from "@firecms/core";import {useMemo} from "react";
// reste de votre code d'application principale
const customViews: CMSView[] = useMemo([{ path: "additional", name: "Additional view", description: "This is an example of an additional view that is defined by the user", // Il peut s'agir de n'importe quel composant React view: <ExampleCMSView/> }], []);
const navigationController = useBuildNavigationController({ views: ({ user }) =>{ if(!user) { return []; } return customViews; }, collections, authController, dataSourceDelegate: firestoreDelegate });Exemple FireCMS Cloud
Section intitulée « Exemple FireCMS Cloud »Dans FireCMS Cloud, vous pouvez définir vos vues de niveau supérieur personnalisées en les ajoutant à votre FireCMSAppConfig. Vous pouvez utiliser un callback ou les ajouter directement à la propriété views. Le callback inclut l’user connecté, vous pouvez donc l’utiliser pour afficher ou masquer conditionnellement des vues en fonction du rôle de l’utilisateur.
import { buildCollection, CMSView } from "@firecms/core";import { ExampleCMSView } from "./ExampleCMSView";import { FireCMSAppConfig, FireCMSCloudApp } from "@firecms/cloud";
const projectId = "YOUR_PROJECT_ID";
const customViews: CMSView[] = [{ path: "additional", name: "Additional view", description: "This is an example of an additional view that is defined by the user", // This can be any React component view: <ExampleCMSView/>}];
const productCollection = buildCollection<any>({ name: "Product", id: "products", path: "products", properties: { name: { name: "Name", validation: { required: true }, dataType: "string" } }});
const appConfig: FireCMSAppConfig = { version: "1", collections: ({ user }) => [ productCollection ], views: ({ user }) => customViews};
export default function App() {
return <FireCMSCloudApp projectId={projectId} appConfig={appConfig} />;}Exemple de vue supplémentaire
Section intitulée « Exemple de vue supplémentaire »Votre vue personnalisée est implémentée comme n’importe quel composant React ordinaire. Vous pouvez utiliser n’importe lequel des hooks fournis, y compris l’authentification, la navigation, la source de données, le stockage, l’état de l’application, etc.
import React from "react";
import { buildCollection, Entity, EntityCollectionView, useAuthController, useReferenceDialog, useSelectionController, useSideEntityController, useSnackbarController} from "@firecms/core";import { Button, GitHubIcon, IconButton, Paper, Tooltip, Typography, } from "@firecms/ui";
const usersCollection = buildCollection({ path: "users", id: "users", name: "Users", singularName: "User", group: "Main", description: "Registered users", textSearchEnabled: true, icon: "Person", properties: { first_name: { name: "First name", dataType: "string" }, last_name: { name: "Last name", dataType: "string" }, email: { name: "Email", dataType: "string", email: true }, phone: { name: "Phone", dataType: "string" }, liked_products: { dataType: "array", name: "Liked products", description: "Products this user has liked", of: { dataType: "reference", path: "products" } }, picture: { name: "Picture", dataType: "map", properties: { large: { name: "Large", dataType: "string", url: "image" }, thumbnail: { name: "Thumbnail", dataType: "string", url: "image" } }, previewProperties: ["large"] } }, additionalFields: [ { key: "sample_additional", name: "Sample additional", Builder: ({ entity }) => <>{`Generated column: ${entity.values.first_name}`}</>, dependencies: ["first_name"] } ]});
/** * Sample CMS view not bound to a collection, customizable by the developer
*/export function ExampleCMSView() {
// hook to display custom snackbars const snackbarController = useSnackbarController();
const selectionController = useSelectionController();
console.log("Selection from ExampleCMSView", selectionController.selectedEntities);
// hook to open the side dialog that shows the entity forms const sideEntityController = useSideEntityController();
// hook to do operations related to authentication const authController = useAuthController();
// hook to open a reference dialog const referenceDialog = useReferenceDialog({ path: "products", onSingleEntitySelected(entity: Entity<any> | null) { snackbarController.open({ type: "success", message: "Selected " + entity?.values.name }) } });
const customProductCollection = buildCollection({ id: "custom_product", path: "custom_product", name: "Custom products", properties: { name: { name: "Name", validation: { required: true }, dataType: "string" }, very_custom_field: { name: "Very custom field", dataType: "string" } } });
const githubLink = ( <Tooltip asChild={true} title="Get the source code of this example view"> <IconButton href={"https://github.com/firecmsco/firecms/blob/main/examples/example_cloud/src/views/ExampleCMSView.tsx"} rel="noopener noreferrer" target="_blank" component={"a"} size="large"> <GitHubIcon/> </IconButton> </Tooltip> );
return ( <div className="flex h-full"> <div className="m-auto flex flex-col items-center max-w-4xl">
<div className="flex flex-col gap-12 items-start">
<div className="mt-24"> <Typography variant="h4"> This is an example of an additional view </Typography> <p> {authController.user ? <>Logged in as {authController.user.displayName}</> : <>You are not logged in</>} </p> </div>
<div className="grid grid-cols-1 sm:grid-cols-3 gap-2"> <Paper className={"w-full flex flex-col p-4 items-start"}> <p className="mb-4 flex-grow"> Use this button to select an entity under the path `products` programmatically </p> <Button variant={"outlined"} size={"small"} onClick={referenceDialog.open}> Test reference dialog </Button> </Paper>
<Paper className="w-full flex flex-col p-4 items-start"> <p className="mb-4 flex-grow"> Use this button to open a snackbar </p> <Button variant={"outlined"} size={"small"} onClick={() => snackbarController.open({ type: "success", message: "This is pretty cool" })}> Test snackbar </Button> </Paper>
<Paper className="w-full flex flex-col p-4 items-start"> <p className="mb-4 flex-grow"> Use this button to open an entity in a custom path with a custom schema </p> <Button size={"small"} variant={"outlined"} onClick={() => sideEntityController.open({ entityId: "B003WT1622", path: "/products-test", collection: customProductCollection, width: 1000 })}> Open custom entity </Button> </Paper> </div>
<div className="w-full"> <p className="mb-4"> You can include full entity collections in your views: </p> <Paper className={"h-[400px]"}> <EntityCollectionView {...usersCollection} fullPath={"users"} selectionController={selectionController}/> </Paper> </div>
<div className="mt-auto"> {githubLink} </div>
</div> </div> </div> );}