@firecms/core 3.0.0-canary.6 → 3.0.0-canary.60
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/README.md +2 -2
- package/dist/components/ClearFilterSortButton.d.ts +5 -0
- package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +11 -11
- package/dist/components/EntityCollectionTable/EntityCollectionTable.d.ts +2 -2
- package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +5 -3
- package/dist/components/EntityCollectionTable/PropertyTableCell.d.ts +3 -2
- package/dist/components/EntityCollectionTable/column_utils.d.ts +1 -2
- package/dist/components/EntityCollectionTable/fields/TableReferenceField.d.ts +2 -0
- package/dist/components/EntityCollectionTable/internal/CollectionTableToolbar.d.ts +1 -4
- package/dist/components/EntityCollectionTable/internal/EntityTableCell.d.ts +2 -2
- package/dist/components/EntityCollectionTable/internal/popup_field/PopupFormField.d.ts +1 -1
- package/dist/components/EntityCollectionView/EntityCollectionView.d.ts +12 -3
- package/dist/components/EntityCollectionView/EntityCollectionViewStartActions.d.ts +11 -0
- package/dist/components/EntityCollectionView/useSelectionController.d.ts +2 -0
- package/dist/components/EntityPreview.d.ts +26 -7
- package/dist/components/EntityView.d.ts +11 -0
- package/dist/components/FieldCaption.d.ts +5 -0
- package/dist/components/FireCMSAppBar.d.ts +4 -2
- package/dist/components/HomePage/NavigationCard.d.ts +8 -0
- package/dist/components/HomePage/{NavigationCollectionCard.d.ts → NavigationCardBinding.d.ts} +2 -2
- package/dist/components/HomePage/SmallNavigationCard.d.ts +6 -0
- package/dist/components/HomePage/index.d.ts +3 -1
- package/dist/components/ReferenceWidget.d.ts +3 -1
- package/dist/components/SelectableTable/SelectableTable.d.ts +1 -1
- package/dist/components/SelectableTable/filters/ReferenceFilterField.d.ts +2 -1
- package/dist/components/VirtualTable/VirtualTableProps.d.ts +6 -7
- package/dist/components/VirtualTable/types.d.ts +3 -3
- package/dist/components/{EntityCollectionTable/internal → common}/default_entity_actions.d.ts +1 -1
- package/dist/components/common/index.d.ts +1 -0
- package/dist/components/common/table_height.d.ts +5 -0
- package/dist/components/common/types.d.ts +4 -6
- package/dist/components/common/useDataSourceEntityCollectionTableController.d.ts +3 -0
- package/dist/components/index.d.ts +5 -2
- package/dist/contexts/AuthControllerContext.d.ts +1 -1
- package/dist/core/Drawer.d.ts +5 -12
- package/dist/core/DrawerNavigationItem.d.ts +9 -0
- package/dist/core/{EntityView.d.ts → EntityEditView.d.ts} +2 -2
- package/dist/core/NavigationRoutes.d.ts +1 -1
- package/dist/core/Scaffold.d.ts +8 -12
- package/dist/core/index.d.ts +3 -4
- package/dist/form/EntityForm.d.ts +1 -1
- package/dist/form/components/ErrorFocus.d.ts +1 -1
- package/dist/form/components/StorageItemPreview.d.ts +3 -2
- package/dist/form/components/StorageUploadProgress.d.ts +1 -1
- package/dist/form/field_bindings/KeyValueFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/StorageUploadFieldBinding.d.ts +4 -3
- package/dist/form/field_bindings/TextFieldBinding.d.ts +2 -2
- package/dist/form/validation.d.ts +1 -1
- package/dist/hooks/data/delete.d.ts +2 -2
- package/dist/hooks/data/save.d.ts +2 -3
- package/dist/hooks/data/useDataSource.d.ts +2 -2
- package/dist/hooks/data/useEntityFetch.d.ts +3 -3
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/useBuildNavigationController.d.ts +6 -4
- package/dist/hooks/useProjectLog.d.ts +6 -2
- package/dist/hooks/useStorageSource.d.ts +2 -2
- package/dist/hooks/useValidateAuthenticator.d.ts +21 -0
- package/dist/index.es.js +10496 -9945
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +5 -5
- package/dist/index.umd.js.map +1 -1
- package/dist/internal/useBuildDataSource.d.ts +1 -16
- package/dist/preview/PropertyPreview.d.ts +1 -1
- package/dist/preview/PropertyPreviewProps.d.ts +1 -4
- package/dist/preview/components/BooleanPreview.d.ts +5 -1
- package/dist/preview/components/EnumValuesChip.d.ts +1 -1
- package/dist/preview/components/ReferencePreview.d.ts +3 -8
- package/dist/types/analytics.d.ts +1 -1
- package/dist/types/auth.d.ts +37 -1
- package/dist/types/collections.d.ts +30 -6
- package/dist/types/datasource.d.ts +21 -14
- package/dist/types/entities.d.ts +5 -1
- package/dist/types/entity_actions.d.ts +14 -0
- package/dist/types/entity_callbacks.d.ts +2 -2
- package/dist/types/entity_overrides.d.ts +6 -0
- package/dist/types/index.d.ts +2 -1
- package/dist/types/navigation.d.ts +15 -14
- package/dist/types/permissions.d.ts +5 -1
- package/dist/types/plugins.d.ts +20 -20
- package/dist/types/properties.d.ts +12 -4
- package/dist/types/property_config.d.ts +2 -2
- package/dist/types/roles.d.ts +31 -0
- package/dist/types/storage.d.ts +11 -3
- package/dist/types/user.d.ts +5 -0
- package/dist/util/collections.d.ts +9 -1
- package/dist/util/entities.d.ts +1 -1
- package/dist/util/icon_synonyms.d.ts +1 -97
- package/dist/util/icons.d.ts +8 -2
- package/dist/util/navigation_utils.d.ts +2 -2
- package/dist/util/objects.d.ts +1 -1
- package/dist/util/permissions.d.ts +4 -4
- package/dist/util/references.d.ts +4 -2
- package/dist/util/resolutions.d.ts +14 -14
- package/dist/util/useTraceUpdate.d.ts +1 -0
- package/package.json +139 -119
- package/src/components/ClearFilterSortButton.tsx +41 -0
- package/src/components/DeleteEntityDialog.tsx +4 -4
- package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +4 -4
- package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +276 -279
- package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +9 -5
- package/src/components/EntityCollectionTable/PropertyTableCell.tsx +48 -45
- package/src/components/EntityCollectionTable/column_utils.tsx +3 -3
- package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +18 -17
- package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +5 -5
- package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +29 -34
- package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +16 -12
- package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +2 -4
- package/src/components/EntityCollectionView/EntityCollectionView.tsx +73 -72
- package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +5 -6
- package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +68 -0
- package/src/components/EntityCollectionView/useSelectionController.tsx +30 -0
- package/src/components/EntityPreview.tsx +209 -70
- package/src/components/EntityView.tsx +84 -0
- package/src/components/FieldCaption.tsx +14 -0
- package/src/components/FireCMSAppBar.tsx +40 -15
- package/src/components/HomePage/DefaultHomePage.tsx +15 -11
- package/src/components/HomePage/NavigationCard.tsx +69 -0
- package/src/components/HomePage/NavigationCardBinding.tsx +116 -0
- package/src/components/HomePage/SmallNavigationCard.tsx +45 -0
- package/src/components/HomePage/index.tsx +3 -1
- package/src/components/PropertyIdCopyTooltipContent.tsx +2 -3
- package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +4 -4
- package/src/components/ReferenceWidget.tsx +22 -12
- package/src/components/SearchIconsView.tsx +5 -5
- package/src/components/SelectableTable/SelectableTable.tsx +5 -3
- package/src/components/SelectableTable/filters/BooleanFilterField.tsx +2 -3
- package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +23 -8
- package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +38 -24
- package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +35 -15
- package/src/components/VirtualTable/VirtualTable.tsx +38 -29
- package/src/components/VirtualTable/VirtualTableHeader.tsx +4 -4
- package/src/components/VirtualTable/VirtualTableHeaderRow.tsx +2 -2
- package/src/components/VirtualTable/VirtualTableProps.tsx +7 -7
- package/src/components/VirtualTable/VirtualTableRow.tsx +4 -5
- package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +1 -1
- package/src/components/VirtualTable/types.tsx +2 -3
- package/src/components/{EntityCollectionTable/internal → common}/default_entity_actions.tsx +11 -7
- package/src/components/common/index.ts +1 -0
- package/src/components/{VirtualTable/common.tsx → common/table_height.tsx} +5 -2
- package/src/components/common/types.tsx +4 -6
- package/src/components/common/useColumnsIds.tsx +10 -2
- package/src/components/common/useDataSourceEntityCollectionTableController.tsx +12 -1
- package/src/components/common/useTableSearchHelper.ts +39 -9
- package/src/components/index.tsx +5 -2
- package/src/contexts/AuthControllerContext.tsx +1 -1
- package/src/core/Drawer.tsx +78 -103
- package/src/core/DrawerNavigationItem.tsx +62 -0
- package/src/core/{EntityView.tsx → EntityEditView.tsx} +27 -45
- package/src/core/EntitySidePanel.tsx +3 -3
- package/src/core/FireCMS.tsx +54 -43
- package/src/core/NavigationRoutes.tsx +11 -4
- package/src/core/Scaffold.tsx +80 -66
- package/src/core/field_configs.tsx +2 -3
- package/src/core/index.tsx +3 -4
- package/src/form/EntityForm.tsx +49 -33
- package/src/form/PropertyFieldBinding.tsx +0 -2
- package/src/form/components/StorageItemPreview.tsx +7 -5
- package/src/form/components/StorageUploadProgress.tsx +9 -8
- package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +10 -12
- package/src/form/field_bindings/BlockFieldBinding.tsx +2 -2
- package/src/form/field_bindings/DateTimeFieldBinding.tsx +1 -1
- package/src/form/field_bindings/KeyValueFieldBinding.tsx +19 -19
- package/src/form/field_bindings/MapFieldBinding.tsx +15 -15
- package/src/form/field_bindings/MarkdownFieldBinding.tsx +2 -2
- package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +3 -3
- package/src/form/field_bindings/ReferenceFieldBinding.tsx +16 -13
- package/src/form/field_bindings/SelectFieldBinding.tsx +3 -3
- package/src/form/field_bindings/StorageUploadFieldBinding.tsx +18 -9
- package/src/form/field_bindings/TextFieldBinding.tsx +7 -5
- package/src/form/validation.ts +3 -4
- package/src/hooks/data/delete.ts +3 -3
- package/src/hooks/data/save.ts +4 -2
- package/src/hooks/data/useCollectionFetch.tsx +1 -1
- package/src/hooks/data/useDataSource.tsx +8 -3
- package/src/hooks/data/useEntityFetch.tsx +4 -4
- package/src/hooks/index.tsx +3 -0
- package/src/hooks/useBuildLocalConfigurationPersistence.tsx +8 -10
- package/src/hooks/useBuildModeController.tsx +11 -5
- package/src/hooks/useBuildNavigationController.tsx +200 -83
- package/src/hooks/useProjectLog.tsx +17 -7
- package/src/hooks/useReferenceDialog.tsx +2 -2
- package/src/hooks/useResolvedNavigationFrom.tsx +1 -1
- package/src/hooks/useStorageSource.tsx +7 -2
- package/src/hooks/useValidateAuthenticator.tsx +115 -0
- package/src/internal/useBuildDataSource.ts +54 -47
- package/src/internal/useBuildSideEntityController.tsx +88 -21
- package/src/preview/PropertyPreview.tsx +5 -15
- package/src/preview/PropertyPreviewProps.tsx +1 -11
- package/src/preview/components/BooleanPreview.tsx +19 -4
- package/src/preview/components/EnumValuesChip.tsx +2 -2
- package/src/preview/components/ReferencePreview.tsx +72 -165
- package/src/preview/property_previews/ArrayOfMapsPreview.tsx +0 -1
- package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +2 -1
- package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +0 -1
- package/src/preview/property_previews/ArrayOfStringsPreview.tsx +0 -1
- package/src/preview/property_previews/ArrayOneOfPreview.tsx +2 -3
- package/src/preview/property_previews/ArrayPropertyPreview.tsx +2 -3
- package/src/preview/property_previews/MapPropertyPreview.tsx +5 -5
- package/src/preview/property_previews/StringPropertyPreview.tsx +8 -7
- package/src/types/analytics.ts +1 -0
- package/src/types/auth.tsx +50 -1
- package/src/types/collections.ts +37 -6
- package/src/types/datasource.ts +24 -17
- package/src/types/entities.ts +9 -1
- package/src/types/entity_actions.tsx +17 -0
- package/src/types/entity_callbacks.ts +2 -2
- package/src/types/entity_overrides.tsx +7 -0
- package/src/types/firecms.tsx +0 -1
- package/src/types/index.ts +2 -1
- package/src/types/navigation.ts +17 -17
- package/src/types/permissions.ts +6 -1
- package/src/types/plugins.tsx +26 -28
- package/src/types/properties.ts +18 -6
- package/src/types/property_config.tsx +2 -2
- package/src/types/roles.ts +41 -0
- package/src/types/side_entity_controller.tsx +1 -0
- package/src/types/storage.ts +12 -3
- package/src/types/user.ts +7 -0
- package/src/util/collections.ts +22 -0
- package/src/util/entities.ts +1 -1
- package/src/util/enums.ts +1 -1
- package/src/util/icon_list.ts +2 -2
- package/src/util/icon_synonyms.ts +3 -99
- package/src/util/icons.tsx +11 -3
- package/src/util/navigation_utils.ts +6 -6
- package/src/util/objects.ts +8 -21
- package/src/util/permissions.ts +11 -8
- package/src/util/references.ts +36 -5
- package/src/util/resolutions.ts +32 -31
- package/src/util/strings.ts +2 -2
- package/src/util/useTraceUpdate.tsx +2 -1
- package/dist/components/VirtualTable/common.d.ts +0 -2
- package/dist/core/SideEntityView.d.ts +0 -7
- package/dist/internal/useBuildCustomizationController.d.ts +0 -2
- package/dist/internal/useLocaleConfig.d.ts +0 -1
- package/dist/types/appcheck.d.ts +0 -26
- package/src/components/HomePage/NavigationCollectionCard.tsx +0 -146
- package/src/core/SideEntityView.tsx +0 -38
- package/src/internal/useBuildCustomizationController.tsx +0 -5
- package/src/internal/useLocaleConfig.tsx +0 -18
- package/src/types/appcheck.ts +0 -29
|
@@ -12,8 +12,7 @@ import {
|
|
|
12
12
|
PartialEntityCollection,
|
|
13
13
|
PropertyOrBuilder,
|
|
14
14
|
ResolvedProperty,
|
|
15
|
-
SaveEntityProps
|
|
16
|
-
SelectionController
|
|
15
|
+
SaveEntityProps
|
|
17
16
|
} from "../../types";
|
|
18
17
|
import {
|
|
19
18
|
EntityCollectionRowActions,
|
|
@@ -25,7 +24,6 @@ import {
|
|
|
25
24
|
canCreateEntity,
|
|
26
25
|
canDeleteEntity,
|
|
27
26
|
canEditEntity,
|
|
28
|
-
fullPathToCollectionSegments,
|
|
29
27
|
getPropertyInPath,
|
|
30
28
|
mergeDeep,
|
|
31
29
|
resolveCollection,
|
|
@@ -37,6 +35,7 @@ import {
|
|
|
37
35
|
useAuthController,
|
|
38
36
|
useCustomizationController,
|
|
39
37
|
useDataSource,
|
|
38
|
+
useFireCMSContext,
|
|
40
39
|
useLargeLayout,
|
|
41
40
|
useNavigationController,
|
|
42
41
|
useSideEntityController
|
|
@@ -46,7 +45,7 @@ import { EntityCollectionViewActions } from "./EntityCollectionViewActions";
|
|
|
46
45
|
import {
|
|
47
46
|
AddIcon,
|
|
48
47
|
Button,
|
|
49
|
-
|
|
48
|
+
cls,
|
|
50
49
|
IconButton,
|
|
51
50
|
KeyboardTabIcon,
|
|
52
51
|
Markdown,
|
|
@@ -67,13 +66,11 @@ import {
|
|
|
67
66
|
} from "../common";
|
|
68
67
|
import { PopupFormField } from "../EntityCollectionTable/internal/popup_field/PopupFormField";
|
|
69
68
|
import { GetPropertyForProps } from "../EntityCollectionTable/EntityCollectionTableProps";
|
|
70
|
-
import {
|
|
71
|
-
copyEntityAction,
|
|
72
|
-
deleteEntityAction,
|
|
73
|
-
editEntityAction
|
|
74
|
-
} from "../EntityCollectionTable/internal/default_entity_actions";
|
|
69
|
+
import { copyEntityAction, deleteEntityAction, editEntityAction } from "../common/default_entity_actions";
|
|
75
70
|
import { DeleteEntityDialog } from "../DeleteEntityDialog";
|
|
76
71
|
import { useAnalyticsController } from "../../hooks/useAnalyticsController";
|
|
72
|
+
import { useSelectionController } from "./useSelectionController";
|
|
73
|
+
import { EntityCollectionViewStartActions } from "./EntityCollectionViewStartActions";
|
|
77
74
|
|
|
78
75
|
const COLLECTION_GROUP_PARENT_ID = "collectionGroupParent";
|
|
79
76
|
|
|
@@ -81,10 +78,22 @@ const COLLECTION_GROUP_PARENT_ID = "collectionGroupParent";
|
|
|
81
78
|
* @group Components
|
|
82
79
|
*/
|
|
83
80
|
export type EntityCollectionViewProps<M extends Record<string, any>> = {
|
|
84
|
-
|
|
81
|
+
/**
|
|
82
|
+
* Complete path where this collection is located.
|
|
83
|
+
* It defaults to the collection path if not provided.
|
|
84
|
+
*/
|
|
85
|
+
fullPath?: string;
|
|
86
|
+
/**
|
|
87
|
+
* If this is a subcollection, specify the parent collection ids.
|
|
88
|
+
*/
|
|
85
89
|
parentCollectionIds?: string[];
|
|
90
|
+
/**
|
|
91
|
+
* Whether this is a subcollection or not.
|
|
92
|
+
*/
|
|
86
93
|
isSubCollection?: boolean;
|
|
94
|
+
|
|
87
95
|
className?: string;
|
|
96
|
+
|
|
88
97
|
} & EntityCollection<M>;
|
|
89
98
|
|
|
90
99
|
/**
|
|
@@ -113,7 +122,7 @@ export type EntityCollectionViewProps<M extends Record<string, any>> = {
|
|
|
113
122
|
*/
|
|
114
123
|
export const EntityCollectionView = React.memo(
|
|
115
124
|
function EntityCollectionView<M extends Record<string, any>>({
|
|
116
|
-
fullPath,
|
|
125
|
+
fullPath: fullPathProp,
|
|
117
126
|
parentCollectionIds,
|
|
118
127
|
isSubCollection,
|
|
119
128
|
className,
|
|
@@ -121,7 +130,9 @@ export const EntityCollectionView = React.memo(
|
|
|
121
130
|
}: EntityCollectionViewProps<M>
|
|
122
131
|
) {
|
|
123
132
|
|
|
124
|
-
const
|
|
133
|
+
const context = useFireCMSContext();
|
|
134
|
+
const fullPath = fullPathProp ?? collectionProp.path;
|
|
135
|
+
const dataSource = useDataSource(collectionProp);
|
|
125
136
|
const navigation = useNavigationController();
|
|
126
137
|
const sideEntityController = useSideEntityController();
|
|
127
138
|
const authController = useAuthController();
|
|
@@ -141,7 +152,7 @@ export const EntityCollectionView = React.memo(
|
|
|
141
152
|
collectionRef.current = collection;
|
|
142
153
|
}, [collection]);
|
|
143
154
|
|
|
144
|
-
const canCreateEntities = canCreateEntity(collection, authController,
|
|
155
|
+
const canCreateEntities = canCreateEntity(collection, authController, fullPath, null);
|
|
145
156
|
const [selectedNavigationEntity, setSelectedNavigationEntity] = useState<Entity<M> | undefined>(undefined);
|
|
146
157
|
const [deleteEntityClicked, setDeleteEntityClicked] = React.useState<Entity<M> | Entity<M>[] | undefined>(undefined);
|
|
147
158
|
|
|
@@ -160,7 +171,7 @@ export const EntityCollectionView = React.memo(
|
|
|
160
171
|
|
|
161
172
|
const checkInlineEditing = useCallback((entity?: Entity<any>): boolean => {
|
|
162
173
|
const collection = collectionRef.current;
|
|
163
|
-
if (!canEditEntity(collection, authController,
|
|
174
|
+
if (!canEditEntity(collection, authController, fullPath, entity ?? null)) {
|
|
164
175
|
return false;
|
|
165
176
|
}
|
|
166
177
|
return collection.inlineEditing === undefined || collection.inlineEditing;
|
|
@@ -175,7 +186,6 @@ export const EntityCollectionView = React.memo(
|
|
|
175
186
|
const usedSelectionController = collection.selectionController ?? selectionController;
|
|
176
187
|
const {
|
|
177
188
|
selectedEntities,
|
|
178
|
-
toggleEntitySelection,
|
|
179
189
|
isEntitySelected,
|
|
180
190
|
setSelectedEntities
|
|
181
191
|
} = usedSelectionController;
|
|
@@ -186,8 +196,7 @@ export const EntityCollectionView = React.memo(
|
|
|
186
196
|
|
|
187
197
|
const tableController = useDataSourceEntityCollectionTableController<M>({
|
|
188
198
|
fullPath,
|
|
189
|
-
collection
|
|
190
|
-
entitiesDisplayedFirst: [],
|
|
199
|
+
collection,
|
|
191
200
|
lastDeleteTimestamp
|
|
192
201
|
});
|
|
193
202
|
|
|
@@ -199,6 +208,7 @@ export const EntityCollectionView = React.memo(
|
|
|
199
208
|
}, [tableController.setPopupCell]);
|
|
200
209
|
|
|
201
210
|
const onEntityClick = useCallback((clickedEntity: Entity<M>) => {
|
|
211
|
+
console.log("Entity clicked", clickedEntity)
|
|
202
212
|
const collection = collectionRef.current;
|
|
203
213
|
setSelectedNavigationEntity(clickedEntity);
|
|
204
214
|
analyticsController.onAnalyticsEvent?.("edit_entity_clicked", {
|
|
@@ -210,9 +220,9 @@ export const EntityCollectionView = React.memo(
|
|
|
210
220
|
path: clickedEntity.path,
|
|
211
221
|
collection,
|
|
212
222
|
updateUrl: true,
|
|
213
|
-
onClose: unselectNavigatedEntity
|
|
223
|
+
onClose: unselectNavigatedEntity,
|
|
214
224
|
});
|
|
215
|
-
}, [unselectNavigatedEntity]);
|
|
225
|
+
}, [unselectNavigatedEntity, sideEntityController]);
|
|
216
226
|
|
|
217
227
|
const onNewClick = useCallback(() => {
|
|
218
228
|
|
|
@@ -224,9 +234,9 @@ export const EntityCollectionView = React.memo(
|
|
|
224
234
|
path: fullPath,
|
|
225
235
|
collection,
|
|
226
236
|
updateUrl: true,
|
|
227
|
-
onClose: unselectNavigatedEntity
|
|
237
|
+
onClose: unselectNavigatedEntity,
|
|
228
238
|
});
|
|
229
|
-
}, [fullPath]);
|
|
239
|
+
}, [fullPath, sideEntityController]);
|
|
230
240
|
|
|
231
241
|
const onMultipleDeleteClick = () => {
|
|
232
242
|
analyticsController.onAnalyticsEvent?.("multiple_delete_dialog_open", {
|
|
@@ -288,7 +298,7 @@ export const EntityCollectionView = React.memo(
|
|
|
288
298
|
onCollectionModifiedForUser(fullPath, { defaultSize: size })
|
|
289
299
|
}, [onCollectionModifiedForUser, fullPath, userConfigPersistence]);
|
|
290
300
|
|
|
291
|
-
const createEnabled = canCreateEntity(collection, authController,
|
|
301
|
+
const createEnabled = canCreateEntity(collection, authController, fullPath, null);
|
|
292
302
|
|
|
293
303
|
const uniqueFieldValidator: UniqueFieldValidator = useCallback(
|
|
294
304
|
({
|
|
@@ -300,13 +310,11 @@ export const EntityCollectionView = React.memo(
|
|
|
300
310
|
[fullPath]);
|
|
301
311
|
|
|
302
312
|
const onValueChange: OnCellValueChange<any, any> = ({
|
|
303
|
-
fullPath,
|
|
304
|
-
context,
|
|
305
313
|
value,
|
|
306
314
|
propertyKey,
|
|
307
315
|
onValueUpdated,
|
|
308
316
|
setError,
|
|
309
|
-
entity,
|
|
317
|
+
data: entity,
|
|
310
318
|
}) => {
|
|
311
319
|
|
|
312
320
|
const updatedValues = setIn({ ...entity.values }, propertyKey, value);
|
|
@@ -323,10 +331,12 @@ export const EntityCollectionView = React.memo(
|
|
|
323
331
|
return saveEntityWithCallbacks({
|
|
324
332
|
...saveProps,
|
|
325
333
|
collection,
|
|
326
|
-
callbacks: collection.callbacks,
|
|
327
334
|
dataSource,
|
|
328
335
|
context,
|
|
329
|
-
onSaveSuccess: () =>
|
|
336
|
+
onSaveSuccess: () => {
|
|
337
|
+
setError(undefined);
|
|
338
|
+
onValueUpdated();
|
|
339
|
+
},
|
|
330
340
|
onSaveFailure: (e: Error) => {
|
|
331
341
|
console.error("Save failure");
|
|
332
342
|
console.error(e);
|
|
@@ -345,7 +355,6 @@ export const EntityCollectionView = React.memo(
|
|
|
345
355
|
|
|
346
356
|
const getPropertyFor = useCallback(({
|
|
347
357
|
propertyKey,
|
|
348
|
-
propertyValue,
|
|
349
358
|
entity
|
|
350
359
|
}: GetPropertyForProps<M>) => {
|
|
351
360
|
let propertyOrBuilder: PropertyOrBuilder<any, M> | undefined = getPropertyInPath<M>(collection.properties, propertyKey);
|
|
@@ -360,7 +369,6 @@ export const EntityCollectionView = React.memo(
|
|
|
360
369
|
propertyKey,
|
|
361
370
|
propertyOrBuilder,
|
|
362
371
|
path: fullPath,
|
|
363
|
-
propertyValue,
|
|
364
372
|
values: entity.values,
|
|
365
373
|
entityId: entity.id,
|
|
366
374
|
fields: customizationController.propertyConfigs
|
|
@@ -387,7 +395,7 @@ export const EntityCollectionView = React.memo(
|
|
|
387
395
|
entityId: entity.id,
|
|
388
396
|
selectedSubPath: subcollection.id ?? subcollection.path,
|
|
389
397
|
collection,
|
|
390
|
-
updateUrl: true
|
|
398
|
+
updateUrl: true,
|
|
391
399
|
});
|
|
392
400
|
}}>
|
|
393
401
|
{subcollection.name}
|
|
@@ -405,7 +413,7 @@ export const EntityCollectionView = React.memo(
|
|
|
405
413
|
Builder: ({ entity }) => {
|
|
406
414
|
const collectionsWithPath = navigation.getParentReferencesFromPath(entity.path);
|
|
407
415
|
return (
|
|
408
|
-
|
|
416
|
+
<div className={"flex flex-col gap-2 w-full"}>
|
|
409
417
|
{collectionsWithPath.map((reference) => {
|
|
410
418
|
return (
|
|
411
419
|
<ReferencePreview
|
|
@@ -414,7 +422,7 @@ export const EntityCollectionView = React.memo(
|
|
|
414
422
|
size={"tiny"}/>
|
|
415
423
|
);
|
|
416
424
|
})}
|
|
417
|
-
|
|
425
|
+
</div>
|
|
418
426
|
);
|
|
419
427
|
}
|
|
420
428
|
}]
|
|
@@ -425,7 +433,7 @@ export const EntityCollectionView = React.memo(
|
|
|
425
433
|
...subcollectionColumns,
|
|
426
434
|
...collectionGroupParentCollections
|
|
427
435
|
];
|
|
428
|
-
}, [collection, fullPath]);
|
|
436
|
+
}, [collection, fullPath, sideEntityController]);
|
|
429
437
|
|
|
430
438
|
const updateLastDeleteTimestamp = useCallback(() => {
|
|
431
439
|
setLastDeleteTimestamp(Date.now());
|
|
@@ -433,11 +441,14 @@ export const EntityCollectionView = React.memo(
|
|
|
433
441
|
|
|
434
442
|
const largeLayout = useLargeLayout();
|
|
435
443
|
|
|
436
|
-
const getActionsForEntity = ({
|
|
444
|
+
const getActionsForEntity = ({
|
|
445
|
+
entity,
|
|
446
|
+
customEntityActions
|
|
447
|
+
}: {
|
|
437
448
|
entity?: Entity<M>,
|
|
438
449
|
customEntityActions?: EntityAction[]
|
|
439
450
|
}): EntityAction[] => {
|
|
440
|
-
const deleteEnabled = entity ? canDeleteEntity(collection, authController,
|
|
451
|
+
const deleteEnabled = entity ? canDeleteEntity(collection, authController, fullPath, entity) : true;
|
|
441
452
|
const actions: EntityAction[] = [editEntityAction];
|
|
442
453
|
if (createEnabled)
|
|
443
454
|
actions.push(copyEntityAction);
|
|
@@ -448,13 +459,13 @@ export const EntityCollectionView = React.memo(
|
|
|
448
459
|
return actions;
|
|
449
460
|
};
|
|
450
461
|
|
|
451
|
-
const getIdColumnWidth =
|
|
462
|
+
const getIdColumnWidth = () => {
|
|
452
463
|
const entityActions = getActionsForEntity({});
|
|
453
464
|
const collapsedActions = entityActions.filter(a => a.collapsed !== false);
|
|
454
465
|
const uncollapsedActions = entityActions.filter(a => a.collapsed === false);
|
|
455
466
|
const actionsWidth = uncollapsedActions.length * (largeLayout ? 40 : 30);
|
|
456
467
|
return (largeLayout ? (80 + actionsWidth) : (70 + actionsWidth)) + (collapsedActions.length > 0 ? (largeLayout ? 40 : 30) : 0);
|
|
457
|
-
}
|
|
468
|
+
};
|
|
458
469
|
|
|
459
470
|
const tableRowActionsBuilder = ({
|
|
460
471
|
entity,
|
|
@@ -470,7 +481,10 @@ export const EntityCollectionView = React.memo(
|
|
|
470
481
|
|
|
471
482
|
const isSelected = isEntitySelected(entity);
|
|
472
483
|
|
|
473
|
-
const actions = getActionsForEntity({
|
|
484
|
+
const actions = getActionsForEntity({
|
|
485
|
+
entity,
|
|
486
|
+
customEntityActions: collection.entityActions
|
|
487
|
+
});
|
|
474
488
|
|
|
475
489
|
return (
|
|
476
490
|
<EntityCollectionRowActions
|
|
@@ -577,12 +591,13 @@ export const EntityCollectionView = React.memo(
|
|
|
577
591
|
});
|
|
578
592
|
|
|
579
593
|
return (
|
|
580
|
-
<div className={
|
|
594
|
+
<div className={cls("overflow-hidden h-full w-full rounded-md", className)}
|
|
581
595
|
ref={containerRef}>
|
|
582
596
|
<EntityCollectionTable
|
|
583
597
|
key={`collection_table_${fullPath}`}
|
|
584
598
|
additionalFields={additionalFields}
|
|
585
599
|
tableController={tableController}
|
|
600
|
+
enablePopupIcon={true}
|
|
586
601
|
displayedColumnIds={displayedColumnIds}
|
|
587
602
|
onSizeChanged={onSizeChanged}
|
|
588
603
|
onEntityClick={onEntityClick}
|
|
@@ -599,6 +614,14 @@ export const EntityCollectionView = React.memo(
|
|
|
599
614
|
onTextSearchClick={textSearchInitialised ? undefined : onTextSearchClick}
|
|
600
615
|
textSearchLoading={textSearchLoading}
|
|
601
616
|
textSearchEnabled={textSearchEnabled}
|
|
617
|
+
actionsStart={<EntityCollectionViewStartActions
|
|
618
|
+
parentCollectionIds={parentCollectionIds ?? []}
|
|
619
|
+
collection={collection}
|
|
620
|
+
tableController={tableController}
|
|
621
|
+
path={fullPath}
|
|
622
|
+
relativePath={collection.path}
|
|
623
|
+
selectionController={usedSelectionController}
|
|
624
|
+
collectionEntitiesCount={docsCount}/>}
|
|
602
625
|
actions={<EntityCollectionViewActions
|
|
603
626
|
parentCollectionIds={parentCollectionIds ?? []}
|
|
604
627
|
collection={collection}
|
|
@@ -676,39 +699,14 @@ export const EntityCollectionView = React.memo(
|
|
|
676
699
|
equal(a.selectionController, b.selectionController) &&
|
|
677
700
|
equal(a.Actions, b.Actions) &&
|
|
678
701
|
equal(a.defaultSize, b.defaultSize) &&
|
|
702
|
+
equal(a.initialFilter, b.initialFilter) &&
|
|
703
|
+
equal(a.initialSort, b.initialSort) &&
|
|
679
704
|
equal(a.textSearchEnabled, b.textSearchEnabled) &&
|
|
680
705
|
equal(a.additionalFields, b.additionalFields) &&
|
|
706
|
+
equal(a.sideDialogWidth, b.sideDialogWidth) &&
|
|
681
707
|
equal(a.forceFilter, b.forceFilter);
|
|
682
708
|
}) as React.FunctionComponent<EntityCollectionViewProps<any>>
|
|
683
709
|
|
|
684
|
-
export function useSelectionController<M extends Record<string, any> = any>(
|
|
685
|
-
onSelectionChange?: (entity: Entity<M>, selected: boolean) => void
|
|
686
|
-
): SelectionController<M> {
|
|
687
|
-
|
|
688
|
-
const [selectedEntities, setSelectedEntities] = useState<Entity<M>[]>([]);
|
|
689
|
-
|
|
690
|
-
const toggleEntitySelection = useCallback((entity: Entity<M>) => {
|
|
691
|
-
let newValue;
|
|
692
|
-
if (selectedEntities.map(e => e.id).includes(entity.id)) {
|
|
693
|
-
onSelectionChange?.(entity, false);
|
|
694
|
-
newValue = selectedEntities.filter((item: Entity<M>) => item.id !== entity.id);
|
|
695
|
-
} else {
|
|
696
|
-
onSelectionChange?.(entity, true);
|
|
697
|
-
newValue = [...selectedEntities, entity];
|
|
698
|
-
}
|
|
699
|
-
setSelectedEntities(newValue);
|
|
700
|
-
}, [selectedEntities]);
|
|
701
|
-
|
|
702
|
-
const isEntitySelected = useCallback((entity: Entity<M>) => selectedEntities.map(e => e.id).includes(entity.id), [selectedEntities]);
|
|
703
|
-
|
|
704
|
-
return {
|
|
705
|
-
selectedEntities,
|
|
706
|
-
setSelectedEntities,
|
|
707
|
-
isEntitySelected,
|
|
708
|
-
toggleEntitySelection
|
|
709
|
-
};
|
|
710
|
-
}
|
|
711
|
-
|
|
712
710
|
function EntitiesCount({
|
|
713
711
|
fullPath,
|
|
714
712
|
collection,
|
|
@@ -723,7 +721,7 @@ function EntitiesCount({
|
|
|
723
721
|
onCountChange?: (count: number) => void,
|
|
724
722
|
}) {
|
|
725
723
|
|
|
726
|
-
const dataSource = useDataSource();
|
|
724
|
+
const dataSource = useDataSource(collection);
|
|
727
725
|
const navigation = useNavigationController();
|
|
728
726
|
const [count, setCount] = useState<number | undefined>(undefined);
|
|
729
727
|
const [error, setError] = useState<Error | undefined>(undefined);
|
|
@@ -745,6 +743,7 @@ function EntitiesCount({
|
|
|
745
743
|
|
|
746
744
|
useEffect(() => {
|
|
747
745
|
if (onCountChange) {
|
|
746
|
+
setError(undefined);
|
|
748
747
|
onCountChange(count ?? 0);
|
|
749
748
|
}
|
|
750
749
|
}, [onCountChange, count]);
|
|
@@ -796,10 +795,10 @@ function EntityIdHeaderWidget({
|
|
|
796
795
|
if (!searchString) return;
|
|
797
796
|
setOpenPopup(false);
|
|
798
797
|
return sideEntityController.open({
|
|
799
|
-
entityId: searchString,
|
|
798
|
+
entityId: searchString.trim(),
|
|
800
799
|
path,
|
|
801
800
|
collection,
|
|
802
|
-
updateUrl: true
|
|
801
|
+
updateUrl: true,
|
|
803
802
|
});
|
|
804
803
|
}}
|
|
805
804
|
className={"text-gray-900 dark:text-white w-96 max-w-full"}>
|
|
@@ -809,11 +808,13 @@ function EntityIdHeaderWidget({
|
|
|
809
808
|
autoFocus={openPopup}
|
|
810
809
|
placeholder={"Find entity by ID"}
|
|
811
810
|
// size={"small"}
|
|
812
|
-
onChange={(e) =>
|
|
811
|
+
onChange={(e) => {
|
|
812
|
+
setSearchString(e.target.value);
|
|
813
|
+
}}
|
|
813
814
|
value={searchString}
|
|
814
815
|
className={"flex-grow bg-transparent outline-none p-1"}/>
|
|
815
816
|
<Button variant={"outlined"}
|
|
816
|
-
disabled={!searchString}
|
|
817
|
+
disabled={!(searchString.trim())}
|
|
817
818
|
type={"submit"}
|
|
818
819
|
>Go</Button>
|
|
819
820
|
</div>
|
|
@@ -44,7 +44,7 @@ export function EntityCollectionViewActions<M extends Record<string, any>>({
|
|
|
44
44
|
|
|
45
45
|
const selectedEntities = selectionController.selectedEntities;
|
|
46
46
|
|
|
47
|
-
const addButton = canCreateEntity(collection, authController,
|
|
47
|
+
const addButton = canCreateEntity(collection, authController, path, null) &&
|
|
48
48
|
onNewClick && (largeLayout
|
|
49
49
|
? <Button
|
|
50
50
|
id={`add_entity_${path}`}
|
|
@@ -57,14 +57,13 @@ export function EntityCollectionViewActions<M extends Record<string, any>>({
|
|
|
57
57
|
: <Button
|
|
58
58
|
id={`add_entity_${path}`}
|
|
59
59
|
onClick={onNewClick}
|
|
60
|
-
size="medium"
|
|
61
60
|
variant="filled"
|
|
62
61
|
color="primary"
|
|
63
62
|
>
|
|
64
63
|
<AddIcon/>
|
|
65
64
|
</Button>);
|
|
66
65
|
|
|
67
|
-
const multipleDeleteEnabled = canDeleteEntity(collection, authController,
|
|
66
|
+
const multipleDeleteEnabled = canDeleteEntity(collection, authController, path, null);
|
|
68
67
|
|
|
69
68
|
let multipleDeleteButton: React.ReactNode | undefined;
|
|
70
69
|
if (selectionEnabled) {
|
|
@@ -112,11 +111,11 @@ export function EntityCollectionViewActions<M extends Record<string, any>>({
|
|
|
112
111
|
|
|
113
112
|
if (plugins) {
|
|
114
113
|
plugins.forEach((plugin, i) => {
|
|
115
|
-
if (plugin.
|
|
116
|
-
actions.push(...toArray(plugin.
|
|
114
|
+
if (plugin.collectionView?.CollectionActions) {
|
|
115
|
+
actions.push(...toArray(plugin.collectionView?.CollectionActions)
|
|
117
116
|
.map((Action, j) => (
|
|
118
117
|
<ErrorBoundary key={`plugin_actions_${i}_${j}`}>
|
|
119
|
-
<Action {...actionProps} {...plugin.
|
|
118
|
+
<Action {...actionProps} {...plugin.collectionView?.collectionActionsProps}/>
|
|
120
119
|
</ErrorBoundary>
|
|
121
120
|
)));
|
|
122
121
|
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { useCustomizationController, useFireCMSContext } from "../../hooks";
|
|
3
|
+
import { CollectionActionsProps, EntityCollection, EntityTableController, SelectionController } from "../../types";
|
|
4
|
+
import { toArray } from "../../util/arrays";
|
|
5
|
+
import { ErrorBoundary } from "../ErrorBoundary";
|
|
6
|
+
import { ClearFilterSortButton } from "../ClearFilterSortButton";
|
|
7
|
+
|
|
8
|
+
export type EntityCollectionViewStartActionsProps<M extends Record<string, any>> = {
|
|
9
|
+
collection: EntityCollection<M>;
|
|
10
|
+
path: string;
|
|
11
|
+
relativePath: string;
|
|
12
|
+
parentCollectionIds: string[];
|
|
13
|
+
selectionController: SelectionController<M>;
|
|
14
|
+
tableController: EntityTableController<M>;
|
|
15
|
+
collectionEntitiesCount: number;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function EntityCollectionViewStartActions<M extends Record<string, any>>({
|
|
19
|
+
collection,
|
|
20
|
+
relativePath,
|
|
21
|
+
parentCollectionIds,
|
|
22
|
+
path,
|
|
23
|
+
selectionController,
|
|
24
|
+
tableController,
|
|
25
|
+
collectionEntitiesCount
|
|
26
|
+
}: EntityCollectionViewStartActionsProps<M>) {
|
|
27
|
+
|
|
28
|
+
const context = useFireCMSContext();
|
|
29
|
+
|
|
30
|
+
const customizationController = useCustomizationController();
|
|
31
|
+
const plugins = customizationController.plugins ?? [];
|
|
32
|
+
|
|
33
|
+
const actionProps: CollectionActionsProps = {
|
|
34
|
+
path,
|
|
35
|
+
relativePath,
|
|
36
|
+
parentCollectionIds,
|
|
37
|
+
collection,
|
|
38
|
+
selectionController,
|
|
39
|
+
context,
|
|
40
|
+
tableController,
|
|
41
|
+
collectionEntitiesCount
|
|
42
|
+
};
|
|
43
|
+
const actions: React.ReactNode[] = [
|
|
44
|
+
<ClearFilterSortButton
|
|
45
|
+
key={"clear_filter"}
|
|
46
|
+
tableController={tableController}
|
|
47
|
+
enabled={!collection.forceFilter}/>
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
if (plugins) {
|
|
51
|
+
plugins.forEach((plugin, i) => {
|
|
52
|
+
if (plugin.collectionView?.CollectionActionsStart) {
|
|
53
|
+
actions.push(...toArray(plugin.collectionView?.CollectionActionsStart)
|
|
54
|
+
.map((Action, j) => (
|
|
55
|
+
<ErrorBoundary key={`plugin_actions_${i}_${j}`}>
|
|
56
|
+
<Action {...actionProps} {...plugin.collectionView?.collectionActionsStartProps}/>
|
|
57
|
+
</ErrorBoundary>
|
|
58
|
+
)));
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<>
|
|
65
|
+
{actions}
|
|
66
|
+
</>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { useCallback, useState } from "react";
|
|
2
|
+
import { Entity, SelectionController } from "../../types";
|
|
3
|
+
|
|
4
|
+
export function useSelectionController<M extends Record<string, any> = any>(
|
|
5
|
+
onSelectionChange?: (entity: Entity<M>, selected: boolean) => void
|
|
6
|
+
): SelectionController<M> {
|
|
7
|
+
|
|
8
|
+
const [selectedEntities, setSelectedEntities] = useState<Entity<M>[]>([]);
|
|
9
|
+
|
|
10
|
+
const toggleEntitySelection = useCallback((entity: Entity<M>) => {
|
|
11
|
+
let newValue;
|
|
12
|
+
if (selectedEntities.map(e => e.id).includes(entity.id)) {
|
|
13
|
+
onSelectionChange?.(entity, false);
|
|
14
|
+
newValue = selectedEntities.filter((item: Entity<M>) => item.id !== entity.id);
|
|
15
|
+
} else {
|
|
16
|
+
onSelectionChange?.(entity, true);
|
|
17
|
+
newValue = [...selectedEntities, entity];
|
|
18
|
+
}
|
|
19
|
+
setSelectedEntities(newValue);
|
|
20
|
+
}, [selectedEntities]);
|
|
21
|
+
|
|
22
|
+
const isEntitySelected = useCallback((entity: Entity<M>) => selectedEntities.map(e => e.id).includes(entity.id), [selectedEntities]);
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
selectedEntities,
|
|
26
|
+
setSelectedEntities,
|
|
27
|
+
isEntitySelected,
|
|
28
|
+
toggleEntitySelection
|
|
29
|
+
};
|
|
30
|
+
}
|