@nkhang1902/strapi-plugin-export-import-clsx 1.1.15 → 1.1.16
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.
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
import { useState, useRef } from "react";
|
|
2
2
|
import {
|
|
3
|
-
ModalLayout,
|
|
4
|
-
ModalHeader,
|
|
5
|
-
ModalBody,
|
|
6
|
-
ModalFooter,
|
|
7
|
-
Typography,
|
|
8
|
-
Box,
|
|
9
3
|
Button,
|
|
10
4
|
} from "@strapi/design-system";
|
|
11
5
|
import { Download, Upload } from "@strapi/icons";
|
|
@@ -14,9 +8,6 @@ import { useNotification } from "@strapi/strapi/admin";
|
|
|
14
8
|
const ExportImportButtons = (props) => {
|
|
15
9
|
const [isExporting, setIsExporting] = useState(false);
|
|
16
10
|
const [isImporting, setIsImporting] = useState(false);
|
|
17
|
-
const [showErrorModal, setShowErrorModal] = useState(false);
|
|
18
|
-
const [importErrors, setImportErrors] = useState([]);
|
|
19
|
-
|
|
20
11
|
const { toggleNotification } = useNotification();
|
|
21
12
|
|
|
22
13
|
// Get current content type from props or URL
|
|
@@ -188,7 +179,7 @@ const ExportImportButtons = (props) => {
|
|
|
188
179
|
|
|
189
180
|
const eventFilter = getEventFilter();
|
|
190
181
|
try {
|
|
191
|
-
const response = await fetch(`/export-import-clsx/import?eventId=${eventFilter
|
|
182
|
+
const response = await fetch(`/export-import-clsx/import?eventId=${eventFilter?.eventId || ""}`, {
|
|
192
183
|
method: "POST",
|
|
193
184
|
body: formData,
|
|
194
185
|
});
|
|
@@ -199,10 +190,14 @@ const ExportImportButtons = (props) => {
|
|
|
199
190
|
const updated = result.summary?.updated || result.result.updated || 0;
|
|
200
191
|
|
|
201
192
|
const errorList = result.result?.errors || [];
|
|
193
|
+
const total = created + updated;
|
|
202
194
|
|
|
203
195
|
if (errorList.length > 0) {
|
|
204
|
-
|
|
205
|
-
|
|
196
|
+
showLongNotification(toggleNotification, {
|
|
197
|
+
title: "Import errors",
|
|
198
|
+
message: errorList.join("\n"),
|
|
199
|
+
type: "danger",
|
|
200
|
+
})
|
|
206
201
|
} else if (total > 0) {
|
|
207
202
|
toggleNotification({
|
|
208
203
|
type: "success",
|
|
@@ -238,7 +233,6 @@ const ExportImportButtons = (props) => {
|
|
|
238
233
|
const fileInputRef = useRef(null);
|
|
239
234
|
|
|
240
235
|
return (
|
|
241
|
-
<>
|
|
242
236
|
<div
|
|
243
237
|
style={{
|
|
244
238
|
display: "flex",
|
|
@@ -276,39 +270,6 @@ const ExportImportButtons = (props) => {
|
|
|
276
270
|
Import
|
|
277
271
|
</Button>
|
|
278
272
|
</div>
|
|
279
|
-
{showErrorModal && (
|
|
280
|
-
<ModalLayout
|
|
281
|
-
onClose={() => setShowErrorModal(false)}
|
|
282
|
-
labelledBy="import-errors-title"
|
|
283
|
-
>
|
|
284
|
-
<ModalHeader>
|
|
285
|
-
<Typography id="import-errors-title" fontWeight="bold">
|
|
286
|
-
Import Errors ({importErrors.length})
|
|
287
|
-
</Typography>
|
|
288
|
-
</ModalHeader>
|
|
289
|
-
|
|
290
|
-
<ModalBody>
|
|
291
|
-
<Box padding={4}>
|
|
292
|
-
{importErrors.map((err, index) => (
|
|
293
|
-
<Box key={index} paddingBottom={2}>
|
|
294
|
-
<Typography textColor="danger600">
|
|
295
|
-
{index + 1}. {err}
|
|
296
|
-
</Typography>
|
|
297
|
-
</Box>
|
|
298
|
-
))}
|
|
299
|
-
</Box>
|
|
300
|
-
</ModalBody>
|
|
301
|
-
|
|
302
|
-
<ModalFooter
|
|
303
|
-
endActions={
|
|
304
|
-
<Button onClick={() => setShowErrorModal(false)}>
|
|
305
|
-
Close
|
|
306
|
-
</Button>
|
|
307
|
-
}
|
|
308
|
-
/>
|
|
309
|
-
</ModalLayout>
|
|
310
|
-
)}
|
|
311
|
-
</>
|
|
312
273
|
);
|
|
313
274
|
};
|
|
314
275
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nkhang1902/strapi-plugin-export-import-clsx",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.16",
|
|
4
4
|
"description": "A powerful Strapi plugin for exporting and importing data with Excel support and advanced filtering",
|
|
5
5
|
"main": "./strapi-server.js",
|
|
6
6
|
"scripts": {
|
|
@@ -147,7 +147,7 @@ module.exports = ({ strapi }) => ({
|
|
|
147
147
|
.map(([fieldName, attr]) => toCamel(fieldName));
|
|
148
148
|
},
|
|
149
149
|
|
|
150
|
-
async handleRelations(entry, contentType,
|
|
150
|
+
async handleRelations(entry, contentType, row) {
|
|
151
151
|
const resolveRelationValue = async (field, value, target) => {
|
|
152
152
|
const targetAttr = strapi.contentTypes[target].attributes;
|
|
153
153
|
for (const field of SHORTCUT_FIELDS) {
|
|
@@ -156,7 +156,7 @@ module.exports = ({ strapi }) => ({
|
|
|
156
156
|
filters: { [field]: { $eq: value } },
|
|
157
157
|
});
|
|
158
158
|
if (existing) return { id: existing.id };
|
|
159
|
-
throw new Error(`
|
|
159
|
+
throw new Error(`Not found.`);
|
|
160
160
|
}
|
|
161
161
|
return null;
|
|
162
162
|
};
|
|
@@ -181,11 +181,7 @@ module.exports = ({ strapi }) => ({
|
|
|
181
181
|
if (relation === "manyToMany" || relation === "oneToMany") {
|
|
182
182
|
updatedEntry[field] = [];
|
|
183
183
|
} else {
|
|
184
|
-
|
|
185
|
-
updatedEntry[field] = { documentId: eventId };
|
|
186
|
-
} else {
|
|
187
|
-
updatedEntry[field] = null;
|
|
188
|
-
}
|
|
184
|
+
updatedEntry[field] = null;
|
|
189
185
|
}
|
|
190
186
|
continue;
|
|
191
187
|
}
|
|
@@ -215,7 +211,7 @@ module.exports = ({ strapi }) => ({
|
|
|
215
211
|
updatedEntry[field] = Array.isArray(value) ? processed : processed[0];
|
|
216
212
|
} catch (err) {
|
|
217
213
|
throw new Error(
|
|
218
|
-
`
|
|
214
|
+
`Error resolving field '${field}' with value '${JSON.stringify(value)}': ${err.message}`
|
|
219
215
|
);
|
|
220
216
|
}
|
|
221
217
|
}
|
|
@@ -342,10 +338,15 @@ module.exports = ({ strapi }) => ({
|
|
|
342
338
|
const f = parseFloat(value);
|
|
343
339
|
return Number.isNaN(f) ? 0 : f;
|
|
344
340
|
}
|
|
345
|
-
case 'date':
|
|
341
|
+
case 'date': {
|
|
342
|
+
const d = new Date(value);
|
|
343
|
+
if (isNaN(d.getTime())) return null;
|
|
344
|
+
return d.toISOString().slice(0, 10); // YYYY-MM-DD ONLY
|
|
345
|
+
}
|
|
346
346
|
case 'datetime': {
|
|
347
347
|
const d = new Date(value);
|
|
348
|
-
|
|
348
|
+
if (isNaN(d.getTime())) return null;
|
|
349
|
+
return d.toISOString(); // full ISO is valid here
|
|
349
350
|
}
|
|
350
351
|
default:
|
|
351
352
|
return value;
|
|
@@ -389,6 +390,9 @@ module.exports = ({ strapi }) => ({
|
|
|
389
390
|
|
|
390
391
|
async importEntries(entries, contentType, eventId) {
|
|
391
392
|
const results = { created: 0, updated: 0, errors: [] };
|
|
393
|
+
const event = eventId ? strapi.documents("api::event.event").findFirst({
|
|
394
|
+
filters: { documentId: eventId },
|
|
395
|
+
}) : null;
|
|
392
396
|
|
|
393
397
|
await strapi.db.transaction(async ({ trx, rollback, onRollback }) => {
|
|
394
398
|
onRollback(() => {
|
|
@@ -416,9 +420,10 @@ module.exports = ({ strapi }) => ({
|
|
|
416
420
|
throw new Error(`Document with id ${id} not found`);
|
|
417
421
|
}
|
|
418
422
|
}
|
|
423
|
+
data["event"] = event ? event.name : "";
|
|
419
424
|
|
|
420
425
|
// Handle relations & components
|
|
421
|
-
data = await this.handleRelations(data, contentType,
|
|
426
|
+
data = await this.handleRelations(data, contentType, row, eventName);
|
|
422
427
|
data = await this.handleComponents(data, existing, contentType);
|
|
423
428
|
const sanitizeErrors = [];
|
|
424
429
|
data = this.sanitizeEntryBeforeWrite(data, contentType, '', sanitizeErrors);
|
|
@@ -446,9 +451,7 @@ module.exports = ({ strapi }) => ({
|
|
|
446
451
|
}
|
|
447
452
|
} catch (err) {
|
|
448
453
|
results.errors.push(
|
|
449
|
-
`
|
|
450
|
-
i + 2
|
|
451
|
-
}: ${err.message}`
|
|
454
|
+
`Row ${i + 2}: ${err.message || err.toString()}`
|
|
452
455
|
);
|
|
453
456
|
results.created = 0;
|
|
454
457
|
results.updated = 0;
|