[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