mirror of
https://github.com/zhigang1992/firecms.git
synced 2026-06-15 10:07:45 +08:00
Enabled overriding of entity schemas side panel
This commit is contained in:
@@ -1,13 +1,25 @@
|
||||
import React from "react";
|
||||
import { Box, Button } from "@material-ui/core";
|
||||
|
||||
import { useSnackbarController, useAuthContext } from "@camberi/firecms";
|
||||
import { useSnackbarController, useAuthContext, useSideEntityController, buildSchema } from "@camberi/firecms";
|
||||
|
||||
export function ExampleAdditionalView() {
|
||||
|
||||
const snackbarController = useSnackbarController();
|
||||
const sideEntityController = useSideEntityController();
|
||||
const authContext = useAuthContext();
|
||||
|
||||
const customProductSchema = buildSchema({
|
||||
name: "Product",
|
||||
properties: {
|
||||
name: {
|
||||
title: "Name",
|
||||
validation: { required: true },
|
||||
dataType: "string"
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<Box
|
||||
display="flex"
|
||||
@@ -30,10 +42,20 @@ export function ExampleAdditionalView() {
|
||||
<Button
|
||||
onClick={() => snackbarController.open({
|
||||
type: "success",
|
||||
message: "Test snackbar"
|
||||
message: "This is pretty cool"
|
||||
})}
|
||||
color="primary">
|
||||
Click me
|
||||
Test snackbar
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
onClick={() => sideEntityController.open({
|
||||
entityId: "B003WT1622",
|
||||
collectionPath: "/products",
|
||||
schema: customProductSchema
|
||||
})}
|
||||
color="primary">
|
||||
Open entity with custom schema
|
||||
</Button>
|
||||
|
||||
</Box>
|
||||
|
||||
@@ -36,7 +36,8 @@ import { CMSDrawer } from "./CMSDrawer";
|
||||
import { CMSRouterSwitch } from "./CMSRouterSwitch";
|
||||
import { CMSAppBar } from "./components/CMSAppBar";
|
||||
import { EntitySideDialogs } from "./side_dialog/EntitySideDialogs";
|
||||
import { SideEntityProvider } from "./side_dialog/SideEntityContext";
|
||||
import { SideEntityProvider } from "./side_dialog/SideEntityPanelsController";
|
||||
import { SchemaOverrideRegistryProvider } from "./side_dialog/SchemaOverrideRegistry";
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
@@ -252,39 +253,41 @@ export function CMSApp(props: CMSAppProps) {
|
||||
function renderMainView() {
|
||||
return (
|
||||
<Router>
|
||||
<SideEntityProvider navigation={navigation}>
|
||||
<BreadcrumbsProvider>
|
||||
<MuiPickersUtilsProvider
|
||||
utils={DateFnsUtils}>
|
||||
<DndProvider backend={HTML5Backend}>
|
||||
<SchemaOverrideRegistryProvider navigation={navigation}>
|
||||
<SideEntityProvider navigation={navigation}>
|
||||
<BreadcrumbsProvider>
|
||||
<MuiPickersUtilsProvider
|
||||
utils={DateFnsUtils}>
|
||||
<DndProvider backend={HTML5Backend}>
|
||||
|
||||
<nav>
|
||||
<CMSDrawer logo={logo}
|
||||
drawerOpen={drawerOpen}
|
||||
navigation={navigation}
|
||||
closeDrawer={closeDrawer}
|
||||
additionalViews={additionalViews}/>
|
||||
</nav>
|
||||
<nav>
|
||||
<CMSDrawer logo={logo}
|
||||
drawerOpen={drawerOpen}
|
||||
navigation={navigation}
|
||||
closeDrawer={closeDrawer}
|
||||
additionalViews={additionalViews}/>
|
||||
</nav>
|
||||
|
||||
<div className={classes.main}>
|
||||
<CMSAppBar title={name}
|
||||
handleDrawerToggle={handleDrawerToggle}
|
||||
toolbarExtraWidget={toolbarExtraWidget}/>
|
||||
<div className={classes.main}>
|
||||
<CMSAppBar title={name}
|
||||
handleDrawerToggle={handleDrawerToggle}
|
||||
toolbarExtraWidget={toolbarExtraWidget}/>
|
||||
|
||||
<main
|
||||
className={classes.content}>
|
||||
<CMSRouterSwitch
|
||||
navigation={navigation}
|
||||
additionalViews={additionalViews}/>
|
||||
</main>
|
||||
</div>
|
||||
<main
|
||||
className={classes.content}>
|
||||
<CMSRouterSwitch
|
||||
navigation={navigation}
|
||||
additionalViews={additionalViews}/>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<EntitySideDialogs navigation={navigation}/>
|
||||
<EntitySideDialogs/>
|
||||
|
||||
</DndProvider>
|
||||
</MuiPickersUtilsProvider>
|
||||
</BreadcrumbsProvider>
|
||||
</SideEntityProvider>
|
||||
</DndProvider>
|
||||
</MuiPickersUtilsProvider>
|
||||
</BreadcrumbsProvider>
|
||||
</SideEntityProvider>
|
||||
</SchemaOverrideRegistryProvider>
|
||||
</Router>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
Typography
|
||||
} from "@material-ui/core";
|
||||
import { Delete, FileCopy, KeyboardTab, MoreVert } from "@material-ui/icons";
|
||||
import { useSideEntityController } from "../side_dialog/SideEntityContext";
|
||||
import { useSideEntityController } from "../side_dialog/SideEntityPanelsController";
|
||||
|
||||
export function CollectionRowActions<S extends EntitySchema>({
|
||||
entity,
|
||||
|
||||
@@ -13,7 +13,7 @@ import { Add, Delete } from "@material-ui/icons";
|
||||
import { CollectionRowActions } from "./CollectionRowActions";
|
||||
import DeleteEntityDialog from "./DeleteEntityDialog";
|
||||
import { getSubcollectionColumnId, useColumnIds } from "./common";
|
||||
import { useSideEntityController } from "../side_dialog/SideEntityContext";
|
||||
import { useSideEntityController } from "../side_dialog/SideEntityPanelsController";
|
||||
|
||||
type EntitySubCollectionProps<S extends EntitySchema> = {
|
||||
collectionPath: string;
|
||||
|
||||
@@ -28,7 +28,7 @@ import ClearIcon from "@material-ui/icons/Clear";
|
||||
import { listenEntityFromRef } from "../../models/firestore";
|
||||
import KeyboardTabIcon from "@material-ui/icons/KeyboardTab";
|
||||
import { CollectionTable } from "../../collection/CollectionTable";
|
||||
import { useSideEntityController } from "../../side_dialog/SideEntityContext";
|
||||
import { useSideEntityController } from "../../side_dialog/SideEntityPanelsController";
|
||||
|
||||
export const useStyles = makeStyles(theme => createStyles({
|
||||
root: {
|
||||
|
||||
@@ -118,6 +118,17 @@ export type {
|
||||
AuthContextController,
|
||||
BreadcrumbsStatus
|
||||
} from "./contexts";
|
||||
|
||||
export {
|
||||
useSideEntityController
|
||||
} from "./side_dialog/SideEntityPanelsController";
|
||||
export type {
|
||||
SideEntityPanelsController
|
||||
} from "./side_dialog/SideEntityPanelsController";
|
||||
export type {
|
||||
EntitySidePanelProps, SchemaSidePanelProps
|
||||
} from "./side_dialog/model";
|
||||
|
||||
export {
|
||||
useSnackbarController,
|
||||
useBreadcrumbsContext,
|
||||
|
||||
@@ -18,7 +18,7 @@ import CloseIcon from "@material-ui/icons/Close";
|
||||
import EditIcon from "@material-ui/icons/Edit";
|
||||
import { getCMSPathFrom, removeInitialSlash } from "../routes/navigation";
|
||||
import { EntityCollectionTable } from "../collection/EntityCollectionTable";
|
||||
import { useSideEntityController } from "../side_dialog/SideEntityContext";
|
||||
import { useSideEntityController } from "../side_dialog/SideEntityPanelsController";
|
||||
|
||||
|
||||
export const useStyles = makeStyles(theme => createStyles({
|
||||
|
||||
@@ -32,7 +32,7 @@ import { useAppConfigContext } from "../../contexts";
|
||||
import firebase from "firebase/app";
|
||||
import "firebase/firestore";
|
||||
import { PreviewComponent } from "../PreviewComponent";
|
||||
import { useSideEntityController } from "../../side_dialog/SideEntityContext";
|
||||
import { useSideEntityController } from "../../side_dialog/SideEntityPanelsController";
|
||||
import { PreviewError } from "./PreviewError";
|
||||
import { Skeleton } from "@material-ui/lab";
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import React from "react";
|
||||
import { EntityCollection, EntitySchema } from "../models";
|
||||
import { EntitySchema } from "../models";
|
||||
import { createStyles, makeStyles } from "@material-ui/core";
|
||||
import { EntityDrawer } from "./EntityDrawer";
|
||||
import EntityView from "./EntityView";
|
||||
import { SidePanelProps, useSideEntityController } from "./SideEntityContext";
|
||||
import { getCollectionViewFromPath } from "../routes/navigation";
|
||||
import { useSideEntityController } from "./SideEntityPanelsController";
|
||||
import { useSchemasRegistryController } from "./SchemaOverrideRegistry";
|
||||
import { EntitySidePanelProps, SchemaSidePanelProps } from "./model";
|
||||
import { ErrorBoundary } from "../components";
|
||||
|
||||
export const useStyles = makeStyles(theme => createStyles({
|
||||
root: {
|
||||
@@ -40,12 +42,14 @@ export const useStyles = makeStyles(theme => createStyles({
|
||||
}));
|
||||
|
||||
|
||||
export function EntitySideDialogs<S extends EntitySchema>({ navigation }: { navigation: EntityCollection[] }) {
|
||||
export function EntitySideDialogs<S extends EntitySchema>() {
|
||||
|
||||
const sideEntityController = useSideEntityController();
|
||||
const schemasRegistry = useSchemasRegistryController();
|
||||
|
||||
const sideEntityContext = useSideEntityController();
|
||||
const classes = useStyles();
|
||||
|
||||
const sidePanels = sideEntityContext.sidePanels;
|
||||
const sidePanels = sideEntityController.sidePanels;
|
||||
// const [sidePanelBeingClosed, setSidePanelBeingClosed] = useState<SidePanelProps | undefined>();
|
||||
|
||||
const onExitAnimation = () => {
|
||||
@@ -54,33 +58,35 @@ export function EntitySideDialogs<S extends EntitySchema>({ navigation }: { navi
|
||||
|
||||
const allPanels = [...sidePanels, undefined];
|
||||
|
||||
function buildEntityView(panel: SidePanelProps) {
|
||||
function buildEntityView(panel: EntitySidePanelProps) {
|
||||
|
||||
const entityCollection = getCollectionViewFromPath(panel.collectionPath, navigation);
|
||||
const editable = entityCollection.editEnabled == undefined || entityCollection.editEnabled;
|
||||
const schema = entityCollection.schema;
|
||||
const subcollections = entityCollection.subcollections;
|
||||
const extendedProps: SchemaSidePanelProps | null = schemasRegistry.get(panel.collectionPath);
|
||||
|
||||
return <EntityView
|
||||
key={`side-form-route-${panel.entityId}`}
|
||||
editable={editable}
|
||||
schema={schema}
|
||||
subcollections={subcollections}
|
||||
{...panel}/>;
|
||||
if (!extendedProps)
|
||||
return null;
|
||||
|
||||
return (
|
||||
<ErrorBoundary>
|
||||
<EntityView
|
||||
key={`side-form-route-${panel.entityId}`}
|
||||
{...extendedProps}
|
||||
{...panel}/>
|
||||
</ErrorBoundary>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* we add an extra closed drawer, that it is used to maintain the transition when a drawer is removed */}
|
||||
{
|
||||
allPanels.map((panel: SidePanelProps | undefined, index) => {
|
||||
allPanels.map((panel: EntitySidePanelProps | undefined, index) => {
|
||||
|
||||
return (
|
||||
<EntityDrawer
|
||||
key={`side_menu_${index}`}
|
||||
open={panel !== undefined}
|
||||
onClose={() => {
|
||||
sideEntityContext.close();
|
||||
sideEntityController.close();
|
||||
}}
|
||||
offsetPosition={sidePanels.length - index - 1}
|
||||
onExitAnimation={onExitAnimation}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useMemo, useState } from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import EntityForm from "../form/EntityForm";
|
||||
import {
|
||||
Entity,
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
EntityStatus,
|
||||
EntityValues
|
||||
} from "../models";
|
||||
import { listenEntity, saveEntity } from "../models/firestore";
|
||||
import { listenEntity, saveEntity } from "../models";
|
||||
import {
|
||||
Box,
|
||||
CircularProgress,
|
||||
@@ -24,11 +24,8 @@ import { Prompt } from "react-router-dom";
|
||||
import CloseIcon from "@material-ui/icons/Close";
|
||||
import { EntityPreview } from "../preview";
|
||||
import { EntityCollectionTable } from "../collection/EntityCollectionTable";
|
||||
import {
|
||||
getCollectionViewFromPath,
|
||||
removeInitialSlash
|
||||
} from "../routes/navigation";
|
||||
import { useSideEntityController } from "./SideEntityContext";
|
||||
import { removeInitialSlash } from "../routes/navigation";
|
||||
import { useSideEntityController } from "./SideEntityPanelsController";
|
||||
import CircularProgressCenter from "../components/CircularProgressCenter";
|
||||
|
||||
|
||||
@@ -85,9 +82,9 @@ const useStylesSide = makeStyles((theme: Theme) =>
|
||||
export interface EntitySideViewProps {
|
||||
collectionPath: string;
|
||||
entityId?: string;
|
||||
copy: boolean;
|
||||
copy?: boolean;
|
||||
selectedSubcollection?: string;
|
||||
editable:boolean;
|
||||
editEnabled?:boolean;
|
||||
schema: EntitySchema<any>;
|
||||
subcollections?: EntityCollection[];
|
||||
}
|
||||
@@ -97,7 +94,7 @@ function EntitySideView({
|
||||
entityId,
|
||||
selectedSubcollection,
|
||||
copy,
|
||||
editable,
|
||||
editEnabled = true,
|
||||
schema,
|
||||
subcollections
|
||||
}: EntitySideViewProps) {
|
||||
@@ -230,7 +227,7 @@ function EntitySideView({
|
||||
|
||||
const containerRef = React.useRef<HTMLDivElement>(null);
|
||||
|
||||
const form = editable ? (
|
||||
const form = editEnabled ? (
|
||||
<EntityForm
|
||||
status={status}
|
||||
collectionPath={collectionPath}
|
||||
@@ -324,7 +321,7 @@ function EntitySideView({
|
||||
scrollButtons="auto"
|
||||
>
|
||||
<Tab
|
||||
label={`${editable ? (existingEntity ? "Edit" : `Add New`) : ""} ${schema.name}`
|
||||
label={`${editEnabled ? (existingEntity ? "Edit" : `Add New`) : ""} ${schema.name}`
|
||||
}/>
|
||||
|
||||
{subcollections && subcollections.map(
|
||||
|
||||
88
src/side_dialog/SchemaOverrideRegistry.tsx
Normal file
88
src/side_dialog/SchemaOverrideRegistry.tsx
Normal file
@@ -0,0 +1,88 @@
|
||||
import React, { useContext, useRef } from "react";
|
||||
import { EntityCollection, EntitySchema } from "../models";
|
||||
import { SchemaSidePanelProps } from "./model";
|
||||
import { getCollectionViewFromPath } from "../routes/navigation";
|
||||
|
||||
const DEFAULT_SIDE_ENTITY = {
|
||||
/**
|
||||
* Get
|
||||
*/
|
||||
get: (collectionPath: string) => null,
|
||||
|
||||
/**
|
||||
* Set
|
||||
*/
|
||||
set: (
|
||||
collectionPath: string,
|
||||
sidePanelProps: SchemaSidePanelProps | null
|
||||
) => {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
export type SchemasRegistryPanelsController<S extends EntitySchema> = {
|
||||
/**
|
||||
* Get props for path
|
||||
*/
|
||||
get: (collectionPath: string) => SchemaSidePanelProps | null;
|
||||
|
||||
/**
|
||||
* Set props for path
|
||||
*/
|
||||
set: (
|
||||
collectionPath: string,
|
||||
sidePanelProps: SchemaSidePanelProps | null
|
||||
) => void;
|
||||
};
|
||||
|
||||
export const SchemasRegistryContext = React.createContext<SchemasRegistryPanelsController<any>>(DEFAULT_SIDE_ENTITY);
|
||||
export const useSchemasRegistryController = () => useContext(SchemasRegistryContext);
|
||||
|
||||
interface ViewRegistryProviderProps {
|
||||
children: React.ReactNode;
|
||||
navigation: EntityCollection[];
|
||||
}
|
||||
|
||||
export const SchemaOverrideRegistryProvider: React.FC<ViewRegistryProviderProps> = ({
|
||||
children,
|
||||
navigation
|
||||
}) => {
|
||||
|
||||
const viewsRef = useRef<Record<string, SchemaSidePanelProps>>({});
|
||||
|
||||
const get = (collectionPath: string): SchemaSidePanelProps | null => {
|
||||
let props: SchemaSidePanelProps | null = viewsRef.current[collectionPath];
|
||||
if (!props) {
|
||||
const entityCollection: EntityCollection = getCollectionViewFromPath(collectionPath, navigation);
|
||||
const editEnabled = entityCollection.editEnabled == undefined || entityCollection.editEnabled;
|
||||
const schema = entityCollection.schema;
|
||||
const subcollections = entityCollection.subcollections;
|
||||
props = {
|
||||
editEnabled, schema, subcollections
|
||||
};
|
||||
}
|
||||
return props;
|
||||
};
|
||||
|
||||
const set = (
|
||||
collectionPath: string,
|
||||
sidePanelProps: SchemaSidePanelProps | null
|
||||
) => {
|
||||
if (!sidePanelProps) {
|
||||
delete viewsRef.current[collectionPath];
|
||||
} else {
|
||||
viewsRef.current[collectionPath] = sidePanelProps;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<SchemasRegistryContext.Provider
|
||||
value={{
|
||||
get,
|
||||
set
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</SchemasRegistryContext.Provider>
|
||||
);
|
||||
};
|
||||
@@ -10,33 +10,43 @@ import {
|
||||
isCollectionPath,
|
||||
NavigationEntry
|
||||
} from "../routes/navigation";
|
||||
import { EntitySidePanelProps, SchemaSidePanelProps } from "./model";
|
||||
import { useSchemasRegistryController } from "./SchemaOverrideRegistry";
|
||||
|
||||
const DEFAULT_SIDE_ENTITY = {
|
||||
sidePanels: [],
|
||||
close: () => {
|
||||
},
|
||||
open: (props: {
|
||||
collectionPath: string,
|
||||
entityId?: string,
|
||||
selectedSubcollection?: string,
|
||||
copy?: boolean
|
||||
}) => {
|
||||
open: (props: EntitySidePanelProps & Partial<SchemaSidePanelProps>) => {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
export type SideEntityPanelsController<S extends EntitySchema> = {
|
||||
/**
|
||||
* Close the last panel
|
||||
*/
|
||||
close: () => void;
|
||||
sidePanels: SidePanelProps[];
|
||||
open: (props: {
|
||||
collectionPath: string,
|
||||
entityId?: string,
|
||||
selectedSubcollection?: string,
|
||||
copy?: boolean
|
||||
}) => void;
|
||||
|
||||
/**
|
||||
* List of side entity panels currently open
|
||||
*/
|
||||
sidePanels: EntitySidePanelProps[];
|
||||
|
||||
/**
|
||||
* Open a new entity sideDialog
|
||||
* @param props
|
||||
*/
|
||||
open: (props: EntitySidePanelProps & Partial<SchemaSidePanelProps>) => void;
|
||||
};
|
||||
|
||||
export const SideEntityContext = React.createContext<SideEntityPanelsController<any>>(DEFAULT_SIDE_ENTITY);
|
||||
export const useSideEntityController = () => useContext(SideEntityContext);
|
||||
export const SideEntityPanelsController = React.createContext<SideEntityPanelsController<any>>(DEFAULT_SIDE_ENTITY);
|
||||
|
||||
/**
|
||||
* Get a reference to the controller used to open side dialogs for entity
|
||||
* edition.
|
||||
*/
|
||||
export const useSideEntityController = () => useContext(SideEntityPanelsController);
|
||||
|
||||
interface SideEntityProviderProps {
|
||||
children: React.ReactNode;
|
||||
@@ -51,7 +61,9 @@ export const SideEntityProvider: React.FC<SideEntityProviderProps> = ({
|
||||
const location: any = useLocation();
|
||||
const history = useHistory();
|
||||
const initialised = useRef<boolean>(false);
|
||||
const [sidePanels, setSidePanels] = useState<SidePanelProps[]>([]);
|
||||
const [sidePanels, setSidePanels] = useState<EntitySidePanelProps[]>([]);
|
||||
|
||||
const viewRegistry = useSchemasRegistryController();
|
||||
|
||||
const mainLocation = location.state && location.state["main_location"] ? location.state["main_location"] : location;
|
||||
|
||||
@@ -89,21 +101,26 @@ export const SideEntityProvider: React.FC<SideEntityProviderProps> = ({
|
||||
const newPath = getCMSPathFrom(lastSidePanel.collectionPath);
|
||||
history.replace(newPath);
|
||||
}
|
||||
|
||||
viewRegistry.set(lastSidePanel.collectionPath, null);
|
||||
};
|
||||
|
||||
const open = (props: {
|
||||
collectionPath: string,
|
||||
entityId?: string,
|
||||
selectedSubcollection?: string,
|
||||
copy?: boolean
|
||||
}) => {
|
||||
|
||||
const { collectionPath, entityId, selectedSubcollection, copy } = props;
|
||||
const open = ({
|
||||
collectionPath,
|
||||
entityId,
|
||||
selectedSubcollection,
|
||||
copy,
|
||||
...schemaProps
|
||||
}: EntitySidePanelProps & Partial<SchemaSidePanelProps>) => {
|
||||
|
||||
if (copy && !entityId) {
|
||||
throw Error("If you want to copy an entity you need to provide an entityId");
|
||||
}
|
||||
|
||||
if (schemaProps && Object.keys(schemaProps).length > 0) {
|
||||
viewRegistry.set(collectionPath, schemaProps as SchemaSidePanelProps);
|
||||
}
|
||||
|
||||
const newPath = entityId
|
||||
? getEntityPath(entityId, collectionPath, selectedSubcollection)
|
||||
: getRouterNewEntityPath(collectionPath);
|
||||
@@ -112,7 +129,7 @@ export const SideEntityProvider: React.FC<SideEntityProviderProps> = ({
|
||||
|
||||
// If the side dialog is open currently, we update it
|
||||
if (entityId && lastSidePanel && lastSidePanel?.entityId === entityId) {
|
||||
const updatedPanel: SidePanelProps = {
|
||||
const updatedPanel: EntitySidePanelProps = {
|
||||
...lastSidePanel,
|
||||
selectedSubcollection
|
||||
};
|
||||
@@ -125,7 +142,7 @@ export const SideEntityProvider: React.FC<SideEntityProviderProps> = ({
|
||||
);
|
||||
|
||||
} else {
|
||||
const newPanel: SidePanelProps = {
|
||||
const newPanel: EntitySidePanelProps = {
|
||||
collectionPath,
|
||||
entityId,
|
||||
copy: copy !== undefined && copy,
|
||||
@@ -142,7 +159,7 @@ export const SideEntityProvider: React.FC<SideEntityProviderProps> = ({
|
||||
};
|
||||
|
||||
return (
|
||||
<SideEntityContext.Provider
|
||||
<SideEntityPanelsController.Provider
|
||||
value={{
|
||||
sidePanels,
|
||||
close,
|
||||
@@ -150,24 +167,16 @@ export const SideEntityProvider: React.FC<SideEntityProviderProps> = ({
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</SideEntityContext.Provider>
|
||||
</SideEntityPanelsController.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
export interface SidePanelProps {
|
||||
collectionPath: string;
|
||||
entityId?: string;
|
||||
copy: boolean;
|
||||
selectedSubcollection?: string;
|
||||
}
|
||||
|
||||
function buildSidePanelsFromUrl(path: string, allCollections: EntityCollection[], newFlag: boolean): SidePanelProps[] {
|
||||
function buildSidePanelsFromUrl(path: string, allCollections: EntityCollection[], newFlag: boolean): EntitySidePanelProps[] {
|
||||
|
||||
const navigationViewsForPath: NavigationEntry[] = getCollectionViewsFromPath(path, allCollections);
|
||||
|
||||
let fullPath: string = "";
|
||||
let sidePanels: SidePanelProps[] = [];
|
||||
let sidePanels: EntitySidePanelProps[] = [];
|
||||
for (let i = 0; i < navigationViewsForPath.length; i++) {
|
||||
const navigationEntry = navigationViewsForPath[i];
|
||||
|
||||
@@ -186,7 +195,7 @@ function buildSidePanelsFromUrl(path: string, allCollections: EntityCollection[]
|
||||
);
|
||||
}
|
||||
} else if (navigationEntry.type === "collection") {
|
||||
const lastSidePanel: SidePanelProps = sidePanels[sidePanels.length - 1];
|
||||
const lastSidePanel: EntitySidePanelProps = sidePanels[sidePanels.length - 1];
|
||||
if (lastSidePanel)
|
||||
lastSidePanel.selectedSubcollection = navigationEntry.collection.relativePath;
|
||||
}
|
||||
49
src/side_dialog/model.tsx
Normal file
49
src/side_dialog/model.tsx
Normal file
@@ -0,0 +1,49 @@
|
||||
import { EntityCollection, EntitySchema } from "../models";
|
||||
|
||||
export interface EntitySidePanelProps {
|
||||
/**
|
||||
* Absolute path of the entity
|
||||
*/
|
||||
collectionPath: string;
|
||||
|
||||
/**
|
||||
* Id of the entity, if not set, it means we are creating a new entity
|
||||
*/
|
||||
entityId?: string;
|
||||
|
||||
/**
|
||||
* Set this flag to true if you want to make a copy of an existing entity
|
||||
*/
|
||||
copy?: boolean;
|
||||
|
||||
/**
|
||||
* Open the entity with a selected subcollection view. If the panel for this
|
||||
* entity was already open, it is replaced.
|
||||
*/
|
||||
selectedSubcollection?: string;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* You can add these additional props to override properties
|
||||
*/
|
||||
export interface SchemaSidePanelProps {
|
||||
|
||||
/**
|
||||
* Can the elements in this collection be added and edited. Defaults to `true`
|
||||
*/
|
||||
editEnabled?: boolean;
|
||||
|
||||
/**
|
||||
* Schema representing the entities of this view
|
||||
*/
|
||||
schema: EntitySchema<any>;
|
||||
|
||||
/**
|
||||
* Following the Firestore document and collection schema, you can add
|
||||
* subcollections to your entity in the same way you define the root
|
||||
* collections.
|
||||
*/
|
||||
subcollections?: EntityCollection[];
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user