@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.
Files changed (201) hide show
  1. package/dist/app/Scaffold.d.ts +4 -0
  2. package/dist/components/ArrayContainer.d.ts +14 -3
  3. package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +2 -1
  4. package/dist/components/EntityCollectionTable/EntityCollectionTable.d.ts +2 -2
  5. package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +15 -1
  6. package/dist/components/EntityCollectionTable/index.d.ts +1 -1
  7. package/dist/components/EntityCollectionView/EntityCollectionView.d.ts +8 -0
  8. package/dist/components/EntityJsonPreview.d.ts +3 -0
  9. package/dist/components/PropertyIdCopyTooltip.d.ts +1 -1
  10. package/dist/components/SelectableTable/SelectableTable.d.ts +12 -2
  11. package/dist/components/SelectableTable/filters/ReferenceFilterField.d.ts +1 -1
  12. package/dist/components/UnsavedChangesDialog.d.ts +8 -0
  13. package/dist/components/VirtualTable/VirtualTableProps.d.ts +13 -0
  14. package/dist/components/common/default_entity_actions.d.ts +0 -2
  15. package/dist/components/common/index.d.ts +1 -1
  16. package/dist/components/common/useColumnsIds.d.ts +1 -0
  17. package/dist/components/common/{useDataSourceEntityCollectionTableController.d.ts → useDataSourceTableController.d.ts} +10 -2
  18. package/dist/components/common/useDebouncedCallback.d.ts +1 -0
  19. package/dist/components/common/useScrollRestoration.d.ts +14 -0
  20. package/dist/contexts/BreacrumbsContext.d.ts +8 -0
  21. package/dist/core/DefaultAppBar.d.ts +8 -2
  22. package/dist/core/EntityEditView.d.ts +36 -21
  23. package/dist/core/EntityEditViewFormActions.d.ts +2 -0
  24. package/dist/core/FireCMS.d.ts +2 -2
  25. package/dist/core/FireCMSRouter.d.ts +4 -0
  26. package/dist/core/NavigationRoutes.d.ts +0 -1
  27. package/dist/core/SideDialogs.d.ts +4 -2
  28. package/dist/core/index.d.ts +2 -1
  29. package/dist/form/EntityForm.d.ts +49 -0
  30. package/dist/form/EntityFormActions.d.ts +17 -0
  31. package/dist/form/PropertyFieldBinding.d.ts +1 -1
  32. package/dist/form/components/FormEntry.d.ts +6 -0
  33. package/dist/form/components/FormLayout.d.ts +5 -0
  34. package/dist/form/components/index.d.ts +2 -0
  35. package/dist/form/field_bindings/ArrayCustomShapedFieldBinding.d.ts +1 -1
  36. package/dist/form/field_bindings/ArrayOfReferencesFieldBinding.d.ts +1 -1
  37. package/dist/form/field_bindings/BlockFieldBinding.d.ts +1 -1
  38. package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
  39. package/dist/form/field_bindings/MarkdownEditorFieldBinding.d.ts +1 -1
  40. package/dist/form/field_bindings/RepeatFieldBinding.d.ts +1 -1
  41. package/dist/form/index.d.ts +16 -16
  42. package/dist/hooks/data/save.d.ts +1 -1
  43. package/dist/hooks/data/useEntityFetch.d.ts +2 -1
  44. package/dist/hooks/useBreadcrumbsController.d.ts +26 -0
  45. package/dist/hooks/useBuildNavigationController.d.ts +4 -1
  46. package/dist/hooks/useModeController.d.ts +1 -2
  47. package/dist/index.es.js +15842 -14396
  48. package/dist/index.es.js.map +1 -1
  49. package/dist/index.umd.js +15833 -14389
  50. package/dist/index.umd.js.map +1 -1
  51. package/dist/internal/useBuildDataSource.d.ts +3 -2
  52. package/dist/internal/useBuildSideEntityController.d.ts +3 -3
  53. package/dist/internal/useUnsavedChangesDialog.d.ts +7 -9
  54. package/dist/routes/CustomCMSRoute.d.ts +4 -0
  55. package/dist/routes/FireCMSRoute.d.ts +1 -0
  56. package/dist/routes/HomePageRoute.d.ts +3 -0
  57. package/dist/types/collections.d.ts +36 -10
  58. package/dist/types/datasource.d.ts +2 -2
  59. package/dist/types/dialogs_controller.d.ts +7 -3
  60. package/dist/types/entities.d.ts +1 -1
  61. package/dist/types/entity_actions.d.ts +10 -0
  62. package/dist/types/fields.d.ts +13 -3
  63. package/dist/types/firecms.d.ts +1 -1
  64. package/dist/types/navigation.d.ts +33 -12
  65. package/dist/types/plugins.d.ts +2 -0
  66. package/dist/types/properties.d.ts +40 -4
  67. package/dist/types/side_entity_controller.d.ts +6 -1
  68. package/dist/util/builders.d.ts +1 -1
  69. package/dist/util/createFormexStub.d.ts +2 -0
  70. package/dist/util/entity_actions.d.ts +2 -0
  71. package/dist/util/entity_cache.d.ts +23 -0
  72. package/dist/util/index.d.ts +1 -0
  73. package/dist/util/navigation_from_path.d.ts +6 -1
  74. package/dist/util/navigation_utils.d.ts +13 -1
  75. package/dist/util/objects.d.ts +1 -1
  76. package/dist/util/property_utils.d.ts +2 -2
  77. package/dist/util/references.d.ts +2 -2
  78. package/dist/util/resolutions.d.ts +12 -2
  79. package/package.json +20 -21
  80. package/src/app/Scaffold.tsx +13 -3
  81. package/src/components/ArrayContainer.tsx +60 -24
  82. package/src/components/CircularProgressCenter.tsx +1 -1
  83. package/src/components/DeleteEntityDialog.tsx +5 -3
  84. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +46 -23
  85. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +10 -4
  86. package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +18 -1
  87. package/src/components/EntityCollectionTable/index.tsx +1 -1
  88. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +3 -3
  89. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +10 -13
  90. package/src/components/EntityCollectionView/EntityCollectionView.tsx +105 -47
  91. package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +4 -2
  92. package/src/components/EntityJsonPreview.tsx +66 -0
  93. package/src/components/EntityPreview.tsx +10 -3
  94. package/src/components/EntityView.tsx +4 -1
  95. package/src/components/NotFoundPage.tsx +2 -2
  96. package/src/components/PropertyIdCopyTooltip.tsx +2 -3
  97. package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +14 -7
  98. package/src/components/SelectableTable/SelectableTable.tsx +18 -3
  99. package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +7 -7
  100. package/src/components/UnsavedChangesDialog.tsx +42 -0
  101. package/src/components/VirtualTable/VirtualTable.tsx +48 -3
  102. package/src/components/VirtualTable/VirtualTableProps.tsx +15 -0
  103. package/src/components/VirtualTable/fields/VirtualTableInput.tsx +1 -1
  104. package/src/components/common/default_entity_actions.tsx +37 -37
  105. package/src/components/common/index.ts +1 -1
  106. package/src/components/common/useColumnsIds.tsx +1 -1
  107. package/src/components/common/useDataSourceTableController.tsx +420 -0
  108. package/src/components/common/useDebouncedCallback.tsx +20 -0
  109. package/src/components/common/useScrollRestoration.tsx +68 -0
  110. package/src/contexts/BreacrumbsContext.tsx +38 -0
  111. package/src/contexts/DialogsProvider.tsx +3 -2
  112. package/src/contexts/ModeController.tsx +1 -3
  113. package/src/core/DefaultAppBar.tsx +59 -17
  114. package/src/core/DefaultDrawer.tsx +1 -1
  115. package/src/core/EntityEditView.tsx +354 -1000
  116. package/src/core/EntityEditViewFormActions.tsx +199 -0
  117. package/src/core/EntitySidePanel.tsx +85 -15
  118. package/src/core/FireCMS.tsx +20 -16
  119. package/src/core/FireCMSRouter.tsx +17 -0
  120. package/src/core/NavigationRoutes.tsx +23 -32
  121. package/src/core/SideDialogs.tsx +20 -11
  122. package/src/core/index.tsx +4 -2
  123. package/src/form/EntityForm.tsx +782 -0
  124. package/src/form/EntityFormActions.tsx +169 -0
  125. package/src/form/PropertyFieldBinding.tsx +21 -16
  126. package/src/form/components/FormEntry.tsx +22 -0
  127. package/src/form/components/FormLayout.tsx +16 -0
  128. package/src/form/components/LabelWithIcon.tsx +6 -3
  129. package/src/form/components/StorageUploadProgress.tsx +1 -1
  130. package/src/form/components/index.tsx +2 -0
  131. package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +8 -5
  132. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +5 -2
  133. package/src/form/field_bindings/BlockFieldBinding.tsx +5 -3
  134. package/src/form/field_bindings/DateTimeFieldBinding.tsx +1 -0
  135. package/src/form/field_bindings/KeyValueFieldBinding.tsx +1 -1
  136. package/src/form/field_bindings/MapFieldBinding.tsx +14 -16
  137. package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +15 -8
  138. package/src/form/field_bindings/MultiSelectFieldBinding.tsx +3 -3
  139. package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +2 -2
  140. package/src/form/field_bindings/ReferenceFieldBinding.tsx +1 -1
  141. package/src/form/field_bindings/RepeatFieldBinding.tsx +13 -4
  142. package/src/form/field_bindings/SelectFieldBinding.tsx +2 -2
  143. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +11 -6
  144. package/src/form/field_bindings/SwitchFieldBinding.tsx +1 -0
  145. package/src/form/field_bindings/TextFieldBinding.tsx +1 -0
  146. package/src/form/index.tsx +16 -32
  147. package/src/form/validation.ts +12 -6
  148. package/src/hooks/data/save.ts +25 -30
  149. package/src/hooks/data/useCollectionFetch.tsx +1 -1
  150. package/src/hooks/data/useEntityFetch.tsx +5 -1
  151. package/src/hooks/useBreadcrumbsController.tsx +31 -0
  152. package/src/hooks/useBuildModeController.tsx +15 -28
  153. package/src/hooks/useBuildNavigationController.tsx +81 -24
  154. package/src/hooks/useFireCMSContext.tsx +0 -30
  155. package/src/hooks/useLargeLayout.tsx +0 -35
  156. package/src/hooks/useModeController.tsx +1 -2
  157. package/src/hooks/useResolvedNavigationFrom.tsx +4 -6
  158. package/src/internal/useBuildDataSource.ts +9 -5
  159. package/src/internal/useBuildSideDialogsController.tsx +3 -2
  160. package/src/internal/useBuildSideEntityController.tsx +135 -88
  161. package/src/internal/useUnsavedChangesDialog.tsx +126 -92
  162. package/src/preview/PropertyPreview.tsx +12 -10
  163. package/src/preview/components/UrlComponentPreview.tsx +17 -18
  164. package/src/preview/property_previews/ArrayOfMapsPreview.tsx +4 -3
  165. package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +4 -3
  166. package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +4 -2
  167. package/src/preview/property_previews/ArrayOfStringsPreview.tsx +4 -3
  168. package/src/preview/property_previews/ArrayOneOfPreview.tsx +4 -2
  169. package/src/preview/property_previews/ArrayPropertyPreview.tsx +4 -2
  170. package/src/preview/property_previews/MapPropertyPreview.tsx +3 -2
  171. package/src/routes/CustomCMSRoute.tsx +21 -0
  172. package/src/routes/FireCMSRoute.tsx +246 -0
  173. package/src/routes/HomePageRoute.tsx +17 -0
  174. package/src/types/collections.ts +45 -13
  175. package/src/types/datasource.ts +2 -1
  176. package/src/types/dialogs_controller.tsx +7 -3
  177. package/src/types/entities.ts +1 -1
  178. package/src/types/entity_actions.tsx +12 -0
  179. package/src/types/fields.tsx +18 -3
  180. package/src/types/firecms.tsx +1 -1
  181. package/src/types/navigation.ts +41 -16
  182. package/src/types/plugins.tsx +2 -0
  183. package/src/types/properties.ts +48 -4
  184. package/src/types/side_dialogs_controller.tsx +2 -0
  185. package/src/types/side_entity_controller.tsx +11 -1
  186. package/src/util/builders.ts +5 -3
  187. package/src/util/createFormexStub.tsx +62 -0
  188. package/src/util/entity_actions.ts +28 -0
  189. package/src/util/entity_cache.ts +204 -0
  190. package/src/util/index.ts +1 -0
  191. package/src/util/join_collections.ts +6 -1
  192. package/src/util/navigation_from_path.ts +18 -7
  193. package/src/util/navigation_utils.ts +115 -14
  194. package/src/util/objects.ts +9 -2
  195. package/src/util/parent_references_from_path.ts +3 -3
  196. package/src/util/property_utils.tsx +7 -3
  197. package/src/util/references.ts +8 -6
  198. package/src/util/resolutions.ts +41 -12
  199. package/src/util/useStorageUploadController.tsx +60 -23
  200. package/src/components/common/useDataSourceEntityCollectionTableController.tsx +0 -236
  201. /package/src/util/{common.tsx → common.ts} +0 -0
@@ -72,6 +72,21 @@ export type EntityCollectionTableProps<M extends Record<string, any>,
72
72
  */
73
73
  onColumnResize?(params: OnColumnResizeParams): void;
74
74
 
75
+ /**
76
+ * Initial scroll position
77
+ */
78
+ initialScroll?: number;
79
+
80
+ /**
81
+ * Callback when the table is scrolled
82
+ * @param props
83
+ */
84
+ onScroll?: (props: {
85
+ scrollDirection: "forward" | "backward",
86
+ scrollOffset: number,
87
+ scrollUpdateWasRequested: boolean
88
+ }) => void;
89
+
75
90
  /**
76
91
  * Callback when the selected size of the table is changed
77
92
  */
@@ -90,7 +105,7 @@ export type EntityCollectionTableProps<M extends Record<string, any>,
90
105
 
91
106
  /**
92
107
  * Controller holding the logic for the table
93
- * {@link useDataSourceEntityCollectionTableController}
108
+ * {@link useDataSourceTableController}
94
109
  * {@link EntityTableController}
95
110
  */
96
111
  tableController: EntityTableController<M>;
@@ -136,6 +151,8 @@ export type EntityCollectionTableProps<M extends Record<string, any>,
136
151
  textSearchLoading?: boolean;
137
152
 
138
153
  enablePopupIcon: boolean;
154
+
155
+ openEntityMode?: "side_panel" | "full_screen";
139
156
  };
140
157
 
141
158
  export type GetPropertyForProps<M extends Record<string, any>> = {
@@ -8,5 +8,5 @@ export type {
8
8
 
9
9
  export * from "./PropertyTableCell";
10
10
  export * from "./EntityCollectionRowActions";
11
- export * from "../common/useDataSourceEntityCollectionTableController";
11
+ export * from "../common/useDataSourceTableController";
12
12
  export * from "./column_utils";
@@ -56,7 +56,7 @@ export function CollectionTableToolbar({
56
56
  <Select
57
57
  value={size as string}
58
58
  className="w-16 h-10"
59
- size={"medium"}
59
+ size={"small"}
60
60
  onValueChange={(v) => onSizeChanged(v as CollectionSize)}
61
61
  renderValue={(v) => <div className={"font-medium"}>{v.toUpperCase()}</div>}
62
62
  >
@@ -87,9 +87,9 @@ export function CollectionTableToolbar({
87
87
 
88
88
  <div className="flex items-center gap-2">
89
89
 
90
- {largeLayout && <div className="w-[22px]">
90
+ {largeLayout && <div className="w-[22px] mr-4">
91
91
  {loading &&
92
- <CircularProgress size={"small"}/>}
92
+ <CircularProgress size={"smallest"}/>}
93
93
  </div>}
94
94
 
95
95
  {(onTextSearch || onTextSearchClick) &&
@@ -20,10 +20,9 @@ import { useWindowSize } from "./useWindowSize";
20
20
  import { ElementResizeListener } from "./ElementResizeListener";
21
21
  import { getPropertyInPath, isReadOnly, resolveCollection } from "../../../../util";
22
22
  import { Button, CloseIcon, DialogActions, IconButton, Typography } from "@firecms/ui";
23
- import { PropertyFieldBinding } from "../../../../form";
24
- import { useCustomizationController, useDataSource, useFireCMSContext } from "../../../../hooks";
23
+ import { PropertyFieldBinding, yupToFormErrors } from "../../../../form";
24
+ import { useAuthController, useCustomizationController, useDataSource, useFireCMSContext } from "../../../../hooks";
25
25
  import { OnCellValueChangeParams } from "../../../common";
26
- import { yupToFormErrors } from "../../../../core/EntityEditView";
27
26
 
28
27
  interface PopupFormFieldProps<M extends Record<string, any>> {
29
28
  customFieldValidator?: CustomFieldValidator;
@@ -108,6 +107,7 @@ export function PopupFormFieldInternal<M extends Record<string, any>>({
108
107
  }) {
109
108
 
110
109
  const fireCMSContext = useFireCMSContext();
110
+ const authController = useAuthController();
111
111
  const customizationController = useCustomizationController();
112
112
 
113
113
  const [savingError, setSavingError] = React.useState<any>();
@@ -122,7 +122,8 @@ export function PopupFormFieldInternal<M extends Record<string, any>>({
122
122
  path,
123
123
  values: entity?.values,
124
124
  entityId,
125
- propertyConfigs: customizationController.propertyConfigs
125
+ propertyConfigs: customizationController.propertyConfigs,
126
+ authController
126
127
  })
127
128
  : undefined;
128
129
 
@@ -240,14 +241,7 @@ export function PopupFormFieldInternal<M extends Record<string, any>>({
240
241
  validation: (values) => {
241
242
  return validationSchema?.validate(values, { abortEarly: false })
242
243
  .then(() => ({}))
243
- .catch((e) => {
244
- // const errors: Record<string, string> = {};
245
- // e.inner.forEach((error: any) => {
246
- // errors[error.path] = error.message;
247
- // });
248
- // return errors;
249
- return yupToFormErrors(e);
250
- });
244
+ .catch(yupToFormErrors);
251
245
  },
252
246
  validateOnInitialRender: true,
253
247
  onSubmit: (values, actions) => {
@@ -278,7 +272,10 @@ export function PopupFormFieldInternal<M extends Record<string, any>>({
278
272
  path,
279
273
  setFieldValue,
280
274
  save: saveValue,
281
- formex
275
+ formex,
276
+ status: "existing",
277
+ openEntityMode: "side_panel",
278
+ disabled: false,
282
279
  };
283
280
 
284
281
  const property: ResolvedProperty<any> | undefined = propertyKey && getPropertyInPath(collection?.properties ?? {} as ResolvedProperties, propertyKey as string);
@@ -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
@@ -87,6 +93,10 @@ export type EntityCollectionViewProps<M extends Record<string, any>> = {
87
93
  * It defaults to the collection path if not provided.
88
94
  */
89
95
  fullPath?: string;
96
+ /**
97
+ * Full path using navigation ids.
98
+ */
99
+ fullIdPath?: string;
90
100
  /**
91
101
  * If this is a subcollection, specify the parent collection ids.
92
102
  */
@@ -98,6 +108,11 @@ export type EntityCollectionViewProps<M extends Record<string, any>> = {
98
108
 
99
109
  className?: string;
100
110
 
111
+ /**
112
+ * If true, this view will store its filter and sorting status in the url params
113
+ */
114
+ updateUrl?: boolean;
115
+
101
116
  } & EntityCollection<M>;
102
117
 
103
118
  /**
@@ -127,17 +142,20 @@ export type EntityCollectionViewProps<M extends Record<string, any>> = {
127
142
  export const EntityCollectionView = React.memo(
128
143
  function EntityCollectionView<M extends Record<string, any>>({
129
144
  fullPath: fullPathProp,
145
+ fullIdPath,
130
146
  parentCollectionIds,
131
147
  isSubCollection,
132
148
  className,
149
+ updateUrl,
133
150
  ...collectionProp
134
151
  }: EntityCollectionViewProps<M>
135
152
  ) {
136
153
 
154
+
137
155
  const context = useFireCMSContext();
156
+ const navigation = useNavigationController();
138
157
  const fullPath = fullPathProp ?? collectionProp.path;
139
158
  const dataSource = useDataSource(collectionProp);
140
- const navigation = useNavigationController();
141
159
  const sideEntityController = useSideEntityController();
142
160
  const authController = useAuthController();
143
161
  const userConfigPersistence = useUserConfigurationPersistence();
@@ -146,11 +164,15 @@ export const EntityCollectionView = React.memo(
146
164
 
147
165
  const containerRef = React.useRef<HTMLDivElement>(null);
148
166
 
167
+ const scrollRestoration = useScrollRestoration();
168
+
149
169
  const collection = useMemo(() => {
150
170
  const userOverride = userConfigPersistence?.getCollectionConfig<M>(fullPath);
151
171
  return (userOverride ? mergeDeep(collectionProp, userOverride) : collectionProp) as EntityCollection<M>;
152
172
  }, [collectionProp, fullPath, userConfigPersistence?.getCollectionConfig]);
153
173
 
174
+ const openEntityMode = collection?.openEntityMode ?? DEFAULT_ENTITY_OPEN_MODE;
175
+
154
176
  const collectionRef = React.useRef(collection);
155
177
  useEffect(() => {
156
178
  collectionRef.current = collection;
@@ -193,14 +215,12 @@ export const EntityCollectionView = React.memo(
193
215
  setSelectedEntities
194
216
  } = usedSelectionController;
195
217
 
196
- // useEffect(() => {
197
- // setDeleteEntityClicked(undefined);
198
- // }, [selectedEntities]);
199
-
200
- const tableController = useDataSourceEntityCollectionTableController<M>({
218
+ const tableController = useDataSourceTableController<M>({
201
219
  fullPath,
202
220
  collection,
203
- lastDeleteTimestamp
221
+ lastDeleteTimestamp,
222
+ scrollRestoration,
223
+ updateUrl
204
224
  });
205
225
 
206
226
  const tableKey = React.useRef<string>(Math.random().toString(36));
@@ -217,13 +237,22 @@ export const EntityCollectionView = React.memo(
217
237
  path: clickedEntity.path,
218
238
  entityId: clickedEntity.id
219
239
  });
220
- return sideEntityController.open({
221
- entityId: clickedEntity.id,
222
- path: clickedEntity.path,
240
+
241
+ if (collection) {
242
+ addRecentId(collection.id, clickedEntity.id);
243
+ }
244
+
245
+ const path = collection?.collectionGroup ? clickedEntity.path : (fullPath ?? clickedEntity.path);
246
+ navigateToEntity({
247
+ navigation,
248
+ path,
249
+ fullIdPath,
250
+ sideEntityController,
251
+ openEntityMode,
223
252
  collection,
224
- updateUrl: true,
225
- onClose: unselectNavigatedEntity,
253
+ entityId: clickedEntity.id
226
254
  });
255
+
227
256
  }, [unselectNavigatedEntity, sideEntityController]);
228
257
 
229
258
  const onNewClick = useCallback(() => {
@@ -232,12 +261,16 @@ export const EntityCollectionView = React.memo(
232
261
  analyticsController.onAnalyticsEvent?.("new_entity_click", {
233
262
  path: fullPath
234
263
  });
235
- sideEntityController.open({
236
- path: fullPath,
264
+ navigateToEntity({
265
+ openEntityMode,
237
266
  collection,
238
- updateUrl: true,
239
- onClose: unselectNavigatedEntity,
240
- });
267
+ entityId: undefined,
268
+ path: fullPath,
269
+ fullIdPath,
270
+ sideEntityController,
271
+ navigation,
272
+ onClose: unselectNavigatedEntity
273
+ })
241
274
  }, [fullPath, sideEntityController]);
242
275
 
243
276
  const onMultipleDeleteClick = () => {
@@ -323,7 +356,7 @@ export const EntityCollectionView = React.memo(
323
356
  const updatedValues = setIn({ ...entity.values }, propertyKey, value);
324
357
 
325
358
  const saveProps: SaveEntityProps = {
326
- path: fullPath,
359
+ path: entity.path ?? fullPath,
327
360
  entityId: entity.id,
328
361
  values: updatedValues,
329
362
  previousValues: entity.values,
@@ -349,11 +382,12 @@ export const EntityCollectionView = React.memo(
349
382
 
350
383
  };
351
384
 
352
- const resolvedFullPath = navigation.resolveAliasesFrom(fullPath);
385
+ const resolvedFullPath = navigation.resolveIdsFrom(fullPath);
353
386
  const resolvedCollection = useMemo(() => resolveCollection<M>({
354
387
  collection,
355
388
  path: fullPath,
356
- propertyConfigs: customizationController.propertyConfigs
389
+ propertyConfigs: customizationController.propertyConfigs,
390
+ authController,
357
391
  }), [collection, fullPath]);
358
392
 
359
393
  const getPropertyFor = useCallback(({
@@ -374,7 +408,8 @@ export const EntityCollectionView = React.memo(
374
408
  path: entity.path,
375
409
  values: entity.values,
376
410
  entityId: entity.id,
377
- propertyConfigs: customizationController.propertyConfigs
411
+ propertyConfigs: customizationController.propertyConfigs,
412
+ authController
378
413
  });
379
414
  }, [collection.properties, customizationController.propertyConfigs, resolvedCollection.properties]);
380
415
 
@@ -393,13 +428,16 @@ export const EntityCollectionView = React.memo(
393
428
  startIcon={<KeyboardTabIcon size={"small"}/>}
394
429
  onClick={(event: any) => {
395
430
  event.stopPropagation();
396
- sideEntityController.open({
397
- path: fullPath,
398
- entityId: entity.id,
399
- selectedSubPath: subcollection.id ?? subcollection.path,
431
+ navigateToEntity({
432
+ openEntityMode,
400
433
  collection,
401
- updateUrl: true,
402
- });
434
+ entityId: entity.id,
435
+ selectedTab: subcollection.id ?? subcollection.path,
436
+ path: fullPath,
437
+ fullIdPath,
438
+ navigation,
439
+ sideEntityController
440
+ })
403
441
  }}>
404
442
  {subcollection.name}
405
443
  </Button>
@@ -458,7 +496,7 @@ export const EntityCollectionView = React.memo(
458
496
  if (deleteEnabled)
459
497
  actions.push(deleteEntityAction);
460
498
  if (customEntityActions)
461
- actions.push(...customEntityActions);
499
+ return mergeEntityActions(actions, customEntityActions);
462
500
  return actions;
463
501
  };
464
502
 
@@ -500,11 +538,12 @@ export const EntityCollectionView = React.memo(
500
538
  highlightEntity={setHighlightedEntity}
501
539
  unhighlightEntity={unselectNavigatedEntity}
502
540
  collection={collection}
503
- fullPath={fullPath}
541
+ fullPath={fullIdPath ?? fullPath}
504
542
  actions={actions}
505
543
  hideId={collection?.hideIdFromCollection}
506
544
  onCollectionChange={updateLastDeleteTimestamp}
507
545
  selectionController={usedSelectionController}
546
+ openEntityMode={openEntityMode}
508
547
  />
509
548
  );
510
549
 
@@ -617,6 +656,8 @@ export const EntityCollectionView = React.memo(
617
656
  properties={resolvedCollection.properties}
618
657
  getPropertyFor={getPropertyFor}
619
658
  onTextSearchClick={textSearchInitialised ? undefined : onTextSearchClick}
659
+ onScroll={tableController.onScroll}
660
+ initialScroll={tableController.initialScroll}
620
661
  textSearchLoading={textSearchLoading}
621
662
  textSearchEnabled={textSearchEnabled}
622
663
  actionsStart={<EntityCollectionViewStartActions
@@ -661,7 +702,9 @@ export const EntityCollectionView = React.memo(
661
702
  getIdColumnWidth={getIdColumnWidth}
662
703
  additionalIDHeaderWidget={<EntityIdHeaderWidget
663
704
  path={fullPath}
705
+ fullIdPath={fullIdPath ?? fullPath}
664
706
  collection={collection}/>}
707
+ openEntityMode={openEntityMode}
665
708
  />
666
709
 
667
710
  {popupCell && <PopupFormField
@@ -692,7 +735,7 @@ export const EntityCollectionView = React.memo(
692
735
  </div>
693
736
  );
694
737
  }, (a, b) => {
695
- return equal(a.fullPath, b.fullPath) &&
738
+ return equal(a.path, b.path) &&
696
739
  equal(a.parentCollectionIds, b.parentCollectionIds) &&
697
740
  equal(a.isSubCollection, b.isSubCollection) &&
698
741
  equal(a.className, b.className) &&
@@ -709,6 +752,7 @@ export const EntityCollectionView = React.memo(
709
752
  equal(a.textSearchEnabled, b.textSearchEnabled) &&
710
753
  equal(a.additionalFields, b.additionalFields) &&
711
754
  equal(a.sideDialogWidth, b.sideDialogWidth) &&
755
+ equal(a.openEntityMode, b.openEntityMode) &&
712
756
  equal(a.forceFilter, b.forceFilter);
713
757
  }) as React.FunctionComponent<EntityCollectionViewProps<any>>
714
758
 
@@ -733,7 +777,7 @@ function EntitiesCount({
733
777
 
734
778
  const sortByProperty = sortBy ? sortBy[0] : undefined;
735
779
  const currentSort = sortBy ? sortBy[1] : undefined;
736
- const resolvedPath = useMemo(() => navigation.resolveAliasesFrom(fullPath), [fullPath, navigation.resolveAliasesFrom]);
780
+ const resolvedPath = useMemo(() => navigation.resolveIdsFrom(fullPath), [fullPath, navigation.resolveIdsFrom]);
737
781
 
738
782
  useEffect(() => {
739
783
  if (dataSource.countEntities)
@@ -775,16 +819,22 @@ function buildPropertyWidthOverwrite(key: string, width: number): PartialEntityC
775
819
 
776
820
  function EntityIdHeaderWidget({
777
821
  collection,
778
- path
822
+ path,
823
+ fullIdPath
779
824
  }: {
780
825
  collection: EntityCollection,
781
- path: string
826
+ path: string,
827
+ fullIdPath: string
782
828
  }) {
829
+
830
+ const navigation = useNavigationController();
783
831
  const [openPopup, setOpenPopup] = React.useState(false);
784
832
  const [searchString, setSearchString] = React.useState("");
785
833
  const [recentIds, setRecentIds] = React.useState<string[]>(getRecentIds(collection.id));
786
834
  const sideEntityController = useSideEntityController();
787
835
 
836
+ const openEntityMode = collection?.openEntityMode ?? DEFAULT_ENTITY_OPEN_MODE;
837
+
788
838
  return (
789
839
  <Tooltip title={!openPopup ? "Find by ID" : undefined} asChild={false}>
790
840
  <Popover
@@ -798,19 +848,24 @@ function EntityIdHeaderWidget({
798
848
  <SearchIcon size={"small"}/>
799
849
  </IconButton>
800
850
  }>
801
- <div className={cls("my-2 rounded-lg bg-surface-50 dark:bg-surface-950 text-surface-900 dark:text-white")}>
851
+ <div
852
+ className={cls("my-2 rounded-lg bg-surface-50 dark:bg-surface-950 text-surface-900 dark:text-white")}>
802
853
  <form noValidate={true}
803
854
  onSubmit={(e) => {
804
855
  e.preventDefault();
805
856
  if (!searchString) return;
806
857
  setOpenPopup(false);
807
- setRecentIds(addRecentId(collection.id, searchString.trim()));
808
- return sideEntityController.open({
809
- entityId: searchString.trim(),
810
- path,
858
+ const entityId = searchString.trim();
859
+ setRecentIds(addRecentId(collection.id, entityId));
860
+ navigateToEntity({
861
+ openEntityMode,
811
862
  collection,
812
- updateUrl: true
813
- });
863
+ entityId,
864
+ path,
865
+ fullIdPath,
866
+ sideEntityController,
867
+ navigation
868
+ })
814
869
  }}
815
870
  className={"w-96 max-w-full"}>
816
871
 
@@ -837,12 +892,15 @@ function EntityIdHeaderWidget({
837
892
  hover={true}
838
893
  onClick={() => {
839
894
  setOpenPopup(false);
840
- sideEntityController.open({
895
+ navigateToEntity({
896
+ openEntityMode,
897
+ collection,
841
898
  entityId: id,
842
899
  path,
843
- collection,
844
- updateUrl: true
845
- });
900
+ fullIdPath,
901
+ sideEntityController,
902
+ navigation
903
+ })
846
904
  }}
847
905
  includeEntityLink={false}
848
906
  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
  </>
@@ -0,0 +1,66 @@
1
+ import React, { useRef } from "react";
2
+ import { Highlight, themes } from "prism-react-renderer";
3
+ import { useModeController } from "../hooks";
4
+
5
+ export function EntityJsonPreview({ values }: { values: object }) {
6
+ const code = JSON.stringify(values, null, "\t");
7
+ const { mode } = useModeController();
8
+ const preRef = useRef<HTMLPreElement>(null);
9
+
10
+ // Global keydown handler
11
+ // const handleGlobalKeyDown = useCallback((e: KeyboardEvent) => {
12
+ // // Check for Control (Windows/Linux) or Command (macOS) + "a":
13
+ // if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "a") {
14
+ // // If our code view is mounted, perform selection
15
+ // if (preRef.current) {
16
+ // e.preventDefault();
17
+ // e.stopPropagation();
18
+ //
19
+ // const selection = window.getSelection();
20
+ // const range = document.createRange();
21
+ // range.selectNodeContents(preRef.current);
22
+ // if (selection) {
23
+ // selection.removeAllRanges();
24
+ // selection.addRange(range);
25
+ // }
26
+ // }
27
+ // }
28
+ // }, []);
29
+
30
+ // // Attach the global keydown listener when component mounts,
31
+ // // and remove it when it unmounts.
32
+ // useEffect(() => {
33
+ // document.addEventListener("keydown", handleGlobalKeyDown);
34
+ // return () => {
35
+ // document.removeEventListener("keydown", handleGlobalKeyDown);
36
+ // };
37
+ // }, [handleGlobalKeyDown]);
38
+
39
+ return (
40
+ <Highlight
41
+ theme={mode === "dark" ? themes.vsDark : themes.github}
42
+ code={code}
43
+ language="json"
44
+ >
45
+ {({ style, tokens, getLineProps, getTokenProps }) => (
46
+ <pre
47
+ // Bind the ref to our pre element so we can select its contents.
48
+ ref={preRef}
49
+ style={{
50
+ ...style,
51
+ backgroundColor: "inherit"
52
+ }}
53
+ className="max-w-6xl mx-auto p-8 rounded text-sm"
54
+ >
55
+ {tokens.map((line, i) => (
56
+ <div key={i} {...getLineProps({ line })} className="text-wrap">
57
+ {line.map((token, key) => (
58
+ <span key={key} {...getTokenProps({ token })} className="word-break" />
59
+ ))}
60
+ </div>
61
+ ))}
62
+ </pre>
63
+ )}
64
+ </Highlight>
65
+ );
66
+ }
@@ -13,7 +13,12 @@ import {
13
13
  } from "../util";
14
14
  import { cls, defaultBorderMixin, IconButton, KeyboardTabIcon, Skeleton, Tooltip, Typography } from "@firecms/ui";
15
15
  import { PreviewSize, PropertyPreview, SkeletonPropertyComponent } from "../preview";
16
- import { useCustomizationController, useNavigationController, useSideEntityController } from "../hooks";
16
+ import {
17
+ useAuthController,
18
+ useCustomizationController,
19
+ useNavigationController,
20
+ useSideEntityController
21
+ } from "../hooks";
17
22
  import { useAnalyticsController } from "../hooks/useAnalyticsController";
18
23
 
19
24
  export type EntityPreviewProps = {
@@ -46,6 +51,7 @@ export function EntityPreview({
46
51
  entity
47
52
  }: EntityPreviewProps) {
48
53
 
54
+ const authController = useAuthController();
49
55
  const analyticsController = useAnalyticsController();
50
56
  const sideEntityController = useSideEntityController();
51
57
  const customizationController = useCustomizationController();
@@ -62,10 +68,11 @@ export function EntityPreview({
62
68
  collection,
63
69
  path: entity.path,
64
70
  values: entity.values,
65
- propertyConfigs: customizationController.propertyConfigs
71
+ propertyConfigs: customizationController.propertyConfigs,
72
+ authController
66
73
  }), [collection]);
67
74
 
68
- const listProperties = useMemo(() => getEntityPreviewKeys(resolvedCollection, customizationController.propertyConfigs, previewProperties, size === "medium" || size === "large" ? 3 : 1),
75
+ const listProperties = useMemo(() => getEntityPreviewKeys(authController, resolvedCollection, customizationController.propertyConfigs, previewProperties, size === "medium" || size === "large" ? 3 : 1),
69
76
  [previewProperties, resolvedCollection, size]);
70
77
 
71
78
  const titleProperty = getEntityTitlePropertyKey(resolvedCollection, customizationController.propertyConfigs);
@@ -5,6 +5,7 @@ import { resolveCollection } from "../util";
5
5
  import { cls, defaultBorderMixin, IconButton, OpenInNewIcon } from "@firecms/ui";
6
6
  import { CustomizationController } from "../types/customization_controller";
7
7
  import { useCustomizationController } from "../hooks/useCustomizationController";
8
+ import { useAuthController } from "../hooks";
8
9
 
9
10
  /**
10
11
  * @group Components
@@ -24,13 +25,15 @@ export function EntityView<M extends Record<string, any>>(
24
25
  className
25
26
  }: EntityViewProps<M>) {
26
27
 
28
+ const authController = useAuthController();
27
29
  const customizationController: CustomizationController = useCustomizationController();
28
30
  const resolvedCollection: ResolvedEntityCollection<M> = useMemo(() => resolveCollection<M>({
29
31
  collection,
30
32
  path,
31
33
  entityId: entity.id,
32
34
  values: entity.values,
33
- propertyConfigs: customizationController.propertyConfigs
35
+ propertyConfigs: customizationController.propertyConfigs,
36
+ authController
34
37
  }), [collection, path, entity, customizationController.propertyConfigs]);
35
38
 
36
39
  const properties: ResolvedProperties = resolvedCollection.properties;
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import { Link as ReactLink } from "react-router-dom";
2
+ import { Link } from "react-router-dom";
3
3
  import { Button, Typography } from "@firecms/ui";
4
4
 
5
5
  export function NotFoundPage() {
@@ -17,7 +17,7 @@ export function NotFoundPage() {
17
17
  </Typography>
18
18
  <Button
19
19
  variant={"text"}
20
- component={ReactLink}
20
+ component={Link}
21
21
  to={"/"}>Back to home</Button>
22
22
  </div>
23
23
  </div>