@firecms/data_import_export 3.0.0-canary.80 → 3.0.0-canary.82

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 (50) hide show
  1. package/LICENSE +2 -1
  2. package/dist/index.d.ts +2 -5
  3. package/dist/index.es.js +12 -1364
  4. package/dist/index.es.js.map +1 -1
  5. package/dist/index.umd.js +29 -2
  6. package/dist/index.umd.js.map +1 -1
  7. package/dist/useImportExportPlugin.d.ts +5 -3
  8. package/package.json +5 -7
  9. package/src/index.ts +2 -5
  10. package/src/useImportExportPlugin.tsx +9 -5
  11. package/dist/components/DataNewPropertiesMapping.d.ts +0 -13
  12. package/dist/components/ImportFileUpload.d.ts +0 -3
  13. package/dist/components/ImportNewPropertyFieldPreview.d.ts +0 -10
  14. package/dist/components/ImportSaveInProgress.d.ts +0 -8
  15. package/dist/components/index.d.ts +0 -4
  16. package/dist/export_import/BasicExportAction.d.ts +0 -7
  17. package/dist/export_import/ExportCollectionAction.d.ts +0 -11
  18. package/dist/export_import/ImportCollectionAction.d.ts +0 -15
  19. package/dist/export_import/export.d.ts +0 -21
  20. package/dist/export_import/index.d.ts +0 -4
  21. package/dist/hooks/index.d.ts +0 -1
  22. package/dist/hooks/useImportConfig.d.ts +0 -2
  23. package/dist/types/column_mapping.d.ts +0 -20
  24. package/dist/types/index.d.ts +0 -1
  25. package/dist/utils/data.d.ts +0 -4
  26. package/dist/utils/file_headers.d.ts +0 -1
  27. package/dist/utils/file_to_json.d.ts +0 -16
  28. package/dist/utils/get_import_inference_type.d.ts +0 -2
  29. package/dist/utils/get_properties_mapping.d.ts +0 -0
  30. package/dist/utils/index.d.ts +0 -3
  31. package/src/components/DataNewPropertiesMapping.tsx +0 -241
  32. package/src/components/ImportFileUpload.tsx +0 -42
  33. package/src/components/ImportNewPropertyFieldPreview.tsx +0 -60
  34. package/src/components/ImportSaveInProgress.tsx +0 -122
  35. package/src/components/index.ts +0 -4
  36. package/src/export_import/BasicExportAction.tsx +0 -147
  37. package/src/export_import/ExportCollectionAction.tsx +0 -288
  38. package/src/export_import/ImportCollectionAction.tsx +0 -442
  39. package/src/export_import/export.ts +0 -234
  40. package/src/export_import/index.ts +0 -4
  41. package/src/hooks/index.ts +0 -1
  42. package/src/hooks/useImportConfig.tsx +0 -34
  43. package/src/types/column_mapping.ts +0 -32
  44. package/src/types/index.ts +0 -1
  45. package/src/utils/data.ts +0 -133
  46. package/src/utils/file_headers.ts +0 -90
  47. package/src/utils/file_to_json.ts +0 -106
  48. package/src/utils/get_import_inference_type.ts +0 -27
  49. package/src/utils/get_properties_mapping.ts +0 -63
  50. package/src/utils/index.ts +0 -3
@@ -1,288 +0,0 @@
1
- import React, { useCallback } from "react";
2
-
3
- import {
4
- CollectionActionsProps,
5
- Entity,
6
- EntityCollection,
7
- ExportConfig,
8
- getDefaultValuesFor,
9
- resolveCollection,
10
- ResolvedEntityCollection,
11
- useCustomizationController,
12
- useDataSource,
13
- useFireCMSContext,
14
- useNavigationController,
15
- User
16
- } from "@firecms/core";
17
- import {
18
- Alert,
19
- BooleanSwitchWithLabel,
20
- Button,
21
- CircularProgress,
22
- cls,
23
- Dialog,
24
- DialogActions,
25
- DialogContent,
26
- focusedMixin,
27
- GetAppIcon,
28
- IconButton,
29
- Tooltip,
30
- Typography
31
- } from "@firecms/ui";
32
- import { downloadEntitiesExport } from "./export";
33
-
34
- const DOCS_LIMIT = 500;
35
-
36
- export function ExportCollectionAction<M extends Record<string, any>, UserType extends User>({
37
- collection: inputCollection,
38
- path: inputPath,
39
- collectionEntitiesCount,
40
- onAnalyticsEvent,
41
- exportAllowed,
42
- notAllowedView
43
- }: CollectionActionsProps<M, UserType, EntityCollection<M, any>> & {
44
- exportAllowed?: (props: { collectionEntitiesCount: number, path: string, collection: EntityCollection }) => boolean;
45
- notAllowedView?: React.ReactNode;
46
- onAnalyticsEvent?: (event: string, params?: any) => void;
47
- }) {
48
-
49
- const customizationController = useCustomizationController();
50
-
51
- const exportConfig = typeof inputCollection.exportable === "object" ? inputCollection.exportable : undefined;
52
-
53
- const dateRef = React.useRef<Date>(new Date());
54
-
55
- const [includeUndefinedValues, setIncludeUndefinedValues] = React.useState<boolean>(false);
56
- const [flattenArrays, setFlattenArrays] = React.useState<boolean>(true);
57
- const [exportType, setExportType] = React.useState<"csv" | "json">("csv");
58
- const [dateExportType, setDateExportType] = React.useState<"timestamp" | "string">("string");
59
-
60
- const context = useFireCMSContext<UserType>();
61
- const dataSource = useDataSource();
62
- const navigationController = useNavigationController();
63
-
64
- const path = navigationController.resolveAliasesFrom(inputPath);
65
-
66
- const canExport = !exportAllowed || exportAllowed({
67
- collectionEntitiesCount,
68
- path,
69
- collection: inputCollection
70
- });
71
-
72
- const collection: ResolvedEntityCollection<M> = React.useMemo(() => resolveCollection({
73
- collection: inputCollection,
74
- path,
75
- fields: customizationController.propertyConfigs
76
- }), [inputCollection, path]);
77
-
78
- const [dataLoading, setDataLoading] = React.useState<boolean>(false);
79
- const [dataLoadingError, setDataLoadingError] = React.useState<Error | undefined>();
80
-
81
- const [open, setOpen] = React.useState(false);
82
-
83
- const handleClickOpen = useCallback(() => {
84
- setOpen(true);
85
- }, [setOpen]);
86
-
87
- const handleClose = useCallback(() => {
88
- setOpen(false);
89
- }, [setOpen]);
90
-
91
- const fetchAdditionalFields = useCallback(async (entities: Entity<M>[]) => {
92
-
93
- const additionalExportFields = exportConfig?.additionalFields;
94
- const additionalFields = collection.additionalFields;
95
-
96
- const resolvedExportColumnsValues: Record<string, any>[] = additionalExportFields
97
- ? await Promise.all(entities.map(async (entity) => {
98
- return (await Promise.all(additionalExportFields.map(async (column) => {
99
- return {
100
- [column.key]: await column.builder({
101
- entity,
102
- context
103
- })
104
- };
105
- }))).reduce((a, b) => ({ ...a, ...b }), {});
106
- }))
107
- : [];
108
-
109
- const resolvedColumnsValues: Record<string, any>[] = additionalFields
110
- ? await Promise.all(entities.map(async (entity) => {
111
- return (await Promise.all(additionalFields
112
- .map(async (field) => {
113
- if (!field.value)
114
- return {};
115
- return {
116
- [field.key]: await field.value({
117
- entity,
118
- context
119
- })
120
- };
121
- }))).reduce((a, b) => ({ ...a, ...b }), {});
122
- }))
123
- : [];
124
- return [...resolvedExportColumnsValues, ...resolvedColumnsValues];
125
- }, [exportConfig?.additionalFields]);
126
-
127
- const doDownload = useCallback(async (collection: ResolvedEntityCollection<M>,
128
- exportConfig: ExportConfig<any> | undefined) => {
129
-
130
- onAnalyticsEvent?.("export_collection", {
131
- collection: collection.path
132
- });
133
- setDataLoading(true);
134
- dataSource.fetchCollection<M>({
135
- path,
136
- collection
137
- })
138
- .then(async (data) => {
139
- setDataLoadingError(undefined);
140
- const additionalData = await fetchAdditionalFields(data);
141
- const additionalHeaders = [
142
- ...exportConfig?.additionalFields?.map(column => column.key) ?? [],
143
- ...collection.additionalFields?.map(field => field.key) ?? []
144
- ];
145
-
146
- const dataWithDefaults = includeUndefinedValues
147
- ? data.map(entity => {
148
- const defaultValues = getDefaultValuesFor(collection.properties);
149
- return {
150
- ...entity,
151
- values: { ...defaultValues, ...entity.values }
152
- };
153
- })
154
- : data;
155
- downloadEntitiesExport({
156
- data: dataWithDefaults,
157
- additionalData,
158
- properties: collection.properties,
159
- propertiesOrder: collection.propertiesOrder,
160
- name: collection.name,
161
- flattenArrays,
162
- additionalHeaders,
163
- exportType,
164
- dateExportType
165
- });
166
- onAnalyticsEvent?.("export_collection_success", {
167
- collection: collection.path
168
- });
169
- })
170
- .catch((e) => {
171
- console.error("Error loading export data", e);
172
- setDataLoadingError(e);
173
- })
174
- .finally(() => setDataLoading(false));
175
-
176
- }, [onAnalyticsEvent, dataSource, path, fetchAdditionalFields, includeUndefinedValues, flattenArrays, exportType, dateExportType]);
177
-
178
- const onOkClicked = useCallback(() => {
179
- doDownload(collection, exportConfig);
180
- handleClose();
181
- }, [doDownload, collection, exportConfig, handleClose]);
182
-
183
- return <>
184
-
185
- <Tooltip title={"Export"}>
186
- <IconButton color={"primary"} onClick={handleClickOpen}>
187
- <GetAppIcon/>
188
- </IconButton>
189
- </Tooltip>
190
-
191
- <Dialog
192
- open={open}
193
- onOpenChange={setOpen}
194
- maxWidth={"xl"}>
195
- <DialogContent className={"flex flex-col gap-4 my-4"}>
196
-
197
- <Typography variant={"h6"}>Export data</Typography>
198
-
199
- <div>Download the the content of this table as a CSV</div>
200
-
201
- {collectionEntitiesCount > DOCS_LIMIT &&
202
- <Alert color={"warning"}>
203
- <div>
204
- This collections has a large number
205
- of documents ({collectionEntitiesCount}).
206
- </div>
207
- </Alert>}
208
-
209
- <div className={"flex flex-row gap-4"}>
210
- <div className={"p-4 flex flex-col"}>
211
- <div className="flex items-center">
212
- <input id="radio-csv" type="radio" value="csv" name="exportType"
213
- checked={exportType === "csv"}
214
- onChange={() => setExportType("csv")}
215
- className={cls(focusedMixin, "w-4 text-primary-dark bg-gray-100 border-gray-300 dark:bg-gray-700 dark:border-gray-600")}/>
216
- <label htmlFor="radio-csv"
217
- className="p-2 text-sm font-medium text-gray-900 dark:text-slate-300">CSV</label>
218
- </div>
219
- <div className="flex items-center">
220
- <input id="radio-json" type="radio" value="json" name="exportType"
221
- checked={exportType === "json"}
222
- onChange={() => setExportType("json")}
223
- className={cls(focusedMixin, "w-4 text-primary-dark bg-gray-100 border-gray-300 dark:bg-gray-700 dark:border-gray-600")}/>
224
- <label htmlFor="radio-json"
225
- className="p-2 text-sm font-medium text-gray-900 dark:text-slate-300">JSON</label>
226
- </div>
227
- </div>
228
-
229
- <div className={"p-4 flex flex-col"}>
230
- <div className="flex items-center">
231
- <input id="radio-timestamp" type="radio" value="timestamp" name="dateExportType"
232
- checked={dateExportType === "timestamp"}
233
- onChange={() => setDateExportType("timestamp")}
234
- className={cls(focusedMixin, "w-4 text-primary-dark bg-gray-100 border-gray-300 dark:bg-gray-700 dark:border-gray-600")}/>
235
- <label htmlFor="radio-timestamp"
236
- className="p-2 text-sm font-medium text-gray-900 dark:text-slate-300">Dates as
237
- timestamps ({dateRef.current.getTime()})</label>
238
- </div>
239
- <div className="flex items-center">
240
- <input id="radio-string" type="radio" value="string" name="dateExportType"
241
- checked={dateExportType === "string"}
242
- onChange={() => setDateExportType("string")}
243
- className={cls(focusedMixin, "w-4 text-primary-dark bg-gray-100 border-gray-300 dark:bg-gray-700 dark:border-gray-600")}/>
244
- <label htmlFor="radio-string"
245
- className="p-2 text-sm font-medium text-gray-900 dark:text-slate-300">Dates as
246
- strings ({dateRef.current.toISOString()})</label>
247
- </div>
248
- </div>
249
- </div>
250
-
251
- <BooleanSwitchWithLabel
252
- size={"small"}
253
- disabled={exportType !== "csv"}
254
- value={flattenArrays}
255
- onValueChange={setFlattenArrays}
256
- label={"Flatten arrays"}/>
257
-
258
- <BooleanSwitchWithLabel
259
- size={"small"}
260
- value={includeUndefinedValues}
261
- onValueChange={setIncludeUndefinedValues}
262
- label={"Include undefined values"}/>
263
-
264
- {!canExport && notAllowedView}
265
-
266
- </DialogContent>
267
-
268
- <DialogActions>
269
-
270
- {dataLoading && <CircularProgress size={"small"}/>}
271
-
272
- <Button onClick={handleClose}
273
- variant={"text"}>
274
- Cancel
275
- </Button>
276
-
277
- <Button variant="filled"
278
- onClick={onOkClicked}
279
- disabled={dataLoading || !canExport}>
280
- Download
281
- </Button>
282
-
283
- </DialogActions>
284
-
285
- </Dialog>
286
-
287
- </>;
288
- }