@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.
Files changed (84) hide show
  1. package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +4 -3
  2. package/dist/components/EntityCollectionTable/column_utils.d.ts +2 -2
  3. package/dist/components/EntityCollectionTable/fields/TableReferenceField.d.ts +5 -1
  4. package/dist/components/EntityCollectionView/EntityCollectionView.d.ts +2 -2
  5. package/dist/components/EntityCollectionView/EntityCollectionViewActions.d.ts +1 -1
  6. package/dist/components/VirtualTable/VirtualTableProps.d.ts +1 -1
  7. package/dist/contexts/AnalyticsContext.d.ts +3 -0
  8. package/dist/contexts/CustomizationControllerContext.d.ts +3 -0
  9. package/dist/core/field_configs.d.ts +1 -1
  10. package/dist/hooks/index.d.ts +1 -0
  11. package/dist/hooks/useAnalyticsController.d.ts +5 -0
  12. package/dist/hooks/useCustomizationController.d.ts +11 -0
  13. package/dist/hooks/useFireCMSContext.d.ts +0 -1
  14. package/dist/index.es.js +4878 -4856
  15. package/dist/index.es.js.map +1 -1
  16. package/dist/index.umd.js +5 -5
  17. package/dist/index.umd.js.map +1 -1
  18. package/dist/internal/useBuildCustomizationController.d.ts +2 -0
  19. package/dist/types/analytics_controller.d.ts +7 -0
  20. package/dist/types/collections.d.ts +3 -0
  21. package/dist/types/customization_controller.d.ts +47 -0
  22. package/dist/types/entity_callbacks.d.ts +17 -3
  23. package/dist/types/firecms_context.d.ts +6 -46
  24. package/dist/types/index.d.ts +2 -0
  25. package/dist/util/icons.d.ts +4 -1
  26. package/dist/util/useTraceUpdate.d.ts +1 -1
  27. package/package.json +3 -3
  28. package/src/components/DeleteEntityDialog.tsx +9 -3
  29. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +1 -1
  30. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +33 -8
  31. package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +5 -5
  32. package/src/components/EntityCollectionTable/PropertyTableCell.tsx +1 -1
  33. package/src/components/EntityCollectionTable/SimpleEntityCollectionTable.tsx +0 -2
  34. package/src/components/EntityCollectionTable/column_utils.tsx +3 -3
  35. package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +125 -122
  36. package/src/components/EntityCollectionTable/filters/DateTimeFilterField.tsx +2 -2
  37. package/src/components/EntityCollectionTable/internal/default_entity_actions.tsx +3 -3
  38. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +4 -3
  39. package/src/components/EntityCollectionView/EntityCollectionView.tsx +77 -48
  40. package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +5 -3
  41. package/src/components/EntityPreview.tsx +11 -9
  42. package/src/components/HomePage/DefaultHomePage.tsx +9 -8
  43. package/src/components/HomePage/NavigationCollectionCard.tsx +6 -5
  44. package/src/components/ReferenceSelectionInner.tsx +38 -36
  45. package/src/components/VirtualTable/VirtualTable.tsx +23 -20
  46. package/src/components/VirtualTable/VirtualTableCell.tsx +27 -9
  47. package/src/components/VirtualTable/VirtualTableHeader.tsx +1 -1
  48. package/src/components/VirtualTable/VirtualTableProps.tsx +2 -2
  49. package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +2 -2
  50. package/src/contexts/AnalyticsContext.tsx +4 -0
  51. package/src/contexts/CustomizationControllerContext.tsx +4 -0
  52. package/src/core/Drawer.tsx +7 -6
  53. package/src/core/FireCMS.tsx +39 -29
  54. package/src/form/EntityForm.tsx +16 -5
  55. package/src/form/PropertyFieldBinding.tsx +8 -10
  56. package/src/form/components/CustomIdField.tsx +7 -5
  57. package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +1 -2
  58. package/src/form/field_bindings/DateTimeFieldBinding.tsx +2 -2
  59. package/src/form/field_bindings/KeyValueFieldBinding.tsx +4 -6
  60. package/src/hooks/data/save.ts +8 -3
  61. package/src/hooks/index.tsx +1 -0
  62. package/src/hooks/useAnalyticsController.tsx +8 -0
  63. package/src/hooks/useCustomizationController.tsx +14 -0
  64. package/src/hooks/useFireCMSContext.tsx +8 -7
  65. package/src/internal/EntityView.tsx +4 -2
  66. package/src/internal/useBuildCustomizationController.tsx +5 -0
  67. package/src/internal/useBuildSideDialogsController.tsx +0 -1
  68. package/src/preview/PropertyPreview.tsx +7 -4
  69. package/src/preview/components/DatePreview.tsx +4 -5
  70. package/src/preview/components/ReferencePreview.tsx +17 -8
  71. package/src/preview/property_previews/ArrayOfMapsPreview.tsx +3 -3
  72. package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +3 -3
  73. package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +3 -3
  74. package/src/preview/property_previews/ArrayOfStringsPreview.tsx +4 -4
  75. package/src/preview/property_previews/ArrayOneOfPreview.tsx +3 -3
  76. package/src/preview/property_previews/ArrayPropertyPreview.tsx +3 -3
  77. package/src/types/analytics_controller.tsx +10 -0
  78. package/src/types/collections.ts +3 -0
  79. package/src/types/customization_controller.tsx +58 -0
  80. package/src/types/entity_callbacks.ts +22 -3
  81. package/src/types/firecms_context.tsx +6 -51
  82. package/src/types/index.ts +2 -0
  83. package/src/util/icons.tsx +22 -19
  84. package/src/util/useTraceUpdate.tsx +5 -5
@@ -1,10 +1,12 @@
1
1
  import React, { useCallback, useState } from "react";
2
+ import equal from "react-fast-compare"
3
+
2
4
  import { ReferencePreview, ReferencePreviewContainer } from "../../../preview";
3
5
  import { CollectionSize, Entity, EntityCollection, EntityReference, FilterValues } from "../../../types";
4
6
 
5
7
  import { getPreviewSizeFrom } from "../../../preview/util";
6
8
  import { getReferenceFrom } from "../../../util";
7
- import { useFireCMSContext, useNavigationController, useReferenceDialog } from "../../../hooks";
9
+ import { useCustomizationController, useNavigationController, useReferenceDialog } from "../../../hooks";
8
10
  import { ErrorView } from "../../ErrorView";
9
11
  import { Button } from "@firecms/ui";
10
12
 
@@ -22,14 +24,14 @@ type TableReferenceFieldProps = {
22
24
  };
23
25
 
24
26
  export function TableReferenceField(props: TableReferenceFieldProps) {
27
+ const customizationController = useCustomizationController();
25
28
 
26
- const context = useFireCMSContext();
27
29
  const navigationController = useNavigationController();
28
30
  const { path } = props;
29
31
  const collection = navigationController.getCollection<EntityCollection>(path);
30
32
  if (!collection) {
31
- if (context.components?.missingReference) {
32
- return <context.components.missingReference path={path}/>;
33
+ if (customizationController.components?.missingReference) {
34
+ return <customizationController.components.missingReference path={path}/>;
33
35
  } else {
34
36
  throw Error(`Couldn't find the corresponding collection view for the path: ${path}`);
35
37
  }
@@ -37,123 +39,124 @@ export function TableReferenceField(props: TableReferenceFieldProps) {
37
39
  return <TableReferenceFieldSuccess {...props} collection={collection}/>;
38
40
  }
39
41
 
40
- function TableReferenceFieldSuccess(props: TableReferenceFieldProps & {
41
- collection: EntityCollection;
42
- }) {
43
- const {
44
- name,
45
- internalValue,
46
- updateValue,
47
- multiselect,
48
- path,
49
- size,
50
- previewProperties,
51
- title,
52
- disabled,
53
- forceFilter,
54
- collection
55
- } = props;
56
-
57
- const [onHover, setOnHover] = useState(false);
58
-
59
- const hoverTrue = useCallback(() => setOnHover(true), []);
60
- const hoverFalse = useCallback(() => setOnHover(false), []);
61
-
62
- const onSingleEntitySelected = useCallback((entity: Entity<any>) => {
63
- updateValue(entity ? getReferenceFrom(entity) : null);
64
- }, [updateValue]);
65
-
66
- const onMultipleEntitiesSelected = useCallback((entities: Entity<any>[]) => {
67
- updateValue(entities.map((e) => getReferenceFrom(e)));
68
- }, [updateValue]);
69
-
70
- const selectedEntityIds = internalValue
71
- ? (Array.isArray(internalValue)
72
- ? internalValue.map((ref) => ref.id)
73
- : internalValue.id ? [internalValue.id] : [])
74
- : [];
75
-
76
- const referenceDialogController = useReferenceDialog({
42
+ export const TableReferenceFieldSuccess = React.memo(
43
+ function TableReferenceFieldSuccess(props: TableReferenceFieldProps & {
44
+ collection: EntityCollection;
45
+ }) {
46
+ const {
47
+ name,
48
+ internalValue,
49
+ updateValue,
77
50
  multiselect,
78
51
  path,
79
- collection,
80
- onMultipleEntitiesSelected,
81
- onSingleEntitySelected,
82
- selectedEntityIds,
83
- forceFilter
84
- }
85
- );
86
-
87
- const handleOpen = useCallback(() => {
88
- if (disabled)
89
- return;
90
- referenceDialogController.open();
91
- }, [disabled, referenceDialogController]);
92
-
93
- const valueNotSet = !internalValue || (Array.isArray(internalValue) && internalValue.length === 0);
94
-
95
- const buildSingleReferenceField = () => {
96
- if (internalValue instanceof EntityReference)
97
- return <ReferencePreview
98
- onClick={disabled ? undefined : handleOpen}
99
- size={getPreviewSizeFrom(size)}
100
- reference={internalValue as EntityReference}
101
- onHover={onHover}
102
- disabled={!path}
103
- previewProperties={previewProperties}
104
- />;
105
- else
106
- return <ReferencePreviewContainer
107
- onClick={disabled ? undefined : handleOpen}
108
- size={getPreviewSizeFrom(size)}>
109
- <ErrorView title="Value is not a reference." error={"Click to edit"}/>
110
- </ReferencePreviewContainer>;
111
- };
112
-
113
- const buildMultipleReferenceField = () => {
114
- if (Array.isArray(internalValue))
115
- return <>
116
- {internalValue.map((reference, index) =>
117
- <div className="m-1 w-full"
118
- key={`preview_array_ref_${name}_${index}`}>
119
- <ReferencePreview
120
- onClick={disabled ? undefined : handleOpen}
121
- size={"tiny"}
122
- reference={reference}
123
- onHover={onHover}
124
- disabled={!path}
125
- previewProperties={previewProperties}
126
- />
127
- </div>
128
- )
129
- }
130
- </>;
131
- else
132
- return <ErrorView error={"Data is not an array of references"}/>;
133
- };
134
-
135
- if (!collection)
136
- return <ErrorView error={"The specified collection does not exist"}/>;
137
-
138
- return (
139
- <div className="w-full"
140
- onMouseEnter={hoverTrue}
141
- onMouseMove={hoverTrue}
142
- onMouseLeave={hoverFalse}>
143
-
144
- {internalValue && !multiselect && buildSingleReferenceField()}
145
-
146
- {internalValue && multiselect && buildMultipleReferenceField()}
147
-
148
- {valueNotSet &&
149
- <Button
150
- onClick={handleOpen}
151
- size={"small"}
152
- variant="outlined"
153
- color="primary">
154
- Edit {title}
155
- </Button>}
156
-
157
- </div>
158
- );
159
- }
52
+ size,
53
+ previewProperties,
54
+ title,
55
+ disabled,
56
+ forceFilter,
57
+ collection
58
+ } = props;
59
+
60
+ const [onHover, setOnHover] = useState(false);
61
+
62
+ const hoverTrue = useCallback(() => setOnHover(true), []);
63
+ const hoverFalse = useCallback(() => setOnHover(false), []);
64
+
65
+ const onSingleEntitySelected = useCallback((entity: Entity<any>) => {
66
+ updateValue(entity ? getReferenceFrom(entity) : null);
67
+ }, [updateValue]);
68
+
69
+ const onMultipleEntitiesSelected = useCallback((entities: Entity<any>[]) => {
70
+ updateValue(entities.map((e) => getReferenceFrom(e)));
71
+ }, [updateValue]);
72
+
73
+ const selectedEntityIds = internalValue
74
+ ? (Array.isArray(internalValue)
75
+ ? internalValue.map((ref) => ref.id)
76
+ : internalValue.id ? [internalValue.id] : [])
77
+ : [];
78
+
79
+ const referenceDialogController = useReferenceDialog({
80
+ multiselect,
81
+ path,
82
+ collection,
83
+ onMultipleEntitiesSelected,
84
+ onSingleEntitySelected,
85
+ selectedEntityIds,
86
+ forceFilter
87
+ }
88
+ );
89
+
90
+ const handleOpen = useCallback(() => {
91
+ if (disabled)
92
+ return;
93
+ referenceDialogController.open();
94
+ }, [disabled, referenceDialogController]);
95
+
96
+ const valueNotSet = !internalValue || (Array.isArray(internalValue) && internalValue.length === 0);
97
+
98
+ const buildSingleReferenceField = () => {
99
+ if (internalValue instanceof EntityReference)
100
+ return <ReferencePreview
101
+ onClick={disabled ? undefined : handleOpen}
102
+ size={getPreviewSizeFrom(size)}
103
+ reference={internalValue as EntityReference}
104
+ onHover={onHover}
105
+ disabled={!path}
106
+ previewProperties={previewProperties}
107
+ />;
108
+ else
109
+ return <ReferencePreviewContainer
110
+ onClick={disabled ? undefined : handleOpen}
111
+ size={getPreviewSizeFrom(size)}>
112
+ <ErrorView title="Value is not a reference." error={"Click to edit"}/>
113
+ </ReferencePreviewContainer>;
114
+ };
115
+
116
+ const buildMultipleReferenceField = () => {
117
+ if (Array.isArray(internalValue))
118
+ return <>
119
+ {internalValue.map((reference, index) =>
120
+ <div className="m-1 w-full"
121
+ key={`preview_array_ref_${name}_${index}`}>
122
+ <ReferencePreview
123
+ onClick={disabled ? undefined : handleOpen}
124
+ size={"tiny"}
125
+ reference={reference}
126
+ onHover={onHover}
127
+ disabled={!path}
128
+ previewProperties={previewProperties}
129
+ />
130
+ </div>
131
+ )
132
+ }
133
+ </>;
134
+ else
135
+ return <ErrorView error={"Data is not an array of references"}/>;
136
+ };
137
+
138
+ if (!collection)
139
+ return <ErrorView error={"The specified collection does not exist"}/>;
140
+
141
+ return (
142
+ <div className="w-full"
143
+ onMouseEnter={hoverTrue}
144
+ onMouseMove={hoverTrue}
145
+ onMouseLeave={hoverFalse}>
146
+
147
+ {internalValue && !multiselect && buildSingleReferenceField()}
148
+
149
+ {internalValue && multiselect && buildMultipleReferenceField()}
150
+
151
+ {valueNotSet &&
152
+ <Button
153
+ onClick={handleOpen}
154
+ size={"small"}
155
+ variant="outlined"
156
+ color="primary">
157
+ Edit {title}
158
+ </Button>}
159
+
160
+ </div>
161
+ );
162
+ }, equal);
@@ -1,7 +1,7 @@
1
1
  import React, { useState } from "react";
2
2
  import { VirtualTableWhereFilterOp } from "../../VirtualTable";
3
3
  import { DateTimeField, Select, SelectItem } from "@firecms/ui";
4
- import { useFireCMSContext } from "../../../hooks";
4
+ import { useCustomizationController } from "../../../hooks";
5
5
 
6
6
  interface DateTimeFilterFieldProps {
7
7
  name: string,
@@ -36,7 +36,7 @@ export function DateTimeFilterField({
36
36
  title
37
37
  }: DateTimeFilterFieldProps) {
38
38
 
39
- const { locale } = useFireCMSContext();
39
+ const { locale } = useCustomizationController();
40
40
  const possibleOperations: (keyof typeof operationLabels) [] = isArray
41
41
  ? ["array-contains"]
42
42
  : ["==", "!=", ">", "<", ">=", "<="];
@@ -14,7 +14,7 @@ export const editEntityAction: EntityAction = {
14
14
  unhighlightEntity
15
15
  }): Promise<void> {
16
16
  highlightEntity?.(entity);
17
- context.onAnalyticsEvent?.("entity_click", {
17
+ context.analyticsController?.onAnalyticsEvent?.("entity_click", {
18
18
  path: entity.path,
19
19
  entityId: entity.id
20
20
  });
@@ -40,7 +40,7 @@ export const copyEntityAction: EntityAction = {
40
40
  unhighlightEntity
41
41
  }): Promise<void> {
42
42
  highlightEntity?.(entity);
43
- context.onAnalyticsEvent?.("copy_entity_click", {
43
+ context.analyticsController?.onAnalyticsEvent?.("copy_entity_click", {
44
44
  path: entity.path,
45
45
  entityId: entity.id
46
46
  });
@@ -107,7 +107,7 @@ export const deleteEntityAction: EntityAction = {
107
107
  callbacks={collection.callbacks}
108
108
  open={open}
109
109
  onEntityDelete={() => {
110
- context.onAnalyticsEvent?.("single_entity_deleted", {
110
+ context.analyticsController?.onAnalyticsEvent?.("single_entity_deleted", {
111
111
  path: fullPath
112
112
  });
113
113
  selectionController?.setSelectedEntities(selectionController.selectedEntities.filter(e => e.id !== entity.id));
@@ -23,7 +23,7 @@ import { ErrorView, OnCellValueChangeParams } from "../../../../components";
23
23
  import { getPropertyInPath, isReadOnly, resolveCollection } from "../../../../util";
24
24
  import { Button, ClearIcon, DialogActions, IconButton, Typography } from "@firecms/ui";
25
25
  import { PropertyFieldBinding } from "../../../../form";
26
- import { useDataSource, useFireCMSContext } from "../../../../hooks";
26
+ import { useCustomizationController, useFireCMSContext } from "../../../../hooks";
27
27
 
28
28
  interface PopupFormFieldProps<M extends Record<string, any>> {
29
29
  entity?: Entity<M>;
@@ -65,6 +65,7 @@ export function PopupFormFieldInternal<M extends Record<string, any>>({
65
65
 
66
66
  // const dataSource = useDataSource();
67
67
  const fireCMSContext = useFireCMSContext();
68
+ const customizationController = useCustomizationController();
68
69
 
69
70
  const [savingError, setSavingError] = React.useState<any>();
70
71
  const [popupLocation, setPopupLocation] = useState<{
@@ -99,7 +100,7 @@ export function PopupFormFieldInternal<M extends Record<string, any>>({
99
100
  path,
100
101
  values: internalValue,
101
102
  entityId,
102
- fields: fireCMSContext.propertyConfigs
103
+ fields: customizationController.propertyConfigs
103
104
  })
104
105
  : undefined;
105
106
 
@@ -315,7 +316,7 @@ export function PopupFormFieldInternal<M extends Record<string, any>>({
315
316
  </div>
316
317
  </>;
317
318
 
318
- const plugins = fireCMSContext.plugins;
319
+ const plugins = customizationController.plugins;
319
320
  if (plugins) {
320
321
  // const formController: FormContext<M> = {
321
322
  // values,