@commercetools-frontend-extensions/operations 3.1.2 → 3.2.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/CHANGELOG.md +12 -0
- package/README.md +1 -2
- package/dist/commercetools-frontend-extensions-operations.cjs.dev.js +84 -72
- package/dist/commercetools-frontend-extensions-operations.cjs.prod.js +84 -72
- package/dist/commercetools-frontend-extensions-operations.esm.js +83 -68
- package/dist/declarations/src/@api/file-import-jobs.d.ts +21 -0
- package/dist/declarations/src/@api/import-containers.d.ts +5 -1
- package/dist/declarations/src/@hooks/use-file-upload.d.ts +0 -1
- package/dist/declarations/src/@types/file-import-job.d.ts +7 -1
- package/dist/declarations/src/@utils/file-upload.d.ts +0 -8
- package/package.json +9 -9
- package/src/@api/file-import-jobs.ts +52 -0
- package/src/@api/import-containers.ts +34 -3
- package/src/@components/uploading-modal/uploading-modal.tsx +6 -4
- package/src/@hooks/use-file-upload.ts +2 -15
- package/src/@types/file-import-job.ts +12 -11
- package/src/@utils/file-upload.ts +0 -39
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @commercetools-frontend-extensions/operations
|
|
2
2
|
|
|
3
|
+
## 3.2.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#1690](https://github.com/commercetools/merchant-center-operations/pull/1690) [`4a83020`](https://github.com/commercetools/merchant-center-operations/commit/4a83020117a46aba524ef16df0768b1bcaa42934) Thanks [@yassinejebli](https://github.com/yassinejebli)! - style(import): adjust spacing under Progress bar
|
|
8
|
+
|
|
9
|
+
## 3.2.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- [#1684](https://github.com/commercetools/merchant-center-operations/pull/1684) [`6dbe7fc`](https://github.com/commercetools/merchant-center-operations/commit/6dbe7fcff7440e42df01aaaf89dad93cb3bb3126) Thanks [@yassinejebli](https://github.com/yassinejebli)! - fix(import-details): fix progress calculation for new file import flow
|
|
14
|
+
|
|
3
15
|
## 3.1.2
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -33,9 +33,8 @@ const { upload, isUploading, progress, validationProgress } = useFileUpload({
|
|
|
33
33
|
- `upload` - Function to start the upload
|
|
34
34
|
- `isUploading` - Whether upload is in progress
|
|
35
35
|
- `progress` - Upload progress (0-100)
|
|
36
|
-
- `validationProgress` - `{ processed: number,
|
|
36
|
+
- `validationProgress` - `{ processed: number, isValidating: boolean }` (job-based flow only)
|
|
37
37
|
- `processed`: Number of resources validated so far (from backend)
|
|
38
|
-
- `total`: Total number of unique resources in the file (counted by unique keys in the CSV)
|
|
39
38
|
- `isValidating`: Whether validation is in progress
|
|
40
39
|
|
|
41
40
|
**Upload config options:**
|
|
@@ -22,8 +22,8 @@ var _inherits = require('@babel/runtime-corejs3/helpers/inherits');
|
|
|
22
22
|
var _wrapNativeSuper = require('@babel/runtime-corejs3/helpers/wrapNativeSuper');
|
|
23
23
|
var constants = require('@commercetools-frontend/constants');
|
|
24
24
|
var _everyInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/every');
|
|
25
|
-
var _Array$isArray = require('@babel/runtime-corejs3/core-js-stable/array/is-array');
|
|
26
25
|
var pluralize = require('pluralize');
|
|
26
|
+
var _Array$isArray = require('@babel/runtime-corejs3/core-js-stable/array/is-array');
|
|
27
27
|
var _reduceInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/reduce');
|
|
28
28
|
var _flatMapInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/flat-map');
|
|
29
29
|
var _mapInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/map');
|
|
@@ -31,13 +31,10 @@ var _Promise = require('@babel/runtime-corejs3/core-js-stable/promise');
|
|
|
31
31
|
var _findInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/find');
|
|
32
32
|
var _includesInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/includes');
|
|
33
33
|
var _someInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/some');
|
|
34
|
-
var _Set = require('@babel/runtime-corejs3/core-js-stable/set');
|
|
35
|
-
var _findIndexInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/find-index');
|
|
36
|
-
var _trimInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/trim');
|
|
37
|
-
var _bindInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/bind');
|
|
38
34
|
var Papa = require('papaparse');
|
|
39
35
|
var _sliceInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/slice');
|
|
40
36
|
var _JSON$stringify = require('@babel/runtime-corejs3/core-js-stable/json/stringify');
|
|
37
|
+
var _bindInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/bind');
|
|
41
38
|
var _startsWithInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/starts-with');
|
|
42
39
|
var _setTimeout = require('@babel/runtime-corejs3/core-js-stable/set-timeout');
|
|
43
40
|
var _concatInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/concat');
|
|
@@ -74,13 +71,10 @@ var _Promise__default = /*#__PURE__*/_interopDefault(_Promise);
|
|
|
74
71
|
var _findInstanceProperty__default = /*#__PURE__*/_interopDefault(_findInstanceProperty);
|
|
75
72
|
var _includesInstanceProperty__default = /*#__PURE__*/_interopDefault(_includesInstanceProperty);
|
|
76
73
|
var _someInstanceProperty__default = /*#__PURE__*/_interopDefault(_someInstanceProperty);
|
|
77
|
-
var _Set__default = /*#__PURE__*/_interopDefault(_Set);
|
|
78
|
-
var _findIndexInstanceProperty__default = /*#__PURE__*/_interopDefault(_findIndexInstanceProperty);
|
|
79
|
-
var _trimInstanceProperty__default = /*#__PURE__*/_interopDefault(_trimInstanceProperty);
|
|
80
|
-
var _bindInstanceProperty__default = /*#__PURE__*/_interopDefault(_bindInstanceProperty);
|
|
81
74
|
var Papa__default = /*#__PURE__*/_interopDefault(Papa);
|
|
82
75
|
var _sliceInstanceProperty__default = /*#__PURE__*/_interopDefault(_sliceInstanceProperty);
|
|
83
76
|
var _JSON$stringify__default = /*#__PURE__*/_interopDefault(_JSON$stringify);
|
|
77
|
+
var _bindInstanceProperty__default = /*#__PURE__*/_interopDefault(_bindInstanceProperty);
|
|
84
78
|
var _startsWithInstanceProperty__default = /*#__PURE__*/_interopDefault(_startsWithInstanceProperty);
|
|
85
79
|
var _setTimeout__default = /*#__PURE__*/_interopDefault(_setTimeout);
|
|
86
80
|
var _concatInstanceProperty__default = /*#__PURE__*/_interopDefault(_concatInstanceProperty);
|
|
@@ -371,14 +365,9 @@ function assertProcessFileImportJobResponse(maybeResponse) {
|
|
|
371
365
|
throw new Error('Invalid Process File Import Job response');
|
|
372
366
|
}
|
|
373
367
|
function assertListFileImportJobsResponse(maybeResponse) {
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
if (maybeResponse.length > 0) {
|
|
378
|
-
const requiredFields = ['id', 'fileName', 'importContainerKey', 'state'];
|
|
379
|
-
if (!hasRequiredFields(maybeResponse[0], requiredFields)) {
|
|
380
|
-
throw new Error('Invalid List File Import Jobs response: missing required fields');
|
|
381
|
-
}
|
|
368
|
+
const requiredFields = ['results', 'total', 'limit', 'offset', 'count'];
|
|
369
|
+
if (!hasRequiredFields(maybeResponse, requiredFields)) {
|
|
370
|
+
throw new Error('Invalid List File Import Jobs response: missing required fields');
|
|
382
371
|
}
|
|
383
372
|
}
|
|
384
373
|
|
|
@@ -491,7 +480,7 @@ function shouldContinuePollingForImportValidation(job) {
|
|
|
491
480
|
}
|
|
492
481
|
|
|
493
482
|
function ownKeys$8(e, r) { var t = _Object$keys__default["default"](e); if (_Object$getOwnPropertySymbols__default["default"]) { var o = _Object$getOwnPropertySymbols__default["default"](e); r && (o = _filterInstanceProperty__default["default"](o).call(o, function (r) { return _Object$getOwnPropertyDescriptor__default["default"](e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
494
|
-
function _objectSpread$8(e) { for (var r = 1; r < arguments.length; r++) { var
|
|
483
|
+
function _objectSpread$8(e) { for (var r = 1; r < arguments.length; r++) { var _context2, _context3; var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? _forEachInstanceProperty__default["default"](_context2 = ownKeys$8(Object(t), !0)).call(_context2, function (r) { _defineProperty(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors__default["default"] ? _Object$defineProperties__default["default"](e, _Object$getOwnPropertyDescriptors__default["default"](t)) : _forEachInstanceProperty__default["default"](_context3 = ownKeys$8(Object(t))).call(_context3, function (r) { _Object$defineProperty__default["default"](e, r, _Object$getOwnPropertyDescriptor__default["default"](t, r)); }); } return e; }
|
|
495
484
|
|
|
496
485
|
/**
|
|
497
486
|
* Convert megabytes to bytes
|
|
@@ -610,44 +599,6 @@ const countJsonFileItems = async file => {
|
|
|
610
599
|
}
|
|
611
600
|
};
|
|
612
601
|
|
|
613
|
-
/**
|
|
614
|
-
* Count unique resources in a CSV file by counting unique values in the "key" column.
|
|
615
|
-
* A single resource can span multiple rows (when it has array fields like variants, assets...),
|
|
616
|
-
* so we count unique keys rather than rows.
|
|
617
|
-
* @param file The CSV file to process
|
|
618
|
-
* @returns A promise that resolves to the number of unique resources
|
|
619
|
-
*/
|
|
620
|
-
const countUniqueResourcesInCsv = file => {
|
|
621
|
-
return new _Promise__default["default"](resolve => {
|
|
622
|
-
const uniqueKeys = new _Set__default["default"]();
|
|
623
|
-
let keyColumnIndex = -1;
|
|
624
|
-
let isFirstRow = true;
|
|
625
|
-
Papa__default["default"].parse(file, {
|
|
626
|
-
step: _ref2 => {
|
|
627
|
-
var _context4, _context5;
|
|
628
|
-
let data = _ref2.data;
|
|
629
|
-
if (!_Array$isArray__default["default"](data)) return;
|
|
630
|
-
if (isFirstRow) {
|
|
631
|
-
keyColumnIndex = _findIndexInstanceProperty__default["default"](data).call(data, col => {
|
|
632
|
-
var _context2, _context3;
|
|
633
|
-
return ((_context2 = col?.toLowerCase()) == null ? void 0 : _bindInstanceProperty__default["default"](_context3 = Function.call).call(_context3, _trimInstanceProperty__default["default"](_context2), _context2))?.() === 'key';
|
|
634
|
-
});
|
|
635
|
-
isFirstRow = false;
|
|
636
|
-
return;
|
|
637
|
-
}
|
|
638
|
-
if (keyColumnIndex === -1) return;
|
|
639
|
-
const keyValue = ((_context4 = data[keyColumnIndex]) == null ? void 0 : _bindInstanceProperty__default["default"](_context5 = Function.call).call(_context5, _trimInstanceProperty__default["default"](_context4), _context4))?.();
|
|
640
|
-
if (keyValue) {
|
|
641
|
-
uniqueKeys.add(keyValue);
|
|
642
|
-
}
|
|
643
|
-
},
|
|
644
|
-
complete: () => {
|
|
645
|
-
resolve(uniqueKeys.size);
|
|
646
|
-
}
|
|
647
|
-
});
|
|
648
|
-
});
|
|
649
|
-
};
|
|
650
|
-
|
|
651
602
|
/**
|
|
652
603
|
* Map file upload errors to upload file error rows with unique IDs
|
|
653
604
|
* @param uploadFileErrors Array of file upload errors
|
|
@@ -1160,10 +1111,48 @@ async function listFileImportJobs(_ref6) {
|
|
|
1160
1111
|
assertListFileImportJobsResponse(response);
|
|
1161
1112
|
return response;
|
|
1162
1113
|
}
|
|
1114
|
+
/**
|
|
1115
|
+
* Gets the file import job info for an import container
|
|
1116
|
+
*
|
|
1117
|
+
* For the new file import job flow, import operations are created incrementally
|
|
1118
|
+
* during the 'initialising' state. The import summary total
|
|
1119
|
+
* reflects only the operations created so far, which can be misleading
|
|
1120
|
+
*
|
|
1121
|
+
* This helper fetches the file import job (if it exists) to get:
|
|
1122
|
+
* - The true total from the job summary (known from initial CSV validation)
|
|
1123
|
+
* - Whether the job is still initializing (creating import operations)
|
|
1124
|
+
*
|
|
1125
|
+
* @returns Job info if found, null otherwise
|
|
1126
|
+
*/
|
|
1127
|
+
async function getFileImportJobInfoForContainer(_ref7) {
|
|
1128
|
+
let projectKey = _ref7.projectKey,
|
|
1129
|
+
importContainerKey = _ref7.importContainerKey;
|
|
1130
|
+
try {
|
|
1131
|
+
const response = await listFileImportJobs({
|
|
1132
|
+
projectKey,
|
|
1133
|
+
importContainerKey,
|
|
1134
|
+
limit: 1
|
|
1135
|
+
});
|
|
1136
|
+
if (response.results.length > 0 && response.results[0].summary?.total != null) {
|
|
1137
|
+
var _context;
|
|
1138
|
+
const job = response.results[0];
|
|
1139
|
+
const isInitializing = _includesInstanceProperty__default["default"](_context = ['processing', 'initialising']).call(_context, job.state);
|
|
1140
|
+
return {
|
|
1141
|
+
total: job.summary.total,
|
|
1142
|
+
isInitializing
|
|
1143
|
+
};
|
|
1144
|
+
}
|
|
1145
|
+
return null;
|
|
1146
|
+
} catch {
|
|
1147
|
+
// Job might not exist (old flow)
|
|
1148
|
+
return null;
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1163
1151
|
|
|
1164
1152
|
function ownKeys$6(e, r) { var t = _Object$keys__default["default"](e); if (_Object$getOwnPropertySymbols__default["default"]) { var o = _Object$getOwnPropertySymbols__default["default"](e); r && (o = _filterInstanceProperty__default["default"](o).call(o, function (r) { return _Object$getOwnPropertyDescriptor__default["default"](e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
1165
1153
|
function _objectSpread$6(e) { for (var r = 1; r < arguments.length; r++) { var _context2, _context3; var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? _forEachInstanceProperty__default["default"](_context2 = ownKeys$6(Object(t), !0)).call(_context2, function (r) { _defineProperty(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors__default["default"] ? _Object$defineProperties__default["default"](e, _Object$getOwnPropertyDescriptors__default["default"](t)) : _forEachInstanceProperty__default["default"](_context3 = ownKeys$6(Object(t))).call(_context3, function (r) { _Object$defineProperty__default["default"](e, r, _Object$getOwnPropertyDescriptor__default["default"](t, r)); }); } return e; }
|
|
1166
1154
|
function getImportState(importSummary) {
|
|
1155
|
+
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
1167
1156
|
const processing = importSummary.states.processing > 0;
|
|
1168
1157
|
if (processing) return ImportStates.Processing;
|
|
1169
1158
|
const waitForUnresolvedReferences = importSummary.states.waitForMasterVariant > 0 || importSummary.states.unresolved > 0;
|
|
@@ -1172,6 +1161,11 @@ function getImportState(importSummary) {
|
|
|
1172
1161
|
if (partiallyCompleted) return ImportStates.PartiallyCompleted;
|
|
1173
1162
|
const noRunning = importSummary.total === 0;
|
|
1174
1163
|
if (noRunning) return ImportStates.NoRunningImports;
|
|
1164
|
+
|
|
1165
|
+
// For the new flow: job is actively creating import operations (to show as Processing even if no operations exist yet)
|
|
1166
|
+
if (options.isJobInitializing) {
|
|
1167
|
+
return ImportStates.Processing;
|
|
1168
|
+
}
|
|
1175
1169
|
const successfullyCompleted = importSummary.states.imported === importSummary.total || importSummary.states.deleted === importSummary.total;
|
|
1176
1170
|
if (successfullyCompleted) return ImportStates.SuccessfullyCompleted;
|
|
1177
1171
|
const failed = importSummary.states.rejected + importSummary.states.validationFailed === importSummary.total;
|
|
@@ -1320,12 +1314,33 @@ async function cancelImportContainerByKey(_ref8) {
|
|
|
1320
1314
|
return response;
|
|
1321
1315
|
}
|
|
1322
1316
|
async function importContainerToContainerDetails(projectKey, importContainer) {
|
|
1323
|
-
|
|
1317
|
+
let importSummary = await fetchImportSummary({
|
|
1324
1318
|
projectKey,
|
|
1325
1319
|
importContainerKey: importContainer.key
|
|
1326
1320
|
});
|
|
1327
|
-
const importState = getImportState(importSummary);
|
|
1328
1321
|
const isFileUploadImport = checkIfFileUploadImport(importContainer.tags);
|
|
1322
|
+
|
|
1323
|
+
// For the new file import job flow the import operations are created incrementally
|
|
1324
|
+
// The import summary total reflects only operations created so far
|
|
1325
|
+
// Only override total when job is actively initializing (creating operations)
|
|
1326
|
+
let isJobInitializing = false;
|
|
1327
|
+
if (isFileUploadImport) {
|
|
1328
|
+
const jobInfo = await getFileImportJobInfoForContainer({
|
|
1329
|
+
projectKey,
|
|
1330
|
+
importContainerKey: importContainer.key
|
|
1331
|
+
});
|
|
1332
|
+
if (jobInfo !== null) {
|
|
1333
|
+
isJobInitializing = jobInfo.isInitializing;
|
|
1334
|
+
if (isJobInitializing || importSummary.total > 0) {
|
|
1335
|
+
importSummary = _objectSpread$6(_objectSpread$6({}, importSummary), {}, {
|
|
1336
|
+
total: jobInfo.total
|
|
1337
|
+
});
|
|
1338
|
+
}
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
const importState = getImportState(importSummary, {
|
|
1342
|
+
isJobInitializing
|
|
1343
|
+
});
|
|
1329
1344
|
return {
|
|
1330
1345
|
importContainer: importContainer,
|
|
1331
1346
|
importState,
|
|
@@ -2603,13 +2618,16 @@ const UploadingModal = _ref => {
|
|
|
2603
2618
|
label: cancelLabel,
|
|
2604
2619
|
onClick: onCancel
|
|
2605
2620
|
})]
|
|
2606
|
-
}), /*#__PURE__*/jsxRuntime.
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2621
|
+
}), /*#__PURE__*/jsxRuntime.jsxs(uiKit.Spacings.Stack, {
|
|
2622
|
+
scale: "xs",
|
|
2623
|
+
children: [/*#__PURE__*/jsxRuntime.jsx(uiKit.ProgressBar, {
|
|
2624
|
+
barWidth: "scale",
|
|
2625
|
+
height: "10",
|
|
2626
|
+
progress: progress
|
|
2627
|
+
}), statusMessage && /*#__PURE__*/jsxRuntime.jsx(uiKit.Text.Detail, {
|
|
2628
|
+
tone: "tertiary",
|
|
2629
|
+
children: statusMessage
|
|
2630
|
+
})]
|
|
2613
2631
|
})]
|
|
2614
2632
|
})
|
|
2615
2633
|
});
|
|
@@ -3032,7 +3050,6 @@ const useFileUpload = _ref2 => {
|
|
|
3032
3050
|
setProgress = _React$useState4[1];
|
|
3033
3051
|
const _React$useState5 = React__default["default"].useState({
|
|
3034
3052
|
processed: 0,
|
|
3035
|
-
total: 0,
|
|
3036
3053
|
isValidating: false
|
|
3037
3054
|
}),
|
|
3038
3055
|
_React$useState6 = _slicedToArray(_React$useState5, 2),
|
|
@@ -3049,7 +3066,6 @@ const useFileUpload = _ref2 => {
|
|
|
3049
3066
|
setProgress(0);
|
|
3050
3067
|
setValidationProgress({
|
|
3051
3068
|
processed: 0,
|
|
3052
|
-
total: 0,
|
|
3053
3069
|
isValidating: false
|
|
3054
3070
|
});
|
|
3055
3071
|
}, []);
|
|
@@ -3058,7 +3074,6 @@ const useFileUpload = _ref2 => {
|
|
|
3058
3074
|
setProgress(0);
|
|
3059
3075
|
try {
|
|
3060
3076
|
if (useJobBasedFlow) {
|
|
3061
|
-
const totalResources = config.skipValidationPolling ? 0 : await countUniqueResourcesInCsv(config.file);
|
|
3062
3077
|
await jobUpload.upload({
|
|
3063
3078
|
file: config.file,
|
|
3064
3079
|
resourceType: config.resourceType,
|
|
@@ -3105,7 +3120,6 @@ const useFileUpload = _ref2 => {
|
|
|
3105
3120
|
try {
|
|
3106
3121
|
setValidationProgress({
|
|
3107
3122
|
processed: 0,
|
|
3108
|
-
total: totalResources,
|
|
3109
3123
|
isValidating: true
|
|
3110
3124
|
});
|
|
3111
3125
|
const validatedJob = await pollJobUntilValidated({
|
|
@@ -3119,7 +3133,6 @@ const useFileUpload = _ref2 => {
|
|
|
3119
3133
|
const processed = job.summary?.total ?? 0;
|
|
3120
3134
|
setValidationProgress({
|
|
3121
3135
|
processed,
|
|
3122
|
-
total: totalResources,
|
|
3123
3136
|
isValidating: true
|
|
3124
3137
|
});
|
|
3125
3138
|
config.onValidationProgress?.(job);
|
|
@@ -3149,7 +3162,6 @@ const useFileUpload = _ref2 => {
|
|
|
3149
3162
|
setIsUploading(false);
|
|
3150
3163
|
setValidationProgress({
|
|
3151
3164
|
processed: 0,
|
|
3152
|
-
total: 0,
|
|
3153
3165
|
isValidating: false
|
|
3154
3166
|
});
|
|
3155
3167
|
config.onSuccess(result);
|
|
@@ -3292,7 +3304,6 @@ exports.cancelImportContainerByKey = cancelImportContainerByKey;
|
|
|
3292
3304
|
exports.checkIfFileUploadImport = checkIfFileUploadImport;
|
|
3293
3305
|
exports.convertFileSizeToKB = convertFileSizeToKB;
|
|
3294
3306
|
exports.countJsonFileItems = countJsonFileItems;
|
|
3295
|
-
exports.countUniqueResourcesInCsv = countUniqueResourcesInCsv;
|
|
3296
3307
|
exports.createFileImportJob = createFileImportJob;
|
|
3297
3308
|
exports.createImportContainerForFileUpload = createImportContainerForFileUpload;
|
|
3298
3309
|
exports.decodeFileNameFromImportContainerKey = decodeFileNameFromImportContainerKey;
|
|
@@ -3324,6 +3335,7 @@ exports.getFileImportJob = getFileImportJob;
|
|
|
3324
3335
|
exports.getFileImportJobByIdURL = getFileImportJobByIdURL;
|
|
3325
3336
|
exports.getFileImportJobDeleteURL = getFileImportJobDeleteURL;
|
|
3326
3337
|
exports.getFileImportJobFileType = getFileImportJobFileType;
|
|
3338
|
+
exports.getFileImportJobInfoForContainer = getFileImportJobInfoForContainer;
|
|
3327
3339
|
exports.getFileImportJobProcessURL = getFileImportJobProcessURL;
|
|
3328
3340
|
exports.getFileImportJobRecords = getFileImportJobRecords;
|
|
3329
3341
|
exports.getFileImportJobRecordsURL = getFileImportJobRecordsURL;
|
|
@@ -22,8 +22,8 @@ var _inherits = require('@babel/runtime-corejs3/helpers/inherits');
|
|
|
22
22
|
var _wrapNativeSuper = require('@babel/runtime-corejs3/helpers/wrapNativeSuper');
|
|
23
23
|
var constants = require('@commercetools-frontend/constants');
|
|
24
24
|
var _everyInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/every');
|
|
25
|
-
var _Array$isArray = require('@babel/runtime-corejs3/core-js-stable/array/is-array');
|
|
26
25
|
var pluralize = require('pluralize');
|
|
26
|
+
var _Array$isArray = require('@babel/runtime-corejs3/core-js-stable/array/is-array');
|
|
27
27
|
var _reduceInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/reduce');
|
|
28
28
|
var _flatMapInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/flat-map');
|
|
29
29
|
var _mapInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/map');
|
|
@@ -31,13 +31,10 @@ var _Promise = require('@babel/runtime-corejs3/core-js-stable/promise');
|
|
|
31
31
|
var _findInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/find');
|
|
32
32
|
var _includesInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/includes');
|
|
33
33
|
var _someInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/some');
|
|
34
|
-
var _Set = require('@babel/runtime-corejs3/core-js-stable/set');
|
|
35
|
-
var _findIndexInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/find-index');
|
|
36
|
-
var _trimInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/trim');
|
|
37
|
-
var _bindInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/bind');
|
|
38
34
|
var Papa = require('papaparse');
|
|
39
35
|
var _sliceInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/slice');
|
|
40
36
|
var _JSON$stringify = require('@babel/runtime-corejs3/core-js-stable/json/stringify');
|
|
37
|
+
var _bindInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/bind');
|
|
41
38
|
var _startsWithInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/starts-with');
|
|
42
39
|
var _setTimeout = require('@babel/runtime-corejs3/core-js-stable/set-timeout');
|
|
43
40
|
var _concatInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/concat');
|
|
@@ -74,13 +71,10 @@ var _Promise__default = /*#__PURE__*/_interopDefault(_Promise);
|
|
|
74
71
|
var _findInstanceProperty__default = /*#__PURE__*/_interopDefault(_findInstanceProperty);
|
|
75
72
|
var _includesInstanceProperty__default = /*#__PURE__*/_interopDefault(_includesInstanceProperty);
|
|
76
73
|
var _someInstanceProperty__default = /*#__PURE__*/_interopDefault(_someInstanceProperty);
|
|
77
|
-
var _Set__default = /*#__PURE__*/_interopDefault(_Set);
|
|
78
|
-
var _findIndexInstanceProperty__default = /*#__PURE__*/_interopDefault(_findIndexInstanceProperty);
|
|
79
|
-
var _trimInstanceProperty__default = /*#__PURE__*/_interopDefault(_trimInstanceProperty);
|
|
80
|
-
var _bindInstanceProperty__default = /*#__PURE__*/_interopDefault(_bindInstanceProperty);
|
|
81
74
|
var Papa__default = /*#__PURE__*/_interopDefault(Papa);
|
|
82
75
|
var _sliceInstanceProperty__default = /*#__PURE__*/_interopDefault(_sliceInstanceProperty);
|
|
83
76
|
var _JSON$stringify__default = /*#__PURE__*/_interopDefault(_JSON$stringify);
|
|
77
|
+
var _bindInstanceProperty__default = /*#__PURE__*/_interopDefault(_bindInstanceProperty);
|
|
84
78
|
var _startsWithInstanceProperty__default = /*#__PURE__*/_interopDefault(_startsWithInstanceProperty);
|
|
85
79
|
var _setTimeout__default = /*#__PURE__*/_interopDefault(_setTimeout);
|
|
86
80
|
var _concatInstanceProperty__default = /*#__PURE__*/_interopDefault(_concatInstanceProperty);
|
|
@@ -371,14 +365,9 @@ function assertProcessFileImportJobResponse(maybeResponse) {
|
|
|
371
365
|
throw new Error('Invalid Process File Import Job response');
|
|
372
366
|
}
|
|
373
367
|
function assertListFileImportJobsResponse(maybeResponse) {
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
if (maybeResponse.length > 0) {
|
|
378
|
-
const requiredFields = ['id', 'fileName', 'importContainerKey', 'state'];
|
|
379
|
-
if (!hasRequiredFields(maybeResponse[0], requiredFields)) {
|
|
380
|
-
throw new Error('Invalid List File Import Jobs response: missing required fields');
|
|
381
|
-
}
|
|
368
|
+
const requiredFields = ['results', 'total', 'limit', 'offset', 'count'];
|
|
369
|
+
if (!hasRequiredFields(maybeResponse, requiredFields)) {
|
|
370
|
+
throw new Error('Invalid List File Import Jobs response: missing required fields');
|
|
382
371
|
}
|
|
383
372
|
}
|
|
384
373
|
|
|
@@ -491,7 +480,7 @@ function shouldContinuePollingForImportValidation(job) {
|
|
|
491
480
|
}
|
|
492
481
|
|
|
493
482
|
function ownKeys$8(e, r) { var t = _Object$keys__default["default"](e); if (_Object$getOwnPropertySymbols__default["default"]) { var o = _Object$getOwnPropertySymbols__default["default"](e); r && (o = _filterInstanceProperty__default["default"](o).call(o, function (r) { return _Object$getOwnPropertyDescriptor__default["default"](e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
494
|
-
function _objectSpread$8(e) { for (var r = 1; r < arguments.length; r++) { var
|
|
483
|
+
function _objectSpread$8(e) { for (var r = 1; r < arguments.length; r++) { var _context2, _context3; var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? _forEachInstanceProperty__default["default"](_context2 = ownKeys$8(Object(t), !0)).call(_context2, function (r) { _defineProperty(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors__default["default"] ? _Object$defineProperties__default["default"](e, _Object$getOwnPropertyDescriptors__default["default"](t)) : _forEachInstanceProperty__default["default"](_context3 = ownKeys$8(Object(t))).call(_context3, function (r) { _Object$defineProperty__default["default"](e, r, _Object$getOwnPropertyDescriptor__default["default"](t, r)); }); } return e; }
|
|
495
484
|
|
|
496
485
|
/**
|
|
497
486
|
* Convert megabytes to bytes
|
|
@@ -610,44 +599,6 @@ const countJsonFileItems = async file => {
|
|
|
610
599
|
}
|
|
611
600
|
};
|
|
612
601
|
|
|
613
|
-
/**
|
|
614
|
-
* Count unique resources in a CSV file by counting unique values in the "key" column.
|
|
615
|
-
* A single resource can span multiple rows (when it has array fields like variants, assets...),
|
|
616
|
-
* so we count unique keys rather than rows.
|
|
617
|
-
* @param file The CSV file to process
|
|
618
|
-
* @returns A promise that resolves to the number of unique resources
|
|
619
|
-
*/
|
|
620
|
-
const countUniqueResourcesInCsv = file => {
|
|
621
|
-
return new _Promise__default["default"](resolve => {
|
|
622
|
-
const uniqueKeys = new _Set__default["default"]();
|
|
623
|
-
let keyColumnIndex = -1;
|
|
624
|
-
let isFirstRow = true;
|
|
625
|
-
Papa__default["default"].parse(file, {
|
|
626
|
-
step: _ref2 => {
|
|
627
|
-
var _context4, _context5;
|
|
628
|
-
let data = _ref2.data;
|
|
629
|
-
if (!_Array$isArray__default["default"](data)) return;
|
|
630
|
-
if (isFirstRow) {
|
|
631
|
-
keyColumnIndex = _findIndexInstanceProperty__default["default"](data).call(data, col => {
|
|
632
|
-
var _context2, _context3;
|
|
633
|
-
return ((_context2 = col?.toLowerCase()) == null ? void 0 : _bindInstanceProperty__default["default"](_context3 = Function.call).call(_context3, _trimInstanceProperty__default["default"](_context2), _context2))?.() === 'key';
|
|
634
|
-
});
|
|
635
|
-
isFirstRow = false;
|
|
636
|
-
return;
|
|
637
|
-
}
|
|
638
|
-
if (keyColumnIndex === -1) return;
|
|
639
|
-
const keyValue = ((_context4 = data[keyColumnIndex]) == null ? void 0 : _bindInstanceProperty__default["default"](_context5 = Function.call).call(_context5, _trimInstanceProperty__default["default"](_context4), _context4))?.();
|
|
640
|
-
if (keyValue) {
|
|
641
|
-
uniqueKeys.add(keyValue);
|
|
642
|
-
}
|
|
643
|
-
},
|
|
644
|
-
complete: () => {
|
|
645
|
-
resolve(uniqueKeys.size);
|
|
646
|
-
}
|
|
647
|
-
});
|
|
648
|
-
});
|
|
649
|
-
};
|
|
650
|
-
|
|
651
602
|
/**
|
|
652
603
|
* Map file upload errors to upload file error rows with unique IDs
|
|
653
604
|
* @param uploadFileErrors Array of file upload errors
|
|
@@ -1160,10 +1111,48 @@ async function listFileImportJobs(_ref6) {
|
|
|
1160
1111
|
assertListFileImportJobsResponse(response);
|
|
1161
1112
|
return response;
|
|
1162
1113
|
}
|
|
1114
|
+
/**
|
|
1115
|
+
* Gets the file import job info for an import container
|
|
1116
|
+
*
|
|
1117
|
+
* For the new file import job flow, import operations are created incrementally
|
|
1118
|
+
* during the 'initialising' state. The import summary total
|
|
1119
|
+
* reflects only the operations created so far, which can be misleading
|
|
1120
|
+
*
|
|
1121
|
+
* This helper fetches the file import job (if it exists) to get:
|
|
1122
|
+
* - The true total from the job summary (known from initial CSV validation)
|
|
1123
|
+
* - Whether the job is still initializing (creating import operations)
|
|
1124
|
+
*
|
|
1125
|
+
* @returns Job info if found, null otherwise
|
|
1126
|
+
*/
|
|
1127
|
+
async function getFileImportJobInfoForContainer(_ref7) {
|
|
1128
|
+
let projectKey = _ref7.projectKey,
|
|
1129
|
+
importContainerKey = _ref7.importContainerKey;
|
|
1130
|
+
try {
|
|
1131
|
+
const response = await listFileImportJobs({
|
|
1132
|
+
projectKey,
|
|
1133
|
+
importContainerKey,
|
|
1134
|
+
limit: 1
|
|
1135
|
+
});
|
|
1136
|
+
if (response.results.length > 0 && response.results[0].summary?.total != null) {
|
|
1137
|
+
var _context;
|
|
1138
|
+
const job = response.results[0];
|
|
1139
|
+
const isInitializing = _includesInstanceProperty__default["default"](_context = ['processing', 'initialising']).call(_context, job.state);
|
|
1140
|
+
return {
|
|
1141
|
+
total: job.summary.total,
|
|
1142
|
+
isInitializing
|
|
1143
|
+
};
|
|
1144
|
+
}
|
|
1145
|
+
return null;
|
|
1146
|
+
} catch {
|
|
1147
|
+
// Job might not exist (old flow)
|
|
1148
|
+
return null;
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1163
1151
|
|
|
1164
1152
|
function ownKeys$6(e, r) { var t = _Object$keys__default["default"](e); if (_Object$getOwnPropertySymbols__default["default"]) { var o = _Object$getOwnPropertySymbols__default["default"](e); r && (o = _filterInstanceProperty__default["default"](o).call(o, function (r) { return _Object$getOwnPropertyDescriptor__default["default"](e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
1165
1153
|
function _objectSpread$6(e) { for (var r = 1; r < arguments.length; r++) { var _context2, _context3; var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? _forEachInstanceProperty__default["default"](_context2 = ownKeys$6(Object(t), !0)).call(_context2, function (r) { _defineProperty(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors__default["default"] ? _Object$defineProperties__default["default"](e, _Object$getOwnPropertyDescriptors__default["default"](t)) : _forEachInstanceProperty__default["default"](_context3 = ownKeys$6(Object(t))).call(_context3, function (r) { _Object$defineProperty__default["default"](e, r, _Object$getOwnPropertyDescriptor__default["default"](t, r)); }); } return e; }
|
|
1166
1154
|
function getImportState(importSummary) {
|
|
1155
|
+
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
1167
1156
|
const processing = importSummary.states.processing > 0;
|
|
1168
1157
|
if (processing) return ImportStates.Processing;
|
|
1169
1158
|
const waitForUnresolvedReferences = importSummary.states.waitForMasterVariant > 0 || importSummary.states.unresolved > 0;
|
|
@@ -1172,6 +1161,11 @@ function getImportState(importSummary) {
|
|
|
1172
1161
|
if (partiallyCompleted) return ImportStates.PartiallyCompleted;
|
|
1173
1162
|
const noRunning = importSummary.total === 0;
|
|
1174
1163
|
if (noRunning) return ImportStates.NoRunningImports;
|
|
1164
|
+
|
|
1165
|
+
// For the new flow: job is actively creating import operations (to show as Processing even if no operations exist yet)
|
|
1166
|
+
if (options.isJobInitializing) {
|
|
1167
|
+
return ImportStates.Processing;
|
|
1168
|
+
}
|
|
1175
1169
|
const successfullyCompleted = importSummary.states.imported === importSummary.total || importSummary.states.deleted === importSummary.total;
|
|
1176
1170
|
if (successfullyCompleted) return ImportStates.SuccessfullyCompleted;
|
|
1177
1171
|
const failed = importSummary.states.rejected + importSummary.states.validationFailed === importSummary.total;
|
|
@@ -1320,12 +1314,33 @@ async function cancelImportContainerByKey(_ref8) {
|
|
|
1320
1314
|
return response;
|
|
1321
1315
|
}
|
|
1322
1316
|
async function importContainerToContainerDetails(projectKey, importContainer) {
|
|
1323
|
-
|
|
1317
|
+
let importSummary = await fetchImportSummary({
|
|
1324
1318
|
projectKey,
|
|
1325
1319
|
importContainerKey: importContainer.key
|
|
1326
1320
|
});
|
|
1327
|
-
const importState = getImportState(importSummary);
|
|
1328
1321
|
const isFileUploadImport = checkIfFileUploadImport(importContainer.tags);
|
|
1322
|
+
|
|
1323
|
+
// For the new file import job flow the import operations are created incrementally
|
|
1324
|
+
// The import summary total reflects only operations created so far
|
|
1325
|
+
// Only override total when job is actively initializing (creating operations)
|
|
1326
|
+
let isJobInitializing = false;
|
|
1327
|
+
if (isFileUploadImport) {
|
|
1328
|
+
const jobInfo = await getFileImportJobInfoForContainer({
|
|
1329
|
+
projectKey,
|
|
1330
|
+
importContainerKey: importContainer.key
|
|
1331
|
+
});
|
|
1332
|
+
if (jobInfo !== null) {
|
|
1333
|
+
isJobInitializing = jobInfo.isInitializing;
|
|
1334
|
+
if (isJobInitializing || importSummary.total > 0) {
|
|
1335
|
+
importSummary = _objectSpread$6(_objectSpread$6({}, importSummary), {}, {
|
|
1336
|
+
total: jobInfo.total
|
|
1337
|
+
});
|
|
1338
|
+
}
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
const importState = getImportState(importSummary, {
|
|
1342
|
+
isJobInitializing
|
|
1343
|
+
});
|
|
1329
1344
|
return {
|
|
1330
1345
|
importContainer: importContainer,
|
|
1331
1346
|
importState,
|
|
@@ -2595,13 +2610,16 @@ const UploadingModal = _ref => {
|
|
|
2595
2610
|
label: cancelLabel,
|
|
2596
2611
|
onClick: onCancel
|
|
2597
2612
|
})]
|
|
2598
|
-
}), /*#__PURE__*/jsxRuntime.
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2613
|
+
}), /*#__PURE__*/jsxRuntime.jsxs(uiKit.Spacings.Stack, {
|
|
2614
|
+
scale: "xs",
|
|
2615
|
+
children: [/*#__PURE__*/jsxRuntime.jsx(uiKit.ProgressBar, {
|
|
2616
|
+
barWidth: "scale",
|
|
2617
|
+
height: "10",
|
|
2618
|
+
progress: progress
|
|
2619
|
+
}), statusMessage && /*#__PURE__*/jsxRuntime.jsx(uiKit.Text.Detail, {
|
|
2620
|
+
tone: "tertiary",
|
|
2621
|
+
children: statusMessage
|
|
2622
|
+
})]
|
|
2605
2623
|
})]
|
|
2606
2624
|
})
|
|
2607
2625
|
});
|
|
@@ -3024,7 +3042,6 @@ const useFileUpload = _ref2 => {
|
|
|
3024
3042
|
setProgress = _React$useState4[1];
|
|
3025
3043
|
const _React$useState5 = React__default["default"].useState({
|
|
3026
3044
|
processed: 0,
|
|
3027
|
-
total: 0,
|
|
3028
3045
|
isValidating: false
|
|
3029
3046
|
}),
|
|
3030
3047
|
_React$useState6 = _slicedToArray(_React$useState5, 2),
|
|
@@ -3041,7 +3058,6 @@ const useFileUpload = _ref2 => {
|
|
|
3041
3058
|
setProgress(0);
|
|
3042
3059
|
setValidationProgress({
|
|
3043
3060
|
processed: 0,
|
|
3044
|
-
total: 0,
|
|
3045
3061
|
isValidating: false
|
|
3046
3062
|
});
|
|
3047
3063
|
}, []);
|
|
@@ -3050,7 +3066,6 @@ const useFileUpload = _ref2 => {
|
|
|
3050
3066
|
setProgress(0);
|
|
3051
3067
|
try {
|
|
3052
3068
|
if (useJobBasedFlow) {
|
|
3053
|
-
const totalResources = config.skipValidationPolling ? 0 : await countUniqueResourcesInCsv(config.file);
|
|
3054
3069
|
await jobUpload.upload({
|
|
3055
3070
|
file: config.file,
|
|
3056
3071
|
resourceType: config.resourceType,
|
|
@@ -3097,7 +3112,6 @@ const useFileUpload = _ref2 => {
|
|
|
3097
3112
|
try {
|
|
3098
3113
|
setValidationProgress({
|
|
3099
3114
|
processed: 0,
|
|
3100
|
-
total: totalResources,
|
|
3101
3115
|
isValidating: true
|
|
3102
3116
|
});
|
|
3103
3117
|
const validatedJob = await pollJobUntilValidated({
|
|
@@ -3111,7 +3125,6 @@ const useFileUpload = _ref2 => {
|
|
|
3111
3125
|
const processed = job.summary?.total ?? 0;
|
|
3112
3126
|
setValidationProgress({
|
|
3113
3127
|
processed,
|
|
3114
|
-
total: totalResources,
|
|
3115
3128
|
isValidating: true
|
|
3116
3129
|
});
|
|
3117
3130
|
config.onValidationProgress?.(job);
|
|
@@ -3141,7 +3154,6 @@ const useFileUpload = _ref2 => {
|
|
|
3141
3154
|
setIsUploading(false);
|
|
3142
3155
|
setValidationProgress({
|
|
3143
3156
|
processed: 0,
|
|
3144
|
-
total: 0,
|
|
3145
3157
|
isValidating: false
|
|
3146
3158
|
});
|
|
3147
3159
|
config.onSuccess(result);
|
|
@@ -3284,7 +3296,6 @@ exports.cancelImportContainerByKey = cancelImportContainerByKey;
|
|
|
3284
3296
|
exports.checkIfFileUploadImport = checkIfFileUploadImport;
|
|
3285
3297
|
exports.convertFileSizeToKB = convertFileSizeToKB;
|
|
3286
3298
|
exports.countJsonFileItems = countJsonFileItems;
|
|
3287
|
-
exports.countUniqueResourcesInCsv = countUniqueResourcesInCsv;
|
|
3288
3299
|
exports.createFileImportJob = createFileImportJob;
|
|
3289
3300
|
exports.createImportContainerForFileUpload = createImportContainerForFileUpload;
|
|
3290
3301
|
exports.decodeFileNameFromImportContainerKey = decodeFileNameFromImportContainerKey;
|
|
@@ -3316,6 +3327,7 @@ exports.getFileImportJob = getFileImportJob;
|
|
|
3316
3327
|
exports.getFileImportJobByIdURL = getFileImportJobByIdURL;
|
|
3317
3328
|
exports.getFileImportJobDeleteURL = getFileImportJobDeleteURL;
|
|
3318
3329
|
exports.getFileImportJobFileType = getFileImportJobFileType;
|
|
3330
|
+
exports.getFileImportJobInfoForContainer = getFileImportJobInfoForContainer;
|
|
3319
3331
|
exports.getFileImportJobProcessURL = getFileImportJobProcessURL;
|
|
3320
3332
|
exports.getFileImportJobRecords = getFileImportJobRecords;
|
|
3321
3333
|
exports.getFileImportJobRecordsURL = getFileImportJobRecordsURL;
|