Post merge fixes
authorDaniel Kos <daniel.kos@contractors.roche.com>
Thu, 30 Aug 2018 21:44:55 +0000 (23:44 +0200)
committerDaniel Kos <daniel.kos@contractors.roche.com>
Thu, 30 Aug 2018 21:44:55 +0000 (23:44 +0200)
Feature #13828

Arvados-DCO-1.1-Signed-off-by: Daniel Kos <daniel.kos@contractors.roche.com>

20 files changed:
src/models/container-request.ts [new file with mode: 0644]
src/models/process.ts
src/routes/routes.ts
src/services/ancestors-service/ancestors-service.ts
src/services/collection-service/collection-service.ts
src/store/collections/collection-trash-actions.ts [deleted file]
src/store/context-menu/context-menu-actions.ts
src/store/project/project-action.ts [deleted file]
src/store/store.ts
src/store/trash-panel/trash-panel-action.ts
src/store/trash-panel/trash-panel-middleware-service.ts
src/store/trash/trash-actions.ts [new file with mode: 0644]
src/store/workbench/workbench-actions.ts
src/views-components/context-menu/action-sets/collection-action-set.ts
src/views-components/context-menu/action-sets/collection-resource-action-set.ts
src/views-components/context-menu/action-sets/project-action-set.ts
src/views/favorite-panel/favorite-panel.tsx
src/views/project-panel/project-panel.tsx
src/views/trash-panel/trash-panel.tsx
src/views/workbench/workbench.tsx

diff --git a/src/models/container-request.ts b/src/models/container-request.ts
new file mode 100644 (file)
index 0000000..78891c7
--- /dev/null
@@ -0,0 +1,41 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { Resource, ResourceKind } from "./resource";
+import { MountType } from "~/models/mount-types";
+import { RuntimeConstraints } from './runtime-constraints';
+import { SchedulingParameters } from './scheduling-parameters';
+
+export enum ContainerRequestState {
+    UNCOMMITTED = "Uncommitted",
+    COMMITTED = "Committed",
+    FINAL = "Final"
+}
+
+export interface ContainerRequestResource extends Resource {
+    kind: ResourceKind.CONTAINER_REQUEST;
+    name: string;
+    description: string;
+    properties: any;
+    state: ContainerRequestState;
+    requestingContainerUuid: string | null;
+    containerUuid: string | null;
+    containerCountMax: number;
+    mounts: MountType[];
+    runtimeConstraints: RuntimeConstraints;
+    schedulingParameters: SchedulingParameters;
+    containerImage: string;
+    environment: any;
+    cwd: string;
+    command: string[];
+    outputPath: string;
+    outputName: string;
+    outputTtl: number;
+    priority: number | null;
+    expiresAt: string;
+    useExisting: boolean;
+    logUuid: string | null;
+    outputUuid: string | null;
+    filters: string;
+}
index bcfbd3a557faa074bb9c654fa50eadd39039dfd7..1e04cb10f395de5284765fbb50244d2e45d4ea1d 100644 (file)
@@ -2,37 +2,6 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
-import { Resource, ResourceKind } from "./resource";
+import { ContainerRequestResource } from "./container-request";
 
-export enum ProcessState {
-    UNCOMMITTED = "Uncommitted",
-    COMMITTED = "Committed",
-    FINAL = "Final"
-}
-
-export interface ProcessResource extends Resource {
-    kind: ResourceKind.PROCESS;
-    name: string;
-    description: string;
-    properties: any;
-    state: ProcessState;
-    requestingContainerUuid: string;
-    containerUuid: string;
-    containerCountMax: number;
-    mounts: any;
-    runtimeConstraints: any;
-    schedulingParameters: any;
-    containerImage: string;
-    environment: any;
-    cwd: string;
-    command: string[];
-    outputPath: string;
-    outputName: string;
-    outputTtl: number;
-    priority: number;
-    expiresAt: string;
-    useExisting: boolean;
-    logUuid: string;
-    outputUuid: string;
-    filters: string;
-}
+export type ProcessResource = ContainerRequestResource;
index 20dd1359b34b626f66ab3b0de959e85a2c28b38f..d1193218bd24ae4d0491b92bc6efc651954f26ec 100644 (file)
@@ -6,9 +6,9 @@ import { History, Location } from 'history';
 import { RootStore } from '~/store/store';
 import { matchPath } from 'react-router';
 import { ResourceKind, RESOURCE_UUID_PATTERN, extractUuidKind } from '~/models/resource';
-import { getProjectUrl } from '../models/project';
+import { getProjectUrl } from '~/models/project';
 import { getCollectionUrl } from '~/models/collection';
-import { loadProject, loadFavorites, loadCollection } from '~/store/workbench/workbench-actions';
+import { loadProject, loadFavorites, loadCollection, loadTrash } from '~/store/workbench/workbench-actions';
 import { loadProcess } from '~/store/processes/processes-actions';
 
 export const Routes = {
@@ -18,6 +18,7 @@ export const Routes = {
     COLLECTIONS: `/collections/:id(${RESOURCE_UUID_PATTERN})`,
     PROCESSES: `/processes/:id(${RESOURCE_UUID_PATTERN})`,
     FAVORITES: '/favorites',
+    TRASH: '/trash'
 };
 
 export const getResourceUrl = (uuid: string) => {
@@ -40,15 +41,18 @@ export const addRouteChangeHandlers = (history: History, store: RootStore) => {
     history.listen(handler);
 };
 
+export interface ResourceRouteParams {
+    id: string;
+}
+
 export const matchRootRoute = (route: string) =>
     matchPath(route, { path: Routes.ROOT, exact: true });
 
 export const matchFavoritesRoute = (route: string) =>
     matchPath(route, { path: Routes.FAVORITES });
 
-export interface ResourceRouteParams {
-    id: string;
-}
+export const matchTrashRoute = (route: string) =>
+    matchPath(route, { path: Routes.TRASH });
 
 export const matchProjectRoute = (route: string) =>
     matchPath<ResourceRouteParams>(route, { path: Routes.PROJECTS });
@@ -64,6 +68,7 @@ const handleLocationChange = (store: RootStore) => ({ pathname }: Location) => {
     const projectMatch = matchProjectRoute(pathname);
     const collectionMatch = matchCollectionRoute(pathname);
     const favoriteMatch = matchFavoritesRoute(pathname);
+    const trashMatch = matchTrashRoute(pathname);
     const processMatch = matchProcessRoute(pathname);
     if (projectMatch) {
         store.dispatch(loadProject(projectMatch.params.id));
@@ -71,6 +76,8 @@ const handleLocationChange = (store: RootStore) => ({ pathname }: Location) => {
         store.dispatch(loadCollection(collectionMatch.params.id));
     } else if (favoriteMatch) {
         store.dispatch(loadFavorites());
+    } else if (trashMatch) {
+        store.dispatch(loadTrash());
     } else if (processMatch) {
         store.dispatch(loadProcess(processMatch.params.id));
     }
index 1cd42fb523945c3a6a5918b24b0474780dabe908..daab58b3fc38ecd8d4ef5cac39c7169dcacbebff 100644 (file)
@@ -6,7 +6,7 @@ import { GroupsService } from "~/services/groups-service/groups-service";
 import { UserService } from '../user-service/user-service';
 import { GroupResource } from '~/models/group';
 import { UserResource } from '~/models/user';
-import { extractUuidObjectType, ResourceObjectType } from "~/models/resource";
+import { extractUuidObjectType, ResourceObjectType, TrashResource } from "~/models/resource";
 
 export class AncestorService {
     constructor(
@@ -14,7 +14,7 @@ export class AncestorService {
         private userService: UserService
     ) { }
 
-    async ancestors(uuid: string, rootUuid: string): Promise<Array<UserResource | GroupResource>> {
+    async ancestors(uuid: string, rootUuid: string): Promise<Array<UserResource | GroupResource | TrashResource>> {
         const service = this.getService(extractUuidObjectType(uuid));
         if (service) {
             const resource = await service.get(uuid);
@@ -41,4 +41,4 @@ export class AncestorService {
                 return undefined;
         }
     }
-}
\ No newline at end of file
+}
index e26da78875b91963a6a1e51703f2a1f9ffbc17cc..581747b95cb1afa92821f6eebe5e34573251b397 100644 (file)
@@ -11,6 +11,7 @@ import { AuthService } from "../auth-service/auth-service";
 import { mapTreeValues } from "~/models/tree";
 import { parseFilesResponse } from "./collection-service-files-response";
 import { fileToArrayBuffer } from "~/common/file";
+import * as _ from 'lodash';
 
 export type UploadProgress = (fileId: number, loaded: number, total: number, currentTime: number) => void;
 
@@ -84,5 +85,5 @@ export class CollectionService extends CommonResourceService<CollectionResource>
             })
             .then(CommonResourceService.mapResponseKeys);
     }
-    
+
 }
diff --git a/src/store/collections/collection-trash-actions.ts b/src/store/collections/collection-trash-actions.ts
deleted file mode 100644 (file)
index c6d4ee0..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-// 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 } from "~/store/snackbar/snackbar-actions";
-import { sidePanelActions } from "~/store/side-panel/side-panel-action";
-import { SidePanelId } from "~/store/side-panel/side-panel-reducer";
-import { trashPanelActions } from "~/store/trash-panel/trash-panel-action";
-import { getProjectList, projectActions } from "~/store/project/project-action";
-
-export const toggleCollectionTrashed = (resource: { uuid: string; name: string, isTrashed?: boolean, ownerUuid?: string }) =>
-    async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository): Promise<any> => {
-        dispatch(snackbarActions.OPEN_SNACKBAR({ message: "Working..." }));
-        if (resource.isTrashed) {
-            return services.collectionService.untrash(resource.uuid).then(() => {
-                dispatch<any>(getProjectList(resource.ownerUuid)).then(() => {
-                    dispatch(sidePanelActions.TOGGLE_SIDE_PANEL_ITEM_OPEN(SidePanelId.PROJECTS));
-                    dispatch(projectActions.TOGGLE_PROJECT_TREE_ITEM_OPEN({ itemId: resource.ownerUuid!!, open: true, recursive: true }));
-                });
-                dispatch(trashPanelActions.REQUEST_ITEMS());
-                dispatch(snackbarActions.CLOSE_SNACKBAR());
-                dispatch(snackbarActions.OPEN_SNACKBAR({
-                    message: "Restored from trash",
-                    hideDuration: 2000
-                }));
-            });
-        } else {
-            return services.collectionService.trash(resource.uuid).then(() => {
-                dispatch(snackbarActions.CLOSE_SNACKBAR());
-                dispatch(snackbarActions.OPEN_SNACKBAR({
-                    message: "Added to trash",
-                    hideDuration: 2000
-                }));
-            });
-        }
-    };
index a1ed6c5536bc4b71bb2b6b8e26ed5fc4f16dfcf7..5ec3a84b6fbc395b02802331de207c0e2b9cf6c3 100644 (file)
@@ -27,7 +27,7 @@ export type ContextMenuResource = {
     description?: string;
     kind: ContextMenuKind;
     isTrashed?: boolean;
-}
+};
 
 export const openContextMenu = (event: React.MouseEvent<HTMLElement>, resource: ContextMenuResource) =>
     (dispatch: Dispatch) => {
diff --git a/src/store/project/project-action.ts b/src/store/project/project-action.ts
deleted file mode 100644 (file)
index bb5da19..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-import { default as unionize, ofType, UnionOf } from "unionize";
-
-import { ProjectResource } from "~/models/project";
-import { Dispatch } from "redux";
-import { FilterBuilder } from "~/common/api/filter-builder";
-import { RootState } from "../store";
-import { checkPresenceInFavorites } from "../favorites/favorites-actions";
-import { ServiceRepository } from "~/services/services";
-import { projectPanelActions } from "~/store/project-panel/project-panel-action";
-import { updateDetails } from "~/store/details-panel/details-panel-action";
-import { snackbarActions } from "~/store/snackbar/snackbar-actions";
-import { trashPanelActions } from "~/store/trash-panel/trash-panel-action";
-import { sidePanelActions } from "~/store/side-panel/side-panel-action";
-import { SidePanelId } from "~/store/side-panel/side-panel-reducer";
-
-export const projectActions = unionize({
-    OPEN_PROJECT_CREATOR: ofType<{ ownerUuid: string }>(),
-    CLOSE_PROJECT_CREATOR: ofType<{}>(),
-    CREATE_PROJECT: ofType<Partial<ProjectResource>>(),
-    CREATE_PROJECT_SUCCESS: ofType<ProjectResource>(),
-    OPEN_PROJECT_UPDATER: ofType<{ uuid: string}>(),
-    CLOSE_PROJECT_UPDATER: ofType<{}>(),
-    UPDATE_PROJECT_SUCCESS: ofType<ProjectResource>(),
-    REMOVE_PROJECT: ofType<string>(),
-    PROJECTS_REQUEST: ofType<string>(),
-    PROJECTS_SUCCESS: ofType<{ projects: ProjectResource[], parentItemId?: string }>(),
-    TOGGLE_PROJECT_TREE_ITEM_OPEN: ofType<{ itemId: string, open?: boolean, recursive?: boolean }>(),
-    TOGGLE_PROJECT_TREE_ITEM_ACTIVE: ofType<{ itemId: string, active?: boolean, recursive?: boolean }>(),
-    RESET_PROJECT_TREE_ACTIVITY: ofType<string>()
-}, {
-    tag: 'type',
-    value: 'payload'
-});
-
-export const PROJECT_FORM_NAME = 'projectEditDialog';
-
-export const getProjectList = (parentUuid: string = '') =>
-    (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
-        dispatch(projectActions.PROJECTS_REQUEST(parentUuid));
-        return services.projectService.list({
-            filters: new FilterBuilder()
-                .addEqual("ownerUuid", parentUuid)
-                .getFilters()
-        }).then(({ items: projects }) => {
-            dispatch(projectActions.PROJECTS_SUCCESS({ projects, parentItemId: parentUuid }));
-            dispatch<any>(checkPresenceInFavorites(projects.map(project => project.uuid)));
-            return projects;
-        });
-    };
-
-export const createProject = (project: Partial<ProjectResource>) =>
-    (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
-        const { ownerUuid } = getState().projects.creator;
-        const projectData = { ownerUuid, ...project };
-        dispatch(projectActions.CREATE_PROJECT(projectData));
-        return services.projectService
-            .create(projectData)
-            .then(project => dispatch(projectActions.CREATE_PROJECT_SUCCESS(project)));
-    };
-
-export const updateProject = (project: Partial<ProjectResource>) =>
-    (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
-        const { uuid } = getState().projects.updater;
-        return services.projectService
-            .update(uuid, project)
-            .then(project => {
-                dispatch(projectActions.UPDATE_PROJECT_SUCCESS(project));
-                dispatch(projectPanelActions.REQUEST_ITEMS());
-                dispatch<any>(getProjectList(project.ownerUuid));
-                dispatch<any>(updateDetails(project));
-            });
-    };
-
-export const toggleProjectTrashed = (resource: { uuid: string; name: string, isTrashed?: boolean, ownerUuid?: string }) =>
-    async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository): Promise<any> => {
-        dispatch(snackbarActions.OPEN_SNACKBAR({ message: "Working..." }));
-        if (resource.isTrashed) {
-            return services.groupsService.untrash(resource.uuid).then(() => {
-                dispatch<any>(getProjectList(resource.ownerUuid)).then(() => {
-                    dispatch(sidePanelActions.TOGGLE_SIDE_PANEL_ITEM_OPEN(SidePanelId.PROJECTS));
-                    dispatch(projectActions.TOGGLE_PROJECT_TREE_ITEM_OPEN({ itemId: resource.ownerUuid!!, open: true, recursive: true }));
-                });
-                dispatch(trashPanelActions.REQUEST_ITEMS());
-                dispatch(snackbarActions.CLOSE_SNACKBAR());
-                dispatch(snackbarActions.OPEN_SNACKBAR({
-                    message: "Restored from trash",
-                    hideDuration: 2000
-                }));
-            });
-        } else {
-            return services.groupsService.trash(resource.uuid).then(() => {
-                dispatch<any>(getProjectList(resource.ownerUuid)).then(() => {
-                    dispatch(projectActions.TOGGLE_PROJECT_TREE_ITEM_OPEN({ itemId: resource.ownerUuid!!, open: true, recursive: true }));
-                });
-                dispatch(snackbarActions.CLOSE_SNACKBAR());
-                dispatch(snackbarActions.OPEN_SNACKBAR({
-                    message: "Added to trash",
-                    hideDuration: 2000
-                }));
-            });
-        }
-    };
-
-export type ProjectAction = UnionOf<typeof projectActions>;
index 584d05e923fd55d8f443be7512c7f16f88234c26..d2371e831768cb3b41811725709174a7416a9861 100644 (file)
@@ -28,6 +28,8 @@ import { resourcesReducer } from '~/store/resources/resources-reducer';
 import { propertiesReducer } from './properties/properties-reducer';
 import { RootState } from './store';
 import { fileUploaderReducer } from './file-uploader/file-uploader-reducer';
+import { TrashPanelMiddlewareService } from "~/store/trash-panel/trash-panel-middleware-service";
+import { TRASH_PANEL_ID } from "~/store/trash-panel/trash-panel-action";
 
 const composeEnhancers =
     (process.env.NODE_ENV === 'development' &&
index 84d5602457516f91e61c732ad1239d2831c99dd3..6be93228be73d438d5b2c8c0f00dd0ba5c46c1ec 100644 (file)
@@ -3,6 +3,9 @@
 // SPDX-License-Identifier: AGPL-3.0
 
 import { bindDataExplorerActions } from "../data-explorer/data-explorer-action";
+import { favoritePanelActions } from "~/store/favorite-panel/favorite-panel-action";
 
 export const TRASH_PANEL_ID = "trashPanel";
 export const trashPanelActions = bindDataExplorerActions(TRASH_PANEL_ID);
+
+export const loadTrashPanel = () => trashPanelActions.REQUEST_ITEMS();
index 3a4da39606ae9a9051883804187e4874ea3f9c22..85bc0ad7739c73a5ac1066835685d3d178b3197e 100644 (file)
@@ -8,7 +8,6 @@ import { DataColumns } from "~/components/data-table/data-table";
 import { ServiceRepository } from "~/services/services";
 import { SortDirection } from "~/components/data-table/data-column";
 import { FilterBuilder } from "~/common/api/filter-builder";
-import { checkPresenceInFavorites } from "../favorites/favorites-actions";
 import { trashPanelActions } from "./trash-panel-action";
 import { Dispatch, MiddlewareAPI } from "redux";
 import { OrderBuilder, OrderDirection } from "~/common/api/order-builder";
@@ -17,6 +16,7 @@ import { resourceToDataItem, TrashPanelItem } from "~/views/trash-panel/trash-pa
 import { TrashPanelColumnNames, TrashPanelFilter } from "~/views/trash-panel/trash-panel";
 import { ProjectResource } from "~/models/project";
 import { ProjectPanelColumnNames } from "~/views/project-panel/project-panel";
+import { updateFavorites } from "~/store/favorites/favorites-actions";
 
 export class TrashPanelMiddlewareService extends DataExplorerMiddlewareService {
     constructor(private services: ServiceRepository, id: string) {
@@ -64,7 +64,7 @@ export class TrashPanelMiddlewareService extends DataExplorerMiddlewareService {
                     page: Math.floor(response.offset / response.limit),
                     rowsPerPage: response.limit
                 }));
-                api.dispatch<any>(checkPresenceInFavorites(response.items.map(item => item.uuid)));
+                api.dispatch<any>(updateFavorites(response.items.map(item => item.uuid)));
             })
             .catch(() => {
                 api.dispatch(trashPanelActions.SET_ITEMS({
diff --git a/src/store/trash/trash-actions.ts b/src/store/trash/trash-actions.ts
new file mode 100644 (file)
index 0000000..97d8185
--- /dev/null
@@ -0,0 +1,66 @@
+// 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 } from "~/store/snackbar/snackbar-actions";
+import { trashPanelActions } from "~/store/trash-panel/trash-panel-action";
+
+export const toggleProjectTrashed = (resource: { uuid: string; name: string, isTrashed?: boolean, ownerUuid?: string }) =>
+    async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository): Promise<any> => {
+        dispatch(snackbarActions.OPEN_SNACKBAR({ message: "Working..." }));
+        if (resource.isTrashed) {
+            return services.groupsService.untrash(resource.uuid).then(() => {
+                // dispatch<any>(getProjectList(resource.ownerUuid)).then(() => {
+                //     dispatch(sidePanelActions.TOGGLE_SIDE_PANEL_ITEM_OPEN(SidePanelId.PROJECTS));
+                //     dispatch(projectActions.TOGGLE_PROJECT_TREE_ITEM_OPEN({ itemId: resource.ownerUuid!!, open: true, recursive: true }));
+                // });
+                dispatch(trashPanelActions.REQUEST_ITEMS());
+                dispatch(snackbarActions.CLOSE_SNACKBAR());
+                dispatch(snackbarActions.OPEN_SNACKBAR({
+                    message: "Restored from trash",
+                    hideDuration: 2000
+                }));
+            });
+        } else {
+            return services.groupsService.trash(resource.uuid).then(() => {
+                // dispatch<any>(getProjectList(resource.ownerUuid)).then(() => {
+                //     dispatch(projectActions.TOGGLE_PROJECT_TREE_ITEM_OPEN({ itemId: resource.ownerUuid!!, open: true, recursive: true }));
+                // });
+                dispatch(snackbarActions.CLOSE_SNACKBAR());
+                dispatch(snackbarActions.OPEN_SNACKBAR({
+                    message: "Added to trash",
+                    hideDuration: 2000
+                }));
+            });
+        }
+    };
+
+export const toggleCollectionTrashed = (resource: { uuid: string; name: string, isTrashed?: boolean, ownerUuid?: string }) =>
+    async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository): Promise<any> => {
+        dispatch(snackbarActions.OPEN_SNACKBAR({ message: "Working..." }));
+        if (resource.isTrashed) {
+            return services.collectionService.untrash(resource.uuid).then(() => {
+                // dispatch<any>(getProjectList(resource.ownerUuid)).then(() => {
+                //     dispatch(sidePanelActions.TOGGLE_SIDE_PANEL_ITEM_OPEN(SidePanelId.PROJECTS));
+                //     dispatch(projectActions.TOGGLE_PROJECT_TREE_ITEM_OPEN({ itemId: resource.ownerUuid!!, open: true, recursive: true }));
+                // });
+                dispatch(trashPanelActions.REQUEST_ITEMS());
+                dispatch(snackbarActions.CLOSE_SNACKBAR());
+                dispatch(snackbarActions.OPEN_SNACKBAR({
+                    message: "Restored from trash",
+                    hideDuration: 2000
+                }));
+            });
+        } else {
+            return services.collectionService.trash(resource.uuid).then(() => {
+                dispatch(snackbarActions.CLOSE_SNACKBAR());
+                dispatch(snackbarActions.OPEN_SNACKBAR({
+                    message: "Added to trash",
+                    hideDuration: 2000
+                }));
+            });
+        }
+    };
index 3c68c0004519b15a73fca9a9c5553b316e3a68e5..012ef90fa7d87bf712167be2eb86d2ec30297abd 100644 (file)
@@ -30,6 +30,8 @@ import * as collectionUpdateActions from '~/store/collections/collection-update-
 import * as collectionMoveActions from '~/store/collections/collection-move-actions';
 import * as processesActions from '../processes/processes-actions';
 import { getProcess } from '../processes/process';
+import { trashPanelColumns } from "~/views/trash-panel/trash-panel";
+import { loadTrashPanel, trashPanelActions } from "~/store/trash-panel/trash-panel-action";
 
 
 export const loadWorkbench = () =>
@@ -41,6 +43,7 @@ export const loadWorkbench = () =>
             if (userResource) {
                 dispatch(projectPanelActions.SET_COLUMNS({ columns: projectPanelColumns }));
                 dispatch(favoritePanelActions.SET_COLUMNS({ columns: favoritePanelColumns }));
+                dispatch(trashPanelActions.SET_COLUMNS({ columns: trashPanelColumns }));
                 dispatch<any>(initSidePanelTree());
                 if (router.location) {
                     const match = matchRootRoute(router.location.pathname);
@@ -63,6 +66,12 @@ export const loadFavorites = () =>
         dispatch<any>(setSidePanelBreadcrumbs(SidePanelTreeCategory.FAVORITES));
     };
 
+export const loadTrash = () =>
+    (dispatch: Dispatch) => {
+        dispatch<any>(activateSidePanelTreeItem(SidePanelTreeCategory.TRASH));
+        dispatch<any>(loadTrashPanel());
+        dispatch<any>(setSidePanelBreadcrumbs(SidePanelTreeCategory.TRASH));
+    };
 
 export const loadProject = (uuid: string) =>
     async (dispatch: Dispatch) => {
@@ -204,4 +213,4 @@ const reloadProjectMatchingUuid = (matchingUuids: string[]) =>
         if (currentProjectPanelUuid && matchingUuids.some(uuid => uuid === currentProjectPanelUuid)) {
             dispatch<any>(loadProject(currentProjectPanelUuid));
         }
-    };
\ No newline at end of file
+    };
index f26003653382701cf8b700143bd30db830788c46..a7d16c680f636655a19b4b0f70981ac703bf338a 100644 (file)
@@ -11,7 +11,7 @@ import { favoritePanelActions } from "~/store/favorite-panel/favorite-panel-acti
 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/collections/collection-trash-actions";
+import { toggleCollectionTrashed } from "~/store/trash/trash-actions";
 
 export const collectionActionSet: ContextMenuActionSet = [[
     {
index a1df8385a4e1ad1a4a369412c5815d31a9cebb83..f1df0c08a84a8ad2531b374b927823a6cca289cc 100644 (file)
@@ -11,6 +11,7 @@ import { openCollectionUpdateDialog } from "~/store/collections/collection-updat
 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 { toggleCollectionTrashed } from "~/store/trash/trash-actions";
 
 export const collectionResourceActionSet: ContextMenuActionSet = [[
     {
index d2412e7eda495394e339d25cee97f76cff517d02..eca395bbcab728172404593598521b2f7aeac289 100644 (file)
@@ -2,32 +2,30 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
-import { reset, initialize } from "redux-form";
-
 import { ContextMenuActionSet } from "../context-menu-action-set";
-import { projectActions, PROJECT_FORM_NAME, toggleProjectTrashed } from "~/store/project/project-action";
-import { NewProjectIcon, RenameIcon } from "~/components/icon/icon";
+import { NewProjectIcon, RenameIcon, CopyIcon, MoveToIcon } 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 { PROJECT_CREATE_DIALOG } from "../../dialog-create/dialog-project-create";
+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";
 
 export const projectActionSet: ContextMenuActionSet = [[
     {
         icon: NewProjectIcon,
         name: "New project",
         execute: (dispatch, resource) => {
-            dispatch(reset(PROJECT_CREATE_DIALOG));
-            dispatch(projectActions.OPEN_PROJECT_CREATOR({ ownerUuid: resource.uuid }));
+            dispatch<any>(openProjectCreateDialog(resource.uuid));
         }
     },
     {
         icon: RenameIcon,
         name: "Edit project",
         execute: (dispatch, resource) => {
-            dispatch(projectActions.OPEN_PROJECT_UPDATER({ uuid: resource.uuid }));
-            dispatch(initialize(PROJECT_FORM_NAME, { name: resource.name, description: resource.description }));
+            dispatch<any>(openProjectUpdateDialog(resource));
         }
     },
     {
@@ -43,5 +41,17 @@ export const projectActionSet: ContextMenuActionSet = [[
         execute: (dispatch, resource) => {
             dispatch<any>(toggleProjectTrashed(resource));
         }
-    }
+    },
+    {
+        icon: MoveToIcon,
+        name: "Move to",
+        execute: (dispatch, resource) => dispatch<any>(openMoveProjectDialog(resource))
+    },
+    {
+        icon: CopyIcon,
+        name: "Copy to project",
+        execute: (dispatch, resource) => {
+            // add code
+        }
+    },
 ]];
index 62b037e3a56da989baa16aa1c91679c2d47a7a77..b915f980b91009dcc74ae9c349e22118312ca4f4 100644 (file)
@@ -9,7 +9,6 @@ import { DispatchProp, connect } from 'react-redux';
 import { DataColumns } from '~/components/data-table/data-table';
 import { RouteComponentProps } from 'react-router';
 import { DataTableFilterItem } from '~/components/data-table-filters/data-table-filters';
-import { ProcessState } from '~/models/process';
 import { SortDirection } from '~/components/data-table/data-column';
 import { ResourceKind } from '~/models/resource';
 import { resourceLabel } from '~/common/labels';
@@ -18,10 +17,10 @@ import { FAVORITE_PANEL_ID } from "~/store/favorite-panel/favorite-panel-action"
 import { ResourceFileSize, ResourceLastModifiedDate, ProcessStatus, ResourceType, ResourceOwner, ResourceName } from '~/views-components/data-explorer/renderers';
 import { FavoriteIcon } from '~/components/icon/icon';
 import { Dispatch } from 'redux';
-import { contextMenuActions, openContextMenu, resourceKindToContextMenuKind } from '~/store/context-menu/context-menu-actions';
-import { ContextMenuKind } from '~/views-components/context-menu/context-menu';
-import { loadDetailsPanel } from '../../store/details-panel/details-panel-action';
+import { openContextMenu, resourceKindToContextMenuKind } from '~/store/context-menu/context-menu-actions';
+import { loadDetailsPanel } from '~/store/details-panel/details-panel-action';
 import { navigateTo } from '~/store/navigation/navigation-action';
+import { ContainerRequestState } from "~/models/container-request";
 
 type CssRules = "toolbar" | "button";
 
@@ -45,7 +44,7 @@ export enum FavoritePanelColumnNames {
 }
 
 export interface FavoritePanelFilter extends DataTableFilterItem {
-    type: ResourceKind | ProcessState;
+    type: ResourceKind | ContainerRequestState;
 }
 
 export const favoritePanelColumns: DataColumns<string, FavoritePanelFilter> = [
@@ -65,19 +64,19 @@ export const favoritePanelColumns: DataColumns<string, FavoritePanelFilter> = [
         sortDirection: SortDirection.NONE,
         filters: [
             {
-                name: ProcessState.COMMITTED,
+                name: ContainerRequestState.COMMITTED,
                 selected: true,
-                type: ProcessState.COMMITTED
+                type: ContainerRequestState.COMMITTED
             },
             {
-                name: ProcessState.FINAL,
+                name: ContainerRequestState.FINAL,
                 selected: true,
-                type: ProcessState.FINAL
+                type: ContainerRequestState.FINAL
             },
             {
-                name: ProcessState.UNCOMMITTED,
+                name: ContainerRequestState.UNCOMMITTED,
                 selected: true,
-                type: ProcessState.UNCOMMITTED
+                type: ContainerRequestState.UNCOMMITTED
             }
         ],
         render: uuid => <ProcessStatus uuid={uuid} />,
index 37a6d202214a6fb1b80114ad4805fac08aace93f..3c7dd30c24c1396b66580c33586a1c4e7138222d 100644 (file)
@@ -10,7 +10,6 @@ import { DataColumns } from '~/components/data-table/data-table';
 import { RouteComponentProps } from 'react-router';
 import { RootState } from '~/store/store';
 import { DataTableFilterItem } from '~/components/data-table-filters/data-table-filters';
-import { ProcessState } from '~/models/process';
 import { SortDirection } from '~/components/data-table/data-column';
 import { ResourceKind } from '~/models/resource';
 import { resourceLabel } from '~/common/labels';
@@ -18,17 +17,15 @@ import { ArvadosTheme } from '~/common/custom-theme';
 import { ResourceFileSize, ResourceLastModifiedDate, ProcessStatus, ResourceType, ResourceOwner } from '~/views-components/data-explorer/renderers';
 import { ProjectIcon } from '~/components/icon/icon';
 import { ResourceName } from '~/views-components/data-explorer/renderers';
-import { ResourcesState, getResource } from '~/store/resources/resources';
+import { ResourcesState } from '~/store/resources/resources';
 import { loadDetailsPanel } from '~/store/details-panel/details-panel-action';
-import { ContextMenuKind } from '~/views-components/context-menu/context-menu';
-import { contextMenuActions, resourceKindToContextMenuKind, openContextMenu } from '~/store/context-menu/context-menu-actions';
-import { CollectionResource } from '~/models/collection';
-import { ProjectResource } from '~/models/project';
+import { resourceKindToContextMenuKind, openContextMenu } from '~/store/context-menu/context-menu-actions';
 import { navigateTo } from '~/store/navigation/navigation-action';
 import { getProperty } from '~/store/properties/properties';
 import { PROJECT_PANEL_CURRENT_UUID } from '~/store/project-panel/project-panel-action';
 import { openCollectionCreateDialog } from '../../store/collections/collection-create-actions';
 import { openProjectCreateDialog } from '~/store/projects/project-create-actions';
+import { ContainerRequestState } from "~/models/container-request";
 
 type CssRules = 'root' | "toolbar" | "button";
 
@@ -57,7 +54,7 @@ export enum ProjectPanelColumnNames {
 }
 
 export interface ProjectPanelFilter extends DataTableFilterItem {
-    type: ResourceKind | ProcessState;
+    type: ResourceKind | ContainerRequestState;
 }
 
 export const projectPanelColumns: DataColumns<string, ProjectPanelFilter> = [
@@ -77,19 +74,19 @@ export const projectPanelColumns: DataColumns<string, ProjectPanelFilter> = [
         sortDirection: SortDirection.NONE,
         filters: [
             {
-                name: ProcessState.COMMITTED,
+                name: ContainerRequestState.COMMITTED,
                 selected: true,
-                type: ProcessState.COMMITTED
+                type: ContainerRequestState.COMMITTED
             },
             {
-                name: ProcessState.FINAL,
+                name: ContainerRequestState.FINAL,
                 selected: true,
-                type: ProcessState.FINAL
+                type: ContainerRequestState.FINAL
             },
             {
-                name: ProcessState.UNCOMMITTED,
+                name: ContainerRequestState.UNCOMMITTED,
                 selected: true,
-                type: ProcessState.UNCOMMITTED
+                type: ContainerRequestState.UNCOMMITTED
             }
         ],
         render: uuid => <ProcessStatus uuid={uuid} />,
index fa73c0b0f83a2c746ef973800d3d80cba08ab94d..bfb99310b82640c61594794a9e2e5fbafcf0241a 100644 (file)
@@ -18,6 +18,8 @@ import { ArvadosTheme } from '~/common/custom-theme';
 import { renderName, renderType, renderFileSize, renderDate } from '~/views-components/data-explorer/renderers';
 import { TrashIcon } from '~/components/icon/icon';
 import { TRASH_PANEL_ID } from "~/store/trash-panel/trash-panel-action";
+import { getProperty } from "~/store/properties/properties";
+import { PROJECT_PANEL_CURRENT_UUID } from "~/store/project-panel/project-panel-action";
 
 type CssRules = "toolbar" | "button";
 
@@ -43,7 +45,7 @@ export interface TrashPanelFilter extends DataTableFilterItem {
     type: ResourceKind;
 }
 
-export const columns: DataColumns<TrashPanelItem, TrashPanelFilter> = [
+export const trashPanelColumns: DataColumns<TrashPanelItem, TrashPanelFilter> = [
     {
         name: TrashPanelColumnNames.NAME,
         selected: true,
@@ -119,16 +121,17 @@ interface TrashPanelActionProps {
     onItemRouteChange: (itemId: string) => void;
 }
 
-type TrashPanelProps = TrashPanelDataProps & TrashPanelActionProps & DispatchProp
-                        & WithStyles<CssRules> & RouteComponentProps<{ id: string }>;
+type TrashPanelProps = TrashPanelDataProps & TrashPanelActionProps & DispatchProp & WithStyles<CssRules>;
 
 export const TrashPanel = withStyles(styles)(
-    connect((state: RootState) => ({ currentItemId: state.projects.currentItemId }))(
+    connect((state: RootState) => ({
+        currentItemId: getProperty(PROJECT_PANEL_CURRENT_UUID)(state.properties),
+        resources: state.resources
+    }))(
         class extends React.Component<TrashPanelProps> {
             render() {
                 return <DataExplorer
                     id={TRASH_PANEL_ID}
-                    columns={columns}
                     onRowClick={this.props.onItemClick}
                     onRowDoubleClick={this.props.onItemDoubleClick}
                     onContextMenu={this.props.onContextMenu}
@@ -137,12 +140,6 @@ export const TrashPanel = withStyles(styles)(
                     defaultMessages={['Your trash list is empty.']}/>
                 ;
             }
-
-            componentWillReceiveProps({ match, currentItemId, onItemRouteChange }: TrashPanelProps) {
-                if (match.params.id !== currentItemId) {
-                    onItemRouteChange(match.params.id);
-                }
-            }
         }
     )
 );
index ea3a278bf9090cbe73b29a2a0b64f4b357d6e399..68bb970073317f00844fdf04e74a388920d527f2 100644 (file)
@@ -40,7 +40,6 @@ import { FilesUploadCollectionDialog } from '~/views-components/dialog-forms/fil
 import { PartialCopyCollectionDialog } from '~/views-components/dialog-forms/partial-copy-collection-dialog';
 
 import { TrashPanel } from "~/views/trash-panel/trash-panel";
-import { trashPanelActions } from "~/store/trash-panel/trash-panel-action";
 
 const APP_BAR_HEIGHT = 100;
 
@@ -170,7 +169,7 @@ export const Workbench = withStyles(styles)(
                                     <Route path={Routes.COLLECTIONS} component={CollectionPanel} />
                                     <Route path={Routes.FAVORITES} component={FavoritePanel} />
                                     <Route path={Routes.PROCESSES} component={ProcessPanel} />
-                                    <Route path="/trash" render={this.renderTrashPanel} />
+                                    <Route path={Routes.TRASH} component={TrashPanel} />
                                 </Switch>
                             </div>
                             {user && <DetailsPanel />}