@firecms/core 3.0.0-alpha.81 → 3.0.0-alpha.83
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +4 -3
- package/dist/components/EntityCollectionTable/column_utils.d.ts +2 -2
- package/dist/components/EntityCollectionTable/fields/TableReferenceField.d.ts +5 -1
- package/dist/components/EntityCollectionView/EntityCollectionView.d.ts +2 -2
- package/dist/components/EntityCollectionView/EntityCollectionViewActions.d.ts +1 -1
- package/dist/components/VirtualTable/VirtualTableProps.d.ts +1 -1
- package/dist/contexts/AnalyticsContext.d.ts +3 -0
- package/dist/contexts/CustomizationControllerContext.d.ts +3 -0
- package/dist/core/field_configs.d.ts +1 -1
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/useAnalyticsController.d.ts +5 -0
- package/dist/hooks/useCustomizationController.d.ts +11 -0
- package/dist/hooks/useFireCMSContext.d.ts +0 -1
- package/dist/index.es.js +4878 -4856
- 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/useBuildCustomizationController.d.ts +2 -0
- package/dist/types/analytics_controller.d.ts +7 -0
- package/dist/types/collections.d.ts +3 -0
- package/dist/types/customization_controller.d.ts +47 -0
- package/dist/types/entity_callbacks.d.ts +17 -3
- package/dist/types/firecms_context.d.ts +6 -46
- package/dist/types/index.d.ts +2 -0
- package/dist/util/icons.d.ts +4 -1
- package/dist/util/useTraceUpdate.d.ts +1 -1
- package/package.json +3 -3
- package/src/components/DeleteEntityDialog.tsx +9 -3
- package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +1 -1
- package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +33 -8
- package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +5 -5
- package/src/components/EntityCollectionTable/PropertyTableCell.tsx +1 -1
- package/src/components/EntityCollectionTable/SimpleEntityCollectionTable.tsx +0 -2
- package/src/components/EntityCollectionTable/column_utils.tsx +3 -3
- package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +125 -122
- package/src/components/EntityCollectionTable/filters/DateTimeFilterField.tsx +2 -2
- package/src/components/EntityCollectionTable/internal/default_entity_actions.tsx +3 -3
- package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +4 -3
- package/src/components/EntityCollectionView/EntityCollectionView.tsx +77 -48
- package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +5 -3
- package/src/components/EntityPreview.tsx +11 -9
- package/src/components/HomePage/DefaultHomePage.tsx +9 -8
- package/src/components/HomePage/NavigationCollectionCard.tsx +6 -5
- package/src/components/ReferenceSelectionInner.tsx +38 -36
- package/src/components/VirtualTable/VirtualTable.tsx +23 -20
- package/src/components/VirtualTable/VirtualTableCell.tsx +27 -9
- package/src/components/VirtualTable/VirtualTableHeader.tsx +1 -1
- package/src/components/VirtualTable/VirtualTableProps.tsx +2 -2
- package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +2 -2
- package/src/contexts/AnalyticsContext.tsx +4 -0
- package/src/contexts/CustomizationControllerContext.tsx +4 -0
- package/src/core/Drawer.tsx +7 -6
- package/src/core/FireCMS.tsx +39 -29
- package/src/form/EntityForm.tsx +16 -5
- package/src/form/PropertyFieldBinding.tsx +8 -10
- package/src/form/components/CustomIdField.tsx +7 -5
- package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +1 -2
- package/src/form/field_bindings/DateTimeFieldBinding.tsx +2 -2
- package/src/form/field_bindings/KeyValueFieldBinding.tsx +4 -6
- package/src/hooks/data/save.ts +8 -3
- package/src/hooks/index.tsx +1 -0
- package/src/hooks/useAnalyticsController.tsx +8 -0
- package/src/hooks/useCustomizationController.tsx +14 -0
- package/src/hooks/useFireCMSContext.tsx +8 -7
- package/src/internal/EntityView.tsx +4 -2
- package/src/internal/useBuildCustomizationController.tsx +5 -0
- package/src/internal/useBuildSideDialogsController.tsx +0 -1
- package/src/preview/PropertyPreview.tsx +7 -4
- package/src/preview/components/DatePreview.tsx +4 -5
- package/src/preview/components/ReferencePreview.tsx +17 -8
- package/src/preview/property_previews/ArrayOfMapsPreview.tsx +3 -3
- package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +3 -3
- package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +3 -3
- package/src/preview/property_previews/ArrayOfStringsPreview.tsx +4 -4
- package/src/preview/property_previews/ArrayOneOfPreview.tsx +3 -3
- package/src/preview/property_previews/ArrayPropertyPreview.tsx +3 -3
- package/src/types/analytics_controller.tsx +10 -0
- package/src/types/collections.ts +3 -0
- package/src/types/customization_controller.tsx +58 -0
- package/src/types/entity_callbacks.ts +22 -3
- package/src/types/firecms_context.tsx +6 -51
- package/src/types/index.ts +2 -0
- package/src/util/icons.tsx +22 -19
- package/src/util/useTraceUpdate.tsx +5 -5
|
@@ -257,31 +257,34 @@ export const VirtualTable = React.memo<VirtualTableProps<any>>(
|
|
|
257
257
|
const empty = !loading && (data?.length ?? 0) === 0;
|
|
258
258
|
const customView = error ? buildErrorView() : (empty ? buildEmptyView() : undefined);
|
|
259
259
|
|
|
260
|
+
const virtualListController = {
|
|
261
|
+
data,
|
|
262
|
+
size,
|
|
263
|
+
cellRenderer,
|
|
264
|
+
columns,
|
|
265
|
+
currentSort,
|
|
266
|
+
onRowClick,
|
|
267
|
+
customView,
|
|
268
|
+
onColumnResize: onColumnResizeInternal,
|
|
269
|
+
onColumnResizeEnd: onColumnResizeEndInternal,
|
|
270
|
+
filter: filterRef.current,
|
|
271
|
+
onColumnSort,
|
|
272
|
+
onFilterUpdate: onFilterUpdateInternal,
|
|
273
|
+
sortByProperty,
|
|
274
|
+
hoverRow: hoverRow ?? false,
|
|
275
|
+
createFilterField,
|
|
276
|
+
rowClassName,
|
|
277
|
+
endAdornment,
|
|
278
|
+
AddColumnComponent
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
// useTraceUpdate(virtualListController);
|
|
260
282
|
return (
|
|
261
283
|
<div
|
|
262
284
|
ref={measureRef}
|
|
263
285
|
className={cn("h-full w-full", className)}>
|
|
264
286
|
<VirtualListContext.Provider
|
|
265
|
-
value={
|
|
266
|
-
data,
|
|
267
|
-
size,
|
|
268
|
-
cellRenderer,
|
|
269
|
-
columns,
|
|
270
|
-
currentSort,
|
|
271
|
-
onRowClick,
|
|
272
|
-
customView,
|
|
273
|
-
onColumnResize: onColumnResizeInternal,
|
|
274
|
-
onColumnResizeEnd: onColumnResizeEndInternal,
|
|
275
|
-
filter: filterRef.current,
|
|
276
|
-
onColumnSort,
|
|
277
|
-
onFilterUpdate: onFilterUpdateInternal,
|
|
278
|
-
sortByProperty,
|
|
279
|
-
hoverRow: hoverRow ?? false,
|
|
280
|
-
createFilterField,
|
|
281
|
-
rowClassName,
|
|
282
|
-
endAdornment,
|
|
283
|
-
AddColumnComponent
|
|
284
|
-
}}>
|
|
287
|
+
value={virtualListController}>
|
|
285
288
|
|
|
286
289
|
<MemoizedList
|
|
287
290
|
outerRef={tableRef}
|
|
@@ -17,16 +17,34 @@ type VirtualTableCellProps<T extends any> = {
|
|
|
17
17
|
|
|
18
18
|
export const VirtualTableCell = React.memo<VirtualTableCellProps<any>>(
|
|
19
19
|
function VirtualTableCell<T extends any>(props: VirtualTableCellProps<T>) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
20
|
+
// @ts-ignore
|
|
21
|
+
return props.rowData && props.cellRenderer(
|
|
22
|
+
{
|
|
23
|
+
cellData: props.cellData,
|
|
24
|
+
rowData: props.rowData,
|
|
25
|
+
rowIndex: props.rowIndex,
|
|
26
|
+
isScrolling: false,
|
|
27
|
+
column: props.column,
|
|
28
|
+
columns: props.columns,
|
|
29
|
+
columnIndex: props.columnIndex,
|
|
30
|
+
width: props.column.width
|
|
31
|
+
} as CellRendererParams<T>
|
|
32
|
+
);
|
|
33
|
+
// return props.rowData && <props.cellRenderer
|
|
34
|
+
// rowData={props.rowData}
|
|
35
|
+
// rowIndex={props.rowIndex}
|
|
36
|
+
// isScrolling={false}
|
|
37
|
+
// column={props.column}
|
|
38
|
+
// columns={props.columns}
|
|
39
|
+
// columnIndex={props.columnIndex}
|
|
40
|
+
// width={props.column.width}/>
|
|
28
41
|
},
|
|
29
42
|
(a, b) => {
|
|
30
|
-
return equal(a, b)
|
|
43
|
+
return equal(a.rowData, b.rowData) &&
|
|
44
|
+
equal(a.column, b.column) &&
|
|
45
|
+
equal(a.cellData, b.cellData) &&
|
|
46
|
+
equal(a.rowIndex, b.rowIndex) &&
|
|
47
|
+
equal(a.cellRenderer, b.cellRenderer) &&
|
|
48
|
+
equal(a.columnIndex, b.columnIndex)
|
|
31
49
|
}
|
|
32
50
|
);
|
|
@@ -106,7 +106,7 @@ export const VirtualTableHeader = React.memo<VirtualTableHeaderProps<any>>(
|
|
|
106
106
|
<div
|
|
107
107
|
className={`flex items-center justify-${column.headerAlign} flex-row`}>
|
|
108
108
|
|
|
109
|
-
{column.icon
|
|
109
|
+
{column.icon}
|
|
110
110
|
|
|
111
111
|
<div
|
|
112
112
|
className="truncate -webkit-box w-full mx-1 overflow-hidden"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { WhereFilterOp } from "../../types";
|
|
3
3
|
import { FilterFormFieldProps } from "./VirtualTableHeader";
|
|
4
4
|
|
|
5
5
|
export type OnRowClickParams<T extends Record<string, any>> = {
|
|
@@ -188,7 +188,7 @@ export interface VirtualTableColumn<CustomProps extends any = any> {
|
|
|
188
188
|
/**
|
|
189
189
|
* Icon displayed in the header
|
|
190
190
|
*/
|
|
191
|
-
icon?:
|
|
191
|
+
icon?: React.ReactNode;
|
|
192
192
|
|
|
193
193
|
/**
|
|
194
194
|
*
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { DateTimeField } from "@firecms/ui";
|
|
3
|
-
import {
|
|
3
|
+
import { useCustomizationController } from "../../../hooks";
|
|
4
4
|
|
|
5
5
|
export function VirtualTableDateField(props: {
|
|
6
6
|
name: string;
|
|
@@ -13,7 +13,7 @@ export function VirtualTableDateField(props: {
|
|
|
13
13
|
onBlur?: React.FocusEventHandler<HTMLInputElement | HTMLTextAreaElement>;
|
|
14
14
|
}) {
|
|
15
15
|
|
|
16
|
-
const { locale } =
|
|
16
|
+
const { locale } = useCustomizationController();
|
|
17
17
|
const {
|
|
18
18
|
disabled,
|
|
19
19
|
error,
|
package/src/core/Drawer.tsx
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import React, { useCallback } from "react";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { useLargeLayout, useNavigationController } from "../hooks";
|
|
4
4
|
|
|
5
5
|
import { NavLink } from "react-router-dom";
|
|
6
6
|
import { CMSAnalyticsEvent, TopNavigationEntry, TopNavigationResult } from "../types";
|
|
7
|
-
import {
|
|
7
|
+
import { IconForView } from "../util";
|
|
8
8
|
import { cn, Tooltip, Typography } from "@firecms/ui";
|
|
9
|
+
import { useAnalyticsController } from "../hooks/useAnalyticsController";
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* Props used in case you need to override the default drawer
|
|
@@ -27,7 +28,7 @@ export function Drawer({
|
|
|
27
28
|
closeDrawer
|
|
28
29
|
}: DrawerProps) {
|
|
29
30
|
|
|
30
|
-
const
|
|
31
|
+
const analyticsController = useAnalyticsController();
|
|
31
32
|
const navigation = useNavigationController();
|
|
32
33
|
|
|
33
34
|
const tooltipsOpen = hovered && !drawerOpen;
|
|
@@ -60,7 +61,7 @@ export function Drawer({
|
|
|
60
61
|
const eventName: CMSAnalyticsEvent = view.type === "collection"
|
|
61
62
|
? "drawer_navigate_to_collection"
|
|
62
63
|
: (view.type === "view" ? "drawer_navigate_to_view" : "unmapped_event");
|
|
63
|
-
|
|
64
|
+
analyticsController.onAnalyticsEvent?.(eventName, { url: view.url });
|
|
64
65
|
if (!largeLayout)
|
|
65
66
|
closeDrawer();
|
|
66
67
|
};
|
|
@@ -77,7 +78,7 @@ export function Drawer({
|
|
|
77
78
|
.map((view, index) =>
|
|
78
79
|
<DrawerNavigationItem
|
|
79
80
|
key={`navigation_${index}`}
|
|
80
|
-
icon={
|
|
81
|
+
icon={<IconForView collectionOrView={view.collection ?? view.view}/>}
|
|
81
82
|
tooltipsOpen={tooltipsOpen}
|
|
82
83
|
drawerOpen={drawerOpen}
|
|
83
84
|
onClick={() => onClick(view)}
|
|
@@ -92,7 +93,7 @@ export function Drawer({
|
|
|
92
93
|
|
|
93
94
|
return <DrawerNavigationItem
|
|
94
95
|
key={`navigation_${index}`}
|
|
95
|
-
icon={
|
|
96
|
+
icon={<IconForView collectionOrView={view.collection ?? view.view}/>}
|
|
96
97
|
tooltipsOpen={tooltipsOpen}
|
|
97
98
|
onClick={() => onClick(view)}
|
|
98
99
|
drawerOpen={drawerOpen}
|
package/src/core/FireCMS.tsx
CHANGED
|
@@ -3,7 +3,7 @@ import React, { useMemo } from "react";
|
|
|
3
3
|
import { EntityCollection, FireCMSContext, FireCMSPlugin, FireCMSProps, User } from "../types";
|
|
4
4
|
import { AuthControllerContext, ModeControllerContext } from "../contexts";
|
|
5
5
|
import { useBuildSideEntityController } from "../internal/useBuildSideEntityController";
|
|
6
|
-
import {
|
|
6
|
+
import { useCustomizationController, useFireCMSContext, useModeController } from "../hooks";
|
|
7
7
|
import { useBuildSideDialogsController } from "../internal/useBuildSideDialogsController";
|
|
8
8
|
import { ErrorView } from "../components";
|
|
9
9
|
import { StorageSourceContext } from "../contexts/StorageSourceContext";
|
|
@@ -17,6 +17,9 @@ import { CenteredView } from "@firecms/ui";
|
|
|
17
17
|
import { DialogsProvider } from "../contexts/DialogsProvider";
|
|
18
18
|
import { useBuildNavigationController } from "../internal/useBuildNavigationController";
|
|
19
19
|
import { useBuildDataSource } from "../internal/useBuildDataSource";
|
|
20
|
+
import { useBuildCustomizationController } from "../internal/useBuildCustomizationController";
|
|
21
|
+
import { CustomizationControllerContext } from "../contexts/CustomizationControllerContext";
|
|
22
|
+
import { AnalyticsContext } from "../contexts/AnalyticsContext";
|
|
20
23
|
|
|
21
24
|
/**
|
|
22
25
|
* If you are using independent components of the CMS
|
|
@@ -82,16 +85,19 @@ export function FireCMS<UserType extends User, EC extends EntityCollection>(prop
|
|
|
82
85
|
|
|
83
86
|
const loading = authController.initialLoading || navigationController.loading || pluginsLoading;
|
|
84
87
|
|
|
85
|
-
const
|
|
86
|
-
entityLinkBuilder,
|
|
88
|
+
const customizationController = useBuildCustomizationController({
|
|
87
89
|
dateTimeFormat,
|
|
88
90
|
locale,
|
|
91
|
+
entityLinkBuilder,
|
|
89
92
|
plugins,
|
|
90
|
-
onAnalyticsEvent,
|
|
91
93
|
entityViews: entityViews ?? [],
|
|
92
94
|
propertyConfigs: propertyConfigs ?? {},
|
|
93
95
|
components
|
|
94
|
-
})
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
const analyticsController = useMemo(() => ({
|
|
99
|
+
onAnalyticsEvent
|
|
100
|
+
}), []);
|
|
95
101
|
|
|
96
102
|
if (navigationController.navigationLoadingError) {
|
|
97
103
|
return (
|
|
@@ -115,35 +121,37 @@ export function FireCMS<UserType extends User, EC extends EntityCollection>(prop
|
|
|
115
121
|
|
|
116
122
|
return (
|
|
117
123
|
<ModeControllerContext.Provider value={modeController}>
|
|
118
|
-
<
|
|
119
|
-
<
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
124
|
+
<AnalyticsContext.Provider value={analyticsController}>
|
|
125
|
+
<CustomizationControllerContext.Provider value={customizationController}>
|
|
126
|
+
<UserConfigurationPersistenceContext.Provider
|
|
127
|
+
value={userConfigPersistence}>
|
|
128
|
+
<StorageSourceContext.Provider
|
|
129
|
+
value={storageSource}>
|
|
130
|
+
<DataSourceContext.Provider
|
|
131
|
+
value={dataSource}>
|
|
132
|
+
<AuthControllerContext.Provider
|
|
133
|
+
value={authController}>
|
|
134
|
+
<SideDialogsControllerContext.Provider
|
|
135
|
+
value={sideDialogsController}>
|
|
136
|
+
<SideEntityControllerContext.Provider
|
|
137
|
+
value={sideEntityController}>
|
|
138
|
+
<NavigationContext.Provider
|
|
139
|
+
value={navigationController}>
|
|
133
140
|
<DialogsProvider>
|
|
134
141
|
<FireCMSInternal
|
|
135
142
|
loading={loading}>
|
|
136
143
|
{children}
|
|
137
144
|
</FireCMSInternal>
|
|
138
145
|
</DialogsProvider>
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
146
|
+
</NavigationContext.Provider>
|
|
147
|
+
</SideEntityControllerContext.Provider>
|
|
148
|
+
</SideDialogsControllerContext.Provider>
|
|
149
|
+
</AuthControllerContext.Provider>
|
|
150
|
+
</DataSourceContext.Provider>
|
|
151
|
+
</StorageSourceContext.Provider>
|
|
152
|
+
</UserConfigurationPersistenceContext.Provider>
|
|
153
|
+
</CustomizationControllerContext.Provider>
|
|
154
|
+
</AnalyticsContext.Provider>
|
|
147
155
|
</ModeControllerContext.Provider>
|
|
148
156
|
);
|
|
149
157
|
|
|
@@ -161,12 +169,14 @@ function FireCMSInternal({
|
|
|
161
169
|
}) {
|
|
162
170
|
|
|
163
171
|
const context = useFireCMSContext();
|
|
172
|
+
const customizationController = useCustomizationController();
|
|
173
|
+
|
|
164
174
|
let childrenResult = children({
|
|
165
175
|
context,
|
|
166
176
|
loading
|
|
167
177
|
});
|
|
168
178
|
|
|
169
|
-
const plugins =
|
|
179
|
+
const plugins = customizationController.plugins;
|
|
170
180
|
if (!loading && plugins) {
|
|
171
181
|
plugins.forEach((plugin: FireCMSPlugin) => {
|
|
172
182
|
if (plugin.provider) {
|
package/src/form/EntityForm.tsx
CHANGED
|
@@ -25,7 +25,13 @@ import {
|
|
|
25
25
|
isReadOnly,
|
|
26
26
|
resolveCollection
|
|
27
27
|
} from "../util";
|
|
28
|
-
import {
|
|
28
|
+
import {
|
|
29
|
+
useAuthController,
|
|
30
|
+
useCustomizationController,
|
|
31
|
+
useDataSource,
|
|
32
|
+
useFireCMSContext,
|
|
33
|
+
useSideEntityController
|
|
34
|
+
} from "../hooks";
|
|
29
35
|
import { ErrorFocus } from "./components/ErrorFocus";
|
|
30
36
|
import { CustomIdField } from "./components/CustomIdField";
|
|
31
37
|
import { Alert, Button, cn, DialogActions, IconButton, Typography } from "@firecms/ui";
|
|
@@ -34,6 +40,7 @@ import {
|
|
|
34
40
|
copyEntityAction,
|
|
35
41
|
deleteEntityAction
|
|
36
42
|
} from "../components/EntityCollectionTable/internal/default_entity_actions";
|
|
43
|
+
import { useAnalyticsController } from "../hooks/useAnalyticsController";
|
|
37
44
|
|
|
38
45
|
/**
|
|
39
46
|
* @group Components
|
|
@@ -148,15 +155,19 @@ function EntityFormInternal<M extends Record<string, any>>({
|
|
|
148
155
|
onIdUpdateError
|
|
149
156
|
}: EntityFormProps<M>) {
|
|
150
157
|
|
|
158
|
+
const analyticsController = useAnalyticsController();
|
|
159
|
+
|
|
160
|
+
const customizationController = useCustomizationController();
|
|
161
|
+
|
|
151
162
|
const context = useFireCMSContext();
|
|
152
163
|
const dataSource = useDataSource();
|
|
153
|
-
const plugins =
|
|
164
|
+
const plugins = customizationController.plugins;
|
|
154
165
|
|
|
155
166
|
const initialResolvedCollection = useMemo(() => resolveCollection({
|
|
156
167
|
collection: inputCollection,
|
|
157
168
|
path,
|
|
158
169
|
values: entity?.values,
|
|
159
|
-
fields:
|
|
170
|
+
fields: customizationController.propertyConfigs
|
|
160
171
|
}), [entity?.values, path]);
|
|
161
172
|
|
|
162
173
|
const mustSetCustomId: boolean = (status === "new" || status === "copy") &&
|
|
@@ -219,7 +230,7 @@ function EntityFormInternal<M extends Record<string, any>>({
|
|
|
219
230
|
entityId,
|
|
220
231
|
values: internalValues,
|
|
221
232
|
previousValues: initialValues,
|
|
222
|
-
fields:
|
|
233
|
+
fields: customizationController.propertyConfigs
|
|
223
234
|
});
|
|
224
235
|
|
|
225
236
|
const onIdUpdate = inputCollection.callbacks?.onIdUpdate;
|
|
@@ -274,7 +285,7 @@ function EntityFormInternal<M extends Record<string, any>>({
|
|
|
274
285
|
const eventName: CMSAnalyticsEvent = status === "new"
|
|
275
286
|
? "new_entity_saved"
|
|
276
287
|
: (status === "copy" ? "entity_copied" : (status === "existing" ? "entity_edited" : "unmapped_event"));
|
|
277
|
-
|
|
288
|
+
analyticsController.onAnalyticsEvent?.(eventName, { path });
|
|
278
289
|
initialValuesRef.current = values;
|
|
279
290
|
})
|
|
280
291
|
.catch(e => {
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
import { ReadOnlyFieldBinding } from "./field_bindings/ReadOnlyFieldBinding";
|
|
18
18
|
|
|
19
19
|
import { isHidden, isPropertyBuilder, isReadOnly, resolveProperty } from "../util";
|
|
20
|
-
import {
|
|
20
|
+
import { useCustomizationController } from "../hooks";
|
|
21
21
|
import { Typography } from "@firecms/ui";
|
|
22
22
|
import { getFieldConfig, getFieldId } from "../core";
|
|
23
23
|
import { ErrorBoundary } from "../components";
|
|
@@ -81,9 +81,9 @@ function PropertyFieldBindingInternal<T extends CMSType = CMSType, CustomProps =
|
|
|
81
81
|
autoFocus,
|
|
82
82
|
}: PropertyFieldBindingProps<T, M>): ReactElement<PropertyFieldBindingProps<T, M>> {
|
|
83
83
|
|
|
84
|
-
const
|
|
84
|
+
const customizationController = useCustomizationController();
|
|
85
85
|
|
|
86
|
-
const shouldAlwaysRerender = shouldPropertyReRender(property,
|
|
86
|
+
const shouldAlwaysRerender = shouldPropertyReRender(property, customizationController.plugins);
|
|
87
87
|
// we use the standard Field for user defined fields, since it rebuilds
|
|
88
88
|
// when there are changes in other values, in contrast to FastField
|
|
89
89
|
const FieldComponent = shouldAlwaysRerender ? Field : FastField;
|
|
@@ -102,7 +102,7 @@ function PropertyFieldBindingInternal<T extends CMSType = CMSType, CustomProps =
|
|
|
102
102
|
values: fieldProps.form.values,
|
|
103
103
|
path: context.path,
|
|
104
104
|
entityId: context.entityId,
|
|
105
|
-
fields:
|
|
105
|
+
fields: customizationController.propertyConfigs
|
|
106
106
|
});
|
|
107
107
|
|
|
108
108
|
if (resolvedProperty === null || isHidden(resolvedProperty)) {
|
|
@@ -114,9 +114,9 @@ function PropertyFieldBindingInternal<T extends CMSType = CMSType, CustomProps =
|
|
|
114
114
|
Component = resolvedProperty.Field as ComponentType<FieldProps<any>>;
|
|
115
115
|
}
|
|
116
116
|
} else {
|
|
117
|
-
const propertyConfig = getFieldConfig(resolvedProperty,
|
|
117
|
+
const propertyConfig = getFieldConfig(resolvedProperty, customizationController.propertyConfigs);
|
|
118
118
|
if (!propertyConfig) {
|
|
119
|
-
console.log("INTERNAL: Could not find field config for property", { propertyKey, resolvedProperty, fields:
|
|
119
|
+
console.log("INTERNAL: Could not find field config for property", { propertyKey, resolvedProperty, fields: customizationController.propertyConfigs, propertyConfig });
|
|
120
120
|
throw new Error(`INTERNAL: Could not find field config for property ${propertyKey}`);
|
|
121
121
|
}
|
|
122
122
|
const configProperty = resolveProperty({
|
|
@@ -125,7 +125,7 @@ function PropertyFieldBindingInternal<T extends CMSType = CMSType, CustomProps =
|
|
|
125
125
|
values: fieldProps.form.values,
|
|
126
126
|
path: context.path,
|
|
127
127
|
entityId: context.entityId,
|
|
128
|
-
fields:
|
|
128
|
+
fields: customizationController.propertyConfigs
|
|
129
129
|
});
|
|
130
130
|
Component = configProperty.Field as ComponentType<FieldProps<T>>;
|
|
131
131
|
}
|
|
@@ -189,7 +189,7 @@ function FieldInternal<T extends CMSType, CustomProps, M extends Record<string,
|
|
|
189
189
|
fieldProps: FormikFieldProps<T>
|
|
190
190
|
}) {
|
|
191
191
|
|
|
192
|
-
const { plugins } =
|
|
192
|
+
const { plugins } = useCustomizationController();
|
|
193
193
|
|
|
194
194
|
const customFieldProps: any = property.customProps;
|
|
195
195
|
const value = fieldProps.field.value;
|
|
@@ -197,8 +197,6 @@ function FieldInternal<T extends CMSType, CustomProps, M extends Record<string,
|
|
|
197
197
|
const error = getIn(fieldProps.form.errors, propertyKey);
|
|
198
198
|
const touched = getIn(fieldProps.form.touched, propertyKey);
|
|
199
199
|
|
|
200
|
-
console.log("error", propertyKey, error);
|
|
201
|
-
|
|
202
200
|
const showError: boolean = error &&
|
|
203
201
|
(fieldProps.form.submitCount > 0 || property.validation?.unique) &&
|
|
204
202
|
(!Array.isArray(error) || !!error.filter((e: any) => !!e).length);
|
|
@@ -2,12 +2,14 @@ import React, { useMemo } from "react";
|
|
|
2
2
|
|
|
3
3
|
import { ErrorMessage } from "formik";
|
|
4
4
|
|
|
5
|
-
import { Entity, EntityStatus, EnumValueConfig, EnumValues
|
|
5
|
+
import { Entity, EntityStatus, EnumValueConfig, EnumValues } from "../../types";
|
|
6
6
|
|
|
7
|
-
import { useClipboard,
|
|
7
|
+
import { useClipboard, useSnackbarController } from "../../hooks";
|
|
8
8
|
import { enumToObjectEntries } from "../../util";
|
|
9
9
|
import { ContentCopyIcon, IconButton, OpenInNewIcon, Select, SelectItem, TextField, Tooltip } from "@firecms/ui";
|
|
10
10
|
import { EnumValuesChip } from "../../preview";
|
|
11
|
+
import { useCustomizationController } from "../../hooks/useCustomizationController";
|
|
12
|
+
import { CustomizationController } from "../../types/customization_controller";
|
|
11
13
|
|
|
12
14
|
export function CustomIdField<M extends Record<string, any>>({
|
|
13
15
|
customId,
|
|
@@ -42,7 +44,7 @@ export function CustomIdField<M extends Record<string, any>>({
|
|
|
42
44
|
})
|
|
43
45
|
});
|
|
44
46
|
|
|
45
|
-
const
|
|
47
|
+
const customizationController: CustomizationController = useCustomizationController();
|
|
46
48
|
|
|
47
49
|
const fieldProps = {
|
|
48
50
|
label: idSetAutomatically ? "ID is set automatically" : "ID",
|
|
@@ -60,10 +62,10 @@ export function CustomIdField<M extends Record<string, any>>({
|
|
|
60
62
|
</IconButton>
|
|
61
63
|
</Tooltip>
|
|
62
64
|
|
|
63
|
-
{
|
|
65
|
+
{customizationController?.entityLinkBuilder &&
|
|
64
66
|
<Tooltip title={"Open in the console"}>
|
|
65
67
|
<IconButton component={"a"}
|
|
66
|
-
href={
|
|
68
|
+
href={customizationController.entityLinkBuilder({ entity })}
|
|
67
69
|
rel="noopener noreferrer"
|
|
68
70
|
target="_blank"
|
|
69
71
|
onClick={(e) => e.stopPropagation()}
|
|
@@ -2,7 +2,7 @@ import React from "react";
|
|
|
2
2
|
import { FieldProps } from "../../types";
|
|
3
3
|
import { FieldHelperText } from "../components";
|
|
4
4
|
import { PropertyFieldBinding } from "../PropertyFieldBinding";
|
|
5
|
-
import { useClearRestoreValue
|
|
5
|
+
import { useClearRestoreValue } from "../../hooks";
|
|
6
6
|
import { ExpandablePanel } from "@firecms/ui";
|
|
7
7
|
import { getIconForProperty } from "../../util";
|
|
8
8
|
import { LabelWithIcon } from "../../components";
|
|
@@ -29,7 +29,6 @@ export function ArrayCustomShapedFieldBinding<T extends Array<any>>({
|
|
|
29
29
|
disabled
|
|
30
30
|
}: FieldProps<T, any, any>) {
|
|
31
31
|
|
|
32
|
-
const { propertyConfigs } = useFireCMSContext();
|
|
33
32
|
if (!Array.isArray(property.resolvedProperties))
|
|
34
33
|
throw Error("ArrayCustomShapedFieldBinding misconfiguration. Property `of` not set");
|
|
35
34
|
|
|
@@ -4,7 +4,7 @@ import { FieldProps } from "../../types";
|
|
|
4
4
|
|
|
5
5
|
import { FieldHelperText } from "../components";
|
|
6
6
|
import { LabelWithIcon } from "../../components";
|
|
7
|
-
import { useClearRestoreValue,
|
|
7
|
+
import { useClearRestoreValue, useCustomizationController } from "../../hooks";
|
|
8
8
|
import { getIconForProperty } from "../../util";
|
|
9
9
|
import { DateTimeField } from "@firecms/ui";
|
|
10
10
|
|
|
@@ -30,7 +30,7 @@ export function DateTimeFieldBinding({
|
|
|
30
30
|
includeDescription
|
|
31
31
|
}: DateTimeFieldProps) {
|
|
32
32
|
|
|
33
|
-
const { locale } =
|
|
33
|
+
const { locale } = useCustomizationController();
|
|
34
34
|
const internalValue = value || null;
|
|
35
35
|
|
|
36
36
|
useClearRestoreValue({
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import React, { useEffect, useState } from "react";
|
|
2
2
|
import { DataType, EntityReference, FieldProps, GeoPoint } from "../../types";
|
|
3
3
|
|
|
4
|
-
import { ArrayContainer } from "../../components";
|
|
4
|
+
import { ArrayContainer, LabelWithIcon } from "../../components";
|
|
5
5
|
import { FieldHelperText } from "../components";
|
|
6
|
-
|
|
7
|
-
import { LabelWithIcon } from "../../components";
|
|
8
6
|
import {
|
|
9
7
|
AddIcon,
|
|
10
8
|
ArrowDropDownIcon,
|
|
@@ -22,7 +20,7 @@ import {
|
|
|
22
20
|
Typography
|
|
23
21
|
} from "@firecms/ui";
|
|
24
22
|
import { getDefaultValueForDataType, getIconForProperty } from "../../util";
|
|
25
|
-
import {
|
|
23
|
+
import { useCustomizationController } from "../../hooks";
|
|
26
24
|
|
|
27
25
|
type MapEditViewRowState = [number, {
|
|
28
26
|
key: string,
|
|
@@ -257,7 +255,7 @@ function MapKeyValueRow<T extends Record<string, any>>({
|
|
|
257
255
|
updateDataType: (rowId: number, dataType: DataType) => void
|
|
258
256
|
}) {
|
|
259
257
|
|
|
260
|
-
const { locale } =
|
|
258
|
+
const { locale } = useCustomizationController();
|
|
261
259
|
|
|
262
260
|
function buildInput(entryValue: any, fieldKey: string, dataType: DataType) {
|
|
263
261
|
if (dataType === "string" || dataType === "number") {
|
|
@@ -439,7 +437,7 @@ function ArrayKeyValueRow<T>({
|
|
|
439
437
|
disabled?: boolean,
|
|
440
438
|
}) {
|
|
441
439
|
|
|
442
|
-
const { locale } =
|
|
440
|
+
const { locale } = useCustomizationController();
|
|
443
441
|
const [selectedDataType, setSelectedDataType] = useState<DataType>(getDataType(value) ?? "string");
|
|
444
442
|
|
|
445
443
|
function doUpdateDataType(dataType: DataType) {
|
package/src/hooks/data/save.ts
CHANGED
|
@@ -70,8 +70,13 @@ export async function saveEntityWithCallbacks<M extends Record<string, any>, Use
|
|
|
70
70
|
}
|
|
71
71
|
): Promise<void> {
|
|
72
72
|
|
|
73
|
+
if (status !== "new" && !entityId) {
|
|
74
|
+
throw new Error("Entity id must be specified when updating an existing entity");
|
|
75
|
+
}
|
|
73
76
|
let updatedValues: Partial<EntityValues<M>>;
|
|
74
77
|
|
|
78
|
+
const customizationController = context.customizationController;
|
|
79
|
+
|
|
75
80
|
const resolvedPath = context.navigation.resolveAliasesFrom(path);
|
|
76
81
|
|
|
77
82
|
const callbacks = collection.callbacks;
|
|
@@ -82,7 +87,7 @@ export async function saveEntityWithCallbacks<M extends Record<string, any>, Use
|
|
|
82
87
|
path,
|
|
83
88
|
values: previousValues as EntityValues<M>,
|
|
84
89
|
entityId,
|
|
85
|
-
fields:
|
|
90
|
+
fields: customizationController.propertyConfigs
|
|
86
91
|
});
|
|
87
92
|
updatedValues = await callbacks.onPreSave({
|
|
88
93
|
collection: resolvedCollection,
|
|
@@ -119,7 +124,7 @@ export async function saveEntityWithCallbacks<M extends Record<string, any>, Use
|
|
|
119
124
|
path,
|
|
120
125
|
values: updatedValues as EntityValues<M>,
|
|
121
126
|
entityId,
|
|
122
|
-
fields:
|
|
127
|
+
fields: customizationController.propertyConfigs
|
|
123
128
|
});
|
|
124
129
|
callbacks.onSaveSuccess({
|
|
125
130
|
collection: resolvedCollection,
|
|
@@ -147,7 +152,7 @@ export async function saveEntityWithCallbacks<M extends Record<string, any>, Use
|
|
|
147
152
|
path,
|
|
148
153
|
values: updatedValues as EntityValues<M>,
|
|
149
154
|
entityId,
|
|
150
|
-
fields:
|
|
155
|
+
fields: customizationController.propertyConfigs
|
|
151
156
|
});
|
|
152
157
|
callbacks.onSaveFailure({
|
|
153
158
|
collection: resolvedCollection,
|
package/src/hooks/index.tsx
CHANGED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { useContext } from "react";
|
|
2
|
+
import { AnalyticsController } from "../types";
|
|
3
|
+
import { AnalyticsContext } from "../contexts/AnalyticsContext";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @group Hooks and utilities
|
|
7
|
+
*/
|
|
8
|
+
export const useAnalyticsController = (): AnalyticsController => useContext(AnalyticsContext);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { useContext } from "react";
|
|
2
|
+
import { CustomizationController } from "../types/customization_controller";
|
|
3
|
+
import { CustomizationControllerContext } from "../contexts/CustomizationControllerContext";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Use this hook to retrieve the customization controller.
|
|
7
|
+
* This hook includes all the customization options that can be used
|
|
8
|
+
* to customize the CMS.
|
|
9
|
+
*
|
|
10
|
+
* You will likely not need to use this hook directly.
|
|
11
|
+
*
|
|
12
|
+
* @group Hooks and utilities
|
|
13
|
+
*/
|
|
14
|
+
export const useCustomizationController = (): CustomizationController => useContext(CustomizationControllerContext);
|