Add partial copy form async name validation
authorMichal Klobukowski <michal.klobukowski@contractors.roche.com>
Sat, 18 Aug 2018 08:09:38 +0000 (10:09 +0200)
committerMichal Klobukowski <michal.klobukowski@contractors.roche.com>
Sat, 18 Aug 2018 08:09:38 +0000 (10:09 +0200)
Feature #14014

Arvados-DCO-1.1-Signed-off-by: Michal Klobukowski <michal.klobukowski@contractors.roche.com>

src/common/api/common-resource-service.ts
src/store/collection-panel/collection-panel-files/collection-panel-files-actions.ts

index caa4d760c9e08ef1c7af63bf86e90b34a03d4ebb..da5bc33cf7c08f33af05e7e5c938c6b9e0663bc4 100644 (file)
@@ -29,6 +29,12 @@ export interface Errors {
     errorToken: string;
 }
 
+export enum CommonResourceServiceError {
+    UNIQUE_VIOLATION = 'UniqueViolation',
+    UNKNOWN = 'Unknown',
+    NONE = 'None'
+}
+
 export class CommonResourceService<T extends Resource> {
 
     static mapResponseKeys = (response: any): Promise<any> =>
@@ -106,3 +112,17 @@ export class CommonResourceService<T extends Resource> {
     }
 }
 
+export const getCommonResourceServiceError = (errorResponse: any) => {
+    if ('errors' in errorResponse && 'errorToken' in errorResponse) {
+        const error = errorResponse.errors.join('');
+        switch (true) {
+            case /UniqueViolation/.test(error):
+                return CommonResourceServiceError.UNIQUE_VIOLATION;
+            default:
+                return CommonResourceServiceError.UNKNOWN;
+        }
+    }
+    return CommonResourceServiceError.NONE;
+};
+
+
index 114446a0f0107c3e6c064410ea73907b972edab2..f2dc551b1077296e5af73e05c759e228428c0bda 100644 (file)
@@ -11,8 +11,9 @@ import { snackbarActions } from "../../snackbar/snackbar-actions";
 import { dialogActions } from '../../dialog/dialog-actions';
 import { getNodeValue } from "~/models/tree";
 import { filterCollectionFilesBySelection } from './collection-panel-files-state';
-import { startSubmit, initialize } from 'redux-form';
+import { startSubmit, initialize, SubmissionError, stopSubmit } from 'redux-form';
 import { loadProjectTreePickerProjects } from '../../../views-components/project-tree-picker/project-tree-picker';
+import { getCommonResourceServiceError, CommonResourceServiceError } from "~/common/api/common-resource-service";
 
 export const collectionPanelFilesAction = unionize({
     SET_COLLECTION_FILES: ofType<CollectionFilesTree>(),
@@ -113,19 +114,25 @@ export const doCollectionPartialCopy = ({ name, description, projectUuid }: Coll
         const state = getState();
         const currentCollection = state.collectionPanel.item;
         if (currentCollection) {
-            const collection = await services.collectionService.get(currentCollection.uuid);
-            const collectionCopy = {
-                ...collection,
-                name,
-                description,
-                ownerUuid: projectUuid,
-                uuid: undefined
-            };
-            const newCollection = await services.collectionService.create(collectionCopy);
-            const paths = filterCollectionFilesBySelection(state.collectionPanelFiles, false).map(file => file.id);
-            await services.collectionService.deleteFiles(newCollection.uuid, paths);
-            dispatch(dialogActions.CLOSE_DIALOG({ id: COLLECTION_PARTIAL_COPY }));
-            dispatch(snackbarActions.OPEN_SNACKBAR({ message: 'New collection created.', hideDuration: 2000 }));
+            try {
+                const collection = await services.collectionService.get(currentCollection.uuid);
+                const collectionCopy = {
+                    ...collection,
+                    name,
+                    description,
+                    ownerUuid: projectUuid,
+                    uuid: undefined
+                };
+                const newCollection = await services.collectionService.create(collectionCopy);
+                const paths = filterCollectionFilesBySelection(state.collectionPanelFiles, false).map(file => file.id);
+                await services.collectionService.deleteFiles(newCollection.uuid, paths);
+                dispatch(dialogActions.CLOSE_DIALOG({ id: COLLECTION_PARTIAL_COPY }));
+                dispatch(snackbarActions.OPEN_SNACKBAR({ message: 'New collection created.', hideDuration: 2000 }));
+            } catch (e) {
+                if (getCommonResourceServiceError(e) === CommonResourceServiceError.UNIQUE_VIOLATION) {
+                    dispatch(stopSubmit(COLLECTION_PARTIAL_COPY, { name: 'Collection with this name already exists.' }));
+                }
+            }
         }
     };