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

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 (201) hide show
  1. package/dist/app/Scaffold.d.ts +4 -0
  2. package/dist/components/ArrayContainer.d.ts +14 -3
  3. package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +2 -1
  4. package/dist/components/EntityCollectionTable/EntityCollectionTable.d.ts +2 -2
  5. package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +15 -1
  6. package/dist/components/EntityCollectionTable/index.d.ts +1 -1
  7. package/dist/components/EntityCollectionView/EntityCollectionView.d.ts +8 -0
  8. package/dist/components/EntityJsonPreview.d.ts +3 -0
  9. package/dist/components/PropertyIdCopyTooltip.d.ts +1 -1
  10. package/dist/components/SelectableTable/SelectableTable.d.ts +12 -2
  11. package/dist/components/SelectableTable/filters/ReferenceFilterField.d.ts +1 -1
  12. package/dist/components/UnsavedChangesDialog.d.ts +8 -0
  13. package/dist/components/VirtualTable/VirtualTableProps.d.ts +13 -0
  14. package/dist/components/common/default_entity_actions.d.ts +0 -2
  15. package/dist/components/common/index.d.ts +1 -1
  16. package/dist/components/common/useColumnsIds.d.ts +1 -0
  17. package/dist/components/common/{useDataSourceEntityCollectionTableController.d.ts → useDataSourceTableController.d.ts} +10 -2
  18. package/dist/components/common/useDebouncedCallback.d.ts +1 -0
  19. package/dist/components/common/useScrollRestoration.d.ts +14 -0
  20. package/dist/contexts/BreacrumbsContext.d.ts +8 -0
  21. package/dist/core/DefaultAppBar.d.ts +8 -2
  22. package/dist/core/EntityEditView.d.ts +36 -21
  23. package/dist/core/EntityEditViewFormActions.d.ts +2 -0
  24. package/dist/core/FireCMS.d.ts +2 -2
  25. package/dist/core/FireCMSRouter.d.ts +4 -0
  26. package/dist/core/NavigationRoutes.d.ts +0 -1
  27. package/dist/core/SideDialogs.d.ts +4 -2
  28. package/dist/core/index.d.ts +2 -1
  29. package/dist/form/EntityForm.d.ts +49 -0
  30. package/dist/form/EntityFormActions.d.ts +17 -0
  31. package/dist/form/PropertyFieldBinding.d.ts +1 -1
  32. package/dist/form/components/FormEntry.d.ts +6 -0
  33. package/dist/form/components/FormLayout.d.ts +5 -0
  34. package/dist/form/components/index.d.ts +2 -0
  35. package/dist/form/field_bindings/ArrayCustomShapedFieldBinding.d.ts +1 -1
  36. package/dist/form/field_bindings/ArrayOfReferencesFieldBinding.d.ts +1 -1
  37. package/dist/form/field_bindings/BlockFieldBinding.d.ts +1 -1
  38. package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
  39. package/dist/form/field_bindings/MarkdownEditorFieldBinding.d.ts +1 -1
  40. package/dist/form/field_bindings/RepeatFieldBinding.d.ts +1 -1
  41. package/dist/form/index.d.ts +16 -16
  42. package/dist/hooks/data/save.d.ts +1 -1
  43. package/dist/hooks/data/useEntityFetch.d.ts +2 -1
  44. package/dist/hooks/useBreadcrumbsController.d.ts +26 -0
  45. package/dist/hooks/useBuildNavigationController.d.ts +4 -1
  46. package/dist/hooks/useModeController.d.ts +1 -2
  47. package/dist/index.es.js +15842 -14396
  48. package/dist/index.es.js.map +1 -1
  49. package/dist/index.umd.js +15833 -14389
  50. package/dist/index.umd.js.map +1 -1
  51. package/dist/internal/useBuildDataSource.d.ts +3 -2
  52. package/dist/internal/useBuildSideEntityController.d.ts +3 -3
  53. package/dist/internal/useUnsavedChangesDialog.d.ts +7 -9
  54. package/dist/routes/CustomCMSRoute.d.ts +4 -0
  55. package/dist/routes/FireCMSRoute.d.ts +1 -0
  56. package/dist/routes/HomePageRoute.d.ts +3 -0
  57. package/dist/types/collections.d.ts +36 -10
  58. package/dist/types/datasource.d.ts +2 -2
  59. package/dist/types/dialogs_controller.d.ts +7 -3
  60. package/dist/types/entities.d.ts +1 -1
  61. package/dist/types/entity_actions.d.ts +10 -0
  62. package/dist/types/fields.d.ts +13 -3
  63. package/dist/types/firecms.d.ts +1 -1
  64. package/dist/types/navigation.d.ts +33 -12
  65. package/dist/types/plugins.d.ts +2 -0
  66. package/dist/types/properties.d.ts +40 -4
  67. package/dist/types/side_entity_controller.d.ts +6 -1
  68. package/dist/util/builders.d.ts +1 -1
  69. package/dist/util/createFormexStub.d.ts +2 -0
  70. package/dist/util/entity_actions.d.ts +2 -0
  71. package/dist/util/entity_cache.d.ts +23 -0
  72. package/dist/util/index.d.ts +1 -0
  73. package/dist/util/navigation_from_path.d.ts +6 -1
  74. package/dist/util/navigation_utils.d.ts +13 -1
  75. package/dist/util/objects.d.ts +1 -1
  76. package/dist/util/property_utils.d.ts +2 -2
  77. package/dist/util/references.d.ts +2 -2
  78. package/dist/util/resolutions.d.ts +12 -2
  79. package/package.json +20 -21
  80. package/src/app/Scaffold.tsx +13 -3
  81. package/src/components/ArrayContainer.tsx +60 -24
  82. package/src/components/CircularProgressCenter.tsx +1 -1
  83. package/src/components/DeleteEntityDialog.tsx +5 -3
  84. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +46 -23
  85. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +10 -4
  86. package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +18 -1
  87. package/src/components/EntityCollectionTable/index.tsx +1 -1
  88. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +3 -3
  89. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +10 -13
  90. package/src/components/EntityCollectionView/EntityCollectionView.tsx +105 -47
  91. package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +4 -2
  92. package/src/components/EntityJsonPreview.tsx +66 -0
  93. package/src/components/EntityPreview.tsx +10 -3
  94. package/src/components/EntityView.tsx +4 -1
  95. package/src/components/NotFoundPage.tsx +2 -2
  96. package/src/components/PropertyIdCopyTooltip.tsx +2 -3
  97. package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +14 -7
  98. package/src/components/SelectableTable/SelectableTable.tsx +18 -3
  99. package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +7 -7
  100. package/src/components/UnsavedChangesDialog.tsx +42 -0
  101. package/src/components/VirtualTable/VirtualTable.tsx +48 -3
  102. package/src/components/VirtualTable/VirtualTableProps.tsx +15 -0
  103. package/src/components/VirtualTable/fields/VirtualTableInput.tsx +1 -1
  104. package/src/components/common/default_entity_actions.tsx +37 -37
  105. package/src/components/common/index.ts +1 -1
  106. package/src/components/common/useColumnsIds.tsx +1 -1
  107. package/src/components/common/useDataSourceTableController.tsx +420 -0
  108. package/src/components/common/useDebouncedCallback.tsx +20 -0
  109. package/src/components/common/useScrollRestoration.tsx +68 -0
  110. package/src/contexts/BreacrumbsContext.tsx +38 -0
  111. package/src/contexts/DialogsProvider.tsx +3 -2
  112. package/src/contexts/ModeController.tsx +1 -3
  113. package/src/core/DefaultAppBar.tsx +59 -17
  114. package/src/core/DefaultDrawer.tsx +1 -1
  115. package/src/core/EntityEditView.tsx +354 -1000
  116. package/src/core/EntityEditViewFormActions.tsx +199 -0
  117. package/src/core/EntitySidePanel.tsx +85 -15
  118. package/src/core/FireCMS.tsx +20 -16
  119. package/src/core/FireCMSRouter.tsx +17 -0
  120. package/src/core/NavigationRoutes.tsx +23 -32
  121. package/src/core/SideDialogs.tsx +20 -11
  122. package/src/core/index.tsx +4 -2
  123. package/src/form/EntityForm.tsx +782 -0
  124. package/src/form/EntityFormActions.tsx +169 -0
  125. package/src/form/PropertyFieldBinding.tsx +21 -16
  126. package/src/form/components/FormEntry.tsx +22 -0
  127. package/src/form/components/FormLayout.tsx +16 -0
  128. package/src/form/components/LabelWithIcon.tsx +6 -3
  129. package/src/form/components/StorageUploadProgress.tsx +1 -1
  130. package/src/form/components/index.tsx +2 -0
  131. package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +8 -5
  132. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +5 -2
  133. package/src/form/field_bindings/BlockFieldBinding.tsx +5 -3
  134. package/src/form/field_bindings/DateTimeFieldBinding.tsx +1 -0
  135. package/src/form/field_bindings/KeyValueFieldBinding.tsx +1 -1
  136. package/src/form/field_bindings/MapFieldBinding.tsx +14 -16
  137. package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +15 -8
  138. package/src/form/field_bindings/MultiSelectFieldBinding.tsx +3 -3
  139. package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +2 -2
  140. package/src/form/field_bindings/ReferenceFieldBinding.tsx +1 -1
  141. package/src/form/field_bindings/RepeatFieldBinding.tsx +13 -4
  142. package/src/form/field_bindings/SelectFieldBinding.tsx +2 -2
  143. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +11 -6
  144. package/src/form/field_bindings/SwitchFieldBinding.tsx +1 -0
  145. package/src/form/field_bindings/TextFieldBinding.tsx +1 -0
  146. package/src/form/index.tsx +16 -32
  147. package/src/form/validation.ts +12 -6
  148. package/src/hooks/data/save.ts +25 -30
  149. package/src/hooks/data/useCollectionFetch.tsx +1 -1
  150. package/src/hooks/data/useEntityFetch.tsx +5 -1
  151. package/src/hooks/useBreadcrumbsController.tsx +31 -0
  152. package/src/hooks/useBuildModeController.tsx +15 -28
  153. package/src/hooks/useBuildNavigationController.tsx +81 -24
  154. package/src/hooks/useFireCMSContext.tsx +0 -30
  155. package/src/hooks/useLargeLayout.tsx +0 -35
  156. package/src/hooks/useModeController.tsx +1 -2
  157. package/src/hooks/useResolvedNavigationFrom.tsx +4 -6
  158. package/src/internal/useBuildDataSource.ts +9 -5
  159. package/src/internal/useBuildSideDialogsController.tsx +3 -2
  160. package/src/internal/useBuildSideEntityController.tsx +135 -88
  161. package/src/internal/useUnsavedChangesDialog.tsx +126 -92
  162. package/src/preview/PropertyPreview.tsx +12 -10
  163. package/src/preview/components/UrlComponentPreview.tsx +17 -18
  164. package/src/preview/property_previews/ArrayOfMapsPreview.tsx +4 -3
  165. package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +4 -3
  166. package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +4 -2
  167. package/src/preview/property_previews/ArrayOfStringsPreview.tsx +4 -3
  168. package/src/preview/property_previews/ArrayOneOfPreview.tsx +4 -2
  169. package/src/preview/property_previews/ArrayPropertyPreview.tsx +4 -2
  170. package/src/preview/property_previews/MapPropertyPreview.tsx +3 -2
  171. package/src/routes/CustomCMSRoute.tsx +21 -0
  172. package/src/routes/FireCMSRoute.tsx +246 -0
  173. package/src/routes/HomePageRoute.tsx +17 -0
  174. package/src/types/collections.ts +45 -13
  175. package/src/types/datasource.ts +2 -1
  176. package/src/types/dialogs_controller.tsx +7 -3
  177. package/src/types/entities.ts +1 -1
  178. package/src/types/entity_actions.tsx +12 -0
  179. package/src/types/fields.tsx +18 -3
  180. package/src/types/firecms.tsx +1 -1
  181. package/src/types/navigation.ts +41 -16
  182. package/src/types/plugins.tsx +2 -0
  183. package/src/types/properties.ts +48 -4
  184. package/src/types/side_dialogs_controller.tsx +2 -0
  185. package/src/types/side_entity_controller.tsx +11 -1
  186. package/src/util/builders.ts +5 -3
  187. package/src/util/createFormexStub.tsx +62 -0
  188. package/src/util/entity_actions.ts +28 -0
  189. package/src/util/entity_cache.ts +204 -0
  190. package/src/util/index.ts +1 -0
  191. package/src/util/join_collections.ts +6 -1
  192. package/src/util/navigation_from_path.ts +18 -7
  193. package/src/util/navigation_utils.ts +115 -14
  194. package/src/util/objects.ts +9 -2
  195. package/src/util/parent_references_from_path.ts +3 -3
  196. package/src/util/property_utils.tsx +7 -3
  197. package/src/util/references.ts +8 -6
  198. package/src/util/resolutions.ts +41 -12
  199. package/src/util/useStorageUploadController.tsx +60 -23
  200. package/src/components/common/useDataSourceEntityCollectionTableController.tsx +0 -236
  201. /package/src/util/{common.tsx → common.ts} +0 -0
@@ -1,6 +1,8 @@
1
1
  import {
2
2
  ArrayProperty,
3
+ AuthController,
3
4
  CMSType,
5
+ CustomizationController,
4
6
  EntityCollection,
5
7
  EntityCustomView,
6
8
  EntityValues,
@@ -26,9 +28,7 @@ import { getDefaultValuesFor, isPropertyBuilder } from "./entities";
26
28
  import { DEFAULT_ONE_OF_TYPE } from "./common";
27
29
  import { getIn } from "@firecms/formex";
28
30
  import { enumToObjectEntries } from "./enums";
29
- import { isDefaultFieldConfigId } from "../core/field_configs";
30
-
31
- // import util from "util";
31
+ import { isDefaultFieldConfigId } from "../core";
32
32
 
33
33
  export const resolveCollection = <M extends Record<string, any>, >
34
34
  ({
@@ -39,7 +39,8 @@ export const resolveCollection = <M extends Record<string, any>, >
39
39
  previousValues,
40
40
  userConfigPersistence,
41
41
  propertyConfigs,
42
- ignoreMissingFields = false
42
+ ignoreMissingFields = false,
43
+ authController
43
44
  }: {
44
45
  collection: EntityCollection<M> | ResolvedEntityCollection<M>;
45
46
  path: string,
@@ -49,6 +50,7 @@ export const resolveCollection = <M extends Record<string, any>, >
49
50
  userConfigPersistence?: UserConfigurationPersistence;
50
51
  propertyConfigs?: Record<string, PropertyConfig>;
51
52
  ignoreMissingFields?: boolean;
53
+ authController: AuthController;
52
54
  }): ResolvedEntityCollection<M> => {
53
55
 
54
56
  const collectionOverride = userConfigPersistence?.getCollectionConfig<M>(path);
@@ -68,7 +70,8 @@ export const resolveCollection = <M extends Record<string, any>, >
68
70
  path,
69
71
  entityId,
70
72
  propertyConfigs: propertyConfigs,
71
- ignoreMissingFields
73
+ ignoreMissingFields,
74
+ authController
72
75
  });
73
76
  if (!childResolvedProperty) return {};
74
77
  return ({
@@ -113,6 +116,7 @@ export function resolveProperty<T extends CMSType = CMSType, M extends Record<st
113
116
  fromBuilder?: boolean;
114
117
  propertyConfigs?: Record<string, PropertyConfig<any>>;
115
118
  ignoreMissingFields?: boolean;
119
+ authController: AuthController;
116
120
  }): ResolvedProperty<T> | null {
117
121
 
118
122
  if (typeof propertyOrBuilder === "object" && "resolved" in propertyOrBuilder) {
@@ -218,11 +222,11 @@ export function resolveProperty<T extends CMSType = CMSType, M extends Record<st
218
222
  }
219
223
 
220
224
  export function getArrayResolvedProperties<M>({
221
- propertyKey,
222
- propertyValue,
223
- property,
224
- ...props
225
- }: {
225
+ propertyKey,
226
+ propertyValue,
227
+ property,
228
+ ...props
229
+ }: {
226
230
  propertyValue: any,
227
231
  propertyKey?: string,
228
232
  property: ArrayProperty<any> | ResolvedArrayProperty<any>,
@@ -233,7 +237,8 @@ export function getArrayResolvedProperties<M>({
233
237
  entityId?: string;
234
238
  index?: number;
235
239
  fromBuilder?: boolean;
236
- propertyConfigs?: Record<string, PropertyConfig>
240
+ propertyConfigs?: Record<string, PropertyConfig>;
241
+ authController: AuthController;
237
242
  }) {
238
243
 
239
244
  const of = property.of;
@@ -265,6 +270,7 @@ export function resolveArrayProperty<T extends any[], M>({
265
270
  fromBuilder?: boolean;
266
271
  propertyConfigs?: Record<string, PropertyConfig>;
267
272
  ignoreMissingFields?: boolean;
273
+ authController: AuthController;
268
274
  }): ResolvedArrayProperty {
269
275
  const propertyValue = propertyKey ? getIn(props.values, propertyKey) : undefined;
270
276
 
@@ -280,7 +286,7 @@ export function resolveArrayProperty<T extends any[], M>({
280
286
  propertyOrBuilder: p as Property<any>,
281
287
  ignoreMissingFields,
282
288
  ...props,
283
- index
289
+ index,
284
290
  });
285
291
  })
286
292
  } as ResolvedArrayProperty;
@@ -372,6 +378,7 @@ export function resolveProperties<M extends Record<string, any>>({
372
378
  fromBuilder?: boolean;
373
379
  propertyConfigs?: Record<string, PropertyConfig>;
374
380
  ignoreMissingFields?: boolean;
381
+ authController: AuthController;
375
382
  }): ResolvedProperties<M> {
376
383
  return Object.entries<PropertyOrBuilder>(properties as Record<string, PropertyOrBuilder>)
377
384
  .map(([key, property]) => {
@@ -430,3 +437,25 @@ export function resolveEntityView(entityView: string | EntityCustomView<any>, co
430
437
  return entityView;
431
438
  }
432
439
  }
440
+
441
+ export function resolvedSelectedEntityView<M extends Record<string, any>>(
442
+ customViews: (string | EntityCustomView<M>)[] | undefined,
443
+ customizationController: CustomizationController,
444
+ selectedTab?: string,
445
+ canEdit?: boolean,
446
+ ) {
447
+ const resolvedEntityViews = customViews ? customViews
448
+ .map(e => resolveEntityView(e, customizationController.entityViews))
449
+ .filter((e): e is EntityCustomView<M> => Boolean(e))
450
+ // .filter((e) => canEdit || !e.includeActions)
451
+ : [];
452
+
453
+ const selectedEntityView = resolvedEntityViews.find(e => e.key === selectedTab);
454
+ const selectedSecondaryForm = customViews
455
+ && resolvedEntityViews.filter(e => e.includeActions).find(e => e.key === selectedTab);
456
+ return {
457
+ resolvedEntityViews,
458
+ selectedEntityView,
459
+ selectedSecondaryForm
460
+ };
461
+ }
@@ -18,6 +18,7 @@ import { PreviewSize } from "../preview";
18
18
  import { randomString } from "./strings";
19
19
  import { resolveStorageFilenameString, resolveStoragePathString } from "./storage";
20
20
  import { resolveProperty } from "./resolutions";
21
+ import { useAuthController } from "../hooks";
21
22
 
22
23
  /**
23
24
  * Internal representation of an item in the storage
@@ -45,18 +46,19 @@ export function useStorageUploadController<M extends object>({
45
46
  disabled,
46
47
  onChange
47
48
  }:
48
- {
49
- entityId: string,
50
- entityValues: EntityValues<M>,
51
- value: string | string[] | null;
52
- path?: string,
53
- propertyKey: string,
54
- property: StringProperty | ArrayProperty<string[]> | ResolvedStringProperty | ResolvedArrayProperty<string[]>,
55
- storageSource: StorageSource,
56
- disabled: boolean,
57
- onChange: (value: string | string[] | null) => void
58
- }) {
59
-
49
+ {
50
+ entityId: string,
51
+ entityValues: EntityValues<M>,
52
+ value: string | string[] | null;
53
+ path?: string,
54
+ propertyKey: string,
55
+ property: StringProperty | ArrayProperty<string[]> | ResolvedStringProperty | ResolvedArrayProperty<string[]>,
56
+ storageSource: StorageSource,
57
+ disabled: boolean,
58
+ onChange: (value: string | string[] | null) => void
59
+ }) {
60
+
61
+ const authController = useAuthController();
60
62
  const storage: StorageConfig | undefined = property.dataType === "string"
61
63
  ? property.storage
62
64
  : property.dataType === "array" &&
@@ -69,22 +71,15 @@ export function useStorageUploadController<M extends object>({
69
71
  if (!storage)
70
72
  throw Error("Storage meta must be specified");
71
73
 
74
+ const processFile = storage?.processFile;
75
+
72
76
  const metadata: Record<string, any> | undefined = storage?.metadata;
73
77
  const size = multipleFilesSupported ? "medium" : "large";
74
78
 
75
79
  const compression: ImageCompression | undefined = storage?.imageCompression;
76
80
 
77
81
  const internalInitialValue: StorageFieldItem[] =
78
- (multipleFilesSupported
79
- ? (value ?? []) as string[]
80
- : value ? [value as string] : []).map(entry => (
81
- {
82
- id: getRandomId(),
83
- storagePathOrDownloadUrl: entry,
84
- metadata,
85
- size
86
- }
87
- ));
82
+ getInternalInitialValue(multipleFilesSupported, value, metadata, size);
88
83
 
89
84
  const [initialValue, setInitialValue] = useState<string | string[] | null>(value);
90
85
  const [internalValue, setInternalValue] = useState<StorageFieldItem[]>(internalInitialValue);
@@ -98,7 +93,8 @@ export function useStorageUploadController<M extends object>({
98
93
 
99
94
  const resolvedProperty = resolveProperty({
100
95
  propertyOrBuilder: property as PropertyOrBuilder,
101
- values: entityValues
96
+ values: entityValues,
97
+ authController
102
98
  }) as ResolvedStringProperty | ResolvedArrayProperty<string[]>;
103
99
 
104
100
  const fileNameBuilder = useCallback(async (file: File) => {
@@ -178,7 +174,22 @@ export function useStorageUploadController<M extends object>({
178
174
  if (!acceptedFiles.length || disabled)
179
175
  return;
180
176
 
177
+ if (processFile) {
178
+ try {
179
+ acceptedFiles = await Promise.all(acceptedFiles.map(async file => {
180
+ const processedFile = await processFile(file);
181
+ if (!processedFile) {
182
+ return file;
183
+ }
184
+ return processedFile;
185
+ }));
186
+ } catch (e) {
187
+ console.error("Error processing file with custom code. Attempting to continue uploading.", e);
188
+ }
189
+ }
190
+
181
191
  let newInternalValue: StorageFieldItem[];
192
+
182
193
  if (multipleFilesSupported) {
183
194
  newInternalValue = [...internalValue,
184
195
  ...(await Promise.all(acceptedFiles.map(async file => {
@@ -226,6 +237,32 @@ export function useStorageUploadController<M extends object>({
226
237
  }
227
238
  }
228
239
 
240
+ function getInternalInitialValue(multipleFilesSupported: boolean,
241
+ value: string | string[] | null,
242
+ metadata: Record<string, any> | undefined,
243
+ size: PreviewSize): StorageFieldItem[] {
244
+ let strings: string[] = [];
245
+ if (multipleFilesSupported) {
246
+ if (Array.isArray(value) && value.every((v) => typeof v === "string")) {
247
+ strings = (value ?? []) as string[];
248
+ }
249
+ } else {
250
+ if (typeof value === "string") {
251
+ strings = value ? [value as string] : [];
252
+ }
253
+ }
254
+
255
+ return strings
256
+ .map(entry => (
257
+ {
258
+ id: getRandomId(),
259
+ storagePathOrDownloadUrl: entry,
260
+ metadata,
261
+ size
262
+ }
263
+ ));
264
+ }
265
+
229
266
  function removeDuplicates(items: StorageFieldItem[]) {
230
267
  return items.filter(
231
268
  (item, i) => {
@@ -1,236 +0,0 @@
1
- import React, { useCallback, useEffect, useMemo, useState } from "react";
2
-
3
- import { useDataSource, useFireCMSContext, useNavigationController } from "../../hooks";
4
- import { useDataOrder } from "../../hooks/data/useDataOrder";
5
- import {
6
- Entity,
7
- EntityCollection,
8
- EntityTableController,
9
- FilterValues,
10
- FireCMSContext,
11
- SelectedCellProps,
12
- User
13
- } from "../../types";
14
- import { useDebouncedData } from "./useDebouncedData";
15
- import equal from "react-fast-compare"
16
-
17
- const DEFAULT_PAGE_SIZE = 50;
18
-
19
- export type DataSourceEntityCollectionTableControllerProps<M extends Record<string, any> = any> = {
20
- /**
21
- * Full path where the data of this table is located
22
- */
23
- fullPath: string;
24
- /**
25
- * The collection that is represented by this config.
26
- */
27
- collection: EntityCollection<M>;
28
- /**
29
- * List of entities that will be displayed on top, no matter the ordering.
30
- * This is used for reference fields selection
31
- */
32
- entitiesDisplayedFirst?: Entity<M>[];
33
-
34
- lastDeleteTimestamp?: number;
35
-
36
- /**
37
- * Force filter to be applied to the table.
38
- */
39
- forceFilter?: FilterValues<string>;
40
- }
41
-
42
- /**
43
- * Use this hook to build a controller for the {@link EntityCollectionTable}.
44
- * This controller is bound to data in a path in your specified datasource.
45
- *
46
- * Note that you can build your own hook returning a {@link EntityTableController}
47
- * if you would like to display different data.
48
- *
49
- * @param fullPath
50
- * @param collection
51
- * @param entitiesDisplayedFirst
52
- * @param lastDeleteTimestamp
53
- * @param forceFilterFromProps
54
- */
55
- export function useDataSourceEntityCollectionTableController<M extends Record<string, any> = any, USER extends User = User>(
56
- {
57
- fullPath,
58
- collection,
59
- entitiesDisplayedFirst,
60
- lastDeleteTimestamp,
61
- forceFilter: forceFilterFromProps,
62
- }: DataSourceEntityCollectionTableControllerProps<M>)
63
- : EntityTableController<M> {
64
-
65
- const {
66
- initialFilter,
67
- initialSort,
68
- forceFilter: forceFilterFromCollection
69
- } = collection;
70
-
71
- const [popupCell, setPopupCell] = React.useState<SelectedCellProps<M> | undefined>(undefined);
72
- const navigation = useNavigationController();
73
- const dataSource = useDataSource(collection);
74
- const resolvedPath = useMemo(() => navigation.resolveAliasesFrom(fullPath), [fullPath, navigation.resolveAliasesFrom]);
75
-
76
- const forceFilter = forceFilterFromProps ?? forceFilterFromCollection;
77
- const paginationEnabled = collection.pagination === undefined || Boolean(collection.pagination);
78
- const pageSize = typeof collection.pagination === "number" ? collection.pagination : DEFAULT_PAGE_SIZE;
79
-
80
- const [searchString, setSearchString] = React.useState<string | undefined>();
81
- const [itemCount, setItemCount] = React.useState<number | undefined>(paginationEnabled ? pageSize : undefined);
82
-
83
- const checkFilterCombination = useCallback((filterValues: FilterValues<any>,
84
- sortBy?: [string, "asc" | "desc"]) => {
85
- if (!dataSource.isFilterCombinationValid)
86
- return true;
87
- return dataSource.isFilterCombinationValid({
88
- path: resolvedPath,
89
- collection,
90
- filterValues,
91
- sortBy
92
- })
93
- }, []);
94
-
95
- const initialSortInternal = useMemo(() => {
96
- if (initialSort && forceFilter && !checkFilterCombination(forceFilter, initialSort)) {
97
- console.warn("Initial sort is not compatible with the force filter. Ignoring initial sort");
98
- return undefined;
99
- }
100
- return initialSort;
101
- }, [initialSort, forceFilter]);
102
-
103
- useEffect(() => {
104
- if (!equal(forceFilter, filterValues)) {
105
- setFilterValues(forceFilter)
106
- }
107
- }, [forceFilter]);
108
-
109
- const [filterValues, setFilterValues] = React.useState<FilterValues<Extract<keyof M, string>> | undefined>(forceFilter ?? initialFilter ?? undefined);
110
- const [sortBy, setSortBy] = React.useState<[Extract<keyof M, string>, "asc" | "desc"] | undefined>(initialSortInternal);
111
-
112
- const sortByProperty = sortBy ? sortBy[0] : undefined;
113
- const currentSort = sortBy ? sortBy[1] : undefined;
114
-
115
- const context: FireCMSContext<USER> = useFireCMSContext();
116
-
117
- const [rawData, setRawData] = useState<Entity<M>[]>([]);
118
-
119
- const [dataLoading, setDataLoading] = useState<boolean>(false);
120
- const [dataLoadingError, setDataLoadingError] = useState<Error | undefined>();
121
- const [noMoreToLoad, setNoMoreToLoad] = useState<boolean>(false);
122
-
123
- const clearFilter = useCallback(() => setFilterValues(forceFilter ?? undefined), [forceFilter]);
124
-
125
- const updateFilterValues = useCallback((updatedFilter: FilterValues<Extract<keyof M, string>> | undefined) => {
126
- if (forceFilter) {
127
- console.warn("Filter is not compatible with the force filter. Ignoring filter");
128
- return;
129
- }
130
- if (updatedFilter && Object.keys(updatedFilter).length === 0) {
131
- setFilterValues(undefined);
132
- } else {
133
- setFilterValues(updatedFilter);
134
- }
135
- }, [forceFilter]);
136
-
137
- useEffect(() => {
138
-
139
- setDataLoading(true);
140
-
141
- const onEntitiesUpdate = async (entities: Entity<M>[]) => {
142
- if (collection.callbacks?.onFetch) {
143
- try {
144
- entities = await Promise.all(
145
- entities.map((entity) =>
146
- collection.callbacks!.onFetch!({
147
- collection,
148
- path: resolvedPath,
149
- entity,
150
- context
151
- })));
152
- } catch (e: any) {
153
- console.error(e);
154
- }
155
- }
156
- setDataLoading(false);
157
- setDataLoadingError(undefined);
158
- setRawData(entities.map(e => ({
159
- ...e,
160
- // values: sanitizeData(e.values, resolvedCollection.properties)
161
- })));
162
- setNoMoreToLoad(!itemCount || entities.length < itemCount);
163
- };
164
-
165
- const onError = (error: Error) => {
166
- console.error("ERROR", error);
167
- setDataLoading(false);
168
- setRawData([]);
169
- setDataLoadingError(error);
170
- };
171
-
172
- if (dataSource.listenCollection) {
173
- return dataSource.listenCollection<M>({
174
- path: resolvedPath,
175
- collection,
176
- onUpdate: onEntitiesUpdate,
177
- onError,
178
- searchString,
179
- filter: filterValues,
180
- limit: itemCount,
181
- startAfter: undefined,
182
- orderBy: sortByProperty,
183
- order: currentSort
184
- });
185
- } else {
186
- dataSource.fetchCollection<M>({
187
- path: resolvedPath,
188
- collection,
189
- searchString,
190
- filter: filterValues,
191
- limit: itemCount,
192
- startAfter: undefined,
193
- orderBy: sortByProperty,
194
- order: currentSort
195
- })
196
- .then(onEntitiesUpdate)
197
- .catch(onError);
198
- return () => {
199
- };
200
- }
201
- }, [resolvedPath, itemCount, currentSort, sortByProperty, filterValues, searchString]);
202
-
203
- const orderedData = useDataOrder({
204
- data: rawData,
205
- entitiesDisplayedFirst
206
- });
207
-
208
- // hack to fix Firestore listeners firing with incomplete data
209
- const data = useDebouncedData(orderedData, {
210
- filterValues,
211
- sortBy,
212
- searchString,
213
- lastDeleteTimestamp
214
- });
215
-
216
- return {
217
- data,
218
- dataLoading,
219
- noMoreToLoad,
220
- dataLoadingError,
221
- filterValues,
222
- setFilterValues: updateFilterValues,
223
- sortBy,
224
- setSortBy,
225
- searchString,
226
- setSearchString,
227
- clearFilter,
228
- itemCount,
229
- setItemCount,
230
- paginationEnabled,
231
- pageSize,
232
- checkFilterCombination,
233
- popupCell,
234
- setPopupCell
235
- }
236
- }
File without changes