Pular para o conteúdo

Views de Nível Superior

Se você precisar desenvolver uma view personalizada que não mapeie diretamente para uma coleção de datasource, você pode implementá-la como um componente React. Isso é útil para implementar dashboards personalizados, visualizações de dados, ou qualquer outra funcionalidade personalizada que você precisar.

As views de nível superior podem ser personalizadas com base no usuário logado, então você pode implementar views personalizadas para diferentes papéis de usuário, ou mesmo ocultá-las completamente para usuários não autenticados.

Você pode usar todos os componentes e hooks fornecidos pelo FireCMS. Veja a galeria de componentes para mais informações.

Você também pode usar todos os hooks, incluindo autenticação, navegação, datasource (Firestore), armazenamento, etc.

Você também pode incluir views de coleção dentro das suas views personalizadas, ou usar o painel lateral para ver detalhes de entidades, ou usar com componentes completamente personalizados.

Você precisa definir o nome, rota e o componente, e adicioná-lo à navegação principal, como no exemplo abaixo.

Por padrão, aparecerá na view de navegação principal.

Para views personalizadas você pode definir as seguintes props:

  • path string

Caminho CMS pelo qual você pode alcançar esta view. Se você incluir múltiplos caminhos, apenas o primeiro será incluído no menu principal

  • name: string

Nome desta view

  • description?: string

Descrição opcional desta view. Você pode usar Markdown

  • hideFromNavigation?: boolean

Esta view deve ser ocultada do painel de navegação principal. Ainda será acessível se você alcançar o caminho especificado

  • view: React.ReactNode

Componente a ser renderizado. Pode ser qualquer componente React e pode usar qualquer um dos hooks fornecidos

  • group?: string

Campo opcional usado para agrupar entradas de navegação de nível superior em uma view de navegação.

Para o FireCMS self-hosted, você pode definir suas views de nível superior personalizadas adicionando-as no seu componente useBuildNavigationController. Você pode passá-las como um array de objetos CMSView ou uma função callback que retorna um array de objetos CMSView. No callback, você pode usar o objeto user para mostrar ou ocultar condicionalmente views com base no papel do usuário.

import {CMSView, useBuildNavigationController} from "@firecms/core";
import {useMemo} from "react";
// restante do código do seu app principal
const customViews: CMSView[] = useMemo([{
path: "additional",
name: "Additional view",
description: "This is an example of an additional view that is defined by the user",
// Pode ser qualquer componente React
view: <ExampleCMSView/>
}], []);
const navigationController = useBuildNavigationController({
views: ({ user }) =>{
if(!user) {
return [];
}
return customViews;
},
collections,
authController,
dataSourceDelegate: firestoreDelegate
});

No FireCMS Cloud, você pode definir suas views de nível superior personalizadas adicionando-as ao seu FireCMSAppConfig. Você pode usar um callback ou adicioná-las diretamente à propriedade views. O callback inclui o user logado, então você pode usá-lo para mostrar ou ocultar condicionalmente views com base no papel do usuário.

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

Sua view personalizada é implementada como qualquer componente React regular. Você pode usar qualquer um dos hooks fornecidos, incluindo autenticação, navegação, datasource, armazenamento, 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>
);
}