From 416fab31f740d559980bb38c526a581beff948d4 Mon Sep 17 00:00:00 2001 From: klakhov Date: Fri, 22 Sep 2023 14:04:28 +0300 Subject: [PATCH 1/6] added cloud storage manifest validation --- .../create-cloud-storage-page/manifests-manager.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cvat-ui/src/components/create-cloud-storage-page/manifests-manager.tsx b/cvat-ui/src/components/create-cloud-storage-page/manifests-manager.tsx index 36a646f85540..7f176a11ed97 100644 --- a/cvat-ui/src/components/create-cloud-storage-page/manifests-manager.tsx +++ b/cvat-ui/src/components/create-cloud-storage-page/manifests-manager.tsx @@ -90,6 +90,11 @@ export default function ManifestsManager(props: Props): JSX.Element { required: true, message: 'Please specify a manifest name', }, + { + type: 'string', + pattern: /^.*\.(jsonl)$/, + message: 'Manifest file should be in the .jsonl format', + }, ]} initialValue={field.name} > From 4f231e9b09f21a599ef261b837d819b5fc634a17 Mon Sep 17 00:00:00 2001 From: klakhov Date: Fri, 22 Sep 2023 14:56:12 +0300 Subject: [PATCH 2/6] improved error message --- .../create-task-page/create-task-content.tsx | 35 ++++++++++++------- .../file-manager/remote-browser.tsx | 2 +- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/cvat-ui/src/components/create-task-page/create-task-content.tsx b/cvat-ui/src/components/create-task-page/create-task-content.tsx index d69cafbffe65..81e2fe694f0d 100644 --- a/cvat-ui/src/components/create-task-page/create-task-content.tsx +++ b/cvat-ui/src/components/create-task-page/create-task-content.tsx @@ -102,26 +102,37 @@ const defaultState: State = { }; const UploadFileErrorMessages = { - one: 'It can not be processed. You can upload an archive with images, a video, a pdf file or multiple images', - multi: 'It can not be processed. You can upload one or more videos', + one: 'It can not be processed. You can upload an archive with images, a video, a pdf file or multiple images. ', + multi: 'It can not be processed. You can upload one or more videos. ', }; +function fileExtensionList(files: RemoteFile[]): string { + const fileTypes = files.map((file: RemoteFile) => `.${file.name.split('.').pop()}`); + return Array.from(new Set(fileTypes)).join(', '); +} + function validateRemoteFiles(remoteFiles: RemoteFile[], many: boolean): string { let uploadFileErrorMessage = ''; - let filteredFiles = remoteFiles; const regFiles = remoteFiles.filter((file) => file.type === 'REG'); const excludedManifests = regFiles.filter((file) => !file.key.endsWith('.jsonl')); if (!many && excludedManifests.length > 1) { - uploadFileErrorMessage = excludedManifests.every( - (it) => it.mimeType === SupportedShareTypes.IMAGE, - ) ? '' : UploadFileErrorMessages.one; + const erroredFiles = excludedManifests.filter( + (it) => it.mimeType !== SupportedShareTypes.IMAGE, + ); + if (erroredFiles.length !== 0) { + const unsupportedTypes = fileExtensionList(erroredFiles); + uploadFileErrorMessage = + `${UploadFileErrorMessages.one} Found unsupported types: ${unsupportedTypes} `; + } } else if (many) { - filteredFiles = filteredFiles.filter((it) => it.mimeType === SupportedShareTypes.VIDEO); - // something is selected and no one video - // or something except of videos selected (excluding directories) - uploadFileErrorMessage = remoteFiles.length && ( - !filteredFiles.length || filteredFiles.length !== regFiles.length - ) ? UploadFileErrorMessages.multi : ''; + const erroredFiles = regFiles.filter( + (it) => it.mimeType !== SupportedShareTypes.VIDEO, + ); + if (erroredFiles.length !== 0) { + const unsupportedTypes = fileExtensionList(erroredFiles); + uploadFileErrorMessage = + `${UploadFileErrorMessages.multi} Found unsupported types: ${unsupportedTypes} `; + } } return uploadFileErrorMessage; } diff --git a/cvat-ui/src/components/file-manager/remote-browser.tsx b/cvat-ui/src/components/file-manager/remote-browser.tsx index a9e7266f35a6..ceb74330a4ac 100644 --- a/cvat-ui/src/components/file-manager/remote-browser.tsx +++ b/cvat-ui/src/components/file-manager/remote-browser.tsx @@ -29,7 +29,7 @@ interface Node { nextToken?: string | null; } -export type RemoteFile = Pick; +export type RemoteFile = Pick; interface Props { resource: 'share' | CloudStorage; From 5513eeada4e084b4c0437b09dd686d451da39db0 Mon Sep 17 00:00:00 2001 From: klakhov Date: Fri, 22 Sep 2023 15:00:23 +0300 Subject: [PATCH 3/6] improved check files code --- .../create-task-page/create-task-content.tsx | 33 +++++++++++-------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/cvat-ui/src/components/create-task-page/create-task-content.tsx b/cvat-ui/src/components/create-task-page/create-task-content.tsx index 81e2fe694f0d..55c3480552d7 100644 --- a/cvat-ui/src/components/create-task-page/create-task-content.tsx +++ b/cvat-ui/src/components/create-task-page/create-task-content.tsx @@ -111,28 +111,33 @@ function fileExtensionList(files: RemoteFile[]): string { return Array.from(new Set(fileTypes)).join(', '); } +function checkFiles(files: RemoteFile[], type: SupportedShareTypes, baseError: string): string { + const erroredFiles = files.filter( + (it) => it.mimeType !== type, + ); + if (erroredFiles.length !== 0) { + const unsupportedTypes = fileExtensionList(erroredFiles); + return `${baseError} Found unsupported types: ${unsupportedTypes} `; + } + return ''; +} + function validateRemoteFiles(remoteFiles: RemoteFile[], many: boolean): string { let uploadFileErrorMessage = ''; const regFiles = remoteFiles.filter((file) => file.type === 'REG'); const excludedManifests = regFiles.filter((file) => !file.key.endsWith('.jsonl')); if (!many && excludedManifests.length > 1) { - const erroredFiles = excludedManifests.filter( - (it) => it.mimeType !== SupportedShareTypes.IMAGE, + uploadFileErrorMessage = checkFiles( + excludedManifests, + SupportedShareTypes.IMAGE, + UploadFileErrorMessages.one, ); - if (erroredFiles.length !== 0) { - const unsupportedTypes = fileExtensionList(erroredFiles); - uploadFileErrorMessage = - `${UploadFileErrorMessages.one} Found unsupported types: ${unsupportedTypes} `; - } } else if (many) { - const erroredFiles = regFiles.filter( - (it) => it.mimeType !== SupportedShareTypes.VIDEO, + uploadFileErrorMessage = checkFiles( + regFiles, + SupportedShareTypes.VIDEO, + UploadFileErrorMessages.multi, ); - if (erroredFiles.length !== 0) { - const unsupportedTypes = fileExtensionList(erroredFiles); - uploadFileErrorMessage = - `${UploadFileErrorMessages.multi} Found unsupported types: ${unsupportedTypes} `; - } } return uploadFileErrorMessage; } From 314eff2e4c3f96da101816fecfa3ad95b9dd875b Mon Sep 17 00:00:00 2001 From: klakhov Date: Fri, 22 Sep 2023 15:26:39 +0300 Subject: [PATCH 4/6] updated changelog --- CHANGELOG.md | 2 +- cvat-ui/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f2d8faba22e..a3c7cc637864 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,7 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - TDB ### Fixed -- TDB +- Validation on Cloud Storage form / error message on create task form () ### Security - TDB diff --git a/cvat-ui/package.json b/cvat-ui/package.json index 5266d6798848..dfd30ca1cb56 100644 --- a/cvat-ui/package.json +++ b/cvat-ui/package.json @@ -1,6 +1,6 @@ { "name": "cvat-ui", - "version": "1.56.1", + "version": "1.56.3", "description": "CVAT single-page application", "main": "src/index.tsx", "scripts": { From f220a0ea32b8596f7c5e971c427cb46114187f3e Mon Sep 17 00:00:00 2001 From: klakhov Date: Mon, 2 Oct 2023 13:00:53 +0300 Subject: [PATCH 5/6] applied comments --- .../manifests-manager.tsx | 2 +- .../create-task-page/create-task-content.tsx | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/cvat-ui/src/components/create-cloud-storage-page/manifests-manager.tsx b/cvat-ui/src/components/create-cloud-storage-page/manifests-manager.tsx index 7f176a11ed97..2a5809b5268d 100644 --- a/cvat-ui/src/components/create-cloud-storage-page/manifests-manager.tsx +++ b/cvat-ui/src/components/create-cloud-storage-page/manifests-manager.tsx @@ -93,7 +93,7 @@ export default function ManifestsManager(props: Props): JSX.Element { { type: 'string', pattern: /^.*\.(jsonl)$/, - message: 'Manifest file should be in the .jsonl format', + message: 'Manifest file must have .jsonl extension', }, ]} initialValue={field.name} diff --git a/cvat-ui/src/components/create-task-page/create-task-content.tsx b/cvat-ui/src/components/create-task-page/create-task-content.tsx index 55c3480552d7..405ba089ec0d 100644 --- a/cvat-ui/src/components/create-task-page/create-task-content.tsx +++ b/cvat-ui/src/components/create-task-page/create-task-content.tsx @@ -102,13 +102,14 @@ const defaultState: State = { }; const UploadFileErrorMessages = { - one: 'It can not be processed. You can upload an archive with images, a video, a pdf file or multiple images. ', - multi: 'It can not be processed. You can upload one or more videos. ', + one: 'Wrong list of files. You can upload an archive with images, a video, a pdf file or multiple images. ', + multi: 'Wrong list of files. You can upload one or more videos. ', }; -function fileExtensionList(files: RemoteFile[]): string { - const fileTypes = files.map((file: RemoteFile) => `.${file.name.split('.').pop()}`); - return Array.from(new Set(fileTypes)).join(', '); +function receiveExtensions(files: RemoteFile[]): string[] { + const fileTypes = files.filter((file: RemoteFile) => file.name.includes('.')) + .map((file: RemoteFile) => `.${file.name.split('.').pop()}`); + return fileTypes; } function checkFiles(files: RemoteFile[], type: SupportedShareTypes, baseError: string): string { @@ -116,8 +117,8 @@ function checkFiles(files: RemoteFile[], type: SupportedShareTypes, baseError: s (it) => it.mimeType !== type, ); if (erroredFiles.length !== 0) { - const unsupportedTypes = fileExtensionList(erroredFiles); - return `${baseError} Found unsupported types: ${unsupportedTypes} `; + const unsupportedTypes = receiveExtensions(erroredFiles); + return unsupportedTypes.length ? `${baseError} Found unsupported types: ${unsupportedTypes} ` : baseError; } return ''; } From a15a18a4edb34b2e58a7562340bf1571929948ab Mon Sep 17 00:00:00 2001 From: klakhov Date: Tue, 3 Oct 2023 11:52:01 +0300 Subject: [PATCH 6/6] fixed unsupported list --- .../src/components/create-task-page/create-task-content.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cvat-ui/src/components/create-task-page/create-task-content.tsx b/cvat-ui/src/components/create-task-page/create-task-content.tsx index 9f84c525bf76..a1ab6c27b177 100644 --- a/cvat-ui/src/components/create-task-page/create-task-content.tsx +++ b/cvat-ui/src/components/create-task-page/create-task-content.tsx @@ -115,7 +115,8 @@ function checkFiles(files: RemoteFile[], type: SupportedShareTypes, baseError: s ); if (erroredFiles.length !== 0) { const unsupportedTypes = receiveExtensions(erroredFiles); - return unsupportedTypes.length ? `${baseError} Found unsupported types: ${unsupportedTypes} ` : baseError; + const extensionList = Array.from(new Set(unsupportedTypes)); + return extensionList.length ? `${baseError} Found unsupported types: ${extensionList.join(', ')}. ` : baseError; } return ''; }