17098: Adds ability to recover an old version collection as the head version.
authorLucas Di Pentima <lucas@di-pentima.com.ar>
Mon, 23 Nov 2020 22:38:16 +0000 (19:38 -0300)
committerLucas Di Pentima <lucas@di-pentima.com.ar>
Mon, 23 Nov 2020 22:38:16 +0000 (19:38 -0300)
This includes a proper menu action set for old collections with the new action.
Also, duplicated code was removed for the collection admin menu action set.

Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas@di-pentima.com.ar>

src/components/icon/icon.tsx
src/index.tsx
src/store/collections/collection-version-actions.ts [new file with mode: 0644]
src/views-components/context-menu/action-sets/collection-action-set.ts
src/views-components/context-menu/action-sets/collection-admin-action-set.ts [deleted file]
src/views-components/context-menu/context-menu.tsx

index 55c3c5a50f44759f10bbee681299b5ebe92cc32a..dbb4ccec2851b73495b247033e1d0a6dd100dc2c 100644 (file)
@@ -24,6 +24,7 @@ import DeviceHub from '@material-ui/icons/DeviceHub';
 import Edit from '@material-ui/icons/Edit';
 import ErrorRoundedIcon from '@material-ui/icons/ErrorRounded';
 import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
+import FlipToFront from '@material-ui/icons/FlipToFront';
 import Folder from '@material-ui/icons/Folder';
 import GetApp from '@material-ui/icons/GetApp';
 import Help from '@material-ui/icons/Help';
@@ -129,6 +130,7 @@ export const RemoveIcon: IconType = (props) => <Delete {...props} />;
 export const RemoveFavoriteIcon: IconType = (props) => <Star {...props} />;
 export const PublicFavoriteIcon: IconType = (props) => <Public {...props} />;
 export const RenameIcon: IconType = (props) => <Edit {...props} />;
+export const RecoverVersionIcon: IconType = (props) => <FlipToFront {...props} />;
 export const RestoreFromTrashIcon: IconType = (props) => <RestoreFromTrash {...props} />;
 export const ReRunProcessIcon: IconType = (props) => <Cached {...props} />;
 export const SearchIcon: IconType = (props) => <Search {...props} />;
index 569656d9117874646b238616330e25d640aa932e..98281b67d9ff5cfb4bca863ea7b5b5f2dd8ce27d 100644 (file)
@@ -27,7 +27,7 @@ import { favoriteActionSet } from "~/views-components/context-menu/action-sets/f
 import { collectionFilesActionSet, readOnlyCollectionFilesActionSet } from '~/views-components/context-menu/action-sets/collection-files-action-set';
 import { collectionFilesItemActionSet, readOnlyCollectionFilesItemActionSet } 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, readOnlyCollectionActionSet } from '~/views-components/context-menu/action-sets/collection-action-set';
+import { collectionActionSet, collectionAdminActionSet, oldCollectionVersionActionSet, readOnlyCollectionActionSet } from '~/views-components/context-menu/action-sets/collection-action-set';
 import { processActionSet } from '~/views-components/context-menu/action-sets/process-action-set';
 import { loadWorkbench } from '~/store/workbench/workbench-actions';
 import { Routes } from '~/routes/routes';
@@ -57,7 +57,6 @@ import { groupActionSet } from '~/views-components/context-menu/action-sets/grou
 import { groupMemberActionSet } from '~/views-components/context-menu/action-sets/group-member-action-set';
 import { linkActionSet } from '~/views-components/context-menu/action-sets/link-action-set';
 import { loadFileViewersConfig } from '~/store/file-viewers/file-viewers-actions';
-import { collectionAdminActionSet } from '~/views-components/context-menu/action-sets/collection-admin-action-set';
 import { processResourceAdminActionSet } from '~/views-components/context-menu/action-sets/process-resource-admin-action-set';
 import { projectAdminActionSet } from '~/views-components/context-menu/action-sets/project-admin-action-set';
 import { snackbarActions, SnackbarKind } from "~/store/snackbar/snackbar-actions";
@@ -78,6 +77,7 @@ addMenuActionSet(ContextMenuKind.COLLECTION_FILES_ITEM, collectionFilesItemActio
 addMenuActionSet(ContextMenuKind.READONLY_COLLECTION_FILES_ITEM, readOnlyCollectionFilesItemActionSet);
 addMenuActionSet(ContextMenuKind.COLLECTION, collectionActionSet);
 addMenuActionSet(ContextMenuKind.READONLY_COLLECTION, readOnlyCollectionActionSet);
+addMenuActionSet(ContextMenuKind.OLD_VERSION_COLLECTION, oldCollectionVersionActionSet);
 addMenuActionSet(ContextMenuKind.TRASHED_COLLECTION, trashedCollectionActionSet);
 addMenuActionSet(ContextMenuKind.PROCESS, processActionSet);
 addMenuActionSet(ContextMenuKind.PROCESS_RESOURCE, processResourceActionSet);
diff --git a/src/store/collections/collection-version-actions.ts b/src/store/collections/collection-version-actions.ts
new file mode 100644 (file)
index 0000000..68b6a18
--- /dev/null
@@ -0,0 +1,32 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { Dispatch } from "redux";
+import { RootState } from '~/store/store';
+import { ServiceRepository } from '~/services/services';
+import { snackbarActions, SnackbarKind } from "../snackbar/snackbar-actions";
+import { resourcesActions } from "../resources/resources-actions";
+import { navigateTo } from "../navigation/navigation-action";
+
+export const recoverVersion = (resourceUuid: string) =>
+    async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
+        try {
+            // Request que entire record because stored old versions usually
+            // don't include the manifest_text field.
+            const oldVersion = await services.collectionService.get(resourceUuid);
+            const { uuid, version, ...rest} = oldVersion;
+            const headVersion = await services.collectionService.update(
+                oldVersion.currentVersionUuid,
+                { ...rest }
+            );
+            dispatch(resourcesActions.SET_RESOURCES([headVersion]));
+            dispatch<any>(navigateTo(headVersion.uuid));
+        } catch (e) {
+            dispatch(snackbarActions.OPEN_SNACKBAR({
+                message: `Couldn't make new version: ${e.errors[0]}`,
+                hideDuration: 2000,
+                kind: SnackbarKind.ERROR
+            }));
+        }
+    };
index 4b6b9224df0f0cb5902ef11301e02739c5371be8..7e4c7b98ca7700d83f12ca20eb21f30172b43880 100644 (file)
@@ -5,7 +5,7 @@
 import { ContextMenuActionSet } from "../context-menu-action-set";
 import { ToggleFavoriteAction } from "../actions/favorite-action";
 import { toggleFavorite } from "~/store/favorites/favorites-actions";
-import { RenameIcon, ShareIcon, MoveToIcon, CopyIcon, DetailsIcon, AdvancedIcon, OpenIcon, Link } from "~/components/icon/icon";
+import { RenameIcon, ShareIcon, MoveToIcon, CopyIcon, DetailsIcon, AdvancedIcon, OpenIcon, Link, RecoverVersionIcon } from "~/components/icon/icon";
 import { openCollectionUpdateDialog } from "~/store/collections/collection-update-actions";
 import { favoritePanelActions } from "~/store/favorite-panel/favorite-panel-action";
 import { openMoveCollectionDialog } from '~/store/collections/collection-move-actions';
@@ -16,6 +16,10 @@ 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 { recoverVersion } from "~/store/collections/collection-version-actions";
+import { TogglePublicFavoriteAction } from "../actions/public-favorite-action";
+import { togglePublicFavorite } from "~/store/public-favorites/public-favorites-actions";
+import { publicFavoritePanelActions } from "~/store/public-favorites-panel/public-favorites-action";
 
 export const readOnlyCollectionActionSet: ContextMenuActionSet = [[
     {
@@ -96,3 +100,31 @@ export const collectionActionSet: ContextMenuActionSet = [
         },
     ]
 ];
+
+export const collectionAdminActionSet: ContextMenuActionSet = [
+    [
+        ...collectionActionSet.reduce((prev, next) => prev.concat(next), []),
+        {
+            component: TogglePublicFavoriteAction,
+            name: 'TogglePublicFavoriteAction',
+            execute: (dispatch, resource) => {
+                dispatch<any>(togglePublicFavorite(resource)).then(() => {
+                    dispatch<any>(publicFavoritePanelActions.REQUEST_ITEMS());
+                });
+            }
+        },
+    ]
+];
+
+export const oldCollectionVersionActionSet: ContextMenuActionSet = [
+    [
+        ...readOnlyCollectionActionSet.reduce((prev, next) => prev.concat(next), []),
+        {
+            icon: RecoverVersionIcon,
+            name: 'Recover version',
+            execute: (dispatch, { uuid }) => {
+                dispatch<any>(recoverVersion(uuid));
+            }
+        },
+    ]
+];
\ No newline at end of file
diff --git a/src/views-components/context-menu/action-sets/collection-admin-action-set.ts b/src/views-components/context-menu/action-sets/collection-admin-action-set.ts
deleted file mode 100644 (file)
index 7b39d74..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-import { ContextMenuActionSet } from "../context-menu-action-set";
-import { ToggleFavoriteAction } from "../actions/favorite-action";
-import { toggleFavorite } from "~/store/favorites/favorites-actions";
-import { RenameIcon, ShareIcon, MoveToIcon, CopyIcon, DetailsIcon, AdvancedIcon, OpenIcon, Link } from "~/components/icon/icon";
-import { openCollectionUpdateDialog } from "~/store/collections/collection-update-actions";
-import { favoritePanelActions } from "~/store/favorite-panel/favorite-panel-action";
-import { openMoveCollectionDialog } from '~/store/collections/collection-move-actions';
-import { openCollectionCopyDialog } from "~/store/collections/collection-copy-actions";
-import { ToggleTrashAction } from "~/views-components/context-menu/actions/trash-action";
-import { toggleCollectionTrashed } from "~/store/trash/trash-actions";
-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 { TogglePublicFavoriteAction } from "~/views-components/context-menu/actions/public-favorite-action";
-import { publicFavoritePanelActions } from "~/store/public-favorites-panel/public-favorites-action";
-import { togglePublicFavorite } from "~/store/public-favorites/public-favorites-actions";
-import { copyToClipboardAction, openInNewTabAction } from "~/store/open-in-new-tab/open-in-new-tab.actions";
-
-export const collectionAdminActionSet: ContextMenuActionSet = [[
-    {
-        icon: RenameIcon,
-        name: "Edit collection",
-        execute: (dispatch, resource) => {
-            dispatch<any>(openCollectionUpdateDialog(resource));
-        }
-    },
-    {
-        icon: OpenIcon,
-        name: "Open in new tab",
-        execute: (dispatch, resource) => {
-            dispatch<any>(openInNewTabAction(resource));
-        }
-    },
-    {
-        icon: Link,
-        name: "Copy to clipboard",
-        execute: (dispatch, resource) => {
-            dispatch<any>(copyToClipboardAction(resource));
-        }
-    },
-    {
-        icon: ShareIcon,
-        name: "Share",
-        execute: (dispatch, { uuid }) => {
-            dispatch<any>(openSharingDialog(uuid));
-        }
-    },
-    {
-        component: ToggleFavoriteAction,
-        name: 'ToggleFavoriteAction',
-        execute: (dispatch, resource) => {
-            dispatch<any>(toggleFavorite(resource)).then(() => {
-                dispatch<any>(favoritePanelActions.REQUEST_ITEMS());
-            });
-        }
-    },
-    {
-        component: TogglePublicFavoriteAction,
-        name: 'TogglePublicFavoriteAction',
-        execute: (dispatch, resource) => {
-            dispatch<any>(togglePublicFavorite(resource)).then(() => {
-                dispatch<any>(publicFavoritePanelActions.REQUEST_ITEMS());
-            });
-        }
-    },
-    {
-        icon: MoveToIcon,
-        name: "Move to",
-        execute: (dispatch, resource) => dispatch<any>(openMoveCollectionDialog(resource))
-    },
-    {
-        icon: CopyIcon,
-        name: "Make a copy",
-        execute: (dispatch, resource) => {
-            dispatch<any>(openCollectionCopyDialog(resource));
-        }
-
-    },
-    {
-        icon: DetailsIcon,
-        name: "View details",
-        execute: dispatch => {
-            dispatch<any>(toggleDetailsPanel());
-        }
-    },
-    {
-        icon: AdvancedIcon,
-        name: "Advanced",
-        execute: (dispatch, resource) => {
-            dispatch<any>(openAdvancedTabDialog(resource.uuid));
-        }
-    },
-    {
-        component: ToggleTrashAction,
-        name: 'ToggleTrashAction',
-        execute: (dispatch, resource) => {
-            dispatch<any>(toggleCollectionTrashed(resource.uuid, resource.isTrashed!!));
-        }
-    },
-]];
index b86498a0e9687dfa7fce6e2e2306ee263569ef30..219913cdd13ce4a2549779159a8ab8f62a4be9c7 100644 (file)
@@ -80,6 +80,7 @@ export enum ContextMenuKind {
     COLLECTION = 'Collection',
     COLLECTION_ADMIN = 'CollectionAdmin',
     READONLY_COLLECTION = 'ReadOnlyCollection',
+    OLD_VERSION_COLLECTION = 'OldVersionCollection',
     TRASHED_COLLECTION = 'TrashedCollection',
     PROCESS = "Process",
     PROCESS_ADMIN = 'ProcessAdmin',