@firecms/core 3.0.0-canary.5 → 3.0.0-canary.50
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/internal/CollectionTableToolbar.d.ts +1 -4
- 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 +25 -7
- package/dist/components/EntityView.d.ts +11 -0
- package/dist/components/FieldCaption.d.ts +5 -0
- package/dist/components/FireCMSAppBar.d.ts +3 -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/SelectableTable/SelectableTable.d.ts +1 -1
- package/dist/components/VirtualTable/VirtualTableProps.d.ts +1 -1
- package/dist/components/common/types.d.ts +4 -6
- package/dist/components/common/useDataSourceEntityCollectionTableController.d.ts +3 -0
- package/dist/components/index.d.ts +4 -2
- package/dist/contexts/AuthControllerContext.d.ts +1 -1
- 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 +1 -1
- 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 +1 -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 +10402 -9898
- 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 -12
- 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 +1 -7
- package/dist/types/analytics.d.ts +1 -1
- package/dist/types/auth.d.ts +37 -1
- package/dist/types/collections.d.ts +29 -5
- package/dist/types/datasource.d.ts +3 -6
- 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 +14 -13
- package/dist/types/permissions.d.ts +5 -1
- package/dist/types/plugins.d.ts +20 -20
- package/dist/types/properties.d.ts +4 -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 -4
- package/dist/util/icons.d.ts +8 -2
- package/dist/util/navigation_utils.d.ts +2 -2
- package/dist/util/permissions.d.ts +4 -4
- package/dist/util/references.d.ts +4 -2
- package/dist/util/resolutions.d.ts +9 -13
- 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 +2 -2
- package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +275 -278
- package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +9 -5
- package/src/components/EntityCollectionTable/PropertyTableCell.tsx +44 -44
- package/src/components/EntityCollectionTable/column_utils.tsx +3 -3
- package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +9 -16
- package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +3 -3
- package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +27 -32
- package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +11 -6
- package/src/components/EntityCollectionTable/internal/default_entity_actions.tsx +9 -5
- package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +2 -4
- package/src/components/EntityCollectionView/EntityCollectionView.tsx +69 -64
- 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 +207 -70
- package/src/components/EntityView.tsx +84 -0
- package/src/components/FieldCaption.tsx +14 -0
- package/src/components/FireCMSAppBar.tsx +33 -11
- 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/ReferenceTable/ReferenceSelectionTable.tsx +4 -4
- package/src/components/ReferenceWidget.tsx +4 -4
- package/src/components/SearchIconsView.tsx +4 -4
- package/src/components/SelectableTable/SelectableTable.tsx +1 -1
- 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 +35 -24
- package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +35 -15
- package/src/components/VirtualTable/VirtualTable.tsx +28 -20
- package/src/components/VirtualTable/VirtualTableProps.tsx +1 -1
- package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +1 -1
- package/src/components/common/types.tsx +4 -6
- package/src/components/common/useDataSourceEntityCollectionTableController.tsx +12 -1
- package/src/components/index.tsx +4 -2
- package/src/contexts/AuthControllerContext.tsx +1 -1
- package/src/core/Drawer.tsx +66 -39
- package/src/core/{EntityView.tsx → EntityEditView.tsx} +21 -40
- package/src/core/EntitySidePanel.tsx +2 -2
- package/src/core/FireCMS.tsx +18 -3
- package/src/core/NavigationRoutes.tsx +11 -4
- package/src/core/Scaffold.tsx +5 -4
- package/src/core/field_configs.tsx +1 -2
- package/src/form/EntityForm.tsx +40 -21
- package/src/form/PropertyFieldBinding.tsx +0 -2
- package/src/form/components/StorageItemPreview.tsx +5 -3
- package/src/form/components/StorageUploadProgress.tsx +7 -6
- package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +8 -12
- package/src/form/field_bindings/DateTimeFieldBinding.tsx +1 -1
- package/src/form/field_bindings/KeyValueFieldBinding.tsx +15 -15
- package/src/form/field_bindings/MapFieldBinding.tsx +15 -15
- package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +1 -1
- package/src/form/field_bindings/ReferenceFieldBinding.tsx +1 -0
- package/src/form/field_bindings/StorageUploadFieldBinding.tsx +14 -5
- 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 +2 -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 +2 -0
- package/src/hooks/useBuildLocalConfigurationPersistence.tsx +9 -10
- package/src/hooks/useBuildModeController.tsx +11 -5
- package/src/hooks/useBuildNavigationController.tsx +199 -81
- package/src/hooks/useProjectLog.tsx +17 -7
- package/src/hooks/useReferenceDialog.tsx +2 -2
- package/src/hooks/useStorageSource.tsx +7 -2
- package/src/hooks/useValidateAuthenticator.tsx +115 -0
- package/src/internal/useBuildDataSource.ts +42 -44
- package/src/internal/useBuildSideEntityController.tsx +86 -20
- package/src/preview/PropertyPreview.tsx +3 -14
- package/src/preview/PropertyPreviewProps.tsx +1 -11
- package/src/preview/components/BooleanPreview.tsx +19 -4
- package/src/preview/components/EnumValuesChip.tsx +1 -1
- package/src/preview/components/ReferencePreview.tsx +55 -147
- package/src/preview/property_previews/ArrayOfMapsPreview.tsx +0 -1
- package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +0 -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 +0 -1
- package/src/preview/property_previews/ArrayPropertyPreview.tsx +0 -1
- 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 +33 -5
- package/src/types/datasource.ts +8 -5
- 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 -16
- package/src/types/permissions.ts +6 -1
- package/src/types/plugins.tsx +26 -28
- package/src/types/properties.ts +8 -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/icon_list.ts +2 -2
- package/src/util/icon_synonyms.ts +1 -4
- package/src/util/icons.tsx +11 -3
- package/src/util/navigation_utils.ts +6 -6
- package/src/util/objects.ts +0 -14
- package/src/util/permissions.ts +11 -8
- package/src/util/references.ts +36 -5
- package/src/util/resolutions.ts +6 -24
- package/src/util/strings.ts +2 -2
- package/src/util/useTraceUpdate.tsx +2 -1
- package/dist/core/SideEntityView.d.ts +0 -7
- 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/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
|
|
@@ -74,6 +73,8 @@ import {
|
|
|
74
73
|
} from "../EntityCollectionTable/internal/default_entity_actions";
|
|
75
74
|
import { DeleteEntityDialog } from "../DeleteEntityDialog";
|
|
76
75
|
import { useAnalyticsController } from "../../hooks/useAnalyticsController";
|
|
76
|
+
import { useSelectionController } from "./useSelectionController";
|
|
77
|
+
import { EntityCollectionViewStartActions } from "./EntityCollectionViewStartActions";
|
|
77
78
|
|
|
78
79
|
const COLLECTION_GROUP_PARENT_ID = "collectionGroupParent";
|
|
79
80
|
|
|
@@ -81,10 +82,22 @@ const COLLECTION_GROUP_PARENT_ID = "collectionGroupParent";
|
|
|
81
82
|
* @group Components
|
|
82
83
|
*/
|
|
83
84
|
export type EntityCollectionViewProps<M extends Record<string, any>> = {
|
|
84
|
-
|
|
85
|
+
/**
|
|
86
|
+
* Complete path where this collection is located.
|
|
87
|
+
* It defaults to the collection path if not provided.
|
|
88
|
+
*/
|
|
89
|
+
fullPath?: string;
|
|
90
|
+
/**
|
|
91
|
+
* If this is a subcollection, specify the parent collection ids.
|
|
92
|
+
*/
|
|
85
93
|
parentCollectionIds?: string[];
|
|
94
|
+
/**
|
|
95
|
+
* Whether this is a subcollection or not.
|
|
96
|
+
*/
|
|
86
97
|
isSubCollection?: boolean;
|
|
98
|
+
|
|
87
99
|
className?: string;
|
|
100
|
+
|
|
88
101
|
} & EntityCollection<M>;
|
|
89
102
|
|
|
90
103
|
/**
|
|
@@ -113,7 +126,7 @@ export type EntityCollectionViewProps<M extends Record<string, any>> = {
|
|
|
113
126
|
*/
|
|
114
127
|
export const EntityCollectionView = React.memo(
|
|
115
128
|
function EntityCollectionView<M extends Record<string, any>>({
|
|
116
|
-
fullPath,
|
|
129
|
+
fullPath: fullPathProp,
|
|
117
130
|
parentCollectionIds,
|
|
118
131
|
isSubCollection,
|
|
119
132
|
className,
|
|
@@ -121,7 +134,9 @@ export const EntityCollectionView = React.memo(
|
|
|
121
134
|
}: EntityCollectionViewProps<M>
|
|
122
135
|
) {
|
|
123
136
|
|
|
124
|
-
const
|
|
137
|
+
const context = useFireCMSContext();
|
|
138
|
+
const fullPath = fullPathProp ?? collectionProp.path;
|
|
139
|
+
const dataSource = useDataSource(collectionProp);
|
|
125
140
|
const navigation = useNavigationController();
|
|
126
141
|
const sideEntityController = useSideEntityController();
|
|
127
142
|
const authController = useAuthController();
|
|
@@ -141,7 +156,7 @@ export const EntityCollectionView = React.memo(
|
|
|
141
156
|
collectionRef.current = collection;
|
|
142
157
|
}, [collection]);
|
|
143
158
|
|
|
144
|
-
const canCreateEntities = canCreateEntity(collection, authController,
|
|
159
|
+
const canCreateEntities = canCreateEntity(collection, authController, fullPath, null);
|
|
145
160
|
const [selectedNavigationEntity, setSelectedNavigationEntity] = useState<Entity<M> | undefined>(undefined);
|
|
146
161
|
const [deleteEntityClicked, setDeleteEntityClicked] = React.useState<Entity<M> | Entity<M>[] | undefined>(undefined);
|
|
147
162
|
|
|
@@ -160,7 +175,7 @@ export const EntityCollectionView = React.memo(
|
|
|
160
175
|
|
|
161
176
|
const checkInlineEditing = useCallback((entity?: Entity<any>): boolean => {
|
|
162
177
|
const collection = collectionRef.current;
|
|
163
|
-
if (!canEditEntity(collection, authController,
|
|
178
|
+
if (!canEditEntity(collection, authController, fullPath, entity ?? null)) {
|
|
164
179
|
return false;
|
|
165
180
|
}
|
|
166
181
|
return collection.inlineEditing === undefined || collection.inlineEditing;
|
|
@@ -175,7 +190,6 @@ export const EntityCollectionView = React.memo(
|
|
|
175
190
|
const usedSelectionController = collection.selectionController ?? selectionController;
|
|
176
191
|
const {
|
|
177
192
|
selectedEntities,
|
|
178
|
-
toggleEntitySelection,
|
|
179
193
|
isEntitySelected,
|
|
180
194
|
setSelectedEntities
|
|
181
195
|
} = usedSelectionController;
|
|
@@ -186,8 +200,7 @@ export const EntityCollectionView = React.memo(
|
|
|
186
200
|
|
|
187
201
|
const tableController = useDataSourceEntityCollectionTableController<M>({
|
|
188
202
|
fullPath,
|
|
189
|
-
collection
|
|
190
|
-
entitiesDisplayedFirst: [],
|
|
203
|
+
collection,
|
|
191
204
|
lastDeleteTimestamp
|
|
192
205
|
});
|
|
193
206
|
|
|
@@ -199,6 +212,7 @@ export const EntityCollectionView = React.memo(
|
|
|
199
212
|
}, [tableController.setPopupCell]);
|
|
200
213
|
|
|
201
214
|
const onEntityClick = useCallback((clickedEntity: Entity<M>) => {
|
|
215
|
+
console.log("Entity clicked", clickedEntity)
|
|
202
216
|
const collection = collectionRef.current;
|
|
203
217
|
setSelectedNavigationEntity(clickedEntity);
|
|
204
218
|
analyticsController.onAnalyticsEvent?.("edit_entity_clicked", {
|
|
@@ -210,9 +224,9 @@ export const EntityCollectionView = React.memo(
|
|
|
210
224
|
path: clickedEntity.path,
|
|
211
225
|
collection,
|
|
212
226
|
updateUrl: true,
|
|
213
|
-
onClose: unselectNavigatedEntity
|
|
227
|
+
onClose: unselectNavigatedEntity,
|
|
214
228
|
});
|
|
215
|
-
}, [unselectNavigatedEntity]);
|
|
229
|
+
}, [unselectNavigatedEntity, sideEntityController]);
|
|
216
230
|
|
|
217
231
|
const onNewClick = useCallback(() => {
|
|
218
232
|
|
|
@@ -224,9 +238,9 @@ export const EntityCollectionView = React.memo(
|
|
|
224
238
|
path: fullPath,
|
|
225
239
|
collection,
|
|
226
240
|
updateUrl: true,
|
|
227
|
-
onClose: unselectNavigatedEntity
|
|
241
|
+
onClose: unselectNavigatedEntity,
|
|
228
242
|
});
|
|
229
|
-
}, [fullPath]);
|
|
243
|
+
}, [fullPath, sideEntityController]);
|
|
230
244
|
|
|
231
245
|
const onMultipleDeleteClick = () => {
|
|
232
246
|
analyticsController.onAnalyticsEvent?.("multiple_delete_dialog_open", {
|
|
@@ -288,7 +302,7 @@ export const EntityCollectionView = React.memo(
|
|
|
288
302
|
onCollectionModifiedForUser(fullPath, { defaultSize: size })
|
|
289
303
|
}, [onCollectionModifiedForUser, fullPath, userConfigPersistence]);
|
|
290
304
|
|
|
291
|
-
const createEnabled = canCreateEntity(collection, authController,
|
|
305
|
+
const createEnabled = canCreateEntity(collection, authController, fullPath, null);
|
|
292
306
|
|
|
293
307
|
const uniqueFieldValidator: UniqueFieldValidator = useCallback(
|
|
294
308
|
({
|
|
@@ -300,13 +314,11 @@ export const EntityCollectionView = React.memo(
|
|
|
300
314
|
[fullPath]);
|
|
301
315
|
|
|
302
316
|
const onValueChange: OnCellValueChange<any, any> = ({
|
|
303
|
-
fullPath,
|
|
304
|
-
context,
|
|
305
317
|
value,
|
|
306
318
|
propertyKey,
|
|
307
319
|
onValueUpdated,
|
|
308
320
|
setError,
|
|
309
|
-
entity,
|
|
321
|
+
data: entity,
|
|
310
322
|
}) => {
|
|
311
323
|
|
|
312
324
|
const updatedValues = setIn({ ...entity.values }, propertyKey, value);
|
|
@@ -323,10 +335,12 @@ export const EntityCollectionView = React.memo(
|
|
|
323
335
|
return saveEntityWithCallbacks({
|
|
324
336
|
...saveProps,
|
|
325
337
|
collection,
|
|
326
|
-
callbacks: collection.callbacks,
|
|
327
338
|
dataSource,
|
|
328
339
|
context,
|
|
329
|
-
onSaveSuccess: () =>
|
|
340
|
+
onSaveSuccess: () => {
|
|
341
|
+
setError(undefined);
|
|
342
|
+
onValueUpdated();
|
|
343
|
+
},
|
|
330
344
|
onSaveFailure: (e: Error) => {
|
|
331
345
|
console.error("Save failure");
|
|
332
346
|
console.error(e);
|
|
@@ -345,7 +359,6 @@ export const EntityCollectionView = React.memo(
|
|
|
345
359
|
|
|
346
360
|
const getPropertyFor = useCallback(({
|
|
347
361
|
propertyKey,
|
|
348
|
-
propertyValue,
|
|
349
362
|
entity
|
|
350
363
|
}: GetPropertyForProps<M>) => {
|
|
351
364
|
let propertyOrBuilder: PropertyOrBuilder<any, M> | undefined = getPropertyInPath<M>(collection.properties, propertyKey);
|
|
@@ -360,7 +373,6 @@ export const EntityCollectionView = React.memo(
|
|
|
360
373
|
propertyKey,
|
|
361
374
|
propertyOrBuilder,
|
|
362
375
|
path: fullPath,
|
|
363
|
-
propertyValue,
|
|
364
376
|
values: entity.values,
|
|
365
377
|
entityId: entity.id,
|
|
366
378
|
fields: customizationController.propertyConfigs
|
|
@@ -387,7 +399,7 @@ export const EntityCollectionView = React.memo(
|
|
|
387
399
|
entityId: entity.id,
|
|
388
400
|
selectedSubPath: subcollection.id ?? subcollection.path,
|
|
389
401
|
collection,
|
|
390
|
-
updateUrl: true
|
|
402
|
+
updateUrl: true,
|
|
391
403
|
});
|
|
392
404
|
}}>
|
|
393
405
|
{subcollection.name}
|
|
@@ -425,7 +437,7 @@ export const EntityCollectionView = React.memo(
|
|
|
425
437
|
...subcollectionColumns,
|
|
426
438
|
...collectionGroupParentCollections
|
|
427
439
|
];
|
|
428
|
-
}, [collection, fullPath]);
|
|
440
|
+
}, [collection, fullPath, sideEntityController]);
|
|
429
441
|
|
|
430
442
|
const updateLastDeleteTimestamp = useCallback(() => {
|
|
431
443
|
setLastDeleteTimestamp(Date.now());
|
|
@@ -433,11 +445,14 @@ export const EntityCollectionView = React.memo(
|
|
|
433
445
|
|
|
434
446
|
const largeLayout = useLargeLayout();
|
|
435
447
|
|
|
436
|
-
const getActionsForEntity = ({
|
|
448
|
+
const getActionsForEntity = ({
|
|
449
|
+
entity,
|
|
450
|
+
customEntityActions
|
|
451
|
+
}: {
|
|
437
452
|
entity?: Entity<M>,
|
|
438
453
|
customEntityActions?: EntityAction[]
|
|
439
454
|
}): EntityAction[] => {
|
|
440
|
-
const deleteEnabled = entity ? canDeleteEntity(collection, authController,
|
|
455
|
+
const deleteEnabled = entity ? canDeleteEntity(collection, authController, fullPath, entity) : true;
|
|
441
456
|
const actions: EntityAction[] = [editEntityAction];
|
|
442
457
|
if (createEnabled)
|
|
443
458
|
actions.push(copyEntityAction);
|
|
@@ -448,13 +463,13 @@ export const EntityCollectionView = React.memo(
|
|
|
448
463
|
return actions;
|
|
449
464
|
};
|
|
450
465
|
|
|
451
|
-
const getIdColumnWidth =
|
|
466
|
+
const getIdColumnWidth = () => {
|
|
452
467
|
const entityActions = getActionsForEntity({});
|
|
453
468
|
const collapsedActions = entityActions.filter(a => a.collapsed !== false);
|
|
454
469
|
const uncollapsedActions = entityActions.filter(a => a.collapsed === false);
|
|
455
470
|
const actionsWidth = uncollapsedActions.length * (largeLayout ? 40 : 30);
|
|
456
471
|
return (largeLayout ? (80 + actionsWidth) : (70 + actionsWidth)) + (collapsedActions.length > 0 ? (largeLayout ? 40 : 30) : 0);
|
|
457
|
-
}
|
|
472
|
+
};
|
|
458
473
|
|
|
459
474
|
const tableRowActionsBuilder = ({
|
|
460
475
|
entity,
|
|
@@ -470,7 +485,10 @@ export const EntityCollectionView = React.memo(
|
|
|
470
485
|
|
|
471
486
|
const isSelected = isEntitySelected(entity);
|
|
472
487
|
|
|
473
|
-
const actions = getActionsForEntity({
|
|
488
|
+
const actions = getActionsForEntity({
|
|
489
|
+
entity,
|
|
490
|
+
customEntityActions: collection.entityActions
|
|
491
|
+
});
|
|
474
492
|
|
|
475
493
|
return (
|
|
476
494
|
<EntityCollectionRowActions
|
|
@@ -577,12 +595,13 @@ export const EntityCollectionView = React.memo(
|
|
|
577
595
|
});
|
|
578
596
|
|
|
579
597
|
return (
|
|
580
|
-
<div className={cn("overflow-hidden h-full w-full", className)}
|
|
598
|
+
<div className={cn("overflow-hidden h-full w-full rounded-md", className)}
|
|
581
599
|
ref={containerRef}>
|
|
582
600
|
<EntityCollectionTable
|
|
583
601
|
key={`collection_table_${fullPath}`}
|
|
584
602
|
additionalFields={additionalFields}
|
|
585
603
|
tableController={tableController}
|
|
604
|
+
enablePopupIcon={true}
|
|
586
605
|
displayedColumnIds={displayedColumnIds}
|
|
587
606
|
onSizeChanged={onSizeChanged}
|
|
588
607
|
onEntityClick={onEntityClick}
|
|
@@ -599,6 +618,14 @@ export const EntityCollectionView = React.memo(
|
|
|
599
618
|
onTextSearchClick={textSearchInitialised ? undefined : onTextSearchClick}
|
|
600
619
|
textSearchLoading={textSearchLoading}
|
|
601
620
|
textSearchEnabled={textSearchEnabled}
|
|
621
|
+
actionsStart={<EntityCollectionViewStartActions
|
|
622
|
+
parentCollectionIds={parentCollectionIds ?? []}
|
|
623
|
+
collection={collection}
|
|
624
|
+
tableController={tableController}
|
|
625
|
+
path={fullPath}
|
|
626
|
+
relativePath={collection.path}
|
|
627
|
+
selectionController={usedSelectionController}
|
|
628
|
+
collectionEntitiesCount={docsCount}/>}
|
|
602
629
|
actions={<EntityCollectionViewActions
|
|
603
630
|
parentCollectionIds={parentCollectionIds ?? []}
|
|
604
631
|
collection={collection}
|
|
@@ -676,39 +703,14 @@ export const EntityCollectionView = React.memo(
|
|
|
676
703
|
equal(a.selectionController, b.selectionController) &&
|
|
677
704
|
equal(a.Actions, b.Actions) &&
|
|
678
705
|
equal(a.defaultSize, b.defaultSize) &&
|
|
706
|
+
equal(a.initialFilter, b.initialFilter) &&
|
|
707
|
+
equal(a.initialSort, b.initialSort) &&
|
|
679
708
|
equal(a.textSearchEnabled, b.textSearchEnabled) &&
|
|
680
709
|
equal(a.additionalFields, b.additionalFields) &&
|
|
710
|
+
equal(a.sideDialogWidth, b.sideDialogWidth) &&
|
|
681
711
|
equal(a.forceFilter, b.forceFilter);
|
|
682
712
|
}) as React.FunctionComponent<EntityCollectionViewProps<any>>
|
|
683
713
|
|
|
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
714
|
function EntitiesCount({
|
|
713
715
|
fullPath,
|
|
714
716
|
collection,
|
|
@@ -723,7 +725,7 @@ function EntitiesCount({
|
|
|
723
725
|
onCountChange?: (count: number) => void,
|
|
724
726
|
}) {
|
|
725
727
|
|
|
726
|
-
const dataSource = useDataSource();
|
|
728
|
+
const dataSource = useDataSource(collection);
|
|
727
729
|
const navigation = useNavigationController();
|
|
728
730
|
const [count, setCount] = useState<number | undefined>(undefined);
|
|
729
731
|
const [error, setError] = useState<Error | undefined>(undefined);
|
|
@@ -745,6 +747,7 @@ function EntitiesCount({
|
|
|
745
747
|
|
|
746
748
|
useEffect(() => {
|
|
747
749
|
if (onCountChange) {
|
|
750
|
+
setError(undefined);
|
|
748
751
|
onCountChange(count ?? 0);
|
|
749
752
|
}
|
|
750
753
|
}, [onCountChange, count]);
|
|
@@ -796,10 +799,10 @@ function EntityIdHeaderWidget({
|
|
|
796
799
|
if (!searchString) return;
|
|
797
800
|
setOpenPopup(false);
|
|
798
801
|
return sideEntityController.open({
|
|
799
|
-
entityId: searchString,
|
|
802
|
+
entityId: searchString.trim(),
|
|
800
803
|
path,
|
|
801
804
|
collection,
|
|
802
|
-
updateUrl: true
|
|
805
|
+
updateUrl: true,
|
|
803
806
|
});
|
|
804
807
|
}}
|
|
805
808
|
className={"text-gray-900 dark:text-white w-96 max-w-full"}>
|
|
@@ -809,11 +812,13 @@ function EntityIdHeaderWidget({
|
|
|
809
812
|
autoFocus={openPopup}
|
|
810
813
|
placeholder={"Find entity by ID"}
|
|
811
814
|
// size={"small"}
|
|
812
|
-
onChange={(e) =>
|
|
815
|
+
onChange={(e) => {
|
|
816
|
+
setSearchString(e.target.value);
|
|
817
|
+
}}
|
|
813
818
|
value={searchString}
|
|
814
819
|
className={"flex-grow bg-transparent outline-none p-1"}/>
|
|
815
820
|
<Button variant={"outlined"}
|
|
816
|
-
disabled={!searchString}
|
|
821
|
+
disabled={!(searchString.trim())}
|
|
817
822
|
type={"submit"}
|
|
818
823
|
>Go</Button>
|
|
819
824
|
</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
|
+
}
|