@firecms/core 3.0.0-alpha.46 → 3.0.0-alpha.47
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/EntityCollectionView/EntityCollectionView.d.ts +1 -1
- package/dist/components/EntityCollectionView/EntityCollectionViewActions.d.ts +2 -2
- package/dist/index.es.js +2087 -2059
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +12 -12
- package/dist/index.umd.js.map +1 -1
- package/dist/internal/EntityView.d.ts +2 -1
- package/dist/types/collections.d.ts +8 -8
- package/dist/types/index.d.ts +1 -0
- package/dist/types/modify_collections.d.ts +5 -0
- package/dist/types/navigation.d.ts +9 -0
- package/dist/types/plugins.d.ts +2 -2
- package/dist/ui/ExpandablePanel.d.ts +2 -1
- package/dist/util/join_collections.d.ts +3 -7
- package/package.json +2 -2
- package/src/components/EntityCollectionTable/internal/EntityCollectionRowActions.tsx +1 -1
- package/src/components/EntityCollectionTable/internal/common.tsx +1 -1
- package/src/components/EntityCollectionView/EntityCollectionView.tsx +7 -7
- package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +3 -3
- package/src/core/EntitySidePanel.tsx +5 -0
- package/src/core/NavigationRoutes.tsx +5 -5
- package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +1 -0
- package/src/internal/EntityView.tsx +6 -12
- package/src/internal/useBuildNavigationController.tsx +33 -9
- package/src/internal/useBuildSideEntityController.tsx +1 -1
- package/src/preview/PropertyPreview.tsx +0 -1
- package/src/types/collections.ts +9 -9
- package/src/types/firecms.tsx +1 -1
- package/src/types/index.ts +1 -0
- package/src/types/modify_collections.tsx +6 -0
- package/src/types/navigation.ts +11 -0
- package/src/types/plugins.tsx +2 -2
- package/src/ui/ExpandablePanel.tsx +9 -2
- package/src/util/builders.ts +2 -1
- package/src/util/join_collections.ts +49 -19
- package/src/util/navigation_from_path.ts +2 -2
- package/src/util/navigation_utils.ts +3 -3
- package/src/util/parent_references_from_path.ts +2 -2
- package/src/util/property_utils.tsx +1 -7
|
@@ -5,6 +5,7 @@ export interface EntityViewProps<M extends Record<string, any>> {
|
|
|
5
5
|
entityId?: string;
|
|
6
6
|
copy?: boolean;
|
|
7
7
|
selectedSubPath?: string;
|
|
8
|
+
parentCollectionIds: string[];
|
|
8
9
|
formWidth?: number | string;
|
|
9
10
|
onValuesAreModified: (modified: boolean) => void;
|
|
10
11
|
onUpdate?: (params: {
|
|
@@ -18,4 +19,4 @@ export interface EntityViewProps<M extends Record<string, any>> {
|
|
|
18
19
|
* You probably don't want to use this view directly since it is bound to the
|
|
19
20
|
* side panel. Instead, you might want to use {@link EntityForm} or {@link EntityCollectionView}
|
|
20
21
|
*/
|
|
21
|
-
export declare function EntityView<M extends Record<string, any>, UserType extends User>({ path, entityId, selectedSubPath, copy, collection, onValuesAreModified, formWidth, onUpdate, onClose }: EntityViewProps<M>): import("react/jsx-runtime").JSX.Element;
|
|
22
|
+
export declare function EntityView<M extends Record<string, any>, UserType extends User>({ path, entityId, selectedSubPath, copy, collection, parentCollectionIds, onValuesAreModified, formWidth, onUpdate, onClose }: EntityViewProps<M>): import("react/jsx-runtime").JSX.Element;
|
|
@@ -16,6 +16,13 @@ import { ExportConfig } from "./export_import";
|
|
|
16
16
|
* @group Models
|
|
17
17
|
*/
|
|
18
18
|
export interface EntityCollection<M extends Record<string, any> = any, UserType extends User = User> {
|
|
19
|
+
/**
|
|
20
|
+
* You can set an alias that will be used internally instead of the `path`.
|
|
21
|
+
* The `alias` value will be used to determine the URL of the collection,
|
|
22
|
+
* while `path` will still be used in the datasource.
|
|
23
|
+
* Note that you can use this value in reference properties too.
|
|
24
|
+
*/
|
|
25
|
+
id: string;
|
|
19
26
|
/**
|
|
20
27
|
* Name of the collection, typically plural.
|
|
21
28
|
* E.g. `Products`, `Blog`
|
|
@@ -41,13 +48,6 @@ export interface EntityCollection<M extends Record<string, any> = any, UserType
|
|
|
41
48
|
* property to `true` to indicate that this collection is a collection group.
|
|
42
49
|
*/
|
|
43
50
|
collectionGroup?: boolean;
|
|
44
|
-
/**
|
|
45
|
-
* You can set an alias that will be used internally instead of the `path`.
|
|
46
|
-
* The `alias` value will be used to determine the URL of the collection,
|
|
47
|
-
* while `path` will still be used in the datasource.
|
|
48
|
-
* Note that you can use this value in reference properties too.
|
|
49
|
-
*/
|
|
50
|
-
alias?: string;
|
|
51
51
|
/**
|
|
52
52
|
* Icon key to use in this collection.
|
|
53
53
|
* You can use any of the icons in the Material specs:
|
|
@@ -262,7 +262,7 @@ export interface CollectionActionsProps<M extends Record<string, any> = any, Use
|
|
|
262
262
|
/**
|
|
263
263
|
* Array of the parent path segments like `['users']`
|
|
264
264
|
*/
|
|
265
|
-
|
|
265
|
+
parentCollectionIds: string[];
|
|
266
266
|
/**
|
|
267
267
|
* The collection configuration
|
|
268
268
|
*/
|
package/dist/types/index.d.ts
CHANGED
|
@@ -42,6 +42,10 @@ export type NavigationController = {
|
|
|
42
42
|
* The collection is resolved from the given path or alias.
|
|
43
43
|
*/
|
|
44
44
|
getCollection: <EC extends EntityCollection = EntityCollection<any>>(pathOrAlias: string, entityId?: string, includeUserOverride?: boolean) => EC | undefined;
|
|
45
|
+
/**
|
|
46
|
+
* Get the collection configuration from its parent path segments.
|
|
47
|
+
*/
|
|
48
|
+
getCollectionFromIds: <EC extends EntityCollection = EntityCollection<any>>(ids: string[]) => EC | undefined;
|
|
45
49
|
/**
|
|
46
50
|
* Get the collection configuration from its parent path segments.
|
|
47
51
|
*/
|
|
@@ -106,6 +110,11 @@ export type NavigationController = {
|
|
|
106
110
|
* @param path
|
|
107
111
|
*/
|
|
108
112
|
getParentReferencesFromPath: (path: string) => EntityReference[];
|
|
113
|
+
/**
|
|
114
|
+
* Retrieve all the related parent collection ids for a given path
|
|
115
|
+
* @param path
|
|
116
|
+
*/
|
|
117
|
+
getParentCollectionIds: (path: string) => string[];
|
|
109
118
|
};
|
|
110
119
|
/**
|
|
111
120
|
* Custom additional views created by the developer, added to the main
|
package/dist/types/plugins.d.ts
CHANGED
|
@@ -95,7 +95,7 @@ export type FireCMSPlugin<PROPS = any, FORM_PROPS = any, EC extends EntityCollec
|
|
|
95
95
|
property: ResolvedProperty;
|
|
96
96
|
propertyKey: string;
|
|
97
97
|
fullPath: string;
|
|
98
|
-
|
|
98
|
+
parentCollectionIds: string[];
|
|
99
99
|
onHover: boolean;
|
|
100
100
|
collection: EC;
|
|
101
101
|
}>;
|
|
@@ -105,7 +105,7 @@ export type FireCMSPlugin<PROPS = any, FORM_PROPS = any, EC extends EntityCollec
|
|
|
105
105
|
*/
|
|
106
106
|
AddColumnComponent?: React.ComponentType<{
|
|
107
107
|
fullPath: string;
|
|
108
|
-
|
|
108
|
+
parentCollectionIds: string[];
|
|
109
109
|
collection: EC;
|
|
110
110
|
}>;
|
|
111
111
|
};
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import React, { PropsWithChildren } from "react";
|
|
2
|
-
export declare function ExpandablePanel({ title, children, invisible,
|
|
2
|
+
export declare function ExpandablePanel({ title, children, invisible, expanded, onExpandedChange, initiallyExpanded, titleClassName, asField, className }: PropsWithChildren<{
|
|
3
3
|
title: React.ReactNode;
|
|
4
4
|
invisible?: boolean;
|
|
5
5
|
initiallyExpanded?: boolean;
|
|
6
|
+
expanded?: boolean;
|
|
6
7
|
onExpandedChange?: (expanded: boolean) => void;
|
|
7
8
|
titleClassName?: string;
|
|
8
9
|
asField?: boolean;
|
|
@@ -1,13 +1,9 @@
|
|
|
1
|
-
import { EntityCollection } from "../types";
|
|
1
|
+
import { EntityCollection, ModifyCollectionProps } from "../types";
|
|
2
2
|
/**
|
|
3
3
|
*
|
|
4
|
-
* @param storedCollections
|
|
5
|
-
* @param codedCollections
|
|
6
4
|
*/
|
|
7
|
-
export declare function joinCollectionLists(
|
|
5
|
+
export declare function joinCollectionLists(targetCollections: EntityCollection[], sourceCollections: EntityCollection[] | undefined, parentPaths?: string[], modifyCollection?: (props: ModifyCollectionProps) => EntityCollection | undefined): EntityCollection[];
|
|
8
6
|
/**
|
|
9
7
|
*
|
|
10
|
-
* @param target
|
|
11
|
-
* @param source
|
|
12
8
|
*/
|
|
13
|
-
export declare function mergeCollection(target: EntityCollection, source: EntityCollection): EntityCollection;
|
|
9
|
+
export declare function mergeCollection(target: EntityCollection, source: EntityCollection, parentPaths?: string[], modifyCollection?: (props: ModifyCollectionProps) => EntityCollection | undefined): EntityCollection;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@firecms/core",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.47",
|
|
4
4
|
"description": "Awesome Firebase/Firestore-based headless open-source CMS",
|
|
5
5
|
"funding": {
|
|
6
6
|
"url": "https://github.com/sponsors/firecmsco"
|
|
@@ -133,7 +133,7 @@
|
|
|
133
133
|
"dist",
|
|
134
134
|
"src"
|
|
135
135
|
],
|
|
136
|
-
"gitHead": "
|
|
136
|
+
"gitHead": "1c2310776f2da9bba46ba352e9a5244118dcdc3f",
|
|
137
137
|
"publishConfig": {
|
|
138
138
|
"access": "public"
|
|
139
139
|
}
|
|
@@ -2,7 +2,7 @@ import React, { MouseEvent, useCallback } from "react";
|
|
|
2
2
|
import equal from "react-fast-compare"
|
|
3
3
|
|
|
4
4
|
import { CollectionSize, Entity, EntityAction, EntityCollection, SelectionController } from "../../../types";
|
|
5
|
-
import { Checkbox, cn, IconButton, Menu, MenuItem, Tooltip, Typography
|
|
5
|
+
import { Checkbox, cn, IconButton, Menu, MenuItem, Skeleton, Tooltip, Typography } from "../../../ui";
|
|
6
6
|
import { useFireCMSContext, useLargeLayout } from "../../../hooks";
|
|
7
7
|
import { MoreVertIcon } from "../../../icons";
|
|
8
8
|
|
|
@@ -66,5 +66,5 @@ export function getTablePropertyColumnWidth(property: ResolvedProperty): number
|
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
export function getSubcollectionColumnId(collection: EntityCollection) {
|
|
69
|
-
return `subcollection:${collection.
|
|
69
|
+
return `subcollection:${collection.id ?? collection.path}`;
|
|
70
70
|
}
|
|
@@ -69,7 +69,7 @@ const COLLECTION_GROUP_PARENT_ID = "collectionGroupParent";
|
|
|
69
69
|
*/
|
|
70
70
|
export type EntityCollectionViewProps<M extends Record<string, any>> = {
|
|
71
71
|
fullPath: string;
|
|
72
|
-
|
|
72
|
+
parentCollectionIds?: string[];
|
|
73
73
|
isSubCollection?: boolean;
|
|
74
74
|
className?: string;
|
|
75
75
|
} & EntityCollection<M>;
|
|
@@ -101,7 +101,7 @@ export type EntityCollectionViewProps<M extends Record<string, any>> = {
|
|
|
101
101
|
export const EntityCollectionView = React.memo(
|
|
102
102
|
function EntityCollectionView<M extends Record<string, any>>({
|
|
103
103
|
fullPath,
|
|
104
|
-
|
|
104
|
+
parentCollectionIds,
|
|
105
105
|
isSubCollection,
|
|
106
106
|
className,
|
|
107
107
|
...collectionProp
|
|
@@ -238,7 +238,7 @@ export const EntityCollectionView = React.memo(
|
|
|
238
238
|
|
|
239
239
|
let AddColumnComponent: React.ComponentType<{
|
|
240
240
|
fullPath: string,
|
|
241
|
-
|
|
241
|
+
parentCollectionIds: string[],
|
|
242
242
|
collection: EntityCollection;
|
|
243
243
|
}> | undefined
|
|
244
244
|
|
|
@@ -367,7 +367,7 @@ export const EntityCollectionView = React.memo(
|
|
|
367
367
|
sideEntityController.open({
|
|
368
368
|
path: fullPath,
|
|
369
369
|
entityId: entity.id,
|
|
370
|
-
selectedSubPath: subcollection.
|
|
370
|
+
selectedSubPath: subcollection.id ?? subcollection.path,
|
|
371
371
|
collection,
|
|
372
372
|
updateUrl: true
|
|
373
373
|
});
|
|
@@ -529,7 +529,7 @@ export const EntityCollectionView = React.memo(
|
|
|
529
529
|
property={property}
|
|
530
530
|
fullPath={fullPath}
|
|
531
531
|
collection={collection}
|
|
532
|
-
|
|
532
|
+
parentCollectionIds={parentCollectionIds ?? []}/>;
|
|
533
533
|
})}
|
|
534
534
|
</>;
|
|
535
535
|
}
|
|
@@ -538,7 +538,7 @@ export const EntityCollectionView = React.memo(
|
|
|
538
538
|
? function () {
|
|
539
539
|
if (typeof AddColumnComponent === "function")
|
|
540
540
|
return <AddColumnComponent fullPath={fullPath}
|
|
541
|
-
|
|
541
|
+
parentCollectionIds={parentCollectionIds ?? []}
|
|
542
542
|
collection={collection}/>;
|
|
543
543
|
return null;
|
|
544
544
|
}
|
|
@@ -565,7 +565,7 @@ export const EntityCollectionView = React.memo(
|
|
|
565
565
|
properties={resolvedCollection.properties}
|
|
566
566
|
getPropertyFor={getPropertyFor}
|
|
567
567
|
actions={<EntityCollectionViewActions
|
|
568
|
-
|
|
568
|
+
parentCollectionIds={parentCollectionIds ?? []}
|
|
569
569
|
collection={collection}
|
|
570
570
|
tableController={tableController}
|
|
571
571
|
onMultipleDeleteClick={onMultipleDeleteClick}
|
|
@@ -12,7 +12,7 @@ export type EntityCollectionViewActionsProps<M extends Record<string, any>> = {
|
|
|
12
12
|
collection: EntityCollection<M>;
|
|
13
13
|
path: string;
|
|
14
14
|
relativePath: string;
|
|
15
|
-
|
|
15
|
+
parentCollectionIds: string[];
|
|
16
16
|
selectionEnabled: boolean;
|
|
17
17
|
onNewClick: () => void;
|
|
18
18
|
onMultipleDeleteClick: () => void;
|
|
@@ -24,7 +24,7 @@ export type EntityCollectionViewActionsProps<M extends Record<string, any>> = {
|
|
|
24
24
|
export function EntityCollectionViewActions<M extends Record<string, any>>({
|
|
25
25
|
collection,
|
|
26
26
|
relativePath,
|
|
27
|
-
|
|
27
|
+
parentCollectionIds,
|
|
28
28
|
onNewClick,
|
|
29
29
|
onMultipleDeleteClick,
|
|
30
30
|
selectionEnabled,
|
|
@@ -95,7 +95,7 @@ export function EntityCollectionViewActions<M extends Record<string, any>>({
|
|
|
95
95
|
const actionProps: CollectionActionsProps = {
|
|
96
96
|
path,
|
|
97
97
|
relativePath,
|
|
98
|
-
|
|
98
|
+
parentCollectionIds,
|
|
99
99
|
collection,
|
|
100
100
|
selectionController,
|
|
101
101
|
context,
|
|
@@ -25,6 +25,10 @@ export function EntitySidePanel(props: EntitySidePanelProps) {
|
|
|
25
25
|
|
|
26
26
|
const navigationController = useNavigationController();
|
|
27
27
|
|
|
28
|
+
const parentCollectionIds = useMemo(() => {
|
|
29
|
+
return navigationController.getParentCollectionIds(props.path);
|
|
30
|
+
}, [navigationController, props.path]);
|
|
31
|
+
|
|
28
32
|
const collection = useMemo(() => {
|
|
29
33
|
if (!props) return undefined;
|
|
30
34
|
let usedCollection = props.collection;
|
|
@@ -76,6 +80,7 @@ export function EntitySidePanel(props: EntitySidePanelProps) {
|
|
|
76
80
|
{...props}
|
|
77
81
|
formWidth={props.width}
|
|
78
82
|
collection={collection}
|
|
83
|
+
parentCollectionIds={parentCollectionIds}
|
|
79
84
|
onValuesAreModified={onValuesAreModified}
|
|
80
85
|
/>
|
|
81
86
|
</ErrorBoundary>
|
|
@@ -67,19 +67,19 @@ export const NavigationRoutes = React.memo<NavigationRoutesProps>(
|
|
|
67
67
|
|
|
68
68
|
const collectionRoutes = sortedCollections
|
|
69
69
|
.map((collection) => {
|
|
70
|
-
const urlPath = navigation.buildUrlCollectionPath(collection.
|
|
70
|
+
const urlPath = navigation.buildUrlCollectionPath(collection.id ?? collection.path);
|
|
71
71
|
return <Route path={urlPath + "/*"}
|
|
72
|
-
key={`navigation_${collection.
|
|
72
|
+
key={`navigation_${collection.id ?? collection.path}`}
|
|
73
73
|
element={
|
|
74
74
|
<RouteWrapper
|
|
75
75
|
path={urlPath}
|
|
76
76
|
title={collection.name}
|
|
77
77
|
type={"collection"}>
|
|
78
78
|
<EntityCollectionView
|
|
79
|
-
key={`collection_view_${collection.
|
|
79
|
+
key={`collection_view_${collection.id ?? collection.path}`}
|
|
80
80
|
isSubCollection={false}
|
|
81
|
-
|
|
82
|
-
fullPath={collection.
|
|
81
|
+
parentCollectionIds={[]}
|
|
82
|
+
fullPath={collection.id ?? collection.path}
|
|
83
83
|
{...collection}
|
|
84
84
|
Actions={toArray(collection.Actions)}/>
|
|
85
85
|
</RouteWrapper>
|
|
@@ -56,6 +56,7 @@ export function ArrayOfReferencesFieldBinding({
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
const onMultipleEntitiesSelected = useCallback((entities: Entity<any>[]) => {
|
|
59
|
+
console.debug("onMultipleEntitiesSelected", entities);
|
|
59
60
|
setValue(entities.map(e => getReferenceFrom(e)));
|
|
60
61
|
}, [setValue]);
|
|
61
62
|
|
|
@@ -45,18 +45,13 @@ export interface EntityViewProps<M extends Record<string, any>> {
|
|
|
45
45
|
entityId?: string;
|
|
46
46
|
copy?: boolean;
|
|
47
47
|
selectedSubPath?: string;
|
|
48
|
+
parentCollectionIds: string[];
|
|
48
49
|
formWidth?: number | string;
|
|
49
50
|
onValuesAreModified: (modified: boolean) => void;
|
|
50
51
|
onUpdate?: (params: { entity: Entity<any> }) => void;
|
|
51
52
|
onClose?: () => void;
|
|
52
53
|
}
|
|
53
54
|
|
|
54
|
-
type EntityViewView = {
|
|
55
|
-
label: string;
|
|
56
|
-
component: React.ReactNode;
|
|
57
|
-
size: "full" | "half";
|
|
58
|
-
}
|
|
59
|
-
|
|
60
55
|
/**
|
|
61
56
|
* This is the default view that is used as the content of a side panel when
|
|
62
57
|
* an entity is opened.
|
|
@@ -69,12 +64,14 @@ export function EntityView<M extends Record<string, any>, UserType extends User>
|
|
|
69
64
|
selectedSubPath,
|
|
70
65
|
copy,
|
|
71
66
|
collection,
|
|
67
|
+
parentCollectionIds,
|
|
72
68
|
onValuesAreModified,
|
|
73
69
|
formWidth,
|
|
74
70
|
onUpdate,
|
|
75
71
|
onClose
|
|
76
72
|
}: EntityViewProps<M>) {
|
|
77
73
|
|
|
74
|
+
|
|
78
75
|
if (collection.customId && collection.formAutoSave) {
|
|
79
76
|
console.warn(`The collection ${collection.path} has customId and formAutoSave enabled. This is not supported and formAutoSave will be ignored`);
|
|
80
77
|
}
|
|
@@ -343,7 +340,7 @@ export function EntityView<M extends Record<string, any>, UserType extends User>
|
|
|
343
340
|
|
|
344
341
|
const subCollectionsViews = subcollections && subcollections.map(
|
|
345
342
|
(subcollection, colIndex) => {
|
|
346
|
-
const subcollectionId = subcollection.
|
|
343
|
+
const subcollectionId = subcollection.id ?? subcollection.path;
|
|
347
344
|
const fullPath = usedEntity ? `${path}/${usedEntity?.id}/${removeInitialAndTrailingSlashes(subcollectionId)}` : undefined;
|
|
348
345
|
if (selectedTabRef.current !== subcollectionId)
|
|
349
346
|
return null;
|
|
@@ -359,7 +356,7 @@ export function EntityView<M extends Record<string, any>, UserType extends User>
|
|
|
359
356
|
(usedEntity && fullPath
|
|
360
357
|
? <EntityCollectionView
|
|
361
358
|
fullPath={fullPath}
|
|
362
|
-
|
|
359
|
+
parentCollectionIds={[...parentCollectionIds, collection.id]}
|
|
363
360
|
isSubCollection={true}
|
|
364
361
|
{...subcollection}/>
|
|
365
362
|
: <div
|
|
@@ -480,7 +477,7 @@ export function EntityView<M extends Record<string, any>, UserType extends User>
|
|
|
480
477
|
(subcollection) =>
|
|
481
478
|
<Tab
|
|
482
479
|
className="text-sm min-w-[140px]"
|
|
483
|
-
value={subcollection.
|
|
480
|
+
value={subcollection.id}
|
|
484
481
|
key={`entity_detail_collection_tab_${subcollection.name}`}>
|
|
485
482
|
{subcollection.name}
|
|
486
483
|
</Tab>
|
|
@@ -533,9 +530,6 @@ export function EntityView<M extends Record<string, any>, UserType extends User>
|
|
|
533
530
|
|
|
534
531
|
<Tab
|
|
535
532
|
disabled={!hasAdditionalViews}
|
|
536
|
-
// onClick={() => {
|
|
537
|
-
// onSideTabClick(-1);
|
|
538
|
-
// }}
|
|
539
533
|
value={MAIN_TAB_VALUE}
|
|
540
534
|
className={`${
|
|
541
535
|
!hasAdditionalViews ? "hidden" : ""
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
AuthController,
|
|
6
6
|
CMSView,
|
|
7
7
|
CMSViewsBuilder,
|
|
8
|
-
|
|
8
|
+
DataSourceDelegate,
|
|
9
9
|
EntityCollection,
|
|
10
10
|
EntityCollectionsBuilder,
|
|
11
11
|
EntityReference,
|
|
@@ -24,7 +24,6 @@ import {
|
|
|
24
24
|
resolvePermissions
|
|
25
25
|
} from "../util";
|
|
26
26
|
import { getParentReferencesFromPath } from "../util/parent_references_from_path";
|
|
27
|
-
import { useTraceUpdate } from "../util/useTraceUpdate";
|
|
28
27
|
|
|
29
28
|
const DEFAULT_BASE_PATH = "/";
|
|
30
29
|
const DEFAULT_COLLECTION_PATH = "/c";
|
|
@@ -79,10 +78,10 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
|
|
|
79
78
|
const navigationEntries: TopNavigationEntry[] = [
|
|
80
79
|
...(collections ?? []).map(collection => (!collection.hideFromNavigation
|
|
81
80
|
? {
|
|
82
|
-
url: buildUrlCollectionPath(collection.
|
|
81
|
+
url: buildUrlCollectionPath(collection.id ?? collection.path),
|
|
83
82
|
type: "collection",
|
|
84
83
|
name: collection.name.trim(),
|
|
85
|
-
path: collection.
|
|
84
|
+
path: collection.id ?? collection.path,
|
|
86
85
|
collection,
|
|
87
86
|
description: collection.description?.trim(),
|
|
88
87
|
group: collection.group?.trim()
|
|
@@ -142,7 +141,7 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
|
|
|
142
141
|
}, [refreshNavigation]);
|
|
143
142
|
|
|
144
143
|
const getCollection = useCallback(<EC extends EntityCollection>(
|
|
145
|
-
|
|
144
|
+
idOrPath: string,
|
|
146
145
|
entityId?: string,
|
|
147
146
|
includeUserOverride = false
|
|
148
147
|
): EC | undefined => {
|
|
@@ -150,9 +149,9 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
|
|
|
150
149
|
if (!collections)
|
|
151
150
|
return undefined;
|
|
152
151
|
|
|
153
|
-
const baseCollection = getCollectionByPathOrAlias(removeInitialAndTrailingSlashes(
|
|
152
|
+
const baseCollection = getCollectionByPathOrAlias(removeInitialAndTrailingSlashes(idOrPath), collections);
|
|
154
153
|
|
|
155
|
-
const userOverride = includeUserOverride ? userConfigPersistence?.getCollectionConfig(
|
|
154
|
+
const userOverride = includeUserOverride ? userConfigPersistence?.getCollectionConfig(idOrPath) : undefined;
|
|
156
155
|
|
|
157
156
|
const overriddenCollection = baseCollection ? mergeDeep(baseCollection, userOverride) : undefined;
|
|
158
157
|
|
|
@@ -187,7 +186,7 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
|
|
|
187
186
|
|
|
188
187
|
for (let i = 0; i < pathSegments.length; i++) {
|
|
189
188
|
const pathSegment = pathSegments[i];
|
|
190
|
-
const collection: EntityCollection | undefined = currentCollections!.find(c => c.
|
|
189
|
+
const collection: EntityCollection | undefined = currentCollections!.find(c => c.id === pathSegment || c.path === pathSegment);
|
|
191
190
|
if (!collection)
|
|
192
191
|
return undefined;
|
|
193
192
|
currentCollections = collection.subcollections;
|
|
@@ -199,6 +198,25 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
|
|
|
199
198
|
|
|
200
199
|
}, [collections]);
|
|
201
200
|
|
|
201
|
+
const getCollectionFromIds = useCallback(<EC extends EntityCollection>(ids: string[]): EC | undefined => {
|
|
202
|
+
let currentCollections = collections;
|
|
203
|
+
if (!currentCollections)
|
|
204
|
+
throw Error("Collections have not been initialised yet");
|
|
205
|
+
|
|
206
|
+
for (let i = 0; i < ids.length; i++) {
|
|
207
|
+
const id = ids[i];
|
|
208
|
+
const collection: EntityCollection | undefined = currentCollections!.find(c => c.id === id);
|
|
209
|
+
if (!collection)
|
|
210
|
+
return undefined;
|
|
211
|
+
currentCollections = collection.subcollections;
|
|
212
|
+
if (i === ids.length - 1)
|
|
213
|
+
return collection as EC;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return undefined;
|
|
217
|
+
|
|
218
|
+
}, [collections]);
|
|
219
|
+
|
|
202
220
|
const isUrlCollectionPath = useCallback(
|
|
203
221
|
(path: string): boolean => removeInitialAndTrailingSlashes(path + "/").startsWith(removeInitialAndTrailingSlashes(fullCollectionPath) + "/"),
|
|
204
222
|
[fullCollectionPath]);
|
|
@@ -239,6 +257,10 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
|
|
|
239
257
|
});
|
|
240
258
|
}, [collections]);
|
|
241
259
|
|
|
260
|
+
const getParentCollectionIds = useCallback((path: string): string[] => {
|
|
261
|
+
return getAllParentCollectionsForPath(path).map(r => r.id);
|
|
262
|
+
}, [getAllParentCollectionsForPath])
|
|
263
|
+
|
|
242
264
|
return useMemo(() => ({
|
|
243
265
|
collections: collections ?? [],
|
|
244
266
|
views: views ?? [],
|
|
@@ -250,6 +272,7 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
|
|
|
250
272
|
initialised,
|
|
251
273
|
getCollection,
|
|
252
274
|
getCollectionFromPaths,
|
|
275
|
+
getCollectionFromIds,
|
|
253
276
|
isUrlCollectionPath,
|
|
254
277
|
urlPathToDataPath,
|
|
255
278
|
buildUrlCollectionPath,
|
|
@@ -259,7 +282,8 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
|
|
|
259
282
|
topLevelNavigation,
|
|
260
283
|
baseLocation,
|
|
261
284
|
refreshNavigation,
|
|
262
|
-
getParentReferencesFromPath: getAllParentCollectionsForPath
|
|
285
|
+
getParentReferencesFromPath: getAllParentCollectionsForPath,
|
|
286
|
+
getParentCollectionIds
|
|
263
287
|
}), [baseCollectionPath, baseLocation, basePath, buildCMSUrlPath, buildUrlCollectionPath, buildUrlEditCollectionPath, collections, getAllParentCollectionsForPath, getCollection, getCollectionFromPaths, homeUrl, initialised, isUrlCollectionPath, navigationLoading, navigationLoadingError, refreshNavigation, resolveAliasesFrom, topLevelNavigation, urlPathToDataPath, views]);
|
|
264
288
|
}
|
|
265
289
|
|
|
@@ -125,7 +125,7 @@ export function buildSidePanelsFromUrl(path: string, collections: EntityCollecti
|
|
|
125
125
|
if (previousEntry.type === "entity") {
|
|
126
126
|
const lastSidePanel: EntitySidePanelProps<any> = sidePanels[sidePanels.length - 1];
|
|
127
127
|
if (lastSidePanel)
|
|
128
|
-
lastSidePanel.selectedSubPath = navigationEntry.collection.
|
|
128
|
+
lastSidePanel.selectedSubPath = navigationEntry.collection.id ?? navigationEntry.collection.path;
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
131
|
}
|
|
@@ -17,7 +17,6 @@ import { UrlComponentPreview } from "./components/UrlComponentPreview";
|
|
|
17
17
|
import { StorageThumbnail } from "./components/StorageThumbnail";
|
|
18
18
|
import { Markdown } from "../ui";
|
|
19
19
|
import { StringPropertyPreview } from "./property_previews/StringPropertyPreview";
|
|
20
|
-
import { ArrayOfMapsPreview } from "./property_previews/ArrayOfMapsPreview";
|
|
21
20
|
import { ArrayPropertyPreview } from "./property_previews/ArrayPropertyPreview";
|
|
22
21
|
import { ArrayOfReferencesPreview } from "./property_previews/ArrayOfReferencesPreview";
|
|
23
22
|
import { ArrayOfStorageComponentsPreview } from "./property_previews/ArrayOfStorageComponentsPreview";
|
package/src/types/collections.ts
CHANGED
|
@@ -18,6 +18,14 @@ import { ExportConfig } from "./export_import";
|
|
|
18
18
|
*/
|
|
19
19
|
export interface EntityCollection<M extends Record<string, any> = any, UserType extends User = User> {
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
* You can set an alias that will be used internally instead of the `path`.
|
|
23
|
+
* The `alias` value will be used to determine the URL of the collection,
|
|
24
|
+
* while `path` will still be used in the datasource.
|
|
25
|
+
* Note that you can use this value in reference properties too.
|
|
26
|
+
*/
|
|
27
|
+
id: string;
|
|
28
|
+
|
|
21
29
|
/**
|
|
22
30
|
* Name of the collection, typically plural.
|
|
23
31
|
* E.g. `Products`, `Blog`
|
|
@@ -48,14 +56,6 @@ export interface EntityCollection<M extends Record<string, any> = any, UserType
|
|
|
48
56
|
*/
|
|
49
57
|
collectionGroup?: boolean;
|
|
50
58
|
|
|
51
|
-
/**
|
|
52
|
-
* You can set an alias that will be used internally instead of the `path`.
|
|
53
|
-
* The `alias` value will be used to determine the URL of the collection,
|
|
54
|
-
* while `path` will still be used in the datasource.
|
|
55
|
-
* Note that you can use this value in reference properties too.
|
|
56
|
-
*/
|
|
57
|
-
alias?: string;
|
|
58
|
-
|
|
59
59
|
/**
|
|
60
60
|
* Icon key to use in this collection.
|
|
61
61
|
* You can use any of the icons in the Material specs:
|
|
@@ -300,7 +300,7 @@ export interface CollectionActionsProps<M extends Record<string, any> = any, Use
|
|
|
300
300
|
/**
|
|
301
301
|
* Array of the parent path segments like `['users']`
|
|
302
302
|
*/
|
|
303
|
-
|
|
303
|
+
parentCollectionIds: string[];
|
|
304
304
|
|
|
305
305
|
/**
|
|
306
306
|
* The collection configuration
|
package/src/types/firecms.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { User } from "./user";
|
|
3
3
|
import { AuthController } from "./auth";
|
|
4
|
-
import {
|
|
4
|
+
import { DataSourceDelegate } from "./datasource";
|
|
5
5
|
import { EntityCollection, EntityCustomView } from "./collections";
|
|
6
6
|
import { CMSView } from "./navigation";
|
|
7
7
|
import { FireCMSContext } from "./firecms_context";
|
package/src/types/index.ts
CHANGED
package/src/types/navigation.ts
CHANGED
|
@@ -52,6 +52,11 @@ export type NavigationController = {
|
|
|
52
52
|
getCollection: <EC extends EntityCollection = EntityCollection<any>>(pathOrAlias: string,
|
|
53
53
|
entityId?: string,
|
|
54
54
|
includeUserOverride?: boolean) => EC | undefined;
|
|
55
|
+
/**
|
|
56
|
+
* Get the collection configuration from its parent path segments.
|
|
57
|
+
*/
|
|
58
|
+
getCollectionFromIds: <EC extends EntityCollection = EntityCollection<any>>(ids: string[]) => EC | undefined;
|
|
59
|
+
|
|
55
60
|
/**
|
|
56
61
|
* Get the collection configuration from its parent path segments.
|
|
57
62
|
*/
|
|
@@ -128,6 +133,12 @@ export type NavigationController = {
|
|
|
128
133
|
* @param path
|
|
129
134
|
*/
|
|
130
135
|
getParentReferencesFromPath: (path: string) => EntityReference[];
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Retrieve all the related parent collection ids for a given path
|
|
139
|
+
* @param path
|
|
140
|
+
*/
|
|
141
|
+
getParentCollectionIds: (path: string) => string[];
|
|
131
142
|
}
|
|
132
143
|
|
|
133
144
|
/**
|
package/src/types/plugins.tsx
CHANGED
|
@@ -116,7 +116,7 @@ export type FireCMSPlugin<PROPS = any, FORM_PROPS = any, EC extends EntityCollec
|
|
|
116
116
|
property: ResolvedProperty,
|
|
117
117
|
propertyKey: string,
|
|
118
118
|
fullPath: string,
|
|
119
|
-
|
|
119
|
+
parentCollectionIds: string[],
|
|
120
120
|
onHover: boolean,
|
|
121
121
|
collection: EC;
|
|
122
122
|
}>;
|
|
@@ -127,7 +127,7 @@ export type FireCMSPlugin<PROPS = any, FORM_PROPS = any, EC extends EntityCollec
|
|
|
127
127
|
*/
|
|
128
128
|
AddColumnComponent?: React.ComponentType<{
|
|
129
129
|
fullPath: string,
|
|
130
|
-
|
|
130
|
+
parentCollectionIds: string[],
|
|
131
131
|
collection: EC;
|
|
132
132
|
}>;
|
|
133
133
|
}
|