@firecms/core 3.0.0-canary.14 → 3.0.0-canary.141

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 (301) 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 +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 +16 -5
  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 +11 -12
  12. package/dist/components/EntityCollectionTable/EntityCollectionTable.d.ts +1 -1
  13. package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +5 -3
  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/internal/CollectionTableToolbar.d.ts +1 -4
  18. package/dist/components/EntityCollectionTable/internal/EntityTableCell.d.ts +2 -2
  19. package/dist/components/EntityCollectionTable/internal/popup_field/PopupFormField.d.ts +7 -4
  20. package/dist/components/EntityCollectionView/EntityCollectionView.d.ts +12 -2
  21. package/dist/components/EntityCollectionView/EntityCollectionViewStartActions.d.ts +11 -0
  22. package/dist/components/EntityCollectionView/utils.d.ts +3 -0
  23. package/dist/components/EntityPreview.d.ts +7 -6
  24. package/dist/components/ErrorView.d.ts +1 -1
  25. package/dist/components/HomePage/DefaultHomePage.d.ts +1 -1
  26. package/dist/components/HomePage/NavigationCardBinding.d.ts +1 -1
  27. package/dist/components/PropertyConfigBadge.d.ts +2 -1
  28. package/dist/components/PropertyIdCopyTooltip.d.ts +8 -0
  29. package/dist/components/ReferenceWidget.d.ts +3 -1
  30. package/dist/components/SelectableTable/SelectableTable.d.ts +1 -1
  31. package/dist/components/SelectableTable/filters/ReferenceFilterField.d.ts +2 -1
  32. package/dist/components/VirtualTable/VirtualTableProps.d.ts +15 -12
  33. package/dist/components/VirtualTable/types.d.ts +3 -3
  34. package/dist/components/{EntityCollectionTable/internal → common}/default_entity_actions.d.ts +1 -1
  35. package/dist/components/common/index.d.ts +1 -0
  36. package/dist/components/common/table_height.d.ts +5 -0
  37. package/dist/components/common/types.d.ts +4 -6
  38. package/dist/components/common/useColumnsIds.d.ts +2 -1
  39. package/dist/components/common/useDataSourceEntityCollectionTableController.d.ts +3 -0
  40. package/dist/components/index.d.ts +4 -2
  41. package/dist/{components/FireCMSAppBar.d.ts → core/DefaultAppBar.d.ts} +6 -9
  42. package/dist/core/DefaultDrawer.d.ts +19 -0
  43. package/dist/core/DrawerNavigationItem.d.ts +10 -0
  44. package/dist/core/EntityEditView.d.ts +18 -4
  45. package/dist/core/FireCMS.d.ts +1 -1
  46. package/dist/core/NavigationRoutes.d.ts +3 -3
  47. package/dist/core/index.d.ts +3 -4
  48. package/dist/form/PropertyFieldBinding.d.ts +1 -1
  49. package/dist/form/components/ErrorFocus.d.ts +1 -1
  50. package/dist/form/components/FieldHelperText.d.ts +3 -3
  51. package/dist/form/components/LabelWithIcon.d.ts +1 -1
  52. package/dist/form/components/LabelWithIconAndTooltip.d.ts +15 -0
  53. package/dist/form/components/StorageItemPreview.d.ts +4 -4
  54. package/dist/form/components/index.d.ts +1 -1
  55. package/dist/form/field_bindings/ArrayCustomShapedFieldBinding.d.ts +1 -1
  56. package/dist/form/field_bindings/ArrayOfReferencesFieldBinding.d.ts +1 -1
  57. package/dist/form/field_bindings/BlockFieldBinding.d.ts +1 -1
  58. package/dist/form/field_bindings/KeyValueFieldBinding.d.ts +1 -1
  59. package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
  60. package/dist/form/field_bindings/MarkdownEditorFieldBinding.d.ts +11 -0
  61. package/dist/form/field_bindings/{MultiSelectBinding.d.ts → MultiSelectFieldBinding.d.ts} +1 -1
  62. package/dist/form/field_bindings/ReadOnlyFieldBinding.d.ts +1 -1
  63. package/dist/form/field_bindings/ReferenceFieldBinding.d.ts +2 -2
  64. package/dist/form/field_bindings/RepeatFieldBinding.d.ts +1 -1
  65. package/dist/form/field_bindings/SelectFieldBinding.d.ts +1 -1
  66. package/dist/form/field_bindings/StorageUploadFieldBinding.d.ts +3 -5
  67. package/dist/form/field_bindings/TextFieldBinding.d.ts +1 -1
  68. package/dist/form/index.d.ts +3 -5
  69. package/dist/form/useClearRestoreValue.d.ts +2 -2
  70. package/dist/hooks/data/save.d.ts +1 -2
  71. package/dist/hooks/index.d.ts +1 -0
  72. package/dist/hooks/useBuildNavigationController.d.ts +1 -2
  73. package/dist/hooks/useProjectLog.d.ts +8 -2
  74. package/dist/hooks/useValidateAuthenticator.d.ts +4 -8
  75. package/dist/index.d.ts +1 -0
  76. package/dist/index.es.js +16760 -13321
  77. package/dist/index.es.js.map +1 -1
  78. package/dist/index.umd.js +20120 -587
  79. package/dist/index.umd.js.map +1 -1
  80. package/dist/internal/useBuildDataSource.d.ts +1 -16
  81. package/dist/preview/PropertyPreviewProps.d.ts +6 -1
  82. package/dist/preview/components/EnumValuesChip.d.ts +1 -1
  83. package/dist/preview/components/ReferencePreview.d.ts +3 -2
  84. package/dist/preview/components/StorageThumbnail.d.ts +2 -1
  85. package/dist/preview/components/UrlComponentPreview.d.ts +2 -1
  86. package/dist/types/auth.d.ts +3 -3
  87. package/dist/types/collections.d.ts +41 -6
  88. package/dist/types/datasource.d.ts +55 -35
  89. package/dist/types/entities.d.ts +6 -1
  90. package/dist/types/entity_actions.d.ts +14 -0
  91. package/dist/types/entity_overrides.d.ts +2 -2
  92. package/dist/types/fields.d.ts +63 -41
  93. package/dist/types/firecms.d.ts +4 -0
  94. package/dist/types/index.d.ts +0 -1
  95. package/dist/types/navigation.d.ts +6 -5
  96. package/dist/types/plugins.d.ts +14 -4
  97. package/dist/types/properties.d.ts +34 -21
  98. package/dist/types/property_config.d.ts +0 -2
  99. package/dist/types/side_dialogs_controller.d.ts +10 -0
  100. package/dist/types/storage.d.ts +86 -3
  101. package/dist/util/entities.d.ts +2 -2
  102. package/dist/util/icon_list.d.ts +5 -1
  103. package/dist/util/icon_synonyms.d.ts +1 -97
  104. package/dist/util/icons.d.ts +3 -2
  105. package/dist/util/index.d.ts +1 -0
  106. package/dist/util/navigation_utils.d.ts +2 -2
  107. package/dist/util/objects.d.ts +2 -1
  108. package/dist/util/plurals.d.ts +0 -2
  109. package/dist/util/property_utils.d.ts +3 -3
  110. package/dist/util/resolutions.d.ts +30 -16
  111. package/dist/util/storage.d.ts +23 -2
  112. package/dist/util/useStorageUploadController.d.ts +3 -3
  113. package/package.json +128 -119
  114. package/src/app/AppBar.tsx +18 -0
  115. package/src/app/Drawer.tsx +24 -0
  116. package/src/app/Scaffold.tsx +243 -0
  117. package/src/app/index.ts +4 -0
  118. package/src/app/useApp.tsx +32 -0
  119. package/src/components/ArrayContainer.tsx +51 -24
  120. package/src/components/CircularProgressCenter.tsx +1 -1
  121. package/src/components/ClearFilterSortButton.tsx +41 -0
  122. package/src/components/{DeleteConfirmationDialog.tsx → ConfirmationDialog.tsx} +1 -1
  123. package/src/components/DeleteEntityDialog.tsx +1 -1
  124. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +12 -19
  125. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +21 -20
  126. package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +10 -6
  127. package/src/components/EntityCollectionTable/PropertyTableCell.tsx +47 -39
  128. package/src/components/EntityCollectionTable/column_utils.tsx +3 -3
  129. package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +31 -16
  130. package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +14 -6
  131. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +29 -34
  132. package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +32 -30
  133. package/src/components/EntityCollectionTable/internal/EntityTableCellActions.tsx +19 -7
  134. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +72 -67
  135. package/src/components/EntityCollectionView/EntityCollectionView.tsx +138 -86
  136. package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +68 -0
  137. package/src/components/EntityCollectionView/useSelectionController.tsx +19 -7
  138. package/src/components/EntityCollectionView/utils.ts +19 -0
  139. package/src/components/EntityPreview.tsx +43 -39
  140. package/src/components/EntityView.tsx +6 -6
  141. package/src/components/ErrorView.tsx +1 -1
  142. package/src/components/HomePage/DefaultHomePage.tsx +25 -19
  143. package/src/components/HomePage/NavigationCard.tsx +3 -3
  144. package/src/components/HomePage/NavigationCardBinding.tsx +1 -1
  145. package/src/components/HomePage/NavigationGroup.tsx +1 -1
  146. package/src/components/HomePage/SmallNavigationCard.tsx +5 -6
  147. package/src/components/PropertyConfigBadge.tsx +9 -3
  148. package/src/components/PropertyIdCopyTooltip.tsx +48 -0
  149. package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +8 -7
  150. package/src/components/ReferenceWidget.tsx +22 -12
  151. package/src/components/SearchIconsView.tsx +10 -7
  152. package/src/components/SelectableTable/SelectableTable.tsx +7 -7
  153. package/src/components/SelectableTable/filters/BooleanFilterField.tsx +2 -3
  154. package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +22 -7
  155. package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +28 -6
  156. package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +88 -21
  157. package/src/components/VirtualTable/VirtualTable.tsx +77 -46
  158. package/src/components/VirtualTable/VirtualTableCell.tsx +1 -9
  159. package/src/components/VirtualTable/VirtualTableHeader.tsx +4 -4
  160. package/src/components/VirtualTable/VirtualTableHeaderRow.tsx +2 -2
  161. package/src/components/VirtualTable/VirtualTableProps.tsx +18 -14
  162. package/src/components/VirtualTable/VirtualTableRow.tsx +4 -5
  163. package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +4 -4
  164. package/src/components/VirtualTable/fields/VirtualTableInput.tsx +2 -1
  165. package/src/components/VirtualTable/fields/VirtualTableNumberInput.tsx +2 -1
  166. package/src/components/VirtualTable/fields/VirtualTableSelect.tsx +14 -28
  167. package/src/components/VirtualTable/types.tsx +2 -3
  168. package/src/components/{EntityCollectionTable/internal → common}/default_entity_actions.tsx +8 -4
  169. package/src/components/common/index.ts +1 -0
  170. package/src/components/{VirtualTable/common.tsx → common/table_height.tsx} +5 -2
  171. package/src/components/common/types.tsx +4 -6
  172. package/src/components/common/useColumnsIds.tsx +23 -2
  173. package/src/components/common/useDataSourceEntityCollectionTableController.tsx +23 -12
  174. package/src/components/common/useTableSearchHelper.ts +53 -12
  175. package/src/components/index.tsx +4 -2
  176. package/src/contexts/DialogsProvider.tsx +2 -2
  177. package/src/core/DefaultAppBar.tsx +176 -0
  178. package/src/core/DefaultDrawer.tsx +183 -0
  179. package/src/core/DrawerNavigationItem.tsx +66 -0
  180. package/src/core/EntityEditView.tsx +716 -153
  181. package/src/core/EntitySidePanel.tsx +1 -2
  182. package/src/core/FireCMS.tsx +53 -52
  183. package/src/core/NavigationRoutes.tsx +7 -8
  184. package/src/core/SideDialogs.tsx +1 -0
  185. package/src/core/field_configs.tsx +7 -8
  186. package/src/core/index.tsx +3 -4
  187. package/src/form/PropertyFieldBinding.tsx +74 -35
  188. package/src/form/components/CustomIdField.tsx +4 -2
  189. package/src/form/components/FieldHelperText.tsx +4 -4
  190. package/src/form/components/LabelWithIcon.tsx +27 -19
  191. package/src/form/components/LabelWithIconAndTooltip.tsx +28 -0
  192. package/src/form/components/StorageItemPreview.tsx +21 -11
  193. package/src/form/components/StorageUploadProgress.tsx +3 -4
  194. package/src/form/components/index.tsx +1 -1
  195. package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +29 -17
  196. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +45 -35
  197. package/src/form/field_bindings/BlockFieldBinding.tsx +51 -32
  198. package/src/form/field_bindings/DateTimeFieldBinding.tsx +17 -14
  199. package/src/form/field_bindings/KeyValueFieldBinding.tsx +54 -45
  200. package/src/form/field_bindings/MapFieldBinding.tsx +65 -48
  201. package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +150 -0
  202. package/src/form/field_bindings/{MultiSelectBinding.tsx → MultiSelectFieldBinding.tsx} +25 -20
  203. package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +11 -16
  204. package/src/form/field_bindings/ReferenceFieldBinding.tsx +42 -31
  205. package/src/form/field_bindings/RepeatFieldBinding.tsx +52 -34
  206. package/src/form/field_bindings/SelectFieldBinding.tsx +20 -13
  207. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +36 -46
  208. package/src/form/field_bindings/SwitchFieldBinding.tsx +9 -5
  209. package/src/form/field_bindings/TextFieldBinding.tsx +26 -23
  210. package/src/form/index.tsx +4 -9
  211. package/src/form/useClearRestoreValue.tsx +2 -2
  212. package/src/form/validation.ts +1 -17
  213. package/src/hooks/data/delete.ts +2 -1
  214. package/src/hooks/data/save.ts +9 -5
  215. package/src/hooks/data/useDataSource.tsx +11 -3
  216. package/src/hooks/index.tsx +1 -0
  217. package/src/hooks/useBuildLocalConfigurationPersistence.tsx +8 -10
  218. package/src/hooks/useBuildModeController.tsx +11 -5
  219. package/src/hooks/useBuildNavigationController.tsx +91 -31
  220. package/src/hooks/useProjectLog.tsx +32 -10
  221. package/src/hooks/useResolvedNavigationFrom.tsx +1 -1
  222. package/src/hooks/useValidateAuthenticator.tsx +21 -41
  223. package/src/index.ts +1 -0
  224. package/src/internal/useBuildDataSource.ts +72 -82
  225. package/src/internal/useBuildSideDialogsController.tsx +1 -0
  226. package/src/internal/useBuildSideEntityController.tsx +102 -22
  227. package/src/internal/useUnsavedChangesDialog.tsx +3 -1
  228. package/src/preview/PropertyPreview.tsx +11 -18
  229. package/src/preview/PropertyPreviewProps.tsx +7 -1
  230. package/src/preview/components/BooleanPreview.tsx +2 -2
  231. package/src/preview/components/EnumValuesChip.tsx +2 -2
  232. package/src/preview/components/ImagePreview.tsx +25 -35
  233. package/src/preview/components/ReferencePreview.tsx +23 -34
  234. package/src/preview/components/StorageThumbnail.tsx +5 -1
  235. package/src/preview/components/UrlComponentPreview.tsx +44 -11
  236. package/src/preview/property_previews/ArrayOfMapsPreview.tsx +2 -3
  237. package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +4 -3
  238. package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +2 -3
  239. package/src/preview/property_previews/ArrayOfStringsPreview.tsx +1 -2
  240. package/src/preview/property_previews/ArrayOneOfPreview.tsx +4 -5
  241. package/src/preview/property_previews/ArrayPropertyPreview.tsx +4 -5
  242. package/src/preview/property_previews/MapPropertyPreview.tsx +6 -6
  243. package/src/preview/property_previews/SkeletonPropertyComponent.tsx +2 -2
  244. package/src/preview/property_previews/StringPropertyPreview.tsx +3 -3
  245. package/src/preview/util.ts +2 -2
  246. package/src/types/auth.tsx +3 -3
  247. package/src/types/collections.ts +50 -8
  248. package/src/types/customization_controller.tsx +0 -1
  249. package/src/types/datasource.ts +65 -43
  250. package/src/types/entities.ts +11 -1
  251. package/src/types/entity_actions.tsx +16 -3
  252. package/src/types/entity_overrides.tsx +2 -2
  253. package/src/types/fields.tsx +69 -45
  254. package/src/types/firecms.tsx +5 -0
  255. package/src/types/index.ts +0 -1
  256. package/src/types/navigation.ts +7 -7
  257. package/src/types/plugins.tsx +16 -6
  258. package/src/types/properties.ts +39 -22
  259. package/src/types/property_config.tsx +0 -2
  260. package/src/types/side_dialogs_controller.tsx +13 -0
  261. package/src/types/storage.ts +94 -3
  262. package/src/util/entities.ts +6 -5
  263. package/src/util/enums.ts +1 -1
  264. package/src/util/icon_list.ts +15 -10
  265. package/src/util/icon_synonyms.ts +3 -99
  266. package/src/util/icons.tsx +8 -2
  267. package/src/util/index.ts +1 -0
  268. package/src/util/make_properties_editable.ts +13 -5
  269. package/src/util/navigation_utils.ts +6 -6
  270. package/src/util/objects.ts +45 -28
  271. package/src/util/permissions.ts +1 -0
  272. package/src/util/plurals.ts +0 -2
  273. package/src/util/property_utils.tsx +11 -4
  274. package/src/util/references.ts +3 -0
  275. package/src/util/resolutions.ts +79 -46
  276. package/src/util/storage.ts +79 -21
  277. package/src/util/strings.ts +2 -2
  278. package/src/util/useStorageUploadController.tsx +33 -7
  279. package/src/util/useTraceUpdate.tsx +1 -0
  280. package/dist/components/PropertyIdCopyTooltipContent.d.ts +0 -3
  281. package/dist/components/VirtualTable/common.d.ts +0 -2
  282. package/dist/core/Drawer.d.ts +0 -23
  283. package/dist/core/Scaffold.d.ts +0 -55
  284. package/dist/core/SideEntityView.d.ts +0 -7
  285. package/dist/form/EntityForm.d.ts +0 -77
  286. package/dist/form/components/FormikArrayContainer.d.ts +0 -18
  287. package/dist/form/field_bindings/MarkdownFieldBinding.d.ts +0 -9
  288. package/dist/internal/useBuildCustomizationController.d.ts +0 -2
  289. package/dist/internal/useLocaleConfig.d.ts +0 -1
  290. package/dist/types/appcheck.d.ts +0 -26
  291. package/src/components/FireCMSAppBar.tsx +0 -165
  292. package/src/components/PropertyIdCopyTooltipContent.tsx +0 -28
  293. package/src/core/Drawer.tsx +0 -191
  294. package/src/core/Scaffold.tsx +0 -281
  295. package/src/core/SideEntityView.tsx +0 -38
  296. package/src/form/EntityForm.tsx +0 -728
  297. package/src/form/components/FormikArrayContainer.tsx +0 -44
  298. package/src/form/field_bindings/MarkdownFieldBinding.tsx +0 -695
  299. package/src/internal/useBuildCustomizationController.tsx +0 -5
  300. package/src/internal/useLocaleConfig.tsx +0 -18
  301. package/src/types/appcheck.ts +0 -29
@@ -5,6 +5,7 @@ import { getIconForProperty } from "../../util";
5
5
  import { FieldHelperText, LabelWithIcon } from "../components";
6
6
  import { BooleanSwitchWithLabel } from "@firecms/ui";
7
7
  import { useClearRestoreValue } from "../useClearRestoreValue";
8
+ import { PropertyIdCopyTooltip } from "../../components";
8
9
 
9
10
  type SwitchFieldProps = FieldProps<boolean>;
10
11
 
@@ -23,7 +24,7 @@ export const SwitchFieldBinding = React.forwardRef(function SwitchFieldBinding({
23
24
  showError,
24
25
  autoFocus,
25
26
  disabled,
26
- touched,
27
+ size = "medium",
27
28
  property,
28
29
  includeDescription
29
30
  }: SwitchFieldProps, ref) {
@@ -37,17 +38,20 @@ export const SwitchFieldBinding = React.forwardRef(function SwitchFieldBinding({
37
38
  return (
38
39
  <>
39
40
 
41
+ <PropertyIdCopyTooltip propertyKey={propertyKey}>
40
42
  <BooleanSwitchWithLabel
41
43
  value={value}
42
44
  onValueChange={(v) => setValue(v)}
43
45
  error={showError}
44
- label={<LabelWithIcon icon={getIconForProperty(property, "small")}
45
- required={property.validation?.required}
46
- title={property.name}/>}
46
+ label={<LabelWithIcon
47
+ icon={getIconForProperty(property, "small")}
48
+ required={property.validation?.required}
49
+ title={property.name}/>}
47
50
  disabled={disabled}
48
51
  autoFocus={autoFocus}
49
- size={"medium"}
52
+ size={size}
50
53
  />
54
+ </PropertyIdCopyTooltip>
51
55
 
52
56
  <FieldHelperText includeDescription={includeDescription}
53
57
  showError={showError}
@@ -6,6 +6,7 @@ import { FieldHelperText, LabelWithIcon } from "../components";
6
6
  import { getIconForProperty } from "../../util";
7
7
  import { PropertyPreview } from "../../preview";
8
8
  import { useClearRestoreValue } from "../useClearRestoreValue";
9
+ import { PropertyIdCopyTooltip } from "../../components/PropertyIdCopyTooltip";
9
10
 
10
11
  interface TextFieldBindingProps<T extends string | number> extends FieldProps<T> {
11
12
  allowInfinity?: boolean
@@ -18,7 +19,6 @@ interface TextFieldBindingProps<T extends string | number> extends FieldProps<T>
18
19
  * @group Form fields
19
20
  */
20
21
  export function TextFieldBinding<T extends string | number>({
21
- context,
22
22
  propertyKey,
23
23
  value,
24
24
  setValue,
@@ -28,6 +28,7 @@ export function TextFieldBinding<T extends string | number>({
28
28
  autoFocus,
29
29
  property,
30
30
  includeDescription,
31
+ size = "medium"
31
32
  }: TextFieldBindingProps<T>) {
32
33
 
33
34
  let multiline: boolean | undefined;
@@ -67,27 +68,29 @@ export function TextFieldBinding<T extends string | number>({
67
68
  const isMultiline = Boolean(multiline);
68
69
 
69
70
  const inputType = property.dataType === "number" ? "number" : undefined;
70
- return (
71
- <>
72
- <TextField
73
- value={value}
74
- onChange={onChange}
75
- autoFocus={autoFocus}
76
- label={<LabelWithIcon icon={getIconForProperty(property, "small")}
77
- required={property.validation?.required}
78
- title={property.name}/>}
79
- type={inputType}
80
- multiline={isMultiline}
81
- disabled={disabled}
82
- endAdornment={
83
- property.clearable && <IconButton
84
- onClick={handleClearClick}>
85
- <ClearIcon/>
86
- </IconButton>
87
- }
88
- error={showError ? error : undefined}
89
- inputClassName={error ? "text-red-500 dark:text-red-600" : ""}/>
90
-
71
+ return (<>
72
+ <PropertyIdCopyTooltip propertyKey={propertyKey}>
73
+ <TextField
74
+ size={size}
75
+ value={value}
76
+ onChange={onChange}
77
+ autoFocus={autoFocus}
78
+ label={<LabelWithIcon
79
+ icon={getIconForProperty(property, "small")}
80
+ required={property.validation?.required}
81
+ title={property.name}/>}
82
+ type={inputType}
83
+ multiline={isMultiline}
84
+ disabled={disabled}
85
+ endAdornment={
86
+ property.clearable && <IconButton
87
+ onClick={handleClearClick}>
88
+ <ClearIcon/>
89
+ </IconButton>
90
+ }
91
+ error={showError ? error : undefined}
92
+ inputClassName={error ? "text-red-500 dark:text-red-600" : ""}/>
93
+ </PropertyIdCopyTooltip>
91
94
  <FieldHelperText includeDescription={includeDescription}
92
95
  showError={showError}
93
96
  error={error}
@@ -100,7 +103,7 @@ export function TextFieldBinding<T extends string | number>({
100
103
  <PropertyPreview
101
104
  value={value}
102
105
  property={property}
103
- size={"medium"}/>
106
+ size={size}/>
104
107
  </Collapse>}
105
108
 
106
109
  </>
@@ -1,5 +1,5 @@
1
1
  import { SelectFieldBinding } from "./field_bindings/SelectFieldBinding";
2
- import { MultiSelectBinding } from "./field_bindings/MultiSelectBinding";
2
+ import { MultiSelectFieldBinding } from "./field_bindings/MultiSelectFieldBinding";
3
3
  import { ArrayOfReferencesFieldBinding } from "./field_bindings/ArrayOfReferencesFieldBinding";
4
4
  import { StorageUploadFieldBinding } from "./field_bindings/StorageUploadFieldBinding";
5
5
  import { TextFieldBinding } from "./field_bindings/TextFieldBinding";
@@ -11,13 +11,13 @@ import { KeyValueFieldBinding } from "./field_bindings/KeyValueFieldBinding";
11
11
  import { RepeatFieldBinding } from "./field_bindings/RepeatFieldBinding";
12
12
  import { BlockFieldBinding } from "./field_bindings/BlockFieldBinding";
13
13
  import { ReadOnlyFieldBinding } from "./field_bindings/ReadOnlyFieldBinding";
14
- import { MarkdownFieldBinding } from "./field_bindings/MarkdownFieldBinding";
14
+ import { MarkdownEditorFieldBinding } from "./field_bindings/MarkdownEditorFieldBinding";
15
15
  import { ArrayCustomShapedFieldBinding } from "./field_bindings/ArrayCustomShapedFieldBinding";
16
16
 
17
17
  export {
18
18
  ArrayCustomShapedFieldBinding,
19
19
  RepeatFieldBinding,
20
- MultiSelectBinding,
20
+ MultiSelectFieldBinding,
21
21
  ArrayOfReferencesFieldBinding,
22
22
  BlockFieldBinding,
23
23
  DateTimeFieldBinding,
@@ -28,16 +28,11 @@ export {
28
28
  SelectFieldBinding,
29
29
  StorageUploadFieldBinding,
30
30
  SwitchFieldBinding,
31
- MarkdownFieldBinding,
31
+ MarkdownEditorFieldBinding,
32
32
  TextFieldBinding
33
33
  };
34
34
 
35
35
  export * from "./components";
36
36
 
37
- export type { EntityFormProps } from "./EntityForm";
38
- export {
39
- EntityForm
40
- } from "./EntityForm";
41
-
42
37
  export { PropertyFieldBinding } from "./PropertyFieldBinding";
43
38
  export * from "./useClearRestoreValue";
@@ -1,5 +1,5 @@
1
1
  import { useEffect, useRef } from "react";
2
- import { CMSType, ResolvedProperty } from "../types";
2
+ import { CMSType, Property, ResolvedProperty } from "../types";
3
3
 
4
4
  /**
5
5
  * Hook we use to restore a value after it has been cleared
@@ -14,7 +14,7 @@ export function useClearRestoreValue<T extends CMSType>({
14
14
  setValue
15
15
  }:
16
16
  {
17
- property: ResolvedProperty<T>,
17
+ property: Property<T> | ResolvedProperty<T>,
18
18
  value: T,
19
19
  setValue: (value: T | null, shouldValidate?: boolean) => void
20
20
  }) {
@@ -112,23 +112,7 @@ export function getYupMapObjectSchema({
112
112
  if (validation?.required) {
113
113
  return shape.required(validation?.requiredMessage ? validation.requiredMessage : "Required").nullable(true);
114
114
  }
115
- return shape.nullable(true);
116
- // const object: ObjectSchema<any> = yup.object().shape(objectSchema);
117
- // return validation?.required
118
- // ? object.required(validation?.requiredMessage ? validation.requiredMessage : "Required").nullable(true)
119
- // : yup.object().optional().default(undefined).notRequired().nullable(true).test(
120
- // "empty-check",
121
- // "Optional map can be empty",
122
- // (o: any, testContext: any) => {
123
- // try {
124
- // if (!o || Object.keys(o).length === 0) return true;
125
- // return object.validateSync(o);
126
- // } catch (e) {
127
- // testContext.createError(e);
128
- // console.error(e);
129
- // return false;
130
- // }
131
- // });
115
+ return yup.object().shape(shape.fields).default(undefined).notRequired().nullable(true);
132
116
  }
133
117
 
134
118
  function getYupStringSchema({
@@ -81,7 +81,8 @@ export async function deleteEntityWithCallbacks<M extends Record<string, any>, U
81
81
  }
82
82
  }
83
83
  return dataSource.deleteEntity({
84
- entity
84
+ entity,
85
+ collection
85
86
  }).then(() => {
86
87
  onDeleteSuccess && onDeleteSuccess(entity);
87
88
  try {
@@ -1,7 +1,6 @@
1
1
  import {
2
2
  DataSource,
3
3
  Entity,
4
- EntityCallbacks,
5
4
  EntityCollection,
6
5
  EntityValues,
7
6
  FireCMSContext,
@@ -17,7 +16,6 @@ import { resolveCollection } from "../../util";
17
16
  export type SaveEntityWithCallbacksProps<M extends Record<string, any>> =
18
17
  SaveEntityProps<M> &
19
18
  {
20
- callbacks?: EntityCallbacks<M>;
21
19
  onSaveSuccess?: (updatedEntity: Entity<M>) => void,
22
20
  onSaveFailure?: (e: Error) => void,
23
21
  onPreSaveHookError?: (e: Error) => void,
@@ -87,7 +85,7 @@ export async function saveEntityWithCallbacks<M extends Record<string, any>, Use
87
85
  path,
88
86
  values: previousValues as EntityValues<M>,
89
87
  entityId,
90
- fields: customizationController.propertyConfigs
88
+ propertyConfigs: customizationController.propertyConfigs
91
89
  });
92
90
  updatedValues = await callbacks.onPreSave({
93
91
  collection: resolvedCollection,
@@ -109,6 +107,11 @@ export async function saveEntityWithCallbacks<M extends Record<string, any>, Use
109
107
  updatedValues = values;
110
108
  }
111
109
 
110
+ console.debug("Saving entity", {
111
+ entityId,
112
+ updatedValues,
113
+ collection
114
+ });
112
115
  return dataSource.saveEntity({
113
116
  collection,
114
117
  path: resolvedPath,
@@ -124,7 +127,7 @@ export async function saveEntityWithCallbacks<M extends Record<string, any>, Use
124
127
  path,
125
128
  values: updatedValues as EntityValues<M>,
126
129
  entityId,
127
- fields: customizationController.propertyConfigs
130
+ propertyConfigs: customizationController.propertyConfigs
128
131
  });
129
132
  callbacks.onSaveSuccess({
130
133
  collection: resolvedCollection,
@@ -145,6 +148,7 @@ export async function saveEntityWithCallbacks<M extends Record<string, any>, Use
145
148
  onSaveSuccess(entity);
146
149
  })
147
150
  .catch((e) => {
151
+ console.error("!!!", e);
148
152
  if (callbacks?.onSaveFailure) {
149
153
 
150
154
  const resolvedCollection = resolveCollection<M>({
@@ -152,7 +156,7 @@ export async function saveEntityWithCallbacks<M extends Record<string, any>, Use
152
156
  path,
153
157
  values: updatedValues as EntityValues<M>,
154
158
  entityId,
155
- fields: customizationController.propertyConfigs
159
+ propertyConfigs: customizationController.propertyConfigs
156
160
  });
157
161
  callbacks.onSaveFailure({
158
162
  collection: resolvedCollection,
@@ -1,4 +1,4 @@
1
- import { useContext, useMemo } from "react";
1
+ import { useContext } from "react";
2
2
  import { DataSource, EntityCollection } from "../../types";
3
3
  import { DataSourceContext } from "../../contexts/DataSourceContext";
4
4
 
@@ -7,8 +7,16 @@ import { DataSourceContext } from "../../contexts/DataSourceContext";
7
7
  * @group Hooks and utilities
8
8
  */
9
9
  export const useDataSource = (collection?: EntityCollection<any, any>): DataSource => {
10
+ // const customizationController = useCustomizationController();
11
+ // const navigationController = useNavigationController();
10
12
  const defaultDataSource = useContext(DataSourceContext);
11
- if (collection?.overrides?.dataSource)
12
- return collection?.overrides.dataSource;
13
+ // if (collection?.overrides?.dataSourceDelegate) {
14
+ // console.trace("Using custom data source for collection " + collection.id);
15
+ // return useBuildDataSource({
16
+ // delegate: collection.overrides.dataSourceDelegate,
17
+ // propertyConfigs: customizationController?.propertyConfigs,
18
+ // navigationController: navigationController
19
+ // });
20
+ // }
13
21
  return defaultDataSource;
14
22
  };
@@ -10,6 +10,7 @@ export * from "./useResolvedNavigationFrom";
10
10
 
11
11
  export * from "./useStorageSource";
12
12
  export * from "./useAuthController";
13
+ export * from "./useDialogsController";
13
14
  export * from "./useSideDialogsController";
14
15
  export * from "./useSideEntityController";
15
16
  export * from "./useFireCMSContext";
@@ -1,10 +1,10 @@
1
- import { useCallback, useEffect, useState } from "react";
1
+ import { useCallback, useEffect, useRef, useState } from "react";
2
2
  import { PartialEntityCollection, UserConfigurationPersistence } from "../types";
3
3
  import { mergeDeep, stripCollectionPath } from "../util";
4
4
 
5
5
  export function useBuildLocalConfigurationPersistence(): UserConfigurationPersistence {
6
6
 
7
- const [configCache, setConfigCache] = useState<Record<string, PartialEntityCollection>>({});
7
+ const configCache = useRef<Record<string, PartialEntityCollection>>({});
8
8
 
9
9
  const getCollectionFromStorage = useCallback((storageKey: string) => {
10
10
  const item = localStorage.getItem(storageKey);
@@ -13,20 +13,18 @@ export function useBuildLocalConfigurationPersistence(): UserConfigurationPersis
13
13
 
14
14
  const getCollectionConfig = useCallback(<M extends Record<string, any>>(path: string): PartialEntityCollection<M> => {
15
15
  const storageKey = `collection_config::${stripCollectionPath(path)}`;
16
- if (configCache[storageKey]) {
17
- return configCache[storageKey] as PartialEntityCollection<M>;
16
+ if (configCache.current[storageKey]) {
17
+ return configCache.current[storageKey] as PartialEntityCollection<M>;
18
18
  }
19
19
  return getCollectionFromStorage(storageKey);
20
- }, [configCache, getCollectionFromStorage]);
20
+ }, [getCollectionFromStorage]);
21
21
 
22
22
  const onCollectionModified = useCallback(<M extends Record<string, any>>(path: string, data: PartialEntityCollection<M>) => {
23
23
  const storageKey = `collection_config::${stripCollectionPath(path)}`;
24
24
  localStorage.setItem(storageKey, JSON.stringify(data));
25
- setConfigCache((currentCache) => {
26
- const cachedConfig = currentCache[storageKey];
27
- const newConfig = mergeDeep(cachedConfig ?? getCollectionFromStorage(path), data);
28
- return (mergeDeep(currentCache, newConfig));
29
- });
25
+ const cachedConfig = configCache.current[storageKey];
26
+ const newConfig = mergeDeep(cachedConfig ?? getCollectionFromStorage(path), data);
27
+ configCache.current[storageKey] = mergeDeep(configCache.current[storageKey], newConfig);
30
28
  }, [getCollectionFromStorage]);
31
29
 
32
30
  const [recentlyVisitedPaths, _setRecentlyVisitedPaths] = useState<string[]>([]);
@@ -8,8 +8,13 @@ import { ModeController } from "./index";
8
8
  */
9
9
  export function useBuildModeController(): ModeController {
10
10
 
11
- const prefersDarkModeQuery = typeof window !== "undefined" &&
12
- window.matchMedia("(prefers-color-scheme: dark)");
11
+ const prefersDarkModeQuery = useCallback((): boolean => {
12
+ if (typeof window === "undefined")
13
+ return false;
14
+ const mediaQueryList = window.matchMedia("(prefers-color-scheme: dark)");
15
+ return mediaQueryList.matches;
16
+ }, []);
17
+
13
18
  const prefersDarkModeStorage: boolean | null = localStorage.getItem("prefers-dark-mode") != null ? localStorage.getItem("prefers-dark-mode") === "true" : null;
14
19
  const prefersDarkMode = prefersDarkModeStorage ?? prefersDarkModeQuery;
15
20
  const [mode, setMode] = useState<"light" | "dark">(prefersDarkMode ? "dark" : "light");
@@ -23,7 +28,7 @@ export function useBuildModeController(): ModeController {
23
28
  const setDarkMode = useCallback(() => {
24
29
  setMode("dark");
25
30
  setDocumentMode("dark");
26
- }, [prefersDarkModeQuery]);
31
+ }, []);
27
32
 
28
33
  const setLightMode = useCallback(() => {
29
34
  setMode("light");
@@ -37,14 +42,15 @@ export function useBuildModeController(): ModeController {
37
42
 
38
43
  const toggleMode = useCallback(() => {
39
44
 
45
+ const prefersDarkModeQueryResult = prefersDarkModeQuery();
40
46
  if (mode === "light") {
41
- if (!prefersDarkModeQuery)
47
+ if (!prefersDarkModeQueryResult)
42
48
  localStorage.setItem("prefers-dark-mode", "true");
43
49
  else
44
50
  localStorage.removeItem("prefers-dark-mode");
45
51
  setDarkMode();
46
52
  } else {
47
- if (prefersDarkModeQuery)
53
+ if (prefersDarkModeQueryResult)
48
54
  localStorage.setItem("prefers-dark-mode", "false");
49
55
  else
50
56
  localStorage.removeItem("prefers-dark-mode");
@@ -20,6 +20,7 @@ import {
20
20
  applyPermissionsFunctionIfEmpty,
21
21
  getCollectionByPathOrId,
22
22
  mergeDeep,
23
+ removeFunctions,
23
24
  removeInitialAndTrailingSlashes,
24
25
  resolveCollectionPathIds,
25
26
  resolvePermissions
@@ -29,7 +30,7 @@ import { getParentReferencesFromPath } from "../util/parent_references_from_path
29
30
  const DEFAULT_BASE_PATH = "/";
30
31
  const DEFAULT_COLLECTION_PATH = "/c";
31
32
 
32
- type BuildNavigationContextProps<EC extends EntityCollection, UserType extends User> = {
33
+ export type BuildNavigationContextProps<EC extends EntityCollection, UserType extends User> = {
33
34
  basePath?: string,
34
35
  baseCollectionPath?: string,
35
36
  authController: AuthController<UserType>;
@@ -130,6 +131,30 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
130
131
  .filter(Boolean) as TopNavigationEntry[]
131
132
  ];
132
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
+
133
158
  if (viewsOrder) {
134
159
  navigationEntries = navigationEntries.sort((a, b) => {
135
160
  const aIndex = viewsOrder.indexOf(a.path);
@@ -163,32 +188,48 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
163
188
  if (authController.initialLoading)
164
189
  return;
165
190
 
191
+ console.debug("Refreshing navigation");
192
+
166
193
  try {
167
- console.debug("Refreshing navigation")
194
+
168
195
  const [resolvedCollections = [], resolvedViews, resolvedAdminViews = []] = await Promise.all([
169
196
  resolveCollections(collectionsProp, collectionPermissions, authController, dataSourceDelegate, injectCollections),
170
197
  resolveCMSViews(viewsProp, authController, dataSourceDelegate),
171
198
  resolveCMSViews(adminViewsProp, authController, dataSourceDelegate)
172
199
  ]
173
200
  );
174
- if (
175
- !equal(collectionsRef.current, resolvedCollections) ||
176
- !equal(viewsRef.current, resolvedViews) ||
177
- !equal(adminViewsRef.current, resolvedAdminViews) ||
178
- !equal(topLevelNavigation, computeTopNavigation(resolvedCollections, resolvedViews, resolvedAdminViews, viewsOrder))
179
- ) {
201
+
202
+ let shouldUpdateTopLevelNav = false;
203
+ if (!areCollectionListsEqual(collectionsRef.current ?? [], resolvedCollections)) {
204
+ collectionsRef.current = resolvedCollections;
205
+ shouldUpdateTopLevelNav = true;
206
+ }
207
+ if (collectionsRef.current === undefined) {
180
208
  collectionsRef.current = resolvedCollections;
209
+ shouldUpdateTopLevelNav = true;
210
+ }
211
+ if (!equal(viewsRef.current, resolvedViews)) {
181
212
  viewsRef.current = resolvedViews;
213
+ shouldUpdateTopLevelNav = true;
214
+ }
215
+ if (!equal(adminViewsRef.current, resolvedAdminViews)) {
182
216
  adminViewsRef.current = resolvedAdminViews;
183
- setTopLevelNavigation(computeTopNavigation(resolvedCollections ?? [], resolvedViews, resolvedAdminViews, viewsOrder));
217
+ shouldUpdateTopLevelNav = true;
218
+ }
219
+
220
+ const computedTopLevelNav = computeTopNavigation(resolvedCollections, resolvedViews, resolvedAdminViews, viewsOrder);
221
+ if (shouldUpdateTopLevelNav && !equal(topLevelNavigation, computedTopLevelNav)) {
222
+ setTopLevelNavigation(computedTopLevelNav);
184
223
  }
185
224
  } catch (e) {
186
225
  console.error(e);
187
226
  setNavigationLoadingError(e as any);
188
227
  }
189
228
 
190
- setNavigationLoading(false);
191
- setInitialised(true);
229
+ if (navigationLoading)
230
+ setNavigationLoading(false);
231
+ if (!initialised)
232
+ setInitialised(true);
192
233
 
193
234
  }, [
194
235
  collectionsProp,
@@ -205,9 +246,8 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
205
246
  refreshNavigation();
206
247
  }, [refreshNavigation]);
207
248
 
208
- const getCollection = useCallback(<EC extends EntityCollection>(
249
+ const getCollection = useCallback((
209
250
  idOrPath: string,
210
- entityId?: string,
211
251
  includeUserOverride = false
212
252
  ): EC | undefined => {
213
253
  const collections = collectionsRef.current;
@@ -217,8 +257,7 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
217
257
  const baseCollection = getCollectionByPathOrId(removeInitialAndTrailingSlashes(idOrPath), collections);
218
258
 
219
259
  const userOverride = includeUserOverride ? userConfigPersistence?.getCollectionConfig(idOrPath) : undefined;
220
-
221
- const overriddenCollection = baseCollection ? mergeDeep(baseCollection, userOverride) : undefined;
260
+ const overriddenCollection = baseCollection ? mergeDeep(baseCollection, userOverride ?? {}) : undefined;
222
261
 
223
262
  let result: Partial<EntityCollection> | undefined = overriddenCollection;
224
263
 
@@ -238,17 +277,14 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
238
277
 
239
278
  return { ...overriddenCollection, ...result } as EC;
240
279
 
241
- }, [
242
- basePath,
243
- baseCollectionPath,
244
- ]);
280
+ }, [userConfigPersistence]);
245
281
 
246
282
  const getCollectionFromPaths = useCallback(<EC extends EntityCollection>(pathSegments: string[]): EC | undefined => {
247
283
 
248
284
  const collections = collectionsRef.current;
285
+ if (collections === undefined)
286
+ throw Error("getCollectionFromPaths: Collections have not been initialised yet");
249
287
  let currentCollections: EntityCollection[] | undefined = [...(collections ?? [])];
250
- if (!currentCollections)
251
- throw Error("Collections have not been initialised yet");
252
288
 
253
289
  for (let i = 0; i < pathSegments.length; i++) {
254
290
  const pathSegment = pathSegments[i];
@@ -267,9 +303,9 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
267
303
  const getCollectionFromIds = useCallback(<EC extends EntityCollection>(ids: string[]): EC | undefined => {
268
304
 
269
305
  const collections = collectionsRef.current;
306
+ if (collections === undefined)
307
+ throw Error("getCollectionFromIds: Collections have not been initialised yet");
270
308
  let currentCollections: EntityCollection[] | undefined = [...(collections ?? [])];
271
- if (!currentCollections)
272
- throw Error("Collections have not been initialised yet");
273
309
 
274
310
  for (let i = 0; i < ids.length; i++) {
275
311
  const id = ids[i];
@@ -305,9 +341,7 @@ export function useBuildNavigationController<EC extends EntityCollection, UserTy
305
341
  []);
306
342
 
307
343
  const resolveAliasesFrom = useCallback((path: string): string => {
308
- const collections = collectionsRef.current;
309
- if (!collections)
310
- throw Error("Collections have not been initialised yet");
344
+ const collections = collectionsRef.current ?? [];
311
345
  return resolveCollectionPathIds(path, collections);
312
346
  }, []);
313
347
 
@@ -410,7 +444,7 @@ async function resolveCollections(collections: undefined | EntityCollection[] |
410
444
  collectionPermissions: PermissionsBuilder | undefined,
411
445
  authController: AuthController,
412
446
  dataSource: DataSourceDelegate,
413
- injectCollections?: (collections: EntityCollection[]) => EntityCollection[]) {
447
+ injectCollections?: (collections: EntityCollection[]) => EntityCollection[]): Promise<EntityCollection[]> {
414
448
  let resolvedCollections: EntityCollection[] = [];
415
449
  if (typeof collections === "function") {
416
450
  resolvedCollections = await collections({
@@ -422,14 +456,14 @@ async function resolveCollections(collections: undefined | EntityCollection[] |
422
456
  resolvedCollections = collections;
423
457
  }
424
458
 
425
- resolvedCollections = applyPermissionsFunctionIfEmpty(resolvedCollections, collectionPermissions);
426
-
427
- resolvedCollections = filterOutNotAllowedCollections(resolvedCollections, authController);
428
-
429
459
  if (injectCollections) {
430
460
  resolvedCollections = injectCollections(resolvedCollections ?? []);
431
461
  }
432
462
 
463
+ resolvedCollections = applyPermissionsFunctionIfEmpty(resolvedCollections, collectionPermissions);
464
+
465
+ resolvedCollections = filterOutNotAllowedCollections(resolvedCollections, authController);
466
+
433
467
  return resolvedCollections;
434
468
  }
435
469
 
@@ -454,3 +488,29 @@ function getGroup(collectionOrView: EntityCollection<any, any> | CMSView) {
454
488
  }
455
489
  return trimmed ?? "Views";
456
490
  }
491
+
492
+ function areCollectionListsEqual(a: EntityCollection[], b: EntityCollection[]) {
493
+ if (a.length !== b.length) {
494
+ return false;
495
+ }
496
+ const aCopy = [...a];
497
+ const bCopy = [...b];
498
+ const aSorted = aCopy.sort((x, y) => x.id.localeCompare(y.id));
499
+ const bSorted = bCopy.sort((x, y) => x.id.localeCompare(y.id));
500
+ return aSorted.every((value, index) => areCollectionsEqual(value, bSorted[index]));
501
+ }
502
+
503
+ function areCollectionsEqual(a: EntityCollection, b: EntityCollection) {
504
+ const {
505
+ subcollections: subcollectionsA,
506
+ ...restA
507
+ } = a;
508
+ const {
509
+ subcollections: subcollectionsB,
510
+ ...restB
511
+ } = b;
512
+ if (!areCollectionListsEqual(subcollectionsA ?? [], subcollectionsB ?? [])) {
513
+ return false;
514
+ }
515
+ return equal(removeFunctions(restA), removeFunctions(restB));
516
+ }