Zum Inhalt springen

Top-Level-Ansichten

Wenn Sie eine benutzerdefinierte Ansicht entwickeln müssen, die nicht direkt einer Datenquellen-Kollektion (Datasource) zugeordnet ist, können Sie sie als React-Komponente implementieren. Dies ist nützlich für die Implementierung benutzerdefinierter Dashboards, Datenvisualisierungen oder jede andere benutzerdefinierte Funktionalität, die Sie benötigen.

Top-Level-Ansichten können basierend auf dem angemeldeten Benutzer angepasst werden, sodass Sie benutzerdefinierte Ansichten für verschiedene Benutzerrollen implementieren oder sie für nicht-authentifizierte Benutzer vollständig ausblenden können.

Sie können alle von FireCMS bereitgestellten Komponenten und Hooks verwenden. Weitere Informationen finden Sie in der Komponentengalerie.

Sie können auch alle Hooks verwenden, einschließlich Authentifizierung, Navigation, Datenquelle (Firestore), Speicher (Storage) usw.

Sie können auch Kollektionsansichten in Ihre benutzerdefinierten Ansichten einbinden, den Seitenbereich für Entity-Details verwenden oder sie mit vollständig benutzerdefinierten Komponenten nutzen.

Sie müssen den Namen, die Route und die Komponente definieren und sie zur Hauptnavigation hinzufügen, wie im folgenden Beispiel.

Standardmäßig wird sie in der Hauptnavigationsansicht angezeigt.

Für benutzerdefinierte Ansichten können Sie folgende Eigenschaften definieren:

  • path: string

Die CMS-Route, über die Sie auf diese Ansicht zugreifen können. Wenn Sie mehrere Routen angeben, wird nur die erste in das Hauptmenü aufgenommen.

  • name: string

Name dieser Ansicht.

  • description?: string

Optionale Beschreibung dieser Ansicht. Sie können Markdown verwenden.

  • hideFromNavigation?: boolean

Soll diese Ansicht aus dem Hauptnavigationsbereich ausgeblendet werden? Sie ist weiterhin zugänglich, wenn Sie die angegebene Route aufrufen.

  • view: React.ReactNode

Zu rendernde Komponente. Es kann jede React-Komponente sein und kann beliebige der bereitgestellten Hooks verwenden.

  • group?: string

Optionales Feld, das verwendet wird, um Top-Level-Navigationseinträge unter einer Navigationsansicht zu gruppieren.

Für Self-Hosted FireCMS können Sie Ihre benutzerdefinierten Top-Level-Ansichten definieren, indem Sie sie zu Ihrem useBuildNavigationController hinzufügen. Sie können sie als Array von CMSView-Objekten oder als Callback-Funktion übergeben, die ein Array von CMSView-Objekten zurückgibt. Im Callback können Sie das user-Objekt verwenden, um Ansichten basierend auf der Benutzerrolle bedingt anzuzeigen oder auszublenden, sowie auf die Authentifizierungs- und Navigations-Hooks zuzugreifen.

import {CMSView, useBuildNavigationController} from "@firecms/core";
import {useMemo} from "react";
// Rest Ihres Haupt-App-Codes
const customViews: CMSView[] = useMemo([{
path: "additional",
name: "Additional view",
description: "This is an example of an additional view that is defined by the user",
// Dies kann jede React-Komponente sein
view: <ExampleCMSView/>
}], []);
const navigationController = useBuildNavigationController({
views: ({ user }) =>{
if(!user) {
return [];
}
return customViews;
},
collections,
authController,
dataSourceDelegate: firestoreDelegate
});

In FireCMS Cloud können Sie Ihre benutzerdefinierten Top-Level-Ansichten definieren, indem Sie sie zu Ihrem FireCMSAppConfig hinzufügen. Sie können einen Callback verwenden oder sie direkt zur views-Eigenschaft hinzufügen. Der Callback enthält den angemeldeten user, sodass Sie ihn verwenden können, um Ansichten basierend auf der Benutzerrolle bedingt anzuzeigen oder auszublenden.

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

Ihre benutzerdefinierte Ansicht wird wie jede reguläre React-Komponente implementiert. Sie können alle bereitgestellten Hooks verwenden, einschließlich Authentifizierung, Navigation, Datenquelle (Datasource), Speicher (Storage), App-Status usw.

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