[ARVADOS-WORKBENCH2] created: 1.1.4-692-g8c0a8c2

Git user git at public.curoverse.com
Mon Aug 20 11:27:53 EDT 2018


        at  8c0a8c26b37118e6e516da2cfaa19b26b8f1e5eb (commit)


commit 8c0a8c26b37118e6e516da2cfaa19b26b8f1e5eb
Author: Michal Klobukowski <michal.klobukowski at contractors.roche.com>
Date:   Mon Aug 20 17:27:08 2018 +0200

    Implement resource moving
    
    Feature #13831
    
    Arvados-DCO-1.1-Signed-off-by: Michal Klobukowski <michal.klobukowski at contractors.roche.com>

diff --git a/src/services/services.ts b/src/services/services.ts
index 1fa35fc..c2615a3 100644
--- a/src/services/services.ts
+++ b/src/services/services.ts
@@ -14,6 +14,7 @@ import { CollectionFilesService } from "./collection-files-service/collection-fi
 import { KeepService } from "./keep-service/keep-service";
 import { WebDAV } from "../common/webdav";
 import { Config } from "../common/config";
+import { ResourceKind } from '~/models/resource';
 
 export type ServiceRepository = ReturnType<typeof createServices>;
 
@@ -49,3 +50,14 @@ export const createServices = (config: Config) => {
     };
 };
 
+export const getResourceService = (resourceKind: ResourceKind, serviceRepository: ServiceRepository) => {
+    switch (resourceKind) {
+        case ResourceKind.PROJECT:
+            return serviceRepository.projectService;
+        case ResourceKind.COLLECTION:
+            return serviceRepository.collectionService;
+        default:
+            return undefined;
+    }
+};
+
diff --git a/src/views-components/context-menu/action-sets/collection-action-set.ts b/src/views-components/context-menu/action-sets/collection-action-set.ts
index 9c07fb0..bbe6f5f 100644
--- a/src/views-components/context-menu/action-sets/collection-action-set.ts
+++ b/src/views-components/context-menu/action-sets/collection-action-set.ts
@@ -9,6 +9,7 @@ import { RenameIcon, ShareIcon, MoveToIcon, CopyIcon, DetailsIcon, ProvenanceGra
 import { openUpdater } from "~/store/collections/updater/collection-updater-action";
 import { favoritePanelActions } from "~/store/favorite-panel/favorite-panel-action";
 import { openMoveToDialog } from "../../move-to-dialog/move-to-dialog";
+import { ResourceKind } from "~/models/resource";
 
 export const collectionActionSet: ContextMenuActionSet = [[
     {
@@ -28,7 +29,11 @@ export const collectionActionSet: ContextMenuActionSet = [[
     {
         icon: MoveToIcon,
         name: "Move to",
-        execute: dispatch => dispatch<any>(openMoveToDialog())
+        execute: (dispatch, resource) => dispatch<any>(openMoveToDialog({
+            name: resource.name,
+            uuid: resource.uuid,
+            kind: ResourceKind.COLLECTION
+        }))
     },
     {
         component: ToggleFavoriteAction,
diff --git a/src/views-components/context-menu/action-sets/collection-resource-action-set.ts b/src/views-components/context-menu/action-sets/collection-resource-action-set.ts
index 337ca2f..24c1bf1 100644
--- a/src/views-components/context-menu/action-sets/collection-resource-action-set.ts
+++ b/src/views-components/context-menu/action-sets/collection-resource-action-set.ts
@@ -9,6 +9,7 @@ import { RenameIcon, ShareIcon, MoveToIcon, CopyIcon, DetailsIcon, RemoveIcon }
 import { openUpdater } from "~/store/collections/updater/collection-updater-action";
 import { favoritePanelActions } from "~/store/favorite-panel/favorite-panel-action";
 import { openMoveToDialog } from "../../move-to-dialog/move-to-dialog";
+import { ResourceKind } from '~/models/resource';
 
 export const collectionResourceActionSet: ContextMenuActionSet = [[
     {
@@ -28,7 +29,11 @@ export const collectionResourceActionSet: ContextMenuActionSet = [[
     {
         icon: MoveToIcon,
         name: "Move to",
-        execute: dispatch => dispatch<any>(openMoveToDialog())
+        execute: (dispatch, resource) => dispatch<any>(openMoveToDialog({
+            name: resource.name,
+            uuid: resource.uuid,
+            kind: ResourceKind.COLLECTION
+        }))
     },
     {
         component: ToggleFavoriteAction,
diff --git a/src/views-components/context-menu/action-sets/project-action-set.ts b/src/views-components/context-menu/action-sets/project-action-set.ts
index efba457..e5c401a 100644
--- a/src/views-components/context-menu/action-sets/project-action-set.ts
+++ b/src/views-components/context-menu/action-sets/project-action-set.ts
@@ -12,6 +12,7 @@ import { toggleFavorite } from "~/store/favorites/favorites-actions";
 import { favoritePanelActions } from "~/store/favorite-panel/favorite-panel-action";
 import { openMoveToDialog } from "../../move-to-dialog/move-to-dialog";
 import { PROJECT_CREATE_DIALOG } from "../../dialog-create/dialog-project-create";
+import { ResourceKind } from '~/models/resource';
 
 export const projectActionSet: ContextMenuActionSet = [[
     {
@@ -41,6 +42,10 @@ export const projectActionSet: ContextMenuActionSet = [[
     {
         icon: MoveToIcon,
         name: "Move to",
-        execute: dispatch => dispatch<any>(openMoveToDialog())
+        execute: (dispatch, resource) => dispatch<any>(openMoveToDialog({
+            name: resource.name,
+            uuid: resource.uuid,
+            kind: ResourceKind.PROJECT
+        }))
     },
 ]];
diff --git a/src/views-components/move-to-dialog/move-to-dialog.tsx b/src/views-components/move-to-dialog/move-to-dialog.tsx
index 5939662..d7c66bc 100644
--- a/src/views-components/move-to-dialog/move-to-dialog.tsx
+++ b/src/views-components/move-to-dialog/move-to-dialog.tsx
@@ -2,26 +2,87 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
+import * as React from "react";
 import { Dispatch, compose } from "redux";
-import { withDialog } from "../../store/dialog/with-dialog";
-import { dialogActions } from "../../store/dialog/dialog-actions";
-import { MoveToDialog } from "../../components/move-to-dialog/move-to-dialog";
-import { reduxForm, startSubmit, stopSubmit } from "redux-form";
+import { withDialog } from "~/store/dialog/with-dialog";
+import { dialogActions } from "~/store/dialog/dialog-actions";
+import { reduxForm, startSubmit, stopSubmit, InjectedFormProps, initialize, Field, WrappedFieldProps } from 'redux-form';
+import { WithDialogProps } from '~/store/dialog/with-dialog';
+import { FormDialog } from '~/components/form-dialog/form-dialog';
+import { ProjectTreePicker } from '~/views-components/project-tree-picker/project-tree-picker';
+import { MOVE_TO_VALIDATION } from '~/validators/validators';
+import { Typography } from "@material-ui/core";
+import { ResourceKind } from '~/models/resource';
+import { ServiceRepository, getResourceService } from '~/services/services';
+import { RootState } from '~/store/store';
+import { getCommonResourceServiceError, CommonResourceServiceError } from "~/common/api/common-resource-service";
+import { snackbarActions } from '../../store/snackbar/snackbar-actions';
 
 export const MOVE_TO_DIALOG = 'moveToDialog';
 
-export const openMoveToDialog = () =>
+export interface MoveToDialogResource {
+    name: string;
+    uuid: string;
+    ownerUuid: string;
+    kind: ResourceKind;
+}
+
+export const openMoveToDialog = (resource: { name: string, uuid: string, kind: ResourceKind }) =>
     (dispatch: Dispatch) => {
+        dispatch(initialize(MOVE_TO_DIALOG, resource));
         dispatch(dialogActions.OPEN_DIALOG({ id: MOVE_TO_DIALOG, data: {} }));
     };
 
+export const moveResource = (resource: MoveToDialogResource) =>
+    async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
+        const service = getResourceService(resource.kind, services);
+        dispatch(startSubmit(MOVE_TO_DIALOG));
+        if (service) {
+            try {
+                const originalResource = await service.get(resource.uuid);
+                await service.update(resource.uuid, { ...originalResource, owner_uuid: resource.ownerUuid });
+                dispatch(dialogActions.CLOSE_DIALOG({ id: MOVE_TO_DIALOG }));
+                dispatch(snackbarActions.OPEN_SNACKBAR({ message: 'Resource has been moved', hideDuration: 2000 }));
+            } catch (e) {
+                const error = getCommonResourceServiceError(e);
+                if (error === CommonResourceServiceError.UNIQUE_VIOLATION) {
+                    dispatch(stopSubmit(MOVE_TO_DIALOG, { ownerUuid: 'A resource with the same name already exists in the target project' }));
+                } else {
+                    dispatch(dialogActions.CLOSE_DIALOG({ id: MOVE_TO_DIALOG }));
+                    dispatch(snackbarActions.OPEN_SNACKBAR({ message: 'Could not move the resource.', hideDuration: 2000 }));
+                }
+            }
+        }
+    };
+
 export const MoveToProjectDialog = compose(
     withDialog(MOVE_TO_DIALOG),
-    reduxForm({
+    reduxForm<MoveToDialogResource>({
         form: MOVE_TO_DIALOG,
         onSubmit: (data, dispatch) => {
-            dispatch(startSubmit(MOVE_TO_DIALOG));
-            setTimeout(() => dispatch(stopSubmit(MOVE_TO_DIALOG, { name: 'Invalid path' })), 2000);
+            dispatch(moveResource(data));
         }
     })
-)(MoveToDialog);
+)((props: WithDialogProps<string> & InjectedFormProps<MoveToDialogResource>) =>
+    <FormDialog
+        dialogTitle='Move to'
+        formFields={MoveToDialogFields}
+        submitLabel='Move'
+        {...props}
+    />);
+
+const MoveToDialogFields = () =>
+    <Field
+        name="ownerUuid"
+        component={Picker}
+        validate={MOVE_TO_VALIDATION} />;
+
+
+const Picker = (props: WrappedFieldProps) =>
+    <div style={{ height: '144px', display: 'flex', flexDirection: 'column' }}>
+        <ProjectTreePicker onChange={projectUuid => props.input.onChange(projectUuid)} />
+        {props.meta.dirty && props.meta.error &&
+            <Typography variant='caption' color='error'>
+                {props.meta.error}
+            </Typography>}
+    </div>;

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list