@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.eventId}`, {
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
- setImportErrors(errorList);
205
- setShowErrorModal(true);
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.15",
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": {
@@ -15,6 +15,9 @@ module.exports = ({ strapi }) => ({
15
15
  .service("import-service");
16
16
 
17
17
  const { eventId } = ctx.request.query;
18
+ if (eventId == "") {
19
+ eventId = null;
20
+ }
18
21
 
19
22
  const result = await importService.importData(file, targetContentType, eventId);
20
23
 
@@ -147,7 +147,7 @@ module.exports = ({ strapi }) => ({
147
147
  .map(([fieldName, attr]) => toCamel(fieldName));
148
148
  },
149
149
 
150
- async handleRelations(entry, contentType, eventId) {
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(`Data with ${field} ${value} not found. Cannot map to ${contentType}`);
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
- if (field === 'event') {
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
- `Failed processing field ${field} with value ${JSON.stringify(value)}: ${err.message}`
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
- return isNaN(d.getTime()) ? null : d.toISOString();
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, eventId);
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
- `Failed ${existing ? "updating" : "creating"} on row ${
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;