20031: Add multiple/single collection files context menu to selectively show actions...
authorStephen Smith <stephen@curii.com>
Mon, 22 May 2023 13:45:31 +0000 (09:45 -0400)
committerStephen Smith <stephen@curii.com>
Mon, 22 May 2023 13:45:31 +0000 (09:45 -0400)
Arvados-DCO-1.1-Signed-off-by: Stephen Smith <stephen@curii.com>

src/index.tsx
src/store/collection-panel/collection-panel-files/collection-panel-files-state.ts
src/store/context-menu/context-menu-actions.ts
src/views-components/context-menu/action-sets/collection-files-action-set.ts
src/views-components/context-menu/context-menu.tsx

index 244d1387307778de1f0c4ccd01412bdc85797ccd..9293dd74f38879e3024f969118b6fa358376b394 100644 (file)
@@ -25,7 +25,7 @@ import { rootProjectActionSet } from "views-components/context-menu/action-sets/
 import { filterGroupActionSet, frozenActionSet, projectActionSet, readOnlyProjectActionSet } from "views-components/context-menu/action-sets/project-action-set";
 import { resourceActionSet } from 'views-components/context-menu/action-sets/resource-action-set';
 import { favoriteActionSet } from "views-components/context-menu/action-sets/favorite-action-set";
-import { collectionFilesActionSet, readOnlyCollectionFilesActionSet } from 'views-components/context-menu/action-sets/collection-files-action-set';
+import { collectionFilesActionSet, collectionFilesMultipleActionSet, readOnlyCollectionFilesActionSet, readOnlyCollectionFilesMultipleActionSet } from 'views-components/context-menu/action-sets/collection-files-action-set';
 import { collectionDirectoryItemActionSet, collectionFileItemActionSet, readOnlyCollectionDirectoryItemActionSet, readOnlyCollectionFileItemActionSet } from 'views-components/context-menu/action-sets/collection-files-item-action-set';
 import { collectionFilesNotSelectedActionSet } from 'views-components/context-menu/action-sets/collection-files-not-selected-action-set';
 import { collectionActionSet, collectionAdminActionSet, oldCollectionVersionActionSet, readOnlyCollectionActionSet } from 'views-components/context-menu/action-sets/collection-action-set';
@@ -77,7 +77,9 @@ addMenuActionSet(ContextMenuKind.FILTER_GROUP, filterGroupActionSet);
 addMenuActionSet(ContextMenuKind.RESOURCE, resourceActionSet);
 addMenuActionSet(ContextMenuKind.FAVORITE, favoriteActionSet);
 addMenuActionSet(ContextMenuKind.COLLECTION_FILES, collectionFilesActionSet);
+addMenuActionSet(ContextMenuKind.COLLECTION_FILES_MULTIPLE, collectionFilesMultipleActionSet);
 addMenuActionSet(ContextMenuKind.READONLY_COLLECTION_FILES, readOnlyCollectionFilesActionSet);
+addMenuActionSet(ContextMenuKind.READONLY_COLLECTION_FILES_MULTIPLE, readOnlyCollectionFilesMultipleActionSet);
 addMenuActionSet(ContextMenuKind.COLLECTION_FILES_NOT_SELECTED, collectionFilesNotSelectedActionSet);
 addMenuActionSet(ContextMenuKind.COLLECTION_DIRECTORY_ITEM, collectionDirectoryItemActionSet);
 addMenuActionSet(ContextMenuKind.READONLY_COLLECTION_DIRECTORY_ITEM, readOnlyCollectionDirectoryItemActionSet);
index 405e7eac093040a8bbfd80ce7f3f5700d1b0c456..d987c84a98061438c1f03a6d2f8a6c896ad739dc 100644 (file)
@@ -36,7 +36,7 @@ export const mergeCollectionPanelFilesStates = (oldState: CollectionPanelFilesSt
     })(newState);
 };
 
-export const filterCollectionFilesBySelection = (tree: CollectionPanelFilesState, selected: boolean) => {
+export const filterCollectionFilesBySelection = (tree: CollectionPanelFilesState, selected: boolean): (CollectionPanelFile | CollectionPanelDirectory)[] => {
     const allFiles = getNodeDescendants('')(tree).map(node => node.value);
     const selectedDirectories = allFiles.filter(file => file.selected === selected && file.type === CollectionFileType.DIRECTORY);
     const selectedFiles = allFiles.filter(file => file.selected === selected && !selectedDirectories.some(dir => dir.id === file.path));
index 3bc91ae0c74c1464aecb5e5c7d0ba7b3b56a0353..e659de8a6c39c02e2d7ddbf188df4d1d7892d9bb 100644 (file)
@@ -23,6 +23,7 @@ import { GroupContentsResource } from 'services/groups-service/groups-service';
 import { LinkResource } from 'models/link';
 import { resourceIsFrozen } from 'common/frozen-resources';
 import { ProjectResource } from 'models/project';
+import { filterCollectionFilesBySelection } from 'store/collection-panel/collection-panel-files/collection-panel-files-state';
 
 export const contextMenuActions = unionize({
     OPEN_CONTEXT_MENU: ofType<{ position: ContextMenuPosition, resource: ContextMenuResource }>(),
@@ -67,17 +68,18 @@ export const openContextMenu = (event: React.MouseEvent<HTMLElement>, resource:
 
 export const openCollectionFilesContextMenu = (event: React.MouseEvent<HTMLElement>, isWritable: boolean) =>
     (dispatch: Dispatch, getState: () => RootState) => {
-        const isCollectionFileSelected = JSON.stringify(getState().collectionPanelFiles).includes('"selected":true');
+        const selectedCount = filterCollectionFilesBySelection(getState().collectionPanelFiles, true).length;
+        const multiple = selectedCount > 1;
         dispatch<any>(openContextMenu(event, {
             name: '',
             uuid: '',
             ownerUuid: '',
             description: '',
             kind: ResourceKind.COLLECTION,
-            menuKind: isCollectionFileSelected
+            menuKind: selectedCount > 0
                 ? isWritable
-                    ? ContextMenuKind.COLLECTION_FILES
-                    : ContextMenuKind.READONLY_COLLECTION_FILES
+                    ? multiple ? ContextMenuKind.COLLECTION_FILES_MULTIPLE : ContextMenuKind.COLLECTION_FILES
+                    : multiple ? ContextMenuKind.READONLY_COLLECTION_FILES_MULTIPLE : ContextMenuKind.READONLY_COLLECTION_FILES
                 : ContextMenuKind.COLLECTION_FILES_NOT_SELECTED
         }));
     };
index c1c541d33a9a3b2016c0ccba0bc3177e9aa5a6b6..06f7789e36c20aae9ea8b7849492d45698bda8d9 100644 (file)
@@ -2,7 +2,7 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
-import { ContextMenuActionSet } from "views-components/context-menu/context-menu-action-set";
+import { ContextMenuAction, ContextMenuActionSet } from "views-components/context-menu/context-menu-action-set";
 import { collectionPanelFilesAction, openMultipleFilesRemoveDialog } from "store/collection-panel/collection-panel-files/collection-panel-files-actions";
 import {
     openCollectionPartialCopyToNewCollectionDialog,
@@ -11,20 +11,7 @@ import {
 } from 'store/collections/collection-partial-copy-actions';
 import { openCollectionPartialMoveToExistingCollectionDialog, openCollectionPartialMoveToNewCollectionDialog, openCollectionPartialMoveToSeparateCollectionsDialog } from "store/collections/collection-partial-move-actions";
 
-// These action sets are used on the multi-select actions button.
-export const readOnlyCollectionFilesActionSet: ContextMenuActionSet = [[
-    {
-        name: "Select all",
-        execute: dispatch => {
-            dispatch(collectionPanelFilesAction.SELECT_ALL_COLLECTION_FILES());
-        }
-    },
-    {
-        name: "Unselect all",
-        execute: dispatch => {
-            dispatch(collectionPanelFilesAction.UNSELECT_ALL_COLLECTION_FILES());
-        }
-    },
+const copyActions: ContextMenuAction[] = [
     {
         name: "Copy selected into new collection",
         execute: dispatch => {
@@ -37,21 +24,19 @@ export const readOnlyCollectionFilesActionSet: ContextMenuActionSet = [[
             dispatch<any>(openCollectionPartialCopyToExistingCollectionDialog());
         }
     },
+];
+
+const copyActionsMultiple: ContextMenuAction[] = [
+    ...copyActions,
     {
         name: "Copy selected into separate collections",
         execute: dispatch => {
             dispatch<any>(openCollectionPartialCopyToSeparateCollectionsDialog());
         }
     }
-]];
+];
 
-export const collectionFilesActionSet: ContextMenuActionSet = readOnlyCollectionFilesActionSet.concat([[
-    {
-        name: "Remove selected",
-        execute: dispatch => {
-            dispatch(openMultipleFilesRemoveDialog());
-        }
-    },
+const moveActions: ContextMenuAction[] = [
     {
         name: "Move selected into new collection",
         execute: dispatch => {
@@ -64,10 +49,57 @@ export const collectionFilesActionSet: ContextMenuActionSet = readOnlyCollection
             dispatch<any>(openCollectionPartialMoveToExistingCollectionDialog());
         }
     },
+];
+
+const moveActionsMultiple: ContextMenuAction[] = [
+    ...moveActions,
     {
         name: "Move selected into separate collections",
         execute: dispatch => {
             dispatch<any>(openCollectionPartialMoveToSeparateCollectionsDialog());
         }
     }
+];
+
+const selectActions: ContextMenuAction[] = [
+    {
+        name: "Select all",
+        execute: dispatch => {
+            dispatch(collectionPanelFilesAction.SELECT_ALL_COLLECTION_FILES());
+        }
+    },
+    {
+        name: "Unselect all",
+        execute: dispatch => {
+            dispatch(collectionPanelFilesAction.UNSELECT_ALL_COLLECTION_FILES());
+        }
+    },
+];
+
+const removeAction: ContextMenuAction = {
+    name: "Remove selected",
+    execute: dispatch => {
+        dispatch(openMultipleFilesRemoveDialog());
+    }
+};
+
+// These action sets are used on the multi-select actions button.
+export const readOnlyCollectionFilesActionSet: ContextMenuActionSet = [
+    selectActions,
+    copyActions,
+];
+
+export const readOnlyCollectionFilesMultipleActionSet: ContextMenuActionSet = [
+    selectActions,
+    copyActionsMultiple,
+];
+
+export const collectionFilesActionSet: ContextMenuActionSet = readOnlyCollectionFilesActionSet.concat([[
+    removeAction,
+    ...moveActions
+]]);
+
+export const collectionFilesMultipleActionSet: ContextMenuActionSet = readOnlyCollectionFilesMultipleActionSet.concat([[
+    removeAction,
+    ...moveActionsMultiple
 ]]);
index c659b7c508a7fd7af4cc2887742aabd4a773edc5..81c1a51e261bae4cf6b09c170da2f934de227ec7 100644 (file)
@@ -87,12 +87,14 @@ export enum ContextMenuKind {
     FAVORITE = "Favorite",
     TRASH = "Trash",
     COLLECTION_FILES = "CollectionFiles",
+    COLLECTION_FILES_MULTIPLE = "CollectionFilesMultiple",
     READONLY_COLLECTION_FILES = "ReadOnlyCollectionFiles",
+    READONLY_COLLECTION_FILES_MULTIPLE = "ReadOnlyCollectionFilesMultiple",
+    COLLECTION_FILES_NOT_SELECTED = "CollectionFilesNotSelected",
     COLLECTION_FILE_ITEM = "CollectionFileItem",
     COLLECTION_DIRECTORY_ITEM = "CollectionDirectoryItem",
     READONLY_COLLECTION_FILE_ITEM = "ReadOnlyCollectionFileItem",
     READONLY_COLLECTION_DIRECTORY_ITEM = "ReadOnlyCollectionDirectoryItem",
-    COLLECTION_FILES_NOT_SELECTED = "CollectionFilesNotSelected",
     COLLECTION = 'Collection',
     COLLECTION_ADMIN = 'CollectionAdmin',
     READONLY_COLLECTION = 'ReadOnlyCollection',