@commercetools-frontend-extensions/operations 0.0.0-canary-20251209161906
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 +61 -0
- package/README.md +178 -0
- package/babel.config.js +6 -0
- package/dist/commercetools-frontend-extensions-operations.cjs.d.ts +2 -0
- package/dist/commercetools-frontend-extensions-operations.cjs.dev.js +3273 -0
- package/dist/commercetools-frontend-extensions-operations.cjs.js +7 -0
- package/dist/commercetools-frontend-extensions-operations.cjs.prod.js +3265 -0
- package/dist/commercetools-frontend-extensions-operations.esm.js +3074 -0
- package/dist/declarations/src/@api/export-operations.d.ts +5 -0
- package/dist/declarations/src/@api/fetcher.d.ts +17 -0
- package/dist/declarations/src/@api/file-import-jobs.d.ts +7 -0
- package/dist/declarations/src/@api/file-upload.d.ts +3 -0
- package/dist/declarations/src/@api/import-containers.d.ts +35 -0
- package/dist/declarations/src/@api/import-operations.d.ts +6 -0
- package/dist/declarations/src/@api/index.d.ts +9 -0
- package/dist/declarations/src/@api/process-file.d.ts +3 -0
- package/dist/declarations/src/@api/test-fixtures.d.ts +279 -0
- package/dist/declarations/src/@api/urls.d.ts +74 -0
- package/dist/declarations/src/@components/file-drop-area/active-drag-drop-area.d.ts +10 -0
- package/dist/declarations/src/@components/file-drop-area/disabled-drop-area.d.ts +5 -0
- package/dist/declarations/src/@components/file-drop-area/drop-area-wrapper.d.ts +11 -0
- package/dist/declarations/src/@components/file-drop-area/enabled-drop-area.d.ts +7 -0
- package/dist/declarations/src/@components/file-drop-area/file-drop-area.d.ts +14 -0
- package/dist/declarations/src/@components/file-drop-area/file-dropped-area.d.ts +6 -0
- package/dist/declarations/src/@components/file-drop-area/index.d.ts +7 -0
- package/dist/declarations/src/@components/file-drop-area/styles.d.ts +9 -0
- package/dist/declarations/src/@components/icons/file-icon.d.ts +2 -0
- package/dist/declarations/src/@components/icons/index.d.ts +2 -0
- package/dist/declarations/src/@components/icons/lock-icon.d.ts +2 -0
- package/dist/declarations/src/@components/index.d.ts +6 -0
- package/dist/declarations/src/@components/info-box/index.d.ts +1 -0
- package/dist/declarations/src/@components/info-box/info-box.d.ts +7 -0
- package/dist/declarations/src/@components/upload-separator/index.d.ts +1 -0
- package/dist/declarations/src/@components/upload-separator/upload-separator.d.ts +12 -0
- package/dist/declarations/src/@components/upload-settings/index.d.ts +1 -0
- package/dist/declarations/src/@components/upload-settings/upload-settings.d.ts +11 -0
- package/dist/declarations/src/@components/uploading-modal/index.d.ts +1 -0
- package/dist/declarations/src/@components/uploading-modal/uploading-modal.d.ts +13 -0
- package/dist/declarations/src/@constants/delimiters.d.ts +8 -0
- package/dist/declarations/src/@constants/file-import-job.d.ts +1 -0
- package/dist/declarations/src/@constants/import-limits.d.ts +6 -0
- package/dist/declarations/src/@constants/import-tags.d.ts +7 -0
- package/dist/declarations/src/@constants/index.d.ts +5 -0
- package/dist/declarations/src/@constants/resource-links.d.ts +10 -0
- package/dist/declarations/src/@errors/http-error.d.ts +6 -0
- package/dist/declarations/src/@errors/index.d.ts +9 -0
- package/dist/declarations/src/@errors/invalid-response-error.d.ts +3 -0
- package/dist/declarations/src/@errors/no-resources-to-export-error.d.ts +3 -0
- package/dist/declarations/src/@errors/polling-aborted-error.d.ts +3 -0
- package/dist/declarations/src/@errors/project-key-not-available-error.d.ts +3 -0
- package/dist/declarations/src/@errors/query-predicate-error.d.ts +4 -0
- package/dist/declarations/src/@errors/unexpected-column-error.d.ts +3 -0
- package/dist/declarations/src/@errors/unexpected-operation-state-error.d.ts +4 -0
- package/dist/declarations/src/@errors/unexpected-resource-type-error.d.ts +3 -0
- package/dist/declarations/src/@hooks/index.d.ts +8 -0
- package/dist/declarations/src/@hooks/use-fetch-export-operations.d.ts +15 -0
- package/dist/declarations/src/@hooks/use-fetch-file-import-job.d.ts +17 -0
- package/dist/declarations/src/@hooks/use-fetch-import-container-details.d.ts +15 -0
- package/dist/declarations/src/@hooks/use-fetch-import-operations.d.ts +16 -0
- package/dist/declarations/src/@hooks/use-fetch-import-summaries.d.ts +20 -0
- package/dist/declarations/src/@hooks/use-file-import-job-upload.d.ts +18 -0
- package/dist/declarations/src/@hooks/use-file-upload.d.ts +28 -0
- package/dist/declarations/src/@hooks/use-import-container-upload.d.ts +19 -0
- package/dist/declarations/src/@types/api.d.ts +13 -0
- package/dist/declarations/src/@types/basic-error-data-type.d.ts +5 -0
- package/dist/declarations/src/@types/export-operation.d.ts +97 -0
- package/dist/declarations/src/@types/file-import-job.d.ts +99 -0
- package/dist/declarations/src/@types/file-upload-result.d.ts +21 -0
- package/dist/declarations/src/@types/file-upload.d.ts +63 -0
- package/dist/declarations/src/@types/import-container.d.ts +53 -0
- package/dist/declarations/src/@types/import-operation.d.ts +13 -0
- package/dist/declarations/src/@types/import-states.d.ts +9 -0
- package/dist/declarations/src/@types/import-summary.d.ts +15 -0
- package/dist/declarations/src/@types/index.d.ts +11 -0
- package/dist/declarations/src/@types/shared.d.ts +7 -0
- package/dist/declarations/src/@utils/error-mapping.d.ts +19 -0
- package/dist/declarations/src/@utils/file-import-job-helpers.d.ts +12 -0
- package/dist/declarations/src/@utils/file-upload.d.ts +54 -0
- package/dist/declarations/src/@utils/form.d.ts +1 -0
- package/dist/declarations/src/@utils/format.d.ts +5 -0
- package/dist/declarations/src/@utils/import-container.d.ts +8 -0
- package/dist/declarations/src/@utils/index.d.ts +8 -0
- package/dist/declarations/src/@utils/poll-job-until-validated.d.ts +11 -0
- package/dist/declarations/src/@utils/url.d.ts +6 -0
- package/dist/declarations/src/index.d.ts +26 -0
- package/index.js +1 -0
- package/jest.test.config.js +11 -0
- package/package.json +62 -0
- package/src/@api/export-operations.ts +26 -0
- package/src/@api/fetcher.spec.ts +51 -0
- package/src/@api/fetcher.ts +137 -0
- package/src/@api/file-import-jobs.ts +217 -0
- package/src/@api/file-upload.spec.ts +85 -0
- package/src/@api/file-upload.ts +46 -0
- package/src/@api/import-containers.ts +256 -0
- package/src/@api/import-operations.ts +33 -0
- package/src/@api/index.ts +9 -0
- package/src/@api/process-file.spec.ts +74 -0
- package/src/@api/process-file.ts +53 -0
- package/src/@api/test-fixtures.ts +894 -0
- package/src/@api/urls.ts +194 -0
- package/src/@components/file-drop-area/active-drag-drop-area.tsx +33 -0
- package/src/@components/file-drop-area/disabled-drop-area.tsx +17 -0
- package/src/@components/file-drop-area/drop-area-wrapper.tsx +38 -0
- package/src/@components/file-drop-area/enabled-drop-area.tsx +27 -0
- package/src/@components/file-drop-area/file-drop-area.tsx +74 -0
- package/src/@components/file-drop-area/file-dropped-area.tsx +29 -0
- package/src/@components/file-drop-area/index.ts +7 -0
- package/src/@components/file-drop-area/styles.ts +67 -0
- package/src/@components/icons/file-icon.tsx +30 -0
- package/src/@components/icons/index.ts +2 -0
- package/src/@components/icons/lock-icon.tsx +34 -0
- package/src/@components/index.ts +6 -0
- package/src/@components/info-box/index.ts +1 -0
- package/src/@components/info-box/info-box.tsx +23 -0
- package/src/@components/upload-separator/index.ts +1 -0
- package/src/@components/upload-separator/upload-separator.tsx +61 -0
- package/src/@components/upload-settings/index.ts +1 -0
- package/src/@components/upload-settings/upload-settings.tsx +36 -0
- package/src/@components/uploading-modal/index.ts +1 -0
- package/src/@components/uploading-modal/uploading-modal.tsx +66 -0
- package/src/@constants/delimiters.ts +14 -0
- package/src/@constants/file-import-job.ts +1 -0
- package/src/@constants/import-limits.ts +13 -0
- package/src/@constants/import-tags.ts +9 -0
- package/src/@constants/index.ts +5 -0
- package/src/@constants/resource-links.ts +61 -0
- package/src/@errors/http-error.ts +17 -0
- package/src/@errors/index.ts +9 -0
- package/src/@errors/invalid-response-error.ts +6 -0
- package/src/@errors/no-resources-to-export-error.ts +6 -0
- package/src/@errors/polling-aborted-error.ts +6 -0
- package/src/@errors/project-key-not-available-error.ts +6 -0
- package/src/@errors/query-predicate-error.ts +10 -0
- package/src/@errors/unexpected-column-error.ts +6 -0
- package/src/@errors/unexpected-operation-state-error.ts +8 -0
- package/src/@errors/unexpected-resource-type-error.ts +6 -0
- package/src/@hooks/index.ts +8 -0
- package/src/@hooks/use-fetch-export-operations.ts +34 -0
- package/src/@hooks/use-fetch-file-import-job.spec.ts +131 -0
- package/src/@hooks/use-fetch-file-import-job.ts +38 -0
- package/src/@hooks/use-fetch-import-container-details.ts +31 -0
- package/src/@hooks/use-fetch-import-operations.ts +42 -0
- package/src/@hooks/use-fetch-import-summaries.ts +47 -0
- package/src/@hooks/use-fetch.spec.ts +68 -0
- package/src/@hooks/use-fetch.ts +76 -0
- package/src/@hooks/use-file-import-job-upload.spec.ts +273 -0
- package/src/@hooks/use-file-import-job-upload.ts +101 -0
- package/src/@hooks/use-file-upload.ts +223 -0
- package/src/@hooks/use-import-container-upload.spec.ts +297 -0
- package/src/@hooks/use-import-container-upload.ts +130 -0
- package/src/@types/api.ts +14 -0
- package/src/@types/basic-error-data-type.ts +5 -0
- package/src/@types/export-operation.ts +147 -0
- package/src/@types/file-import-job.ts +165 -0
- package/src/@types/file-upload-result.ts +23 -0
- package/src/@types/file-upload.ts +81 -0
- package/src/@types/import-container.ts +104 -0
- package/src/@types/import-operation.ts +31 -0
- package/src/@types/import-states.ts +9 -0
- package/src/@types/import-summary.ts +22 -0
- package/src/@types/index.ts +11 -0
- package/src/@types/shared.ts +52 -0
- package/src/@utils/error-mapping.spec.ts +126 -0
- package/src/@utils/error-mapping.ts +40 -0
- package/src/@utils/file-import-job-helpers.spec.ts +147 -0
- package/src/@utils/file-import-job-helpers.ts +47 -0
- package/src/@utils/file-upload.spec.ts +151 -0
- package/src/@utils/file-upload.ts +189 -0
- package/src/@utils/form.ts +20 -0
- package/src/@utils/format.spec.ts +62 -0
- package/src/@utils/format.ts +53 -0
- package/src/@utils/import-container.spec.ts +26 -0
- package/src/@utils/import-container.ts +34 -0
- package/src/@utils/index.ts +8 -0
- package/src/@utils/poll-job-until-validated.ts +76 -0
- package/src/@utils/url.spec.ts +75 -0
- package/src/@utils/url.ts +18 -0
- package/src/index.ts +27 -0
- package/tsconfig.json +9 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { ResourceTypeId } from '@commercetools/importapi-sdk'
|
|
2
|
+
import { CheckboxInput } from '@commercetools-frontend/ui-kit'
|
|
3
|
+
|
|
4
|
+
type UploadSettingsProps = {
|
|
5
|
+
resourceType?: ResourceTypeId
|
|
6
|
+
isPublishChecked?: boolean
|
|
7
|
+
onPublishChange: (checked: boolean) => void
|
|
8
|
+
publishProductsLabel: string
|
|
9
|
+
dataTrackingTarget: string
|
|
10
|
+
canPublishProducts?: boolean
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const UploadSettings = ({
|
|
14
|
+
resourceType,
|
|
15
|
+
isPublishChecked,
|
|
16
|
+
onPublishChange,
|
|
17
|
+
publishProductsLabel,
|
|
18
|
+
dataTrackingTarget,
|
|
19
|
+
canPublishProducts,
|
|
20
|
+
}: UploadSettingsProps) => {
|
|
21
|
+
if (resourceType !== 'product' || !canPublishProducts) {
|
|
22
|
+
return null
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<CheckboxInput
|
|
27
|
+
data-tracking-target={dataTrackingTarget}
|
|
28
|
+
isChecked={isPublishChecked}
|
|
29
|
+
onChange={(e) => {
|
|
30
|
+
onPublishChange(e.target.checked)
|
|
31
|
+
}}
|
|
32
|
+
>
|
|
33
|
+
{publishProductsLabel}
|
|
34
|
+
</CheckboxInput>
|
|
35
|
+
)
|
|
36
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './uploading-modal'
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { InfoDialog } from '@commercetools-frontend/application-components'
|
|
2
|
+
import {
|
|
3
|
+
Constraints,
|
|
4
|
+
ProgressBar,
|
|
5
|
+
SecondaryButton,
|
|
6
|
+
Spacings,
|
|
7
|
+
Text,
|
|
8
|
+
} from '@commercetools-frontend/ui-kit'
|
|
9
|
+
import { convertFileSizeToKB } from '../../@utils'
|
|
10
|
+
import { FileIcon } from '../icons/file-icon'
|
|
11
|
+
|
|
12
|
+
type UploadingModalProps = {
|
|
13
|
+
isOpen: boolean
|
|
14
|
+
title: string
|
|
15
|
+
fileName: string
|
|
16
|
+
fileSize: number
|
|
17
|
+
progress?: number
|
|
18
|
+
cancelLabel: string
|
|
19
|
+
onCancel: () => void
|
|
20
|
+
onClose: () => void
|
|
21
|
+
statusMessage?: string
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const UploadingModal = ({
|
|
25
|
+
isOpen,
|
|
26
|
+
title,
|
|
27
|
+
fileName,
|
|
28
|
+
fileSize,
|
|
29
|
+
progress,
|
|
30
|
+
cancelLabel,
|
|
31
|
+
onCancel,
|
|
32
|
+
onClose,
|
|
33
|
+
statusMessage,
|
|
34
|
+
}: UploadingModalProps) => {
|
|
35
|
+
return (
|
|
36
|
+
<InfoDialog size={16} isOpen={isOpen} title={title} onClose={onClose}>
|
|
37
|
+
<Spacings.Stack scale="m">
|
|
38
|
+
<Spacings.Inline alignItems="center" justifyContent="space-between">
|
|
39
|
+
<Spacings.Inline alignItems="center">
|
|
40
|
+
<FileIcon />
|
|
41
|
+
<Spacings.Inline>
|
|
42
|
+
<Constraints.Horizontal max={10}>
|
|
43
|
+
<Text.Body truncate isBold>
|
|
44
|
+
{fileName}
|
|
45
|
+
</Text.Body>
|
|
46
|
+
</Constraints.Horizontal>
|
|
47
|
+
</Spacings.Inline>
|
|
48
|
+
<Text.Body tone="secondary">
|
|
49
|
+
({convertFileSizeToKB(fileSize).toLocaleString()} KB)
|
|
50
|
+
</Text.Body>
|
|
51
|
+
</Spacings.Inline>
|
|
52
|
+
<SecondaryButton
|
|
53
|
+
tone="secondary"
|
|
54
|
+
size="medium"
|
|
55
|
+
label={cancelLabel}
|
|
56
|
+
onClick={onCancel}
|
|
57
|
+
/>
|
|
58
|
+
</Spacings.Inline>
|
|
59
|
+
<ProgressBar barWidth="scale" height="10" progress={progress} />
|
|
60
|
+
{statusMessage && (
|
|
61
|
+
<Text.Detail tone="tertiary">{statusMessage}</Text.Detail>
|
|
62
|
+
)}
|
|
63
|
+
</Spacings.Stack>
|
|
64
|
+
</InfoDialog>
|
|
65
|
+
)
|
|
66
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const FILE_IMPORT_JOB_POLLING_INTERVAL = 2000
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export const IMPORT_MAX_FILE_SIZE_MB = 200
|
|
2
|
+
|
|
3
|
+
export const IMPORT_MAX_ITEM_COUNT = 500_000
|
|
4
|
+
|
|
5
|
+
// =============================================================================
|
|
6
|
+
// Legacy constants (old flow) - Remove after testing and migration is complete
|
|
7
|
+
// =============================================================================
|
|
8
|
+
|
|
9
|
+
/** @deprecated Use IMPORT_MAX_FILE_SIZE_MB instead. Remove after migration. */
|
|
10
|
+
export const IMPORT_LEGACY_MAX_FILE_SIZE_MB = 35
|
|
11
|
+
|
|
12
|
+
/** @deprecated Use IMPORT_MAX_ITEM_COUNT instead. Remove after migration. */
|
|
13
|
+
export const IMPORT_LEGACY_MAX_ROW_COUNT = 80_000
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { ResourceTypeId } from '@commercetools/importapi-sdk'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* CommerceTools API documentation base URL
|
|
5
|
+
*/
|
|
6
|
+
export const CT_API_DOCS_URL = 'https://docs.commercetools.com/api/'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Template download links for each resource type
|
|
10
|
+
*/
|
|
11
|
+
export const RESOURCE_TYPE_TEMPLATE_DOWNLOAD_LINKS: Record<
|
|
12
|
+
ResourceTypeId,
|
|
13
|
+
string
|
|
14
|
+
> = {
|
|
15
|
+
category:
|
|
16
|
+
'https://docs.commercetools.com/merchant-center/downloads/category_import_template.csv',
|
|
17
|
+
'custom-object':
|
|
18
|
+
'https://docs.commercetools.com/merchant-center/downloads/custom_object_import_template.json',
|
|
19
|
+
product:
|
|
20
|
+
'https://docs.commercetools.com/merchant-center/import-data#download-a-template',
|
|
21
|
+
'inventory-entry':
|
|
22
|
+
'https://docs.commercetools.com/merchant-center/downloads/inventory_entry_import_template.csv',
|
|
23
|
+
// TODO: remove `inventory` after aligning the resource type names in the Import API and Export API
|
|
24
|
+
inventory:
|
|
25
|
+
'https://docs.commercetools.com/merchant-center/downloads/inventory_entry_import_template.csv',
|
|
26
|
+
'discount-code':
|
|
27
|
+
'https://docs.commercetools.com/merchant-center/downloads/discount_code_import_template.csv',
|
|
28
|
+
customer:
|
|
29
|
+
'https://docs.commercetools.com/merchant-center/import-data#download-a-template',
|
|
30
|
+
order:
|
|
31
|
+
'https://docs.commercetools.com/merchant-center/import-data#download-a-template',
|
|
32
|
+
'product-type':
|
|
33
|
+
'https://docs.commercetools.com/merchant-center/downloads/product_type_import_template.csv',
|
|
34
|
+
'business-unit':
|
|
35
|
+
'https://docs.commercetools.com/merchant-center/downloads/business_unit_import_template.csv',
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export const RESOURCE_TYPE_DOCUMENTATION_LINKS: Record<ResourceTypeId, string> =
|
|
39
|
+
{
|
|
40
|
+
category:
|
|
41
|
+
'https://docs.commercetools.com/merchant-center/import-categories#supported-headers-and-values',
|
|
42
|
+
'custom-object':
|
|
43
|
+
'https://docs.commercetools.com/merchant-center/import-custom-objects#supported-fields-and-values',
|
|
44
|
+
product:
|
|
45
|
+
'https://docs.commercetools.com/merchant-center/import-products#supported-headers-and-values',
|
|
46
|
+
'inventory-entry':
|
|
47
|
+
'https://docs.commercetools.com/merchant-center/import-inventory#supported-headers-and-values',
|
|
48
|
+
// TODO: remove `inventory` after aligning the resource type names in the Import API and Export API
|
|
49
|
+
inventory:
|
|
50
|
+
'https://docs.commercetools.com/merchant-center/import-inventory#supported-headers-and-values',
|
|
51
|
+
'discount-code':
|
|
52
|
+
'https://docs.commercetools.com/merchant-center/import-discount-codes#supported-headers-and-values',
|
|
53
|
+
customer:
|
|
54
|
+
'https://docs.commercetools.com/merchant-center/import-customers#supported-headers-and-values',
|
|
55
|
+
order:
|
|
56
|
+
'https://docs.commercetools.com/merchant-center/import-orders#supported-headers-and-values',
|
|
57
|
+
'product-type':
|
|
58
|
+
'https://docs.commercetools.com/merchant-center/import-product-types#supported-headers-and-values',
|
|
59
|
+
'business-unit':
|
|
60
|
+
'https://docs.commercetools.com/merchant-center/import-business-units#supported-headers-and-values',
|
|
61
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { BasicErrorDataType } from '../@types'
|
|
2
|
+
|
|
3
|
+
export class HttpError<T = BasicErrorDataType> extends Error {
|
|
4
|
+
readonly statusCode: number
|
|
5
|
+
readonly errorData?: T
|
|
6
|
+
|
|
7
|
+
constructor(statusCode: number, statusText?: string, errorData?: T) {
|
|
8
|
+
super(
|
|
9
|
+
`HTTP Error! Status code: ${statusCode}, message: "${
|
|
10
|
+
statusText ? statusText : ''
|
|
11
|
+
}"`
|
|
12
|
+
)
|
|
13
|
+
this.name = 'HttpError'
|
|
14
|
+
this.statusCode = statusCode
|
|
15
|
+
this.errorData = errorData
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from './http-error'
|
|
2
|
+
export * from './invalid-response-error'
|
|
3
|
+
export * from './no-resources-to-export-error'
|
|
4
|
+
export * from './polling-aborted-error'
|
|
5
|
+
export * from './project-key-not-available-error'
|
|
6
|
+
export * from './query-predicate-error'
|
|
7
|
+
export * from './unexpected-column-error'
|
|
8
|
+
export * from './unexpected-operation-state-error'
|
|
9
|
+
export * from './unexpected-resource-type-error'
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ProcessingState } from '@commercetools/importapi-sdk'
|
|
2
|
+
|
|
3
|
+
export class UnexpectedOperationStateError extends Error {
|
|
4
|
+
constructor(state: ProcessingState) {
|
|
5
|
+
super(`Unexpected operation state "${state}"`)
|
|
6
|
+
this.name = 'UnexpectedOperationStateError'
|
|
7
|
+
}
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export * from './use-fetch-export-operations'
|
|
2
|
+
export * from './use-fetch-file-import-job'
|
|
3
|
+
export * from './use-fetch-import-container-details'
|
|
4
|
+
export * from './use-fetch-import-operations'
|
|
5
|
+
export * from './use-fetch-import-summaries'
|
|
6
|
+
export * from './use-file-import-job-upload'
|
|
7
|
+
export * from './use-file-upload'
|
|
8
|
+
export * from './use-import-container-upload'
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { fetchExportOperations } from '../@api'
|
|
3
|
+
import { ProjectKeyNotAvailableError } from '../@errors'
|
|
4
|
+
import type {
|
|
5
|
+
PaginatedExportOperationResponse,
|
|
6
|
+
ExportOperationQueryParams,
|
|
7
|
+
} from '../@types'
|
|
8
|
+
import { useFetch } from './use-fetch'
|
|
9
|
+
|
|
10
|
+
type UseFetchExportOperationsConfig = {
|
|
11
|
+
projectKey: string
|
|
12
|
+
queryParams: ExportOperationQueryParams
|
|
13
|
+
pollingInterval?: number
|
|
14
|
+
shouldContinuePolling?: (data: PaginatedExportOperationResponse) => boolean
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const useFetchExportOperations = ({
|
|
18
|
+
projectKey,
|
|
19
|
+
queryParams,
|
|
20
|
+
pollingInterval,
|
|
21
|
+
shouldContinuePolling,
|
|
22
|
+
}: UseFetchExportOperationsConfig) => {
|
|
23
|
+
const fetchData = React.useCallback(() => {
|
|
24
|
+
if (!projectKey) {
|
|
25
|
+
return Promise.reject(new ProjectKeyNotAvailableError())
|
|
26
|
+
}
|
|
27
|
+
return fetchExportOperations({ projectKey, queryParams })
|
|
28
|
+
}, [projectKey, queryParams])
|
|
29
|
+
|
|
30
|
+
return useFetch(fetchData, {
|
|
31
|
+
pollingInterval,
|
|
32
|
+
shouldContinuePolling,
|
|
33
|
+
})
|
|
34
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { renderHook, waitFor } from '@testing-library/react'
|
|
2
|
+
import { getFileImportJob } from '../@api'
|
|
3
|
+
import { useFetchFileImportJob } from './use-fetch-file-import-job'
|
|
4
|
+
import type { FileImportJob } from '../@types'
|
|
5
|
+
|
|
6
|
+
jest.mock('@commercetools-frontend/sentry', () => ({
|
|
7
|
+
reportErrorToSentry: jest.fn(),
|
|
8
|
+
}))
|
|
9
|
+
jest.mock('../@api', () => ({
|
|
10
|
+
getFileImportJob: jest.fn(),
|
|
11
|
+
}))
|
|
12
|
+
|
|
13
|
+
const mockGetFileImportJob = getFileImportJob as jest.MockedFunction<
|
|
14
|
+
typeof getFileImportJob
|
|
15
|
+
>
|
|
16
|
+
|
|
17
|
+
describe('useFetchFileImportJob', () => {
|
|
18
|
+
const projectKey = 'test-with-big-data'
|
|
19
|
+
const resourceType = 'product'
|
|
20
|
+
const importContainerKey = 'test-container'
|
|
21
|
+
const jobId = 'test-job-id'
|
|
22
|
+
|
|
23
|
+
const mockJob: FileImportJob = {
|
|
24
|
+
id: jobId,
|
|
25
|
+
fileName: 'test.csv',
|
|
26
|
+
importContainerKey,
|
|
27
|
+
state: 'validated',
|
|
28
|
+
summary: {
|
|
29
|
+
total: 100,
|
|
30
|
+
invalid: 5,
|
|
31
|
+
valid: 95,
|
|
32
|
+
fieldsCount: 10,
|
|
33
|
+
fields: ['field1', 'field2'],
|
|
34
|
+
ignoredFields: [],
|
|
35
|
+
},
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
beforeEach(() => {
|
|
39
|
+
jest.clearAllMocks()
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
it('should fetch job details', async () => {
|
|
43
|
+
mockGetFileImportJob.mockResolvedValue(mockJob)
|
|
44
|
+
|
|
45
|
+
const { result } = renderHook(() =>
|
|
46
|
+
useFetchFileImportJob({
|
|
47
|
+
projectKey,
|
|
48
|
+
resourceType,
|
|
49
|
+
importContainerKey,
|
|
50
|
+
jobId,
|
|
51
|
+
})
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
await waitFor(() => {
|
|
55
|
+
expect(result.current.data).toEqual(mockJob)
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
expect(mockGetFileImportJob).toHaveBeenCalledWith({
|
|
59
|
+
projectKey,
|
|
60
|
+
resourceType,
|
|
61
|
+
importContainerKey,
|
|
62
|
+
jobId,
|
|
63
|
+
})
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
it('should handle errors', async () => {
|
|
67
|
+
const error = new Error('Failed to fetch job')
|
|
68
|
+
mockGetFileImportJob.mockRejectedValue(error)
|
|
69
|
+
|
|
70
|
+
const { result } = renderHook(() =>
|
|
71
|
+
useFetchFileImportJob({
|
|
72
|
+
projectKey,
|
|
73
|
+
resourceType,
|
|
74
|
+
importContainerKey,
|
|
75
|
+
jobId,
|
|
76
|
+
})
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
await waitFor(() => {
|
|
80
|
+
expect(result.current.error).toBeTruthy()
|
|
81
|
+
})
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
it('should pass polling config to useFetch', async () => {
|
|
85
|
+
mockGetFileImportJob.mockResolvedValue(mockJob)
|
|
86
|
+
|
|
87
|
+
const pollingInterval = 100
|
|
88
|
+
const shouldContinuePolling = jest.fn(
|
|
89
|
+
(data: typeof mockJob) => data.state !== 'validated'
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
const { result } = renderHook(() =>
|
|
93
|
+
useFetchFileImportJob({
|
|
94
|
+
projectKey,
|
|
95
|
+
resourceType,
|
|
96
|
+
importContainerKey,
|
|
97
|
+
jobId,
|
|
98
|
+
pollingInterval,
|
|
99
|
+
shouldContinuePolling,
|
|
100
|
+
})
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
await waitFor(() => {
|
|
104
|
+
expect(result.current.data).toEqual(mockJob)
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
expect(mockGetFileImportJob).toHaveBeenCalledWith({
|
|
108
|
+
projectKey,
|
|
109
|
+
resourceType,
|
|
110
|
+
importContainerKey,
|
|
111
|
+
jobId,
|
|
112
|
+
})
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
it('should throw ProjectKeyNotAvailableError when projectKey is empty', async () => {
|
|
116
|
+
const { result } = renderHook(() =>
|
|
117
|
+
useFetchFileImportJob({
|
|
118
|
+
projectKey: '',
|
|
119
|
+
resourceType,
|
|
120
|
+
importContainerKey,
|
|
121
|
+
jobId,
|
|
122
|
+
})
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
await waitFor(() => {
|
|
126
|
+
expect(result.current.error).toBeTruthy()
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
expect(result.current.error?.message).toBe('Project key is not available')
|
|
130
|
+
})
|
|
131
|
+
})
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { getFileImportJob } from '../@api'
|
|
3
|
+
import { ProjectKeyNotAvailableError } from '../@errors'
|
|
4
|
+
import type { FileImportJob } from '../@types'
|
|
5
|
+
import { useFetch } from './use-fetch'
|
|
6
|
+
|
|
7
|
+
type UseFetchFileImportJobConfig = {
|
|
8
|
+
projectKey: string
|
|
9
|
+
resourceType: string
|
|
10
|
+
importContainerKey: string
|
|
11
|
+
jobId: string
|
|
12
|
+
pollingInterval?: number
|
|
13
|
+
shouldContinuePolling?: (data: FileImportJob) => boolean
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const useFetchFileImportJob = ({
|
|
17
|
+
projectKey,
|
|
18
|
+
importContainerKey,
|
|
19
|
+
jobId,
|
|
20
|
+
pollingInterval,
|
|
21
|
+
shouldContinuePolling,
|
|
22
|
+
}: UseFetchFileImportJobConfig) => {
|
|
23
|
+
const fetchData = React.useCallback(() => {
|
|
24
|
+
if (!projectKey) {
|
|
25
|
+
return Promise.reject(new ProjectKeyNotAvailableError())
|
|
26
|
+
}
|
|
27
|
+
return getFileImportJob({
|
|
28
|
+
projectKey,
|
|
29
|
+
importContainerKey,
|
|
30
|
+
jobId,
|
|
31
|
+
})
|
|
32
|
+
}, [projectKey, importContainerKey, jobId])
|
|
33
|
+
|
|
34
|
+
return useFetch(fetchData, {
|
|
35
|
+
pollingInterval,
|
|
36
|
+
shouldContinuePolling,
|
|
37
|
+
})
|
|
38
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { fetchImportContainerDetails } from '../@api'
|
|
3
|
+
import { ProjectKeyNotAvailableError } from '../@errors'
|
|
4
|
+
import { useFetch } from './use-fetch'
|
|
5
|
+
import { type ImportContainerDetails } from '../@types'
|
|
6
|
+
|
|
7
|
+
type UseFetchImportContainerDetailsConfig = {
|
|
8
|
+
projectKey: string
|
|
9
|
+
importContainerKey: string
|
|
10
|
+
pollingInterval?: number
|
|
11
|
+
shouldContinuePolling?: (data: ImportContainerDetails) => boolean
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const useFetchImportContainerDetails = ({
|
|
15
|
+
projectKey,
|
|
16
|
+
importContainerKey,
|
|
17
|
+
pollingInterval,
|
|
18
|
+
shouldContinuePolling,
|
|
19
|
+
}: UseFetchImportContainerDetailsConfig) => {
|
|
20
|
+
const fetchData = React.useCallback(() => {
|
|
21
|
+
if (!projectKey) {
|
|
22
|
+
return Promise.reject(new ProjectKeyNotAvailableError())
|
|
23
|
+
}
|
|
24
|
+
return fetchImportContainerDetails({ projectKey, importContainerKey })
|
|
25
|
+
}, [projectKey, importContainerKey])
|
|
26
|
+
|
|
27
|
+
return useFetch(fetchData, {
|
|
28
|
+
pollingInterval,
|
|
29
|
+
shouldContinuePolling,
|
|
30
|
+
})
|
|
31
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { fetchImportOperations } from '../@api'
|
|
3
|
+
import { ProjectKeyNotAvailableError } from '../@errors'
|
|
4
|
+
import type {
|
|
5
|
+
ExtendedImportOperationPagedResponse,
|
|
6
|
+
ImportOperationQueryParams,
|
|
7
|
+
} from '../@types'
|
|
8
|
+
import { useFetch } from './use-fetch'
|
|
9
|
+
|
|
10
|
+
type UseFetchImportOperationsConfig = {
|
|
11
|
+
projectKey: string
|
|
12
|
+
importContainerKey: string
|
|
13
|
+
queryParams: ImportOperationQueryParams
|
|
14
|
+
pollingInterval?: number
|
|
15
|
+
shouldContinuePolling?: (
|
|
16
|
+
data: ExtendedImportOperationPagedResponse
|
|
17
|
+
) => boolean
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const useFetchImportOperations = ({
|
|
21
|
+
projectKey,
|
|
22
|
+
importContainerKey,
|
|
23
|
+
queryParams,
|
|
24
|
+
pollingInterval,
|
|
25
|
+
shouldContinuePolling,
|
|
26
|
+
}: UseFetchImportOperationsConfig) => {
|
|
27
|
+
const fetchData = React.useCallback(() => {
|
|
28
|
+
if (!projectKey) {
|
|
29
|
+
return Promise.reject(new ProjectKeyNotAvailableError())
|
|
30
|
+
}
|
|
31
|
+
return fetchImportOperations({
|
|
32
|
+
projectKey,
|
|
33
|
+
importContainerKey,
|
|
34
|
+
queryParams,
|
|
35
|
+
})
|
|
36
|
+
}, [projectKey, importContainerKey, queryParams])
|
|
37
|
+
|
|
38
|
+
return useFetch(fetchData, {
|
|
39
|
+
pollingInterval,
|
|
40
|
+
shouldContinuePolling,
|
|
41
|
+
})
|
|
42
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { fetchImportSummaries } from '../@api'
|
|
3
|
+
import { ProjectKeyNotAvailableError } from '../@errors'
|
|
4
|
+
import type {
|
|
5
|
+
ImportContainerQueryParams,
|
|
6
|
+
ImportContainerDetails,
|
|
7
|
+
} from '../@types'
|
|
8
|
+
import { useFetch } from './use-fetch'
|
|
9
|
+
|
|
10
|
+
export type ImportSummariesResult = {
|
|
11
|
+
results: ImportContainerDetails[]
|
|
12
|
+
count: number
|
|
13
|
+
total: number
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
type UseFetchImportSummariesConfig = {
|
|
17
|
+
projectKey: string
|
|
18
|
+
queryParams: ImportContainerQueryParams
|
|
19
|
+
pollingInterval?: number
|
|
20
|
+
shouldContinuePolling?: (data: ImportSummariesResult) => boolean
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const useFetchImportSummaries = ({
|
|
24
|
+
projectKey,
|
|
25
|
+
queryParams,
|
|
26
|
+
pollingInterval,
|
|
27
|
+
shouldContinuePolling,
|
|
28
|
+
}: UseFetchImportSummariesConfig) => {
|
|
29
|
+
const fetchData =
|
|
30
|
+
React.useCallback(async (): Promise<ImportSummariesResult> => {
|
|
31
|
+
if (!projectKey) {
|
|
32
|
+
return Promise.reject(new ProjectKeyNotAvailableError())
|
|
33
|
+
}
|
|
34
|
+
const summary = await fetchImportSummaries({ projectKey, queryParams })
|
|
35
|
+
const resolvedResults = await Promise.all(summary.results)
|
|
36
|
+
return {
|
|
37
|
+
results: resolvedResults,
|
|
38
|
+
count: summary.count,
|
|
39
|
+
total: summary.total,
|
|
40
|
+
}
|
|
41
|
+
}, [projectKey, queryParams])
|
|
42
|
+
|
|
43
|
+
return useFetch<ImportSummariesResult>(fetchData, {
|
|
44
|
+
pollingInterval,
|
|
45
|
+
shouldContinuePolling,
|
|
46
|
+
})
|
|
47
|
+
}
|