@firecms/core 3.0.0-canary.21 → 3.0.0-canary.211

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 (382) hide show
  1. package/README.md +3 -3
  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 +34 -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 +23 -6
  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 -13
  12. package/dist/components/EntityCollectionTable/EntityCollectionTable.d.ts +2 -2
  13. package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +22 -6
  14. package/dist/components/EntityCollectionTable/PropertyTableCell.d.ts +1 -0
  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 +1 -1
  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 +7 -4
  21. package/dist/components/EntityCollectionView/EntityCollectionView.d.ts +16 -2
  22. package/dist/components/EntityCollectionView/EntityCollectionViewStartActions.d.ts +11 -0
  23. package/dist/components/EntityCollectionView/utils.d.ts +3 -0
  24. package/dist/components/EntityJsonPreview.d.ts +3 -0
  25. package/dist/components/EntityPreview.d.ts +5 -4
  26. package/dist/components/ErrorView.d.ts +1 -1
  27. package/dist/components/HomePage/DefaultHomePage.d.ts +1 -1
  28. package/dist/components/HomePage/NavigationCardBinding.d.ts +1 -1
  29. package/dist/components/PropertyConfigBadge.d.ts +2 -1
  30. package/dist/components/PropertyIdCopyTooltip.d.ts +8 -0
  31. package/dist/components/ReferenceWidget.d.ts +3 -1
  32. package/dist/components/SelectableTable/SelectableTable.d.ts +13 -3
  33. package/dist/components/SelectableTable/filters/ReferenceFilterField.d.ts +2 -1
  34. package/dist/components/UnsavedChangesDialog.d.ts +8 -0
  35. package/dist/components/VirtualTable/VirtualTableProps.d.ts +28 -12
  36. package/dist/components/VirtualTable/types.d.ts +3 -3
  37. package/dist/components/{EntityCollectionTable/internal → common}/default_entity_actions.d.ts +1 -3
  38. package/dist/components/common/index.d.ts +2 -1
  39. package/dist/components/common/table_height.d.ts +5 -0
  40. package/dist/components/common/types.d.ts +4 -6
  41. package/dist/components/common/useColumnsIds.d.ts +3 -1
  42. package/dist/components/common/{useDataSourceEntityCollectionTableController.d.ts → useDataSourceTableController.d.ts} +13 -2
  43. package/dist/components/common/useDebouncedCallback.d.ts +1 -0
  44. package/dist/components/common/useScrollRestoration.d.ts +14 -0
  45. package/dist/components/index.d.ts +4 -2
  46. package/dist/contexts/BreacrumbsContext.d.ts +8 -0
  47. package/dist/core/DefaultAppBar.d.ts +29 -0
  48. package/dist/core/DefaultDrawer.d.ts +19 -0
  49. package/dist/core/DrawerNavigationItem.d.ts +10 -0
  50. package/dist/core/EntityEditView.d.ts +35 -11
  51. package/dist/core/EntityEditViewFormActions.d.ts +2 -0
  52. package/dist/core/FireCMS.d.ts +3 -3
  53. package/dist/core/FireCMSRouter.d.ts +4 -0
  54. package/dist/core/NavigationRoutes.d.ts +2 -3
  55. package/dist/core/SideDialogs.d.ts +4 -2
  56. package/dist/core/index.d.ts +4 -4
  57. package/dist/form/EntityForm.d.ts +37 -69
  58. package/dist/form/EntityFormActions.d.ts +17 -0
  59. package/dist/form/PropertyFieldBinding.d.ts +1 -1
  60. package/dist/form/components/ErrorFocus.d.ts +1 -1
  61. package/dist/form/components/FieldHelperText.d.ts +3 -3
  62. package/dist/form/components/FormEntry.d.ts +6 -0
  63. package/dist/form/components/FormLayout.d.ts +5 -0
  64. package/dist/form/components/LabelWithIcon.d.ts +1 -1
  65. package/dist/form/components/LabelWithIconAndTooltip.d.ts +15 -0
  66. package/dist/form/components/StorageItemPreview.d.ts +4 -4
  67. package/dist/form/components/index.d.ts +3 -1
  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 -5
  80. package/dist/form/field_bindings/SwitchFieldBinding.d.ts +1 -2
  81. package/dist/form/field_bindings/TextFieldBinding.d.ts +1 -1
  82. package/dist/form/index.d.ts +16 -18
  83. package/dist/form/useClearRestoreValue.d.ts +2 -2
  84. package/dist/hooks/data/delete.d.ts +4 -4
  85. package/dist/hooks/data/save.d.ts +4 -5
  86. package/dist/hooks/data/useCollectionFetch.d.ts +1 -1
  87. package/dist/hooks/data/useEntityFetch.d.ts +4 -3
  88. package/dist/hooks/index.d.ts +1 -0
  89. package/dist/hooks/useAuthController.d.ts +1 -1
  90. package/dist/hooks/useBreadcrumbsController.d.ts +26 -0
  91. package/dist/hooks/useBuildNavigationController.d.ts +7 -5
  92. package/dist/hooks/useFireCMSContext.d.ts +1 -1
  93. package/dist/hooks/useModeController.d.ts +1 -2
  94. package/dist/hooks/useProjectLog.d.ts +8 -2
  95. package/dist/hooks/useResolvedNavigationFrom.d.ts +3 -3
  96. package/dist/hooks/useValidateAuthenticator.d.ts +4 -8
  97. package/dist/index.d.ts +1 -0
  98. package/dist/index.es.js +21921 -14330
  99. package/dist/index.es.js.map +1 -1
  100. package/dist/index.umd.js +24271 -588
  101. package/dist/index.umd.js.map +1 -1
  102. package/dist/internal/useBuildDataSource.d.ts +1 -16
  103. package/dist/internal/useBuildSideEntityController.d.ts +2 -2
  104. package/dist/internal/useUnsavedChangesDialog.d.ts +7 -9
  105. package/dist/preview/PropertyPreviewProps.d.ts +6 -1
  106. package/dist/preview/components/EnumValuesChip.d.ts +1 -1
  107. package/dist/preview/components/ReferencePreview.d.ts +3 -2
  108. package/dist/preview/components/StorageThumbnail.d.ts +2 -1
  109. package/dist/preview/components/UrlComponentPreview.d.ts +2 -1
  110. package/dist/preview/util.d.ts +3 -3
  111. package/dist/routes/CustomCMSRoute.d.ts +4 -0
  112. package/dist/routes/FireCMSRoute.d.ts +1 -0
  113. package/dist/routes/HomePageRoute.d.ts +3 -0
  114. package/dist/types/auth.d.ts +8 -10
  115. package/dist/types/collections.d.ts +77 -22
  116. package/dist/types/datasource.d.ts +52 -36
  117. package/dist/types/dialogs_controller.d.ts +7 -3
  118. package/dist/types/entities.d.ts +7 -2
  119. package/dist/types/entity_actions.d.ts +28 -4
  120. package/dist/types/entity_callbacks.d.ts +16 -16
  121. package/dist/types/entity_overrides.d.ts +2 -2
  122. package/dist/types/export_import.d.ts +4 -4
  123. package/dist/types/fields.d.ts +71 -42
  124. package/dist/types/firecms.d.ts +6 -2
  125. package/dist/types/firecms_context.d.ts +1 -1
  126. package/dist/types/index.d.ts +0 -1
  127. package/dist/types/navigation.d.ts +32 -14
  128. package/dist/types/permissions.d.ts +4 -4
  129. package/dist/types/plugins.d.ts +23 -12
  130. package/dist/types/properties.d.ts +52 -24
  131. package/dist/types/property_config.d.ts +0 -2
  132. package/dist/types/side_dialogs_controller.d.ts +10 -0
  133. package/dist/types/side_entity_controller.d.ts +6 -1
  134. package/dist/types/storage.d.ts +86 -3
  135. package/dist/types/user.d.ts +1 -0
  136. package/dist/util/builders.d.ts +3 -3
  137. package/dist/util/entities.d.ts +3 -3
  138. package/dist/util/entity_actions.d.ts +2 -0
  139. package/dist/util/entity_cache.d.ts +23 -0
  140. package/dist/util/icon_list.d.ts +5 -1
  141. package/dist/util/icon_synonyms.d.ts +1 -98
  142. package/dist/util/icons.d.ts +6 -3
  143. package/dist/util/index.d.ts +2 -0
  144. package/dist/util/navigation_from_path.d.ts +6 -1
  145. package/dist/util/navigation_utils.d.ts +14 -3
  146. package/dist/util/objects.d.ts +2 -1
  147. package/dist/util/permissions.d.ts +4 -4
  148. package/dist/util/plurals.d.ts +0 -2
  149. package/dist/util/property_utils.d.ts +3 -3
  150. package/dist/util/resolutions.d.ts +36 -17
  151. package/dist/util/storage.d.ts +23 -2
  152. package/dist/util/useStorageUploadController.d.ts +3 -3
  153. package/package.json +62 -48
  154. package/src/app/AppBar.tsx +18 -0
  155. package/src/app/Drawer.tsx +24 -0
  156. package/src/app/Scaffold.tsx +253 -0
  157. package/src/app/index.ts +4 -0
  158. package/src/app/useApp.tsx +32 -0
  159. package/src/components/ArrayContainer.tsx +127 -41
  160. package/src/components/CircularProgressCenter.tsx +2 -2
  161. package/src/components/ClearFilterSortButton.tsx +41 -0
  162. package/src/components/{DeleteConfirmationDialog.tsx → ConfirmationDialog.tsx} +3 -3
  163. package/src/components/DeleteEntityDialog.tsx +10 -19
  164. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +54 -37
  165. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +38 -31
  166. package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +30 -9
  167. package/src/components/EntityCollectionTable/PropertyTableCell.tsx +47 -39
  168. package/src/components/EntityCollectionTable/column_utils.tsx +3 -3
  169. package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +30 -16
  170. package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +19 -17
  171. package/src/components/EntityCollectionTable/index.tsx +1 -1
  172. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +31 -36
  173. package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +36 -34
  174. package/src/components/EntityCollectionTable/internal/EntityTableCellActions.tsx +20 -8
  175. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +81 -80
  176. package/src/components/EntityCollectionView/EntityCollectionView.tsx +207 -113
  177. package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +4 -2
  178. package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +68 -0
  179. package/src/components/EntityCollectionView/useSelectionController.tsx +20 -7
  180. package/src/components/EntityCollectionView/utils.ts +19 -0
  181. package/src/components/EntityJsonPreview.tsx +66 -0
  182. package/src/components/EntityPreview.tsx +62 -52
  183. package/src/components/EntityView.tsx +10 -10
  184. package/src/components/ErrorView.tsx +4 -4
  185. package/src/components/HomePage/DefaultHomePage.tsx +26 -19
  186. package/src/components/HomePage/FavouritesView.tsx +6 -11
  187. package/src/components/HomePage/NavigationCard.tsx +3 -3
  188. package/src/components/HomePage/NavigationCardBinding.tsx +5 -10
  189. package/src/components/HomePage/NavigationGroup.tsx +2 -2
  190. package/src/components/HomePage/SmallNavigationCard.tsx +5 -6
  191. package/src/components/NotFoundPage.tsx +2 -2
  192. package/src/components/PropertyConfigBadge.tsx +9 -3
  193. package/src/components/PropertyIdCopyTooltip.tsx +47 -0
  194. package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +19 -13
  195. package/src/components/ReferenceWidget.tsx +21 -11
  196. package/src/components/SearchIconsView.tsx +10 -7
  197. package/src/components/SelectableTable/SelectableTable.tsx +27 -12
  198. package/src/components/SelectableTable/filters/BooleanFilterField.tsx +2 -3
  199. package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +25 -8
  200. package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +36 -12
  201. package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +92 -23
  202. package/src/components/UnsavedChangesDialog.tsx +42 -0
  203. package/src/components/VirtualTable/VirtualTable.tsx +96 -48
  204. package/src/components/VirtualTable/VirtualTableCell.tsx +1 -9
  205. package/src/components/VirtualTable/VirtualTableHeader.tsx +10 -10
  206. package/src/components/VirtualTable/VirtualTableHeaderRow.tsx +2 -2
  207. package/src/components/VirtualTable/VirtualTableProps.tsx +33 -14
  208. package/src/components/VirtualTable/VirtualTableRow.tsx +5 -6
  209. package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +5 -5
  210. package/src/components/VirtualTable/fields/VirtualTableInput.tsx +3 -2
  211. package/src/components/VirtualTable/fields/VirtualTableNumberInput.tsx +2 -1
  212. package/src/components/VirtualTable/fields/VirtualTableSelect.tsx +16 -28
  213. package/src/components/VirtualTable/types.tsx +2 -3
  214. package/src/components/{EntityCollectionTable/internal → common}/default_entity_actions.tsx +33 -40
  215. package/src/components/common/index.ts +2 -1
  216. package/src/components/{VirtualTable/common.tsx → common/table_height.tsx} +5 -2
  217. package/src/components/common/types.tsx +4 -6
  218. package/src/components/common/useColumnsIds.tsx +24 -3
  219. package/src/components/common/useDataSourceTableController.tsx +420 -0
  220. package/src/components/common/useDebouncedCallback.tsx +20 -0
  221. package/src/components/common/useScrollRestoration.tsx +68 -0
  222. package/src/components/common/useTableSearchHelper.ts +53 -12
  223. package/src/components/index.tsx +4 -2
  224. package/src/contexts/BreacrumbsContext.tsx +38 -0
  225. package/src/contexts/DialogsProvider.tsx +5 -4
  226. package/src/contexts/ModeController.tsx +1 -3
  227. package/src/contexts/SnackbarProvider.tsx +2 -0
  228. package/src/core/DefaultAppBar.tsx +219 -0
  229. package/src/core/DefaultDrawer.tsx +185 -0
  230. package/src/core/DrawerNavigationItem.tsx +66 -0
  231. package/src/core/EntityEditView.tsx +345 -480
  232. package/src/core/EntityEditViewFormActions.tsx +199 -0
  233. package/src/core/EntitySidePanel.tsx +86 -17
  234. package/src/core/FireCMS.tsx +56 -49
  235. package/src/core/FireCMSRouter.tsx +17 -0
  236. package/src/core/NavigationRoutes.tsx +28 -38
  237. package/src/core/SideDialogs.tsx +22 -12
  238. package/src/core/field_configs.tsx +11 -12
  239. package/src/core/index.tsx +6 -5
  240. package/src/form/EntityForm.tsx +585 -539
  241. package/src/form/EntityFormActions.tsx +169 -0
  242. package/src/form/PropertyFieldBinding.tsx +85 -44
  243. package/src/form/components/CustomIdField.tsx +6 -2
  244. package/src/form/components/FieldHelperText.tsx +4 -4
  245. package/src/form/components/FormEntry.tsx +22 -0
  246. package/src/form/components/FormLayout.tsx +16 -0
  247. package/src/form/components/LabelWithIcon.tsx +30 -19
  248. package/src/form/components/LabelWithIconAndTooltip.tsx +28 -0
  249. package/src/form/components/StorageItemPreview.tsx +22 -12
  250. package/src/form/components/StorageUploadProgress.tsx +4 -5
  251. package/src/form/components/index.tsx +3 -1
  252. package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +31 -19
  253. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +47 -35
  254. package/src/form/field_bindings/BlockFieldBinding.tsx +56 -34
  255. package/src/form/field_bindings/DateTimeFieldBinding.tsx +18 -14
  256. package/src/form/field_bindings/KeyValueFieldBinding.tsx +60 -51
  257. package/src/form/field_bindings/MapFieldBinding.tsx +71 -54
  258. package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +153 -0
  259. package/src/form/field_bindings/{MultiSelectBinding.tsx → MultiSelectFieldBinding.tsx} +25 -20
  260. package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +11 -16
  261. package/src/form/field_bindings/ReferenceFieldBinding.tsx +42 -31
  262. package/src/form/field_bindings/RepeatFieldBinding.tsx +56 -35
  263. package/src/form/field_bindings/SelectFieldBinding.tsx +22 -14
  264. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +42 -50
  265. package/src/form/field_bindings/SwitchFieldBinding.tsx +29 -24
  266. package/src/form/field_bindings/TextFieldBinding.tsx +28 -24
  267. package/src/form/index.tsx +16 -37
  268. package/src/form/useClearRestoreValue.tsx +2 -2
  269. package/src/form/validation.ts +13 -23
  270. package/src/hooks/data/delete.ts +6 -5
  271. package/src/hooks/data/save.ts +13 -9
  272. package/src/hooks/data/useCollectionFetch.tsx +3 -3
  273. package/src/hooks/data/useDataSource.tsx +11 -3
  274. package/src/hooks/data/useEntityFetch.tsx +10 -6
  275. package/src/hooks/index.tsx +1 -0
  276. package/src/hooks/useAuthController.tsx +1 -1
  277. package/src/hooks/useBreadcrumbsController.tsx +31 -0
  278. package/src/hooks/useBuildLocalConfigurationPersistence.tsx +8 -10
  279. package/src/hooks/useBuildModeController.tsx +22 -29
  280. package/src/hooks/useBuildNavigationController.tsx +159 -54
  281. package/src/hooks/useFireCMSContext.tsx +5 -5
  282. package/src/hooks/useLargeLayout.tsx +0 -35
  283. package/src/hooks/useModeController.tsx +1 -2
  284. package/src/hooks/useProjectLog.tsx +32 -10
  285. package/src/hooks/useResolvedNavigationFrom.tsx +10 -12
  286. package/src/hooks/useValidateAuthenticator.tsx +17 -37
  287. package/src/index.ts +1 -0
  288. package/src/internal/useBuildDataSource.ts +72 -82
  289. package/src/internal/useBuildSideDialogsController.tsx +4 -2
  290. package/src/internal/useBuildSideEntityController.tsx +194 -73
  291. package/src/internal/useUnsavedChangesDialog.tsx +127 -91
  292. package/src/preview/PropertyPreview.tsx +17 -24
  293. package/src/preview/PropertyPreviewProps.tsx +7 -1
  294. package/src/preview/components/BooleanPreview.tsx +2 -2
  295. package/src/preview/components/EmptyValue.tsx +1 -1
  296. package/src/preview/components/EnumValuesChip.tsx +2 -2
  297. package/src/preview/components/ImagePreview.tsx +25 -36
  298. package/src/preview/components/ReferencePreview.tsx +22 -33
  299. package/src/preview/components/StorageThumbnail.tsx +5 -1
  300. package/src/preview/components/UrlComponentPreview.tsx +60 -28
  301. package/src/preview/property_previews/ArrayOfMapsPreview.tsx +2 -3
  302. package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +4 -3
  303. package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +2 -3
  304. package/src/preview/property_previews/ArrayOfStringsPreview.tsx +1 -2
  305. package/src/preview/property_previews/ArrayOneOfPreview.tsx +4 -5
  306. package/src/preview/property_previews/ArrayPropertyPreview.tsx +4 -5
  307. package/src/preview/property_previews/MapPropertyPreview.tsx +12 -11
  308. package/src/preview/property_previews/SkeletonPropertyComponent.tsx +12 -12
  309. package/src/preview/property_previews/StringPropertyPreview.tsx +3 -3
  310. package/src/preview/util.ts +10 -10
  311. package/src/routes/CustomCMSRoute.tsx +21 -0
  312. package/src/routes/FireCMSRoute.tsx +235 -0
  313. package/src/routes/HomePageRoute.tsx +17 -0
  314. package/src/types/auth.tsx +9 -13
  315. package/src/types/collections.ts +94 -27
  316. package/src/types/customization_controller.tsx +0 -1
  317. package/src/types/datasource.ts +61 -43
  318. package/src/types/dialogs_controller.tsx +7 -3
  319. package/src/types/entities.ts +12 -2
  320. package/src/types/entity_actions.tsx +32 -7
  321. package/src/types/entity_callbacks.ts +18 -18
  322. package/src/types/entity_overrides.tsx +2 -2
  323. package/src/types/export_import.ts +4 -4
  324. package/src/types/fields.tsx +81 -46
  325. package/src/types/firecms.tsx +7 -2
  326. package/src/types/firecms_context.tsx +1 -1
  327. package/src/types/index.ts +0 -1
  328. package/src/types/navigation.ts +38 -18
  329. package/src/types/permissions.ts +5 -5
  330. package/src/types/plugins.tsx +25 -14
  331. package/src/types/properties.ts +60 -25
  332. package/src/types/property_config.tsx +0 -2
  333. package/src/types/side_dialogs_controller.tsx +15 -0
  334. package/src/types/side_entity_controller.tsx +6 -1
  335. package/src/types/storage.ts +94 -3
  336. package/src/types/user.ts +2 -0
  337. package/src/util/builders.ts +10 -8
  338. package/src/util/entities.ts +9 -6
  339. package/src/util/entity_actions.ts +28 -0
  340. package/src/util/entity_cache.ts +204 -0
  341. package/src/util/enums.ts +1 -1
  342. package/src/util/icon_list.ts +16 -10
  343. package/src/util/icon_synonyms.ts +3 -100
  344. package/src/util/icons.tsx +17 -7
  345. package/src/util/index.ts +2 -0
  346. package/src/util/join_collections.ts +3 -0
  347. package/src/util/make_properties_editable.ts +13 -5
  348. package/src/util/navigation_from_path.ts +13 -6
  349. package/src/util/navigation_utils.ts +59 -7
  350. package/src/util/objects.ts +48 -28
  351. package/src/util/parent_references_from_path.ts +3 -3
  352. package/src/util/permissions.ts +9 -8
  353. package/src/util/plurals.ts +0 -2
  354. package/src/util/property_utils.tsx +11 -4
  355. package/src/util/references.ts +11 -2
  356. package/src/util/resolutions.ts +100 -46
  357. package/src/util/storage.ts +79 -21
  358. package/src/util/strings.ts +2 -2
  359. package/src/util/useStorageUploadController.tsx +71 -27
  360. package/dist/components/FireCMSAppBar.d.ts +0 -26
  361. package/dist/components/PropertyIdCopyTooltipContent.d.ts +0 -3
  362. package/dist/components/VirtualTable/common.d.ts +0 -2
  363. package/dist/core/Drawer.d.ts +0 -23
  364. package/dist/core/Scaffold.d.ts +0 -55
  365. package/dist/core/SideEntityView.d.ts +0 -7
  366. package/dist/form/components/FormikArrayContainer.d.ts +0 -18
  367. package/dist/form/field_bindings/MarkdownFieldBinding.d.ts +0 -9
  368. package/dist/internal/useBuildCustomizationController.d.ts +0 -2
  369. package/dist/internal/useLocaleConfig.d.ts +0 -1
  370. package/dist/types/appcheck.d.ts +0 -26
  371. package/src/components/FireCMSAppBar.tsx +0 -165
  372. package/src/components/PropertyIdCopyTooltipContent.tsx +0 -28
  373. package/src/components/common/useDataSourceEntityCollectionTableController.tsx +0 -225
  374. package/src/core/Drawer.tsx +0 -191
  375. package/src/core/Scaffold.tsx +0 -281
  376. package/src/core/SideEntityView.tsx +0 -38
  377. package/src/form/components/FormikArrayContainer.tsx +0 -44
  378. package/src/form/field_bindings/MarkdownFieldBinding.tsx +0 -695
  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/src/util/{common.tsx → common.ts} +0 -0
@@ -1,561 +1,426 @@
1
- import React, { useCallback, useEffect, useRef, useState } from "react";
2
- import {
3
- Entity,
4
- EntityCollection,
5
- EntityCustomView,
6
- EntityStatus,
7
- EntityValues,
8
- FireCMSPlugin,
9
- FormContext,
10
- User
11
- } from "../types";
12
- import { CircularProgressCenter, EntityCollectionView, EntityView, ErrorBoundary, } from "../components";
1
+ import React, { useEffect, useMemo, useState } from "react";
2
+ import { Entity, EntityCollection, EntityStatus, FireCMSPlugin, FormContext, User } from "../types";
3
+
4
+ import { CircularProgressCenter, EntityCollectionView, EntityView, ErrorBoundary } from "../components";
13
5
  import {
14
6
  canEditEntity,
15
7
  removeInitialAndTrailingSlashes,
16
8
  resolveDefaultSelectedView,
17
- resolveEntityView,
18
- useDebouncedCallback
9
+ resolvedSelectedEntityView
19
10
  } from "../util";
20
11
 
21
12
  import {
22
- saveEntityWithCallbacks,
23
13
  useAuthController,
24
14
  useCustomizationController,
25
- useDataSource,
26
15
  useEntityFetch,
27
16
  useFireCMSContext,
28
- useSideEntityController,
29
- useSnackbarController
17
+ useLargeLayout
30
18
  } from "../hooks";
31
- import { EntityForm } from "../form";
32
- import { CircularProgress, CloseIcon, cn, defaultBorderMixin, IconButton, Tab, Tabs, Typography } from "@firecms/ui";
33
- import { EntityFormSaveParams } from "../form/EntityForm";
34
- import { FORM_CONTAINER_WIDTH } from "../internal/common";
35
- import { useSideDialogContext } from "./index";
19
+ import { CircularProgress, cls, CodeIcon, defaultBorderMixin, Tab, Tabs, Typography } from "@firecms/ui";
20
+ import { getEntityFromCache } from "../util/entity_cache";
21
+ import { EntityForm, EntityFormProps } from "../form";
22
+ import { EntityEditViewFormActions } from "./EntityEditViewFormActions";
23
+ import { EntityJsonPreview } from "../components/EntityJsonPreview";
24
+
25
+ export const MAIN_TAB_VALUE = "__main_##Q$SC^#S6";
26
+ export const JSON_TAB_VALUE = "__json";
27
+
28
+ export type OnUpdateParams = {
29
+ entity: Entity<any>,
30
+ status: EntityStatus,
31
+ path: string,
32
+ entityId?: string;
33
+ selectedTab?: string;
34
+ collection: EntityCollection<any>
35
+ };
36
36
 
37
- const MAIN_TAB_VALUE = "main_##Q$SC^#S6";
37
+ export type OnTabChangeParams<M extends Record<string, any>> = {
38
+ path: string;
39
+ entityId?: string;
40
+ selectedTab?: string;
41
+ collection: EntityCollection<M>;
42
+ };
38
43
 
39
44
  export interface EntityEditViewProps<M extends Record<string, any>> {
40
45
  path: string;
41
46
  collection: EntityCollection<M>;
42
47
  entityId?: string;
48
+ databaseId?: string;
43
49
  copy?: boolean;
44
- selectedSubPath?: string;
50
+ selectedTab?: string;
45
51
  parentCollectionIds: string[];
46
- formWidth?: number | string;
47
- onValuesAreModified: (modified: boolean) => void;
48
- onUpdate?: (params: { entity: Entity<any> }) => void;
49
- onClose?: () => void;
52
+ onValuesModified?: (modified: boolean) => void;
53
+ onSaved?: (params: OnUpdateParams) => void;
54
+ onTabChange?: (props: OnTabChangeParams<M>) => void;
55
+ layout?: "side_panel" | "full_screen";
56
+ barActions?: React.ReactNode;
57
+ formProps?: Partial<EntityFormProps<M>>
50
58
  }
51
59
 
52
60
  /**
53
61
  * This is the default view that is used as the content of a side panel when
54
62
  * an entity is opened.
55
- * You probably don't want to use this view directly since it is bound to the
56
- * side panel. Instead, you might want to use {@link EntityForm} or {@link EntityCollectionView}
57
63
  */
58
- export function EntityEditView<M extends Record<string, any>, UserType extends User>({
59
- path,
60
- entityId,
61
- selectedSubPath,
62
- copy,
63
- collection,
64
- parentCollectionIds,
65
- onValuesAreModified,
66
- formWidth,
67
- onUpdate,
68
- onClose,
69
- }: EntityEditViewProps<M>) {
70
-
71
- if (collection.customId && collection.formAutoSave) {
72
- console.warn(`The collection ${collection.path} has customId and formAutoSave enabled. This is not supported and formAutoSave will be ignored`);
73
- }
64
+ export function EntityEditView<M extends Record<string, any>, USER extends User>({
65
+ entityId,
66
+ ...props
67
+ }: EntityEditViewProps<M>) {
74
68
 
75
- const [saving, setSaving] = useState(false);
76
- /**
77
- * These are the values that are being saved. They are debounced.
78
- * We use this only when autoSave is enabled.
79
- */
80
- const [valuesToBeSaved, setValuesToBeSaved] = useState<EntityValues<M> | undefined>(undefined);
81
- useDebouncedCallback(valuesToBeSaved, () => {
82
- if (valuesToBeSaved)
83
- saveEntity({
84
- entityId: usedEntity?.id,
85
- collection,
86
- path,
87
- values: valuesToBeSaved,
88
- closeAfterSave: false
89
- });
90
- }, false, 2000);
91
-
92
- // const largeLayout = useLargeLayout();
93
- // const largeLayoutTabSelected = useRef(!largeLayout);
94
-
95
- const resolvedFormWidth: string = typeof formWidth === "number" ? `${formWidth}px` : formWidth ?? FORM_CONTAINER_WIDTH;
69
+ const {
70
+ entity,
71
+ dataLoading,
72
+ // eslint-disable-next-line no-unused-vars
73
+ dataLoadingError
74
+ } = useEntityFetch<M, USER>({
75
+ path: props.path,
76
+ entityId: entityId,
77
+ collection: props.collection,
78
+ databaseId: props.databaseId,
79
+ useCache: false
80
+ });
96
81
 
97
- const dataSource = useDataSource(collection);
98
- const sideDialogContext = useSideDialogContext();
99
- const sideEntityController = useSideEntityController();
100
- const snackbarController = useSnackbarController();
101
- const customizationController = useCustomizationController();
102
- const context = useFireCMSContext();
103
- const authController = useAuthController<UserType>();
82
+ const cachedValues = entityId
83
+ ? getEntityFromCache(props.path + "/" + entityId)
84
+ : getEntityFromCache(props.path + "#new");
104
85
 
105
- const [formContext, setFormContext] = useState<FormContext<M> | undefined>(undefined);
86
+ const authController = useAuthController();
106
87
 
107
- const [status, setStatus] = useState<EntityStatus>(copy ? "copy" : (entityId ? "existing" : "new"));
88
+ const initialStatus = props.copy ? "copy" : (entityId ? "existing" : "new");
89
+ const [status, setStatus] = useState<EntityStatus>(initialStatus);
108
90
 
109
- const modifiedValuesRef = useRef<EntityValues<M> | undefined>(undefined);
110
- const modifiedValues = modifiedValuesRef.current;
91
+ const canEdit = useMemo(() => {
92
+ if (status === "new" || status === "copy") {
93
+ return true;
94
+ } else {
95
+ return entity ? canEditEntity(props.collection, authController, props.path, entity ?? null) : undefined;
96
+ }
97
+ }, [authController, entity, status]);
111
98
 
112
- const subcollections = (collection.subcollections ?? []).filter(c => !c.hideFromNavigation);
113
- const subcollectionsCount = subcollections?.length ?? 0;
114
- const customViews = collection.entityViews;
115
- const customViewsCount = customViews?.length ?? 0;
116
- const autoSave = collection.formAutoSave && !collection.customId;
99
+ if ((dataLoading && !cachedValues) || (!entity || canEdit === undefined) && (status === "existing" || status === "copy")) {
100
+ return <CircularProgressCenter/>;
101
+ }
117
102
 
118
- const hasAdditionalViews = customViewsCount > 0 || subcollectionsCount > 0;
103
+ if (entityId && !entity && !cachedValues) {
104
+ console.error(`Entity with id ${entityId} not found in collection ${props.path}`);
105
+ }
119
106
 
120
- const defaultSelectedView = selectedSubPath ?? resolveDefaultSelectedView(
121
- collection ? collection.defaultSelectedView : undefined,
122
- {
123
- status,
124
- entityId
125
- }
126
- );
107
+ if (!canEdit) {
108
+ return <div className={"flex flex-col"}>
109
+ <Typography className={"mt-16 mb-8 mx-8"} variant={"h4"}>
110
+ {props.collection.singularName ?? props.collection.name}
111
+ </Typography>
112
+ <EntityView
113
+ className={"px-8"}
114
+ entity={entity as Entity<M>}
115
+ path={props.path}
116
+ collection={props.collection}/>
117
+ </div>
118
+ }
127
119
 
128
- const selectedTabRef = useRef<string>(defaultSelectedView ?? MAIN_TAB_VALUE);
120
+ return <EntityEditViewInner<M> {...props}
121
+ entityId={entityId}
122
+ entity={entity}
123
+ cachedDirtyValues={cachedValues as Partial<M>}
124
+ dataLoading={dataLoading}
125
+ status={status}
126
+ setStatus={setStatus}
127
+ />;
128
+ }
129
129
 
130
- const mainViewVisible = selectedTabRef.current === MAIN_TAB_VALUE;
130
+ export function EntityEditViewInner<M extends Record<string, any>>({
131
+ path,
132
+ entityId,
133
+ selectedTab: selectedTabProp,
134
+ collection,
135
+ parentCollectionIds,
136
+ onValuesModified,
137
+ onSaved,
138
+ onTabChange,
139
+ entity,
140
+ cachedDirtyValues,
141
+ dataLoading,
142
+ layout = "side_panel",
143
+ barActions,
144
+ status,
145
+ setStatus,
146
+ formProps
147
+ }: EntityEditViewProps<M> & {
148
+ entity?: Entity<M>,
149
+ cachedDirtyValues?: Partial<M>, // dirty cached entity in memory
150
+ dataLoading: boolean,
151
+ status: EntityStatus,
152
+ setStatus: (status: EntityStatus) => void,
153
+ }) {
131
154
 
132
- const {
133
- entity,
134
- dataLoading,
135
- // eslint-disable-next-line no-unused-vars
136
- dataLoadingError
137
- } = useEntityFetch<M, UserType>({
138
- path,
139
- entityId,
140
- collection,
141
- useCache: false
142
- });
155
+ const context = useFireCMSContext();
143
156
 
144
157
  const [usedEntity, setUsedEntity] = useState<Entity<M> | undefined>(entity);
145
- const [readOnly, setReadOnly] = useState<boolean | undefined>(undefined);
146
158
 
147
159
  useEffect(() => {
148
160
  if (entity)
149
161
  setUsedEntity(entity);
150
162
  }, [entity]);
151
163
 
152
- useEffect(() => {
153
- if (status === "new") {
154
- setReadOnly(false);
155
- } else {
156
- const editEnabled = usedEntity ? canEditEntity(collection, authController, path, usedEntity ?? null) : false;
157
- if (usedEntity)
158
- setReadOnly(!editEnabled);
159
- }
160
- }, [authController, usedEntity, status]);
164
+ // Instead of using a ref (which does not trigger re-render), we use state for the form context.
165
+ const [formContext, setFormContext] = useState<FormContext<M> | undefined>(undefined);
161
166
 
162
- const onPreSaveHookError = useCallback((e: Error) => {
163
- setSaving(false);
164
- snackbarController.open({
165
- type: "error",
166
- message: "Error before saving: " + e?.message
167
- });
168
- console.error(e);
169
- }, [snackbarController]);
170
-
171
- const onSaveSuccessHookError = useCallback((e: Error) => {
172
- setSaving(false);
173
- snackbarController.open({
174
- type: "error",
175
- message: "Error after saving (entity is saved): " + e?.message
176
- });
177
- console.error(e);
178
- }, [snackbarController]);
167
+ const largeLayout = useLargeLayout();
179
168
 
180
- const onSaveSuccess = (updatedEntity: Entity<M>, closeAfterSave: boolean) => {
169
+ const customizationController = useCustomizationController();
181
170
 
182
- setSaving(false);
183
- if (!autoSave)
184
- snackbarController.open({
185
- type: "success",
186
- message: `${collection.singularName ?? collection.name}: Saved correctly`
187
- });
171
+ const defaultSelectedView = useMemo(() => resolveDefaultSelectedView(
172
+ collection ? collection.defaultSelectedView : undefined,
173
+ {
174
+ status,
175
+ entityId
176
+ }
177
+ ), []);
188
178
 
189
- setUsedEntity(updatedEntity);
190
- setStatus("existing");
179
+ const [selectedTab, setSelectedTab] = useState<string>(selectedTabProp ?? defaultSelectedView ?? MAIN_TAB_VALUE);
191
180
 
192
- onValuesAreModified(false);
181
+ useEffect(() => {
182
+ if ((selectedTabProp ?? MAIN_TAB_VALUE) !== selectedTab) {
183
+ setSelectedTab(selectedTabProp ?? MAIN_TAB_VALUE);
184
+ }
185
+ }, [selectedTabProp]);
193
186
 
194
- if (onUpdate)
195
- onUpdate({ entity: updatedEntity });
187
+ const subcollections = (collection.subcollections ?? []).filter(c => !c.hideFromNavigation);
188
+ const subcollectionsCount = subcollections?.length ?? 0;
189
+ const customViews = collection.entityViews;
190
+ const customViewsCount = customViews?.length ?? 0;
191
+ const includeJsonView = true;
192
+ const hasAdditionalViews = customViewsCount > 0 || subcollectionsCount > 0 || includeJsonView;
196
193
 
197
- if (closeAfterSave) {
198
- sideDialogContext.setBlocked(false);
199
- sideDialogContext.close(true);
200
- onClose?.();
201
- } else if (status !== "existing") {
202
- sideEntityController.replace({
203
- path,
204
- entityId: updatedEntity.id,
205
- selectedSubPath: selectedTabRef.current,
206
- updateUrl: true,
207
- collection,
208
- });
209
- }
194
+ const {
195
+ resolvedEntityViews,
196
+ selectedEntityView,
197
+ selectedSecondaryForm
198
+ } = resolvedSelectedEntityView(customViews, customizationController, selectedTab);
210
199
 
211
- };
200
+ const actionsAtTheBottom = !largeLayout || layout === "side_panel" || selectedEntityView?.includeActions === "bottom";
212
201
 
213
- const onSaveFailure = useCallback((e: Error) => {
202
+ const mainViewVisible = selectedTab === MAIN_TAB_VALUE || Boolean(selectedSecondaryForm);
214
203
 
215
- setSaving(false);
216
- snackbarController.open({
217
- type: "error",
218
- message: "Error saving: " + e?.message
219
- });
204
+ const customViewsView: React.ReactNode[] | undefined = customViews && resolvedEntityViews
205
+ .filter(e => !e.includeActions)
206
+ .map((customView) => {
207
+ if (!customView)
208
+ return null;
209
+ const Builder = customView.Builder;
210
+ if (!Builder) {
211
+ console.error("customView.Builder is not defined");
212
+ return null;
213
+ }
220
214
 
221
- console.error("Error saving entity", path, entityId);
222
- console.error(e);
223
- }, [entityId, path, snackbarController]);
224
-
225
- const saveEntity = ({
226
- values,
227
- previousValues,
228
- closeAfterSave,
229
- entityId,
230
- collection,
231
- path
232
- }: {
233
- collection: EntityCollection<M>,
234
- path: string,
235
- entityId: string | undefined,
236
- values: M,
237
- previousValues?: M,
238
- closeAfterSave: boolean,
239
- }) => {
240
- setSaving(true);
241
- saveEntityWithCallbacks({
242
- path,
243
- entityId,
244
- values,
245
- previousValues,
246
- collection,
247
- status,
248
- dataSource,
249
- context,
250
- onSaveSuccess: (updatedEntity: Entity<M>) => onSaveSuccess(updatedEntity, closeAfterSave),
251
- onSaveFailure,
252
- onPreSaveHookError,
253
- onSaveSuccessHookError
254
- }).then();
255
- };
215
+ return <div
216
+ className={cls(defaultBorderMixin,
217
+ "relative flex-1 w-full h-full overflow-auto",
218
+ { "hidden": selectedTab !== customView.key }
219
+ )}
220
+ key={`custom_view_${customView.key}`}
221
+ role="tabpanel">
222
+ <ErrorBoundary>
223
+ {formContext && <Builder
224
+ collection={collection}
225
+ entity={usedEntity}
226
+ modifiedValues={formContext.formex.values ?? usedEntity?.values}
227
+ formContext={formContext}
228
+ />}
229
+ </ErrorBoundary>
230
+ </div>;
231
+ }).filter(Boolean);
232
+
233
+ const globalLoading = dataLoading && !usedEntity;
234
+
235
+ const jsonView = <div
236
+ className={cls("relative flex-1 h-full overflow-auto w-full",
237
+ { "hidden": selectedTab !== JSON_TAB_VALUE })}
238
+ key={"json_view"}
239
+ role="tabpanel">
240
+ <ErrorBoundary>
241
+ <EntityJsonPreview
242
+ values={formContext?.values ?? {}}/>
243
+ </ErrorBoundary>
244
+ </div>;
245
+
246
+ const subCollectionsViews = subcollections && subcollections.map((subcollection) => {
247
+ const subcollectionId = subcollection.id ?? subcollection.path;
248
+ const fullPath = usedEntity ? `${path}/${usedEntity?.id}/${removeInitialAndTrailingSlashes(subcollectionId)}` : undefined;
249
+ if (selectedTab !== subcollectionId) return null;
250
+ return (
251
+ <div
252
+ className={"relative flex-1 h-full overflow-auto w-full"}
253
+ key={`subcol_${subcollectionId}`}
254
+ role="tabpanel">
255
+
256
+ {globalLoading && <CircularProgressCenter/>}
257
+
258
+ {!globalLoading &&
259
+ (usedEntity && fullPath
260
+ ? <EntityCollectionView
261
+ fullPath={fullPath}
262
+ parentCollectionIds={[...parentCollectionIds, collection.id]}
263
+ isSubCollection={true}
264
+ updateUrl={false}
265
+ {...subcollection}
266
+ openEntityMode={layout}/>
267
+ : <div className="flex items-center justify-center w-full h-full p-3">
268
+ <Typography variant={"label"}>
269
+ You need to save your entity before
270
+ adding additional collections
271
+ </Typography>
272
+ </div>)
273
+ }
256
274
 
257
- const onSaveEntityRequest = async ({
258
- collection,
259
- path,
260
- entityId,
261
- values,
262
- previousValues,
263
- closeAfterSave,
264
- autoSave
265
- }: EntityFormSaveParams<M>): Promise<void> => {
266
- if (!status)
267
- return;
268
-
269
- if (autoSave) {
270
- setValuesToBeSaved(values);
271
- } else {
272
- saveEntity({
273
- collection,
275
+ </div>
276
+ );
277
+ }).filter(Boolean);
278
+
279
+ const onSideTabClick = (value: string) => {
280
+ setSelectedTab(value);
281
+ if (status === "existing") {
282
+ onTabChange?.({
274
283
  path,
275
284
  entityId,
276
- values,
277
- previousValues,
278
- closeAfterSave
285
+ selectedTab: value === MAIN_TAB_VALUE ? undefined : value,
286
+ collection
279
287
  });
280
288
  }
281
289
  };
282
290
 
283
- const resolvedEntityViews = customViews ? customViews
284
- .map(e => resolveEntityView(e, customizationController.entityViews))
285
- .filter(Boolean) as EntityCustomView[]
286
- : [];
291
+ // Render the main entity form view (or a read-only view if the user cannot edit)
292
+ const entityView = <EntityForm<M>
293
+ collection={collection}
294
+ path={path}
295
+ entityId={entityId ?? usedEntity?.id}
296
+ onValuesModified={onValuesModified}
297
+ entity={entity}
298
+ initialDirtyValues={cachedDirtyValues}
299
+ openEntityMode={layout}
300
+ forceActionsAtTheBottom={actionsAtTheBottom}
301
+ initialStatus={status}
302
+ className={cls(!mainViewVisible ? "hidden" : "", formProps?.className)}
303
+ EntityFormActionsComponent={EntityEditViewFormActions}
304
+ {...formProps}
305
+ onEntityChange={(entity) => {
306
+ setUsedEntity(entity);
307
+ formProps?.onEntityChange?.(entity);
308
+ }}
309
+ onStatusChange={(status) => {
310
+ setStatus(status);
311
+ formProps?.onStatusChange?.(status);
312
+ }}
313
+ onFormContextReady={(formContext) => {
314
+ setFormContext(formContext);
315
+ formProps?.onFormContextReady?.(formContext);
316
+ }}
317
+ onSaved={(params) => {
318
+ const res = {
319
+ ...params,
320
+ selectedTab: MAIN_TAB_VALUE === selectedTab ? undefined : selectedTab
321
+ };
322
+ onSaved?.(res);
323
+ formProps?.onSaved?.(res);
324
+ }}
325
+ Builder={selectedSecondaryForm?.Builder}
326
+ />;
327
+
328
+ const subcollectionTabs = subcollections && subcollections.map((subcollection) =>
329
+ <Tab
330
+ className="text-sm min-w-[120px]"
331
+ value={subcollection.id}
332
+ key={`entity_detail_collection_tab_${subcollection.name}`}>
333
+ {subcollection.name}
334
+ </Tab>
335
+ );
287
336
 
288
- const customViewsView: React.ReactNode[] | undefined = customViews && resolvedEntityViews
289
- .map(
290
- (customView, colIndex) => {
291
- if (!customView)
292
- return null;
293
- if (selectedTabRef.current !== customView.key)
294
- return null;
295
- const Builder = customView.Builder;
296
- if (!Builder) {
297
- console.error("customView.Builder is not defined");
298
- return null;
299
- }
300
- return <div
301
- className={cn(defaultBorderMixin,
302
- "relative flex-grow w-full h-full overflow-auto ")}
303
- key={`custom_view_${customView.key}`}
304
- role="tabpanel">
305
- <ErrorBoundary>
306
- {formContext && <Builder
307
- collection={collection}
308
- entity={usedEntity}
309
- modifiedValues={modifiedValues ?? usedEntity?.values}
310
- formContext={formContext}
311
- />}
312
- </ErrorBoundary>
313
- </div>;
314
- }
315
- ).filter(Boolean);
337
+ const customViewTabs = resolvedEntityViews.map((view) =>
338
+ <Tab
339
+ className="text-sm min-w-[120px]"
340
+ value={view.key}
341
+ key={`entity_detail_collection_tab_${view.name}`}>
342
+ {view.name}
343
+ </Tab>
344
+ );
316
345
 
317
- const globalLoading = (dataLoading && !usedEntity) ||
318
- ((!usedEntity || readOnly === undefined) && (status === "existing" || status === "copy"));
346
+ const shouldShowTopBar = Boolean(barActions) || hasAdditionalViews;
319
347
 
320
- const loading = globalLoading || saving;
348
+ let result = <div className="relative flex flex-col h-full w-full bg-white dark:bg-surface-900">
321
349
 
322
- const subCollectionsViews = subcollections && subcollections.map(
323
- (subcollection, colIndex) => {
324
- const subcollectionId = subcollection.id ?? subcollection.path;
325
- const fullPath = usedEntity ? `${path}/${usedEntity?.id}/${removeInitialAndTrailingSlashes(subcollectionId)}` : undefined;
326
- if (selectedTabRef.current !== subcollectionId)
327
- return null;
328
- return (
329
- <div
330
- className={"relative flex-grow h-full overflow-auto w-full"}
331
- key={`subcol_${subcollectionId}`}
332
- role="tabpanel">
333
-
334
- {loading && <CircularProgressCenter/>}
335
-
336
- {!globalLoading &&
337
- (usedEntity && fullPath
338
- ? <EntityCollectionView
339
- fullPath={fullPath}
340
- parentCollectionIds={[...parentCollectionIds, collection.id]}
341
- isSubCollection={true}
342
- {...subcollection}/>
343
- : <div
344
- className="flex items-center justify-center w-full h-full p-3">
345
- <Typography variant={"label"}>
346
- You need to save your entity before
347
- adding additional collections
348
- </Typography>
349
- </div>)
350
- }
351
-
352
- </div>
353
- );
354
- }
355
- ).filter(Boolean);
350
+ {shouldShowTopBar && <div
351
+ className={cls("h-14 flex overflow-visible overflow-x-scroll w-full no-scrollbar h-14 border-b pl-2 pr-2 pt-1 flex items-end bg-surface-50 dark:bg-surface-900", defaultBorderMixin)}>
356
352
 
357
- const onDiscard = useCallback(() => {
358
- onValuesAreModified(false);
359
- }, []);
353
+ {barActions}
360
354
 
361
- const onSideTabClick = (value: string) => {
362
- selectedTabRef.current = value;
363
- sideEntityController.replace({
364
- path,
365
- entityId,
366
- selectedSubPath: value === MAIN_TAB_VALUE ? undefined : value,
367
- updateUrl: true,
368
- collection,
369
- });
370
- };
355
+ <div className={"flex-grow"}/>
371
356
 
372
- const onValuesChanged = useCallback((values?: EntityValues<M>) => {
373
- modifiedValuesRef.current = values;
374
- }, []);
357
+ {globalLoading && <div className="self-center">
358
+ <CircularProgress size={"small"}/>
359
+ </div>}
375
360
 
376
- // eslint-disable-next-line n/handle-callback-err
377
- const onIdUpdateError = useCallback((error: any) => {
378
- snackbarController.open({
379
- type: "error",
380
- message: "Error updating id, check the console"
381
- });
382
- }, []);
361
+ {hasAdditionalViews && <Tabs
362
+ value={selectedTab}
363
+ onValueChange={(value) => {
364
+ onSideTabClick(value);
365
+ }}>
383
366
 
384
- const onIdChange = useCallback((id: string) => {
385
- setUsedEntity((prevEntity) => prevEntity
386
- ? {
387
- ...prevEntity,
388
- id
389
- }
390
- : undefined);
391
- }, []);
367
+ {includeJsonView && <Tab
368
+ disabled={!hasAdditionalViews}
369
+ value={JSON_TAB_VALUE}
370
+ innerClassName={"block"}
371
+ className={"text-sm"}>
372
+ <CodeIcon size={"small"}/>
373
+ </Tab>}
392
374
 
393
- const onModified = (dirty: boolean) => {
394
- if (!autoSave)
395
- onValuesAreModified(dirty);
396
- }
375
+ <Tab
376
+ disabled={!hasAdditionalViews}
377
+ value={MAIN_TAB_VALUE}
378
+ className={"text-sm min-w-[120px]"}>
379
+ {collection.singularName ?? collection.name}
380
+ </Tab>
397
381
 
398
- function buildForm() {
399
- const plugins = customizationController.plugins;
400
- let form = <EntityForm
401
- status={status}
402
- path={path}
403
- collection={collection}
404
- onEntitySaveRequested={onSaveEntityRequest}
405
- onDiscard={onDiscard}
406
- onValuesChanged={onValuesChanged}
407
- onModified={onModified}
408
- entity={usedEntity}
409
- onIdChange={onIdChange}
410
- onFormContextChange={setFormContext}
411
- hideId={collection.hideIdFromForm}
412
- autoSave={autoSave}
413
- onIdUpdateError={onIdUpdateError}
414
- />;
415
- if (plugins) {
416
- plugins.forEach((plugin: FireCMSPlugin) => {
417
- if (plugin.form?.provider) {
418
- form = (
419
- <plugin.form.provider.Component
420
- status={status}
421
- path={path}
422
- collection={collection}
423
- onDiscard={onDiscard}
424
- onValuesChanged={onValuesChanged}
425
- onModified={onModified}
426
- entity={usedEntity}
427
- context={context}
428
- formContext={formContext}
429
- {...plugin.form.provider.props}>
430
- {form}
431
- </plugin.form.provider.Component>
432
- );
433
- }
434
- });
435
- }
436
- return <ErrorBoundary>{form}</ErrorBoundary>;
437
- }
438
382
 
439
- const form = (readOnly === undefined)
440
- ? <></>
441
- : (!readOnly
442
- ? buildForm()
443
- : (
444
- <>
445
- <Typography
446
- className={"mt-16 mb-8 mx-8"}
447
- variant={"h4"}>{collection.singularName ?? collection.name}
448
- </Typography>
449
- <EntityView
450
- className={"px-12"}
451
- entity={usedEntity as Entity<M>}
452
- path={path}
453
- collection={collection}/>
454
- </>
455
- ));
456
-
457
- const subcollectionTabs = subcollections && subcollections.map(
458
- (subcollection) =>
459
- <Tab
460
- className="text-sm min-w-[140px]"
461
- value={subcollection.id}
462
- key={`entity_detail_collection_tab_${subcollection.name}`}>
463
- {subcollection.name}
464
- </Tab>
465
- );
383
+ {customViewTabs}
466
384
 
467
- const customViewTabs = resolvedEntityViews.map(
468
- (view) =>
385
+ {subcollectionTabs}
386
+ </Tabs>}
387
+ </div>}
469
388
 
470
- <Tab
471
- className="text-sm min-w-[140px]"
472
- value={view.key}
473
- key={`entity_detail_collection_tab_${view.name}`}>
474
- {view.name}
475
- </Tab>
476
- );
389
+ {globalLoading
390
+ ? <div className="w-full pt-12 pb-16 px-4 sm:px-8 md:px-10">
391
+ <CircularProgressCenter/>
392
+ </div>
393
+ : entityView}
394
+
395
+ {jsonView}
396
+
397
+ {customViewsView}
398
+
399
+ {subCollectionsViews}
400
+
401
+ </div>;
477
402
 
478
- return (
479
- <div
480
- className="flex flex-col h-full w-full transition-width duration-250 ease-in-out">
481
- {
482
- <>
483
-
484
- <div
485
- className={cn(defaultBorderMixin, "no-scrollbar border-b pl-2 pr-2 pt-1 flex items-end overflow-scroll bg-gray-50 dark:bg-gray-950")}>
486
-
487
- <div
488
- className="pb-1 self-center">
489
- <IconButton
490
- onClick={() => {
491
- onClose?.();
492
- return sideDialogContext.close(false);
493
- }}
494
- size="large">
495
- <CloseIcon/>
496
- </IconButton>
497
- </div>
498
-
499
- <div className={"flex-grow"}/>
500
-
501
- {globalLoading && <div
502
- className="self-center">
503
- <CircularProgress size={"small"}/>
504
- </div>}
505
-
506
- <Tabs
507
- value={selectedTabRef.current}
508
- onValueChange={(value) => {
509
- onSideTabClick(value);
510
- }}
511
- className="pl-4 pr-4 pt-0">
512
-
513
- <Tab
514
- disabled={!hasAdditionalViews}
515
- value={MAIN_TAB_VALUE}
516
- className={`${
517
- !hasAdditionalViews ? "hidden" : ""
518
- } text-sm min-w-[140px]`}
519
- >{collection.singularName ?? collection.name}</Tab>
520
-
521
- {customViewTabs}
522
-
523
- {subcollectionTabs}
524
- </Tabs>
525
-
526
- </div>
527
-
528
- <div
529
- className={"flex-grow h-full flex overflow-auto flex-row w-full "}
530
- style={{
531
- // width: `calc(${ADDITIONAL_TAB_WIDTH} + ${resolvedFormWidth})`,
532
- // maxWidth: "100%",
533
- // [`@media (max-width: ${resolvedFormWidth})`]: {
534
- // width: resolvedFormWidth
535
- // }
536
- }}>
537
-
538
- <div
539
- role="tabpanel"
540
- hidden={!mainViewVisible}
541
- id={`form_${path}`}
542
- className={" w-full"}>
543
-
544
- {globalLoading
545
- ? <CircularProgressCenter/>
546
- : form}
547
-
548
- </div>
549
-
550
- {customViewsView}
551
-
552
- {subCollectionsViews}
553
-
554
- </div>
555
-
556
- </>
403
+ const plugins = customizationController.plugins;
404
+
405
+ if (plugins) {
406
+ plugins.forEach((plugin: FireCMSPlugin) => {
407
+ if (plugin.form?.provider) {
408
+ result = (
409
+ <plugin.form.provider.Component
410
+ status={status}
411
+ path={path}
412
+ collection={collection}
413
+ entity={usedEntity}
414
+ context={context}
415
+ formContext={formContext}
416
+ {...plugin.form.provider.props}>
417
+ {result}
418
+ </plugin.form.provider.Component>
419
+ );
557
420
  }
421
+ });
422
+ }
558
423
 
559
- </div>
560
- );
424
+ return result;
561
425
  }
426
+