@nocobase/plugin-action-import 2.0.0-alpha.9 → 2.0.0-beta.1
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.
- package/dist/client/index.js +1 -1
- package/dist/client/models/getOptionFields.d.ts +9 -0
- package/dist/externalVersion.js +10 -11
- package/dist/locale/de-DE.json +41 -39
- package/dist/locale/en-US.json +42 -31
- package/dist/locale/es-ES.json +43 -17
- package/dist/locale/fr-FR.json +53 -0
- package/dist/locale/hu-HU.json +53 -0
- package/dist/locale/id-ID.json +53 -0
- package/dist/locale/it-IT.json +40 -38
- package/dist/locale/ja-JP.json +42 -19
- package/dist/locale/ko-KR.json +47 -22
- package/dist/locale/nl-NL.json +51 -48
- package/dist/locale/pt-BR.json +44 -17
- package/dist/locale/ru-RU.json +54 -0
- package/dist/locale/tr-TR.json +53 -0
- package/dist/locale/uk-UA.json +53 -0
- package/dist/locale/vi-VN.json +53 -0
- package/dist/locale/zh-CN.json +41 -41
- package/dist/locale/zh-TW.json +53 -0
- package/dist/node_modules/exceljs/package.json +1 -1
- package/dist/node_modules/xlsx/package.json +1 -1
- package/dist/server/errors.d.ts +9 -1
- package/dist/server/errors.js +2 -3
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.js +15 -8
- package/dist/server/locale/zh-CN.json +3 -2
- package/dist/server/services/xlsx-importer.d.ts +2 -1
- package/dist/server/services/xlsx-importer.js +51 -18
- package/package.json +5 -2
- /package/dist/client/{ImportActionModel.d.ts → models/ImportActionModel.d.ts} +0 -0
|
@@ -66,6 +66,17 @@ class XlsxImporter extends import_events.default {
|
|
|
66
66
|
async beforePerformImport(data, options) {
|
|
67
67
|
return data;
|
|
68
68
|
}
|
|
69
|
+
async validateBySpaces(data, ctx) {
|
|
70
|
+
var _a;
|
|
71
|
+
if ((_a = ctx == null ? void 0 : ctx.space) == null ? void 0 : _a.can) {
|
|
72
|
+
await ctx.space.can({
|
|
73
|
+
data: (data == null ? void 0 : data.slice(1)) || [],
|
|
74
|
+
columns: this.options.columns.map((column) => column.dataIndex),
|
|
75
|
+
collection: this.options.collection.name,
|
|
76
|
+
ctx
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
69
80
|
async validate(ctx) {
|
|
70
81
|
const columns = this.getColumnsByPermission(ctx);
|
|
71
82
|
if (columns.length == 0) {
|
|
@@ -78,6 +89,7 @@ class XlsxImporter extends import_events.default {
|
|
|
78
89
|
}
|
|
79
90
|
}
|
|
80
91
|
const data = await this.getData(ctx);
|
|
92
|
+
await this.validateBySpaces(data, ctx);
|
|
81
93
|
return data;
|
|
82
94
|
}
|
|
83
95
|
async run(options = {}) {
|
|
@@ -187,12 +199,13 @@ class XlsxImporter extends import_events.default {
|
|
|
187
199
|
getModel() {
|
|
188
200
|
return this.repository instanceof import_database.RelationRepository ? this.repository.targetModel : this.repository.model;
|
|
189
201
|
}
|
|
190
|
-
async handleRowValuesWithColumns(row, rowValues, options) {
|
|
191
|
-
|
|
192
|
-
|
|
202
|
+
async handleRowValuesWithColumns(row, rowValues, options, columns) {
|
|
203
|
+
var _a;
|
|
204
|
+
for (let index = 0; index < columns.length; index++) {
|
|
205
|
+
const column = columns[index];
|
|
193
206
|
const field = this.options.collection.getField(column.dataIndex[0]);
|
|
194
207
|
if (!field) {
|
|
195
|
-
throw new import_errors.ImportValidationError("Import validation.Field not found", {
|
|
208
|
+
throw new import_errors.ImportValidationError("Import validation. Field not found", {
|
|
196
209
|
field: column.dataIndex[0]
|
|
197
210
|
});
|
|
198
211
|
}
|
|
@@ -215,7 +228,15 @@ class XlsxImporter extends import_events.default {
|
|
|
215
228
|
ctx.targetCollection = field.targetCollection();
|
|
216
229
|
ctx.filterKey = column.dataIndex[1];
|
|
217
230
|
}
|
|
218
|
-
|
|
231
|
+
try {
|
|
232
|
+
rowValues[dataKey] = str == null ? null : await interfaceInstance.toValue(this.trimString(str), ctx);
|
|
233
|
+
} catch (error) {
|
|
234
|
+
throw new import_errors.ImportValidationError("Failed to parse field {{field}} in row {{rowIndex}}: {{message}}", {
|
|
235
|
+
rowIndex: ((_a = options == null ? void 0 : options.context) == null ? void 0 : _a.handingRowIndex) || 1,
|
|
236
|
+
field: dataKey,
|
|
237
|
+
message: error.message
|
|
238
|
+
});
|
|
239
|
+
}
|
|
219
240
|
}
|
|
220
241
|
const model = this.getModel();
|
|
221
242
|
const guard = import_database.UpdateGuard.fromOptions(model, {
|
|
@@ -226,13 +247,14 @@ class XlsxImporter extends import_events.default {
|
|
|
226
247
|
rowValues = this.repository instanceof import_database.RelationRepository ? model.callSetters(guard.sanitize(rowValues || {}), options) : guard.sanitize(rowValues);
|
|
227
248
|
}
|
|
228
249
|
async handleChuckRows(chunkRows, runOptions, options) {
|
|
229
|
-
var _a, _b;
|
|
250
|
+
var _a, _b, _c;
|
|
230
251
|
let { handingRowIndex = 1 } = options;
|
|
231
252
|
const { transaction } = runOptions;
|
|
253
|
+
const columns = this.getColumnsByPermission(options == null ? void 0 : options.context);
|
|
232
254
|
const rows = [];
|
|
233
255
|
for (const row of chunkRows) {
|
|
234
256
|
const rowValues = {};
|
|
235
|
-
await this.handleRowValuesWithColumns(row, rowValues, runOptions);
|
|
257
|
+
await this.handleRowValuesWithColumns(row, rowValues, runOptions, columns);
|
|
236
258
|
rows.push({
|
|
237
259
|
...this.options.rowDefaultValues || {},
|
|
238
260
|
...rowValues
|
|
@@ -257,14 +279,18 @@ class XlsxImporter extends import_events.default {
|
|
|
257
279
|
)}`
|
|
258
280
|
);
|
|
259
281
|
}
|
|
260
|
-
(_b =
|
|
282
|
+
if ((_b = error.params) == null ? void 0 : _b.rowIndex) {
|
|
283
|
+
handingRowIndex += error.params.rowIndex;
|
|
284
|
+
error.params.rowIndex = handingRowIndex;
|
|
285
|
+
}
|
|
286
|
+
(_c = this.logger) == null ? void 0 : _c.error(`Import error at row ${handingRowIndex}: ${error.message}`, {
|
|
261
287
|
rowIndex: handingRowIndex,
|
|
262
288
|
rowData: rows[handingRowIndex],
|
|
263
289
|
originalError: error.stack || error.toString()
|
|
264
290
|
});
|
|
265
291
|
throw new import_errors.ImportError(`Import failed at row ${handingRowIndex}`, {
|
|
266
292
|
rowIndex: handingRowIndex,
|
|
267
|
-
rowData: rows[handingRowIndex],
|
|
293
|
+
rowData: rows[handingRowIndex - (this.options.explain ? 2 : 1)],
|
|
268
294
|
cause: error
|
|
269
295
|
});
|
|
270
296
|
}
|
|
@@ -288,15 +314,10 @@ class XlsxImporter extends import_events.default {
|
|
|
288
314
|
for (let i = 0; i < instances.length; i++) {
|
|
289
315
|
const instance = instances[i];
|
|
290
316
|
const value = values[i];
|
|
291
|
-
await this.loggerService.measureExecutedTime(
|
|
292
|
-
async () => (0, import_database.updateAssociations)(instance, value, { transaction }),
|
|
293
|
-
`Row ${i + 1}: updateAssociations completed in {time}ms`,
|
|
294
|
-
"debug"
|
|
295
|
-
);
|
|
296
317
|
if (insertOptions.hooks !== false) {
|
|
297
318
|
await this.loggerService.measureExecutedTime(
|
|
298
319
|
async () => {
|
|
299
|
-
await db.
|
|
320
|
+
await db.emitAsync(`${this.repository.collection.name}.afterCreate`, instance, {
|
|
300
321
|
transaction
|
|
301
322
|
});
|
|
302
323
|
await db.emitAsync(`${this.repository.collection.name}.afterSave`, instance, {
|
|
@@ -308,6 +329,11 @@ class XlsxImporter extends import_events.default {
|
|
|
308
329
|
"debug"
|
|
309
330
|
);
|
|
310
331
|
}
|
|
332
|
+
await this.loggerService.measureExecutedTime(
|
|
333
|
+
async () => (0, import_database.updateAssociations)(instance, value, { transaction }),
|
|
334
|
+
`Row ${i + 1}: updateAssociations completed in {time}ms`,
|
|
335
|
+
"debug"
|
|
336
|
+
);
|
|
311
337
|
if ((context == null ? void 0 : context.skipWorkflow) !== true) {
|
|
312
338
|
await this.loggerService.measureExecutedTime(
|
|
313
339
|
async () => {
|
|
@@ -378,7 +404,7 @@ class XlsxImporter extends import_events.default {
|
|
|
378
404
|
headers: expectedHeaders.join(", ")
|
|
379
405
|
});
|
|
380
406
|
}
|
|
381
|
-
data = this.alignWithHeaders({ data, expectedHeaders,
|
|
407
|
+
data = this.alignWithHeaders({ data, expectedHeaders, headerRowIndex });
|
|
382
408
|
const rows = data.slice(headerRowIndex + 1);
|
|
383
409
|
if (rows.length === 0) {
|
|
384
410
|
throw new import_errors.ImportValidationError("No data to import");
|
|
@@ -386,8 +412,14 @@ class XlsxImporter extends import_events.default {
|
|
|
386
412
|
return [headers, ...rows];
|
|
387
413
|
}
|
|
388
414
|
alignWithHeaders(params) {
|
|
389
|
-
const {
|
|
390
|
-
const
|
|
415
|
+
const { data, expectedHeaders, headerRowIndex } = params;
|
|
416
|
+
const headerRow = data[headerRowIndex];
|
|
417
|
+
const keepCols = expectedHeaders.map((header) => headerRow.indexOf(header));
|
|
418
|
+
if (keepCols.some((index) => index < 0)) {
|
|
419
|
+
throw new import_errors.ImportValidationError("Headers not found. Expected headers: {{headers}}", {
|
|
420
|
+
headers: expectedHeaders.join(", ")
|
|
421
|
+
});
|
|
422
|
+
}
|
|
391
423
|
return data.map((row) => keepCols.map((i) => row[i]));
|
|
392
424
|
}
|
|
393
425
|
findAndValidateHeaders(options) {
|
|
@@ -401,6 +433,7 @@ class XlsxImporter extends import_events.default {
|
|
|
401
433
|
return { headerRowIndex: rowIndex, headers: orderedHeaders };
|
|
402
434
|
}
|
|
403
435
|
}
|
|
436
|
+
return { headerRowIndex: -1, headers: [] };
|
|
404
437
|
}
|
|
405
438
|
}
|
|
406
439
|
// Annotate the CommonJS export names for ESM import in node:
|
package/package.json
CHANGED
|
@@ -2,12 +2,15 @@
|
|
|
2
2
|
"name": "@nocobase/plugin-action-import",
|
|
3
3
|
"displayName": "Action: Import records",
|
|
4
4
|
"displayName.zh-CN": "操作:导入记录",
|
|
5
|
+
"displayName.ru-RU": "Действие: Импорт записей",
|
|
5
6
|
"description": "Import records using excel templates. You can configure which fields to import and templates will be generated automatically.",
|
|
7
|
+
"description.ru-RU": "Импорт записей с помощью шаблонов Excel: можно настроить, какие поля импортировать, шаблоны будут генерироваться автоматически.",
|
|
6
8
|
"description.zh-CN": "使用 Excel 模板导入数据,可以配置导入哪些字段,自动生成模板。",
|
|
7
|
-
"version": "2.0.0-
|
|
9
|
+
"version": "2.0.0-beta.1",
|
|
8
10
|
"license": "AGPL-3.0",
|
|
9
11
|
"main": "./dist/server/index.js",
|
|
10
12
|
"homepage": "https://docs.nocobase.com/handbook/action-import",
|
|
13
|
+
"homepage.ru-RU": "https://docs.nocobase.ru/handbook/action-import",
|
|
11
14
|
"homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/action-import",
|
|
12
15
|
"devDependencies": {
|
|
13
16
|
"@ant-design/icons": "5.x",
|
|
@@ -36,7 +39,7 @@
|
|
|
36
39
|
"@nocobase/test": "2.x",
|
|
37
40
|
"@nocobase/utils": "2.x"
|
|
38
41
|
},
|
|
39
|
-
"gitHead": "
|
|
42
|
+
"gitHead": "b3d1f65848fc91e673372ee734dafe6b1cf80586",
|
|
40
43
|
"keywords": [
|
|
41
44
|
"Actions"
|
|
42
45
|
]
|
|
File without changes
|