@firecms/core 3.0.0-beta.1 → 3.0.0-beta.11

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 (387) hide show
  1. package/README.md +6 -7
  2. package/dist/app/AppBar.d.ts +12 -0
  3. package/dist/app/Drawer.d.ts +16 -0
  4. package/dist/app/Scaffold.d.ts +30 -0
  5. package/dist/app/index.d.ts +4 -0
  6. package/dist/app/useApp.d.ts +16 -0
  7. package/dist/components/ArrayContainer.d.ts +19 -8
  8. package/dist/components/CircularProgressCenter.d.ts +1 -1
  9. package/dist/components/ClearFilterSortButton.d.ts +5 -0
  10. package/dist/components/{DeleteConfirmationDialog.d.ts → ConfirmationDialog.d.ts} +1 -1
  11. package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +13 -18
  12. package/dist/components/EntityCollectionTable/EntityCollectionTable.d.ts +2 -5
  13. package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +9 -15
  14. package/dist/components/EntityCollectionTable/PropertyTableCell.d.ts +3 -2
  15. package/dist/components/EntityCollectionTable/column_utils.d.ts +1 -2
  16. package/dist/components/EntityCollectionTable/fields/TableReferenceField.d.ts +3 -1
  17. package/dist/components/EntityCollectionTable/index.d.ts +2 -4
  18. package/dist/components/EntityCollectionTable/internal/CollectionTableToolbar.d.ts +1 -4
  19. package/dist/components/EntityCollectionTable/internal/EntityTableCell.d.ts +2 -2
  20. package/dist/components/EntityCollectionTable/internal/popup_field/PopupFormField.d.ts +8 -5
  21. package/dist/components/EntityCollectionView/EntityCollectionView.d.ts +13 -4
  22. package/dist/components/EntityCollectionView/EntityCollectionViewStartActions.d.ts +11 -0
  23. package/dist/components/EntityCollectionView/useSelectionController.d.ts +2 -0
  24. package/dist/components/EntityCollectionView/utils.d.ts +3 -0
  25. package/dist/components/EntityPreview.d.ts +26 -7
  26. package/dist/components/EntityView.d.ts +11 -0
  27. package/dist/components/ErrorView.d.ts +1 -1
  28. package/dist/components/FieldCaption.d.ts +5 -0
  29. package/dist/components/HomePage/DefaultHomePage.d.ts +1 -1
  30. package/dist/components/HomePage/NavigationCard.d.ts +8 -0
  31. package/dist/components/HomePage/{NavigationCollectionCard.d.ts → NavigationCardBinding.d.ts} +3 -3
  32. package/dist/components/HomePage/SmallNavigationCard.d.ts +6 -0
  33. package/dist/components/HomePage/index.d.ts +3 -1
  34. package/dist/components/{FieldConfigBadge.d.ts → PropertyConfigBadge.d.ts} +2 -1
  35. package/dist/components/PropertyIdCopyTooltip.d.ts +8 -0
  36. package/dist/components/{ReferenceSelectionInner.d.ts → ReferenceTable/ReferenceSelectionTable.d.ts} +2 -2
  37. package/dist/components/ReferenceWidget.d.ts +6 -4
  38. package/dist/components/{EntityCollectionTable/SimpleEntityCollectionTable.d.ts → SelectableTable/SelectableTable.d.ts} +8 -28
  39. package/dist/components/SelectableTable/SelectableTableContext.d.ts +4 -0
  40. package/dist/components/{EntityCollectionTable → SelectableTable}/filters/ReferenceFilterField.d.ts +2 -1
  41. package/dist/components/VirtualTable/VirtualTableProps.d.ts +16 -13
  42. package/dist/components/VirtualTable/types.d.ts +3 -3
  43. package/dist/components/{EntityCollectionTable/internal → common}/default_entity_actions.d.ts +1 -1
  44. package/dist/components/common/index.d.ts +6 -0
  45. package/dist/components/common/table_height.d.ts +5 -0
  46. package/dist/components/{EntityCollectionTable → common}/types.d.ts +11 -6
  47. package/dist/components/{EntityCollectionView → common}/useColumnsIds.d.ts +2 -1
  48. package/dist/components/{EntityCollectionTable → common}/useDataSourceEntityCollectionTableController.d.ts +5 -2
  49. package/dist/components/common/useTableSearchHelper.d.ts +12 -0
  50. package/dist/components/index.d.ts +14 -8
  51. package/dist/contexts/AuthControllerContext.d.ts +1 -1
  52. package/dist/{components/FireCMSAppBar.d.ts → core/DefaultAppBar.d.ts} +6 -9
  53. package/dist/core/DefaultDrawer.d.ts +19 -0
  54. package/dist/core/DrawerNavigationItem.d.ts +10 -0
  55. package/dist/core/EntityEditView.d.ts +36 -0
  56. package/dist/core/FireCMS.d.ts +2 -2
  57. package/dist/core/NavigationRoutes.d.ts +3 -3
  58. package/dist/core/index.d.ts +3 -6
  59. package/dist/form/PropertyFieldBinding.d.ts +1 -1
  60. package/dist/form/components/CustomIdField.d.ts +2 -1
  61. package/dist/form/components/ErrorFocus.d.ts +1 -1
  62. package/dist/form/components/FieldHelperText.d.ts +3 -3
  63. package/dist/{components → form/components}/LabelWithIcon.d.ts +1 -1
  64. package/dist/form/components/LabelWithIconAndTooltip.d.ts +15 -0
  65. package/dist/form/components/StorageItemPreview.d.ts +4 -3
  66. package/dist/form/components/StorageUploadProgress.d.ts +1 -1
  67. package/dist/form/components/index.d.ts +2 -2
  68. package/dist/form/field_bindings/ArrayCustomShapedFieldBinding.d.ts +1 -1
  69. package/dist/form/field_bindings/ArrayOfReferencesFieldBinding.d.ts +1 -1
  70. package/dist/form/field_bindings/BlockFieldBinding.d.ts +1 -1
  71. package/dist/form/field_bindings/KeyValueFieldBinding.d.ts +1 -1
  72. package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
  73. package/dist/form/field_bindings/MarkdownEditorFieldBinding.d.ts +11 -0
  74. package/dist/form/field_bindings/{MultiSelectBinding.d.ts → MultiSelectFieldBinding.d.ts} +1 -1
  75. package/dist/form/field_bindings/ReadOnlyFieldBinding.d.ts +1 -1
  76. package/dist/form/field_bindings/ReferenceFieldBinding.d.ts +2 -2
  77. package/dist/form/field_bindings/RepeatFieldBinding.d.ts +1 -1
  78. package/dist/form/field_bindings/SelectFieldBinding.d.ts +1 -1
  79. package/dist/form/field_bindings/StorageUploadFieldBinding.d.ts +3 -4
  80. package/dist/form/field_bindings/SwitchFieldBinding.d.ts +1 -2
  81. package/dist/form/field_bindings/TextFieldBinding.d.ts +2 -2
  82. package/dist/form/index.d.ts +4 -5
  83. package/dist/form/useClearRestoreValue.d.ts +2 -2
  84. package/dist/form/validation.d.ts +1 -1
  85. package/dist/hooks/data/delete.d.ts +4 -4
  86. package/dist/hooks/data/save.d.ts +4 -5
  87. package/dist/hooks/data/useCollectionFetch.d.ts +1 -1
  88. package/dist/hooks/data/useDataSource.d.ts +2 -2
  89. package/dist/hooks/data/useEntityFetch.d.ts +3 -3
  90. package/dist/hooks/index.d.ts +5 -1
  91. package/dist/hooks/useAuthController.d.ts +1 -1
  92. package/dist/{core → hooks}/useBuildModeController.d.ts +1 -1
  93. package/dist/hooks/useBuildNavigationController.d.ts +23 -0
  94. package/dist/hooks/useFireCMSContext.d.ts +1 -1
  95. package/dist/hooks/useProjectLog.d.ts +14 -0
  96. package/dist/hooks/useResolvedNavigationFrom.d.ts +3 -3
  97. package/dist/hooks/useSnackbarController.d.ts +1 -0
  98. package/dist/hooks/useStorageSource.d.ts +2 -2
  99. package/dist/hooks/useValidateAuthenticator.d.ts +21 -0
  100. package/dist/index.d.ts +1 -0
  101. package/dist/index.es.js +20246 -13863
  102. package/dist/index.es.js.map +1 -1
  103. package/dist/index.umd.js +22772 -588
  104. package/dist/index.umd.js.map +1 -1
  105. package/dist/internal/useBuildDataSource.d.ts +1 -12
  106. package/dist/preview/PropertyPreview.d.ts +1 -1
  107. package/dist/preview/PropertyPreviewProps.d.ts +7 -5
  108. package/dist/preview/components/BooleanPreview.d.ts +5 -1
  109. package/dist/preview/components/EnumValuesChip.d.ts +1 -1
  110. package/dist/preview/components/ReferencePreview.d.ts +4 -9
  111. package/dist/preview/components/StorageThumbnail.d.ts +2 -1
  112. package/dist/preview/components/UrlComponentPreview.d.ts +2 -1
  113. package/dist/preview/util.d.ts +3 -3
  114. package/dist/types/analytics.d.ts +1 -1
  115. package/dist/types/auth.d.ts +37 -3
  116. package/dist/types/collections.d.ts +68 -20
  117. package/dist/types/datasource.d.ts +55 -39
  118. package/dist/types/entities.d.ts +7 -1
  119. package/dist/types/entity_actions.d.ts +18 -4
  120. package/dist/types/entity_callbacks.d.ts +17 -17
  121. package/dist/types/entity_overrides.d.ts +6 -0
  122. package/dist/types/export_import.d.ts +4 -4
  123. package/dist/types/fields.d.ts +63 -42
  124. package/dist/types/firecms.d.ts +10 -25
  125. package/dist/types/firecms_context.d.ts +1 -1
  126. package/dist/types/index.d.ts +2 -1
  127. package/dist/types/navigation.d.ts +18 -16
  128. package/dist/types/permissions.d.ts +8 -4
  129. package/dist/types/plugins.d.ts +39 -39
  130. package/dist/types/properties.d.ts +36 -23
  131. package/dist/types/property_config.d.ts +2 -4
  132. package/dist/types/roles.d.ts +31 -0
  133. package/dist/types/side_dialogs_controller.d.ts +10 -0
  134. package/dist/types/storage.d.ts +86 -3
  135. package/dist/types/user.d.ts +6 -0
  136. package/dist/util/builders.d.ts +2 -2
  137. package/dist/util/collections.d.ts +9 -1
  138. package/dist/util/entities.d.ts +3 -3
  139. package/dist/util/icon_list.d.ts +5 -1
  140. package/dist/util/icon_synonyms.d.ts +1 -98
  141. package/dist/util/icons.d.ts +13 -4
  142. package/dist/util/index.d.ts +3 -1
  143. package/dist/util/navigation_utils.d.ts +2 -2
  144. package/dist/util/objects.d.ts +2 -1
  145. package/dist/util/permissions.d.ts +4 -4
  146. package/dist/util/plurals.d.ts +0 -2
  147. package/dist/util/property_utils.d.ts +3 -3
  148. package/dist/util/references.d.ts +4 -2
  149. package/dist/util/resolutions.d.ts +31 -17
  150. package/dist/util/storage.d.ts +23 -2
  151. package/dist/util/strings.d.ts +1 -1
  152. package/dist/util/useDebouncedCallback.d.ts +1 -0
  153. package/dist/util/useStorageUploadController.d.ts +3 -3
  154. package/dist/util/useTraceUpdate.d.ts +1 -0
  155. package/package.json +70 -47
  156. package/src/app/AppBar.tsx +18 -0
  157. package/src/app/Drawer.tsx +24 -0
  158. package/src/app/Scaffold.tsx +243 -0
  159. package/src/app/index.ts +4 -0
  160. package/src/app/useApp.tsx +32 -0
  161. package/src/components/ArrayContainer.tsx +122 -90
  162. package/src/components/CircularProgressCenter.tsx +2 -2
  163. package/src/components/ClearFilterSortButton.tsx +41 -0
  164. package/src/components/{DeleteConfirmationDialog.tsx → ConfirmationDialog.tsx} +3 -3
  165. package/src/components/DeleteEntityDialog.tsx +13 -22
  166. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +51 -59
  167. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +258 -453
  168. package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +13 -14
  169. package/src/components/EntityCollectionTable/PropertyTableCell.tsx +60 -52
  170. package/src/components/EntityCollectionTable/column_utils.tsx +4 -4
  171. package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +40 -33
  172. package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +22 -20
  173. package/src/components/EntityCollectionTable/index.tsx +1 -9
  174. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +44 -46
  175. package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +36 -34
  176. package/src/components/EntityCollectionTable/internal/EntityTableCellActions.tsx +20 -8
  177. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +191 -178
  178. package/src/components/EntityCollectionView/EntityCollectionView.tsx +187 -175
  179. package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +5 -6
  180. package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +68 -0
  181. package/src/components/EntityCollectionView/useSelectionController.tsx +43 -0
  182. package/src/components/EntityCollectionView/utils.ts +19 -0
  183. package/src/components/EntityPreview.tsx +218 -72
  184. package/src/components/EntityView.tsx +84 -0
  185. package/src/components/ErrorView.tsx +4 -4
  186. package/src/components/FieldCaption.tsx +14 -0
  187. package/src/components/HomePage/DefaultHomePage.tsx +39 -28
  188. package/src/components/HomePage/FavouritesView.tsx +6 -11
  189. package/src/components/HomePage/NavigationCard.tsx +69 -0
  190. package/src/components/HomePage/NavigationCardBinding.tsx +111 -0
  191. package/src/components/HomePage/NavigationGroup.tsx +2 -2
  192. package/src/components/HomePage/SmallNavigationCard.tsx +44 -0
  193. package/src/components/HomePage/index.tsx +3 -1
  194. package/src/components/PropertyConfigBadge.tsx +23 -0
  195. package/src/components/PropertyIdCopyTooltip.tsx +48 -0
  196. package/src/components/{ReferenceSelectionInner.tsx → ReferenceTable/ReferenceSelectionTable.tsx} +38 -24
  197. package/src/components/ReferenceWidget.tsx +26 -16
  198. package/src/components/SearchIconsView.tsx +10 -7
  199. package/src/components/{EntityCollectionTable/SimpleEntityCollectionTable.tsx → SelectableTable/SelectableTable.tsx} +46 -84
  200. package/src/components/SelectableTable/SelectableTableContext.tsx +6 -0
  201. package/src/components/{EntityCollectionTable → SelectableTable}/filters/BooleanFilterField.tsx +2 -3
  202. package/src/components/{EntityCollectionTable → SelectableTable}/filters/DateTimeFilterField.tsx +25 -8
  203. package/src/components/{EntityCollectionTable → SelectableTable}/filters/ReferenceFilterField.tsx +40 -24
  204. package/src/components/{EntityCollectionTable → SelectableTable}/filters/StringNumberFilterField.tsx +92 -24
  205. package/src/components/VirtualTable/VirtualTable.tsx +77 -46
  206. package/src/components/VirtualTable/VirtualTableCell.tsx +1 -9
  207. package/src/components/VirtualTable/VirtualTableHeader.tsx +19 -13
  208. package/src/components/VirtualTable/VirtualTableHeaderRow.tsx +2 -2
  209. package/src/components/VirtualTable/VirtualTableProps.tsx +19 -15
  210. package/src/components/VirtualTable/VirtualTableRow.tsx +5 -6
  211. package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +5 -5
  212. package/src/components/VirtualTable/fields/VirtualTableInput.tsx +4 -3
  213. package/src/components/VirtualTable/fields/VirtualTableNumberInput.tsx +4 -3
  214. package/src/components/VirtualTable/fields/VirtualTableSelect.tsx +16 -28
  215. package/src/components/VirtualTable/types.tsx +2 -3
  216. package/src/components/{EntityCollectionTable/internal → common}/default_entity_actions.tsx +17 -9
  217. package/src/components/common/index.ts +6 -0
  218. package/src/components/{VirtualTable/common.tsx → common/table_height.tsx} +5 -2
  219. package/src/components/{EntityCollectionTable → common}/types.tsx +9 -6
  220. package/src/components/{EntityCollectionView → common}/useColumnsIds.tsx +23 -2
  221. package/src/components/{EntityCollectionTable → common}/useDataSourceEntityCollectionTableController.tsx +27 -16
  222. package/src/components/common/useTableSearchHelper.ts +88 -0
  223. package/src/components/index.tsx +15 -8
  224. package/src/contexts/AuthControllerContext.tsx +1 -1
  225. package/src/contexts/DialogsProvider.tsx +2 -2
  226. package/src/contexts/SnackbarProvider.tsx +2 -0
  227. package/src/core/DefaultAppBar.tsx +177 -0
  228. package/src/core/DefaultDrawer.tsx +185 -0
  229. package/src/core/DrawerNavigationItem.tsx +66 -0
  230. package/src/core/EntityEditView.tsx +1125 -0
  231. package/src/core/EntitySidePanel.tsx +9 -8
  232. package/src/core/FireCMS.tsx +71 -63
  233. package/src/core/NavigationRoutes.tsx +25 -17
  234. package/src/core/SideDialogs.tsx +2 -1
  235. package/src/core/field_configs.tsx +22 -23
  236. package/src/core/index.tsx +3 -6
  237. package/src/form/PropertyFieldBinding.tsx +79 -45
  238. package/src/form/components/CustomIdField.tsx +53 -36
  239. package/src/form/components/ErrorFocus.tsx +3 -3
  240. package/src/form/components/FieldHelperText.tsx +4 -4
  241. package/src/form/components/LabelWithIcon.tsx +41 -0
  242. package/src/form/components/LabelWithIconAndTooltip.tsx +28 -0
  243. package/src/form/components/StorageItemPreview.tsx +23 -11
  244. package/src/form/components/StorageUploadProgress.tsx +8 -8
  245. package/src/form/components/index.tsx +2 -2
  246. package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +30 -19
  247. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +52 -46
  248. package/src/form/field_bindings/BlockFieldBinding.tsx +67 -47
  249. package/src/form/field_bindings/DateTimeFieldBinding.tsx +20 -17
  250. package/src/form/field_bindings/KeyValueFieldBinding.tsx +76 -67
  251. package/src/form/field_bindings/MapFieldBinding.tsx +81 -60
  252. package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +150 -0
  253. package/src/form/field_bindings/{MultiSelectBinding.tsx → MultiSelectFieldBinding.tsx} +26 -22
  254. package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +12 -18
  255. package/src/form/field_bindings/ReferenceFieldBinding.tsx +46 -34
  256. package/src/form/field_bindings/RepeatFieldBinding.tsx +55 -35
  257. package/src/form/field_bindings/SelectFieldBinding.tsx +24 -17
  258. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +42 -43
  259. package/src/form/field_bindings/SwitchFieldBinding.tsx +30 -27
  260. package/src/form/field_bindings/TextFieldBinding.tsx +34 -30
  261. package/src/form/index.tsx +5 -9
  262. package/src/form/useClearRestoreValue.tsx +2 -2
  263. package/src/form/validation.ts +4 -21
  264. package/src/hooks/data/delete.ts +7 -6
  265. package/src/hooks/data/save.ts +12 -8
  266. package/src/hooks/data/useCollectionFetch.tsx +3 -3
  267. package/src/hooks/data/useDataSource.tsx +15 -2
  268. package/src/hooks/data/useEntityFetch.tsx +6 -6
  269. package/src/hooks/index.tsx +7 -1
  270. package/src/hooks/useAuthController.tsx +1 -1
  271. package/src/{core → hooks}/useBuildLocalConfigurationPersistence.tsx +8 -10
  272. package/src/{core → hooks}/useBuildModeController.tsx +12 -6
  273. package/src/{internal → hooks}/useBuildNavigationController.tsx +245 -101
  274. package/src/hooks/useFireCMSContext.tsx +53 -5
  275. package/src/hooks/useLargeLayout.tsx +10 -7
  276. package/src/hooks/useProjectLog.tsx +63 -0
  277. package/src/hooks/useReferenceDialog.tsx +3 -3
  278. package/src/hooks/useResolvedNavigationFrom.tsx +6 -6
  279. package/src/hooks/useSnackbarController.tsx +1 -2
  280. package/src/hooks/useStorageSource.tsx +7 -2
  281. package/src/hooks/useValidateAuthenticator.tsx +115 -0
  282. package/src/index.ts +1 -0
  283. package/src/internal/useBuildDataSource.ts +80 -85
  284. package/src/internal/useBuildSideDialogsController.tsx +1 -0
  285. package/src/internal/useBuildSideEntityController.tsx +103 -23
  286. package/src/internal/useUnsavedChangesDialog.tsx +5 -3
  287. package/src/preview/PropertyPreview.tsx +15 -22
  288. package/src/preview/PropertyPreviewProps.tsx +6 -10
  289. package/src/preview/components/BooleanPreview.tsx +19 -4
  290. package/src/preview/components/EmptyValue.tsx +1 -1
  291. package/src/preview/components/EnumValuesChip.tsx +2 -2
  292. package/src/preview/components/ImagePreview.tsx +25 -36
  293. package/src/preview/components/ReferencePreview.tsx +73 -176
  294. package/src/preview/components/StorageThumbnail.tsx +5 -1
  295. package/src/preview/components/UrlComponentPreview.tsx +44 -11
  296. package/src/preview/property_previews/ArrayOfMapsPreview.tsx +2 -3
  297. package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +4 -3
  298. package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +2 -3
  299. package/src/preview/property_previews/ArrayOfStringsPreview.tsx +1 -2
  300. package/src/preview/property_previews/ArrayOneOfPreview.tsx +4 -5
  301. package/src/preview/property_previews/ArrayPropertyPreview.tsx +4 -5
  302. package/src/preview/property_previews/MapPropertyPreview.tsx +9 -9
  303. package/src/preview/property_previews/SkeletonPropertyComponent.tsx +12 -12
  304. package/src/preview/property_previews/StringPropertyPreview.tsx +8 -7
  305. package/src/preview/util.ts +10 -10
  306. package/src/types/analytics.ts +1 -0
  307. package/src/types/auth.tsx +48 -3
  308. package/src/types/collections.ts +77 -20
  309. package/src/types/customization_controller.tsx +0 -1
  310. package/src/types/datasource.ts +64 -47
  311. package/src/types/entities.ts +15 -1
  312. package/src/types/entity_actions.tsx +21 -4
  313. package/src/types/entity_callbacks.ts +20 -19
  314. package/src/types/entity_overrides.tsx +7 -0
  315. package/src/types/export_import.ts +4 -4
  316. package/src/types/fields.tsx +69 -45
  317. package/src/types/firecms.tsx +11 -28
  318. package/src/types/firecms_context.tsx +1 -1
  319. package/src/types/index.ts +2 -1
  320. package/src/types/navigation.ts +20 -19
  321. package/src/types/permissions.ts +10 -5
  322. package/src/types/plugins.tsx +46 -48
  323. package/src/types/properties.ts +42 -24
  324. package/src/types/property_config.tsx +2 -4
  325. package/src/types/roles.ts +41 -0
  326. package/src/types/side_dialogs_controller.tsx +13 -0
  327. package/src/types/side_entity_controller.tsx +1 -0
  328. package/src/types/storage.ts +94 -3
  329. package/src/types/user.ts +9 -0
  330. package/src/util/builders.ts +6 -6
  331. package/src/util/collections.ts +22 -0
  332. package/src/util/entities.ts +9 -6
  333. package/src/util/enums.ts +1 -1
  334. package/src/util/icon_list.ts +16 -10
  335. package/src/util/icon_synonyms.ts +3 -100
  336. package/src/util/icons.tsx +26 -8
  337. package/src/util/index.ts +3 -1
  338. package/src/util/make_properties_editable.ts +13 -5
  339. package/src/util/navigation_utils.ts +6 -6
  340. package/src/util/objects.ts +45 -28
  341. package/src/util/permissions.ts +20 -16
  342. package/src/util/plurals.ts +0 -2
  343. package/src/util/property_utils.tsx +11 -4
  344. package/src/util/references.ts +45 -5
  345. package/src/util/resolutions.ts +80 -47
  346. package/src/util/storage.ts +79 -21
  347. package/src/util/strings.ts +4 -3
  348. package/src/util/{useDebounce.ts → useDebouncedCallback.ts} +1 -1
  349. package/src/util/useStorageUploadController.tsx +34 -8
  350. package/src/util/useTraceUpdate.tsx +2 -1
  351. package/dist/components/VirtualTable/common.d.ts +0 -2
  352. package/dist/core/Drawer.d.ts +0 -23
  353. package/dist/core/Scaffold.d.ts +0 -52
  354. package/dist/form/EntityForm.d.ts +0 -75
  355. package/dist/form/components/FormikArrayContainer.d.ts +0 -18
  356. package/dist/form/components/SubmitListener.d.ts +0 -1
  357. package/dist/form/components/SwitchControl.d.ts +0 -8
  358. package/dist/form/field_bindings/MarkdownFieldBinding.d.ts +0 -9
  359. package/dist/hooks/useVerifyLicense.d.ts +0 -0
  360. package/dist/internal/EntityView.d.ts +0 -22
  361. package/dist/internal/useBuildCustomizationController.d.ts +0 -2
  362. package/dist/internal/useBuildNavigationController.d.ts +0 -14
  363. package/dist/internal/useLocaleConfig.d.ts +0 -1
  364. package/dist/types/appcheck.d.ts +0 -26
  365. package/dist/util/useDebounce.d.ts +0 -1
  366. package/src/components/FieldConfigBadge.tsx +0 -17
  367. package/src/components/FireCMSAppBar.tsx +0 -157
  368. package/src/components/HomePage/NavigationCollectionCard.tsx +0 -146
  369. package/src/components/LabelWithIcon.tsx +0 -33
  370. package/src/core/Drawer.tsx +0 -162
  371. package/src/core/Scaffold.tsx +0 -278
  372. package/src/form/EntityForm.tsx +0 -657
  373. package/src/form/components/FormikArrayContainer.tsx +0 -44
  374. package/src/form/components/SubmitListener.tsx +0 -32
  375. package/src/form/components/SwitchControl.tsx +0 -39
  376. package/src/form/field_bindings/MarkdownFieldBinding.tsx +0 -696
  377. package/src/hooks/useVerifyLicense.tsx +0 -1
  378. package/src/internal/EntityView.tsx +0 -578
  379. package/src/internal/useBuildCustomizationController.tsx +0 -5
  380. package/src/internal/useLocaleConfig.tsx +0 -18
  381. package/src/types/appcheck.ts +0 -29
  382. /package/dist/components/{EntityCollectionTable → SelectableTable}/filters/BooleanFilterField.d.ts +0 -0
  383. /package/dist/components/{EntityCollectionTable → SelectableTable}/filters/DateTimeFilterField.d.ts +0 -0
  384. /package/dist/components/{EntityCollectionTable → SelectableTable}/filters/StringNumberFilterField.d.ts +0 -0
  385. /package/dist/components/{EntityCollectionTable → common}/useDebouncedData.d.ts +0 -0
  386. /package/dist/{core → hooks}/useBuildLocalConfigurationPersistence.d.ts +0 -0
  387. /package/src/components/{EntityCollectionTable → common}/useDebouncedData.ts +0 -0
@@ -1,5 +1,5 @@
1
- import { useCallback, useEffect, useMemo, useState } from "react";
2
- import { useLocation } from "react-router-dom";
1
+ import { useCallback, useEffect, useRef, useState } from "react";
2
+ import equal from "react-fast-compare"
3
3
 
4
4
  import {
5
5
  AuthController,
@@ -9,16 +9,18 @@ import {
9
9
  EntityCollection,
10
10
  EntityCollectionsBuilder,
11
11
  EntityReference,
12
- FireCMSPlugin,
13
12
  NavigationController,
13
+ PermissionsBuilder,
14
14
  TopNavigationEntry,
15
15
  TopNavigationResult,
16
16
  User,
17
17
  UserConfigurationPersistence
18
18
  } from "../types";
19
19
  import {
20
+ applyPermissionsFunctionIfEmpty,
20
21
  getCollectionByPathOrId,
21
22
  mergeDeep,
23
+ removeFunctions,
22
24
  removeInitialAndTrailingSlashes,
23
25
  resolveCollectionPathIds,
24
26
  resolvePermissions
@@ -28,32 +30,46 @@ import { getParentReferencesFromPath } from "../util/parent_references_from_path
28
30
  const DEFAULT_BASE_PATH = "/";
29
31
  const DEFAULT_COLLECTION_PATH = "/c";
30
32
 
31
- type BuildNavigationContextProps<EC extends EntityCollection, UserType extends User> = {
33
+ export type BuildNavigationContextProps<EC extends EntityCollection, USER extends User> = {
32
34
  basePath?: string,
33
35
  baseCollectionPath?: string,
34
- authController: AuthController<UserType>;
36
+ authController: AuthController<USER>;
35
37
  collections?: EC[] | EntityCollectionsBuilder<EC>;
38
+ collectionPermissions?: PermissionsBuilder;
36
39
  views?: CMSView[] | CMSViewsBuilder;
40
+ adminViews?: CMSView[] | CMSViewsBuilder;
41
+ viewsOrder?: string[];
37
42
  userConfigPersistence?: UserConfigurationPersistence;
38
- plugins?: FireCMSPlugin[];
39
- dataSource: DataSourceDelegate;
43
+ dataSourceDelegate: DataSourceDelegate;
44
+ /**
45
+ * Use this method to inject collections to the CMS.
46
+ * You receive the current collections as a parameter, and you can return
47
+ * a new list of collections.
48
+ * @see {@link joinCollectionLists}
49
+ * @param collections
50
+ */
51
+ injectCollections?: (collections: EntityCollection[]) => EntityCollection[];
40
52
  };
41
53
 
42
- export function useBuildNavigationController<EC extends EntityCollection, UserType extends User>({
43
- basePath = DEFAULT_BASE_PATH,
44
- baseCollectionPath = DEFAULT_COLLECTION_PATH,
45
- authController,
46
- collections: baseCollections,
47
- views: baseViews,
48
- userConfigPersistence,
49
- plugins,
50
- dataSource
51
- }: BuildNavigationContextProps<EC, UserType>): NavigationController {
52
-
53
- const location = useLocation();
54
-
55
- const [collections, setCollections] = useState<EntityCollection[] | undefined>();
56
- const [views, setViews] = useState<CMSView[] | undefined>();
54
+ export function useBuildNavigationController<EC extends EntityCollection, USER extends User>(props: BuildNavigationContextProps<EC, USER>): NavigationController {
55
+ const {
56
+ basePath = DEFAULT_BASE_PATH,
57
+ baseCollectionPath = DEFAULT_COLLECTION_PATH,
58
+ authController,
59
+ collections: collectionsProp,
60
+ collectionPermissions,
61
+ views: viewsProp,
62
+ adminViews: adminViewsProp,
63
+ viewsOrder,
64
+ userConfigPersistence,
65
+ dataSourceDelegate,
66
+ injectCollections
67
+ } = props;
68
+
69
+ const collectionsRef = useRef<EntityCollection[] | undefined>();
70
+ const viewsRef = useRef<CMSView[] | undefined>();
71
+ const adminViewsRef = useRef<CMSView[] | undefined>();
72
+
57
73
  const [initialised, setInitialised] = useState<boolean>(false);
58
74
 
59
75
  const [topLevelNavigation, setTopLevelNavigation] = useState<TopNavigationResult | undefined>(undefined);
@@ -73,19 +89,18 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
73
89
  const buildUrlCollectionPath = useCallback((path: string): string => `${removeInitialAndTrailingSlashes(baseCollectionPath)}/${encodePath(path)}`,
74
90
  [baseCollectionPath]);
75
91
 
76
- const computeTopNavigation = useCallback((collections: EntityCollection[], views: CMSView[]): TopNavigationResult => {
77
- // return (collection.editable && resolvePermissions(collection, authController, paths).editCollection) ?? DEFAULT_PERMISSIONS.editCollection;
78
- const navigationEntries: TopNavigationEntry[] = [
92
+ const computeTopNavigation = useCallback((collections: EntityCollection[], views: CMSView[], adminViews: CMSView[], viewsOrder?: string[]): TopNavigationResult => {
93
+ let navigationEntries: TopNavigationEntry[] = [
79
94
  ...(collections ?? []).map(collection => (!collection.hideFromNavigation
80
- ? {
95
+ ? ({
81
96
  url: buildUrlCollectionPath(collection.id ?? collection.path),
82
97
  type: "collection",
83
98
  name: collection.name.trim(),
84
99
  path: collection.id ?? collection.path,
85
100
  collection,
86
101
  description: collection.description?.trim(),
87
- group: collection.group?.trim()
88
- }
102
+ group: getGroup(collection)
103
+ } satisfies TopNavigationEntry)
89
104
  : undefined))
90
105
  .filter(Boolean) as TopNavigationEntry[],
91
106
  ...(views ?? []).map(view =>
@@ -94,18 +109,74 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
94
109
  url: buildCMSUrlPath(Array.isArray(view.path) ? view.path[0] : view.path),
95
110
  name: view.name.trim(),
96
111
  type: "view",
112
+ path: view.path,
113
+ view,
114
+ description: view.description?.trim(),
115
+ group: getGroup(view)
116
+ } satisfies TopNavigationEntry)
117
+ : undefined)
118
+ .filter(Boolean) as TopNavigationEntry[],
119
+ ...(adminViews ?? []).map(view =>
120
+ !view.hideFromNavigation
121
+ ? ({
122
+ url: buildCMSUrlPath(Array.isArray(view.path) ? view.path[0] : view.path),
123
+ name: view.name.trim(),
124
+ type: "admin",
125
+ path: view.path,
97
126
  view,
98
127
  description: view.description?.trim(),
99
- group: view.group?.trim()
100
- })
128
+ group: "Admin"
129
+ } satisfies TopNavigationEntry)
101
130
  : undefined)
102
131
  .filter(Boolean) as TopNavigationEntry[]
103
132
  ];
104
133
 
134
+ // Sort by group, entries with group "Admin" will go last, and second to last will be the group "Views"
135
+ navigationEntries = navigationEntries.sort((a, b) => {
136
+ if (a.group !== "Views" && a.group !== "Admin" && (b.group === "Views" || b.group === "Admin")) {
137
+ return -1;
138
+ }
139
+ if (b.group !== "Views" && b.group !== "Admin" && (a.group === "Views" || a.group === "Admin")) {
140
+ return 1;
141
+ }
142
+ if (a.group === "Admin" && b.group !== "Admin") {
143
+ return 1;
144
+ }
145
+ if (a.group !== "Admin" && b.group === "Admin") {
146
+ return -1;
147
+ }
148
+ if (a.group === "Views" && b.group !== "Views") {
149
+ return -1;
150
+ }
151
+ if (a.group !== "Views" && b.group === "Views") {
152
+ return 1;
153
+ }
154
+ return 0;
155
+
156
+ });
157
+
158
+ if (viewsOrder) {
159
+ navigationEntries = navigationEntries.sort((a, b) => {
160
+ const aIndex = viewsOrder.indexOf(a.path);
161
+ const bIndex = viewsOrder.indexOf(b.path);
162
+ if (aIndex === -1 && bIndex === -1) {
163
+ return 0;
164
+ }
165
+ if (aIndex === -1) {
166
+ return 1;
167
+ }
168
+ if (bIndex === -1) {
169
+ return -1;
170
+ }
171
+ return aIndex - bIndex;
172
+ });
173
+ }
174
+
105
175
  const groups: string[] = Object.values(navigationEntries)
106
176
  .map(e => e.group)
107
177
  .filter(Boolean)
108
178
  .filter((value, index, array) => array.indexOf(value) === index) as string[];
179
+
109
180
  return {
110
181
  navigationEntries,
111
182
  groups
@@ -117,43 +188,77 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
117
188
  if (authController.initialLoading)
118
189
  return;
119
190
 
191
+ console.debug("Refreshing navigation");
192
+
120
193
  try {
121
- const [resolvedCollections = [], resolvedViews = []] = await Promise.all([
122
- resolveCollections(baseCollections, authController, dataSource, plugins),
123
- resolveCMSViews(baseViews, authController, dataSource)
194
+
195
+ const [resolvedCollections = [], resolvedViews, resolvedAdminViews = []] = await Promise.all([
196
+ resolveCollections(collectionsProp, collectionPermissions, authController, dataSourceDelegate, injectCollections),
197
+ resolveCMSViews(viewsProp, authController, dataSourceDelegate),
198
+ resolveCMSViews(adminViewsProp, authController, dataSourceDelegate)
124
199
  ]
125
200
  );
126
201
 
127
- setCollections(resolvedCollections);
128
- setViews(resolvedViews);
129
- setTopLevelNavigation(computeTopNavigation(resolvedCollections ?? [], resolvedViews));
202
+ let shouldUpdateTopLevelNav = false;
203
+ if (!areCollectionListsEqual(collectionsRef.current ?? [], resolvedCollections)) {
204
+ collectionsRef.current = resolvedCollections;
205
+ console.log("Collections have changed", resolvedCollections);
206
+ shouldUpdateTopLevelNav = true;
207
+ }
208
+ if (collectionsRef.current === undefined) {
209
+ collectionsRef.current = resolvedCollections;
210
+ shouldUpdateTopLevelNav = true;
211
+ }
212
+ if (!equal(viewsRef.current, resolvedViews)) {
213
+ viewsRef.current = resolvedViews;
214
+ shouldUpdateTopLevelNav = true;
215
+ }
216
+ if (!equal(adminViewsRef.current, resolvedAdminViews)) {
217
+ adminViewsRef.current = resolvedAdminViews;
218
+ shouldUpdateTopLevelNav = true;
219
+ }
220
+
221
+ const computedTopLevelNav = computeTopNavigation(resolvedCollections, resolvedViews, resolvedAdminViews, viewsOrder);
222
+ if (shouldUpdateTopLevelNav && !equal(topLevelNavigation, computedTopLevelNav)) {
223
+ setTopLevelNavigation(computedTopLevelNav);
224
+ }
130
225
  } catch (e) {
131
226
  console.error(e);
132
227
  setNavigationLoadingError(e as any);
133
228
  }
134
229
 
135
- setNavigationLoading(false);
136
- setInitialised(true);
137
- }, [baseCollections, authController.user, authController.initialLoading, plugins, baseViews, computeTopNavigation]);
230
+ if (navigationLoading)
231
+ setNavigationLoading(false);
232
+ if (!initialised)
233
+ setInitialised(true);
234
+
235
+ }, [
236
+ collectionsProp,
237
+ collectionPermissions,
238
+ authController.user,
239
+ authController.initialLoading,
240
+ viewsProp,
241
+ adminViewsProp,
242
+ computeTopNavigation,
243
+ injectCollections
244
+ ]);
138
245
 
139
246
  useEffect(() => {
140
247
  refreshNavigation();
141
248
  }, [refreshNavigation]);
142
249
 
143
- const getCollection = useCallback(<EC extends EntityCollection>(
250
+ const getCollection = useCallback((
144
251
  idOrPath: string,
145
- entityId?: string,
146
252
  includeUserOverride = false
147
253
  ): EC | undefined => {
148
-
254
+ const collections = collectionsRef.current;
149
255
  if (!collections)
150
256
  return undefined;
151
257
 
152
258
  const baseCollection = getCollectionByPathOrId(removeInitialAndTrailingSlashes(idOrPath), collections);
153
259
 
154
260
  const userOverride = includeUserOverride ? userConfigPersistence?.getCollectionConfig(idOrPath) : undefined;
155
-
156
- const overriddenCollection = baseCollection ? mergeDeep(baseCollection, userOverride) : undefined;
261
+ const overriddenCollection = baseCollection ? mergeDeep(baseCollection, userOverride ?? {}) : undefined;
157
262
 
158
263
  let result: Partial<EntityCollection> | undefined = overriddenCollection;
159
264
 
@@ -173,16 +278,14 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
173
278
 
174
279
  return { ...overriddenCollection, ...result } as EC;
175
280
 
176
- }, [
177
- basePath,
178
- baseCollectionPath,
179
- collections,
180
- ]);
281
+ }, [userConfigPersistence]);
181
282
 
182
283
  const getCollectionFromPaths = useCallback(<EC extends EntityCollection>(pathSegments: string[]): EC | undefined => {
183
- let currentCollections = collections;
184
- if (!currentCollections)
185
- throw Error("Collections have not been initialised yet");
284
+
285
+ const collections = collectionsRef.current;
286
+ if (collections === undefined)
287
+ throw Error("getCollectionFromPaths: Collections have not been initialised yet");
288
+ let currentCollections: EntityCollection[] | undefined = [...(collections ?? [])];
186
289
 
187
290
  for (let i = 0; i < pathSegments.length; i++) {
188
291
  const pathSegment = pathSegments[i];
@@ -196,12 +299,14 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
196
299
 
197
300
  return undefined;
198
301
 
199
- }, [collections]);
302
+ }, []);
200
303
 
201
304
  const getCollectionFromIds = useCallback(<EC extends EntityCollection>(ids: string[]): EC | undefined => {
202
- let currentCollections = collections;
203
- if (!currentCollections)
204
- throw Error("Collections have not been initialised yet");
305
+
306
+ const collections = collectionsRef.current;
307
+ if (collections === undefined)
308
+ throw Error("getCollectionFromIds: Collections have not been initialised yet");
309
+ let currentCollections: EntityCollection[] | undefined = [...(collections ?? [])];
205
310
 
206
311
  for (let i = 0; i < ids.length; i++) {
207
312
  const id = ids[i];
@@ -215,7 +320,7 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
215
320
 
216
321
  return undefined;
217
322
 
218
- }, [collections]);
323
+ }, []);
219
324
 
220
325
  const isUrlCollectionPath = useCallback(
221
326
  (path: string): boolean => removeInitialAndTrailingSlashes(path + "/").startsWith(removeInitialAndTrailingSlashes(fullCollectionPath) + "/"),
@@ -237,48 +342,53 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
237
342
  []);
238
343
 
239
344
  const resolveAliasesFrom = useCallback((path: string): string => {
240
- if (!collections)
241
- throw Error("Collections have not been initialised yet");
345
+ const collections = collectionsRef.current ?? [];
242
346
  return resolveCollectionPathIds(path, collections);
243
- }, [collections]);
244
-
245
- const state = location.state as any;
246
- /**
247
- * The location can be overridden if `base_location` is set in the
248
- * state field of the current location. This can happen if you open
249
- * a side entity, like `products`, from a different one, like `users`
250
- */
251
- const baseLocation = state && state.base_location ? state.base_location : location;
347
+ }, []);
252
348
 
253
- const getAllParentCollectionsForPath = useCallback((path: string): EntityReference[] => {
349
+ const getAllParentReferencesForPath = useCallback((path: string): EntityReference[] => {
350
+ const collections = collectionsRef.current ?? [];
254
351
  return getParentReferencesFromPath({
255
352
  path,
256
353
  collections
257
354
  });
258
- }, [collections]);
355
+ }, []);
259
356
 
260
357
  const getParentCollectionIds = useCallback((path: string): string[] => {
261
- return getAllParentCollectionsForPath(path).map(r => r.id);
262
- }, [getAllParentCollectionsForPath])
358
+
359
+ const strings = path.split("/");
360
+ const oddPathSegments = strings.filter((_, i) => i % 2 === 0);
361
+ oddPathSegments.pop();
362
+
363
+ const result: string[][] = [];
364
+
365
+ for (let i = 1; i <= oddPathSegments.length; i++) {
366
+ result.push(oddPathSegments.slice(0, i));
367
+ }
368
+
369
+ // for each odd path segment, get the collection
370
+ return result.map(r => getCollectionFromPaths(r)?.id).filter(Boolean) as string[];
371
+ }, [getAllParentReferencesForPath])
263
372
 
264
373
  const convertIdsToPaths = useCallback((ids: string[]): string[] => {
265
- let currentCollections = collections;
266
- const paths: string[] = [];
267
- for (let i = 0; i < ids.length; i++) {
268
- const id = ids[i];
269
- const collection: EntityCollection | undefined = currentCollections!.find(c => c.id === id);
270
- if (!collection)
271
- throw Error(`Collection with id ${id} not found`);
272
- paths.push(collection.path);
273
- currentCollections = collection.subcollections;
274
- }
275
- return paths;
374
+ const collections = collectionsRef.current;
375
+ let currentCollections = collections;
376
+ const paths: string[] = [];
377
+ for (let i = 0; i < ids.length; i++) {
378
+ const id = ids[i];
379
+ const collection: EntityCollection | undefined = currentCollections!.find(c => c.id === id);
380
+ if (!collection)
381
+ throw Error(`Collection with id ${id} not found`);
382
+ paths.push(collection.path);
383
+ currentCollections = collection.subcollections;
276
384
  }
277
- , [getCollectionFromIds]);
385
+ return paths;
386
+ }, [getCollectionFromIds]);
278
387
 
279
- return useMemo(() => ({
280
- collections: collections ?? [],
281
- views: views ?? [],
388
+ return {
389
+ collections: collectionsRef.current,
390
+ views: viewsRef.current,
391
+ adminViews: adminViewsRef.current,
282
392
  loading: !initialised || navigationLoading,
283
393
  navigationLoadingError,
284
394
  homeUrl,
@@ -295,12 +405,11 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
295
405
  buildCMSUrlPath,
296
406
  resolveAliasesFrom,
297
407
  topLevelNavigation,
298
- baseLocation,
299
408
  refreshNavigation,
300
- getParentReferencesFromPath: getAllParentCollectionsForPath,
409
+ getParentReferencesFromPath: getAllParentReferencesForPath,
301
410
  getParentCollectionIds,
302
411
  convertIdsToPaths
303
- }), [baseCollectionPath, baseLocation, basePath, buildCMSUrlPath, buildUrlCollectionPath, buildUrlEditCollectionPath, collections, getAllParentCollectionsForPath, getCollection, getCollectionFromPaths, homeUrl, initialised, isUrlCollectionPath, navigationLoading, navigationLoadingError, refreshNavigation, resolveAliasesFrom, topLevelNavigation, urlPathToDataPath, views]);
412
+ };
304
413
  }
305
414
 
306
415
  export function getSidePanelKey(path: string, entityId?: string) {
@@ -320,8 +429,8 @@ function filterOutNotAllowedCollections(resolvedCollections: EntityCollection[],
320
429
  return resolvedCollections
321
430
  .filter((c) => {
322
431
  if (!c.permissions) return true;
323
- const resolvedPermissions = resolvePermissions(c, authController, [c.path], null,)
324
- return resolvedPermissions.read !== false;
432
+ const resolvedPermissions = resolvePermissions(c, authController, c.path, null);
433
+ return resolvedPermissions?.read !== false;
325
434
  })
326
435
  .map((c) => {
327
436
  if (!c.subcollections) return c;
@@ -332,7 +441,11 @@ function filterOutNotAllowedCollections(resolvedCollections: EntityCollection[],
332
441
  });
333
442
  }
334
443
 
335
- async function resolveCollections(collections: undefined | EntityCollection[] | EntityCollectionsBuilder<any>, authController: AuthController, dataSource: DataSourceDelegate, plugins?: FireCMSPlugin[]) {
444
+ async function resolveCollections(collections: undefined | EntityCollection[] | EntityCollectionsBuilder<any>,
445
+ collectionPermissions: PermissionsBuilder | undefined,
446
+ authController: AuthController,
447
+ dataSource: DataSourceDelegate,
448
+ injectCollections?: (collections: EntityCollection[]) => EntityCollection[]): Promise<EntityCollection[]> {
336
449
  let resolvedCollections: EntityCollection[] = [];
337
450
  if (typeof collections === "function") {
338
451
  resolvedCollections = await collections({
@@ -344,15 +457,12 @@ async function resolveCollections(collections: undefined | EntityCollection[] |
344
457
  resolvedCollections = collections;
345
458
  }
346
459
 
347
- resolvedCollections = filterOutNotAllowedCollections(resolvedCollections, authController);
348
-
349
- if (plugins) {
350
- plugins.forEach((plugin: FireCMSPlugin) => {
351
- if (plugin.collections?.injectCollections) {
352
- resolvedCollections = plugin.collections?.injectCollections(resolvedCollections ?? []);
353
- }
354
- });
460
+ if (injectCollections) {
461
+ resolvedCollections = injectCollections(resolvedCollections ?? []);
355
462
  }
463
+
464
+ resolvedCollections = applyPermissionsFunctionIfEmpty(resolvedCollections, collectionPermissions);
465
+ resolvedCollections = filterOutNotAllowedCollections(resolvedCollections, authController);
356
466
  return resolvedCollections;
357
467
  }
358
468
 
@@ -369,3 +479,37 @@ async function resolveCMSViews(baseViews: CMSView[] | CMSViewsBuilder | undefine
369
479
  }
370
480
  return resolvedViews;
371
481
  }
482
+
483
+ function getGroup(collectionOrView: EntityCollection<any, any> | CMSView) {
484
+ const trimmed = collectionOrView.group?.trim();
485
+ if (!trimmed || trimmed === "") {
486
+ return "Views";
487
+ }
488
+ return trimmed ?? "Views";
489
+ }
490
+
491
+ function areCollectionListsEqual(a: EntityCollection[], b: EntityCollection[]) {
492
+ if (a.length !== b.length) {
493
+ return false;
494
+ }
495
+ const aCopy = [...a];
496
+ const bCopy = [...b];
497
+ const aSorted = aCopy.sort((x, y) => x.id.localeCompare(y.id));
498
+ const bSorted = bCopy.sort((x, y) => x.id.localeCompare(y.id));
499
+ return aSorted.every((value, index) => areCollectionsEqual(value, bSorted[index]));
500
+ }
501
+
502
+ function areCollectionsEqual(a: EntityCollection, b: EntityCollection) {
503
+ const {
504
+ subcollections: subcollectionsA,
505
+ ...restA
506
+ } = a;
507
+ const {
508
+ subcollections: subcollectionsB,
509
+ ...restB
510
+ } = b;
511
+ if (!areCollectionListsEqual(subcollectionsA ?? [], subcollectionsB ?? [])) {
512
+ return false;
513
+ }
514
+ return equal(removeFunctions(restA), removeFunctions(restB));
515
+ }
@@ -10,6 +10,7 @@ import { useUserConfigurationPersistence } from "./useUserConfigurationPersisten
10
10
  import { useDialogsController } from "./useDialogsController";
11
11
  import { useCustomizationController } from "./useCustomizationController";
12
12
  import { useAnalyticsController } from "./useAnalyticsController";
13
+ import React, { useEffect } from "react";
13
14
 
14
15
  /**
15
16
  * Hook to retrieve the {@link FireCMSContext}.
@@ -20,9 +21,9 @@ import { useAnalyticsController } from "./useAnalyticsController";
20
21
  * @see FireCMSContext
21
22
  * @group Hooks and utilities
22
23
  */
23
- 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> => {
24
25
 
25
- const authController = useAuthController<UserType, AuthControllerType>();
26
+ const authController = useAuthController<USER, AuthControllerType>();
26
27
  const sideDialogsController = useSideDialogsController();
27
28
  const sideEntityController = useSideEntityController();
28
29
  const navigation = useNavigationController();
@@ -34,7 +35,7 @@ export const useFireCMSContext = <UserType extends User = User, AuthControllerTy
34
35
  const customizationController = useCustomizationController();
35
36
  const analyticsController = useAnalyticsController();
36
37
 
37
- return {
38
+ const fireCMSContextRef = React.useRef<FireCMSContext<USER, AuthControllerType>>({
38
39
  authController,
39
40
  sideDialogsController,
40
41
  sideEntityController,
@@ -46,6 +47,53 @@ export const useFireCMSContext = <UserType extends User = User, AuthControllerTy
46
47
  dialogsController,
47
48
  customizationController,
48
49
  analyticsController
49
- };
50
+ });
50
51
 
51
- };
52
+ useEffect(() => {
53
+ fireCMSContextRef.current = {
54
+ authController,
55
+ sideDialogsController,
56
+ sideEntityController,
57
+ navigation,
58
+ dataSource,
59
+ storageSource,
60
+ snackbarController,
61
+ userConfigPersistence,
62
+ dialogsController,
63
+ customizationController,
64
+ analyticsController
65
+ };
66
+ }, [authController, dialogsController, navigation, sideDialogsController]);
67
+
68
+ return fireCMSContextRef.current;
69
+ }
70
+
71
+ // export const useFireCMSContext = <USER extends User = User, AuthControllerType extends AuthController<USER> = AuthController<USER>>(): FireCMSContext<USER, AuthControllerType> => {
72
+ //
73
+ // const authController = useAuthController<USER, AuthControllerType>();
74
+ // const sideDialogsController = useSideDialogsController();
75
+ // const sideEntityController = useSideEntityController();
76
+ // const navigation = useNavigationController();
77
+ // const dataSource = useDataSource();
78
+ // const storageSource = useStorageSource();
79
+ // const snackbarController = useSnackbarController();
80
+ // const userConfigPersistence = useUserConfigurationPersistence();
81
+ // const dialogsController = useDialogsController();
82
+ // const customizationController = useCustomizationController();
83
+ // const analyticsController = useAnalyticsController();
84
+ //
85
+ // return {
86
+ // authController,
87
+ // sideDialogsController,
88
+ // sideEntityController,
89
+ // navigation,
90
+ // dataSource,
91
+ // storageSource,
92
+ // snackbarController,
93
+ // userConfigPersistence,
94
+ // dialogsController,
95
+ // customizationController,
96
+ // analyticsController
97
+ // };
98
+ //
99
+ // };
@@ -22,13 +22,14 @@ const notifyListeners = () => {
22
22
  };
23
23
 
24
24
  // Listen to resize events once, at a global level
25
- window.addEventListener("resize", () => {
26
- const newIsLargeLayout = checkLargeLayout("lg");
27
- if (newIsLargeLayout !== isLargeLayoutGlobal) {
28
- isLargeLayoutGlobal = newIsLargeLayout;
29
- notifyListeners();
30
- }
31
- });
25
+ if (typeof window !== "undefined")
26
+ window.addEventListener("resize", () => {
27
+ const newIsLargeLayout = checkLargeLayout("lg");
28
+ if (newIsLargeLayout !== isLargeLayoutGlobal) {
29
+ isLargeLayoutGlobal = newIsLargeLayout;
30
+ notifyListeners();
31
+ }
32
+ });
32
33
 
33
34
  export const useLargeLayout = () => {
34
35
  const [isLargeLayout, setIsLargeLayout] = useState(isLargeLayoutGlobal);
@@ -58,6 +59,8 @@ export const useLargeLayout = () => {
58
59
  };
59
60
 
60
61
  function checkLargeLayout(breakpoint: "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl" = "lg"): boolean {
62
+ if (typeof window === "undefined")
63
+ return false;
61
64
  return window.matchMedia(`(min-width: ${breakpoints[breakpoint] + 1}px)`).matches;
62
65
  }
63
66