@firecms/core 3.0.0-beta.12 → 3.0.0-beta.14
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/app/Scaffold.d.ts +4 -0
- package/dist/components/ArrayContainer.d.ts +13 -11
- package/dist/components/EntityCollectionView/EntityCollectionView.d.ts +4 -0
- package/dist/components/EntityJsonPreview.d.ts +3 -0
- package/dist/components/EntityPreview.d.ts +4 -2
- package/dist/components/SelectableTable/SelectableTable.d.ts +1 -1
- package/dist/components/VirtualTable/VirtualTableProps.d.ts +0 -4
- package/dist/components/index.d.ts +1 -0
- package/dist/core/DefaultAppBar.d.ts +8 -2
- package/dist/core/EntityEditView.d.ts +8 -1
- package/dist/core/FireCMS.d.ts +2 -2
- package/dist/form/EntityForm.d.ts +5 -1
- package/dist/form/PropertyFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/StorageUploadFieldBinding.d.ts +3 -9
- package/dist/hooks/data/save.d.ts +1 -1
- package/dist/hooks/useBuildNavigationController.d.ts +2 -9
- package/dist/index.es.js +9251 -8721
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +16686 -16160
- package/dist/index.umd.js.map +1 -1
- package/dist/internal/useBuildDataSource.d.ts +3 -2
- package/dist/internal/useBuildSideEntityController.d.ts +3 -3
- package/dist/types/collections.d.ts +26 -2
- package/dist/types/fields.d.ts +4 -1
- package/dist/types/firecms.d.ts +3 -2
- package/dist/types/navigation.d.ts +9 -0
- package/dist/types/plugins.d.ts +13 -0
- package/dist/types/properties.d.ts +22 -1
- package/dist/types/side_entity_controller.d.ts +4 -0
- package/dist/util/callbacks.d.ts +2 -0
- package/dist/util/createFormexStub.d.ts +2 -0
- package/dist/util/index.d.ts +1 -0
- package/dist/util/navigation_utils.d.ts +2 -1
- package/dist/util/objects.d.ts +1 -1
- package/dist/util/property_utils.d.ts +2 -2
- package/dist/util/references.d.ts +2 -2
- package/dist/util/resolutions.d.ts +11 -6
- package/package.json +9 -6
- package/src/app/Scaffold.tsx +13 -3
- package/src/components/ArrayContainer.tsx +414 -282
- package/src/components/ClearFilterSortButton.tsx +1 -1
- package/src/components/ConfirmationDialog.tsx +9 -9
- package/src/components/DeleteEntityDialog.tsx +4 -2
- package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +8 -6
- package/src/components/EntityCollectionTable/PropertyTableCell.tsx +1 -1
- package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +1 -1
- package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +13 -2
- package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +58 -29
- package/src/components/EntityCollectionTable/internal/popup_field/useDraggable.tsx +9 -9
- package/src/components/EntityCollectionView/EntityCollectionView.tsx +26 -6
- package/src/components/EntityJsonPreview.tsx +66 -0
- package/src/components/EntityPreview.tsx +27 -16
- package/src/components/EntityView.tsx +4 -1
- package/src/components/ErrorView.tsx +1 -1
- package/src/components/HomePage/DefaultHomePage.tsx +2 -1
- package/src/components/HomePage/NavigationCardBinding.tsx +3 -1
- package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +3 -1
- package/src/components/SelectableTable/SelectableTable.tsx +140 -143
- package/src/components/VirtualTable/VirtualTable.tsx +37 -31
- package/src/components/VirtualTable/VirtualTableProps.tsx +0 -5
- package/src/components/VirtualTable/fields/VirtualTableInput.tsx +0 -1
- package/src/components/common/default_entity_actions.tsx +15 -4
- package/src/components/index.tsx +2 -0
- package/src/core/DefaultAppBar.tsx +17 -5
- package/src/core/EntityEditView.tsx +135 -47
- package/src/core/EntitySidePanel.tsx +15 -20
- package/src/core/FireCMS.tsx +19 -12
- package/src/form/EntityForm.tsx +32 -24
- package/src/form/PropertyFieldBinding.tsx +8 -6
- package/src/form/components/CustomIdField.tsx +3 -1
- package/src/form/components/LabelWithIcon.tsx +1 -1
- package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +4 -1
- package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +4 -2
- package/src/form/field_bindings/BlockFieldBinding.tsx +1 -1
- package/src/form/field_bindings/KeyValueFieldBinding.tsx +1 -1
- package/src/form/field_bindings/MapFieldBinding.tsx +5 -4
- package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +6 -2
- package/src/form/field_bindings/MultiSelectFieldBinding.tsx +3 -3
- package/src/form/field_bindings/RepeatFieldBinding.tsx +9 -2
- package/src/form/field_bindings/SelectFieldBinding.tsx +3 -2
- package/src/form/field_bindings/StorageUploadFieldBinding.tsx +227 -156
- package/src/hooks/data/save.ts +24 -35
- package/src/hooks/useBuildNavigationController.tsx +42 -17
- package/src/hooks/useFireCMSContext.tsx +0 -30
- package/src/internal/useBuildDataSource.ts +9 -5
- package/src/internal/useBuildSideEntityController.tsx +26 -20
- package/src/preview/PropertyPreview.tsx +4 -2
- package/src/preview/components/ImagePreview.tsx +2 -2
- package/src/preview/components/ReferencePreview.tsx +1 -1
- package/src/preview/property_previews/ArrayOfMapsPreview.tsx +5 -4
- package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +4 -3
- package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +4 -2
- package/src/preview/property_previews/ArrayOfStringsPreview.tsx +4 -3
- package/src/preview/property_previews/ArrayOneOfPreview.tsx +4 -2
- package/src/preview/property_previews/ArrayPropertyPreview.tsx +4 -2
- package/src/preview/property_previews/MapPropertyPreview.tsx +1 -1
- package/src/preview/property_previews/SkeletonPropertyComponent.tsx +1 -1
- package/src/preview/property_previews/StringPropertyPreview.tsx +1 -1
- package/src/routes/FireCMSRoute.tsx +15 -4
- package/src/types/collections.ts +31 -2
- package/src/types/fields.tsx +5 -1
- package/src/types/firecms.tsx +3 -3
- package/src/types/navigation.ts +11 -0
- package/src/types/plugins.tsx +17 -0
- package/src/types/properties.ts +27 -1
- package/src/types/side_entity_controller.tsx +5 -0
- package/src/util/callbacks.ts +119 -0
- package/src/util/createFormexStub.tsx +62 -0
- package/src/util/index.ts +1 -0
- package/src/util/join_collections.ts +3 -1
- package/src/util/navigation_from_path.ts +5 -1
- package/src/util/navigation_utils.ts +84 -20
- package/src/util/objects.ts +54 -17
- package/src/util/property_utils.tsx +7 -3
- package/src/util/references.ts +8 -6
- package/src/util/resolutions.ts +17 -9
- package/src/util/useStorageUploadController.tsx +21 -2
- package/dist/components/EntityCollectionTable/internal/popup_field/ElementResizeListener.d.ts +0 -5
- package/src/components/EntityCollectionTable/internal/popup_field/ElementResizeListener.tsx +0 -59
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
EntityCollection,
|
|
10
10
|
EntityCollectionsBuilder,
|
|
11
11
|
EntityReference,
|
|
12
|
+
FireCMSPlugin,
|
|
12
13
|
NavigationBlocker,
|
|
13
14
|
NavigationController,
|
|
14
15
|
PermissionsBuilder,
|
|
@@ -43,15 +44,7 @@ export type BuildNavigationContextProps<EC extends EntityCollection, USER extend
|
|
|
43
44
|
viewsOrder?: string[];
|
|
44
45
|
userConfigPersistence?: UserConfigurationPersistence;
|
|
45
46
|
dataSourceDelegate: DataSourceDelegate;
|
|
46
|
-
|
|
47
|
-
* Use this method to inject collections to the CMS.
|
|
48
|
-
* You receive the current collections as a parameter, and you can return
|
|
49
|
-
* a new list of collections.
|
|
50
|
-
* @see {@link joinCollectionLists}
|
|
51
|
-
* @param collections
|
|
52
|
-
*/
|
|
53
|
-
injectCollections?: (collections: EntityCollection[]) => EntityCollection[];
|
|
54
|
-
|
|
47
|
+
plugins?: FireCMSPlugin[];
|
|
55
48
|
/**
|
|
56
49
|
* If true, the navigation logic will not be updated until this flag is false
|
|
57
50
|
*/
|
|
@@ -68,9 +61,9 @@ export function useBuildNavigationController<EC extends EntityCollection, USER e
|
|
|
68
61
|
views: viewsProp,
|
|
69
62
|
adminViews: adminViewsProp,
|
|
70
63
|
viewsOrder,
|
|
64
|
+
plugins,
|
|
71
65
|
userConfigPersistence,
|
|
72
66
|
dataSourceDelegate,
|
|
73
|
-
injectCollections,
|
|
74
67
|
disabled
|
|
75
68
|
} = props;
|
|
76
69
|
|
|
@@ -203,7 +196,7 @@ export function useBuildNavigationController<EC extends EntityCollection, USER e
|
|
|
203
196
|
try {
|
|
204
197
|
|
|
205
198
|
const [resolvedCollections = [], resolvedViews, resolvedAdminViews = []] = await Promise.all([
|
|
206
|
-
resolveCollections(collectionsProp, collectionPermissions, authController, dataSourceDelegate,
|
|
199
|
+
resolveCollections(collectionsProp, collectionPermissions, authController, dataSourceDelegate, plugins),
|
|
207
200
|
resolveCMSViews(viewsProp, authController, dataSourceDelegate),
|
|
208
201
|
resolveCMSViews(adminViewsProp, authController, dataSourceDelegate)
|
|
209
202
|
]
|
|
@@ -250,8 +243,7 @@ export function useBuildNavigationController<EC extends EntityCollection, USER e
|
|
|
250
243
|
disabled,
|
|
251
244
|
viewsProp,
|
|
252
245
|
adminViewsProp,
|
|
253
|
-
computeTopNavigation
|
|
254
|
-
injectCollections
|
|
246
|
+
computeTopNavigation
|
|
255
247
|
]);
|
|
256
248
|
|
|
257
249
|
useEffect(() => {
|
|
@@ -291,6 +283,16 @@ export function useBuildNavigationController<EC extends EntityCollection, USER e
|
|
|
291
283
|
|
|
292
284
|
}, [userConfigPersistence]);
|
|
293
285
|
|
|
286
|
+
const getCollectionById = useCallback((id: string): EC | undefined => {
|
|
287
|
+
const collections = collectionsRef.current;
|
|
288
|
+
if (collections === undefined)
|
|
289
|
+
throw Error("getCollectionById: Collections have not been initialised yet");
|
|
290
|
+
const collection: EntityCollection | undefined = collections.find(c => c.id === id);
|
|
291
|
+
if (!collection)
|
|
292
|
+
return undefined;
|
|
293
|
+
return collection as EC;
|
|
294
|
+
}, []);
|
|
295
|
+
|
|
294
296
|
const getCollectionFromPaths = useCallback(<EC extends EntityCollection>(pathSegments: string[]): EC | undefined => {
|
|
295
297
|
|
|
296
298
|
const collections = collectionsRef.current;
|
|
@@ -398,6 +400,7 @@ export function useBuildNavigationController<EC extends EntityCollection, USER e
|
|
|
398
400
|
baseCollectionPath,
|
|
399
401
|
initialised,
|
|
400
402
|
getCollection,
|
|
403
|
+
getCollectionById,
|
|
401
404
|
getCollectionFromPaths,
|
|
402
405
|
getCollectionFromIds,
|
|
403
406
|
isUrlCollectionPath,
|
|
@@ -410,6 +413,7 @@ export function useBuildNavigationController<EC extends EntityCollection, USER e
|
|
|
410
413
|
getParentCollectionIds,
|
|
411
414
|
convertIdsToPaths,
|
|
412
415
|
navigate,
|
|
416
|
+
plugins
|
|
413
417
|
};
|
|
414
418
|
}
|
|
415
419
|
|
|
@@ -436,11 +440,24 @@ function filterOutNotAllowedCollections(resolvedCollections: EntityCollection[],
|
|
|
436
440
|
});
|
|
437
441
|
}
|
|
438
442
|
|
|
443
|
+
function applyPluginModifyCollection(resolvedCollections: EntityCollection[], modifyCollection: (collection: EntityCollection) => EntityCollection) {
|
|
444
|
+
return resolvedCollections.map((collection: EntityCollection): EntityCollection => {
|
|
445
|
+
const modifiedCollection = modifyCollection(collection);
|
|
446
|
+
if (modifiedCollection.subcollections) {
|
|
447
|
+
return {
|
|
448
|
+
...modifiedCollection,
|
|
449
|
+
subcollections: applyPluginModifyCollection(modifiedCollection.subcollections, modifyCollection)
|
|
450
|
+
} satisfies EntityCollection;
|
|
451
|
+
}
|
|
452
|
+
return modifiedCollection;
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
|
|
439
456
|
async function resolveCollections(collections: undefined | EntityCollection[] | EntityCollectionsBuilder<any>,
|
|
440
457
|
collectionPermissions: PermissionsBuilder | undefined,
|
|
441
458
|
authController: AuthController,
|
|
442
459
|
dataSource: DataSourceDelegate,
|
|
443
|
-
|
|
460
|
+
plugins: FireCMSPlugin[] | undefined): Promise<EntityCollection[]> {
|
|
444
461
|
let resolvedCollections: EntityCollection[] = [];
|
|
445
462
|
if (typeof collections === "function") {
|
|
446
463
|
resolvedCollections = await collections({
|
|
@@ -452,8 +469,16 @@ async function resolveCollections(collections: undefined | EntityCollection[] |
|
|
|
452
469
|
resolvedCollections = collections;
|
|
453
470
|
}
|
|
454
471
|
|
|
455
|
-
if (
|
|
456
|
-
|
|
472
|
+
if (plugins) {
|
|
473
|
+
for (const plugin of plugins) {
|
|
474
|
+
if (plugin.collection?.modifyCollection) {
|
|
475
|
+
resolvedCollections = applyPluginModifyCollection(resolvedCollections, plugin.collection.modifyCollection);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
if (plugin.collection?.injectCollections) {
|
|
479
|
+
resolvedCollections = plugin.collection.injectCollections(resolvedCollections ?? []);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
457
482
|
}
|
|
458
483
|
|
|
459
484
|
resolvedCollections = applyPermissionsFunctionIfEmpty(resolvedCollections, collectionPermissions);
|
|
@@ -528,7 +553,7 @@ function useCustomBlocker(): NavigationBlocker {
|
|
|
528
553
|
return shouldBlock;
|
|
529
554
|
});
|
|
530
555
|
} catch (e) {
|
|
531
|
-
console.warn("Blocker not available, navigation will not be blocked");
|
|
556
|
+
// console.warn("Blocker not available, navigation will not be blocked");
|
|
532
557
|
}
|
|
533
558
|
|
|
534
559
|
const updateBlockListener = (path: string, block: boolean, basePath?: string) => {
|
|
@@ -67,33 +67,3 @@ export const useFireCMSContext = <USER extends User = User, AuthControllerType e
|
|
|
67
67
|
|
|
68
68
|
return fireCMSContextRef.current;
|
|
69
69
|
}
|
|
70
|
-
|
|
71
|
-
// export const useFireCMSContext = <USER extends User = User, AuthControllerType extends AuthController<USER> = AuthController<USER>>(): FireCMSContext<USER, AuthControllerType> => {
|
|
72
|
-
//
|
|
73
|
-
// const authController = useAuthController<USER, AuthControllerType>();
|
|
74
|
-
// const sideDialogsController = useSideDialogsController();
|
|
75
|
-
// const sideEntityController = useSideEntityController();
|
|
76
|
-
// const navigation = useNavigationController();
|
|
77
|
-
// const dataSource = useDataSource();
|
|
78
|
-
// const storageSource = useStorageSource();
|
|
79
|
-
// const snackbarController = useSnackbarController();
|
|
80
|
-
// const userConfigPersistence = useUserConfigurationPersistence();
|
|
81
|
-
// const dialogsController = useDialogsController();
|
|
82
|
-
// const customizationController = useCustomizationController();
|
|
83
|
-
// const analyticsController = useAnalyticsController();
|
|
84
|
-
//
|
|
85
|
-
// return {
|
|
86
|
-
// authController,
|
|
87
|
-
// sideDialogsController,
|
|
88
|
-
// sideEntityController,
|
|
89
|
-
// navigation,
|
|
90
|
-
// dataSource,
|
|
91
|
-
// storageSource,
|
|
92
|
-
// snackbarController,
|
|
93
|
-
// userConfigPersistence,
|
|
94
|
-
// dialogsController,
|
|
95
|
-
// customizationController,
|
|
96
|
-
// analyticsController
|
|
97
|
-
// };
|
|
98
|
-
//
|
|
99
|
-
// };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useCallback } from "react";
|
|
2
2
|
import {
|
|
3
|
+
AuthController,
|
|
3
4
|
DataSource,
|
|
4
5
|
DataSourceDelegate,
|
|
5
6
|
DeleteEntityProps,
|
|
@@ -27,11 +28,13 @@ import { resolveCollection, updateDateAutoValues } from "../util";
|
|
|
27
28
|
export function useBuildDataSource({
|
|
28
29
|
delegate,
|
|
29
30
|
propertyConfigs,
|
|
30
|
-
navigationController
|
|
31
|
+
navigationController,
|
|
32
|
+
authController
|
|
31
33
|
}: {
|
|
32
34
|
delegate: DataSourceDelegate,
|
|
33
35
|
propertyConfigs?: Record<string, PropertyConfig>;
|
|
34
36
|
navigationController: NavigationController;
|
|
37
|
+
authController: AuthController;
|
|
35
38
|
}): DataSource {
|
|
36
39
|
|
|
37
40
|
return {
|
|
@@ -209,26 +212,27 @@ export function useBuildDataSource({
|
|
|
209
212
|
collection,
|
|
210
213
|
path,
|
|
211
214
|
entityId,
|
|
212
|
-
propertyConfigs: propertyConfigs
|
|
215
|
+
propertyConfigs: propertyConfigs,
|
|
216
|
+
authController
|
|
213
217
|
})
|
|
214
218
|
: undefined;
|
|
215
219
|
|
|
216
220
|
const properties: ResolvedProperties<M> | undefined = resolvedCollection?.properties;
|
|
217
221
|
|
|
218
|
-
const
|
|
222
|
+
const delegateValues = usedDelegate.cmsToDelegateModel(
|
|
219
223
|
values,
|
|
220
224
|
);
|
|
221
225
|
|
|
222
226
|
const updatedValues: EntityValues<M> = properties
|
|
223
227
|
? updateDateAutoValues(
|
|
224
228
|
{
|
|
225
|
-
inputValues:
|
|
229
|
+
inputValues: delegateValues,
|
|
226
230
|
properties,
|
|
227
231
|
status,
|
|
228
232
|
timestampNowValue: usedDelegate.currentTime?.() ?? new Date(),
|
|
229
233
|
setDateToMidnight: usedDelegate.setDateToMidnight
|
|
230
234
|
})
|
|
231
|
-
:
|
|
235
|
+
: delegateValues;
|
|
232
236
|
|
|
233
237
|
return usedDelegate.saveEntity({
|
|
234
238
|
path,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useCallback, useEffect, useRef } from "react";
|
|
2
2
|
import {
|
|
3
|
+
AuthController,
|
|
3
4
|
CustomizationController,
|
|
4
5
|
EntityCollection,
|
|
5
6
|
EntitySidePanelProps,
|
|
@@ -20,18 +21,19 @@ import {
|
|
|
20
21
|
import { ADDITIONAL_TAB_WIDTH, CONTAINER_FULL_WIDTH, FORM_CONTAINER_WIDTH } from "./common";
|
|
21
22
|
import { useCustomizationController, useLargeLayout } from "../hooks";
|
|
22
23
|
import { EntitySidePanel } from "../core/EntitySidePanel";
|
|
24
|
+
import { JSON_TAB_VALUE } from "../core/EntityEditView";
|
|
23
25
|
|
|
24
26
|
const NEW_URL_HASH = "new_side";
|
|
25
27
|
const SIDE_URL_HASH = "side";
|
|
26
28
|
|
|
27
|
-
export function getEntityViewWidth(props: EntitySidePanelProps<any>, small: boolean, customizationController: CustomizationController): string {
|
|
29
|
+
export function getEntityViewWidth(props: EntitySidePanelProps<any>, small: boolean, customizationController: CustomizationController, authController: AuthController): string {
|
|
28
30
|
if (small) return CONTAINER_FULL_WIDTH;
|
|
29
31
|
|
|
30
32
|
const {
|
|
31
33
|
selectedSecondaryForm
|
|
32
34
|
} = resolvedSelectedEntityView(props.collection?.entityViews, customizationController, props.selectedTab);
|
|
33
35
|
|
|
34
|
-
const shouldUseSmallLayout = !props.selectedTab || Boolean(selectedSecondaryForm);
|
|
36
|
+
const shouldUseSmallLayout = !props.selectedTab || props.selectedTab === JSON_TAB_VALUE || props.selectedTab === "__history" || Boolean(selectedSecondaryForm);
|
|
35
37
|
|
|
36
38
|
let resolvedWidth: string | undefined;
|
|
37
39
|
if (props.width) {
|
|
@@ -48,21 +50,22 @@ export function getEntityViewWidth(props: EntitySidePanelProps<any>, small: bool
|
|
|
48
50
|
} else if (!props.collection) {
|
|
49
51
|
return FORM_CONTAINER_WIDTH;
|
|
50
52
|
} else {
|
|
51
|
-
return calculateCollectionDesiredWidth(props.collection);
|
|
53
|
+
return calculateCollectionDesiredWidth(props.collection, authController);
|
|
52
54
|
}
|
|
53
55
|
}
|
|
54
56
|
}
|
|
55
57
|
|
|
56
58
|
const collectionViewWidthCache: { [key: string]: string } = {};
|
|
57
59
|
|
|
58
|
-
function calculateCollectionDesiredWidth(collection: EntityCollection<any
|
|
60
|
+
function calculateCollectionDesiredWidth(collection: EntityCollection<any>, authController: AuthController): string {
|
|
59
61
|
if (collectionViewWidthCache[collection.id]) {
|
|
60
62
|
return collectionViewWidthCache[collection.id];
|
|
61
63
|
}
|
|
62
64
|
const resolvedCollection = resolveCollection({
|
|
63
65
|
collection,
|
|
64
66
|
path: "__ignored",
|
|
65
|
-
ignoreMissingFields: true
|
|
67
|
+
ignoreMissingFields: true,
|
|
68
|
+
authController
|
|
66
69
|
});
|
|
67
70
|
|
|
68
71
|
let result = FORM_CONTAINER_WIDTH
|
|
@@ -97,7 +100,9 @@ function getNestedPropertiesDepth(property: ResolvedProperty, accumulator: numbe
|
|
|
97
100
|
}
|
|
98
101
|
|
|
99
102
|
export const useBuildSideEntityController = (navigation: NavigationController,
|
|
100
|
-
sideDialogsController: SideDialogsController
|
|
103
|
+
sideDialogsController: SideDialogsController,
|
|
104
|
+
authController: AuthController
|
|
105
|
+
): SideEntityController => {
|
|
101
106
|
|
|
102
107
|
const location = useLocation();
|
|
103
108
|
const initialised = useRef<boolean>(false);
|
|
@@ -105,7 +110,6 @@ export const useBuildSideEntityController = (navigation: NavigationController,
|
|
|
105
110
|
|
|
106
111
|
const smallLayout = !useLargeLayout();
|
|
107
112
|
|
|
108
|
-
// only on initialisation, create panels from URL
|
|
109
113
|
useEffect(() => {
|
|
110
114
|
|
|
111
115
|
const newFlag = location.hash === `#${NEW_URL_HASH}`;
|
|
@@ -118,9 +122,9 @@ export const useBuildSideEntityController = (navigation: NavigationController,
|
|
|
118
122
|
for (let i = 0; i < panelsFromUrl.length; i++) {
|
|
119
123
|
const props = panelsFromUrl[i];
|
|
120
124
|
if (i === 0)
|
|
121
|
-
sideDialogsController.replace(propsToSidePanel(props, navigation.buildUrlCollectionPath, navigation.resolveIdsFrom, smallLayout, customizationController));
|
|
125
|
+
sideDialogsController.replace(propsToSidePanel(props, navigation.buildUrlCollectionPath, navigation.resolveIdsFrom, smallLayout, customizationController, authController));
|
|
122
126
|
else
|
|
123
|
-
sideDialogsController.open(propsToSidePanel(props, navigation.buildUrlCollectionPath, navigation.resolveIdsFrom, smallLayout, customizationController))
|
|
127
|
+
sideDialogsController.open(propsToSidePanel(props, navigation.buildUrlCollectionPath, navigation.resolveIdsFrom, smallLayout, customizationController, authController))
|
|
124
128
|
}
|
|
125
129
|
}
|
|
126
130
|
initialised.current = true;
|
|
@@ -140,7 +144,7 @@ export const useBuildSideEntityController = (navigation: NavigationController,
|
|
|
140
144
|
return;
|
|
141
145
|
}
|
|
142
146
|
const lastPanel = panelsFromUrl[panelsFromUrl.length - 1];
|
|
143
|
-
const panelProps = propsToSidePanel(lastPanel, navigation.buildUrlCollectionPath, navigation.resolveIdsFrom, smallLayout, customizationController);
|
|
147
|
+
const panelProps = propsToSidePanel(lastPanel, navigation.buildUrlCollectionPath, navigation.resolveIdsFrom, smallLayout, customizationController, authController);
|
|
144
148
|
const lastCurrentPanel = currentPanelKeys.length > 0 ? currentPanelKeys[currentPanelKeys.length - 1] : undefined;
|
|
145
149
|
if (!lastCurrentPanel || lastCurrentPanel !== panelProps.key) {
|
|
146
150
|
sideDialogsController.replace(panelProps);
|
|
@@ -153,7 +157,7 @@ export const useBuildSideEntityController = (navigation: NavigationController,
|
|
|
153
157
|
useEffect(() => {
|
|
154
158
|
const updatedSidePanels = sideDialogsController.sidePanels.map(sidePanelProps => {
|
|
155
159
|
if (sidePanelProps.additional) {
|
|
156
|
-
return propsToSidePanel(sidePanelProps.additional, navigation.buildUrlCollectionPath, navigation.resolveIdsFrom, smallLayout, customizationController);
|
|
160
|
+
return propsToSidePanel(sidePanelProps.additional, navigation.buildUrlCollectionPath, navigation.resolveIdsFrom, smallLayout, customizationController, authController);
|
|
157
161
|
}
|
|
158
162
|
return sidePanelProps;
|
|
159
163
|
});
|
|
@@ -186,10 +190,11 @@ export const useBuildSideEntityController = (navigation: NavigationController,
|
|
|
186
190
|
navigation.buildUrlCollectionPath,
|
|
187
191
|
navigation.resolveIdsFrom,
|
|
188
192
|
smallLayout,
|
|
189
|
-
customizationController
|
|
193
|
+
customizationController,
|
|
194
|
+
authController
|
|
190
195
|
));
|
|
191
196
|
|
|
192
|
-
}, [sideDialogsController, navigation.buildUrlCollectionPath, navigation.resolveIdsFrom, smallLayout]);
|
|
197
|
+
}, [sideDialogsController, navigation.buildUrlCollectionPath, navigation.resolveIdsFrom, smallLayout, authController.user]);
|
|
193
198
|
|
|
194
199
|
const replace = useCallback((props: EntitySidePanelProps<any>) => {
|
|
195
200
|
|
|
@@ -197,9 +202,9 @@ export const useBuildSideEntityController = (navigation: NavigationController,
|
|
|
197
202
|
throw Error("If you want to copy an entity you need to provide an entityId");
|
|
198
203
|
}
|
|
199
204
|
|
|
200
|
-
sideDialogsController.replace(propsToSidePanel(props, navigation.buildUrlCollectionPath, navigation.resolveIdsFrom, smallLayout, customizationController));
|
|
205
|
+
sideDialogsController.replace(propsToSidePanel(props, navigation.buildUrlCollectionPath, navigation.resolveIdsFrom, smallLayout, customizationController, authController));
|
|
201
206
|
|
|
202
|
-
}, [navigation.buildUrlCollectionPath, navigation.resolveIdsFrom, sideDialogsController, smallLayout]);
|
|
207
|
+
}, [navigation.buildUrlCollectionPath, navigation.resolveIdsFrom, sideDialogsController, smallLayout, authController.user]);
|
|
203
208
|
|
|
204
209
|
return {
|
|
205
210
|
close,
|
|
@@ -228,6 +233,7 @@ export function buildSidePanelsFromUrl(path: string, collections: EntityCollecti
|
|
|
228
233
|
if (navigationEntry.type === "entity") {
|
|
229
234
|
sidePanel = {
|
|
230
235
|
path: navigationEntry.path,
|
|
236
|
+
// fullIdPath: navigationEntry.path,
|
|
231
237
|
entityId: navigationEntry.entityId,
|
|
232
238
|
copy: false,
|
|
233
239
|
width: navigationEntry.parentCollection?.sideDialogWidth
|
|
@@ -249,6 +255,7 @@ export function buildSidePanelsFromUrl(path: string, collections: EntityCollecti
|
|
|
249
255
|
if (newFlag) {
|
|
250
256
|
sidePanel = {
|
|
251
257
|
path: lastCollectionPath,
|
|
258
|
+
// fullIdPath: lastCollectionPath,
|
|
252
259
|
copy: false
|
|
253
260
|
}
|
|
254
261
|
}
|
|
@@ -260,23 +267,22 @@ const propsToSidePanel = (props: EntitySidePanelProps,
|
|
|
260
267
|
buildUrlCollectionPath: (path: string) => string,
|
|
261
268
|
resolveIdsFrom: (pathWithAliases: string) => string,
|
|
262
269
|
smallLayout: boolean,
|
|
263
|
-
customizationController: CustomizationController
|
|
270
|
+
customizationController: CustomizationController,
|
|
271
|
+
authController: AuthController
|
|
272
|
+
): SideDialogPanelProps => {
|
|
264
273
|
|
|
265
274
|
const collectionPath = removeInitialAndTrailingSlashes(props.path);
|
|
266
275
|
|
|
267
276
|
const newPath = props.entityId
|
|
268
277
|
? buildUrlCollectionPath(`${collectionPath}/${props.entityId}${props.selectedTab ? "/" + props.selectedTab : ""}#${SIDE_URL_HASH}`)
|
|
269
278
|
: buildUrlCollectionPath(`${collectionPath}#${NEW_URL_HASH}`);
|
|
270
|
-
const resolvedPath = resolveIdsFrom(props.path);
|
|
271
279
|
|
|
272
280
|
const resolvedPanelProps: EntitySidePanelProps<any> = {
|
|
273
281
|
...props,
|
|
274
|
-
path: resolvedPath,
|
|
275
282
|
formProps: props.formProps
|
|
276
283
|
};
|
|
277
284
|
|
|
278
|
-
const entityViewWidth = getEntityViewWidth(props, smallLayout, customizationController);
|
|
279
|
-
|
|
285
|
+
const entityViewWidth = getEntityViewWidth(props, smallLayout, customizationController, authController);
|
|
280
286
|
return {
|
|
281
287
|
key: `${props.path}/${props.entityId}`,
|
|
282
288
|
component: <EntitySidePanel {...resolvedPanelProps}/>,
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
import { resolveProperty } from "../util";
|
|
14
14
|
|
|
15
15
|
import { PropertyPreviewProps } from "./PropertyPreviewProps";
|
|
16
|
-
import { useCustomizationController } from "../hooks";
|
|
16
|
+
import { useAuthController, useCustomizationController } from "../hooks";
|
|
17
17
|
import { EmptyValue } from "./components/EmptyValue";
|
|
18
18
|
import { UrlComponentPreview } from "./components/UrlComponentPreview";
|
|
19
19
|
import { StorageThumbnail } from "./components/StorageThumbnail";
|
|
@@ -37,6 +37,7 @@ import { ErrorView } from "../components";
|
|
|
37
37
|
*/
|
|
38
38
|
export const PropertyPreview = React.memo(function PropertyPreview<T extends CMSType>(props: PropertyPreviewProps<T>) {
|
|
39
39
|
|
|
40
|
+
const authController = useAuthController();
|
|
40
41
|
const customizationController = useCustomizationController();
|
|
41
42
|
|
|
42
43
|
let content: React.ReactNode | any;
|
|
@@ -53,7 +54,8 @@ export const PropertyPreview = React.memo(function PropertyPreview<T extends CMS
|
|
|
53
54
|
const property = resolveProperty({
|
|
54
55
|
propertyKey,
|
|
55
56
|
propertyOrBuilder: inputProperty,
|
|
56
|
-
propertyConfigs: customizationController.propertyConfigs
|
|
57
|
+
propertyConfigs: customizationController.propertyConfigs,
|
|
58
|
+
authController
|
|
57
59
|
});
|
|
58
60
|
|
|
59
61
|
if (property === null) {
|
|
@@ -62,7 +62,7 @@ export function ImagePreview({
|
|
|
62
62
|
title="Copy url to clipboard" side={"bottom"}>
|
|
63
63
|
<IconButton
|
|
64
64
|
variant={"filled"}
|
|
65
|
-
size={"
|
|
65
|
+
size={"smallest"}
|
|
66
66
|
onClick={(e) => {
|
|
67
67
|
e.stopPropagation();
|
|
68
68
|
e.preventDefault();
|
|
@@ -81,7 +81,7 @@ export function ImagePreview({
|
|
|
81
81
|
href={url}
|
|
82
82
|
rel="noopener noreferrer"
|
|
83
83
|
target="_blank"
|
|
84
|
-
size={"
|
|
84
|
+
size={"smallest"}
|
|
85
85
|
onClick={(e: any) => e.stopPropagation()}
|
|
86
86
|
>
|
|
87
87
|
<OpenInNewIcon className={"text-surface-700 dark:text-surface-300"}
|
|
@@ -141,7 +141,7 @@ function ReferencePreviewExisting<M extends Record<string, any> = any>({
|
|
|
141
141
|
);
|
|
142
142
|
}
|
|
143
143
|
return <EntityPreview size={size}
|
|
144
|
-
|
|
144
|
+
previewKeys={previewProperties}
|
|
145
145
|
disabled={disabled}
|
|
146
146
|
entity={usedEntity}
|
|
147
147
|
collection={collection}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { ErrorBoundary } from "../../components";
|
|
3
|
-
import { useCustomizationController } from "../../hooks";
|
|
3
|
+
import { useAuthController, useCustomizationController } from "../../hooks";
|
|
4
4
|
import { PropertyPreviewProps } from "../PropertyPreviewProps";
|
|
5
5
|
import { PropertyPreview } from "../PropertyPreview";
|
|
6
6
|
import { resolveArrayProperty } from "../../util";
|
|
@@ -15,12 +15,13 @@ export function ArrayOfMapsPreview({
|
|
|
15
15
|
size,
|
|
16
16
|
// entity
|
|
17
17
|
}: PropertyPreviewProps<Record<string, any>[]>) {
|
|
18
|
-
|
|
18
|
+
const authController = useAuthController();
|
|
19
19
|
const customizationController = useCustomizationController();
|
|
20
20
|
const property = resolveArrayProperty({
|
|
21
21
|
propertyKey,
|
|
22
22
|
property: inputProperty,
|
|
23
|
-
propertyConfigs: customizationController.propertyConfigs
|
|
23
|
+
propertyConfigs: customizationController.propertyConfigs,
|
|
24
|
+
authController
|
|
24
25
|
});
|
|
25
26
|
|
|
26
27
|
if (Array.isArray(property?.of)) {
|
|
@@ -36,7 +37,7 @@ export function ArrayOfMapsPreview({
|
|
|
36
37
|
throw Error(`You need to specify a 'properties' prop (or specify a custom field) in your map property ${propertyKey}`);
|
|
37
38
|
}
|
|
38
39
|
const values = value;
|
|
39
|
-
const previewProperties: string[] | undefined = mapProperty.
|
|
40
|
+
const previewProperties: string[] | undefined = mapProperty.previewKeys;
|
|
40
41
|
|
|
41
42
|
if (!values) return null;
|
|
42
43
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ResolvedReferenceProperty } from "../../types";
|
|
2
2
|
import { resolveArrayProperty } from "../../util";
|
|
3
|
-
import { useCustomizationController } from "../../hooks";
|
|
3
|
+
import { useAuthController, useCustomizationController } from "../../hooks";
|
|
4
4
|
import { PreviewSize, PropertyPreviewProps } from "../PropertyPreviewProps";
|
|
5
5
|
import { ReferencePreview } from "../components/ReferencePreview";
|
|
6
6
|
|
|
@@ -13,12 +13,13 @@ export function ArrayOfReferencesPreview({
|
|
|
13
13
|
property: inputProperty,
|
|
14
14
|
size
|
|
15
15
|
}: PropertyPreviewProps<any[]>) {
|
|
16
|
-
|
|
16
|
+
const authController = useAuthController();
|
|
17
17
|
const customizationController = useCustomizationController();
|
|
18
18
|
const property = resolveArrayProperty({
|
|
19
19
|
propertyKey,
|
|
20
20
|
property: inputProperty,
|
|
21
|
-
propertyConfigs: customizationController.propertyConfigs
|
|
21
|
+
propertyConfigs: customizationController.propertyConfigs,
|
|
22
|
+
authController
|
|
22
23
|
});
|
|
23
24
|
|
|
24
25
|
if (Array.isArray(property?.of)) {
|
|
@@ -3,7 +3,7 @@ import React from "react";
|
|
|
3
3
|
import { resolveArrayProperty } from "../../util";
|
|
4
4
|
import { ResolvedProperty } from "../../types";
|
|
5
5
|
|
|
6
|
-
import { useCustomizationController } from "../../hooks";
|
|
6
|
+
import { useAuthController, useCustomizationController } from "../../hooks";
|
|
7
7
|
import { PreviewSize, PropertyPreviewProps } from "../PropertyPreviewProps";
|
|
8
8
|
import { PropertyPreview } from "../PropertyPreview";
|
|
9
9
|
import { ErrorBoundary } from "../../components";
|
|
@@ -19,11 +19,13 @@ export function ArrayOfStorageComponentsPreview({
|
|
|
19
19
|
size
|
|
20
20
|
}: PropertyPreviewProps<any[]>) {
|
|
21
21
|
|
|
22
|
+
const authController = useAuthController();
|
|
22
23
|
const customizationController = useCustomizationController();
|
|
23
24
|
const property = resolveArrayProperty({
|
|
24
25
|
propertyKey,
|
|
25
26
|
property: inputProperty,
|
|
26
|
-
propertyConfigs: customizationController.propertyConfigs
|
|
27
|
+
propertyConfigs: customizationController.propertyConfigs,
|
|
28
|
+
authController
|
|
27
29
|
});
|
|
28
30
|
|
|
29
31
|
if (Array.isArray(property.of)) {
|
|
@@ -3,7 +3,7 @@ import { ResolvedStringProperty } from "../../types";
|
|
|
3
3
|
|
|
4
4
|
import { resolveArrayProperty } from "../../util";
|
|
5
5
|
import { PropertyPreviewProps, StringPropertyPreview } from "../../preview";
|
|
6
|
-
import { useCustomizationController } from "../../hooks";
|
|
6
|
+
import { useAuthController, useCustomizationController } from "../../hooks";
|
|
7
7
|
import { ErrorBoundary } from "../../components";
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -16,12 +16,13 @@ export function ArrayOfStringsPreview({
|
|
|
16
16
|
// entity,
|
|
17
17
|
size
|
|
18
18
|
}: PropertyPreviewProps<string[]>) {
|
|
19
|
-
|
|
19
|
+
const authController = useAuthController();
|
|
20
20
|
const customizationController = useCustomizationController();
|
|
21
21
|
const property = resolveArrayProperty({
|
|
22
22
|
propertyKey,
|
|
23
23
|
property: inputProperty,
|
|
24
|
-
propertyConfigs: customizationController.propertyConfigs
|
|
24
|
+
propertyConfigs: customizationController.propertyConfigs,
|
|
25
|
+
authController
|
|
25
26
|
});
|
|
26
27
|
|
|
27
28
|
if (Array.isArray(property.of)) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { resolveArrayProperty } from "../../util";
|
|
3
3
|
import { ResolvedProperty } from "../../types";
|
|
4
|
-
import { useCustomizationController } from "../../hooks";
|
|
4
|
+
import { useAuthController, useCustomizationController } from "../../hooks";
|
|
5
5
|
import { PreviewSize, PropertyPreviewProps } from "../PropertyPreviewProps";
|
|
6
6
|
import { PropertyPreview } from "../PropertyPreview";
|
|
7
7
|
import { cls, defaultBorderMixin } from "@firecms/ui";
|
|
@@ -19,11 +19,13 @@ export function ArrayOneOfPreview({
|
|
|
19
19
|
// entity
|
|
20
20
|
}: PropertyPreviewProps<any[]>) {
|
|
21
21
|
|
|
22
|
+
const authController = useAuthController();
|
|
22
23
|
const customizationController = useCustomizationController();
|
|
23
24
|
const property = resolveArrayProperty({
|
|
24
25
|
propertyKey,
|
|
25
26
|
property: inputProperty,
|
|
26
|
-
propertyConfigs: customizationController.propertyConfigs
|
|
27
|
+
propertyConfigs: customizationController.propertyConfigs,
|
|
28
|
+
authController
|
|
27
29
|
});
|
|
28
30
|
|
|
29
31
|
if (property?.dataType !== "array")
|
|
@@ -2,7 +2,7 @@ import React from "react";
|
|
|
2
2
|
|
|
3
3
|
import { resolveArrayProperty } from "../../util";
|
|
4
4
|
import { ResolvedProperty } from "../../types";
|
|
5
|
-
import { useCustomizationController } from "../../hooks";
|
|
5
|
+
import { useAuthController, useCustomizationController } from "../../hooks";
|
|
6
6
|
import { PreviewSize, PropertyPreviewProps } from "../PropertyPreviewProps";
|
|
7
7
|
import { PropertyPreview } from "../PropertyPreview";
|
|
8
8
|
import { cls, defaultBorderMixin } from "@firecms/ui";
|
|
@@ -19,11 +19,13 @@ export function ArrayPropertyPreview({
|
|
|
19
19
|
size
|
|
20
20
|
}: PropertyPreviewProps<any[]>) {
|
|
21
21
|
|
|
22
|
+
const authController = useAuthController();
|
|
22
23
|
const customizationController = useCustomizationController();
|
|
23
24
|
const property = resolveArrayProperty({
|
|
24
25
|
propertyKey,
|
|
25
26
|
property: inputProperty,
|
|
26
|
-
propertyConfigs: customizationController.propertyConfigs
|
|
27
|
+
propertyConfigs: customizationController.propertyConfigs,
|
|
28
|
+
authController
|
|
27
29
|
});
|
|
28
30
|
|
|
29
31
|
if (!property.of) {
|
|
@@ -128,7 +128,7 @@ export function KeyValuePreview({ value }: { value: any }) {
|
|
|
128
128
|
</div>
|
|
129
129
|
<div
|
|
130
130
|
className="flex-grow max-w-[75%]">
|
|
131
|
-
{childValue && <Typography>
|
|
131
|
+
{childValue && typeof childValue !== "object" && <Typography>
|
|
132
132
|
<ErrorBoundary>
|
|
133
133
|
{childValue.toString()}
|
|
134
134
|
</ErrorBoundary>
|
|
@@ -46,7 +46,7 @@ export function SkeletonPropertyComponent({
|
|
|
46
46
|
content = <>{arrayProperty.of.map((p, i) => renderGenericArrayCell(p, i))} </>;
|
|
47
47
|
} else {
|
|
48
48
|
if (arrayProperty.of.dataType === "map" && arrayProperty.of.properties) {
|
|
49
|
-
content = renderArrayOfMaps(arrayProperty.of.properties, size, arrayProperty.of.
|
|
49
|
+
content = renderArrayOfMaps(arrayProperty.of.properties, size, arrayProperty.of.previewKeys);
|
|
50
50
|
} else if (arrayProperty.of.dataType === "string") {
|
|
51
51
|
if (arrayProperty.of.enumValues) {
|
|
52
52
|
content = renderArrayEnumTableCell();
|
|
@@ -45,7 +45,7 @@ export function StringPropertyPreview({
|
|
|
45
45
|
if (!value) return <></>;
|
|
46
46
|
const lines = value.split("\n");
|
|
47
47
|
return value && value.includes("\n")
|
|
48
|
-
? <div className={cls("overflow-x-scroll", size === "small" ? "text-sm" : "")}>
|
|
48
|
+
? <div className={cls("overflow-x-scroll overflow-hidden", size === "small" ? "text-sm" : "")}>
|
|
49
49
|
{lines.map((str, index) =>
|
|
50
50
|
<React.Fragment key={`string_preview_${index}`}>
|
|
51
51
|
<span>{str}</span>
|