Refactor of Routes to use React Router 6

This commit is contained in:
francesco
2021-09-13 21:51:10 +02:00
parent 385a9d3be2
commit 32ecb65f20
22 changed files with 265 additions and 344 deletions

View File

@@ -2,7 +2,7 @@ import React from "react";
import { FirebaseApp } from "firebase/app";
import { GoogleAuthProvider } from "firebase/auth";
import { ThemeProvider, CssBaseline } from "@mui/material";
import { CssBaseline, ThemeProvider } from "@mui/material";
import { BrowserRouter as Router } from "react-router-dom";
import "typeface-rubik";
@@ -15,16 +15,17 @@ import {
buildSchema,
CircularProgressCenter,
CMSAppProvider,
CMSMainView,
CMSRoutes,
CMSScaffold,
createCMSDefaultTheme,
EntityLinkBuilder,
FirebaseLoginView,
initialiseFirebase,
NavigationBuilder,
NavigationBuilderProps,
useFirebaseAuthHandler,
useFirebaseStorageSource,
useFirestoreDataSource
useFirestoreDataSource,
useInitialiseFirebase
} from "@camberi/firecms";
import { firebaseConfig } from "./firebase_config";
@@ -95,7 +96,7 @@ export function SimpleAppWithProvider() {
firebaseConfigLoading,
configError,
firebaseConfigError
} = initialiseFirebase({ firebaseConfig });
} = useInitialiseFirebase({ firebaseConfig });
if (configError) {
return <div> {configError} </div>;
@@ -139,7 +140,7 @@ export function SimpleAppWithProvider() {
storageSource={storageSource}>
{({ context }) => {
if (context.authController.authLoading) {
if (context.authController.authLoading || !context.navigation) {
return <CircularProgressCenter/>;
}
@@ -152,11 +153,14 @@ export function SimpleAppWithProvider() {
);
}
return <CMSMainView name={"My Online Shop"}/>;
return (
<CMSScaffold name={"My Online Shop"}>
<CMSRoutes navigation={context.navigation}/>
</CMSScaffold>);
}}
</CMSAppProvider>
</Router>
</ThemeProvider>
);
);
}

View File

@@ -35,15 +35,11 @@
},
"dependencies": {
"@date-io/date-fns": "^1.3.11",
"@types/deep-equal": "^1.0.1",
"@types/react-measure": "^2.0.6",
"@uiw/react-md-editor": "^3.4.10",
"date-fns": "^2.21.3",
"deep-equal": "^2.0.5",
"firebaseui": "~0.600",
"formik": "^2.2.6",
"history": "^5.0.0",
"material-ui-popup-state": "^1.8.3",
"object-hash": "^2.1.1",
"react-base-table": "^1.12.0",
"react-csv": "^2.0.3",
@@ -51,8 +47,8 @@
"react-dnd-html5-backend": "^14.0.0",
"react-dropzone": "^11.3.2",
"react-measure": "^2.5.2",
"react-router": "^6.0.0-beta.0",
"react-router-dom": "^6.0.0-beta.0",
"react-router": "^6.0.0-beta.4",
"react-router-dom": "^6.0.0-beta.4",
"react-transition-group": "^4.4.1",
"typeface-roboto": "^1.1.13",
"typeface-rubik": "^1.1.13",
@@ -63,10 +59,10 @@
"peerDependencies": {
"@emotion/react": "latest",
"@emotion/styled": "latest",
"@mui/material": "next",
"@mui/styles": "next",
"@mui/icons-material": "next",
"@mui/lab": "next",
"@mui/material": "next",
"@mui/styles": "next",
"algoliasearch": "^4.9.1",
"firebase": "^9.0.0",
"react": "^17.0.2",
@@ -82,11 +78,13 @@
"devDependencies": {
"@emotion/react": "latest",
"@emotion/styled": "latest",
"@mui/material": "next",
"@mui/styles": "next",
"@mui/icons-material": "next",
"@mui/lab": "next",
"@mui/material": "next",
"@mui/styles": "next",
"@rollup/plugin-typescript": "^8.2.1",
"@types/deep-equal": "^1.0.1",
"@types/react-measure": "^2.0.6",
"@types/jest": "^26.0.23",
"@types/node": "^15.0.2",
"@types/object-hash": "^2.1.0",

View File

@@ -95,7 +95,7 @@ export const SideEntityProvider: React.FC<SideEntityProviderProps> = ({
const schemasRegistry = useSchemasRegistry();
const basePathname = location.state && location.state["base_pathname"] ? location.state["base_pathname"] : location.pathname;
const baseLocation = location.state && location.state["base_location"] ? location.state["base_location"] : location;
useEffect(() => {
if (schemasRegistry.initialised) {
@@ -194,7 +194,7 @@ export const SideEntityProvider: React.FC<SideEntityProviderProps> = ({
{
replace: true,
state: {
base_pathname: basePathname,
base_location: baseLocation,
panels: [...sidePanels.slice(0, -1), updatedPanel]
}
}
@@ -212,7 +212,7 @@ export const SideEntityProvider: React.FC<SideEntityProviderProps> = ({
newPath,
{
state: {
base_pathname: basePathname,
base_location: baseLocation,
panels: [...sidePanels, newPanel]
}
}

View File

@@ -1,102 +0,0 @@
import React from "react";
import { useLocation } from "react-router-dom";
import { Navigation } from "../models";
import { addInitialSlash, buildCollectionUrlPath } from "./navigation";
import CollectionRoute from "./internal/CollectionRoute";
import CMSViewRoute from "./internal/CMSViewRoute";
import HomeRoute from "./internal/HomeRoute";
export function CMSRouterSwitch({ navigation }: {
navigation: Navigation
}) {
const location = useLocation();
const basePathname = location.state && location.state["base_pathname"] ? location.state["base_pathname"] : location.pathname;
if (addInitialSlash(basePathname) === "/")
return <HomeRoute navigation={navigation}/>;
const matchedCollection = [...navigation.collections]
// we reorder collections so that nested paths are included first
.sort((a, b) => b.relativePath.length - a.relativePath.length)
.find(entityCollection => {
return addInitialSlash(buildCollectionUrlPath(entityCollection)) === addInitialSlash(basePathname);
});
if (matchedCollection) {
return <CollectionRoute
key={`col_${matchedCollection.relativePath}`}
path={matchedCollection.relativePath}
collectionConfig={matchedCollection}
/>;
}
if (navigation.views) {
const matchedView = [...navigation.views].find(view => {
if (Array.isArray(view.path)) {
const matchedPath = view.path.find((p) => addInitialSlash(p) === addInitialSlash(basePathname));
return matchedPath !== undefined;
} else {
return addInitialSlash(view.path) === addInitialSlash(basePathname);
}
});
if (matchedView) {
return <CMSViewRoute cmsView={matchedView}/>;
}
}
return <></>;
// TODO: the following implementation relies on being able to override the location
// TODO: in react-router
// const buildCMSViewRoute = (path: string, cmsView: CMSView) => {
// return <Route
// key={"navigation_view_" + path}
// path={addInitialSlash(path)}
// >
// <CMSViewRoute cmsView={cmsView}/>
// </Route>;
// };
//
// let customRoutes: JSX.Element[] = [];
// if (navigation.views) {
// navigation.views.forEach((cmsView) => {
// if (Array.isArray(cmsView.path))
// customRoutes.push(...cmsView.path.map(path => buildCMSViewRoute(path, cmsView)));
// else
// customRoutes.push(buildCMSViewRoute(cmsView.path, cmsView));
// });
// }
// const collectionRoutes = [...collections]
// // we reorder collections so that nested paths are included first
// .sort((a, b) => b.relativePath.length - a.relativePath.length)
// .map(entityCollection => (
// <Route
// path={buildCollectionUrlPath(entityCollection)}
// key={`navigation_${entityCollection.relativePath}`}>
// <CollectionRoute
// path={entityCollection.relativePath}
// collectionConfig={entityCollection}
// />
// </Route>
// )
// );
// return (
// <Routes>
//
// {collectionRoutes}
//
// {customRoutes}
//
// <Route
// key={`navigation_home`}>
// <HomeRoute
// collections={collections}
// cmsViews={views}
// />
// </Route>
//
// </Routes>
// );
}

97
src/core/CMSRoutes.tsx Normal file
View File

@@ -0,0 +1,97 @@
import React from "react";
import { Route, Routes, useLocation } from "react-router-dom";
import { CMSView, Navigation } from "../models";
import { addInitialSlash, buildCollectionUrlPath } from "./navigation";
import { EntityCollectionTable } from "./components/EntityCollectionTable";
import BreadcrumbUpdater from "./components/BreadcrumbUpdater";
import CMSHome from "./components/CMSHome";
/**
* This component is in charge of taking a {@link Navigation} and rendering
* all the related routes (entity collection root views, custom views
* or the home route).
*
* @param navigation
* @constructor
*/
export function CMSRoutes({ navigation }: {
navigation: Navigation
}) {
const location = useLocation();
/**
* The location can be overridden if `base_location` is set in the
* state field of the current location. This can happen if you open
* a side entity, like `products`, from a different one, like `users`
*/
const baseLocation = location.state && location.state["base_location"] ? location.state["base_location"] : location;
const customRoutes: JSX.Element[] = [];
if (navigation.views) {
const buildCMSViewRoute = (path: string, cmsView: CMSView) => {
return <Route
key={"navigation_view_" + path}
path={addInitialSlash(path)}
element={
<BreadcrumbUpdater
path={addInitialSlash(path)}
key={`navigation_${path}`}
title={cmsView.name}>
{cmsView.view}
</BreadcrumbUpdater>}
/>;
};
navigation.views.forEach((cmsView) => {
if (Array.isArray(cmsView.path))
customRoutes.push(...cmsView.path.map(path => buildCMSViewRoute(path, cmsView)));
else
customRoutes.push(buildCMSViewRoute(cmsView.path, cmsView));
});
}
const collectionRoutes = [...navigation.collections]
// we reorder collections so that nested paths are included first
.sort((a, b) => b.relativePath.length - a.relativePath.length)
.map(entityCollection => {
const urlPath = buildCollectionUrlPath(entityCollection);
return (
<Route path={urlPath}
element={
<BreadcrumbUpdater
path={urlPath}
key={`navigation_${entityCollection.relativePath}`}
title={entityCollection.name}>
<EntityCollectionTable
path={entityCollection.relativePath}
collectionConfig={entityCollection}/>
</BreadcrumbUpdater>
}/>
);
}
);
const homeRoute =
<Route path={"/"}
element={
<BreadcrumbUpdater
path={"/"}
key={`navigation_home`}
title={"Home"}>
<CMSHome navigation={navigation}/>
</BreadcrumbUpdater>
}/>;
return (
<Routes location={baseLocation}>
{collectionRoutes}
{customRoutes}
{homeRoute}
</Routes>
);
}

View File

@@ -20,7 +20,7 @@ import * as locales from "date-fns/locale";
/**
* @category Core
*/
export interface CMSMainViewProps {
export interface CMSScaffoldProps {
/**
* Name of the app, displayed as the main title and in the tab title
@@ -32,12 +32,6 @@ export interface CMSMainViewProps {
*/
logo?: string;
/**
* If authentication is enabled, allow the user to access the content
* without login.
*/
allowSkipLogin?: boolean;
/**
* A component that gets rendered on the upper side of the main toolbar
*/
@@ -92,7 +86,7 @@ const useStyles = makeStyles((theme: Theme) =>
* @constructor
* @category Core
*/
export function CMSMainView(props: PropsWithChildren<CMSMainViewProps>) {
export function CMSScaffold(props: PropsWithChildren<CMSScaffoldProps>) {
const {
children,

View File

@@ -0,0 +1,37 @@
import React, { PropsWithChildren } from "react";
import { useBreadcrumbsContext } from "../../contexts";
import { EntityCollectionTable } from "./EntityCollectionTable";
export type BreadcrumbRouteProps = {
title: string;
path: string;
};
/**
* This component updates the breadcrumb in the app bar when rendered
* @param children
* @param title
* @param path
* @constructor
*/
function BreadcrumbUpdater({
children,
title,
path
}
: PropsWithChildren<BreadcrumbRouteProps>) {
const breadcrumbsContext = useBreadcrumbsContext();
React.useEffect(() => {
breadcrumbsContext.set({
breadcrumbs: [{
title: title,
url: path
}]
});
}, [path]);
return <> {children}</>;
}
export default BreadcrumbUpdater;

View File

@@ -1,4 +1,4 @@
import React, { useEffect } from "react";
import React from "react";
import {
Box,
Card,
@@ -16,14 +16,9 @@ import createStyles from "@mui/styles/createStyles";
import makeStyles from "@mui/styles/makeStyles";
import ArrowForwardIcon from "@mui/icons-material/ArrowForward";
import PlaylistPlayIcon from "@mui/icons-material/PlaylistPlay";
import { Link as ReactLink, useLocation } from "react-router-dom";
import { Link as ReactLink } from "react-router-dom";
import {
BreadcrumbEntry,
computeNavigation,
NavigationEntry
} from "../navigation";
import { useBreadcrumbsContext } from "../../contexts";
import { computeNavigation, NavigationEntry } from "../navigation";
import { Navigation } from "../../models";
import { Markdown } from "../../preview";
@@ -41,30 +36,21 @@ export const useStyles = makeStyles((theme: Theme) =>
})
);
interface HomeRouteProps {
export interface CMSHomeProps {
navigation: Navigation;
}
function HomeRoute({
/**
* Default main view and entry point for the CMS
* This components takes navigation as an input and renders
* @param navigation
* @constructor
*/
function CMSHome({
navigation
}: HomeRouteProps) {
}: CMSHomeProps) {
const classes = useStyles();
const { pathname } = useLocation();
const breadcrumb: BreadcrumbEntry = {
title: "Home",
url: pathname
};
const breadcrumbsContext = useBreadcrumbsContext();
useEffect(() => {
breadcrumbsContext.set({
breadcrumbs: [breadcrumb]
});
}, [pathname]);
const {
navigationEntries,
@@ -114,7 +100,6 @@ function HomeRoute({
);
}
return (
<Container>
{allGroups.map((group, index) => (
@@ -145,4 +130,4 @@ function HomeRoute({
);
}
export default HomeRoute;
export default CMSHome;

View File

@@ -1,3 +1,5 @@
import { CMSHomeProps } from "./CMSHome";
export type { ErrorViewProps } from "./ErrorView";
export {
default as ErrorView
@@ -22,8 +24,12 @@ export {
default as CircularProgressCenter
} from "./CircularProgressCenter";
export type { FirebaseLoginViewProps } from "./FirebaseLoginView";
export type { CMSHomeProps } from "./CMSHome";
export {
default as FirebaseLoginView
} from "./FirebaseLoginView";
default as CMSHome
} from "./CMSHome";
export {
default as BreadcrumbUpdater
} from "./BreadcrumbUpdater";

View File

@@ -1,17 +1,17 @@
export { CMSAppProvider } from "./CMSAppProvider";
export type {
CMSAppProviderProps
} from "./CMSAppProvider";
export { CMSMainView } from "./CMSMainView";
export { CMSRoutes } from "./CMSRoutes";
export { CMSScaffold } from "./CMSScaffold";
export type {
CMSMainViewProps
} from "./CMSMainView";
CMSScaffoldProps
} from "./CMSScaffold";
export * from "./components";
export { initialiseFirebase } from "./initialiseFirebase";
export { createCMSDefaultTheme } from "./theme";

View File

@@ -1,36 +0,0 @@
import React, { useEffect } from "react";
import { useLocation } from "react-router-dom";
import { BreadcrumbEntry } from "../navigation";
import { useBreadcrumbsContext } from "../../contexts";
import { CMSView } from "../../models";
interface CMSViewRouteProps {
cmsView: CMSView;
}
function CMSViewRoute({
cmsView
}: CMSViewRouteProps) {
const { pathname } = useLocation();
const breadcrumb: BreadcrumbEntry = {
title: cmsView.name,
url: pathname
};
const breadcrumbsContext = useBreadcrumbsContext();
useEffect(() => {
breadcrumbsContext.set({
breadcrumbs: [breadcrumb]
});
}, [pathname]);
return <React.Fragment>
{cmsView.view}
</React.Fragment>;
}
export default CMSViewRoute;

View File

@@ -1,54 +0,0 @@
import React from "react";
import { EntityCollection } from "../../models";
import createStyles from "@mui/styles/createStyles";
import makeStyles from "@mui/styles/makeStyles";
import { useLocation } from "react-router-dom";
import { useBreadcrumbsContext } from "../../contexts";
import { EntityCollectionTable } from "../components/EntityCollectionTable";
export const useStyles = makeStyles(() =>
createStyles({
root: {
height: "100%",
display: "flex",
flexDirection: "column"
}
})
);
interface CollectionRouteProps<M extends { [Key: string]: any }> {
collectionConfig: EntityCollection<M>;
path: string
}
function CollectionRoute<M extends { [Key: string]: any }>({
collectionConfig,
path
}
: CollectionRouteProps<M>) {
const { pathname } = useLocation();
const breadcrumbsContext = useBreadcrumbsContext();
React.useEffect(() => {
breadcrumbsContext.set({
breadcrumbs: [{
title: collectionConfig.name,
url: pathname
}]
});
}, [pathname]);
const classes = useStyles();
return (
<div className={classes.root}>
<EntityCollectionTable
path={path}
collectionConfig={collectionConfig}/>
</div>
);
}
export default CollectionRoute;

View File

@@ -38,10 +38,6 @@ export function buildCollectionUrlPath(view: EntityCollection) {
return `${DATA_PATH}/${removeInitialAndTrailingSlashes(view.relativePath)}`;
}
export function buildCollectionPath(view: EntityCollection) {
return `${DATA_PATH}/${removeInitialAndTrailingSlashes(view.relativePath)}`;
}
export function removeInitialAndTrailingSlashes(s: string) {
return removeInitialSlash(removeTrailingSlash(s));
}
@@ -243,6 +239,7 @@ export function computeNavigation(navigation:Navigation, includeHiddenViews: boo
...navigation.collections.map(collection => ({
url: buildCollectionUrlPath(collection),
name: collection.name,
description: collection.description,
group: collection.group
})),
...(navigation.views ?? []).map(view =>

View File

@@ -2,28 +2,29 @@ import React from "react";
import { GoogleAuthProvider } from "firebase/auth";
import { CssBaseline, ThemeProvider } from "@mui/material";
import { BrowserRouter as Router } from "react-router-dom";
import { BrowserRouter } from "react-router-dom";
import {
CircularProgressCenter,
CMSAppProvider,
CMSScaffold,
CMSRoutes,
createCMSDefaultTheme
} from "../core";
import { AuthController } from "../contexts";
import { EntityLinkBuilder } from "../models";
import { CMSAppProps } from "./CMSAppProps";
import {
CMSAppProvider,
CMSMainView,
createCMSDefaultTheme,
initialiseFirebase
} from "../core";
import { CMSRouterSwitch } from "../core/CMSRouterSwitch";
import { CircularProgressCenter, FirebaseLoginView } from "../core/components";
import { AuthController } from "../contexts";
import { useFirebaseAuthHandler } from "./useFirebaseAuthHandler";
import { EntityLinkBuilder } from "../models";
import { useFirestoreDataSource } from "./useFirestoreDataSource";
import { useFirebaseStorageSource } from "./useFirebaseStorageSource";
import { useInitialiseFirebase } from "./useInitialiseFirebase";
import FirebaseLoginView from "./FirebaseLoginView";
const DEFAULT_SIGN_IN_OPTIONS = [
GoogleAuthProvider.PROVIDER_ID
];
/**
* Main entry point for FireCMS. You can use this component as a full app,
* by specifying collections and entity schemas.
@@ -32,7 +33,7 @@ const DEFAULT_SIGN_IN_OPTIONS = [
* configuration object.
*
* If you are building a larger app and need finer control, you can use
* {@link CMSAppProvider} and {@link CMSMainView} instead.
* {@link CMSAppProvider} and {@link CMSScaffold} instead.
*
* @param props
* @constructor
@@ -62,7 +63,7 @@ export function CMSApp({
firebaseConfigLoading,
configError,
firebaseConfigError
} = initialiseFirebase({ onFirebaseInit, firebaseConfig });
} = useInitialiseFirebase({ onFirebaseInit, firebaseConfig });
const authController: AuthController = useFirebaseAuthHandler({
firebaseApp,
@@ -86,7 +87,10 @@ export function CMSApp({
return <CircularProgressCenter/>;
}
const dataSource = useFirestoreDataSource({ firebaseApp: firebaseApp! , textSearchDelegateResolver});
const dataSource = useFirestoreDataSource({
firebaseApp: firebaseApp!,
textSearchDelegateResolver
});
const storageSource = useFirebaseStorageSource({ firebaseApp: firebaseApp! });
const mode: "light" | "dark" = "light";
@@ -100,9 +104,11 @@ export function CMSApp({
const entityLinkBuilder: EntityLinkBuilder = ({ entity }) => `https://console.firebase.google.com/project/${firebaseApp.options.projectId}/firestore/data/${entity.path}/${entity.id}`;
return (
<ThemeProvider theme={theme}>
<CssBaseline/>
<Router>
<BrowserRouter>
<ThemeProvider theme={theme}>
<CssBaseline/>
<CMSAppProvider navigation={navigation}
authController={authController}
schemaResolver={schemaResolver}
@@ -127,14 +133,16 @@ export function CMSApp({
);
}
return <CMSMainView name={name}
logo={logo}
toolbarExtraWidget={toolbarExtraWidget}>
<CMSRouterSwitch navigation={context.navigation}/>
</CMSMainView>;
return (
<CMSScaffold name={name}
logo={logo}
toolbarExtraWidget={toolbarExtraWidget}>
<CMSRoutes navigation={context.navigation}/>
</CMSScaffold>
);
}}
</CMSAppProvider>
</Router>
</ThemeProvider>
);
</ThemeProvider>
</BrowserRouter>
);
}

View File

@@ -7,7 +7,7 @@ import {
NavigationBuilder,
SchemaResolver
} from "../models";
import { TextSearchDelegateResolver } from "./text_search_delegate";
import { TextSearchDelegateResolver } from "./text_search";
/**
* Main entry point that defines the CMS configuration

View File

@@ -6,7 +6,7 @@ import makeStyles from "@mui/styles/makeStyles";
import firebase from "firebase/compat/app";
import { useAuthController } from "../../contexts";
import { useAuthController } from "../contexts";
import * as firebaseui from "firebaseui";
import "firebaseui/dist/firebaseui.css";

View File

@@ -1,3 +1,4 @@
import { InitialiseFirebaseResult } from "./useInitialiseFirebase";
export { CMSApp } from "./CMSApp";
export type {
@@ -20,3 +21,11 @@ export {
export type { TextSearchDelegateResolver } from "./text_search";
export { performAlgoliaTextSearch } from "./text_search";
export type { FirebaseLoginViewProps } from "./FirebaseLoginView";
export {
default as FirebaseLoginView
} from "./FirebaseLoginView";
export type { InitialiseFirebaseResult } from "./useInitialiseFirebase";
export { useInitialiseFirebase } from "./useInitialiseFirebase";

View File

@@ -45,7 +45,8 @@ import {
where as whereClause
} from "firebase/firestore";
import { FirebaseApp } from "firebase/app";
import { TextSearchDelegateResolver } from "./text_search_delegate";
import { TextSearchDelegateResolver } from "./text_search";
import firebase from "firebase/compat/app";
export type FirestoreDataSourceProps = {
firebaseApp: FirebaseApp,
@@ -365,15 +366,8 @@ export function useFirestoreDataSource({
}: SaveEntityProps<M>): Promise<void> {
const properties: Properties<M> = computeSchemaProperties(schema, path, entityId);
let updatedValues: EntityValues<M> = updateAutoValues(
{
inputValues: values,
properties,
status,
timestampNowValue: serverTimestamp(),
referenceConverter: (value: EntityReference) => doc(db, value.path, value.id),
geopointConverter: (value: GeoPoint) => new GeoPoint(value.latitude, value.longitude)
});
let updatedValues: EntityValues<M>;
if (schema.onPreSave) {
try {
@@ -381,7 +375,7 @@ export function useFirestoreDataSource({
schema,
path,
entityId,
values: updatedValues,
values,
status,
context
});
@@ -393,6 +387,17 @@ export function useFirestoreDataSource({
}
}
updatedValues = updateAutoValues(
{
inputValues: values,
properties,
status,
timestampNowValue: serverTimestamp(),
referenceConverter: (value: EntityReference) => doc(db, value.path, value.id),
geopointConverter: (value: GeoPoint) => new firebase.firestore.GeoPoint(value.latitude, value.longitude)
});
console.debug("Saving entity", path, entityId, updatedValues);
let documentReference: DocumentReference;

View File

@@ -2,7 +2,7 @@ import React, { useEffect } from "react";
import { FirebaseApp, initializeApp } from "firebase/app";
export interface CMSFirebaseInitResult {
export interface InitialiseFirebaseResult {
firebaseConfigLoading: boolean,
firebaseApp?: FirebaseApp;
configError?: string,
@@ -24,10 +24,10 @@ export interface CMSFirebaseInitResult {
* @param firebaseConfig
* @category Hooks and utilities Functions
*/
export function initialiseFirebase({ firebaseConfig, onFirebaseInit }: {
export function useInitialiseFirebase({ firebaseConfig, onFirebaseInit }: {
onFirebaseInit?: ((config: object) => void) | undefined,
firebaseConfig: Object | undefined
}): CMSFirebaseInitResult {
}): InitialiseFirebaseResult {
const [firebaseApp, setFirebaseApp] = React.useState<FirebaseApp | undefined>();
const [firebaseConfigLoading, setFirebaseConfigLoading] = React.useState<boolean>(false);

View File

@@ -210,7 +210,7 @@ export interface EntityOnSaveProps<M extends { [Key: string]: any }> {
/**
* Values being saved
*/
values: EntityValues<M>;
values: Partial<EntityValues<M>>;
/**
* New or existing entity

View File

@@ -6,10 +6,8 @@ it("Test Algolia search", async () => {
const client = algoliasearch(
"Y6FR1MDSVW",
"f084e6dcc154c04295c8124dbb797ff1");
const usersIndex = client.initIndex("users");
await performAlgoliaTextSearch(
client,
"users",
"john").then(console.log);
await performAlgoliaTextSearch(usersIndex, "john").then(console.log);
console.log("done");
});

View File

@@ -1991,7 +1991,7 @@
dependencies:
regenerator-runtime "^0.13.4"
"@babel/runtime@^7.13.10", "@babel/runtime@^7.14.8", "@babel/runtime@^7.7.6":
"@babel/runtime@^7.13.10", "@babel/runtime@^7.14.8":
version "7.15.3"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.3.tgz#2e1c2880ca118e5b2f9988322bd8a7656a32502b"
integrity sha512-OvwMLqNXkCXSz1kSm58sEsNuhqOx/fKpnUnKnFB5v8uDda5bLNEHNgKPvhDN6IU0LDcnHQ90LlJ0Q6jnyBSIBA==
@@ -2893,11 +2893,6 @@
refractor "^3.3.1"
unist-util-visit "^2.0.3"
"@material-ui/types@^6.0.1":
version "6.0.1"
resolved "https://registry.yarnpkg.com/@material-ui/types/-/types-6.0.1.tgz#bfcdcd3bb5091e5feac2b191db516543d84e26af"
integrity sha512-t53C2BZE59e8ao38EDIZdM2smPDSEo5Xx9XxQ/MNM9Ph63Mu4vj5pmECiXkYp0y2OrvFiiZhcqRWV34SBOA18g==
"@mui/core@5.0.0-alpha.46":
version "5.0.0-alpha.46"
resolved "https://registry.yarnpkg.com/@mui/core/-/core-5.0.0-alpha.46.tgz#f4c0e5b2ad346e31e74bb96b684f6734b55cc9e6"
@@ -5383,7 +5378,7 @@ class-utils@^0.3.5:
isobject "^3.0.0"
static-extend "^0.1.1"
classnames@^2.2.5, classnames@^2.2.6:
classnames@^2.2.5:
version "2.2.6"
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce"
integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==
@@ -8320,13 +8315,6 @@ hex-color-regex@^1.1.0:
resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e"
integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==
history@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/history/-/history-5.0.0.tgz#0cabbb6c4bbf835addb874f8259f6d25101efd08"
integrity sha512-3NyRMKIiFSJmIPdq7FxkNMJkQ7ZEtVblOQ38VtKaA0zZMW1Eo6Q6W8oDKEflr1kNNTItSnk4JMCO1deeSgbLLg==
dependencies:
"@babel/runtime" "^7.7.6"
hmac-drbg@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
@@ -10370,16 +10358,6 @@ material-design-lite@^1.2.0:
resolved "https://registry.yarnpkg.com/material-design-lite/-/material-design-lite-1.3.0.tgz#d004ce3fee99a1eeb74a78b8a325134a5f1171d3"
integrity sha1-0ATOP+6Zoe63Sni4oyUTSl8RcdM=
material-ui-popup-state@^1.8.3:
version "1.9.0"
resolved "https://registry.yarnpkg.com/material-ui-popup-state/-/material-ui-popup-state-1.9.0.tgz#569d173c941c41ba32791ea759ff21b1a84d70fd"
integrity sha512-a0OqcXgicrYYKMoBXuajjT94uARgl7ozt1gs735Xb+UmEtanBxjavtoOVo+C4pfVRCHOVamJg+1H48zhOrGd/w==
dependencies:
"@babel/runtime" "^7.12.5"
"@material-ui/types" "^6.0.1"
classnames "^2.2.6"
prop-types "^15.7.2"
maxmin@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/maxmin/-/maxmin-2.1.0.tgz#4d3b220903d95eee7eb7ac7fa864e72dc09a3166"
@@ -12982,20 +12960,17 @@ react-refresh@^0.8.3:
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f"
integrity sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg==
react-router-dom@^6.0.0-beta.0:
version "6.0.0-beta.0"
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.0.0-beta.0.tgz#9dcc8555365f22f7fbd09f26b6b82543f3eb97d6"
integrity sha512-36yNNGMT8RB9FRPL9nKJi6HKDkgOakU+o/2hHpSzR6e37gN70MpOU6QQlmif4oAWWBwjyGc3ZNOMFCsFuHUY5w==
react-router-dom@^6.0.0-beta.4:
version "6.0.0-beta.4"
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.0.0-beta.4.tgz#9cc9fb57bca3d5548b297ae8101efcdcc68dd903"
integrity sha512-yppoRR8S7FxNMG6OGFn9DPJBPLsjeIuQa7GYnkRlgOSTBSPhAQpD6z7rvRzZnesQ9r6W+ibD9RvnqTcna4w/Pg==
dependencies:
prop-types "^15.7.2"
react-router "6.0.0-beta.0"
react-router "6.0.0-beta.4"
react-router@6.0.0-beta.0, react-router@^6.0.0-beta.0:
version "6.0.0-beta.0"
resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.0.0-beta.0.tgz#3e11f39b6ded4412c2fed9e4f989dd4c8156724d"
integrity sha512-VgMdfpVcmFQki/LZuLh8E/MNACekDetz4xqft+a6fBZvvJnVqKbLqebF7hyoawGrV1HcO5tVaUang2Og4W2j1Q==
dependencies:
prop-types "^15.7.2"
react-router@6.0.0-beta.4, react-router@^6.0.0-beta.4:
version "6.0.0-beta.4"
resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.0.0-beta.4.tgz#e35a440b36fd07a2ac854e1f1f176b56a777793a"
integrity sha512-48JRRZJOwmfOKM12Tv3WjmNkVb2NpSEgDTWC4+MEJaud0+eyLJxqy62CKzOydMlk7hrfRFpC/elUYSZAuyx3qA==
react-scripts@^4.0.3:
version "4.0.3"