Merge branch '15768-multi-select-operations'
[arvados-workbench2.git] / src / store / workbench / workbench-actions.ts
index 8401ba95652f964f7e6adec8cdfee7d5a2b03ced..956fa3d9a24a05379f45b1ef0c697b6097dea4f3 100644 (file)
@@ -8,12 +8,8 @@ import { getUserUuid } from "common/getuser";
 import { loadDetailsPanel } from "store/details-panel/details-panel-action";
 import { snackbarActions, SnackbarKind } from "store/snackbar/snackbar-actions";
 import { favoritePanelActions, loadFavoritePanel } from "store/favorite-panel/favorite-panel-action";
-import {
-    getProjectPanelCurrentUuid,
-    openProjectPanel,
-    projectPanelActions,
-    setIsProjectPanelTrashed,
-} from "store/project-panel/project-panel-action";
+import { getProjectPanelCurrentUuid, setIsProjectPanelTrashed } from "store/project-panel/project-panel-action";
+import { projectPanelActions } from "store/project-panel/project-panel-action-bind";
 import {
     activateSidePanelTreeItem,
     initSidePanelTree,
@@ -100,7 +96,8 @@ import { loadAllProcessesPanel, allProcessesPanelActions } from "../all-processe
 import { allProcessesPanelColumns } from "views/all-processes-panel/all-processes-panel";
 import { AdminMenuIcon } from "components/icon/icon";
 import { userProfileGroupsColumns } from "views/user-profile-panel/user-profile-panel-root";
-import { selectedToArray, selectedToKindSet } from "components/multiselectToolbar/MultiselectToolbar";
+import { selectedToArray, selectedToKindSet } from "components/multiselect-toolbar/MultiselectToolbar";
+import { multiselectActions } from "store/multiselect/multiselect-actions";
 
 export const WORKBENCH_LOADING_SCREEN = "workbenchLoadingScreen";
 
@@ -282,9 +279,9 @@ export const moveProject =
     (data: MoveToFormDialogData, isSecondaryMove = false) =>
     async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
         const checkedList = getState().multiselect.checkedList;
-        const uuidsToMove: string[] = selectedToArray(checkedList);
+        const uuidsToMove: string[] = data.fromContextMenu ? [data.uuid] : selectedToArray(checkedList);
 
-        //if no items in checkedlist && no items passed in, default to normal context menu behavior
+        //if no items in checkedlist default to normal context menu behavior
         if (!isSecondaryMove && !uuidsToMove.length) uuidsToMove.push(data.uuid);
 
         const sourceUuid = getResource(data.uuid)(getState().resources)?.ownerUuid;
@@ -331,7 +328,6 @@ export const moveProject =
                         kind: SnackbarKind.ERROR,
                     })
                 );
-                // }
             }
         }
         if (sourceUuid) await dispatch<any>(loadSidePanelTreeProjects(sourceUuid));
@@ -426,36 +422,60 @@ export const createCollection = (data: collectionCreateActions.CollectionCreateF
 };
 
 export const copyCollection = (data: CopyFormDialogData) => async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
-    try {
-        const copyToProject = getResource(data.ownerUuid)(getState().resources);
-        const collection = await dispatch<any>(collectionCopyActions.copyCollection(data));
-        if (copyToProject && collection) {
-            dispatch<any>(reloadProjectMatchingUuid([copyToProject.uuid]));
+    const checkedList = getState().multiselect.checkedList;
+    const uuidsToCopy: string[] = data.fromContextMenu ? [data.uuid] : selectedToArray(checkedList);
+
+    //if no items in checkedlist && no items passed in, default to normal context menu behavior
+    if (!uuidsToCopy.length) uuidsToCopy.push(data.uuid);
+
+    const collectionsToCopy: CollectionCopyResource[] = uuidsToCopy
+        .map(uuid => getResource(uuid)(getState().resources) as CollectionCopyResource)
+        .filter(resource => resource.kind === ResourceKind.COLLECTION);
+
+    for (const collection of collectionsToCopy) {
+        await copySingleCollection({ ...collection, ownerUuid: data.ownerUuid } as CollectionCopyResource);
+    }
+
+    async function copySingleCollection(copyToProject: CollectionCopyResource) {
+        const newName = data.fromContextMenu || collectionsToCopy.length === 1 ? data.name : `Copy of: ${copyToProject.name}`;
+        try {
+            const collection = await dispatch<any>(
+                collectionCopyActions.copyCollection({
+                    ...copyToProject,
+                    name: newName,
+                    fromContextMenu: collectionsToCopy.length === 1 ? true : data.fromContextMenu,
+                })
+            );
+            if (copyToProject && collection) {
+                await dispatch<any>(reloadProjectMatchingUuid([copyToProject.uuid]));
+                dispatch(
+                    snackbarActions.OPEN_SNACKBAR({
+                        message: "Collection has been copied.",
+                        hideDuration: 3000,
+                        kind: SnackbarKind.SUCCESS,
+                        link: collection.ownerUuid,
+                    })
+                );
+                dispatch<any>(multiselectActions.deselectOne(copyToProject.uuid));
+            }
+        } catch (e) {
             dispatch(
                 snackbarActions.OPEN_SNACKBAR({
-                    message: "Collection has been copied.",
-                    hideDuration: 3000,
-                    kind: SnackbarKind.SUCCESS,
-                    link: collection.ownerUuid,
+                    message: e.message,
+                    hideDuration: 2000,
+                    kind: SnackbarKind.ERROR,
                 })
             );
         }
-    } catch (e) {
-        dispatch(
-            snackbarActions.OPEN_SNACKBAR({
-                message: e.message,
-                hideDuration: 2000,
-                kind: SnackbarKind.ERROR,
-            })
-        );
     }
+    dispatch(projectPanelActions.REQUEST_ITEMS());
 };
 
 export const moveCollection =
     (data: MoveToFormDialogData, isSecondaryMove = false) =>
     async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
         const checkedList = getState().multiselect.checkedList;
-        const uuidsToMove: string[] = selectedToArray(checkedList);
+        const uuidsToMove: string[] = data.fromContextMenu ? [data.uuid] : selectedToArray(checkedList);
 
         //if no items in checkedlist && no items passed in, default to normal context menu behavior
         if (!isSecondaryMove && !uuidsToMove.length) uuidsToMove.push(data.uuid);
@@ -577,7 +597,7 @@ export const moveProcess =
     (data: MoveToFormDialogData, isSecondaryMove = false) =>
     async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
         const checkedList = getState().multiselect.checkedList;
-        const uuidsToMove: string[] = selectedToArray(checkedList);
+        const uuidsToMove: string[] = data.fromContextMenu ? [data.uuid] : selectedToArray(checkedList);
 
         //if no items in checkedlist && no items passed in, default to normal context menu behavior
         if (!isSecondaryMove && !uuidsToMove.length) uuidsToMove.push(data.uuid);
@@ -762,7 +782,6 @@ export const loadGroupDetailsPanel = (groupUuid: string) =>
 
 const finishLoadingProject = (project: GroupContentsResource | string) => async (dispatch: Dispatch<any>) => {
     const uuid = typeof project === "string" ? project : project.uuid;
-    dispatch(openProjectPanel(uuid));
     dispatch(loadDetailsPanel(uuid));
     if (typeof project !== "string") {
         dispatch(updateResources([project]));
@@ -812,6 +831,8 @@ const groupContentsHandlers = unionize(groupContentsHandlersRecord);
 
 type GroupContentsHandler = UnionOf<typeof groupContentsHandlers>;
 
+type CollectionCopyResource = Resource & { name: string; fromContextMenu: boolean };
+
 type MoveableResource = Resource & { name: string };
 
 type MoveFunc = (