Salta ai contenuti

Viste di primo livello

Se hai bisogno di sviluppare una vista personalizzata che non mappa direttamente una collezione di datasource, puoi implementarla come componente React. Questo è utile per implementare dashboard personalizzate, visualizzazioni dati o qualsiasi altra funzionalità personalizzata di cui hai bisogno.

Le viste di primo livello possono essere personalizzate in base all’utente connesso, quindi puoi implementare viste personalizzate per diversi ruoli utente, o persino nasconderle completamente per gli utenti non autenticati.

Puoi usare tutti i componenti e gli hook forniti da FireCMS. Consulta la galleria componenti per ulteriori informazioni.

Puoi anche usare tutti gli hook, inclusi autenticazione, navigazione, datasource (Firestore), storage, ecc.

Puoi anche includere viste di collezione nelle tue viste personalizzate, o usare il pannello laterale per vedere i dettagli delle entità, o usare componenti completamente personalizzati.

Devi definire il nome, il percorso e il componente, e aggiungerli alla navigazione principale, come l’esempio qui sotto.

Per impostazione predefinita, verrà mostrato nella vista di navigazione principale.

Per le viste personalizzate puoi definire le seguenti props:

  • path string

Percorso CMS da cui puoi raggiungere questa vista. Se includi più percorsi, solo il primo sarà incluso nel menu principale.

  • name: string

Nome di questa vista

  • description?: string

Descrizione opzionale di questa vista. Puoi usare Markdown.

  • hideFromNavigation?: boolean

Questa vista deve essere nascosta dal pannello di navigazione principale? Sarà comunque accessibile se raggiungi il percorso specificato.

  • view: React.ReactNode

Componente da renderizzare. Può essere qualsiasi componente React e può usare qualsiasi degli hook forniti.

  • group?: string

Campo opzionale usato per raggruppare le voci di navigazione di primo livello sotto una vista di navigazione.

Per FireCMS self-hosted, puoi definire le tue viste di primo livello personalizzate aggiungendole nel tuo componente useBuildNavigationController. Puoi passarle come array di oggetti CMSView o una funzione callback che restituisce un array di oggetti CMSView. Nella callback, puoi usare l’oggetto user per mostrare o nascondere condizionalmente le viste in base al ruolo utente, nonché accedere agli hook authentication e navigation.

import {CMSView, useBuildNavigationController} from "@firecms/core";
import {useMemo} from "react";
// resto del codice principale dell'app
const customViews: CMSView[] = useMemo([{
path: "additional",
name: "Vista aggiuntiva",
description: "Questo è un esempio di vista aggiuntiva definita dall'utente",
// Può essere qualsiasi componente React
view: <ExampleCMSView/>
}], []);
const navigationController = useBuildNavigationController({
views: ({ user }) =>{
if(!user) {
return [];
}
return customViews;
},
collections,
authController,
dataSourceDelegate: firestoreDelegate
});

In FireCMS Cloud, puoi definire le tue viste di primo livello personalizzate aggiungendole al tuo FireCMSAppConfig. Puoi usare una callback o aggiungerle direttamente alla proprietà views. La callback include l’user connesso, quindi puoi usarlo per mostrare o nascondere condizionalmente le viste in base al ruolo utente.

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}
/>;
}

La tua vista personalizzata è implementata come qualsiasi normale componente React. Puoi usare qualsiasi degli hook forniti, inclusi autenticazione, navigazione, datasource, storage, stato app, ecc.

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>
);
}