@firecms/core 3.0.0-beta.10 → 3.0.0-beta.12

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 (267) hide show
  1. package/dist/components/ArrayContainer.d.ts +22 -6
  2. package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +2 -1
  3. package/dist/components/EntityCollectionTable/EntityCollectionTable.d.ts +2 -2
  4. package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +17 -3
  5. package/dist/components/EntityCollectionTable/index.d.ts +1 -1
  6. package/dist/components/EntityCollectionTable/internal/popup_field/PopupFormField.d.ts +6 -3
  7. package/dist/components/EntityCollectionView/EntityCollectionView.d.ts +4 -0
  8. package/dist/components/PropertyIdCopyTooltip.d.ts +1 -1
  9. package/dist/components/SelectableTable/SelectableTable.d.ts +12 -2
  10. package/dist/components/SelectableTable/filters/ReferenceFilterField.d.ts +1 -1
  11. package/dist/components/UnsavedChangesDialog.d.ts +8 -0
  12. package/dist/components/VirtualTable/VirtualTableProps.d.ts +13 -0
  13. package/dist/components/common/default_entity_actions.d.ts +0 -2
  14. package/dist/components/common/index.d.ts +1 -1
  15. package/dist/components/common/useColumnsIds.d.ts +1 -0
  16. package/dist/components/common/{useDataSourceEntityCollectionTableController.d.ts → useDataSourceTableController.d.ts} +10 -2
  17. package/dist/components/common/useDebouncedCallback.d.ts +1 -0
  18. package/dist/components/common/useScrollRestoration.d.ts +14 -0
  19. package/dist/contexts/BreacrumbsContext.d.ts +8 -0
  20. package/dist/core/EntityEditView.d.ts +30 -22
  21. package/dist/core/EntityEditViewFormActions.d.ts +2 -0
  22. package/dist/core/FireCMS.d.ts +1 -1
  23. package/dist/core/FireCMSRouter.d.ts +4 -0
  24. package/dist/core/NavigationRoutes.d.ts +0 -1
  25. package/dist/core/SideDialogs.d.ts +4 -2
  26. package/dist/core/index.d.ts +2 -1
  27. package/dist/form/EntityForm.d.ts +45 -0
  28. package/dist/form/EntityFormActions.d.ts +17 -0
  29. package/dist/form/PropertyFieldBinding.d.ts +1 -1
  30. package/dist/form/components/FormEntry.d.ts +6 -0
  31. package/dist/form/components/FormLayout.d.ts +5 -0
  32. package/dist/form/components/index.d.ts +2 -1
  33. package/dist/form/field_bindings/ArrayCustomShapedFieldBinding.d.ts +1 -1
  34. package/dist/form/field_bindings/ArrayOfReferencesFieldBinding.d.ts +1 -1
  35. package/dist/form/field_bindings/BlockFieldBinding.d.ts +1 -1
  36. package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
  37. package/dist/form/field_bindings/MarkdownEditorFieldBinding.d.ts +1 -1
  38. package/dist/form/field_bindings/ReferenceFieldBinding.d.ts +2 -2
  39. package/dist/form/field_bindings/RepeatFieldBinding.d.ts +1 -1
  40. package/dist/form/field_bindings/SwitchFieldBinding.d.ts +1 -2
  41. package/dist/form/index.d.ts +16 -16
  42. package/dist/hooks/data/delete.d.ts +4 -4
  43. package/dist/hooks/data/save.d.ts +3 -3
  44. package/dist/hooks/data/useCollectionFetch.d.ts +1 -1
  45. package/dist/hooks/data/useEntityFetch.d.ts +4 -3
  46. package/dist/hooks/useAuthController.d.ts +1 -1
  47. package/dist/hooks/useBreadcrumbsController.d.ts +26 -0
  48. package/dist/hooks/useBuildNavigationController.d.ts +7 -4
  49. package/dist/hooks/useFireCMSContext.d.ts +1 -1
  50. package/dist/hooks/useModeController.d.ts +1 -2
  51. package/dist/hooks/useResolvedNavigationFrom.d.ts +3 -3
  52. package/dist/hooks/useValidateAuthenticator.d.ts +3 -3
  53. package/dist/index.es.js +17032 -12909
  54. package/dist/index.es.js.map +1 -1
  55. package/dist/index.umd.js +17019 -12898
  56. package/dist/index.umd.js.map +1 -1
  57. package/dist/internal/useBuildSideEntityController.d.ts +2 -2
  58. package/dist/internal/useUnsavedChangesDialog.d.ts +7 -9
  59. package/dist/preview/PropertyPreviewProps.d.ts +1 -1
  60. package/dist/preview/components/EnumValuesChip.d.ts +1 -1
  61. package/dist/preview/util.d.ts +3 -3
  62. package/dist/routes/CustomCMSRoute.d.ts +4 -0
  63. package/dist/routes/FireCMSRoute.d.ts +1 -0
  64. package/dist/routes/HomePageRoute.d.ts +3 -0
  65. package/dist/types/auth.d.ts +7 -9
  66. package/dist/types/collections.d.ts +44 -23
  67. package/dist/types/datasource.d.ts +2 -6
  68. package/dist/types/dialogs_controller.d.ts +7 -3
  69. package/dist/types/entities.d.ts +1 -1
  70. package/dist/types/entity_actions.d.ts +14 -4
  71. package/dist/types/entity_callbacks.d.ts +16 -16
  72. package/dist/types/export_import.d.ts +4 -4
  73. package/dist/types/fields.d.ts +27 -4
  74. package/dist/types/firecms.d.ts +2 -2
  75. package/dist/types/firecms_context.d.ts +1 -1
  76. package/dist/types/navigation.d.ts +29 -12
  77. package/dist/types/permissions.d.ts +4 -4
  78. package/dist/types/plugins.d.ts +9 -8
  79. package/dist/types/properties.d.ts +18 -3
  80. package/dist/types/property_config.d.ts +0 -2
  81. package/dist/types/side_entity_controller.d.ts +6 -1
  82. package/dist/types/user.d.ts +1 -0
  83. package/dist/util/builders.d.ts +3 -3
  84. package/dist/util/entities.d.ts +1 -1
  85. package/dist/util/entity_actions.d.ts +2 -0
  86. package/dist/util/entity_cache.d.ts +23 -0
  87. package/dist/util/icon_synonyms.d.ts +0 -1
  88. package/dist/util/icons.d.ts +3 -1
  89. package/dist/util/index.d.ts +1 -0
  90. package/dist/util/navigation_from_path.d.ts +6 -1
  91. package/dist/util/navigation_utils.d.ts +12 -1
  92. package/dist/util/objects.d.ts +1 -0
  93. package/dist/util/permissions.d.ts +4 -4
  94. package/dist/util/property_utils.d.ts +2 -2
  95. package/dist/util/resolutions.d.ts +12 -7
  96. package/package.json +129 -125
  97. package/src/app/Scaffold.tsx +4 -4
  98. package/src/components/ArrayContainer.tsx +115 -34
  99. package/src/components/CircularProgressCenter.tsx +1 -1
  100. package/src/components/ConfirmationDialog.tsx +2 -2
  101. package/src/components/DeleteEntityDialog.tsx +10 -19
  102. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +44 -20
  103. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +23 -17
  104. package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +20 -3
  105. package/src/components/EntityCollectionTable/PropertyTableCell.tsx +6 -4
  106. package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +8 -9
  107. package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +5 -11
  108. package/src/components/EntityCollectionTable/index.tsx +1 -1
  109. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +3 -3
  110. package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +5 -5
  111. package/src/components/EntityCollectionTable/internal/EntityTableCellActions.tsx +2 -2
  112. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +77 -73
  113. package/src/components/EntityCollectionView/EntityCollectionView.tsx +90 -49
  114. package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +4 -2
  115. package/src/components/EntityCollectionView/useSelectionController.tsx +5 -4
  116. package/src/components/EntityPreview.tsx +39 -30
  117. package/src/components/EntityView.tsx +5 -5
  118. package/src/components/ErrorView.tsx +3 -3
  119. package/src/components/HomePage/DefaultHomePage.tsx +1 -0
  120. package/src/components/HomePage/FavouritesView.tsx +6 -11
  121. package/src/components/HomePage/NavigationCard.tsx +1 -1
  122. package/src/components/HomePage/NavigationCardBinding.tsx +4 -9
  123. package/src/components/HomePage/NavigationGroup.tsx +1 -1
  124. package/src/components/NotFoundPage.tsx +2 -2
  125. package/src/components/PropertyConfigBadge.tsx +1 -1
  126. package/src/components/PropertyIdCopyTooltip.tsx +3 -4
  127. package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +13 -8
  128. package/src/components/SelectableTable/SelectableTable.tsx +20 -5
  129. package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +4 -2
  130. package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +10 -8
  131. package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +7 -5
  132. package/src/components/UnsavedChangesDialog.tsx +42 -0
  133. package/src/components/VirtualTable/VirtualTable.tsx +19 -2
  134. package/src/components/VirtualTable/VirtualTableHeader.tsx +8 -8
  135. package/src/components/VirtualTable/VirtualTableHeaderRow.tsx +1 -1
  136. package/src/components/VirtualTable/VirtualTableProps.tsx +15 -0
  137. package/src/components/VirtualTable/VirtualTableRow.tsx +1 -1
  138. package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +1 -1
  139. package/src/components/VirtualTable/fields/VirtualTableInput.tsx +1 -1
  140. package/src/components/VirtualTable/fields/VirtualTableSelect.tsx +2 -0
  141. package/src/components/common/default_entity_actions.tsx +26 -37
  142. package/src/components/common/index.ts +1 -1
  143. package/src/components/common/useColumnsIds.tsx +1 -1
  144. package/src/components/common/useDataSourceTableController.tsx +420 -0
  145. package/src/components/common/useDebouncedCallback.tsx +20 -0
  146. package/src/components/common/useScrollRestoration.tsx +68 -0
  147. package/src/contexts/BreacrumbsContext.tsx +38 -0
  148. package/src/contexts/DialogsProvider.tsx +3 -2
  149. package/src/contexts/ModeController.tsx +1 -3
  150. package/src/contexts/SnackbarProvider.tsx +2 -0
  151. package/src/core/DefaultAppBar.tsx +56 -25
  152. package/src/core/DefaultDrawer.tsx +11 -9
  153. package/src/core/DrawerNavigationItem.tsx +4 -4
  154. package/src/core/EntityEditView.tsx +282 -1006
  155. package/src/core/EntityEditViewFormActions.tsx +199 -0
  156. package/src/core/EntitySidePanel.tsx +85 -15
  157. package/src/core/FireCMS.tsx +12 -9
  158. package/src/core/FireCMSRouter.tsx +17 -0
  159. package/src/core/NavigationRoutes.tsx +23 -32
  160. package/src/core/SideDialogs.tsx +21 -12
  161. package/src/core/field_configs.tsx +4 -4
  162. package/src/core/index.tsx +4 -2
  163. package/src/form/EntityForm.tsx +774 -0
  164. package/src/form/EntityFormActions.tsx +169 -0
  165. package/src/form/PropertyFieldBinding.tsx +39 -30
  166. package/src/form/components/CustomIdField.tsx +2 -0
  167. package/src/form/components/FormEntry.tsx +22 -0
  168. package/src/form/components/FormLayout.tsx +16 -0
  169. package/src/form/components/LabelWithIcon.tsx +6 -3
  170. package/src/form/components/StorageItemPreview.tsx +3 -3
  171. package/src/form/components/StorageUploadProgress.tsx +1 -1
  172. package/src/form/components/index.tsx +2 -1
  173. package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +7 -6
  174. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +20 -12
  175. package/src/form/field_bindings/BlockFieldBinding.tsx +45 -25
  176. package/src/form/field_bindings/DateTimeFieldBinding.tsx +2 -1
  177. package/src/form/field_bindings/KeyValueFieldBinding.tsx +10 -7
  178. package/src/form/field_bindings/MapFieldBinding.tsx +69 -52
  179. package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +9 -6
  180. package/src/form/field_bindings/MultiSelectFieldBinding.tsx +1 -1
  181. package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +2 -2
  182. package/src/form/field_bindings/ReferenceFieldBinding.tsx +5 -5
  183. package/src/form/field_bindings/RepeatFieldBinding.tsx +30 -22
  184. package/src/form/field_bindings/SelectFieldBinding.tsx +6 -5
  185. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +7 -5
  186. package/src/form/field_bindings/SwitchFieldBinding.tsx +26 -25
  187. package/src/form/field_bindings/TextFieldBinding.tsx +4 -3
  188. package/src/form/index.tsx +16 -32
  189. package/src/form/validation.ts +12 -6
  190. package/src/hooks/data/delete.ts +4 -4
  191. package/src/hooks/data/save.ts +8 -9
  192. package/src/hooks/data/useCollectionFetch.tsx +3 -3
  193. package/src/hooks/data/useEntityFetch.tsx +10 -6
  194. package/src/hooks/useAuthController.tsx +1 -1
  195. package/src/hooks/useBreadcrumbsController.tsx +31 -0
  196. package/src/hooks/useBuildModeController.tsx +15 -28
  197. package/src/hooks/useBuildNavigationController.tsx +74 -29
  198. package/src/hooks/useFireCMSContext.tsx +5 -5
  199. package/src/hooks/useLargeLayout.tsx +0 -35
  200. package/src/hooks/useModeController.tsx +1 -2
  201. package/src/hooks/useResolvedNavigationFrom.tsx +9 -11
  202. package/src/hooks/useValidateAuthenticator.tsx +3 -3
  203. package/src/internal/useBuildDataSource.ts +1 -1
  204. package/src/internal/useBuildSideDialogsController.tsx +3 -2
  205. package/src/internal/useBuildSideEntityController.tsx +124 -83
  206. package/src/internal/useUnsavedChangesDialog.tsx +127 -93
  207. package/src/preview/PropertyPreview.tsx +11 -11
  208. package/src/preview/PropertyPreviewProps.tsx +1 -1
  209. package/src/preview/components/BooleanPreview.tsx +1 -1
  210. package/src/preview/components/EmptyValue.tsx +1 -1
  211. package/src/preview/components/EnumValuesChip.tsx +1 -1
  212. package/src/preview/components/ImagePreview.tsx +5 -6
  213. package/src/preview/components/UrlComponentPreview.tsx +20 -21
  214. package/src/preview/property_previews/ArrayOfMapsPreview.tsx +1 -1
  215. package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +2 -2
  216. package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +2 -2
  217. package/src/preview/property_previews/ArrayOfStringsPreview.tsx +1 -1
  218. package/src/preview/property_previews/ArrayOneOfPreview.tsx +2 -2
  219. package/src/preview/property_previews/ArrayPropertyPreview.tsx +2 -2
  220. package/src/preview/property_previews/MapPropertyPreview.tsx +7 -6
  221. package/src/preview/property_previews/SkeletonPropertyComponent.tsx +12 -12
  222. package/src/preview/property_previews/StringPropertyPreview.tsx +2 -2
  223. package/src/preview/util.ts +10 -10
  224. package/src/routes/CustomCMSRoute.tsx +21 -0
  225. package/src/routes/FireCMSRoute.tsx +235 -0
  226. package/src/routes/HomePageRoute.tsx +17 -0
  227. package/src/types/auth.tsx +8 -12
  228. package/src/types/collections.ts +52 -26
  229. package/src/types/datasource.ts +2 -6
  230. package/src/types/dialogs_controller.tsx +7 -3
  231. package/src/types/entities.ts +1 -1
  232. package/src/types/entity_actions.tsx +16 -4
  233. package/src/types/entity_callbacks.ts +18 -18
  234. package/src/types/export_import.ts +4 -4
  235. package/src/types/fields.tsx +33 -4
  236. package/src/types/firecms.tsx +2 -2
  237. package/src/types/firecms_context.tsx +1 -1
  238. package/src/types/navigation.ts +36 -16
  239. package/src/types/permissions.ts +5 -5
  240. package/src/types/plugins.tsx +9 -8
  241. package/src/types/properties.ts +21 -3
  242. package/src/types/property_config.tsx +0 -2
  243. package/src/types/side_dialogs_controller.tsx +2 -0
  244. package/src/types/side_entity_controller.tsx +6 -1
  245. package/src/types/user.ts +2 -0
  246. package/src/util/builders.ts +10 -8
  247. package/src/util/entities.ts +3 -1
  248. package/src/util/entity_actions.ts +28 -0
  249. package/src/util/entity_cache.ts +204 -0
  250. package/src/util/icon_list.ts +1 -0
  251. package/src/util/icon_synonyms.ts +0 -1
  252. package/src/util/icons.tsx +12 -8
  253. package/src/util/index.ts +1 -0
  254. package/src/util/join_collections.ts +3 -0
  255. package/src/util/navigation_from_path.ts +13 -6
  256. package/src/util/navigation_utils.ts +53 -1
  257. package/src/util/objects.ts +24 -1
  258. package/src/util/parent_references_from_path.ts +3 -3
  259. package/src/util/permissions.ts +8 -8
  260. package/src/util/property_utils.tsx +10 -3
  261. package/src/util/references.ts +8 -2
  262. package/src/util/resolutions.ts +34 -13
  263. package/src/util/useStorageUploadController.tsx +40 -22
  264. package/dist/form/components/FormikArrayContainer.d.ts +0 -19
  265. package/src/components/common/useDataSourceEntityCollectionTableController.tsx +0 -236
  266. package/src/form/components/FormikArrayContainer.tsx +0 -47
  267. /package/src/util/{common.tsx → common.ts} +0 -0
@@ -1,5 +1,4 @@
1
1
  import React, { useCallback, useEffect, useLayoutEffect, useMemo, useState } from "react";
2
- import equal from "react-fast-compare"
3
2
 
4
3
  import * as Portal from "@radix-ui/react-portal";
5
4
 
@@ -19,20 +18,19 @@ import { useDraggable } from "./useDraggable";
19
18
  import { CustomFieldValidator, getYupEntitySchema } from "../../../../form/validation";
20
19
  import { useWindowSize } from "./useWindowSize";
21
20
  import { ElementResizeListener } from "./ElementResizeListener";
22
- import { ErrorView } from "../../../ErrorView";
23
21
  import { getPropertyInPath, isReadOnly, resolveCollection } from "../../../../util";
24
- import { Button, ClearIcon, DialogActions, IconButton, Typography } from "@firecms/ui";
25
- import { PropertyFieldBinding } from "../../../../form";
26
- import { useCustomizationController, useFireCMSContext } from "../../../../hooks";
22
+ import { Button, CloseIcon, DialogActions, IconButton, Typography } from "@firecms/ui";
23
+ import { PropertyFieldBinding, yupToFormErrors } from "../../../../form";
24
+ import { useCustomizationController, useDataSource, useFireCMSContext } from "../../../../hooks";
27
25
  import { OnCellValueChangeParams } from "../../../common";
28
26
 
29
27
  interface PopupFormFieldProps<M extends Record<string, any>> {
30
- entity: Entity<M>;
31
28
  customFieldValidator?: CustomFieldValidator;
32
29
  path: string;
30
+ entityId: string;
33
31
  tableKey: string;
34
32
  propertyKey?: Extract<keyof M, string>;
35
- collection?: EntityCollection<M>;
33
+ collection?: EntityCollection<any>;
36
34
  cellRect?: DOMRect;
37
35
  open: boolean;
38
36
  onClose: () => void;
@@ -46,13 +44,54 @@ interface PopupFormFieldProps<M extends Record<string, any>> {
46
44
 
47
45
  export function PopupFormField<M extends Record<string, any>>(props: PopupFormFieldProps<M>) {
48
46
  if (!props.open) return null;
49
- return <PopupFormFieldInternal {...props} />;
47
+ return <PopupFormFieldLoading {...props} />;
50
48
 
51
49
  }
52
50
 
51
+ export function PopupFormFieldLoading<M extends Record<string, any>>({
52
+ tableKey,
53
+ entityId,
54
+ customFieldValidator,
55
+ propertyKey,
56
+ collection: inputCollection,
57
+ path,
58
+ cellRect,
59
+ open,
60
+ onClose,
61
+ onCellValueChange,
62
+ container
63
+ }: PopupFormFieldProps<M>) {
64
+ const dataSource = useDataSource();
65
+ const [entity, setEntity] = useState<Entity<M> | undefined>(undefined);
66
+ useEffect(() => {
67
+ if (entityId && inputCollection) {
68
+ dataSource.fetchEntity({
69
+ path,
70
+ entityId,
71
+ collection: inputCollection
72
+ }).then(setEntity);
73
+ }
74
+ }, [entityId, inputCollection]);
75
+
76
+ if (!entity) return null;
77
+ return <PopupFormFieldInternal {...{
78
+ tableKey,
79
+ entityId,
80
+ customFieldValidator,
81
+ propertyKey,
82
+ collection: inputCollection,
83
+ path,
84
+ cellRect,
85
+ open,
86
+ onClose,
87
+ onCellValueChange,
88
+ container
89
+ }} entity={entity}/>;
90
+ }
91
+
53
92
  export function PopupFormFieldInternal<M extends Record<string, any>>({
54
93
  tableKey,
55
- entity: entityProp,
94
+ entityId,
56
95
  customFieldValidator,
57
96
  propertyKey,
58
97
  collection: inputCollection,
@@ -61,10 +100,12 @@ export function PopupFormFieldInternal<M extends Record<string, any>>({
61
100
  open,
62
101
  onClose,
63
102
  onCellValueChange,
64
- container
65
- }: PopupFormFieldProps<M>) {
103
+ container,
104
+ entity
105
+ }: PopupFormFieldProps<M> & {
106
+ entity?: Entity<M>
107
+ }) {
66
108
 
67
- // const dataSource = useDataSource();
68
109
  const fireCMSContext = useFireCMSContext();
69
110
  const customizationController = useCustomizationController();
70
111
 
@@ -74,34 +115,13 @@ export function PopupFormFieldInternal<M extends Record<string, any>>({
74
115
  y: number
75
116
  }>();
76
117
 
77
- const entityId = entityProp.id;
78
- const [entity, setEntity] = useState<Entity<M> | undefined>(entityProp);
79
- // useEffect(() => {
80
- // if (entityId && inputCollection) {
81
- // return dataSource.listenEntity?.({
82
- // path,
83
- // entityId,
84
- // collection: inputCollection,
85
- // onUpdate: (e) => {
86
- // setEntity(e);
87
- // setInternalValue(e?.values);
88
- // }
89
- // });
90
- // } else {
91
- // return () => {
92
- // };
93
- // }
94
- // }, [dataSource, entityId, inputCollection, path, open]);
95
-
96
- const [internalValue, setInternalValue] = useState<EntityValues<M> | undefined>(entity?.values);
97
-
98
118
  const collection: ResolvedEntityCollection<M> | undefined = inputCollection
99
119
  ? resolveCollection<M>({
100
120
  collection: inputCollection,
101
121
  path,
102
- values: internalValue,
122
+ values: entity?.values,
103
123
  entityId,
104
- fields: customizationController.propertyConfigs
124
+ propertyConfigs: customizationController.propertyConfigs
105
125
  })
106
126
  : undefined;
107
127
 
@@ -214,46 +234,32 @@ export function PopupFormFieldInternal<M extends Record<string, any>>({
214
234
  return Promise.resolve();
215
235
  };
216
236
 
217
- if (!entity)
218
- return <></>;
219
-
220
- // eslint-disable-next-line react-hooks/rules-of-hooks
221
237
  const formex = useCreateFormex<M>({
222
238
  initialValues: (entity?.values ?? {}) as EntityValues<M>,
223
239
  validation: (values) => {
224
240
  return validationSchema?.validate(values, { abortEarly: false })
225
241
  .then(() => ({}))
226
- .catch((e) => {
227
- const errors: Record<string, string> = {};
228
- e.inner.forEach((error: any) => {
229
- errors[error.path] = error.message;
230
- });
231
- return errors;
232
- });
242
+ .catch(yupToFormErrors);
233
243
  },
234
244
  validateOnInitialRender: true,
235
245
  onSubmit: (values, actions) => {
236
246
  saveValue(values)
237
- .then(() => onClose())
247
+ .then(() => {
248
+ formex.resetForm({
249
+ values: values
250
+ })
251
+ onClose();
252
+ })
238
253
  .finally(() => actions.setSubmitting(false));
239
254
  }
240
255
  });
241
256
 
242
- const { values, isSubmitting, setFieldValue, handleSubmit } = formex;
243
-
244
- // eslint-disable-next-line react-hooks/rules-of-hooks
245
- useEffect(() => {
246
- if (!equal(values, internalValue)) {
247
- setInternalValue(values);
248
- }
249
- }, [values]);
250
-
251
- if (!entity)
252
- return <ErrorView
253
- error={"PopupFormField misconfiguration"}/>;
254
-
255
- if (!collection)
256
- return <></>;
257
+ const {
258
+ values,
259
+ isSubmitting,
260
+ setFieldValue,
261
+ handleSubmit
262
+ } = formex;
257
263
 
258
264
  const disabled = isSubmitting;
259
265
 
@@ -264,10 +270,12 @@ export function PopupFormFieldInternal<M extends Record<string, any>>({
264
270
  path,
265
271
  setFieldValue,
266
272
  save: saveValue,
267
- formex
273
+ formex,
274
+ status: "existing",
275
+ openEntityMode: "side_panel",
268
276
  };
269
277
 
270
- const property: ResolvedProperty<any> | undefined = propertyKey && getPropertyInPath(collection.properties, propertyKey as string);
278
+ const property: ResolvedProperty<any> | undefined = propertyKey && getPropertyInPath(collection?.properties ?? {} as ResolvedProperties, propertyKey as string);
271
279
  const fieldProps: PropertyFieldBindingProps<any, M> | undefined = propertyKey && property
272
280
  ? {
273
281
  propertyKey: propertyKey as string,
@@ -285,7 +293,7 @@ export function PopupFormFieldInternal<M extends Record<string, any>>({
285
293
  let internalForm = <>
286
294
  <div
287
295
  key={`popup_form_${tableKey}_${entityId}_${propertyKey}`}
288
- className="w-[560px] max-w-full max-h-[85vh]">
296
+ className="w-[700px] max-w-full max-h-[85vh]">
289
297
  <form
290
298
  onSubmit={handleSubmit}
291
299
  noValidate>
@@ -320,10 +328,6 @@ export function PopupFormFieldInternal<M extends Record<string, any>>({
320
328
 
321
329
  const plugins = customizationController.plugins;
322
330
  if (plugins) {
323
- // const formController: FormContext<M> = {
324
- // values,
325
- // setFieldValue
326
- // }
327
331
  plugins.forEach((plugin: FireCMSPlugin) => {
328
332
  if (plugin.form?.provider) {
329
333
  internalForm = (
@@ -343,7 +347,7 @@ export function PopupFormFieldInternal<M extends Record<string, any>>({
343
347
  });
344
348
  }
345
349
  const form = <div
346
- className={`text-gray-900 dark:text-white overflow-auto rounded rounded-md bg-white dark:bg-gray-950 ${!open ? "hidden" : ""} cursor-grab max-w-[100vw]`}>
350
+ className={`text-surface-900 dark:text-white overflow-auto rounded rounded-md bg-white dark:bg-surface-950 ${!open ? "hidden" : ""} cursor-grab max-w-[100vw]`}>
347
351
 
348
352
  {internalForm}
349
353
 
@@ -360,7 +364,7 @@ export function PopupFormFieldInternal<M extends Record<string, any>>({
360
364
  style={{
361
365
  boxShadow: "0 0 0 2px rgba(128,128,128,0.2)",
362
366
  }}
363
- className={`inline-block fixed z-20 shadow-outline rounded-md bg-white dark:bg-gray-950 ${
367
+ className={`inline-block fixed z-20 shadow-outline rounded-md bg-white dark:bg-surface-950 ${
364
368
  !open ? "invisible" : "visible"
365
369
  } cursor-grab overflow-visible`}
366
370
  ref={draggableRef}>
@@ -373,7 +377,7 @@ export function PopupFormFieldInternal<M extends Record<string, any>>({
373
377
  {form}
374
378
 
375
379
  <div
376
- className="absolute -top-3.5 -right-3.5 bg-gray-500 rounded-full"
380
+ className="absolute -top-3.5 -right-3.5 bg-surface-500 rounded-full"
377
381
  style={{
378
382
  width: "32px",
379
383
  height: "32px"
@@ -384,7 +388,7 @@ export function PopupFormFieldInternal<M extends Record<string, any>>({
384
388
  event.stopPropagation();
385
389
  onClose();
386
390
  }}>
387
- <ClearIcon className="text-white"
391
+ <CloseIcon className="text-white"
388
392
  size={"small"}/>
389
393
  </IconButton>
390
394
  </div>
@@ -19,7 +19,7 @@ import {
19
19
  import {
20
20
  EntityCollectionRowActions,
21
21
  EntityCollectionTable,
22
- useDataSourceEntityCollectionTableController
22
+ useDataSourceTableController
23
23
  } from "../EntityCollectionTable";
24
24
 
25
25
  import {
@@ -28,6 +28,8 @@ import {
28
28
  canEditEntity,
29
29
  getPropertyInPath,
30
30
  mergeDeep,
31
+ mergeEntityActions,
32
+ navigateToEntity,
31
33
  resolveCollection,
32
34
  resolveProperty
33
35
  } from "../../util";
@@ -61,6 +63,10 @@ import {
61
63
  import { setIn } from "@firecms/formex";
62
64
  import { getSubcollectionColumnId } from "../EntityCollectionTable/internal/common";
63
65
  import {
66
+ COLLECTION_GROUP_PARENT_ID,
67
+ copyEntityAction,
68
+ deleteEntityAction,
69
+ editEntityAction,
64
70
  OnCellValueChange,
65
71
  OnColumnResizeParams,
66
72
  UniqueFieldValidator,
@@ -69,14 +75,14 @@ import {
69
75
  } from "../common";
70
76
  import { PopupFormField } from "../EntityCollectionTable/internal/popup_field/PopupFormField";
71
77
  import { GetPropertyForProps } from "../EntityCollectionTable/EntityCollectionTableProps";
72
- import { copyEntityAction, deleteEntityAction, editEntityAction } from "../common/default_entity_actions";
73
78
  import { DeleteEntityDialog } from "../DeleteEntityDialog";
74
79
  import { useAnalyticsController } from "../../hooks/useAnalyticsController";
75
80
  import { useSelectionController } from "./useSelectionController";
76
81
  import { EntityCollectionViewStartActions } from "./EntityCollectionViewStartActions";
77
82
  import { addRecentId, getRecentIds } from "./utils";
83
+ import { useScrollRestoration } from "../common/useScrollRestoration";
78
84
 
79
- const COLLECTION_GROUP_PARENT_ID = "collectionGroupParent";
85
+ const DEFAULT_ENTITY_OPEN_MODE: "side_panel" | "full_screen" = "side_panel";
80
86
 
81
87
  /**
82
88
  * @group Components
@@ -98,6 +104,11 @@ export type EntityCollectionViewProps<M extends Record<string, any>> = {
98
104
 
99
105
  className?: string;
100
106
 
107
+ /**
108
+ * If true, this view will store its filter and sorting status in the url params
109
+ */
110
+ updateUrl?: boolean;
111
+
101
112
  } & EntityCollection<M>;
102
113
 
103
114
  /**
@@ -130,6 +141,7 @@ export const EntityCollectionView = React.memo(
130
141
  parentCollectionIds,
131
142
  isSubCollection,
132
143
  className,
144
+ updateUrl,
133
145
  ...collectionProp
134
146
  }: EntityCollectionViewProps<M>
135
147
  ) {
@@ -146,11 +158,15 @@ export const EntityCollectionView = React.memo(
146
158
 
147
159
  const containerRef = React.useRef<HTMLDivElement>(null);
148
160
 
161
+ const scrollRestoration = useScrollRestoration();
162
+
149
163
  const collection = useMemo(() => {
150
164
  const userOverride = userConfigPersistence?.getCollectionConfig<M>(fullPath);
151
165
  return (userOverride ? mergeDeep(collectionProp, userOverride) : collectionProp) as EntityCollection<M>;
152
166
  }, [collectionProp, fullPath, userConfigPersistence?.getCollectionConfig]);
153
167
 
168
+ const openEntityMode = collection?.openEntityMode ?? DEFAULT_ENTITY_OPEN_MODE;
169
+
154
170
  const collectionRef = React.useRef(collection);
155
171
  useEffect(() => {
156
172
  collectionRef.current = collection;
@@ -193,14 +209,12 @@ export const EntityCollectionView = React.memo(
193
209
  setSelectedEntities
194
210
  } = usedSelectionController;
195
211
 
196
- // useEffect(() => {
197
- // setDeleteEntityClicked(undefined);
198
- // }, [selectedEntities]);
199
-
200
- const tableController = useDataSourceEntityCollectionTableController<M>({
212
+ const tableController = useDataSourceTableController<M>({
201
213
  fullPath,
202
214
  collection,
203
- lastDeleteTimestamp
215
+ lastDeleteTimestamp,
216
+ scrollRestoration,
217
+ updateUrl
204
218
  });
205
219
 
206
220
  const tableKey = React.useRef<string>(Math.random().toString(36));
@@ -217,13 +231,21 @@ export const EntityCollectionView = React.memo(
217
231
  path: clickedEntity.path,
218
232
  entityId: clickedEntity.id
219
233
  });
220
- return sideEntityController.open({
221
- entityId: clickedEntity.id,
222
- path: clickedEntity.path,
234
+
235
+ if (collection) {
236
+ addRecentId(collection.id, clickedEntity.id);
237
+ }
238
+
239
+ const path = collection?.collectionGroup ? clickedEntity.path : (fullPath ?? clickedEntity.path);
240
+ navigateToEntity({
241
+ navigation,
242
+ path,
243
+ sideEntityController,
244
+ openEntityMode,
223
245
  collection,
224
- updateUrl: true,
225
- onClose: unselectNavigatedEntity,
246
+ entityId: clickedEntity.id
226
247
  });
248
+
227
249
  }, [unselectNavigatedEntity, sideEntityController]);
228
250
 
229
251
  const onNewClick = useCallback(() => {
@@ -232,12 +254,15 @@ export const EntityCollectionView = React.memo(
232
254
  analyticsController.onAnalyticsEvent?.("new_entity_click", {
233
255
  path: fullPath
234
256
  });
235
- sideEntityController.open({
236
- path: fullPath,
257
+ navigateToEntity({
258
+ openEntityMode,
237
259
  collection,
238
- updateUrl: true,
239
- onClose: unselectNavigatedEntity,
240
- });
260
+ entityId: undefined,
261
+ path: fullPath,
262
+ sideEntityController,
263
+ navigation,
264
+ onClose: unselectNavigatedEntity
265
+ })
241
266
  }, [fullPath, sideEntityController]);
242
267
 
243
268
  const onMultipleDeleteClick = () => {
@@ -323,7 +348,7 @@ export const EntityCollectionView = React.memo(
323
348
  const updatedValues = setIn({ ...entity.values }, propertyKey, value);
324
349
 
325
350
  const saveProps: SaveEntityProps = {
326
- path: fullPath,
351
+ path: entity.path ?? fullPath,
327
352
  entityId: entity.id,
328
353
  values: updatedValues,
329
354
  previousValues: entity.values,
@@ -349,11 +374,11 @@ export const EntityCollectionView = React.memo(
349
374
 
350
375
  };
351
376
 
352
- const resolvedFullPath = navigation.resolveAliasesFrom(fullPath);
377
+ const resolvedFullPath = navigation.resolveIdsFrom(fullPath);
353
378
  const resolvedCollection = useMemo(() => resolveCollection<M>({
354
379
  collection,
355
380
  path: fullPath,
356
- fields: customizationController.propertyConfigs
381
+ propertyConfigs: customizationController.propertyConfigs
357
382
  }), [collection, fullPath]);
358
383
 
359
384
  const getPropertyFor = useCallback(({
@@ -374,7 +399,7 @@ export const EntityCollectionView = React.memo(
374
399
  path: entity.path,
375
400
  values: entity.values,
376
401
  entityId: entity.id,
377
- fields: customizationController.propertyConfigs
402
+ propertyConfigs: customizationController.propertyConfigs
378
403
  });
379
404
  }, [collection.properties, customizationController.propertyConfigs, resolvedCollection.properties]);
380
405
 
@@ -393,13 +418,15 @@ export const EntityCollectionView = React.memo(
393
418
  startIcon={<KeyboardTabIcon size={"small"}/>}
394
419
  onClick={(event: any) => {
395
420
  event.stopPropagation();
396
- sideEntityController.open({
397
- path: fullPath,
398
- entityId: entity.id,
399
- selectedSubPath: subcollection.id ?? subcollection.path,
421
+ navigateToEntity({
422
+ openEntityMode,
400
423
  collection,
401
- updateUrl: true,
402
- });
424
+ entityId: entity.id,
425
+ selectedTab: subcollection.id ?? subcollection.path,
426
+ path: fullPath,
427
+ navigation,
428
+ sideEntityController
429
+ })
403
430
  }}>
404
431
  {subcollection.name}
405
432
  </Button>
@@ -422,7 +449,7 @@ export const EntityCollectionView = React.memo(
422
449
  <ReferencePreview
423
450
  key={reference.path + "/" + reference.id}
424
451
  reference={reference}
425
- size={"smallest"}/>
452
+ size={"small"}/>
426
453
  );
427
454
  })}
428
455
  </div>
@@ -458,7 +485,7 @@ export const EntityCollectionView = React.memo(
458
485
  if (deleteEnabled)
459
486
  actions.push(deleteEntityAction);
460
487
  if (customEntityActions)
461
- actions.push(...customEntityActions);
488
+ return mergeEntityActions(actions, customEntityActions);
462
489
  return actions;
463
490
  };
464
491
 
@@ -482,7 +509,7 @@ export const EntityCollectionView = React.memo(
482
509
  frozen?: boolean
483
510
  }) => {
484
511
 
485
- const isSelected = usedSelectionController.selectedEntities.map(e => e.id).includes(entity.id);
512
+ const isSelected = Boolean(usedSelectionController.selectedEntities.find(e => e.id == entity.id && e.path == entity.path));
486
513
 
487
514
  const actions = getActionsForEntity({
488
515
  entity,
@@ -505,6 +532,7 @@ export const EntityCollectionView = React.memo(
505
532
  hideId={collection?.hideIdFromCollection}
506
533
  onCollectionChange={updateLastDeleteTimestamp}
507
534
  selectionController={usedSelectionController}
535
+ openEntityMode={openEntityMode}
508
536
  />
509
537
  );
510
538
 
@@ -538,7 +566,7 @@ export const EntityCollectionView = React.memo(
538
566
  </div>}
539
567
  >
540
568
 
541
- {collection.description && <div className="m-4 text-gray-900 dark:text-white">
569
+ {collection.description && <div className="m-4 text-surface-900 dark:text-white">
542
570
  <Markdown source={collection.description}/>
543
571
  </div>}
544
572
 
@@ -617,6 +645,8 @@ export const EntityCollectionView = React.memo(
617
645
  properties={resolvedCollection.properties}
618
646
  getPropertyFor={getPropertyFor}
619
647
  onTextSearchClick={textSearchInitialised ? undefined : onTextSearchClick}
648
+ onScroll={tableController.onScroll}
649
+ initialScroll={tableController.initialScroll}
620
650
  textSearchLoading={textSearchLoading}
621
651
  textSearchEnabled={textSearchEnabled}
622
652
  actionsStart={<EntityCollectionViewStartActions
@@ -662,16 +692,17 @@ export const EntityCollectionView = React.memo(
662
692
  additionalIDHeaderWidget={<EntityIdHeaderWidget
663
693
  path={fullPath}
664
694
  collection={collection}/>}
695
+ openEntityMode={openEntityMode}
665
696
  />
666
697
 
667
698
  {popupCell && <PopupFormField
668
- key={`popup_form_${popupCell?.propertyKey}_${popupCell?.entity?.id}`}
699
+ key={`popup_form_${popupCell?.propertyKey}_${popupCell?.entityId}`}
669
700
  open={Boolean(popupCell)}
670
701
  onClose={onPopupClose}
671
702
  cellRect={popupCell?.cellRect}
672
703
  propertyKey={popupCell?.propertyKey}
673
704
  collection={collection}
674
- entity={popupCell.entity}
705
+ entityId={popupCell.entityId}
675
706
  tableKey={tableKey.current}
676
707
  customFieldValidator={uniqueFieldValidator}
677
708
  path={resolvedFullPath}
@@ -692,7 +723,7 @@ export const EntityCollectionView = React.memo(
692
723
  </div>
693
724
  );
694
725
  }, (a, b) => {
695
- return equal(a.fullPath, b.fullPath) &&
726
+ return equal(a.path, b.path) &&
696
727
  equal(a.parentCollectionIds, b.parentCollectionIds) &&
697
728
  equal(a.isSubCollection, b.isSubCollection) &&
698
729
  equal(a.className, b.className) &&
@@ -709,6 +740,7 @@ export const EntityCollectionView = React.memo(
709
740
  equal(a.textSearchEnabled, b.textSearchEnabled) &&
710
741
  equal(a.additionalFields, b.additionalFields) &&
711
742
  equal(a.sideDialogWidth, b.sideDialogWidth) &&
743
+ equal(a.openEntityMode, b.openEntityMode) &&
712
744
  equal(a.forceFilter, b.forceFilter);
713
745
  }) as React.FunctionComponent<EntityCollectionViewProps<any>>
714
746
 
@@ -733,7 +765,7 @@ function EntitiesCount({
733
765
 
734
766
  const sortByProperty = sortBy ? sortBy[0] : undefined;
735
767
  const currentSort = sortBy ? sortBy[1] : undefined;
736
- const resolvedPath = useMemo(() => navigation.resolveAliasesFrom(fullPath), [fullPath, navigation.resolveAliasesFrom]);
768
+ const resolvedPath = useMemo(() => navigation.resolveIdsFrom(fullPath), [fullPath, navigation.resolveIdsFrom]);
737
769
 
738
770
  useEffect(() => {
739
771
  if (dataSource.countEntities)
@@ -780,11 +812,14 @@ function EntityIdHeaderWidget({
780
812
  collection: EntityCollection,
781
813
  path: string
782
814
  }) {
815
+
816
+ const navigation = useNavigationController();
783
817
  const [openPopup, setOpenPopup] = React.useState(false);
784
818
  const [searchString, setSearchString] = React.useState("");
785
819
  const [recentIds, setRecentIds] = React.useState<string[]>(getRecentIds(collection.id));
786
820
  const sideEntityController = useSideEntityController();
787
821
 
822
+ const openEntityMode = collection?.openEntityMode ?? DEFAULT_ENTITY_OPEN_MODE;
788
823
 
789
824
  return (
790
825
  <Tooltip title={!openPopup ? "Find by ID" : undefined} asChild={false}>
@@ -799,19 +834,23 @@ function EntityIdHeaderWidget({
799
834
  <SearchIcon size={"small"}/>
800
835
  </IconButton>
801
836
  }>
802
- <div className={cls("my-2 rounded-lg bg-gray-50 dark:bg-gray-950 text-gray-900 dark:text-white")}>
837
+ <div
838
+ className={cls("my-2 rounded-lg bg-surface-50 dark:bg-surface-950 text-surface-900 dark:text-white")}>
803
839
  <form noValidate={true}
804
840
  onSubmit={(e) => {
805
841
  e.preventDefault();
806
842
  if (!searchString) return;
807
843
  setOpenPopup(false);
808
- setRecentIds(addRecentId(collection.id, searchString.trim()));
809
- return sideEntityController.open({
810
- entityId: searchString.trim(),
811
- path,
844
+ const entityId = searchString.trim();
845
+ setRecentIds(addRecentId(collection.id, entityId));
846
+ navigateToEntity({
847
+ openEntityMode,
812
848
  collection,
813
- updateUrl: true
814
- });
849
+ entityId,
850
+ path,
851
+ sideEntityController,
852
+ navigation
853
+ })
815
854
  }}
816
855
  className={"w-96 max-w-full"}>
817
856
 
@@ -824,7 +863,7 @@ function EntityIdHeaderWidget({
824
863
  setSearchString(e.target.value);
825
864
  }}
826
865
  value={searchString}
827
- className={"rounded-lg bg-white dark:bg-gray-800 flex-grow bg-transparent outline-none p-2 " + focusedDisabled}/>
866
+ className={"rounded-lg bg-white dark:bg-surface-800 flex-grow bg-transparent outline-none p-2 " + focusedDisabled}/>
828
867
  <Button variant={"text"}
829
868
  disabled={!(searchString.trim())}
830
869
  type={"submit"}
@@ -838,12 +877,14 @@ function EntityIdHeaderWidget({
838
877
  hover={true}
839
878
  onClick={() => {
840
879
  setOpenPopup(false);
841
- sideEntityController.open({
880
+ navigateToEntity({
881
+ openEntityMode,
882
+ collection,
842
883
  entityId: id,
843
884
  path,
844
- collection,
845
- updateUrl: true
846
- });
885
+ sideEntityController,
886
+ navigation
887
+ })
847
888
  }}
848
889
  includeEntityLink={false}
849
890
  size={"small"}/>
@@ -1,6 +1,6 @@
1
1
  import React from "react";
2
2
 
3
- import { canCreateEntity, canDeleteEntity, fullPathToCollectionSegments } from "../../util";
3
+ import { canCreateEntity, canDeleteEntity } from "../../util";
4
4
  import { useAuthController, useCustomizationController, useFireCMSContext, useLargeLayout } from "../../hooks";
5
5
  import { CollectionActionsProps, EntityCollection, EntityTableController, SelectionController } from "../../types";
6
6
  import { AddIcon, Button, DeleteIcon, IconButton, Tooltip } from "@firecms/ui";
@@ -124,7 +124,9 @@ export function EntityCollectionViewActions<M extends Record<string, any>>({
124
124
 
125
125
  return (
126
126
  <>
127
- {actions}
127
+ <ErrorBoundary>
128
+ {actions}
129
+ </ErrorBoundary>
128
130
  {multipleDeleteButton}
129
131
  {addButton}
130
132
  </>