Removed schema registry and merged with navigation context

This commit is contained in:
francesco
2021-12-07 18:14:39 +01:00
parent ba59a01d01
commit 3d2e592fb4
18 changed files with 264 additions and 367 deletions

View File

@@ -26,8 +26,6 @@ import { BreadcrumbsProvider } from "./contexts/BreacrumbsContext";
import { ModeProvider, ModeStateContext } from "./contexts/ModeState";
import { useBuildSideEntityController } from "./internal/useBuildSideEntityController";
import { useBuildNavigationContext } from "./internal/useBuildNavigationContext";
import { useBuildSchemaRegistryController } from "./contexts/useBuildSchemaRegistryController";
import { useBuildAuthController } from "./internal/useBuildAuthController";
const DEFAULT_COLLECTION_PATH = `/c`;
@@ -180,11 +178,11 @@ export function FireCMS<UserType>(props: FireCMSProps<UserType>) {
dateTimeFormat,
locale,
dataSource,
storageSource
storageSource,
schemaOverrideHandler
});
const schemaRegistryController = useBuildSchemaRegistryController(navigationContext, schemaOverrideHandler);
const sideEntityController = useBuildSideEntityController(navigationContext, schemaRegistryController);
const sideEntityController = useBuildSideEntityController(navigationContext);
const loading = authController.authLoading || authController.initialLoading || navigationContext.loading;
@@ -212,7 +210,6 @@ export function FireCMS<UserType>(props: FireCMSProps<UserType>) {
navigationContext,
dataSource,
storageSource,
schemaRegistryController,
snackbarController
};

View File

@@ -3,13 +3,12 @@ import { EntityCollectionResolver, SideEntityPanelProps } from "../models";
import { SideDialogDrawer } from "./internal/SideDialogDrawer";
import { EntityView } from "./internal/EntityView";
import { CONTAINER_WIDTH } from "./internal/common";
import { useSideEntityController } from "../hooks";
import { useNavigation, useSideEntityController } from "../hooks";
import { ErrorBoundary } from "./internal/ErrorBoundary";
import {
UnsavedChangesDialog,
useNavigationUnsavedChangesDialog
} from "./internal/useUnsavedChangesDialog";
import { useSchemaRegistryController } from "../hooks/useSchemaRegistryController";
import { computeSchema } from "./utils";
/**
@@ -79,8 +78,8 @@ function SideEntityDialog({
};
const sideEntityController = useSideEntityController();
const schemaRegistry = useSchemaRegistryController();
const schemaProps: EntityCollectionResolver | undefined = schemaRegistry.getSchemaConfig(panel.path, panel.entityId);
const navigationContext = useNavigation();
const schemaProps: EntityCollectionResolver | undefined = navigationContext.getCollectionResolver(panel.path, panel.entityId);
if (!schemaProps) {
throw Error("ERROR: You are trying to open an entity with no schema defined.");
}

View File

@@ -14,7 +14,7 @@ import { ReferenceDialog } from "../../../ReferenceDialog";
import { getPreviewSizeFrom } from "../../../../../preview/util";
import { useInputStyles } from "./styles";
import { getReferenceFrom } from "../../../../utils";
import { useFireCMSContext } from "../../../../../hooks";
import { useFireCMSContext, useNavigation } from "../../../../../hooks";
export function TableReferenceField<M extends { [Key: string]: any }>(props: {
@@ -55,8 +55,8 @@ export function TableReferenceField<M extends { [Key: string]: any }>(props: {
const [onHover, setOnHover] = useState(false);
const [open, setOpen] = useState<boolean>(false);
const schemaRegistry = useFireCMSContext().schemaRegistryController;
const collectionResolver = schemaRegistry.getCollectionResolver(path);
const navigationContext = useNavigation();
const collectionResolver = navigationContext.getCollectionResolver(path);
if (!collectionResolver) {
throw Error(`Couldn't find the corresponding collection view for the path: ${path}`);
}

View File

@@ -28,10 +28,9 @@ import { canCreate, canDelete, canEdit } from "../util/permissions";
import { Markdown } from "../../preview";
import {
useAuthController,
useFireCMSContext,
useFireCMSContext, useNavigation,
useSideEntityController
} from "../../hooks";
import { useSchemaRegistryController } from "../../hooks/useSchemaRegistryController";
import { useCollectionPersist } from "../internal/useCollectionPersist";
/**
@@ -109,7 +108,7 @@ export function EntityCollectionView<M extends { [Key: string]: any }>({
const sideEntityController = useSideEntityController();
const context = useFireCMSContext();
const authController = useAuthController();
const schemaRegistry = useSchemaRegistryController();
const navigationContext = useNavigation();
const theme = useTheme();
const largeLayout = useMediaQuery(theme.breakpoints.up("md"));
@@ -122,7 +121,7 @@ export function EntityCollectionView<M extends { [Key: string]: any }>({
const collection = persistedCollection ?? baseCollection;
const schemaConfig = schemaRegistry.getSchemaConfig(path);
const schemaConfig = navigationContext.getCollectionResolver<M>(path);
if (!schemaConfig) {
throw Error(`Couldn't find the corresponding schemaConfig for the path: ${path}`);
}

View File

@@ -5,7 +5,6 @@ import { FireCMSContext } from "../../models";
export const FireCMSContextInstance = React.createContext<FireCMSContext>({
sideEntityController: {} as any,
navigationContext: {} as any,
schemaRegistryController: {} as any,
dataSource: {} as any,
storageSource: {} as any,
authController: {} as any,

View File

@@ -1,198 +0,0 @@
import React, { useRef } from "react";
import {
EntityCollection,
EntityCollectionResolver,
EntitySchema,
EntitySchemaResolver,
EntitySchemaResolverProps,
NavigationContext,
PartialEntityCollection,
PartialProperties,
SchemaOverrideHandler,
SchemaRegistryController
} from "../../models";
import { removeInitialAndTrailingSlashes } from "../util/navigation_utils";
import { computeProperties } from "../utils";
import { getValueInPath, mergeDeep } from "../util/objects";
export function useBuildSchemaRegistryController(
navigationContext: NavigationContext,
schemaOverrideHandler: SchemaOverrideHandler | undefined
): SchemaRegistryController {
const initialised = navigationContext.navigation?.collections !== undefined;
const schemaConfigRecord = useRef<Record<string, Partial<EntityCollectionResolver> & { overrideSchemaRegistry?: boolean }>>({});
const getSchemaConfig = <M extends any>(path: string, entityId?: string): EntityCollectionResolver<M> => {
const sidePanelKey = getSidePanelKey(path, entityId);
let result: Partial<EntityCollectionResolver> = {};
const overriddenProps = schemaConfigRecord.current[sidePanelKey];
const resolvedProps: Partial<EntityCollectionResolver> | undefined = schemaOverrideHandler && schemaOverrideHandler({
entityId,
path: removeInitialAndTrailingSlashes(path)
});
if (resolvedProps)
result = resolvedProps;
if (overriddenProps) {
// override schema resolver default to true
const shouldOverrideRegistry = overriddenProps.overrideSchemaRegistry === undefined || overriddenProps.overrideSchemaRegistry;
if (shouldOverrideRegistry)
result = {
...overriddenProps,
permissions: result.permissions || overriddenProps.permissions,
schemaResolver: result.schemaResolver || overriddenProps.schemaResolver,
subcollections: result.subcollections || overriddenProps.subcollections,
callbacks: result.callbacks || overriddenProps.callbacks
};
else
result = {
...result,
permissions: overriddenProps.permissions ?? result.permissions,
schemaResolver: overriddenProps.schemaResolver ?? result.schemaResolver,
subcollections: overriddenProps.subcollections ?? result.subcollections,
callbacks: overriddenProps.callbacks ?? result.callbacks
};
}
const entityCollection: EntityCollection | undefined = navigationContext.getCollection(path);
if (entityCollection) {
const schema = entityCollection.schema;
const subcollections = entityCollection.subcollections;
const callbacks = entityCollection.callbacks;
const permissions = entityCollection.permissions;
result = {
...result,
schemaResolver: result.schemaResolver ?? buildSchemaResolver({
schema,
path
}),
subcollections: result.subcollections ?? subcollections,
callbacks: result.callbacks ?? callbacks,
permissions: result.permissions ?? permissions
};
}
if (!result.schemaResolver) {
if (!result.schema)
throw Error(`Not able to resolve schema for ${sidePanelKey}`);
result.schemaResolver = buildSchemaResolver({
schema: result.schema,
path
});
}
return result as EntityCollectionResolver<M>;
};
const getCollectionResolver = <M extends any>(path: string): EntityCollectionResolver<M> => {
const collection = navigationContext.getCollection<M>(path);
if (!collection) {
throw Error(`No collection found for path ${path}`);
}
const schemaConfig = getSchemaConfig<M>(path);
if (!schemaConfig) {
throw Error(`No schema config found for path ${path}`);
}
return { ...collection, ...schemaConfig };
};
const setOverride = ({
path,
entityId,
schemaConfig,
overrideSchemaRegistry
}: {
path: string,
entityId?: string,
schemaConfig?: Partial<EntityCollectionResolver>
overrideSchemaRegistry?: boolean
}
) => {
const key = getSidePanelKey(path, entityId);
if (!schemaConfig) {
delete schemaConfigRecord.current[key];
return undefined;
} else {
schemaConfigRecord.current[key] = {
...schemaConfig,
overrideSchemaRegistry
};
return key;
}
};
const onCollectionModifiedForUser = <M extends any>(path: string, partialCollection: PartialEntityCollection<M>) => {
navigationContext.onCollectionModifiedForUser(path, partialCollection);
}
const removeAllOverridesExcept = (entityRefs: {
path: string, entityId?: string
}[]) => {
const keys = entityRefs.map(({
path,
entityId
}) => getSidePanelKey(path, entityId));
Object.keys(schemaConfigRecord.current).forEach((currentKey) => {
if (!keys.includes(currentKey))
delete schemaConfigRecord.current[currentKey];
});
};
function buildSchemaResolver<M>({
schema,
path
}: { schema: EntitySchema<M>, path: string }): EntitySchemaResolver {
return ({
entityId,
values,
}: EntitySchemaResolverProps) => {
const schemaOverride = navigationContext.getSchemaOverride(path);
const storedProperties: PartialProperties<M> | undefined = getValueInPath(schemaOverride, "properties");
const properties = computeProperties({
propertiesOrBuilder: schema.properties,
path,
entityId,
values: values ?? schema.defaultValues
});
return {
...schema,
properties: mergeDeep(properties, storedProperties)
};
};
}
return {
initialised,
getSchemaConfig,
getCollectionResolver,
setOverride,
removeAllOverridesExcept,
onCollectionModifiedForUser
};
}
export function getSidePanelKey(path: string, entityId?: string) {
if (entityId)
return `${removeInitialAndTrailingSlashes(path)}/${removeInitialAndTrailingSlashes(entityId)}`;
else
return removeInitialAndTrailingSlashes(path);
}

View File

@@ -1,14 +1,20 @@
import React, { useEffect, useState } from "react";
import React, { useEffect, useRef, useState } from "react";
import {
AuthController,
DataSource,
EntityCollection,
EntityCollectionResolver,
EntitySchema,
EntitySchemaResolver,
EntitySchemaResolverProps,
Locale,
Navigation,
NavigationBuilder,
NavigationContext,
PartialEntityCollection,
PartialProperties,
PartialSchema,
SchemaOverrideHandler,
StorageSource,
User
} from "../../models";
@@ -20,13 +26,15 @@ import {
getStorageCollectionConfig,
saveStorageCollectionConfig
} from "../util/storage";
import { mergeDeep } from "../util/objects";
import { getValueInPath, mergeDeep } from "../util/objects";
import { computeProperties } from "../utils";
export function useBuildNavigationContext<UserType>({
basePath,
baseCollectionPath,
authController,
navigationOrBuilder,
schemaOverrideHandler,
dateTimeFormat,
locale,
dataSource,
@@ -36,6 +44,7 @@ export function useBuildNavigationContext<UserType>({
baseCollectionPath: string,
authController: AuthController<UserType>;
navigationOrBuilder: Navigation | NavigationBuilder<UserType> | EntityCollection[];
schemaOverrideHandler: SchemaOverrideHandler | undefined;
dateTimeFormat?: string;
locale?: Locale;
dataSource: DataSource;
@@ -46,6 +55,177 @@ export function useBuildNavigationContext<UserType>({
const [navigationLoading, setNavigationLoading] = useState<boolean>(false);
const [navigationLoadingError, setNavigationLoadingError] = useState<Error | undefined>(undefined);
const schemaConfigRecord = useRef<Record<string, Partial<EntityCollectionResolver> & { overrideSchemaRegistry?: boolean }>>({});
const cleanBasePath = removeInitialAndTrailingSlashes(basePath);
const cleanBaseCollectionPath = removeInitialAndTrailingSlashes(baseCollectionPath);
const homeUrl = cleanBasePath ? `/${cleanBasePath}` : "/";
const fullCollectionPath = cleanBasePath ? `/${cleanBasePath}/${cleanBaseCollectionPath}` : `/${cleanBaseCollectionPath}`;
const initialised = navigation?.collections !== undefined;
useEffect(() => {
if (!authController.canAccessMainView) {
return;
}
setNavigationLoading(true);
getNavigation({
navigationOrCollections: navigationOrBuilder,
user: authController.user,
authController,
dateTimeFormat,
locale,
dataSource,
storageSource
})
.then((result: Navigation) => {
setNavigation(result);
setNavigationLoading(false);
}).catch(setNavigationLoadingError);
}, [authController.user, authController.canAccessMainView, navigationOrBuilder]);
const getCollectionResolver = <M extends any>(path: string, entityId?: string): EntityCollectionResolver<M> => {
const collection = getCollection<M>(path);
// if (!collection) {
// throw Error(`No collection found for path ${path}`);
// }
const sidePanelKey = getSidePanelKey(path, entityId);
let result: Partial<EntityCollectionResolver> = {};
const overriddenProps = schemaConfigRecord.current[sidePanelKey];
const resolvedProps: Partial<EntityCollectionResolver> | undefined = schemaOverrideHandler && schemaOverrideHandler({
entityId,
path: removeInitialAndTrailingSlashes(path)
});
if (resolvedProps)
result = resolvedProps;
if (overriddenProps) {
// override schema resolver default to true
const shouldOverrideRegistry = overriddenProps.overrideSchemaRegistry === undefined || overriddenProps.overrideSchemaRegistry;
if (shouldOverrideRegistry)
result = {
...overriddenProps,
permissions: result.permissions || overriddenProps.permissions,
schemaResolver: result.schemaResolver || overriddenProps.schemaResolver,
subcollections: result.subcollections || overriddenProps.subcollections,
callbacks: result.callbacks || overriddenProps.callbacks
};
else
result = {
...result,
permissions: overriddenProps.permissions ?? result.permissions,
schemaResolver: overriddenProps.schemaResolver ?? result.schemaResolver,
subcollections: overriddenProps.subcollections ?? result.subcollections,
callbacks: overriddenProps.callbacks ?? result.callbacks
};
}
const entityCollection: EntityCollection | undefined = getCollection(path);
if (entityCollection) {
const schema = entityCollection.schema;
const subcollections = entityCollection.subcollections;
const callbacks = entityCollection.callbacks;
const permissions = entityCollection.permissions;
result = {
...result,
schemaResolver: result.schemaResolver ?? buildSchemaResolver({
schema,
path
}),
subcollections: result.subcollections ?? subcollections,
callbacks: result.callbacks ?? callbacks,
permissions: result.permissions ?? permissions
};
}
if (!result.schemaResolver) {
if (!result.schema)
throw Error(`Not able to resolve schema for ${sidePanelKey}`);
result.schemaResolver = buildSchemaResolver({
schema: result.schema,
path
});
}
return { ...collection, ...(result as EntityCollectionResolver<M>) };
};
const setOverride = ({
path,
entityId,
schemaConfig,
overrideSchemaRegistry
}: {
path: string,
entityId?: string,
schemaConfig?: Partial<EntityCollectionResolver>
overrideSchemaRegistry?: boolean
}
) => {
const key = getSidePanelKey(path, entityId);
if (!schemaConfig) {
delete schemaConfigRecord.current[key];
return undefined;
} else {
schemaConfigRecord.current[key] = {
...schemaConfig,
overrideSchemaRegistry
};
return key;
}
};
const removeAllOverridesExcept = (entityRefs: {
path: string, entityId?: string
}[]) => {
const keys = entityRefs.map(({
path,
entityId
}) => getSidePanelKey(path, entityId));
Object.keys(schemaConfigRecord.current).forEach((currentKey) => {
if (!keys.includes(currentKey))
delete schemaConfigRecord.current[currentKey];
});
};
function buildSchemaResolver<M>({
schema,
path
}: { schema: EntitySchema<M>, path: string }): EntitySchemaResolver {
return ({
entityId,
values,
}: EntitySchemaResolverProps) => {
const collectionOverride = getCollectionOverride<M>(path);
const schemaOverride = collectionOverride?.schema;
const storedProperties: PartialProperties<M> | undefined = getValueInPath(schemaOverride, "properties");
const properties = computeProperties({
propertiesOrBuilder: schema.properties,
path,
entityId,
values: values ?? schema.defaultValues
});
return {
...schema,
properties: mergeDeep(properties, storedProperties)
};
};
}
async function getNavigation<UserType>({ navigationOrCollections, user, authController, dateTimeFormat, locale, dataSource, storageSource }:
{
navigationOrCollections: Navigation | NavigationBuilder<UserType> | EntityCollection[],
@@ -69,34 +249,6 @@ export function useBuildNavigationContext<UserType>({
}
}
useEffect(() => {
if (!authController.canAccessMainView) {
return;
}
setNavigationLoading(true);
getNavigation({
navigationOrCollections: navigationOrBuilder,
user: authController .user,
authController,
dateTimeFormat,
locale,
dataSource,
storageSource
})
.then((result: Navigation) => {
setNavigation(result);
setNavigationLoading(false);
}).catch(setNavigationLoadingError);
}, [authController.user, authController.canAccessMainView, navigationOrBuilder]);
const cleanBasePath = removeInitialAndTrailingSlashes(basePath);
const cleanBaseCollectionPath = removeInitialAndTrailingSlashes(baseCollectionPath);
const homeUrl = cleanBasePath ? `/${cleanBasePath}` : "/";
const fullCollectionPath = cleanBasePath ? `/${cleanBasePath}/${cleanBaseCollectionPath}` : `/${cleanBaseCollectionPath}`;
function isUrlCollectionPath(path: string): boolean {
return removeInitialAndTrailingSlashes(path + "/").startsWith(removeInitialAndTrailingSlashes(fullCollectionPath) + "/");
}
@@ -132,31 +284,39 @@ export function useBuildNavigationContext<UserType>({
const collection = getCollectionFromCollections<M>(removeInitialAndTrailingSlashes(path), collections);
const dynamicCollectionConfig = { ...getStorageCollectionConfig(path) };
const dynamicCollectionConfig = { ...getCollectionOverride(path) };
delete dynamicCollectionConfig["schema"];
return collection ? mergeDeep(collection, dynamicCollectionConfig) : undefined;
}
const getSchemaOverride = <M extends any>(path: string): PartialSchema<M> | undefined => {
let storageCollectionConfig = getStorageCollectionConfig<M>(path);
if (!storageCollectionConfig) return undefined;
return storageCollectionConfig.schema;
const getCollectionOverride = <M extends any>(path: string): PartialEntityCollection<M> | undefined => {
return getStorageCollectionConfig<M>(path);
}
return {
navigation,
loading: navigationLoading,
navigationLoadingError,
isUrlCollectionPath,
urlPathToDataPath,
buildUrlCollectionPath,
buildCMSUrlPath,
homeUrl,
basePath,
baseCollectionPath,
onCollectionModifiedForUser,
getCollection,
getSchemaOverride
initialised,
getCollectionResolver,
setOverride,
removeAllOverridesExcept,
isUrlCollectionPath,
urlPathToDataPath,
buildUrlCollectionPath,
buildCMSUrlPath,
};
}
}
export function getSidePanelKey(path: string, entityId?: string) {
if (entityId)
return `${removeInitialAndTrailingSlashes(path)}/${removeInitialAndTrailingSlashes(entityId)}`;
else
return removeInitialAndTrailingSlashes(path);
}

View File

@@ -2,7 +2,6 @@ import React, { useCallback, useEffect, useRef, useState } from "react";
import {
EntityCollection,
NavigationContext,
SchemaRegistryController,
SideEntityController,
SideEntityPanelProps
} from "../../models";
@@ -15,7 +14,7 @@ import { removeInitialAndTrailingSlashes } from "../util/navigation_utils";
const NEW_URL_HASH = "new";
export const useBuildSideEntityController = (navigationContext: NavigationContext, schemaRegistry: SchemaRegistryController): SideEntityController => {
export const useBuildSideEntityController = (navigationContext: NavigationContext): SideEntityController => {
const location = useLocation();
const navigate = useNavigate();
@@ -28,11 +27,11 @@ export const useBuildSideEntityController = (navigationContext: NavigationContex
const updatePanels = useCallback((newPanels: SideEntityPanelProps[]) => {
setSidePanels(newPanels);
schemaRegistry.removeAllOverridesExcept(newPanels);
navigationContext.removeAllOverridesExcept(newPanels);
}, []);
useEffect(() => {
if (schemaRegistry.initialised) {
if (navigationContext.initialised) {
if (location?.state && location.state["panels"]) {
const statePanel = location.state["panels"] as SideEntityPanelProps[];
updatePanels(statePanel);
@@ -40,7 +39,7 @@ export const useBuildSideEntityController = (navigationContext: NavigationContex
updatePanels([]);
}
}
}, [location?.state, schemaRegistry.initialised]);
}, [location?.state, navigationContext.initialised]);
// only on initialisation
useEffect(() => {
@@ -95,7 +94,7 @@ export const useBuildSideEntityController = (navigationContext: NavigationContex
const schemaOrResolver = schemaProps.schema;
const subcollections = schemaProps.subcollections;
const overrideSchemaRegistry = schemaProps.overrideSchemaRegistry;
schemaRegistry.setOverride(
navigationContext.setOverride(
{
path,
entityId,

View File

@@ -1,14 +1,14 @@
import { useMemo, useState } from "react";
import { EntityCollection, PartialEntityCollection } from "../../models";
import { mergeDeep } from "../util/objects";
import { useSchemaRegistryController } from "../../hooks/useSchemaRegistryController";
import { useNavigation } from "../../hooks";
export function useCollectionPersist<M>({
path,
}: { path: string }) {
const schemaRegistry = useSchemaRegistryController();
const collectionResolver = schemaRegistry.getCollectionResolver(path);
const navigationContext = useNavigation();
const collectionResolver = navigationContext.getCollectionResolver(path);
if (!collectionResolver) {
throw Error(`Couldn't find the corresponding collection view for the path: ${path}`);
}
@@ -18,7 +18,7 @@ export function useCollectionPersist<M>({
const onCollectionModifiedForUser = (partialCollection: PartialEntityCollection<M>) => {
const newCollection: PartialEntityCollection<M> = mergeDeep(modifiedCollection, partialCollection);
schemaRegistry.onCollectionModifiedForUser(path, newCollection);
navigationContext.onCollectionModifiedForUser(path, newCollection);
setModifiedCollection(newCollection);
}

View File

@@ -11,9 +11,8 @@ import { ReferencePreview } from "../../preview";
import { ArrayContainer, FieldDescription, LabelWithIcon } from "../components";
import { ErrorView, ReferenceDialog } from "../../core";
import { formStyles } from "../styles";
import { useClearRestoreValue } from "../../hooks";
import { useClearRestoreValue, useNavigation } from "../../hooks";
import { getReferenceFrom } from "../../core/utils";
import { useSchemaRegistryController } from "../../hooks/useSchemaRegistryController";
type ArrayOfReferencesFieldProps = FieldProps<EntityReference[]>;
@@ -54,9 +53,9 @@ export function ArrayOfReferencesField({
setValue
});
const schemaRegistry = useSchemaRegistryController();
const navigationContext = useNavigation();
const collectionResolver: EntityCollectionResolver | undefined = useMemo(() => {
return schemaRegistry.getCollectionResolver(ofProperty.path);
return navigationContext.getCollectionResolver(ofProperty.path);
}, [ofProperty.path]);
if (!collectionResolver) {

View File

@@ -33,11 +33,10 @@ import { PreviewComponent, SkeletonComponent } from "../../preview";
import { LabelWithIcon } from "../components";
import {
useClearRestoreValue,
useEntityFetch,
useEntityFetch, useNavigation,
useSideEntityController
} from "../../hooks";
import { getReferenceFrom } from "../../core/utils";
import { useSchemaRegistryController } from "../../hooks/useSchemaRegistryController";
export const useStyles = makeStyles((theme: Theme) => createStyles({
root: {
@@ -127,9 +126,9 @@ export function ReferenceField<M extends { [Key: string]: any }>({
const [open, setOpen] = React.useState(autoFocus);
const sideEntityController = useSideEntityController();
const schemaRegistry = useSchemaRegistryController();
const navigationContext = useNavigation();
const collectionResolver: EntityCollectionResolver | undefined = useMemo(() => {
return schemaRegistry.getCollectionResolver(property.path);
return navigationContext.getCollectionResolver(property.path);
}, [property.path]);
if (!collectionResolver) {

View File

@@ -68,16 +68,13 @@ export function resolveNavigationFrom<M, UserType>({
const dataSource = context.dataSource;
const navigationContext = context.navigationContext;
const navigation = context.navigationContext.navigation;
const schemaRegistry = context.schemaRegistryController;
if (!navigation) {
throw Error("Calling getNavigationFrom, but main navigation has not yet been initialised");
}
if (!schemaRegistry) {
throw Error("Calling getNavigationFrom, but main schemaRegistryController has not yet been initialised");
}
const navigationEntries = getNavigationEntriesFromPathInternal({
path,
@@ -88,7 +85,7 @@ export function resolveNavigationFrom<M, UserType>({
if (entry.type === "collection") {
return Promise.resolve(entry);
} else if (entry.type === "entity") {
const entityCollectionResolver = schemaRegistry.getSchemaConfig(entry.path, entry.entityId);
const entityCollectionResolver = navigationContext.getCollectionResolver(entry.path, entry.entityId);
if (!entityCollectionResolver?.schemaResolver) {
throw Error(`No schema defined in the navigation for the entity with path ${entry.path}`);
}

View File

@@ -1,16 +0,0 @@
import { AuthController, SchemaRegistryController } from "../models";
import { useFireCMSContext } from "./useFireCMSContext";
/**
* Hook to retrieve the Schema registry controller.
*
* Consider that in order to use this hook you need to have a parent
* `FireCMS`
*
* @see AuthController
* @category Hooks and utilities
*/
export function useSchemaRegistryController(): SchemaRegistryController {
const context = useFireCMSContext();
return context.schemaRegistryController;
}

View File

@@ -1,7 +1,6 @@
import { Locale } from "./locales";
import { DataSource } from "./datasource";
import { StorageSource } from "./storage";
import { SchemaRegistryController } from "./schema_registry_controller";
import { NavigationContext } from "./navigation";
import { SideEntityController } from "./side_entity_controller";
import { AuthController } from "./auth";
@@ -39,14 +38,6 @@ export interface FireCMSContext<UserType extends User = User> {
*/
storageSource: StorageSource;
/**
* This controller is in charge of resolving the entity schemas from a given
* path. It takes into account the `navigation` prop set in the main level of the
* CMSApp as well as the `schemaResolver` in case you want to override schemas
* to specific entities.
*/
schemaRegistryController: SchemaRegistryController;
/**
* Context that includes the resolved navigation and utility methods and
* attributes.

View File

@@ -12,7 +12,6 @@ export * from "./fields";
export * from "./datasource";
export * from "./entity_link_builder";
export * from "./side_entity_controller";
export * from "./schema_registry_controller";
export * from "./firecms_context";
export * from "./entity_callbacks";
export * from "./overrides";

View File

@@ -87,14 +87,40 @@ export type NavigationContext = {
navigationLoadingError?: any;
getCollection: <M>(path: string) => EntityCollection<M> | undefined;
getSchemaOverride: <M>(path: string) => PartialSchema<M> | undefined;
/**
* Is the registry ready to be used
*/
initialised: boolean;
/**
* Set props for path
* @return used key
*/
setOverride: <M>(props: {
path: string,
entityId?: string,
schemaConfig?: Partial<EntityCollectionResolver>
overrideSchemaRegistry?: boolean
}
) => string | undefined;
/**
* Get the schema configuration for a given path
*/
getCollectionResolver: <M>(path: string, entityId?: string) => EntityCollectionResolver<M> | undefined;
/**
* Remove all keys not used
* @param used keys
*/
removeAllOverridesExcept: (entityRefs: {
path: string, entityId?: string
}[]) => void;
/**
* Use this callback when a collection has been modified so it is persisted.
*/
onCollectionModifiedForUser: <M>(path: string, partialCollection: PartialEntityCollection<M>) => void;
onCollectionModifiedForUser: <M>(path:string, partialCollection: PartialEntityCollection<M>) => void;
/**
* Default path under the navigation routes of the CMS will be created

View File

@@ -1,53 +0,0 @@
import { EntityCollectionResolver } from "./collections";
import { PartialEntityCollection } from "./overrides";
/**
* This controller is in charge of resolving the entity schemas from a given
* path. It takes into account the `navigation` prop set in the main level of the
* `FireCMS` app as well as the `schemaResolver` in case you want to override schemas
* to specific entities.
*
* @category Hooks and utilities
*/
export interface SchemaRegistryController {
/**
* Is the registry ready to be used
*/
initialised: boolean;
/**
* Set props for path
* @return used key
*/
setOverride: <M>(props: {
path: string,
entityId?: string,
schemaConfig?: Partial<EntityCollectionResolver>
overrideSchemaRegistry?: boolean
}
) => string | undefined;
/**
* Get the schema configuration for a given path
*/
getSchemaConfig: (path: string, entityId?: string) => EntityCollectionResolver | undefined;
/**
* Get the entity collection for a given path
*/
getCollectionResolver: <M>(path: string) => EntityCollectionResolver<M> | undefined;
/**
* Remove all keys not used
* @param used keys
*/
removeAllOverridesExcept: (entityRefs: {
path: string, entityId?: string
}[]) => void;
/**
* Use this callback when a collection has been modified so it is persisted.
*/
onCollectionModifiedForUser: <M>(path:string, partialCollection: PartialEntityCollection<M>) => void;
}

View File

@@ -26,7 +26,7 @@ import { SkeletonComponent } from "./SkeletonComponent";
import { ErrorView } from "../../core";
import {
useEntityFetch,
useFireCMSContext,
useFireCMSContext, useNavigation,
useSideEntityController
} from "../../hooks";
@@ -105,10 +105,10 @@ function ReferencePreviewComponent<M extends { [Key: string]: any }>(
const reference: EntityReference = value;
const previewProperties = property.previewProperties;
const schemaRegistry = useFireCMSContext().schemaRegistryController;
const navigationContext = useNavigation();
const sideEntityController = useSideEntityController();
const collectionResolver = schemaRegistry.getCollectionResolver<M>(property.path);
const collectionResolver = navigationContext.getCollectionResolver<M>(property.path);
if (!collectionResolver) {
throw Error(`Couldn't find the corresponding collection view for the path: ${property.path}`);
}