@firecms/core 3.0.0-beta.10 → 3.0.0-beta.12
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/ArrayContainer.d.ts +22 -6
- package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +2 -1
- package/dist/components/EntityCollectionTable/EntityCollectionTable.d.ts +2 -2
- package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +17 -3
- package/dist/components/EntityCollectionTable/index.d.ts +1 -1
- package/dist/components/EntityCollectionTable/internal/popup_field/PopupFormField.d.ts +6 -3
- package/dist/components/EntityCollectionView/EntityCollectionView.d.ts +4 -0
- package/dist/components/PropertyIdCopyTooltip.d.ts +1 -1
- package/dist/components/SelectableTable/SelectableTable.d.ts +12 -2
- package/dist/components/SelectableTable/filters/ReferenceFilterField.d.ts +1 -1
- package/dist/components/UnsavedChangesDialog.d.ts +8 -0
- package/dist/components/VirtualTable/VirtualTableProps.d.ts +13 -0
- package/dist/components/common/default_entity_actions.d.ts +0 -2
- package/dist/components/common/index.d.ts +1 -1
- package/dist/components/common/useColumnsIds.d.ts +1 -0
- package/dist/components/common/{useDataSourceEntityCollectionTableController.d.ts → useDataSourceTableController.d.ts} +10 -2
- package/dist/components/common/useDebouncedCallback.d.ts +1 -0
- package/dist/components/common/useScrollRestoration.d.ts +14 -0
- package/dist/contexts/BreacrumbsContext.d.ts +8 -0
- package/dist/core/EntityEditView.d.ts +30 -22
- package/dist/core/EntityEditViewFormActions.d.ts +2 -0
- package/dist/core/FireCMS.d.ts +1 -1
- package/dist/core/FireCMSRouter.d.ts +4 -0
- package/dist/core/NavigationRoutes.d.ts +0 -1
- package/dist/core/SideDialogs.d.ts +4 -2
- package/dist/core/index.d.ts +2 -1
- package/dist/form/EntityForm.d.ts +45 -0
- package/dist/form/EntityFormActions.d.ts +17 -0
- package/dist/form/PropertyFieldBinding.d.ts +1 -1
- package/dist/form/components/FormEntry.d.ts +6 -0
- package/dist/form/components/FormLayout.d.ts +5 -0
- package/dist/form/components/index.d.ts +2 -1
- package/dist/form/field_bindings/ArrayCustomShapedFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/ArrayOfReferencesFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/BlockFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/MarkdownEditorFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/ReferenceFieldBinding.d.ts +2 -2
- package/dist/form/field_bindings/RepeatFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/SwitchFieldBinding.d.ts +1 -2
- package/dist/form/index.d.ts +16 -16
- package/dist/hooks/data/delete.d.ts +4 -4
- package/dist/hooks/data/save.d.ts +3 -3
- package/dist/hooks/data/useCollectionFetch.d.ts +1 -1
- package/dist/hooks/data/useEntityFetch.d.ts +4 -3
- package/dist/hooks/useAuthController.d.ts +1 -1
- package/dist/hooks/useBreadcrumbsController.d.ts +26 -0
- package/dist/hooks/useBuildNavigationController.d.ts +7 -4
- package/dist/hooks/useFireCMSContext.d.ts +1 -1
- package/dist/hooks/useModeController.d.ts +1 -2
- package/dist/hooks/useResolvedNavigationFrom.d.ts +3 -3
- package/dist/hooks/useValidateAuthenticator.d.ts +3 -3
- package/dist/index.es.js +17032 -12909
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +17019 -12898
- package/dist/index.umd.js.map +1 -1
- package/dist/internal/useBuildSideEntityController.d.ts +2 -2
- package/dist/internal/useUnsavedChangesDialog.d.ts +7 -9
- package/dist/preview/PropertyPreviewProps.d.ts +1 -1
- package/dist/preview/components/EnumValuesChip.d.ts +1 -1
- package/dist/preview/util.d.ts +3 -3
- package/dist/routes/CustomCMSRoute.d.ts +4 -0
- package/dist/routes/FireCMSRoute.d.ts +1 -0
- package/dist/routes/HomePageRoute.d.ts +3 -0
- package/dist/types/auth.d.ts +7 -9
- package/dist/types/collections.d.ts +44 -23
- package/dist/types/datasource.d.ts +2 -6
- package/dist/types/dialogs_controller.d.ts +7 -3
- package/dist/types/entities.d.ts +1 -1
- package/dist/types/entity_actions.d.ts +14 -4
- package/dist/types/entity_callbacks.d.ts +16 -16
- package/dist/types/export_import.d.ts +4 -4
- package/dist/types/fields.d.ts +27 -4
- package/dist/types/firecms.d.ts +2 -2
- package/dist/types/firecms_context.d.ts +1 -1
- package/dist/types/navigation.d.ts +29 -12
- package/dist/types/permissions.d.ts +4 -4
- package/dist/types/plugins.d.ts +9 -8
- package/dist/types/properties.d.ts +18 -3
- package/dist/types/property_config.d.ts +0 -2
- package/dist/types/side_entity_controller.d.ts +6 -1
- package/dist/types/user.d.ts +1 -0
- package/dist/util/builders.d.ts +3 -3
- package/dist/util/entities.d.ts +1 -1
- package/dist/util/entity_actions.d.ts +2 -0
- package/dist/util/entity_cache.d.ts +23 -0
- package/dist/util/icon_synonyms.d.ts +0 -1
- package/dist/util/icons.d.ts +3 -1
- package/dist/util/index.d.ts +1 -0
- package/dist/util/navigation_from_path.d.ts +6 -1
- package/dist/util/navigation_utils.d.ts +12 -1
- package/dist/util/objects.d.ts +1 -0
- package/dist/util/permissions.d.ts +4 -4
- package/dist/util/property_utils.d.ts +2 -2
- package/dist/util/resolutions.d.ts +12 -7
- package/package.json +129 -125
- package/src/app/Scaffold.tsx +4 -4
- package/src/components/ArrayContainer.tsx +115 -34
- package/src/components/CircularProgressCenter.tsx +1 -1
- package/src/components/ConfirmationDialog.tsx +2 -2
- package/src/components/DeleteEntityDialog.tsx +10 -19
- package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +44 -20
- package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +23 -17
- package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +20 -3
- package/src/components/EntityCollectionTable/PropertyTableCell.tsx +6 -4
- package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +8 -9
- package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +5 -11
- package/src/components/EntityCollectionTable/index.tsx +1 -1
- package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +3 -3
- package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +5 -5
- package/src/components/EntityCollectionTable/internal/EntityTableCellActions.tsx +2 -2
- package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +77 -73
- package/src/components/EntityCollectionView/EntityCollectionView.tsx +90 -49
- package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +4 -2
- package/src/components/EntityCollectionView/useSelectionController.tsx +5 -4
- package/src/components/EntityPreview.tsx +39 -30
- package/src/components/EntityView.tsx +5 -5
- package/src/components/ErrorView.tsx +3 -3
- package/src/components/HomePage/DefaultHomePage.tsx +1 -0
- package/src/components/HomePage/FavouritesView.tsx +6 -11
- package/src/components/HomePage/NavigationCard.tsx +1 -1
- package/src/components/HomePage/NavigationCardBinding.tsx +4 -9
- package/src/components/HomePage/NavigationGroup.tsx +1 -1
- package/src/components/NotFoundPage.tsx +2 -2
- package/src/components/PropertyConfigBadge.tsx +1 -1
- package/src/components/PropertyIdCopyTooltip.tsx +3 -4
- package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +13 -8
- package/src/components/SelectableTable/SelectableTable.tsx +20 -5
- package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +4 -2
- package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +10 -8
- package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +7 -5
- package/src/components/UnsavedChangesDialog.tsx +42 -0
- package/src/components/VirtualTable/VirtualTable.tsx +19 -2
- package/src/components/VirtualTable/VirtualTableHeader.tsx +8 -8
- package/src/components/VirtualTable/VirtualTableHeaderRow.tsx +1 -1
- package/src/components/VirtualTable/VirtualTableProps.tsx +15 -0
- package/src/components/VirtualTable/VirtualTableRow.tsx +1 -1
- package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +1 -1
- package/src/components/VirtualTable/fields/VirtualTableInput.tsx +1 -1
- package/src/components/VirtualTable/fields/VirtualTableSelect.tsx +2 -0
- package/src/components/common/default_entity_actions.tsx +26 -37
- package/src/components/common/index.ts +1 -1
- package/src/components/common/useColumnsIds.tsx +1 -1
- package/src/components/common/useDataSourceTableController.tsx +420 -0
- package/src/components/common/useDebouncedCallback.tsx +20 -0
- package/src/components/common/useScrollRestoration.tsx +68 -0
- package/src/contexts/BreacrumbsContext.tsx +38 -0
- package/src/contexts/DialogsProvider.tsx +3 -2
- package/src/contexts/ModeController.tsx +1 -3
- package/src/contexts/SnackbarProvider.tsx +2 -0
- package/src/core/DefaultAppBar.tsx +56 -25
- package/src/core/DefaultDrawer.tsx +11 -9
- package/src/core/DrawerNavigationItem.tsx +4 -4
- package/src/core/EntityEditView.tsx +282 -1006
- package/src/core/EntityEditViewFormActions.tsx +199 -0
- package/src/core/EntitySidePanel.tsx +85 -15
- package/src/core/FireCMS.tsx +12 -9
- package/src/core/FireCMSRouter.tsx +17 -0
- package/src/core/NavigationRoutes.tsx +23 -32
- package/src/core/SideDialogs.tsx +21 -12
- package/src/core/field_configs.tsx +4 -4
- package/src/core/index.tsx +4 -2
- package/src/form/EntityForm.tsx +774 -0
- package/src/form/EntityFormActions.tsx +169 -0
- package/src/form/PropertyFieldBinding.tsx +39 -30
- package/src/form/components/CustomIdField.tsx +2 -0
- package/src/form/components/FormEntry.tsx +22 -0
- package/src/form/components/FormLayout.tsx +16 -0
- package/src/form/components/LabelWithIcon.tsx +6 -3
- package/src/form/components/StorageItemPreview.tsx +3 -3
- package/src/form/components/StorageUploadProgress.tsx +1 -1
- package/src/form/components/index.tsx +2 -1
- package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +7 -6
- package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +20 -12
- package/src/form/field_bindings/BlockFieldBinding.tsx +45 -25
- package/src/form/field_bindings/DateTimeFieldBinding.tsx +2 -1
- package/src/form/field_bindings/KeyValueFieldBinding.tsx +10 -7
- package/src/form/field_bindings/MapFieldBinding.tsx +69 -52
- package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +9 -6
- package/src/form/field_bindings/MultiSelectFieldBinding.tsx +1 -1
- package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +2 -2
- package/src/form/field_bindings/ReferenceFieldBinding.tsx +5 -5
- package/src/form/field_bindings/RepeatFieldBinding.tsx +30 -22
- package/src/form/field_bindings/SelectFieldBinding.tsx +6 -5
- package/src/form/field_bindings/StorageUploadFieldBinding.tsx +7 -5
- package/src/form/field_bindings/SwitchFieldBinding.tsx +26 -25
- package/src/form/field_bindings/TextFieldBinding.tsx +4 -3
- package/src/form/index.tsx +16 -32
- package/src/form/validation.ts +12 -6
- package/src/hooks/data/delete.ts +4 -4
- package/src/hooks/data/save.ts +8 -9
- package/src/hooks/data/useCollectionFetch.tsx +3 -3
- package/src/hooks/data/useEntityFetch.tsx +10 -6
- package/src/hooks/useAuthController.tsx +1 -1
- package/src/hooks/useBreadcrumbsController.tsx +31 -0
- package/src/hooks/useBuildModeController.tsx +15 -28
- package/src/hooks/useBuildNavigationController.tsx +74 -29
- package/src/hooks/useFireCMSContext.tsx +5 -5
- package/src/hooks/useLargeLayout.tsx +0 -35
- package/src/hooks/useModeController.tsx +1 -2
- package/src/hooks/useResolvedNavigationFrom.tsx +9 -11
- package/src/hooks/useValidateAuthenticator.tsx +3 -3
- package/src/internal/useBuildDataSource.ts +1 -1
- package/src/internal/useBuildSideDialogsController.tsx +3 -2
- package/src/internal/useBuildSideEntityController.tsx +124 -83
- package/src/internal/useUnsavedChangesDialog.tsx +127 -93
- package/src/preview/PropertyPreview.tsx +11 -11
- package/src/preview/PropertyPreviewProps.tsx +1 -1
- package/src/preview/components/BooleanPreview.tsx +1 -1
- package/src/preview/components/EmptyValue.tsx +1 -1
- package/src/preview/components/EnumValuesChip.tsx +1 -1
- package/src/preview/components/ImagePreview.tsx +5 -6
- package/src/preview/components/UrlComponentPreview.tsx +20 -21
- package/src/preview/property_previews/ArrayOfMapsPreview.tsx +1 -1
- package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +2 -2
- package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +2 -2
- package/src/preview/property_previews/ArrayOfStringsPreview.tsx +1 -1
- package/src/preview/property_previews/ArrayOneOfPreview.tsx +2 -2
- package/src/preview/property_previews/ArrayPropertyPreview.tsx +2 -2
- package/src/preview/property_previews/MapPropertyPreview.tsx +7 -6
- package/src/preview/property_previews/SkeletonPropertyComponent.tsx +12 -12
- package/src/preview/property_previews/StringPropertyPreview.tsx +2 -2
- package/src/preview/util.ts +10 -10
- package/src/routes/CustomCMSRoute.tsx +21 -0
- package/src/routes/FireCMSRoute.tsx +235 -0
- package/src/routes/HomePageRoute.tsx +17 -0
- package/src/types/auth.tsx +8 -12
- package/src/types/collections.ts +52 -26
- package/src/types/datasource.ts +2 -6
- package/src/types/dialogs_controller.tsx +7 -3
- package/src/types/entities.ts +1 -1
- package/src/types/entity_actions.tsx +16 -4
- package/src/types/entity_callbacks.ts +18 -18
- package/src/types/export_import.ts +4 -4
- package/src/types/fields.tsx +33 -4
- package/src/types/firecms.tsx +2 -2
- package/src/types/firecms_context.tsx +1 -1
- package/src/types/navigation.ts +36 -16
- package/src/types/permissions.ts +5 -5
- package/src/types/plugins.tsx +9 -8
- package/src/types/properties.ts +21 -3
- package/src/types/property_config.tsx +0 -2
- package/src/types/side_dialogs_controller.tsx +2 -0
- package/src/types/side_entity_controller.tsx +6 -1
- package/src/types/user.ts +2 -0
- package/src/util/builders.ts +10 -8
- package/src/util/entities.ts +3 -1
- package/src/util/entity_actions.ts +28 -0
- package/src/util/entity_cache.ts +204 -0
- package/src/util/icon_list.ts +1 -0
- package/src/util/icon_synonyms.ts +0 -1
- package/src/util/icons.tsx +12 -8
- package/src/util/index.ts +1 -0
- package/src/util/join_collections.ts +3 -0
- package/src/util/navigation_from_path.ts +13 -6
- package/src/util/navigation_utils.ts +53 -1
- package/src/util/objects.ts +24 -1
- package/src/util/parent_references_from_path.ts +3 -3
- package/src/util/permissions.ts +8 -8
- package/src/util/property_utils.tsx +10 -3
- package/src/util/references.ts +8 -2
- package/src/util/resolutions.ts +34 -13
- package/src/util/useStorageUploadController.tsx +40 -22
- package/dist/form/components/FormikArrayContainer.d.ts +0 -19
- package/src/components/common/useDataSourceEntityCollectionTableController.tsx +0 -236
- package/src/form/components/FormikArrayContainer.tsx +0 -47
- /package/src/util/{common.tsx → common.ts} +0 -0
package/src/util/index.ts
CHANGED
|
@@ -7,6 +7,7 @@ export * from "./objects";
|
|
|
7
7
|
export * from "./paths";
|
|
8
8
|
export * from "./regexp";
|
|
9
9
|
export * from "./navigation_utils";
|
|
10
|
+
export * from "./entity_actions";
|
|
10
11
|
export * from "./useDebouncedCallback";
|
|
11
12
|
export * from "./property_utils";
|
|
12
13
|
export * from "./resolutions";
|
|
@@ -11,22 +11,27 @@ export interface NavigationViewEntityInternal<M extends Record<string, any>> {
|
|
|
11
11
|
type: "entity";
|
|
12
12
|
entityId: string;
|
|
13
13
|
path: string;
|
|
14
|
+
fullPath: string;
|
|
14
15
|
parentCollection: EntityCollection<M>;
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
export interface NavigationViewCollectionInternal<M extends Record<string, any>> {
|
|
18
19
|
type: "collection";
|
|
20
|
+
id: string;
|
|
19
21
|
path: string;
|
|
22
|
+
fullPath: string;
|
|
20
23
|
collection: EntityCollection<M>;
|
|
21
24
|
}
|
|
22
25
|
|
|
23
26
|
export interface NavigationViewEntityCustomInternal<M extends Record<string, any>> {
|
|
24
27
|
type: "custom_view";
|
|
25
28
|
path: string;
|
|
29
|
+
fullPath: string;
|
|
30
|
+
entityId: string;
|
|
26
31
|
view: EntityCustomView<M>;
|
|
27
32
|
}
|
|
28
33
|
|
|
29
|
-
export function
|
|
34
|
+
export function getNavigationEntriesFromPath(props: {
|
|
30
35
|
path: string,
|
|
31
36
|
collections: EntityCollection[] | undefined,
|
|
32
37
|
currentFullPath?: string,
|
|
@@ -56,7 +61,9 @@ export function getNavigationEntriesFromPathInternal(props: {
|
|
|
56
61
|
|
|
57
62
|
result.push({
|
|
58
63
|
type: "collection",
|
|
64
|
+
id: collection.id,
|
|
59
65
|
path: collectionPath,
|
|
66
|
+
fullPath: collectionPath,
|
|
60
67
|
collection
|
|
61
68
|
});
|
|
62
69
|
const restOfThePath = removeInitialAndTrailingSlashes(removeInitialAndTrailingSlashes(path).replace(subpathCombination, ""));
|
|
@@ -68,6 +75,7 @@ export function getNavigationEntriesFromPathInternal(props: {
|
|
|
68
75
|
type: "entity",
|
|
69
76
|
entityId,
|
|
70
77
|
path: collectionPath,
|
|
78
|
+
fullPath: fullPath,
|
|
71
79
|
parentCollection: collection
|
|
72
80
|
});
|
|
73
81
|
if (nextSegments.length > 1) {
|
|
@@ -81,16 +89,15 @@ export function getNavigationEntriesFromPathInternal(props: {
|
|
|
81
89
|
.filter(Boolean)
|
|
82
90
|
.find((entry) => entry!.key === newPath);
|
|
83
91
|
if (customView) {
|
|
84
|
-
const path = currentFullPath && currentFullPath.length > 0
|
|
85
|
-
? (currentFullPath + "/" + customView.key)
|
|
86
|
-
: customView.key;
|
|
87
92
|
result.push({
|
|
88
93
|
type: "custom_view",
|
|
89
|
-
path,
|
|
94
|
+
path: collectionPath,
|
|
95
|
+
entityId: entityId,
|
|
96
|
+
fullPath: fullPath + "/" + customView.key,
|
|
90
97
|
view: customView
|
|
91
98
|
});
|
|
92
99
|
} else if (collection.subcollections) {
|
|
93
|
-
result.push(...
|
|
100
|
+
result.push(...getNavigationEntriesFromPath({
|
|
94
101
|
path: newPath,
|
|
95
102
|
collections: collection.subcollections,
|
|
96
103
|
currentFullPath: fullPath,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EntityCollection } from "../types";
|
|
1
|
+
import { EntityCollection, NavigationController, SideEntityController } from "../types";
|
|
2
2
|
|
|
3
3
|
export function removeInitialAndTrailingSlashes(s: string): string {
|
|
4
4
|
return removeInitialSlash(removeTrailingSlash(s));
|
|
@@ -109,3 +109,55 @@ export function getCollectionPathsCombinations(subpaths: string[]): string[] {
|
|
|
109
109
|
return result;
|
|
110
110
|
|
|
111
111
|
}
|
|
112
|
+
|
|
113
|
+
export function navigateToEntity({
|
|
114
|
+
openEntityMode,
|
|
115
|
+
collection,
|
|
116
|
+
entityId,
|
|
117
|
+
copy,
|
|
118
|
+
path,
|
|
119
|
+
selectedTab,
|
|
120
|
+
sideEntityController,
|
|
121
|
+
onClose,
|
|
122
|
+
navigation
|
|
123
|
+
}:
|
|
124
|
+
|
|
125
|
+
{
|
|
126
|
+
openEntityMode: "side_panel" | "full_screen";
|
|
127
|
+
collection?: EntityCollection;
|
|
128
|
+
entityId?: string;
|
|
129
|
+
selectedTab?: string;
|
|
130
|
+
copy?: boolean;
|
|
131
|
+
path: string;
|
|
132
|
+
sideEntityController: SideEntityController;
|
|
133
|
+
onClose?: () => void;
|
|
134
|
+
navigation: NavigationController
|
|
135
|
+
}) {
|
|
136
|
+
|
|
137
|
+
if (openEntityMode === "side_panel") {
|
|
138
|
+
|
|
139
|
+
sideEntityController.open({
|
|
140
|
+
entityId,
|
|
141
|
+
path,
|
|
142
|
+
copy,
|
|
143
|
+
selectedTab,
|
|
144
|
+
collection,
|
|
145
|
+
updateUrl: true,
|
|
146
|
+
onClose
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
} else {
|
|
150
|
+
let to = navigation.buildUrlCollectionPath(entityId ? `${path}/${entityId}` : path);
|
|
151
|
+
if (entityId && selectedTab) {
|
|
152
|
+
to += `/${selectedTab}`;
|
|
153
|
+
}
|
|
154
|
+
if (!entityId) {
|
|
155
|
+
to += "#new";
|
|
156
|
+
}
|
|
157
|
+
if (copy) {
|
|
158
|
+
to += "#copy";
|
|
159
|
+
}
|
|
160
|
+
navigation.navigate(to);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
}
|
package/src/util/objects.ts
CHANGED
|
@@ -18,7 +18,10 @@ export function mergeDeep<T extends Record<any, any>, U extends Record<any, any>
|
|
|
18
18
|
if (targetIsObject && isObject(source)) {
|
|
19
19
|
Object.keys(source).forEach(key => {
|
|
20
20
|
const sourceElement = source[key];
|
|
21
|
-
if (
|
|
21
|
+
if (sourceElement instanceof Date) {
|
|
22
|
+
// Assign a new Date instance with the same time value
|
|
23
|
+
Object.assign(output, { [key]: new Date(sourceElement.getTime()) });
|
|
24
|
+
} else if (isObject(sourceElement)) {
|
|
22
25
|
if (!(key in target))
|
|
23
26
|
Object.assign(output, { [key]: sourceElement });
|
|
24
27
|
else
|
|
@@ -125,6 +128,26 @@ export function removeUndefined(value: any, removeEmptyStrings?: boolean): any {
|
|
|
125
128
|
return value;
|
|
126
129
|
}
|
|
127
130
|
|
|
131
|
+
export function removeNulls(value: any): any {
|
|
132
|
+
if (typeof value === "function") {
|
|
133
|
+
return value;
|
|
134
|
+
}
|
|
135
|
+
if (Array.isArray(value)) {
|
|
136
|
+
return value.map((v: any) => removeNulls(v));
|
|
137
|
+
}
|
|
138
|
+
if (typeof value === "object") {
|
|
139
|
+
const res: object = {};
|
|
140
|
+
if (value === null)
|
|
141
|
+
return value;
|
|
142
|
+
Object.keys(value).forEach((key) => {
|
|
143
|
+
if (value[key] !== null)
|
|
144
|
+
(res as any)[key] = removeNulls(value[key]);
|
|
145
|
+
});
|
|
146
|
+
return res;
|
|
147
|
+
}
|
|
148
|
+
return value;
|
|
149
|
+
}
|
|
150
|
+
|
|
128
151
|
export function isEmptyObject(obj: object) {
|
|
129
152
|
return obj &&
|
|
130
153
|
Object.getPrototypeOf(obj) === Object.prototype &&
|
|
@@ -22,11 +22,11 @@ export function getParentReferencesFromPath(props: {
|
|
|
22
22
|
|
|
23
23
|
const collection: EntityCollection<any> | undefined = collections && collections.find((entry) => entry.id === subpathCombination || entry.path === subpathCombination);
|
|
24
24
|
|
|
25
|
+
// If we find a collection, we add the reference and continue
|
|
25
26
|
if (collection) {
|
|
26
|
-
const pathOrAlias = collection.id ?? collection.path;
|
|
27
27
|
const collectionPath = currentFullPath && currentFullPath.length > 0
|
|
28
|
-
? (currentFullPath + "/" +
|
|
29
|
-
:
|
|
28
|
+
? (currentFullPath + "/" + collection.path)
|
|
29
|
+
: collection.path;
|
|
30
30
|
|
|
31
31
|
const restOfThePath = removeInitialAndTrailingSlashes(removeInitialAndTrailingSlashes(path).replace(subpathCombination, ""));
|
|
32
32
|
const nextSegments = restOfThePath.length > 0 ? restOfThePath.split("/") : [];
|
package/src/util/permissions.ts
CHANGED
|
@@ -8,9 +8,9 @@ const DEFAULT_PERMISSIONS = {
|
|
|
8
8
|
delete: true
|
|
9
9
|
};
|
|
10
10
|
|
|
11
|
-
export function resolvePermissions<M extends Record<string, any>,
|
|
11
|
+
export function resolvePermissions<M extends Record<string, any>, USER extends User>
|
|
12
12
|
(collection: EntityCollection<M>,
|
|
13
|
-
authController: AuthController<
|
|
13
|
+
authController: AuthController<USER>,
|
|
14
14
|
path: string,
|
|
15
15
|
entity: Entity<M> | null): Permissions | undefined {
|
|
16
16
|
|
|
@@ -34,29 +34,29 @@ export function resolvePermissions<M extends Record<string, any>, UserType exten
|
|
|
34
34
|
throw Error("New type of permission added and not mapped");
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
export function canEditEntity<M extends Record<string, any>,
|
|
37
|
+
export function canEditEntity<M extends Record<string, any>, USER extends User>
|
|
38
38
|
(
|
|
39
39
|
collection: EntityCollection<M>,
|
|
40
|
-
authController: AuthController<
|
|
40
|
+
authController: AuthController<USER>,
|
|
41
41
|
path: string,
|
|
42
42
|
entity: Entity<M> | null): boolean {
|
|
43
43
|
return resolvePermissions(collection, authController, path, entity)?.edit ?? DEFAULT_PERMISSIONS.edit;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
export function canCreateEntity<M extends Record<string, any>,
|
|
46
|
+
export function canCreateEntity<M extends Record<string, any>, USER extends User>
|
|
47
47
|
(
|
|
48
48
|
collection: EntityCollection<M>,
|
|
49
|
-
authController: AuthController<
|
|
49
|
+
authController: AuthController<USER>,
|
|
50
50
|
path: string,
|
|
51
51
|
entity: Entity<M> | null): boolean {
|
|
52
52
|
if (collection.collectionGroup) return false;
|
|
53
53
|
return resolvePermissions(collection, authController, path, entity)?.create ?? DEFAULT_PERMISSIONS.create;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
export function canDeleteEntity<M extends Record<string, any>,
|
|
56
|
+
export function canDeleteEntity<M extends Record<string, any>, USER extends User>
|
|
57
57
|
(
|
|
58
58
|
collection: EntityCollection<M>,
|
|
59
|
-
authController: AuthController<
|
|
59
|
+
authController: AuthController<USER>,
|
|
60
60
|
path: string,
|
|
61
61
|
entity: Entity<M> | null): boolean {
|
|
62
62
|
return resolvePermissions(collection, authController, path, entity)?.delete ?? DEFAULT_PERMISSIONS.delete;
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
EntityCollection,
|
|
5
|
+
PropertiesOrBuilders,
|
|
6
|
+
PropertyConfig,
|
|
7
|
+
PropertyOrBuilder,
|
|
8
|
+
ResolvedProperties,
|
|
9
|
+
ResolvedProperty
|
|
10
|
+
} from "../types";
|
|
4
11
|
import { isPropertyBuilder } from "./entities";
|
|
5
12
|
import { resolveProperty } from "./resolutions";
|
|
6
13
|
import { CircleIcon, FunctionsIcon } from "@firecms/ui";
|
|
@@ -11,7 +18,7 @@ export function isReferenceProperty(propertyOrBuilder: PropertyOrBuilder,
|
|
|
11
18
|
const resolvedProperty = resolveProperty({
|
|
12
19
|
propertyKey: "ignore", // TODO
|
|
13
20
|
propertyOrBuilder,
|
|
14
|
-
fields
|
|
21
|
+
propertyConfigs: fields
|
|
15
22
|
});
|
|
16
23
|
if (!resolvedProperty) return null;
|
|
17
24
|
if (resolvedProperty.dataType === "reference") {
|
|
@@ -63,7 +70,7 @@ export function getColorForProperty(property: PropertyOrBuilder, fields: Record<
|
|
|
63
70
|
* @param properties
|
|
64
71
|
* @param path
|
|
65
72
|
*/
|
|
66
|
-
export function getPropertyInPath<M extends Record<string, any>>(properties: PropertiesOrBuilders<M
|
|
73
|
+
export function getPropertyInPath<M extends Record<string, any>>(properties: PropertiesOrBuilders<M> | ResolvedProperties, path: string): PropertyOrBuilder<any, M> | undefined {
|
|
67
74
|
if (typeof properties === "object") {
|
|
68
75
|
if (path in properties) {
|
|
69
76
|
return properties[path];
|
package/src/util/references.ts
CHANGED
|
@@ -42,13 +42,19 @@ export function getEntityTitlePropertyKey<M extends Record<string, any>>(collect
|
|
|
42
42
|
|
|
43
43
|
export function getEntityImagePreviewPropertyKey<M extends object>(collection: ResolvedEntityCollection<M>): string | undefined {
|
|
44
44
|
|
|
45
|
-
// find first
|
|
45
|
+
// find first storage property of type image
|
|
46
46
|
for (const key in collection.properties) {
|
|
47
47
|
const property = collection.properties[key];
|
|
48
48
|
if (property.dataType === "string" && property.storage?.acceptedFiles?.includes("image/*")) {
|
|
49
49
|
return key;
|
|
50
50
|
}
|
|
51
|
-
|
|
51
|
+
}
|
|
52
|
+
// alternatively, look for the first array of images
|
|
53
|
+
for (const key in collection.properties) {
|
|
54
|
+
const property = collection.properties[key];
|
|
55
|
+
if (property.dataType === "array" && property.of?.dataType === "string" && property.of.storage?.acceptedFiles?.includes("image/*")) {
|
|
56
|
+
return key;
|
|
57
|
+
}
|
|
52
58
|
}
|
|
53
59
|
return undefined;
|
|
54
60
|
}
|
package/src/util/resolutions.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ArrayProperty,
|
|
3
3
|
CMSType,
|
|
4
|
+
CustomizationController,
|
|
4
5
|
EntityCollection,
|
|
5
6
|
EntityCustomView,
|
|
6
7
|
EntityValues,
|
|
@@ -38,7 +39,7 @@ export const resolveCollection = <M extends Record<string, any>, >
|
|
|
38
39
|
values,
|
|
39
40
|
previousValues,
|
|
40
41
|
userConfigPersistence,
|
|
41
|
-
|
|
42
|
+
propertyConfigs,
|
|
42
43
|
ignoreMissingFields = false
|
|
43
44
|
}: {
|
|
44
45
|
collection: EntityCollection<M> | ResolvedEntityCollection<M>;
|
|
@@ -47,7 +48,7 @@ export const resolveCollection = <M extends Record<string, any>, >
|
|
|
47
48
|
values?: Partial<EntityValues<M>>,
|
|
48
49
|
previousValues?: Partial<EntityValues<M>>,
|
|
49
50
|
userConfigPersistence?: UserConfigurationPersistence;
|
|
50
|
-
|
|
51
|
+
propertyConfigs?: Record<string, PropertyConfig>;
|
|
51
52
|
ignoreMissingFields?: boolean;
|
|
52
53
|
}): ResolvedEntityCollection<M> => {
|
|
53
54
|
|
|
@@ -67,7 +68,7 @@ export const resolveCollection = <M extends Record<string, any>, >
|
|
|
67
68
|
previousValues: usedPreviousValues,
|
|
68
69
|
path,
|
|
69
70
|
entityId,
|
|
70
|
-
|
|
71
|
+
propertyConfigs: propertyConfigs,
|
|
71
72
|
ignoreMissingFields
|
|
72
73
|
});
|
|
73
74
|
if (!childResolvedProperty) return {};
|
|
@@ -111,7 +112,7 @@ export function resolveProperty<T extends CMSType = CMSType, M extends Record<st
|
|
|
111
112
|
entityId?: string,
|
|
112
113
|
index?: number,
|
|
113
114
|
fromBuilder?: boolean;
|
|
114
|
-
|
|
115
|
+
propertyConfigs?: Record<string, PropertyConfig<any>>;
|
|
115
116
|
ignoreMissingFields?: boolean;
|
|
116
117
|
}): ResolvedProperty<T> | null {
|
|
117
118
|
|
|
@@ -182,7 +183,7 @@ export function resolveProperty<T extends CMSType = CMSType, M extends Record<st
|
|
|
182
183
|
}
|
|
183
184
|
|
|
184
185
|
if (resolvedProperty.propertyConfig && !isDefaultFieldConfigId(resolvedProperty.propertyConfig)) {
|
|
185
|
-
const cmsFields = props.
|
|
186
|
+
const cmsFields = props.propertyConfigs;
|
|
186
187
|
if (!cmsFields && !ignoreMissingFields) {
|
|
187
188
|
throw Error(`Trying to resolve a property with key '${resolvedProperty.propertyConfig}' that inherits from a custom property config but no custom property configs were provided. Use the property 'propertyConfigs' in your app config to provide them`);
|
|
188
189
|
}
|
|
@@ -218,11 +219,11 @@ export function resolveProperty<T extends CMSType = CMSType, M extends Record<st
|
|
|
218
219
|
}
|
|
219
220
|
|
|
220
221
|
export function getArrayResolvedProperties<M>({
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
222
|
+
propertyKey,
|
|
223
|
+
propertyValue,
|
|
224
|
+
property,
|
|
225
|
+
...props
|
|
226
|
+
}: {
|
|
226
227
|
propertyValue: any,
|
|
227
228
|
propertyKey?: string,
|
|
228
229
|
property: ArrayProperty<any> | ResolvedArrayProperty<any>,
|
|
@@ -233,7 +234,7 @@ export function getArrayResolvedProperties<M>({
|
|
|
233
234
|
entityId?: string;
|
|
234
235
|
index?: number;
|
|
235
236
|
fromBuilder?: boolean;
|
|
236
|
-
|
|
237
|
+
propertyConfigs?: Record<string, PropertyConfig>
|
|
237
238
|
}) {
|
|
238
239
|
|
|
239
240
|
const of = property.of;
|
|
@@ -263,7 +264,7 @@ export function resolveArrayProperty<T extends any[], M>({
|
|
|
263
264
|
entityId?: string,
|
|
264
265
|
index?: number,
|
|
265
266
|
fromBuilder?: boolean;
|
|
266
|
-
|
|
267
|
+
propertyConfigs?: Record<string, PropertyConfig>;
|
|
267
268
|
ignoreMissingFields?: boolean;
|
|
268
269
|
}): ResolvedArrayProperty {
|
|
269
270
|
const propertyValue = propertyKey ? getIn(props.values, propertyKey) : undefined;
|
|
@@ -370,7 +371,7 @@ export function resolveProperties<M extends Record<string, any>>({
|
|
|
370
371
|
entityId?: string,
|
|
371
372
|
index?: number,
|
|
372
373
|
fromBuilder?: boolean;
|
|
373
|
-
|
|
374
|
+
propertyConfigs?: Record<string, PropertyConfig>;
|
|
374
375
|
ignoreMissingFields?: boolean;
|
|
375
376
|
}): ResolvedProperties<M> {
|
|
376
377
|
return Object.entries<PropertyOrBuilder>(properties as Record<string, PropertyOrBuilder>)
|
|
@@ -430,3 +431,23 @@ export function resolveEntityView(entityView: string | EntityCustomView<any>, co
|
|
|
430
431
|
return entityView;
|
|
431
432
|
}
|
|
432
433
|
}
|
|
434
|
+
|
|
435
|
+
export function resolvedSelectedEntityView<M extends Record<string, any>>(
|
|
436
|
+
customViews: (string | EntityCustomView<M>)[] | undefined,
|
|
437
|
+
customizationController: CustomizationController,
|
|
438
|
+
selectedTab?: string
|
|
439
|
+
) {
|
|
440
|
+
const resolvedEntityViews = customViews ? customViews
|
|
441
|
+
.map(e => resolveEntityView(e, customizationController.entityViews))
|
|
442
|
+
.filter(Boolean) as EntityCustomView[]
|
|
443
|
+
: [];
|
|
444
|
+
|
|
445
|
+
const selectedEntityView = resolvedEntityViews.find(e => e.key === selectedTab);
|
|
446
|
+
const selectedSecondaryForm = customViews
|
|
447
|
+
&& resolvedEntityViews.filter(e => e.includeActions).find(e => e.key === selectedTab);
|
|
448
|
+
return {
|
|
449
|
+
resolvedEntityViews,
|
|
450
|
+
selectedEntityView,
|
|
451
|
+
selectedSecondaryForm
|
|
452
|
+
};
|
|
453
|
+
}
|
|
@@ -34,6 +34,7 @@ export interface StorageFieldItem {
|
|
|
34
34
|
size: PreviewSize
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
|
|
37
38
|
export function useStorageUploadController<M extends object>({
|
|
38
39
|
entityId,
|
|
39
40
|
entityValues,
|
|
@@ -45,17 +46,17 @@ export function useStorageUploadController<M extends object>({
|
|
|
45
46
|
disabled,
|
|
46
47
|
onChange
|
|
47
48
|
}:
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
49
|
+
{
|
|
50
|
+
entityId: string,
|
|
51
|
+
entityValues: EntityValues<M>,
|
|
52
|
+
value: string | string[] | null;
|
|
53
|
+
path?: string,
|
|
54
|
+
propertyKey: string,
|
|
55
|
+
property: StringProperty | ArrayProperty<string[]> | ResolvedStringProperty | ResolvedArrayProperty<string[]>,
|
|
56
|
+
storageSource: StorageSource,
|
|
57
|
+
disabled: boolean,
|
|
58
|
+
onChange: (value: string | string[] | null) => void
|
|
59
|
+
}) {
|
|
59
60
|
|
|
60
61
|
const storage: StorageConfig | undefined = property.dataType === "string"
|
|
61
62
|
? property.storage
|
|
@@ -70,21 +71,12 @@ export function useStorageUploadController<M extends object>({
|
|
|
70
71
|
throw Error("Storage meta must be specified");
|
|
71
72
|
|
|
72
73
|
const metadata: Record<string, any> | undefined = storage?.metadata;
|
|
73
|
-
const size = multipleFilesSupported ? "
|
|
74
|
+
const size = multipleFilesSupported ? "medium" : "large";
|
|
74
75
|
|
|
75
76
|
const compression: ImageCompression | undefined = storage?.imageCompression;
|
|
76
77
|
|
|
77
78
|
const internalInitialValue: StorageFieldItem[] =
|
|
78
|
-
(multipleFilesSupported
|
|
79
|
-
? (value ?? []) as string[]
|
|
80
|
-
: value ? [value as string] : []).map(entry => (
|
|
81
|
-
{
|
|
82
|
-
id: getRandomId(),
|
|
83
|
-
storagePathOrDownloadUrl: entry,
|
|
84
|
-
metadata,
|
|
85
|
-
size
|
|
86
|
-
}
|
|
87
|
-
));
|
|
79
|
+
getInternalInitialValue(multipleFilesSupported, value, metadata, size);
|
|
88
80
|
|
|
89
81
|
const [initialValue, setInitialValue] = useState<string | string[] | null>(value);
|
|
90
82
|
const [internalValue, setInternalValue] = useState<StorageFieldItem[]>(internalInitialValue);
|
|
@@ -226,6 +218,32 @@ export function useStorageUploadController<M extends object>({
|
|
|
226
218
|
}
|
|
227
219
|
}
|
|
228
220
|
|
|
221
|
+
function getInternalInitialValue(multipleFilesSupported: boolean,
|
|
222
|
+
value: string | string[] | null,
|
|
223
|
+
metadata: Record<string, any> | undefined,
|
|
224
|
+
size: PreviewSize): StorageFieldItem[] {
|
|
225
|
+
let strings: string[] = [];
|
|
226
|
+
if (multipleFilesSupported) {
|
|
227
|
+
if (Array.isArray(value) && value.every((v) => typeof v === "string")) {
|
|
228
|
+
strings = (value ?? []) as string[];
|
|
229
|
+
}
|
|
230
|
+
} else {
|
|
231
|
+
if (typeof value === "string") {
|
|
232
|
+
strings = value ? [value as string] : [];
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return strings
|
|
237
|
+
.map(entry => (
|
|
238
|
+
{
|
|
239
|
+
id: getRandomId(),
|
|
240
|
+
storagePathOrDownloadUrl: entry,
|
|
241
|
+
metadata,
|
|
242
|
+
size
|
|
243
|
+
}
|
|
244
|
+
));
|
|
245
|
+
}
|
|
246
|
+
|
|
229
247
|
function removeDuplicates(items: StorageFieldItem[]) {
|
|
230
248
|
return items.filter(
|
|
231
249
|
(item, i) => {
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
interface ArrayContainerProps<T> {
|
|
3
|
-
value: T[];
|
|
4
|
-
name: string;
|
|
5
|
-
addLabel: string;
|
|
6
|
-
buildEntry: (index: number, internalId: number) => React.ReactNode;
|
|
7
|
-
disabled?: boolean;
|
|
8
|
-
small?: boolean;
|
|
9
|
-
onInternalIdAdded?: (id: number) => void;
|
|
10
|
-
includeAddButton?: boolean;
|
|
11
|
-
newDefaultEntry?: T | null;
|
|
12
|
-
setFieldValue: (field: string, value: any, shouldValidate?: boolean | undefined) => void;
|
|
13
|
-
className?: string;
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* @group Form custom fields
|
|
17
|
-
*/
|
|
18
|
-
export declare function FormikArrayContainer<T>({ name, addLabel, value, disabled, buildEntry, small, onInternalIdAdded, includeAddButton, newDefaultEntry, setFieldValue, className }: ArrayContainerProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
19
|
-
export {};
|