15768: project multimove works Arvados-DCO-1.1-Signed-off-by: Lisa Knox <lisa.knox...
authorLisa Knox <lisaknox83@gmail.com>
Mon, 28 Aug 2023 15:25:24 +0000 (11:25 -0400)
committerLisa Knox <lisaknox83@gmail.com>
Mon, 28 Aug 2023 15:25:24 +0000 (11:25 -0400)
src/components/multiselectToolbar/MultiselectToolbar.tsx
src/store/projects/project-move-actions.ts
src/store/workbench/workbench-actions.ts
src/views-components/context-menu/action-sets/project-action-set.ts
src/views-components/context-menu/context-menu-action-set.ts

index 99d15e07d5b86adb264939c0fbc6b46581d74e92..880d0f49c25d968628608c2df87ea2efa5bcdea1 100644 (file)
@@ -2,39 +2,38 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
-import React from 'react';
-import { connect } from 'react-redux';
-import { StyleRulesCallback, withStyles, WithStyles, Toolbar, Tooltip, IconButton } from '@material-ui/core';
-import { ArvadosTheme } from 'common/custom-theme';
-import { RootState } from 'store/store';
-import { Dispatch } from 'redux';
-import { TCheckedList } from 'components/data-table/data-table';
-import { ContextMenuResource } from 'store/context-menu/context-menu-actions';
-import { Resource, extractUuidKind } from 'models/resource';
-import { getResource } from 'store/resources/resources';
-import { ResourcesState } from 'store/resources/resources';
-import { ContextMenuAction, ContextMenuActionSet } from 'views-components/context-menu/context-menu-action-set';
-import { RestoreFromTrashIcon, TrashIcon } from 'components/icon/icon';
-import { multiselectActionsFilters, TMultiselectActionsFilters } from './ms-toolbar-action-filters';
-import { kindToActionSet, findActionByName } from './ms-kind-action-differentiator';
-import { toggleTrashAction } from 'views-components/context-menu/action-sets/project-action-set';
-
-type CssRules = 'root' | 'button';
+import React from "react";
+import { connect } from "react-redux";
+import { StyleRulesCallback, withStyles, WithStyles, Toolbar, Tooltip, IconButton } from "@material-ui/core";
+import { ArvadosTheme } from "common/custom-theme";
+import { RootState } from "store/store";
+import { Dispatch } from "redux";
+import { TCheckedList } from "components/data-table/data-table";
+import { ContextMenuResource } from "store/context-menu/context-menu-actions";
+import { Resource, extractUuidKind } from "models/resource";
+import { getResource } from "store/resources/resources";
+import { ResourcesState } from "store/resources/resources";
+import { ContextMenuAction, ContextMenuActionSet } from "views-components/context-menu/context-menu-action-set";
+import { RestoreFromTrashIcon, TrashIcon } from "components/icon/icon";
+import { multiselectActionsFilters, TMultiselectActionsFilters } from "./ms-toolbar-action-filters";
+import { kindToActionSet, findActionByName } from "./ms-kind-action-differentiator";
+import { toggleTrashAction } from "views-components/context-menu/action-sets/project-action-set";
+
+type CssRules = "root" | "button";
 
 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
     root: {
-        display: 'flex',
-        flexDirection: 'row',
+        display: "flex",
+        flexDirection: "row",
         width: 0,
         padding: 0,
-        margin: '1rem auto auto 0.5rem',
-        overflow: 'hidden',
-        transition: 'width 150ms',
-        // borderBottom: '1px solid gray',
+        margin: "1rem auto auto 0.5rem",
+        overflow: "hidden",
+        transition: "width 150ms",
     },
     button: {
-        width: '1rem',
-        margin: 'auto 5px',
+        width: "1rem",
+        margin: "auto 5px",
     },
 });
 
@@ -53,7 +52,7 @@ export const MultiselectToolbar = connect(
         const { classes, checkedList } = props;
         const currentResourceKinds = Array.from(selectedToKindSet(checkedList));
 
-        const currentPathIsTrash = window.location.pathname === '/trash';
+        const currentPathIsTrash = window.location.pathname === "/trash";
         const buttons =
             currentPathIsTrash && selectedToKindSet(checkedList).size
                 ? [toggleTrashAction]
@@ -65,10 +64,10 @@ export const MultiselectToolbar = connect(
                 style={{ width: `${buttons.length * 2.12}rem` }}>
                 {buttons.length ? (
                     buttons.map((btn, i) =>
-                        btn.name === 'ToggleTrashAction' ? (
+                        btn.name === "ToggleTrashAction" ? (
                             <Tooltip
                                 className={classes.button}
-                                title={currentPathIsTrash ? 'Restore' : 'Move to trash'}
+                                title={currentPathIsTrash ? "Restore" : "Move to trash"}
                                 key={i}
                                 disableFocusListener>
                                 <IconButton onClick={() => props.executeMulti(btn, checkedList, props.resources)}>
@@ -138,7 +137,7 @@ function selectActionsByKind(currentResourceKinds: Array<string>, filterSet: TMu
 
     const filteredNameSet = allFiltersArray.map(filterArray => {
         const resultSet = new Set();
-        filterArray.forEach(action => resultSet.add(action.name || ''));
+        filterArray.forEach(action => resultSet.add(action.name || ""));
         return resultSet;
     });
 
@@ -150,8 +149,8 @@ function selectActionsByKind(currentResourceKinds: Array<string>, filterSet: TMu
     });
 
     return filteredResult.sort((a, b) => {
-        const nameA = a.name || '';
-        const nameB = b.name || '';
+        const nameA = a.name || "";
+        const nameB = b.name || "";
         if (nameA < nameB) {
             return -1;
         }
index ab46e4b59ac3c202d4183ea9c16a6dd5f17ae734..618ce21e2d46f717fc5a06d26330cf75b92c905a 100644 (file)
@@ -2,34 +2,31 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
-import { Dispatch } from 'redux';
-import { dialogActions } from 'store/dialog/dialog-actions';
-import { startSubmit, stopSubmit, initialize, FormErrors } from 'redux-form';
-import { ServiceRepository } from 'services/services';
-import { RootState } from 'store/store';
-import { getUserUuid } from 'common/getuser';
-import { getCommonResourceServiceError, CommonResourceServiceError } from 'services/common-service/common-resource-service';
-import { MoveToFormDialogData } from 'store/move-to-dialog/move-to-dialog';
-import { resetPickerProjectTree } from 'store/project-tree-picker/project-tree-picker-actions';
-import { initProjectsTreePicker } from 'store/tree-picker/tree-picker-actions';
-import { projectPanelActions } from 'store/project-panel/project-panel-action';
-import { loadSidePanelTreeProjects } from '../side-panel-tree/side-panel-tree-actions';
+import { Dispatch } from "redux";
+import { dialogActions } from "store/dialog/dialog-actions";
+import { startSubmit, stopSubmit, initialize, FormErrors } from "redux-form";
+import { ServiceRepository } from "services/services";
+import { RootState } from "store/store";
+import { getUserUuid } from "common/getuser";
+import { getCommonResourceServiceError, CommonResourceServiceError } from "services/common-service/common-resource-service";
+import { MoveToFormDialogData } from "store/move-to-dialog/move-to-dialog";
+import { resetPickerProjectTree } from "store/project-tree-picker/project-tree-picker-actions";
+import { initProjectsTreePicker } from "store/tree-picker/tree-picker-actions";
+import { projectPanelActions } from "store/project-panel/project-panel-action";
+import { loadSidePanelTreeProjects } from "../side-panel-tree/side-panel-tree-actions";
 
-export const PROJECT_MOVE_FORM_NAME = 'projectMoveFormName';
+export const PROJECT_MOVE_FORM_NAME = "projectMoveFormName";
 
-// export const openMoveProjectDialog = (resource: { name: string; uuid: string }) => {
-// console.log(resource);
 export const openMoveProjectDialog = (resources: Array<any>) => {
     return (dispatch: Dispatch) => {
         dispatch<any>(resetPickerProjectTree());
         dispatch<any>(initProjectsTreePicker(PROJECT_MOVE_FORM_NAME));
-        dispatch(initialize(PROJECT_MOVE_FORM_NAME, resources[0], undefined, resources)); //here
+        dispatch(initialize(PROJECT_MOVE_FORM_NAME, resources[0]));
         dispatch(dialogActions.OPEN_DIALOG({ id: PROJECT_MOVE_FORM_NAME, data: {} }));
     };
 };
 
 export const moveProject = (resource: MoveToFormDialogData) => async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
-    console.log('SUCCESS?', resource);
     const userUuid = getUserUuid(getState());
     if (!userUuid) {
         return;
@@ -45,13 +42,13 @@ export const moveProject = (resource: MoveToFormDialogData) => async (dispatch:
         const error = getCommonResourceServiceError(e);
         if (error === CommonResourceServiceError.UNIQUE_NAME_VIOLATION) {
             dispatch(
-                stopSubmit(PROJECT_MOVE_FORM_NAME, { ownerUuid: 'A project with the same name already exists in the target project.' } as FormErrors)
+                stopSubmit(PROJECT_MOVE_FORM_NAME, { ownerUuid: "A project with the same name already exists in the target project." } as FormErrors)
             );
         } else if (error === CommonResourceServiceError.OWNERSHIP_CYCLE) {
-            dispatch(stopSubmit(PROJECT_MOVE_FORM_NAME, { ownerUuid: 'Cannot move a project into itself.' } as FormErrors));
+            dispatch(stopSubmit(PROJECT_MOVE_FORM_NAME, { ownerUuid: "Cannot move a project into itself." } as FormErrors));
         } else {
             dispatch(dialogActions.CLOSE_DIALOG({ id: PROJECT_MOVE_FORM_NAME }));
-            throw new Error('Could not move the project.');
+            throw new Error("Could not move the project.");
         }
         return;
     }
index ab3041ad2af5118f9e89210ce77fce4c0dd8701f..6182a314d8d735aacf34d5833f4c57473c044a97 100644 (file)
@@ -279,31 +279,23 @@ export const createProject = (data: projectCreateActions.ProjectCreateFormDialog
 };
 
 export const moveProject = (data: MoveToFormDialogData) => async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
-    console.log("moveProject---");
-    console.log("moveProject:", data);
-    // const currentState = getState();
-    // console.log('current', currentState.multiselect.checkedList);
-    const projectsToMove = selectedToArray(getState().multiselect.checkedList);
-    // console.log("resource?", getResource(projectsToMove[0])(getState().resources));
-    const sourceUuid = getResource(projectsToMove[0])(getState().resources)?.ownerUuid;
+    const projectsToMove: string[] = selectedToArray(getState().multiselect.checkedList);
+    //if no items in checkedlist, default to normal context menu behavior
+    if (!projectsToMove.length) projectsToMove.push(data.uuid);
+    const sourceUuid = getResource(data.uuid)(getState().resources)?.ownerUuid;
     const destinationUuid = data.ownerUuid;
 
-    for (const project of projectsToMove) {
-        await moveSingleProject(project);
+    for (const projectUuid of projectsToMove) {
+        await moveSingleProject(projectUuid);
     }
 
     async function moveSingleProject(projectUuid) {
         try {
-            // const oldProject = getResource(projectUuid)(getState().resources);
-            const originalProject = getResource(projectUuid)(getState().resources) as any;
+            const originalProject = getResource(projectUuid)(getState().resources);
             const oldProject = { ...originalProject, ownerUuid: data.ownerUuid } as any;
-            // const { name, uuid, ownerUuid } = getResource(projectUuid)(getState().resources) as any;
-            // const oldProject: MoveToFormDialogData = { name, uuid, ownerUuid };
-            console.log("oldProject", oldProject, data);
             const oldOwnerUuid = oldProject ? oldProject.ownerUuid : "";
             const movedProject = await dispatch<any>(projectMoveActions.moveProject(oldProject));
             if (movedProject) {
-                console.log("movedProject", movedProject);
                 dispatch(
                     snackbarActions.OPEN_SNACKBAR({
                         message: "Project has been moved",
@@ -311,10 +303,6 @@ export const moveProject = (data: MoveToFormDialogData) => async (dispatch: Disp
                         kind: SnackbarKind.SUCCESS,
                     })
                 );
-                // if (oldProject) {
-                // await dispatch<any>(loadSidePanelTreeProjects(oldProject.ownerUuid));
-                // await dispatch<any>(loadSidePanelTreeProjects(originalProject.ownerUuid));
-                // }
                 await dispatch<any>(reloadProjectMatchingUuid([oldOwnerUuid, movedProject.ownerUuid, movedProject.uuid]));
             }
         } catch (e) {
@@ -329,33 +317,6 @@ export const moveProject = (data: MoveToFormDialogData) => async (dispatch: Disp
     }
     if (sourceUuid) await dispatch<any>(loadSidePanelTreeProjects(sourceUuid));
     await dispatch<any>(loadSidePanelTreeProjects(destinationUuid));
-
-    // try {
-    //     const oldProject = getResource(data.uuid)(getState().resources);
-    //     const oldOwnerUuid = oldProject ? oldProject.ownerUuid : '';
-    //     const movedProject = await dispatch<any>(projectMoveActions.moveProject(data));
-    //     if (movedProject) {
-    //         dispatch(
-    //             snackbarActions.OPEN_SNACKBAR({
-    //                 message: 'Project has been moved',
-    //                 hideDuration: 2000,
-    //                 kind: SnackbarKind.SUCCESS,
-    //             })
-    //         );
-    //         if (oldProject) {
-    //             await dispatch<any>(loadSidePanelTreeProjects(oldProject.ownerUuid));
-    //         }
-    //         dispatch<any>(reloadProjectMatchingUuid([oldOwnerUuid, movedProject.ownerUuid, movedProject.uuid]));
-    //     }
-    // } catch (e) {
-    //     dispatch(
-    //         snackbarActions.OPEN_SNACKBAR({
-    //             message: e.message,
-    //             hideDuration: 2000,
-    //             kind: SnackbarKind.ERROR,
-    //         })
-    //     );
-    // }
 };
 
 export const updateProject = (data: projectUpdateActions.ProjectUpdateFormDialogData) => async (dispatch: Dispatch) => {
index 21019ce8b1c6b79edff1cd39d567a1220a817077..877c34b9357b200ad37b9d9fafe61e73a90463e3 100644 (file)
@@ -2,30 +2,30 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
-import { ContextMenuActionSet } from '../context-menu-action-set';
-import { NewProjectIcon, RenameIcon, MoveToIcon, DetailsIcon, AdvancedIcon, OpenIcon, Link, FolderSharedIcon } from 'components/icon/icon';
-import { ToggleFavoriteAction } from '../actions/favorite-action';
-import { toggleFavorite } from 'store/favorites/favorites-actions';
-import { favoritePanelActions } from 'store/favorite-panel/favorite-panel-action';
-import { openMoveProjectDialog } from 'store/projects/project-move-actions';
-import { openProjectCreateDialog } from 'store/projects/project-create-actions';
-import { openProjectUpdateDialog } from 'store/projects/project-update-actions';
-import { ToggleTrashAction } from 'views-components/context-menu/actions/trash-action';
-import { toggleProjectTrashed } from 'store/trash/trash-actions';
-import { ShareIcon } from 'components/icon/icon';
-import { openSharingDialog } from 'store/sharing-dialog/sharing-dialog-actions';
-import { openAdvancedTabDialog } from 'store/advanced-tab/advanced-tab';
-import { toggleDetailsPanel } from 'store/details-panel/details-panel-action';
-import { copyToClipboardAction, openInNewTabAction } from 'store/open-in-new-tab/open-in-new-tab.actions';
-import { openWebDavS3InfoDialog } from 'store/collections/collection-info-actions';
-import { ToggleLockAction } from '../actions/lock-action';
-import { freezeProject, unfreezeProject } from 'store/projects/project-lock-actions';
+import { ContextMenuActionSet } from "../context-menu-action-set";
+import { NewProjectIcon, RenameIcon, MoveToIcon, DetailsIcon, AdvancedIcon, OpenIcon, Link, FolderSharedIcon } from "components/icon/icon";
+import { ToggleFavoriteAction } from "../actions/favorite-action";
+import { toggleFavorite } from "store/favorites/favorites-actions";
+import { favoritePanelActions } from "store/favorite-panel/favorite-panel-action";
+import { openMoveProjectDialog } from "store/projects/project-move-actions";
+import { openProjectCreateDialog } from "store/projects/project-create-actions";
+import { openProjectUpdateDialog } from "store/projects/project-update-actions";
+import { ToggleTrashAction } from "views-components/context-menu/actions/trash-action";
+import { toggleProjectTrashed } from "store/trash/trash-actions";
+import { ShareIcon } from "components/icon/icon";
+import { openSharingDialog } from "store/sharing-dialog/sharing-dialog-actions";
+import { openAdvancedTabDialog } from "store/advanced-tab/advanced-tab";
+import { toggleDetailsPanel } from "store/details-panel/details-panel-action";
+import { copyToClipboardAction, openInNewTabAction } from "store/open-in-new-tab/open-in-new-tab.actions";
+import { openWebDavS3InfoDialog } from "store/collections/collection-info-actions";
+import { ToggleLockAction } from "../actions/lock-action";
+import { freezeProject, unfreezeProject } from "store/projects/project-lock-actions";
 
 export const toggleFavoriteAction = {
     component: ToggleFavoriteAction,
-    name: 'ToggleFavoriteAction',
+    name: "ToggleFavoriteAction",
     execute: (dispatch, resources) => {
-        resources.forEach((resource) =>
+        resources.forEach(resource =>
             dispatch(toggleFavorite(resource)).then(() => {
                 dispatch(favoritePanelActions.REQUEST_ITEMS());
             })
@@ -35,15 +35,15 @@ export const toggleFavoriteAction = {
 
 export const openInNewTabMenuAction = {
     icon: OpenIcon,
-    name: 'Open in new tab',
+    name: "Open in new tab",
     execute: (dispatch, resources) => {
-        resources.forEach((resource) => dispatch(openInNewTabAction(resource)));
+        resources.forEach(resource => dispatch(openInNewTabAction(resource)));
     },
 };
 
 export const copyToClipboardMenuAction = {
     icon: Link,
-    name: 'Copy to clipboard',
+    name: "Copy to clipboard",
     execute: (dispatch, resources) => {
         dispatch(copyToClipboardAction(resources));
     },
@@ -51,76 +51,65 @@ export const copyToClipboardMenuAction = {
 
 export const viewDetailsAction = {
     icon: DetailsIcon,
-    name: 'View details',
-    execute: (dispatch) => {
+    name: "View details",
+    execute: dispatch => {
         dispatch(toggleDetailsPanel());
     },
 };
 
 export const advancedAction = {
     icon: AdvancedIcon,
-    name: 'API Details',
+    name: "API Details",
     execute: (dispatch, resources) => {
-        resources.forEach((resource) => dispatch(openAdvancedTabDialog(resource.uuid)));
+        resources.forEach(resource => dispatch(openAdvancedTabDialog(resource.uuid)));
     },
 };
 
 export const openWith3rdPartyClientAction = {
     icon: FolderSharedIcon,
-    name: 'Open with 3rd party client',
+    name: "Open with 3rd party client",
     execute: (dispatch, resources) => {
-        resources.forEach((resource) => dispatch(openWebDavS3InfoDialog(resource.uuid)));
+        resources.forEach(resource => dispatch(openWebDavS3InfoDialog(resource.uuid)));
     },
 };
 
 export const editProjectAction = {
     icon: RenameIcon,
-    name: 'Edit project',
+    name: "Edit project",
     execute: (dispatch, resources) => {
-        resources.forEach((resource) => dispatch(openProjectUpdateDialog(resource)));
+        resources.forEach(resource => dispatch(openProjectUpdateDialog(resource)));
     },
 };
 
 export const shareAction = {
     icon: ShareIcon,
-    name: 'Share',
+    name: "Share",
     execute: (dispatch, processes) => {
-        processes.forEach((process) => dispatch(openSharingDialog(process.uuid)));
+        processes.forEach(process => dispatch(openSharingDialog(process.uuid)));
     },
 };
 
 export const moveToAction = {
     icon: MoveToIcon,
-    name: 'Move to',
+    name: "Move to",
     execute: (dispatch, resources) => {
-        // resources.length === 1
-        //     ? dispatch(openMoveProjectDialog(resources[0]))
-        // : resources.forEach((resource) => {
         dispatch(openMoveProjectDialog(resources));
-        //   })
     },
-    // execute: (dispatch, resources) => {
-    //     resources.forEach((resource) => {
-    //         dispatch(openMoveProjectDialog(resource));
-    //     });
-    // },
 };
 
 export const toggleTrashAction = {
     component: ToggleTrashAction,
-    name: 'ToggleTrashAction',
+    name: "ToggleTrashAction",
     execute: (dispatch, resources) => {
-        resources.forEach((resource) =>
-            dispatch(toggleProjectTrashed(resource.uuid, resource.ownerUuid, resource.isTrashed!!, resources.length > 1))
-        );
+        resources.forEach(resource => dispatch(toggleProjectTrashed(resource.uuid, resource.ownerUuid, resource.isTrashed!!, resources.length > 1)));
     },
 };
 
 export const freezeProjectAction = {
     component: ToggleLockAction,
-    name: 'ToggleLockAction',
+    name: "ToggleLockAction",
     execute: (dispatch, resources) => {
-        resources.forEach((resource) => {
+        resources.forEach(resource => {
             if (resource.isFrozen) {
                 dispatch(unfreezeProject(resource.uuid));
             } else {
@@ -132,7 +121,7 @@ export const freezeProjectAction = {
 
 export const newProjectAction: any = {
     icon: NewProjectIcon,
-    name: 'New project',
+    name: "New project",
     execute: (dispatch, resource): void => {
         dispatch(openProjectCreateDialog(resource.uuid));
     },
index 9ee4106eb659af6099498dac6b8361cfe27a2030..a953500b3ae7a49f9216bce9544b24b3771a9982 100644 (file)
@@ -2,10 +2,9 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
-import { Dispatch } from 'redux';
-import { ContextMenuItem } from 'components/context-menu/context-menu';
-import { ContextMenuResource } from 'store/context-menu/context-menu-actions';
-import { RootState } from 'store/store';
+import { Dispatch } from "redux";
+import { ContextMenuItem } from "components/context-menu/context-menu";
+import { ContextMenuResource } from "store/context-menu/context-menu-actions";
 
 export interface ContextMenuAction extends ContextMenuItem {
     execute(dispatch: Dispatch, resources: ContextMenuResource[], state?: any): void;