@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
@@ -9,6 +9,7 @@ import {
9
9
  EntityCollection,
10
10
  EntityCollectionsBuilder,
11
11
  EntityReference,
12
+ NavigationBlocker,
12
13
  NavigationController,
13
14
  PermissionsBuilder,
14
15
  TopNavigationEntry,
@@ -26,14 +27,15 @@ import {
26
27
  resolvePermissions
27
28
  } from "../util";
28
29
  import { getParentReferencesFromPath } from "../util/parent_references_from_path";
30
+ import { useBlocker, useNavigate } from "react-router-dom";
29
31
 
30
32
  const DEFAULT_BASE_PATH = "/";
31
33
  const DEFAULT_COLLECTION_PATH = "/c";
32
34
 
33
- export type BuildNavigationContextProps<EC extends EntityCollection, UserType extends User> = {
35
+ export type BuildNavigationContextProps<EC extends EntityCollection, USER extends User> = {
34
36
  basePath?: string,
35
37
  baseCollectionPath?: string,
36
- authController: AuthController<UserType>;
38
+ authController: AuthController<USER>;
37
39
  collections?: EC[] | EntityCollectionsBuilder<EC>;
38
40
  collectionPermissions?: PermissionsBuilder;
39
41
  views?: CMSView[] | CMSViewsBuilder;
@@ -49,9 +51,14 @@ export type BuildNavigationContextProps<EC extends EntityCollection, UserType ex
49
51
  * @param collections
50
52
  */
51
53
  injectCollections?: (collections: EntityCollection[]) => EntityCollection[];
54
+
55
+ /**
56
+ * If true, the navigation logic will not be updated until this flag is false
57
+ */
58
+ disabled?: boolean;
52
59
  };
53
60
 
54
- export function useBuildNavigationController<EC extends EntityCollection, UserType extends User>(props: BuildNavigationContextProps<EC, UserType>): NavigationController {
61
+ export function useBuildNavigationController<EC extends EntityCollection, USER extends User>(props: BuildNavigationContextProps<EC, USER>): NavigationController {
55
62
  const {
56
63
  basePath = DEFAULT_BASE_PATH,
57
64
  baseCollectionPath = DEFAULT_COLLECTION_PATH,
@@ -63,9 +70,12 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
63
70
  viewsOrder,
64
71
  userConfigPersistence,
65
72
  dataSourceDelegate,
66
- injectCollections
73
+ injectCollections,
74
+ disabled
67
75
  } = props;
68
76
 
77
+ const navigate = useNavigate();
78
+
69
79
  const collectionsRef = useRef<EntityCollection[] | undefined>();
70
80
  const viewsRef = useRef<CMSView[] | undefined>();
71
81
  const adminViewsRef = useRef<CMSView[] | undefined>();
@@ -185,7 +195,7 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
185
195
 
186
196
  const refreshNavigation = useCallback(async () => {
187
197
 
188
- if (authController.initialLoading)
198
+ if (disabled || authController.initialLoading)
189
199
  return;
190
200
 
191
201
  console.debug("Refreshing navigation");
@@ -202,6 +212,7 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
202
212
  let shouldUpdateTopLevelNav = false;
203
213
  if (!areCollectionListsEqual(collectionsRef.current ?? [], resolvedCollections)) {
204
214
  collectionsRef.current = resolvedCollections;
215
+ console.debug("Collections have changed", resolvedCollections);
205
216
  shouldUpdateTopLevelNav = true;
206
217
  }
207
218
  if (collectionsRef.current === undefined) {
@@ -236,6 +247,7 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
236
247
  collectionPermissions,
237
248
  authController.user,
238
249
  authController.initialLoading,
250
+ disabled,
239
251
  viewsProp,
240
252
  adminViewsProp,
241
253
  computeTopNavigation,
@@ -331,16 +343,7 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
331
343
  throw Error("Expected path starting with " + fullCollectionPath);
332
344
  }, [fullCollectionPath]);
333
345
 
334
- const buildUrlEditCollectionPath = useCallback(({
335
- path
336
- }: {
337
- path: string
338
- }): string => {
339
- return `s/edit/${encodePath(path)}`;
340
- },
341
- []);
342
-
343
- const resolveAliasesFrom = useCallback((path: string): string => {
346
+ const resolveIdsFrom = useCallback((path: string): string => {
344
347
  const collections = collectionsRef.current ?? [];
345
348
  return resolveCollectionPathIds(path, collections);
346
349
  }, []);
@@ -400,24 +403,16 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
400
403
  isUrlCollectionPath,
401
404
  urlPathToDataPath,
402
405
  buildUrlCollectionPath,
403
- buildUrlEditCollectionPath,
404
- buildCMSUrlPath,
405
- resolveAliasesFrom,
406
+ resolveIdsFrom,
406
407
  topLevelNavigation,
407
408
  refreshNavigation,
408
409
  getParentReferencesFromPath: getAllParentReferencesForPath,
409
410
  getParentCollectionIds,
410
- convertIdsToPaths
411
+ convertIdsToPaths,
412
+ navigate,
411
413
  };
412
414
  }
413
415
 
414
- export function getSidePanelKey(path: string, entityId?: string) {
415
- if (entityId)
416
- return `${removeInitialAndTrailingSlashes(path)}/${removeInitialAndTrailingSlashes(entityId)}`;
417
- else
418
- return removeInitialAndTrailingSlashes(path);
419
- }
420
-
421
416
  function encodePath(input: string) {
422
417
  return encodeURIComponent(removeInitialAndTrailingSlashes(input))
423
418
  .replaceAll("%2F", "/")
@@ -426,9 +421,10 @@ function encodePath(input: string) {
426
421
 
427
422
  function filterOutNotAllowedCollections(resolvedCollections: EntityCollection[], authController: AuthController<User>): EntityCollection[] {
428
423
  return resolvedCollections
424
+ .filter((c) => Boolean(c.path))
429
425
  .filter((c) => {
430
426
  if (!c.permissions) return true;
431
- const resolvedPermissions = resolvePermissions(c, authController, c.path, null)
427
+ const resolvedPermissions = resolvePermissions(c, authController, c.path, null);
432
428
  return resolvedPermissions?.read !== false;
433
429
  })
434
430
  .map((c) => {
@@ -461,9 +457,7 @@ async function resolveCollections(collections: undefined | EntityCollection[] |
461
457
  }
462
458
 
463
459
  resolvedCollections = applyPermissionsFunctionIfEmpty(resolvedCollections, collectionPermissions);
464
-
465
460
  resolvedCollections = filterOutNotAllowedCollections(resolvedCollections, authController);
466
-
467
461
  return resolvedCollections;
468
462
  }
469
463
 
@@ -514,3 +508,54 @@ function areCollectionsEqual(a: EntityCollection, b: EntityCollection) {
514
508
  }
515
509
  return equal(removeFunctions(restA), removeFunctions(restB));
516
510
  }
511
+
512
+ function useCustomBlocker(): NavigationBlocker {
513
+ const [blockListeners, setBlockListeners] = useState<Record<string, {
514
+ block: boolean,
515
+ basePath?: string
516
+ }>>({});
517
+
518
+ const shouldBlock = Object.values(blockListeners).some(b => b.block);
519
+
520
+ let blocker: any;
521
+ try {
522
+ blocker = useBlocker(({
523
+ nextLocation
524
+ }) => {
525
+ const allBasePaths = Object.values(blockListeners).map(b => b.basePath).filter(Boolean) as string[];
526
+ if (allBasePaths && allBasePaths.some(path => nextLocation.pathname.startsWith(path)))
527
+ return false;
528
+ return shouldBlock;
529
+ });
530
+ } catch (e) {
531
+ console.warn("Blocker not available, navigation will not be blocked");
532
+ }
533
+
534
+ const updateBlockListener = (path: string, block: boolean, basePath?: string) => {
535
+ setBlockListeners(prev => ({
536
+ ...prev,
537
+ [path]: {
538
+ block,
539
+ basePath
540
+ }
541
+ }));
542
+ return () => setBlockListeners(prev => {
543
+ const {
544
+ [path]: removed,
545
+ ...rest
546
+ } = prev;
547
+ return rest;
548
+ })
549
+ };
550
+
551
+ const isBlocked = (path: string) => {
552
+ return (blockListeners[path]?.block ?? false) && blocker?.state === "blocked";
553
+ }
554
+
555
+ return {
556
+ updateBlockListener,
557
+ isBlocked,
558
+ proceed: blocker?.proceed,
559
+ reset: blocker?.reset
560
+ }
561
+ }
@@ -21,9 +21,9 @@ import React, { useEffect } from "react";
21
21
  * @see FireCMSContext
22
22
  * @group Hooks and utilities
23
23
  */
24
- export const useFireCMSContext = <UserType extends User = User, AuthControllerType extends AuthController<UserType> = AuthController<UserType>>(): FireCMSContext<UserType, AuthControllerType> => {
24
+ export const useFireCMSContext = <USER extends User = User, AuthControllerType extends AuthController<USER> = AuthController<USER>>(): FireCMSContext<USER, AuthControllerType> => {
25
25
 
26
- const authController = useAuthController<UserType, AuthControllerType>();
26
+ const authController = useAuthController<USER, AuthControllerType>();
27
27
  const sideDialogsController = useSideDialogsController();
28
28
  const sideEntityController = useSideEntityController();
29
29
  const navigation = useNavigationController();
@@ -35,7 +35,7 @@ export const useFireCMSContext = <UserType extends User = User, AuthControllerTy
35
35
  const customizationController = useCustomizationController();
36
36
  const analyticsController = useAnalyticsController();
37
37
 
38
- const fireCMSContextRef = React.useRef<FireCMSContext<UserType, AuthControllerType>>({
38
+ const fireCMSContextRef = React.useRef<FireCMSContext<USER, AuthControllerType>>({
39
39
  authController,
40
40
  sideDialogsController,
41
41
  sideEntityController,
@@ -68,9 +68,9 @@ export const useFireCMSContext = <UserType extends User = User, AuthControllerTy
68
68
  return fireCMSContextRef.current;
69
69
  }
70
70
 
71
- // export const useFireCMSContext = <UserType extends User = User, AuthControllerType extends AuthController<UserType> = AuthController<UserType>>(): FireCMSContext<UserType, AuthControllerType> => {
71
+ // export const useFireCMSContext = <USER extends User = User, AuthControllerType extends AuthController<USER> = AuthController<USER>>(): FireCMSContext<USER, AuthControllerType> => {
72
72
  //
73
- // const authController = useAuthController<UserType, AuthControllerType>();
73
+ // const authController = useAuthController<USER, AuthControllerType>();
74
74
  // const sideDialogsController = useSideDialogsController();
75
75
  // const sideEntityController = useSideEntityController();
76
76
  // const navigation = useNavigationController();
@@ -63,38 +63,3 @@ function checkLargeLayout(breakpoint: "xs" | "sm" | "md" | "lg" | "xl" | "2xl" |
63
63
  return false;
64
64
  return window.matchMedia(`(min-width: ${breakpoints[breakpoint] + 1}px)`).matches;
65
65
  }
66
-
67
- // import { useEffect, useState } from "react";
68
- //
69
- // const breakpoints = {
70
- // xs: 0,
71
- // sm: 640,
72
- // md: 768,
73
- // lg: 1024,
74
- // xl: 1280,
75
- // "2xl": 1536,
76
- // "3xl": 1920
77
- // }
78
- // export const useLargeLayout = (breakpoint: "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl" = "lg"): boolean => {
79
- // const [isLargeLayout, setIsLargeLayout] = useState<boolean>(false);
80
- //
81
- // useEffect(() => {
82
- // const handleResize = () => {
83
- // const matched = window.matchMedia(`(min-width: ${breakpoints[breakpoint] + 1}px)`).matches;
84
- // setIsLargeLayout(matched);
85
- // };
86
- //
87
- // // Set initial state
88
- // handleResize();
89
- //
90
- // // Set up event listener for resize events
91
- // window.addEventListener("resize", handleResize);
92
- //
93
- // // Clean up event listener when component unmounts
94
- // return () => {
95
- // window.removeEventListener("resize", handleResize);
96
- // };
97
- // }, []);
98
- //
99
- // return isLargeLayout;
100
- // };
@@ -7,8 +7,7 @@ import { useContext } from "react";
7
7
  */
8
8
  export interface ModeController {
9
9
  mode: "light" | "dark";
10
- setMode: (mode: "light" | "dark") => void;
11
- toggleMode: () => void;
10
+ setMode: (mode: "light" | "dark" | "system") => void;
12
11
  }
13
12
 
14
13
  /**
@@ -1,6 +1,6 @@
1
1
  import { Entity, EntityCollection, EntityCustomView, FireCMSContext, User } from "../types";
2
2
  import { useEffect, useState } from "react";
3
- import { getNavigationEntriesFromPathInternal } from "../util/navigation_from_path";
3
+ import { getNavigationEntriesFromPath } from "../util/navigation_from_path";
4
4
  import { useFireCMSContext } from "./useFireCMSContext";
5
5
 
6
6
  /**
@@ -55,22 +55,22 @@ interface ResolvedNavigationEntityCustom<M extends Record<string, any>> {
55
55
  * @param context
56
56
  * @group Hooks and utilities
57
57
  */
58
- export function resolveNavigationFrom<M extends Record<string, any>, UserType extends User>({
58
+ export function resolveNavigationFrom<M extends Record<string, any>, USER extends User>({
59
59
  path,
60
60
  context
61
61
  }: {
62
62
  path: string,
63
- context: FireCMSContext<UserType>
63
+ context: FireCMSContext<USER>
64
64
  }): Promise<ResolvedNavigationEntry<M>[]> {
65
65
 
66
66
  const dataSource = context.dataSource;
67
67
  const navigation = context.navigation;
68
68
 
69
69
  if (!navigation) {
70
- throw Error("Calling getNavigationFrom, but main navigation has not yet been initialised");
70
+ throw Error("Calling resolveNavigationFrom, but main navigation has not yet been initialised");
71
71
  }
72
72
 
73
- const navigationEntries = getNavigationEntriesFromPathInternal({
73
+ const navigationEntries = getNavigationEntriesFromPath({
74
74
  path,
75
75
  collections: navigation.collections ?? []
76
76
  });
@@ -126,12 +126,12 @@ export interface NavigationFrom<M extends Record<string, any>> {
126
126
  * in any React component that lives under `FireCMS`
127
127
  * @group Hooks and utilities
128
128
  */
129
- export function useResolvedNavigationFrom<M extends Record<string, any>, UserType extends User>(
129
+ export function useResolvedNavigationFrom<M extends Record<string, any>, USER extends User>(
130
130
  {
131
131
  path
132
132
  }: NavigationFromProps): NavigationFrom<M> {
133
133
 
134
- const context: FireCMSContext<UserType> = useFireCMSContext();
134
+ const context: FireCMSContext<USER> = useFireCMSContext();
135
135
 
136
136
  const [data, setData] = useState<ResolvedNavigationEntry<M>[] | undefined>();
137
137
  const [dataLoading, setDataLoading] = useState<boolean>(false);
@@ -142,10 +142,8 @@ export function useResolvedNavigationFrom<M extends Record<string, any>, UserTyp
142
142
  if (navigation) {
143
143
  setDataLoading(true);
144
144
  setDataLoadingError(undefined);
145
- resolveNavigationFrom<M, UserType>({ path, context })
146
- .then((res) => {
147
- setData(res);
148
- })
145
+ resolveNavigationFrom<M, USER>({ path, context })
146
+ .then(setData)
149
147
  .catch((e) => setDataLoadingError(e))
150
148
  .finally(() => setDataLoading(false));
151
149
  }
@@ -11,7 +11,7 @@ import { AuthController, Authenticator, DataSourceDelegate, StorageSource, User
11
11
  * @param storageSource
12
12
  * @param dataSourceDelegate
13
13
  */
14
- export function useValidateAuthenticator<UserType extends User = User, Controller extends AuthController<UserType> = AuthController<UserType>>
14
+ export function useValidateAuthenticator<USER extends User = any>
15
15
  ({
16
16
  disabled,
17
17
  authController,
@@ -21,8 +21,8 @@ export function useValidateAuthenticator<UserType extends User = User, Controlle
21
21
  }:
22
22
  {
23
23
  disabled?: boolean,
24
- authController: Controller,
25
- authenticator?: boolean | Authenticator<UserType, Controller>,
24
+ authController: AuthController<USER>,
25
+ authenticator?: boolean | Authenticator<USER>,
26
26
  dataSourceDelegate: DataSourceDelegate;
27
27
  storageSource: StorageSource;
28
28
  }): {
@@ -209,7 +209,7 @@ export function useBuildDataSource({
209
209
  collection,
210
210
  path,
211
211
  entityId,
212
- fields: propertyConfigs
212
+ propertyConfigs: propertyConfigs
213
213
  })
214
214
  : undefined;
215
215
 
@@ -25,8 +25,9 @@ export function useBuildSideDialogsController(): SideDialogsController {
25
25
  const newPanels = panelKeys
26
26
  .map(key => routesStore.current[key])
27
27
  .filter(p => Boolean(p)) as SideDialogPanelProps[];
28
- if (!equal(sidePanelsRef.current.map(p => p.key), newPanels.map(p => p.key)))
28
+ if (!equal(sidePanelsRef.current.map(p => p.key), newPanels.map(p => p.key))) {
29
29
  updateSidePanels(newPanels);
30
+ }
30
31
  }, [location]);
31
32
 
32
33
  const close = useCallback(() => {
@@ -39,7 +40,7 @@ export function useBuildSideDialogsController(): SideDialogsController {
39
40
  updateSidePanels(updatedPanels);
40
41
 
41
42
  if (routesCount.current > 0) {
42
- if (lastSidePanel.urlPath)
43
+ if (lastSidePanel.urlPath) // if it has a url path, we need to navigate back, don't remove this code
43
44
  navigate(-1);
44
45
  routesCount.current--;
45
46
  } else if (lastSidePanel.parentUrlPath) {