@firecms/core 3.0.0-beta.11 → 3.0.0-beta.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app/Scaffold.d.ts +4 -0
- package/dist/components/ArrayContainer.d.ts +14 -3
- 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 +15 -1
- package/dist/components/EntityCollectionTable/index.d.ts +1 -1
- package/dist/components/EntityCollectionView/EntityCollectionView.d.ts +8 -0
- package/dist/components/EntityJsonPreview.d.ts +3 -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/DefaultAppBar.d.ts +8 -2
- package/dist/core/EntityEditView.d.ts +36 -21
- package/dist/core/EntityEditViewFormActions.d.ts +2 -0
- package/dist/core/FireCMS.d.ts +2 -2
- 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 +49 -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 -0
- 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/RepeatFieldBinding.d.ts +1 -1
- package/dist/form/index.d.ts +16 -16
- package/dist/hooks/data/save.d.ts +1 -1
- package/dist/hooks/data/useEntityFetch.d.ts +2 -1
- package/dist/hooks/useBreadcrumbsController.d.ts +26 -0
- package/dist/hooks/useBuildNavigationController.d.ts +4 -1
- package/dist/hooks/useModeController.d.ts +1 -2
- package/dist/index.es.js +15842 -14396
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +15833 -14389
- package/dist/index.umd.js.map +1 -1
- package/dist/internal/useBuildDataSource.d.ts +3 -2
- package/dist/internal/useBuildSideEntityController.d.ts +3 -3
- package/dist/internal/useUnsavedChangesDialog.d.ts +7 -9
- 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/collections.d.ts +36 -10
- package/dist/types/datasource.d.ts +2 -2
- package/dist/types/dialogs_controller.d.ts +7 -3
- package/dist/types/entities.d.ts +1 -1
- package/dist/types/entity_actions.d.ts +10 -0
- package/dist/types/fields.d.ts +13 -3
- package/dist/types/firecms.d.ts +1 -1
- package/dist/types/navigation.d.ts +33 -12
- package/dist/types/plugins.d.ts +2 -0
- package/dist/types/properties.d.ts +40 -4
- package/dist/types/side_entity_controller.d.ts +6 -1
- package/dist/util/builders.d.ts +1 -1
- package/dist/util/createFormexStub.d.ts +2 -0
- package/dist/util/entity_actions.d.ts +2 -0
- package/dist/util/entity_cache.d.ts +23 -0
- 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 +13 -1
- package/dist/util/objects.d.ts +1 -1
- package/dist/util/property_utils.d.ts +2 -2
- package/dist/util/references.d.ts +2 -2
- package/dist/util/resolutions.d.ts +12 -2
- package/package.json +20 -21
- package/src/app/Scaffold.tsx +13 -3
- package/src/components/ArrayContainer.tsx +60 -24
- package/src/components/CircularProgressCenter.tsx +1 -1
- package/src/components/DeleteEntityDialog.tsx +5 -3
- package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +46 -23
- package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +10 -4
- package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +18 -1
- package/src/components/EntityCollectionTable/index.tsx +1 -1
- package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +3 -3
- package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +10 -13
- package/src/components/EntityCollectionView/EntityCollectionView.tsx +105 -47
- package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +4 -2
- package/src/components/EntityJsonPreview.tsx +66 -0
- package/src/components/EntityPreview.tsx +10 -3
- package/src/components/EntityView.tsx +4 -1
- package/src/components/NotFoundPage.tsx +2 -2
- package/src/components/PropertyIdCopyTooltip.tsx +2 -3
- package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +14 -7
- package/src/components/SelectableTable/SelectableTable.tsx +18 -3
- package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +7 -7
- package/src/components/UnsavedChangesDialog.tsx +42 -0
- package/src/components/VirtualTable/VirtualTable.tsx +48 -3
- package/src/components/VirtualTable/VirtualTableProps.tsx +15 -0
- package/src/components/VirtualTable/fields/VirtualTableInput.tsx +1 -1
- package/src/components/common/default_entity_actions.tsx +37 -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/core/DefaultAppBar.tsx +59 -17
- package/src/core/DefaultDrawer.tsx +1 -1
- package/src/core/EntityEditView.tsx +354 -1000
- package/src/core/EntityEditViewFormActions.tsx +199 -0
- package/src/core/EntitySidePanel.tsx +85 -15
- package/src/core/FireCMS.tsx +20 -16
- package/src/core/FireCMSRouter.tsx +17 -0
- package/src/core/NavigationRoutes.tsx +23 -32
- package/src/core/SideDialogs.tsx +20 -11
- package/src/core/index.tsx +4 -2
- package/src/form/EntityForm.tsx +782 -0
- package/src/form/EntityFormActions.tsx +169 -0
- package/src/form/PropertyFieldBinding.tsx +21 -16
- 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/StorageUploadProgress.tsx +1 -1
- package/src/form/components/index.tsx +2 -0
- package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +8 -5
- package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +5 -2
- package/src/form/field_bindings/BlockFieldBinding.tsx +5 -3
- package/src/form/field_bindings/DateTimeFieldBinding.tsx +1 -0
- package/src/form/field_bindings/KeyValueFieldBinding.tsx +1 -1
- package/src/form/field_bindings/MapFieldBinding.tsx +14 -16
- package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +15 -8
- package/src/form/field_bindings/MultiSelectFieldBinding.tsx +3 -3
- package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +2 -2
- package/src/form/field_bindings/ReferenceFieldBinding.tsx +1 -1
- package/src/form/field_bindings/RepeatFieldBinding.tsx +13 -4
- package/src/form/field_bindings/SelectFieldBinding.tsx +2 -2
- package/src/form/field_bindings/StorageUploadFieldBinding.tsx +11 -6
- package/src/form/field_bindings/SwitchFieldBinding.tsx +1 -0
- package/src/form/field_bindings/TextFieldBinding.tsx +1 -0
- package/src/form/index.tsx +16 -32
- package/src/form/validation.ts +12 -6
- package/src/hooks/data/save.ts +25 -30
- package/src/hooks/data/useCollectionFetch.tsx +1 -1
- package/src/hooks/data/useEntityFetch.tsx +5 -1
- package/src/hooks/useBreadcrumbsController.tsx +31 -0
- package/src/hooks/useBuildModeController.tsx +15 -28
- package/src/hooks/useBuildNavigationController.tsx +81 -24
- package/src/hooks/useFireCMSContext.tsx +0 -30
- package/src/hooks/useLargeLayout.tsx +0 -35
- package/src/hooks/useModeController.tsx +1 -2
- package/src/hooks/useResolvedNavigationFrom.tsx +4 -6
- package/src/internal/useBuildDataSource.ts +9 -5
- package/src/internal/useBuildSideDialogsController.tsx +3 -2
- package/src/internal/useBuildSideEntityController.tsx +135 -88
- package/src/internal/useUnsavedChangesDialog.tsx +126 -92
- package/src/preview/PropertyPreview.tsx +12 -10
- package/src/preview/components/UrlComponentPreview.tsx +17 -18
- package/src/preview/property_previews/ArrayOfMapsPreview.tsx +4 -3
- package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +4 -3
- package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +4 -2
- package/src/preview/property_previews/ArrayOfStringsPreview.tsx +4 -3
- package/src/preview/property_previews/ArrayOneOfPreview.tsx +4 -2
- package/src/preview/property_previews/ArrayPropertyPreview.tsx +4 -2
- package/src/preview/property_previews/MapPropertyPreview.tsx +3 -2
- package/src/routes/CustomCMSRoute.tsx +21 -0
- package/src/routes/FireCMSRoute.tsx +246 -0
- package/src/routes/HomePageRoute.tsx +17 -0
- package/src/types/collections.ts +45 -13
- package/src/types/datasource.ts +2 -1
- package/src/types/dialogs_controller.tsx +7 -3
- package/src/types/entities.ts +1 -1
- package/src/types/entity_actions.tsx +12 -0
- package/src/types/fields.tsx +18 -3
- package/src/types/firecms.tsx +1 -1
- package/src/types/navigation.ts +41 -16
- package/src/types/plugins.tsx +2 -0
- package/src/types/properties.ts +48 -4
- package/src/types/side_dialogs_controller.tsx +2 -0
- package/src/types/side_entity_controller.tsx +11 -1
- package/src/util/builders.ts +5 -3
- package/src/util/createFormexStub.tsx +62 -0
- package/src/util/entity_actions.ts +28 -0
- package/src/util/entity_cache.ts +204 -0
- package/src/util/index.ts +1 -0
- package/src/util/join_collections.ts +6 -1
- package/src/util/navigation_from_path.ts +18 -7
- package/src/util/navigation_utils.ts +115 -14
- package/src/util/objects.ts +9 -2
- package/src/util/parent_references_from_path.ts +3 -3
- package/src/util/property_utils.tsx +7 -3
- package/src/util/references.ts +8 -6
- package/src/util/resolutions.ts +41 -12
- package/src/util/useStorageUploadController.tsx +60 -23
- package/src/components/common/useDataSourceEntityCollectionTableController.tsx +0 -236
- /package/src/util/{common.tsx → common.ts} +0 -0
|
@@ -4,7 +4,7 @@ import { useCallback, useState } from "react";
|
|
|
4
4
|
export function PropertyIdCopyTooltip({
|
|
5
5
|
propertyKey,
|
|
6
6
|
className,
|
|
7
|
-
children
|
|
7
|
+
children,
|
|
8
8
|
}: {
|
|
9
9
|
propertyKey: string,
|
|
10
10
|
className?: string,
|
|
@@ -13,11 +13,10 @@ export function PropertyIdCopyTooltip({
|
|
|
13
13
|
return <Tooltip title={<PropertyIdCopyTooltipContent propertyKey={propertyKey}/>}
|
|
14
14
|
delayDuration={800}
|
|
15
15
|
side={"top"}
|
|
16
|
-
asChild={false}
|
|
17
16
|
align={"start"}
|
|
18
17
|
sideOffset={8}
|
|
19
18
|
className={className}>
|
|
20
|
-
|
|
19
|
+
{children}
|
|
21
20
|
</Tooltip>
|
|
22
21
|
|
|
23
22
|
}
|
|
@@ -4,7 +4,7 @@ import { CollectionSize, Entity, EntityCollection, FilterValues } from "../../ty
|
|
|
4
4
|
import {
|
|
5
5
|
EntityCollectionRowActions,
|
|
6
6
|
EntityCollectionTable,
|
|
7
|
-
|
|
7
|
+
useDataSourceTableController
|
|
8
8
|
} from "../EntityCollectionTable";
|
|
9
9
|
import {
|
|
10
10
|
useAuthController,
|
|
@@ -101,13 +101,14 @@ export function ReferenceSelectionTable<M extends Record<string, any>>(
|
|
|
101
101
|
maxSelection,
|
|
102
102
|
}: ReferenceSelectionInnerProps<M>) {
|
|
103
103
|
|
|
104
|
+
const authController = useAuthController();
|
|
104
105
|
const sideDialogContext = useSideDialogContext();
|
|
105
106
|
const sideEntityController = useSideEntityController();
|
|
106
107
|
const navigation = useNavigationController();
|
|
107
108
|
const analyticsController = useAnalyticsController();
|
|
108
109
|
const customizationController = useCustomizationController();
|
|
109
110
|
|
|
110
|
-
const fullPath = navigation.
|
|
111
|
+
const fullPath = navigation.resolveIdsFrom(pathInput);
|
|
111
112
|
|
|
112
113
|
const dataSource = useDataSource(collection);
|
|
113
114
|
|
|
@@ -233,7 +234,9 @@ export function ReferenceSelectionTable<M extends Record<string, any>>(
|
|
|
233
234
|
selectionEnabled={multiselect}
|
|
234
235
|
hideId={collection?.hideIdFromCollection}
|
|
235
236
|
fullPath={fullPath}
|
|
236
|
-
selectionController={selectionController}
|
|
237
|
+
selectionController={selectionController}
|
|
238
|
+
openEntityMode={"side_panel"}
|
|
239
|
+
/>;
|
|
237
240
|
|
|
238
241
|
};
|
|
239
242
|
|
|
@@ -251,16 +254,18 @@ export function ReferenceSelectionTable<M extends Record<string, any>>(
|
|
|
251
254
|
collection: collection,
|
|
252
255
|
path: fullPath,
|
|
253
256
|
values: {},
|
|
254
|
-
propertyConfigs: customizationController.propertyConfigs
|
|
257
|
+
propertyConfigs: customizationController.propertyConfigs,
|
|
258
|
+
authController
|
|
255
259
|
}), [collection, customizationController.propertyConfigs, fullPath]);
|
|
256
260
|
|
|
257
261
|
const displayedColumnIds = useColumnIds(resolvedCollection, false);
|
|
258
262
|
|
|
259
|
-
const tableController =
|
|
263
|
+
const tableController = useDataSourceTableController<M>({
|
|
260
264
|
fullPath,
|
|
261
265
|
collection,
|
|
262
266
|
entitiesDisplayedFirst,
|
|
263
|
-
forceFilter
|
|
267
|
+
forceFilter,
|
|
268
|
+
updateUrl: false,
|
|
264
269
|
});
|
|
265
270
|
|
|
266
271
|
const {
|
|
@@ -289,12 +294,14 @@ export function ReferenceSelectionTable<M extends Record<string, any>>(
|
|
|
289
294
|
tableController={tableController}
|
|
290
295
|
enablePopupIcon={false}
|
|
291
296
|
tableRowActionsBuilder={tableRowActionsBuilder}
|
|
297
|
+
openEntityMode={"side_panel"}
|
|
292
298
|
title={<Typography variant={"subtitle2"} className={"flex flex-row gap-2"}>
|
|
293
299
|
<IconForView
|
|
294
300
|
size={"small"}
|
|
295
301
|
collectionOrView={collection}
|
|
296
302
|
className={"text-surface-300 dark:text-surface-600"}/>
|
|
297
|
-
{collection.singularName ? `Select ${collection.singularName}` : `Select
|
|
303
|
+
{collection.singularName ? `Select ${collection.singularName}` : `Select
|
|
304
|
+
from ${collection.name}`}
|
|
298
305
|
</Typography>}
|
|
299
306
|
defaultSize={collection.defaultSize}
|
|
300
307
|
properties={resolvedCollection.properties}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import React, { useCallback, useEffect, useRef } from "react";
|
|
2
|
-
import equal from "react-fast-compare";
|
|
3
2
|
import {
|
|
4
3
|
CollectionSize,
|
|
5
4
|
Entity,
|
|
@@ -60,7 +59,7 @@ export type SelectableTableProps<M extends Record<string, any>> = {
|
|
|
60
59
|
|
|
61
60
|
/**
|
|
62
61
|
* Controller holding the logic for the table
|
|
63
|
-
* {@link
|
|
62
|
+
* {@link useDataSourceTableController}
|
|
64
63
|
* {@link EntityTableController}
|
|
65
64
|
*/
|
|
66
65
|
tableController: EntityTableController<M>;
|
|
@@ -77,6 +76,18 @@ export type SelectableTableProps<M extends Record<string, any>> = {
|
|
|
77
76
|
|
|
78
77
|
size?: CollectionSize;
|
|
79
78
|
|
|
79
|
+
initialScroll?: number;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Callback when the table is scrolled
|
|
83
|
+
* @param props
|
|
84
|
+
*/
|
|
85
|
+
onScroll?: (props: {
|
|
86
|
+
scrollDirection: "forward" | "backward",
|
|
87
|
+
scrollOffset: number,
|
|
88
|
+
scrollUpdateWasRequested: boolean
|
|
89
|
+
}) => void;
|
|
90
|
+
|
|
80
91
|
emptyComponent?: React.ReactNode;
|
|
81
92
|
|
|
82
93
|
endAdornment?: React.ReactNode;
|
|
@@ -101,7 +112,7 @@ export type SelectableTableProps<M extends Record<string, any>> = {
|
|
|
101
112
|
*
|
|
102
113
|
* The data displayed in the table is managed by a {@link EntityTableController}.
|
|
103
114
|
* You can build the default, bound to a path in the datasource, by using the hook
|
|
104
|
-
* {@link
|
|
115
|
+
* {@link useDataSourceTableController}
|
|
105
116
|
*
|
|
106
117
|
* @see EntityCollectionTableProps
|
|
107
118
|
* @see EntityCollectionView
|
|
@@ -136,6 +147,8 @@ export const SelectableTable = React.memo<SelectableTableProps<any>>(
|
|
|
136
147
|
setPopupCell
|
|
137
148
|
},
|
|
138
149
|
filterable = true,
|
|
150
|
+
onScroll,
|
|
151
|
+
initialScroll,
|
|
139
152
|
emptyComponent,
|
|
140
153
|
columns,
|
|
141
154
|
forceFilter,
|
|
@@ -229,6 +242,8 @@ export const SelectableTable = React.memo<SelectableTableProps<any>>(
|
|
|
229
242
|
sortBy={sortBy}
|
|
230
243
|
onSortByUpdate={setSortBy as ((sortBy?: [string, "asc" | "desc"]) => void)}
|
|
231
244
|
hoverRow={hoverRow}
|
|
245
|
+
initialScroll={initialScroll}
|
|
246
|
+
onScroll={onScroll}
|
|
232
247
|
checkFilterCombination={checkFilterCombination}
|
|
233
248
|
createFilterField={filterable ? createFilterField : undefined}
|
|
234
249
|
rowClassName={useCallback((entity: Entity<M>) => {
|
|
@@ -35,12 +35,10 @@ const operationLabels = {
|
|
|
35
35
|
const multipleSelectOperations = ["array-contains-any", "in", "not-in"];
|
|
36
36
|
|
|
37
37
|
export function ReferenceFilterField({
|
|
38
|
-
name,
|
|
39
38
|
value,
|
|
40
39
|
setValue,
|
|
41
40
|
isArray,
|
|
42
41
|
path,
|
|
43
|
-
title,
|
|
44
42
|
includeId = true,
|
|
45
43
|
previewProperties,
|
|
46
44
|
setHidden
|
|
@@ -50,9 +48,11 @@ export function ReferenceFilterField({
|
|
|
50
48
|
? ["array-contains"]
|
|
51
49
|
: ["==", "!=", ">", "<", ">=", "<="];
|
|
52
50
|
|
|
53
|
-
isArray
|
|
54
|
-
|
|
55
|
-
|
|
51
|
+
if (isArray) {
|
|
52
|
+
possibleOperations.push("array-contains-any");
|
|
53
|
+
} else {
|
|
54
|
+
possibleOperations.push("in", "not-in");
|
|
55
|
+
}
|
|
56
56
|
|
|
57
57
|
const [fieldOperation, fieldValue] = value || [possibleOperations[0], undefined];
|
|
58
58
|
const [operation, setOperation] = useState<VirtualTableWhereFilterOp>(fieldOperation);
|
|
@@ -144,7 +144,7 @@ export function ReferenceFilterField({
|
|
|
144
144
|
|
|
145
145
|
return (
|
|
146
146
|
|
|
147
|
-
<div className="flex w-[
|
|
147
|
+
<div className="flex w-[480px] flex-row">
|
|
148
148
|
<div className="w-[140px]">
|
|
149
149
|
<Select value={operation}
|
|
150
150
|
size={"large"}
|
|
@@ -161,7 +161,7 @@ export function ReferenceFilterField({
|
|
|
161
161
|
</Select>
|
|
162
162
|
</div>
|
|
163
163
|
|
|
164
|
-
<div className="flex-grow ml-2 h-full gap-2 flex flex-col">
|
|
164
|
+
<div className="flex-grow ml-2 h-full gap-2 flex flex-col w-[340px]">
|
|
165
165
|
|
|
166
166
|
{internalValue && Array.isArray(internalValue) && <div>
|
|
167
167
|
{internalValue.map((ref, index) => buildEntry(ref))}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Button, Dialog, DialogActions, DialogContent, DialogTitle, Typography } from "@firecms/ui";
|
|
2
|
+
|
|
3
|
+
export interface UnsavedChangesDialogProps {
|
|
4
|
+
open: boolean;
|
|
5
|
+
body?: React.ReactNode;
|
|
6
|
+
title?: string;
|
|
7
|
+
handleOk: () => void;
|
|
8
|
+
handleCancel: () => void;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function UnsavedChangesDialog({
|
|
12
|
+
open,
|
|
13
|
+
handleOk,
|
|
14
|
+
handleCancel,
|
|
15
|
+
body,
|
|
16
|
+
title
|
|
17
|
+
}: UnsavedChangesDialogProps) {
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<Dialog
|
|
21
|
+
onEscapeKeyDown={() => {
|
|
22
|
+
handleCancel();
|
|
23
|
+
}}
|
|
24
|
+
open={open}
|
|
25
|
+
>
|
|
26
|
+
<DialogTitle variant={"h6"}>{title}</DialogTitle>
|
|
27
|
+
<DialogContent>
|
|
28
|
+
|
|
29
|
+
{body}
|
|
30
|
+
|
|
31
|
+
<Typography>
|
|
32
|
+
Are you sure you want to leave this page?
|
|
33
|
+
</Typography>
|
|
34
|
+
|
|
35
|
+
</DialogContent>
|
|
36
|
+
<DialogActions>
|
|
37
|
+
<Button variant="text" onClick={handleCancel} autoFocus> Cancel </Button>
|
|
38
|
+
<Button onClick={handleOk}> Ok </Button>
|
|
39
|
+
</DialogActions>
|
|
40
|
+
</Dialog>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
@@ -20,6 +20,7 @@ import { VirtualTableHeaderRow } from "./VirtualTableHeaderRow";
|
|
|
20
20
|
import { VirtualTableRow } from "./VirtualTableRow";
|
|
21
21
|
import { VirtualTableCell } from "./VirtualTableCell";
|
|
22
22
|
import { AssignmentIcon, CenteredView, cls, Typography } from "@firecms/ui";
|
|
23
|
+
import { useDebounceCallback } from "../common/useDebouncedCallback";
|
|
23
24
|
|
|
24
25
|
const VirtualListContext = createContext<VirtualTableContextProps<any>>({} as any);
|
|
25
26
|
VirtualListContext.displayName = "VirtualListContext";
|
|
@@ -103,6 +104,7 @@ export const VirtualTable = React.memo<VirtualTableProps<any>>(
|
|
|
103
104
|
error,
|
|
104
105
|
emptyComponent,
|
|
105
106
|
onSortByUpdate,
|
|
107
|
+
onScroll: onScrollProp,
|
|
106
108
|
loading,
|
|
107
109
|
cellRenderer,
|
|
108
110
|
hoverRow,
|
|
@@ -112,6 +114,7 @@ export const VirtualTable = React.memo<VirtualTableProps<any>>(
|
|
|
112
114
|
className,
|
|
113
115
|
endAdornment,
|
|
114
116
|
AddColumnComponent,
|
|
117
|
+
initialScroll = 0,
|
|
115
118
|
debug
|
|
116
119
|
}: VirtualTableProps<T>) {
|
|
117
120
|
|
|
@@ -123,11 +126,48 @@ export const VirtualTable = React.memo<VirtualTableProps<any>>(
|
|
|
123
126
|
const tableRef = useRef<HTMLDivElement>(null);
|
|
124
127
|
const endReachCallbackThreshold = useRef<number>(0);
|
|
125
128
|
|
|
129
|
+
const debouncedScroll = useDebounceCallback(onScrollProp, 200);
|
|
130
|
+
|
|
131
|
+
// Set initial scroll position
|
|
132
|
+
useEffect(() => {
|
|
133
|
+
if (tableRef.current && initialScroll) {
|
|
134
|
+
tableRef.current.scrollTo(0, initialScroll);
|
|
135
|
+
}
|
|
136
|
+
}, [tableRef, initialScroll]);
|
|
137
|
+
|
|
126
138
|
useEffect(() => {
|
|
127
139
|
setColumns(columnsProp);
|
|
128
140
|
}, [columnsProp]);
|
|
129
141
|
|
|
130
|
-
const [
|
|
142
|
+
const [_, setForceUpdate] = useState(false);
|
|
143
|
+
useEffect(() => {
|
|
144
|
+
// Create a ResizeObserver to detect size changes more aggressively
|
|
145
|
+
if (tableRef.current) {
|
|
146
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
147
|
+
// Force a re-render when size changes
|
|
148
|
+
setForceUpdate(prev => !prev);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
resizeObserver.observe(tableRef.current);
|
|
152
|
+
|
|
153
|
+
return () => {
|
|
154
|
+
if (tableRef.current) {
|
|
155
|
+
resizeObserver.unobserve(tableRef.current);
|
|
156
|
+
}
|
|
157
|
+
resizeObserver.disconnect();
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
return () => {
|
|
161
|
+
}
|
|
162
|
+
}, [tableRef]);
|
|
163
|
+
|
|
164
|
+
const [measureRef, bounds] = useMeasure({
|
|
165
|
+
debounce: 50,
|
|
166
|
+
polyfill: ResizeObserver,
|
|
167
|
+
scroll: true,
|
|
168
|
+
// This is important for handling zooming in react-flow
|
|
169
|
+
offsetSize: true
|
|
170
|
+
});
|
|
131
171
|
|
|
132
172
|
const onColumnResizeInternal = useCallback((params: OnVirtualTableColumnResizeParams) => {
|
|
133
173
|
if (debug)
|
|
@@ -158,7 +198,6 @@ export const VirtualTable = React.memo<VirtualTableProps<any>>(
|
|
|
158
198
|
console.log("scrollToTop");
|
|
159
199
|
endReachCallbackThreshold.current = 0;
|
|
160
200
|
if (tableRef.current) {
|
|
161
|
-
// scrollRef.current = [scrollRef.current[0], 0];
|
|
162
201
|
tableRef.current.scrollTo(tableRef.current?.scrollLeft, 0);
|
|
163
202
|
}
|
|
164
203
|
}, []);
|
|
@@ -222,6 +261,13 @@ export const VirtualTable = React.memo<VirtualTableProps<any>>(
|
|
|
222
261
|
scrollOffset,
|
|
223
262
|
scrollUpdateWasRequested
|
|
224
263
|
});
|
|
264
|
+
if (onScrollProp) {
|
|
265
|
+
debouncedScroll({
|
|
266
|
+
scrollDirection,
|
|
267
|
+
scrollOffset,
|
|
268
|
+
scrollUpdateWasRequested
|
|
269
|
+
})
|
|
270
|
+
}
|
|
225
271
|
if (!scrollUpdateWasRequested && (scrollOffset >= maxScroll - endOffset))
|
|
226
272
|
onEndReachedInternal(scrollOffset);
|
|
227
273
|
}, [maxScroll, onEndReachedInternal]);
|
|
@@ -294,7 +340,6 @@ export const VirtualTable = React.memo<VirtualTableProps<any>>(
|
|
|
294
340
|
if (debug)
|
|
295
341
|
console.log("VirtualTable render", virtualListController);
|
|
296
342
|
|
|
297
|
-
// useTraceUpdate(virtualListController);
|
|
298
343
|
return (
|
|
299
344
|
<div
|
|
300
345
|
ref={measureRef}
|
|
@@ -82,6 +82,16 @@ export interface VirtualTableProps<T extends Record<string, any>> {
|
|
|
82
82
|
*/
|
|
83
83
|
onFilterUpdate?: (filter?: VirtualTableFilterValues<any> | undefined) => void;
|
|
84
84
|
|
|
85
|
+
/**
|
|
86
|
+
* Callback when the table is scrolled
|
|
87
|
+
* @param props
|
|
88
|
+
*/
|
|
89
|
+
onScroll?: (props: {
|
|
90
|
+
scrollDirection: "forward" | "backward",
|
|
91
|
+
scrollOffset: number,
|
|
92
|
+
scrollUpdateWasRequested: boolean
|
|
93
|
+
}) => void;
|
|
94
|
+
|
|
85
95
|
/**
|
|
86
96
|
* Default sort applied to this collection
|
|
87
97
|
*/
|
|
@@ -147,6 +157,11 @@ export interface VirtualTableProps<T extends Record<string, any>> {
|
|
|
147
157
|
*/
|
|
148
158
|
AddColumnComponent?: React.ComponentType;
|
|
149
159
|
|
|
160
|
+
/**
|
|
161
|
+
* Initial scroll position
|
|
162
|
+
*/
|
|
163
|
+
initialScroll?: number;
|
|
164
|
+
|
|
150
165
|
/**
|
|
151
166
|
* Debug mode
|
|
152
167
|
*/
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DeleteIcon, EditIcon, FileCopyIcon } from "@firecms/ui";
|
|
2
2
|
import { EntityAction } from "../../types";
|
|
3
3
|
import { DeleteEntityDialog } from "../DeleteEntityDialog";
|
|
4
4
|
import { addRecentId } from "../EntityCollectionView/utils";
|
|
5
|
+
import { navigateToEntity, resolveDefaultSelectedView } from "../../util";
|
|
5
6
|
|
|
6
7
|
export const editEntityAction: EntityAction = {
|
|
7
8
|
icon: <EditIcon/>,
|
|
9
|
+
key: "edit",
|
|
8
10
|
name: "Edit",
|
|
9
11
|
collapsed: false,
|
|
10
12
|
onClick({
|
|
@@ -14,23 +16,40 @@ export const editEntityAction: EntityAction = {
|
|
|
14
16
|
context,
|
|
15
17
|
highlightEntity,
|
|
16
18
|
unhighlightEntity,
|
|
19
|
+
openEntityMode
|
|
17
20
|
}): Promise<void> {
|
|
21
|
+
|
|
18
22
|
highlightEntity?.(entity);
|
|
23
|
+
|
|
19
24
|
context.analyticsController?.onAnalyticsEvent?.("entity_click", {
|
|
20
25
|
path: entity.path,
|
|
21
26
|
entityId: entity.id
|
|
22
27
|
});
|
|
28
|
+
|
|
23
29
|
if (collection) {
|
|
24
30
|
addRecentId(collection.id, entity.id);
|
|
25
31
|
}
|
|
26
|
-
|
|
27
|
-
|
|
32
|
+
|
|
33
|
+
const path = collection?.collectionGroup ? collection.id : (fullPath ?? collection?.id ?? entity.path);
|
|
34
|
+
const defaultSelectedView = resolveDefaultSelectedView(
|
|
35
|
+
collection ? collection.defaultSelectedView : undefined,
|
|
36
|
+
{
|
|
37
|
+
status: "existing",
|
|
38
|
+
entityId: entity.id,
|
|
39
|
+
}
|
|
40
|
+
);
|
|
41
|
+
navigateToEntity({
|
|
42
|
+
openEntityMode,
|
|
43
|
+
collection,
|
|
28
44
|
entityId: entity.id,
|
|
29
45
|
path,
|
|
30
|
-
|
|
31
|
-
|
|
46
|
+
fullIdPath: path,
|
|
47
|
+
sideEntityController: context.sideEntityController,
|
|
32
48
|
onClose: () => unhighlightEntity?.(entity),
|
|
49
|
+
navigation: context.navigation,
|
|
50
|
+
selectedTab: defaultSelectedView
|
|
33
51
|
});
|
|
52
|
+
|
|
34
53
|
return Promise.resolve(undefined);
|
|
35
54
|
}
|
|
36
55
|
}
|
|
@@ -38,55 +57,35 @@ export const editEntityAction: EntityAction = {
|
|
|
38
57
|
export const copyEntityAction: EntityAction = {
|
|
39
58
|
icon: <FileCopyIcon/>,
|
|
40
59
|
name: "Copy",
|
|
60
|
+
key: "copy",
|
|
41
61
|
onClick({
|
|
42
62
|
entity,
|
|
43
63
|
collection,
|
|
44
64
|
context,
|
|
65
|
+
fullPath,
|
|
45
66
|
highlightEntity,
|
|
46
67
|
unhighlightEntity,
|
|
68
|
+
openEntityMode
|
|
47
69
|
}): Promise<void> {
|
|
48
70
|
highlightEntity?.(entity);
|
|
49
71
|
context.analyticsController?.onAnalyticsEvent?.("copy_entity_click", {
|
|
50
72
|
path: entity.path,
|
|
51
73
|
entityId: entity.id
|
|
52
74
|
});
|
|
53
|
-
|
|
75
|
+
|
|
76
|
+
const path = collection?.collectionGroup ? collection.id : (fullPath ?? collection?.id ?? entity.path);
|
|
77
|
+
navigateToEntity({
|
|
78
|
+
openEntityMode,
|
|
79
|
+
collection,
|
|
54
80
|
entityId: entity.id,
|
|
55
|
-
path
|
|
81
|
+
path,
|
|
82
|
+
fullIdPath: path,
|
|
56
83
|
copy: true,
|
|
57
|
-
|
|
58
|
-
updateUrl: true,
|
|
84
|
+
sideEntityController: context.sideEntityController,
|
|
59
85
|
onClose: () => unhighlightEntity?.(entity),
|
|
86
|
+
navigation: context.navigation
|
|
60
87
|
});
|
|
61
|
-
return Promise.resolve(undefined);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
88
|
|
|
65
|
-
export const archiveEntityAction: EntityAction = {
|
|
66
|
-
icon: <ArchiveIcon/>,
|
|
67
|
-
name: "Archive",
|
|
68
|
-
onClick({
|
|
69
|
-
entity,
|
|
70
|
-
collection,
|
|
71
|
-
context: {
|
|
72
|
-
dataSource,
|
|
73
|
-
}
|
|
74
|
-
}): Promise<void> {
|
|
75
|
-
// Add your code here
|
|
76
|
-
return Promise.resolve(undefined);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export const openWebsiteAction: EntityAction = {
|
|
81
|
-
icon: <OpenInNewIcon/>,
|
|
82
|
-
name: "See in website",
|
|
83
|
-
onClick({
|
|
84
|
-
entity,
|
|
85
|
-
collection,
|
|
86
|
-
context,
|
|
87
|
-
}): Promise<void> {
|
|
88
|
-
// open a new tab
|
|
89
|
-
window.open(`https://example.com/${entity.id}`, "_blank");
|
|
90
89
|
return Promise.resolve(undefined);
|
|
91
90
|
}
|
|
92
91
|
}
|
|
@@ -94,6 +93,7 @@ export const openWebsiteAction: EntityAction = {
|
|
|
94
93
|
export const deleteEntityAction: EntityAction = {
|
|
95
94
|
icon: <DeleteIcon/>,
|
|
96
95
|
name: "Delete",
|
|
96
|
+
key: "delete",
|
|
97
97
|
onClick({
|
|
98
98
|
entity,
|
|
99
99
|
fullPath,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export * from "./types";
|
|
2
2
|
export * from "./useDebouncedData";
|
|
3
3
|
export * from "./useColumnsIds";
|
|
4
|
-
export * from "./
|
|
4
|
+
export * from "./useDataSourceTableController";
|
|
5
5
|
export * from "./useTableSearchHelper";
|
|
6
6
|
export * from "./default_entity_actions";
|
|
@@ -3,7 +3,7 @@ import { EntityCollection, ResolvedEntityCollection, ResolvedProperty } from "..
|
|
|
3
3
|
import { getSubcollectionColumnId } from "../EntityCollectionTable/internal/common";
|
|
4
4
|
import { PropertyColumnConfig } from "../EntityCollectionTable/EntityCollectionTableProps";
|
|
5
5
|
|
|
6
|
-
const COLLECTION_GROUP_PARENT_ID = "collectionGroupParent";
|
|
6
|
+
export const COLLECTION_GROUP_PARENT_ID = "collectionGroupParent";
|
|
7
7
|
|
|
8
8
|
export function useColumnIds<M extends Record<string, any>>(collection: ResolvedEntityCollection<M>, includeSubcollections: boolean): PropertyColumnConfig[] {
|
|
9
9
|
return useMemo(() => {
|