@commercetools-frontend-extensions/import-resources-modal 1.15.0 → 1.16.0

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.
@@ -549,6 +549,11 @@ var messages$5 = reactIntl.defineMessages({
549
549
  description: 'Generic notification message when file upload fails',
550
550
  defaultMessage: 'An unexpected error occurred during the file upload. Please try again, or contact support if this error occurs again.'
551
551
  },
552
+ uploadIsTakingTooLong: {
553
+ id: 'operations.import.resource.upload.uploadIsTakingTooLong',
554
+ description: 'Notification message when file upload is taking longer than expected',
555
+ defaultMessage: 'The upload took too long. Please reduce file size or split the data into smaller files.'
556
+ },
552
557
  missingRequiredField: {
553
558
  id: 'ImportResourcesModal.missingRequiredField',
554
559
  description: 'Error message displayed when a required field is missing',
@@ -1031,6 +1036,19 @@ const useUpload = () => {
1031
1036
  } else if (error.errorData?.invalid > 0) {
1032
1037
  actions.setUploadFileResponse(error.errorData);
1033
1038
  actions.setCurrentStep(CurrentStep$1.UploadResult);
1039
+ } else if (error.statusCode === 408) {
1040
+ actions.cancelImport();
1041
+ showNotification({
1042
+ kind: 'error',
1043
+ domain: constants.DOMAINS.PAGE,
1044
+ text: intl.formatMessage(messages$5.uploadIsTakingTooLong)
1045
+ });
1046
+ sentry.reportErrorToSentry(new Error('Upload File Error: The upload request timed out (408 Request Timeout)'), {
1047
+ extra: {
1048
+ resourceType: state.resourceType,
1049
+ fileSizeInBytes: state.droppedFile?.size
1050
+ }
1051
+ });
1034
1052
  } else {
1035
1053
  actions.cancelImport();
1036
1054
  showNotification({
@@ -1039,6 +1057,19 @@ const useUpload = () => {
1039
1057
  text: intl.formatMessage(messages$5.unexpectedError)
1040
1058
  });
1041
1059
  }
1060
+ } else if (error instanceof operations.PollingTimeoutError) {
1061
+ actions.cancelImport();
1062
+ showNotification({
1063
+ kind: 'error',
1064
+ domain: constants.DOMAINS.PAGE,
1065
+ text: intl.formatMessage(messages$5.uploadIsTakingTooLong)
1066
+ });
1067
+ sentry.reportErrorToSentry(error, {
1068
+ extra: {
1069
+ resourceType: state.resourceType,
1070
+ fileSizeInBytes: state.droppedFile?.size
1071
+ }
1072
+ });
1042
1073
  } else {
1043
1074
  actions.cancelImport();
1044
1075
  showNotification({
@@ -1335,9 +1366,14 @@ var messages$4 = reactIntl.defineMessages({
1335
1366
  },
1336
1367
  uploadErrorDescription: {
1337
1368
  id: 'ImportResourcesModal.uploadErrorDescription',
1338
- description: 'Title when errors detected while uploading file',
1369
+ description: 'Title when errors detected while uploading file (old flow)',
1339
1370
  defaultMessage: 'There {errorsCount, plural, one {is <b>{errorsCount}</b> error} other {are <b>{errorsCount}</b> errors}} detected while uploading the file <b>{fileName}</b>.'
1340
1371
  },
1372
+ uploadRowsErrorDescription: {
1373
+ id: 'ImportResourcesModal.uploadRowsErrorDescription',
1374
+ description: 'Title when errors detected while uploading file (new flow)',
1375
+ defaultMessage: 'Found errors in <b>{errorsCount}</b> {errorsCount, plural, one {row} other {rows}} while uploading <b>{fileName}</b>.'
1376
+ },
1341
1377
  supportedValuesDocumentation: {
1342
1378
  id: 'ImportResourcesModal.supportedValuesDocumentation',
1343
1379
  description: 'Link to the documentation for supported values',
@@ -1566,7 +1602,10 @@ const UploadErrorsModal = () => {
1566
1602
  const hasInvalidRecords = (state.uploadFileResponse?.invalid ?? 0) > 0;
1567
1603
  const isRowLevelErrors = hasInvalidRecords && (state.uploadFileResponse?.results?.length ?? 0) > 0;
1568
1604
  const isFileLevelErrors = state.fileUploadErrors.length > 0;
1569
- const errorsCount = isNewFlow ? state.uploadFileResponse?.invalid ?? 0 : isRowLevelErrors ? operations.getFileUploadErrorsCount(state.uploadFileResponse?.results) : state.fileUploadErrors.length;
1605
+
1606
+ // For new flow: use invalid rows count
1607
+ // For old flow: use individual errors count (for backwards compatibility)
1608
+ const rowsWithErrorsCount = isNewFlow ? state.uploadFileResponse?.invalid ?? 0 : isRowLevelErrors ? state.uploadFileResponse?.results?.length ?? 0 : state.fileUploadErrors.length;
1570
1609
  const documentationLink = operations.RESOURCE_TYPE_DOCUMENTATION_LINKS[state.resourceType];
1571
1610
  return jsxRuntime.jsx(applicationComponents.InfoDialog, {
1572
1611
  size: 16,
@@ -1580,10 +1619,10 @@ const UploadErrorsModal = () => {
1580
1619
  scale: "xs",
1581
1620
  children: [jsxRuntime.jsx(fullstory.Masking.Mask, {
1582
1621
  children: jsxRuntime.jsx(uiKit.Text.Body, {
1583
- intlMessage: _objectSpread$5(_objectSpread$5({}, messages$4.uploadErrorDescription), {}, {
1622
+ intlMessage: _objectSpread$5(_objectSpread$5({}, isNewFlow ? messages$4.uploadRowsErrorDescription : messages$4.uploadErrorDescription), {}, {
1584
1623
  values: {
1585
1624
  fileName: state.droppedFile?.name,
1586
- errorsCount: intl.formatNumber(errorsCount),
1625
+ errorsCount: intl.formatNumber(rowsWithErrorsCount),
1587
1626
  b: getBold$2
1588
1627
  }
1589
1628
  })
@@ -549,6 +549,11 @@ var messages$5 = reactIntl.defineMessages({
549
549
  description: 'Generic notification message when file upload fails',
550
550
  defaultMessage: 'An unexpected error occurred during the file upload. Please try again, or contact support if this error occurs again.'
551
551
  },
552
+ uploadIsTakingTooLong: {
553
+ id: 'operations.import.resource.upload.uploadIsTakingTooLong',
554
+ description: 'Notification message when file upload is taking longer than expected',
555
+ defaultMessage: 'The upload took too long. Please reduce file size or split the data into smaller files.'
556
+ },
552
557
  missingRequiredField: {
553
558
  id: 'ImportResourcesModal.missingRequiredField',
554
559
  description: 'Error message displayed when a required field is missing',
@@ -1031,6 +1036,19 @@ const useUpload = () => {
1031
1036
  } else if (error.errorData?.invalid > 0) {
1032
1037
  actions.setUploadFileResponse(error.errorData);
1033
1038
  actions.setCurrentStep(CurrentStep$1.UploadResult);
1039
+ } else if (error.statusCode === 408) {
1040
+ actions.cancelImport();
1041
+ showNotification({
1042
+ kind: 'error',
1043
+ domain: constants.DOMAINS.PAGE,
1044
+ text: intl.formatMessage(messages$5.uploadIsTakingTooLong)
1045
+ });
1046
+ sentry.reportErrorToSentry(new Error('Upload File Error: The upload request timed out (408 Request Timeout)'), {
1047
+ extra: {
1048
+ resourceType: state.resourceType,
1049
+ fileSizeInBytes: state.droppedFile?.size
1050
+ }
1051
+ });
1034
1052
  } else {
1035
1053
  actions.cancelImport();
1036
1054
  showNotification({
@@ -1039,6 +1057,19 @@ const useUpload = () => {
1039
1057
  text: intl.formatMessage(messages$5.unexpectedError)
1040
1058
  });
1041
1059
  }
1060
+ } else if (error instanceof operations.PollingTimeoutError) {
1061
+ actions.cancelImport();
1062
+ showNotification({
1063
+ kind: 'error',
1064
+ domain: constants.DOMAINS.PAGE,
1065
+ text: intl.formatMessage(messages$5.uploadIsTakingTooLong)
1066
+ });
1067
+ sentry.reportErrorToSentry(error, {
1068
+ extra: {
1069
+ resourceType: state.resourceType,
1070
+ fileSizeInBytes: state.droppedFile?.size
1071
+ }
1072
+ });
1042
1073
  } else {
1043
1074
  actions.cancelImport();
1044
1075
  showNotification({
@@ -1335,9 +1366,14 @@ var messages$4 = reactIntl.defineMessages({
1335
1366
  },
1336
1367
  uploadErrorDescription: {
1337
1368
  id: 'ImportResourcesModal.uploadErrorDescription',
1338
- description: 'Title when errors detected while uploading file',
1369
+ description: 'Title when errors detected while uploading file (old flow)',
1339
1370
  defaultMessage: 'There {errorsCount, plural, one {is <b>{errorsCount}</b> error} other {are <b>{errorsCount}</b> errors}} detected while uploading the file <b>{fileName}</b>.'
1340
1371
  },
1372
+ uploadRowsErrorDescription: {
1373
+ id: 'ImportResourcesModal.uploadRowsErrorDescription',
1374
+ description: 'Title when errors detected while uploading file (new flow)',
1375
+ defaultMessage: 'Found errors in <b>{errorsCount}</b> {errorsCount, plural, one {row} other {rows}} while uploading <b>{fileName}</b>.'
1376
+ },
1341
1377
  supportedValuesDocumentation: {
1342
1378
  id: 'ImportResourcesModal.supportedValuesDocumentation',
1343
1379
  description: 'Link to the documentation for supported values',
@@ -1566,7 +1602,10 @@ const UploadErrorsModal = () => {
1566
1602
  const hasInvalidRecords = (state.uploadFileResponse?.invalid ?? 0) > 0;
1567
1603
  const isRowLevelErrors = hasInvalidRecords && (state.uploadFileResponse?.results?.length ?? 0) > 0;
1568
1604
  const isFileLevelErrors = state.fileUploadErrors.length > 0;
1569
- const errorsCount = isNewFlow ? state.uploadFileResponse?.invalid ?? 0 : isRowLevelErrors ? operations.getFileUploadErrorsCount(state.uploadFileResponse?.results) : state.fileUploadErrors.length;
1605
+
1606
+ // For new flow: use invalid rows count
1607
+ // For old flow: use individual errors count (for backwards compatibility)
1608
+ const rowsWithErrorsCount = isNewFlow ? state.uploadFileResponse?.invalid ?? 0 : isRowLevelErrors ? state.uploadFileResponse?.results?.length ?? 0 : state.fileUploadErrors.length;
1570
1609
  const documentationLink = operations.RESOURCE_TYPE_DOCUMENTATION_LINKS[state.resourceType];
1571
1610
  return jsxRuntime.jsx(applicationComponents.InfoDialog, {
1572
1611
  size: 16,
@@ -1580,10 +1619,10 @@ const UploadErrorsModal = () => {
1580
1619
  scale: "xs",
1581
1620
  children: [jsxRuntime.jsx(fullstory.Masking.Mask, {
1582
1621
  children: jsxRuntime.jsx(uiKit.Text.Body, {
1583
- intlMessage: _objectSpread$5(_objectSpread$5({}, messages$4.uploadErrorDescription), {}, {
1622
+ intlMessage: _objectSpread$5(_objectSpread$5({}, isNewFlow ? messages$4.uploadRowsErrorDescription : messages$4.uploadErrorDescription), {}, {
1584
1623
  values: {
1585
1624
  fileName: state.droppedFile?.name,
1586
- errorsCount: intl.formatNumber(errorsCount),
1625
+ errorsCount: intl.formatNumber(rowsWithErrorsCount),
1587
1626
  b: getBold$2
1588
1627
  }
1589
1628
  })
@@ -10,7 +10,7 @@ import _defineProperty from '@babel/runtime-corejs3/helpers/esm/defineProperty';
10
10
  import _everyInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/every';
11
11
  import { defineMessages, useIntl, FormattedMessage, IntlProvider } from 'react-intl';
12
12
  import { useApplicationContext } from '@commercetools-frontend/application-shell-connectors';
13
- import { deleteImportContainer, FileDroppedArea, DisabledDropArea, EnabledDropArea, ActiveDragDropArea, COLUMN_DELIMITERS, useFileUpload, validateDelimiter, getRowCount, toBytes, isAbortError, HttpError, formatKeys, isError, IMPORT_MAX_FILE_SIZE_MB, IMPORT_LEGACY_MAX_FILE_SIZE_MB, IMPORT_MAX_ITEM_COUNT, IMPORT_LEGACY_MAX_ROW_COUNT, assertResourceType, FileDropArea as FileDropArea$1, InfoBox, CT_API_DOCS_URL, UploadSeparator, UploadSettings, useFetchFileImportJobRecords, mapUploadFileErrorsResponseToUploadFileErrorRows, UnexpectedColumnError, extractErrorDescriptionFromValidationMessage, formatErrorCode, getFileUploadErrorsCount, RESOURCE_TYPE_DOCUMENTATION_LINKS, mapFileUploadErrorsToUploadFileErrorRows, getValidatedColumns, processFileImportJob, processUploadedFile, UploadingModal, UnexpectedResourceTypeError as UnexpectedResourceTypeError$1, RESOURCE_TYPE_TEMPLATE_DOWNLOAD_LINKS, isResourceType } from '@commercetools-frontend-extensions/operations';
13
+ import { deleteImportContainer, FileDroppedArea, DisabledDropArea, EnabledDropArea, ActiveDragDropArea, COLUMN_DELIMITERS, useFileUpload, validateDelimiter, getRowCount, toBytes, isAbortError, HttpError, formatKeys, PollingTimeoutError, isError, IMPORT_MAX_FILE_SIZE_MB, IMPORT_LEGACY_MAX_FILE_SIZE_MB, IMPORT_MAX_ITEM_COUNT, IMPORT_LEGACY_MAX_ROW_COUNT, assertResourceType, FileDropArea as FileDropArea$1, InfoBox, CT_API_DOCS_URL, UploadSeparator, UploadSettings, useFetchFileImportJobRecords, mapUploadFileErrorsResponseToUploadFileErrorRows, UnexpectedColumnError, extractErrorDescriptionFromValidationMessage, formatErrorCode, RESOURCE_TYPE_DOCUMENTATION_LINKS, mapFileUploadErrorsToUploadFileErrorRows, getValidatedColumns, processFileImportJob, processUploadedFile, UploadingModal, UnexpectedResourceTypeError as UnexpectedResourceTypeError$1, RESOURCE_TYPE_TEMPLATE_DOWNLOAD_LINKS, isResourceType } from '@commercetools-frontend-extensions/operations';
14
14
  import _slicedToArray from '@babel/runtime-corejs3/helpers/esm/slicedToArray';
15
15
  import React, { useContext, useMemo, useState, useEffect } from 'react';
16
16
  import { jsx, jsxs, Fragment } from '@emotion/react/jsx-runtime';
@@ -528,6 +528,11 @@ var messages$5 = defineMessages({
528
528
  description: 'Generic notification message when file upload fails',
529
529
  defaultMessage: 'An unexpected error occurred during the file upload. Please try again, or contact support if this error occurs again.'
530
530
  },
531
+ uploadIsTakingTooLong: {
532
+ id: 'operations.import.resource.upload.uploadIsTakingTooLong',
533
+ description: 'Notification message when file upload is taking longer than expected',
534
+ defaultMessage: 'The upload took too long. Please reduce file size or split the data into smaller files.'
535
+ },
531
536
  missingRequiredField: {
532
537
  id: 'ImportResourcesModal.missingRequiredField',
533
538
  description: 'Error message displayed when a required field is missing',
@@ -1010,6 +1015,19 @@ const useUpload = () => {
1010
1015
  } else if (error.errorData?.invalid > 0) {
1011
1016
  actions.setUploadFileResponse(error.errorData);
1012
1017
  actions.setCurrentStep(CurrentStep$1.UploadResult);
1018
+ } else if (error.statusCode === 408) {
1019
+ actions.cancelImport();
1020
+ showNotification({
1021
+ kind: 'error',
1022
+ domain: DOMAINS.PAGE,
1023
+ text: intl.formatMessage(messages$5.uploadIsTakingTooLong)
1024
+ });
1025
+ reportErrorToSentry(new Error('Upload File Error: The upload request timed out (408 Request Timeout)'), {
1026
+ extra: {
1027
+ resourceType: state.resourceType,
1028
+ fileSizeInBytes: state.droppedFile?.size
1029
+ }
1030
+ });
1013
1031
  } else {
1014
1032
  actions.cancelImport();
1015
1033
  showNotification({
@@ -1018,6 +1036,19 @@ const useUpload = () => {
1018
1036
  text: intl.formatMessage(messages$5.unexpectedError)
1019
1037
  });
1020
1038
  }
1039
+ } else if (error instanceof PollingTimeoutError) {
1040
+ actions.cancelImport();
1041
+ showNotification({
1042
+ kind: 'error',
1043
+ domain: DOMAINS.PAGE,
1044
+ text: intl.formatMessage(messages$5.uploadIsTakingTooLong)
1045
+ });
1046
+ reportErrorToSentry(error, {
1047
+ extra: {
1048
+ resourceType: state.resourceType,
1049
+ fileSizeInBytes: state.droppedFile?.size
1050
+ }
1051
+ });
1021
1052
  } else {
1022
1053
  actions.cancelImport();
1023
1054
  showNotification({
@@ -1314,9 +1345,14 @@ var messages$4 = defineMessages({
1314
1345
  },
1315
1346
  uploadErrorDescription: {
1316
1347
  id: 'ImportResourcesModal.uploadErrorDescription',
1317
- description: 'Title when errors detected while uploading file',
1348
+ description: 'Title when errors detected while uploading file (old flow)',
1318
1349
  defaultMessage: 'There {errorsCount, plural, one {is <b>{errorsCount}</b> error} other {are <b>{errorsCount}</b> errors}} detected while uploading the file <b>{fileName}</b>.'
1319
1350
  },
1351
+ uploadRowsErrorDescription: {
1352
+ id: 'ImportResourcesModal.uploadRowsErrorDescription',
1353
+ description: 'Title when errors detected while uploading file (new flow)',
1354
+ defaultMessage: 'Found errors in <b>{errorsCount}</b> {errorsCount, plural, one {row} other {rows}} while uploading <b>{fileName}</b>.'
1355
+ },
1320
1356
  supportedValuesDocumentation: {
1321
1357
  id: 'ImportResourcesModal.supportedValuesDocumentation',
1322
1358
  description: 'Link to the documentation for supported values',
@@ -1545,7 +1581,10 @@ const UploadErrorsModal = () => {
1545
1581
  const hasInvalidRecords = (state.uploadFileResponse?.invalid ?? 0) > 0;
1546
1582
  const isRowLevelErrors = hasInvalidRecords && (state.uploadFileResponse?.results?.length ?? 0) > 0;
1547
1583
  const isFileLevelErrors = state.fileUploadErrors.length > 0;
1548
- const errorsCount = isNewFlow ? state.uploadFileResponse?.invalid ?? 0 : isRowLevelErrors ? getFileUploadErrorsCount(state.uploadFileResponse?.results) : state.fileUploadErrors.length;
1584
+
1585
+ // For new flow: use invalid rows count
1586
+ // For old flow: use individual errors count (for backwards compatibility)
1587
+ const rowsWithErrorsCount = isNewFlow ? state.uploadFileResponse?.invalid ?? 0 : isRowLevelErrors ? state.uploadFileResponse?.results?.length ?? 0 : state.fileUploadErrors.length;
1549
1588
  const documentationLink = RESOURCE_TYPE_DOCUMENTATION_LINKS[state.resourceType];
1550
1589
  return jsx(InfoDialog, {
1551
1590
  size: 16,
@@ -1559,10 +1598,10 @@ const UploadErrorsModal = () => {
1559
1598
  scale: "xs",
1560
1599
  children: [jsx(Masking.Mask, {
1561
1600
  children: jsx(Text.Body, {
1562
- intlMessage: _objectSpread$5(_objectSpread$5({}, messages$4.uploadErrorDescription), {}, {
1601
+ intlMessage: _objectSpread$5(_objectSpread$5({}, isNewFlow ? messages$4.uploadRowsErrorDescription : messages$4.uploadErrorDescription), {}, {
1563
1602
  values: {
1564
1603
  fileName: state.droppedFile?.name,
1565
- errorsCount: intl.formatNumber(errorsCount),
1604
+ errorsCount: intl.formatNumber(rowsWithErrorsCount),
1566
1605
  b: getBold$2
1567
1606
  }
1568
1607
  })
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@commercetools-frontend-extensions/import-resources-modal",
3
3
  "description": "Shared import modal for importing resources",
4
- "version": "1.15.0",
4
+ "version": "1.16.0",
5
5
  "license": "BSD-3-Clause",
6
6
  "publishConfig": {
7
7
  "access": "public"
@@ -23,7 +23,7 @@
23
23
  "@formatjs/cli": "6.7.4",
24
24
  "babel-plugin-module-resolver": "^5.0.2",
25
25
  "jest": "30.2.0",
26
- "lodash": "4.17.21",
26
+ "lodash": "4.17.23",
27
27
  "lodash.truncate": "4.4.2",
28
28
  "moment": "2.30.1",
29
29
  "omit-empty-es": "^1.1.3",
@@ -31,7 +31,7 @@
31
31
  "pluralize": "8.0.0",
32
32
  "prop-types": "15.8.1",
33
33
  "ramda": "^0.32.0",
34
- "@commercetools-frontend-extensions/operations": "3.3.0"
34
+ "@commercetools-frontend-extensions/operations": "3.5.0"
35
35
  },
36
36
  "devDependencies": {
37
37
  "@commercetools-frontend/actions-global": "25.1.0",