@firecms/core 3.0.0-canary.7 → 3.0.0-canary.71

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