From 25691034b44b9323cae96c8db002826880ccfd7e Mon Sep 17 00:00:00 2001 From: Daniel Kos Date: Thu, 30 Aug 2018 23:44:55 +0200 Subject: [PATCH] Post merge fixes Feature #13828 Arvados-DCO-1.1-Signed-off-by: Daniel Kos --- src/models/container-request.ts | 41 +++++++ src/models/process.ts | 35 +----- src/routes/routes.ts | 17 ++- .../ancestors-service/ancestors-service.ts | 6 +- .../collection-service/collection-service.ts | 3 +- .../collections/collection-trash-actions.ts | 39 ------- .../context-menu/context-menu-actions.ts | 2 +- src/store/project/project-action.ts | 107 ------------------ src/store/store.ts | 2 + src/store/trash-panel/trash-panel-action.ts | 3 + .../trash-panel-middleware-service.ts | 4 +- src/store/trash/trash-actions.ts | 66 +++++++++++ src/store/workbench/workbench-actions.ts | 11 +- .../action-sets/collection-action-set.ts | 2 +- .../collection-resource-action-set.ts | 1 + .../action-sets/project-action-set.ts | 30 +++-- src/views/favorite-panel/favorite-panel.tsx | 21 ++-- src/views/project-panel/project-panel.tsx | 23 ++-- src/views/trash-panel/trash-panel.tsx | 19 ++-- src/views/workbench/workbench.tsx | 3 +- 20 files changed, 195 insertions(+), 240 deletions(-) create mode 100644 src/models/container-request.ts delete mode 100644 src/store/collections/collection-trash-actions.ts delete mode 100644 src/store/project/project-action.ts create mode 100644 src/store/trash/trash-actions.ts diff --git a/src/models/container-request.ts b/src/models/container-request.ts new file mode 100644 index 00000000..78891c7b --- /dev/null +++ b/src/models/container-request.ts @@ -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; +} diff --git a/src/models/process.ts b/src/models/process.ts index bcfbd3a5..1e04cb10 100644 --- a/src/models/process.ts +++ b/src/models/process.ts @@ -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; diff --git a/src/routes/routes.ts b/src/routes/routes.ts index 20dd1359..d1193218 100644 --- a/src/routes/routes.ts +++ b/src/routes/routes.ts @@ -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(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)); } diff --git a/src/services/ancestors-service/ancestors-service.ts b/src/services/ancestors-service/ancestors-service.ts index 1cd42fb5..daab58b3 100644 --- a/src/services/ancestors-service/ancestors-service.ts +++ b/src/services/ancestors-service/ancestors-service.ts @@ -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> { + async ancestors(uuid: string, rootUuid: string): Promise> { 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 +} diff --git a/src/services/collection-service/collection-service.ts b/src/services/collection-service/collection-service.ts index e26da788..581747b9 100644 --- a/src/services/collection-service/collection-service.ts +++ b/src/services/collection-service/collection-service.ts @@ -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 }) .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 index c6d4ee0a..00000000 --- a/src/store/collections/collection-trash-actions.ts +++ /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 => { - dispatch(snackbarActions.OPEN_SNACKBAR({ message: "Working..." })); - if (resource.isTrashed) { - return services.collectionService.untrash(resource.uuid).then(() => { - dispatch(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 - })); - }); - } - }; diff --git a/src/store/context-menu/context-menu-actions.ts b/src/store/context-menu/context-menu-actions.ts index a1ed6c55..5ec3a84b 100644 --- a/src/store/context-menu/context-menu-actions.ts +++ b/src/store/context-menu/context-menu-actions.ts @@ -27,7 +27,7 @@ export type ContextMenuResource = { description?: string; kind: ContextMenuKind; isTrashed?: boolean; -} +}; export const openContextMenu = (event: React.MouseEvent, resource: ContextMenuResource) => (dispatch: Dispatch) => { diff --git a/src/store/project/project-action.ts b/src/store/project/project-action.ts deleted file mode 100644 index bb5da199..00000000 --- a/src/store/project/project-action.ts +++ /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>(), - CREATE_PROJECT_SUCCESS: ofType(), - OPEN_PROJECT_UPDATER: ofType<{ uuid: string}>(), - CLOSE_PROJECT_UPDATER: ofType<{}>(), - UPDATE_PROJECT_SUCCESS: ofType(), - REMOVE_PROJECT: ofType(), - PROJECTS_REQUEST: ofType(), - 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() -}, { - 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(checkPresenceInFavorites(projects.map(project => project.uuid))); - return projects; - }); - }; - -export const createProject = (project: Partial) => - (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) => - (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(getProjectList(project.ownerUuid)); - dispatch(updateDetails(project)); - }); - }; - -export const toggleProjectTrashed = (resource: { uuid: string; name: string, isTrashed?: boolean, ownerUuid?: string }) => - async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository): Promise => { - dispatch(snackbarActions.OPEN_SNACKBAR({ message: "Working..." })); - if (resource.isTrashed) { - return services.groupsService.untrash(resource.uuid).then(() => { - dispatch(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(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; diff --git a/src/store/store.ts b/src/store/store.ts index 584d05e9..d2371e83 100644 --- a/src/store/store.ts +++ b/src/store/store.ts @@ -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' && diff --git a/src/store/trash-panel/trash-panel-action.ts b/src/store/trash-panel/trash-panel-action.ts index 84d56024..6be93228 100644 --- a/src/store/trash-panel/trash-panel-action.ts +++ b/src/store/trash-panel/trash-panel-action.ts @@ -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(); diff --git a/src/store/trash-panel/trash-panel-middleware-service.ts b/src/store/trash-panel/trash-panel-middleware-service.ts index 3a4da396..85bc0ad7 100644 --- a/src/store/trash-panel/trash-panel-middleware-service.ts +++ b/src/store/trash-panel/trash-panel-middleware-service.ts @@ -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(checkPresenceInFavorites(response.items.map(item => item.uuid))); + api.dispatch(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 index 00000000..97d81853 --- /dev/null +++ b/src/store/trash/trash-actions.ts @@ -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 => { + dispatch(snackbarActions.OPEN_SNACKBAR({ message: "Working..." })); + if (resource.isTrashed) { + return services.groupsService.untrash(resource.uuid).then(() => { + // dispatch(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(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 => { + dispatch(snackbarActions.OPEN_SNACKBAR({ message: "Working..." })); + if (resource.isTrashed) { + return services.collectionService.untrash(resource.uuid).then(() => { + // dispatch(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 + })); + }); + } + }; diff --git a/src/store/workbench/workbench-actions.ts b/src/store/workbench/workbench-actions.ts index 3c68c000..012ef90f 100644 --- a/src/store/workbench/workbench-actions.ts +++ b/src/store/workbench/workbench-actions.ts @@ -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(initSidePanelTree()); if (router.location) { const match = matchRootRoute(router.location.pathname); @@ -63,6 +66,12 @@ export const loadFavorites = () => dispatch(setSidePanelBreadcrumbs(SidePanelTreeCategory.FAVORITES)); }; +export const loadTrash = () => + (dispatch: Dispatch) => { + dispatch(activateSidePanelTreeItem(SidePanelTreeCategory.TRASH)); + dispatch(loadTrashPanel()); + dispatch(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(loadProject(currentProjectPanelUuid)); } - }; \ No newline at end of file + }; diff --git a/src/views-components/context-menu/action-sets/collection-action-set.ts b/src/views-components/context-menu/action-sets/collection-action-set.ts index f2600365..a7d16c68 100644 --- a/src/views-components/context-menu/action-sets/collection-action-set.ts +++ b/src/views-components/context-menu/action-sets/collection-action-set.ts @@ -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 = [[ { diff --git a/src/views-components/context-menu/action-sets/collection-resource-action-set.ts b/src/views-components/context-menu/action-sets/collection-resource-action-set.ts index a1df8385..f1df0c08 100644 --- a/src/views-components/context-menu/action-sets/collection-resource-action-set.ts +++ b/src/views-components/context-menu/action-sets/collection-resource-action-set.ts @@ -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 = [[ { diff --git a/src/views-components/context-menu/action-sets/project-action-set.ts b/src/views-components/context-menu/action-sets/project-action-set.ts index d2412e7e..eca395bb 100644 --- a/src/views-components/context-menu/action-sets/project-action-set.ts +++ b/src/views-components/context-menu/action-sets/project-action-set.ts @@ -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(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(openProjectUpdateDialog(resource)); } }, { @@ -43,5 +41,17 @@ export const projectActionSet: ContextMenuActionSet = [[ execute: (dispatch, resource) => { dispatch(toggleProjectTrashed(resource)); } - } + }, + { + icon: MoveToIcon, + name: "Move to", + execute: (dispatch, resource) => dispatch(openMoveProjectDialog(resource)) + }, + { + icon: CopyIcon, + name: "Copy to project", + execute: (dispatch, resource) => { + // add code + } + }, ]]; diff --git a/src/views/favorite-panel/favorite-panel.tsx b/src/views/favorite-panel/favorite-panel.tsx index 62b037e3..b915f980 100644 --- a/src/views/favorite-panel/favorite-panel.tsx +++ b/src/views/favorite-panel/favorite-panel.tsx @@ -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 = [ @@ -65,19 +64,19 @@ export const favoritePanelColumns: DataColumns = [ 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 => , diff --git a/src/views/project-panel/project-panel.tsx b/src/views/project-panel/project-panel.tsx index 37a6d202..3c7dd30c 100644 --- a/src/views/project-panel/project-panel.tsx +++ b/src/views/project-panel/project-panel.tsx @@ -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 = [ @@ -77,19 +74,19 @@ export const projectPanelColumns: DataColumns = [ 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 => , diff --git a/src/views/trash-panel/trash-panel.tsx b/src/views/trash-panel/trash-panel.tsx index fa73c0b0..bfb99310 100644 --- a/src/views/trash-panel/trash-panel.tsx +++ b/src/views/trash-panel/trash-panel.tsx @@ -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 = [ +export const trashPanelColumns: DataColumns = [ { name: TrashPanelColumnNames.NAME, selected: true, @@ -119,16 +121,17 @@ interface TrashPanelActionProps { onItemRouteChange: (itemId: string) => void; } -type TrashPanelProps = TrashPanelDataProps & TrashPanelActionProps & DispatchProp - & WithStyles & RouteComponentProps<{ id: string }>; +type TrashPanelProps = TrashPanelDataProps & TrashPanelActionProps & DispatchProp & WithStyles; 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 { render() { return ; } - - componentWillReceiveProps({ match, currentItemId, onItemRouteChange }: TrashPanelProps) { - if (match.params.id !== currentItemId) { - onItemRouteChange(match.params.id); - } - } } ) ); diff --git a/src/views/workbench/workbench.tsx b/src/views/workbench/workbench.tsx index ea3a278b..68bb9700 100644 --- a/src/views/workbench/workbench.tsx +++ b/src/views/workbench/workbench.tsx @@ -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)( - + {user && } -- 2.30.2