From fc14bf232fe2cb77bf1f14ab0002fca606234214 Mon Sep 17 00:00:00 2001 From: Michal Klobukowski Date: Sun, 26 Aug 2018 00:32:20 +0200 Subject: [PATCH] Restore context menu in side bar and breadcrumbs Feature #14102 Arvados-DCO-1.1-Signed-off-by: Michal Klobukowski --- .../context-menu/context-menu-actions.ts | 44 ++++++++++++++++++- src/store/resources/resources.ts | 6 +-- src/store/side-panel/side-panel-action.ts | 4 ++ src/store/snackbar/snackbar-reducer.ts | 2 +- .../breadcrumbs/breadcrumbs.ts | 7 +-- .../project-tree-picker.tsx | 3 +- .../side-panel-tree/side-panel-tree.tsx | 6 ++- .../tree-picker/tree-picker.ts | 3 +- 8 files changed, 64 insertions(+), 11 deletions(-) diff --git a/src/store/context-menu/context-menu-actions.ts b/src/store/context-menu/context-menu-actions.ts index b517503d..26e25c3d 100644 --- a/src/store/context-menu/context-menu-actions.ts +++ b/src/store/context-menu/context-menu-actions.ts @@ -6,6 +6,12 @@ import { unionize, ofType, UnionOf } from '~/common/unionize'; import { ContextMenuPosition, ContextMenuResource } from "./context-menu-reducer"; import { ContextMenuKind } from '~/views-components/context-menu/context-menu'; import { Dispatch } from 'redux'; +import { RootState } from '~/store/store'; +import { getResource } from '../resources/resources'; +import { ProjectResource } from '~/models/project'; +import { UserResource } from '../../models/user'; +import { isSidePanelTreeCategory } from '~/store/side-panel-tree/side-panel-tree-actions'; +import { extractUuidKind, ResourceKind } from '~/models/resource'; export const contextMenuActions = unionize({ OPEN_CONTEXT_MENU: ofType<{ position: ContextMenuPosition, resource: ContextMenuResource }>(), @@ -23,4 +29,40 @@ export const openContextMenu = (event: React.MouseEvent, resource: resource }) ); - }; \ No newline at end of file + }; + +export const openRootProjectContextMenu = (event: React.MouseEvent, projectUuid: string) => + (dispatch: Dispatch, getState: () => RootState) => { + const userResource = getResource(projectUuid)(getState().resources); + if (userResource) { + dispatch(openContextMenu(event, { + name: '', + uuid: userResource.uuid, + kind: ContextMenuKind.ROOT_PROJECT + })); + } + }; + +export const openProjectContextMenu = (event: React.MouseEvent, projectUuid: string) => + (dispatch: Dispatch, getState: () => RootState) => { + const projectResource = getResource(projectUuid)(getState().resources); + if (projectResource) { + dispatch(openContextMenu(event, { + name: projectResource.name, + uuid: projectResource.uuid, + kind: ContextMenuKind.PROJECT + })); + } + }; + +export const openSidePanelContextMenu = (event: React.MouseEvent, id: string) => + (dispatch: Dispatch, getState: () => RootState) => { + if (!isSidePanelTreeCategory(id)) { + const kind = extractUuidKind(id); + if (kind === ResourceKind.USER) { + dispatch(openRootProjectContextMenu(event, id)); + } else if (kind === ResourceKind.PROJECT) { + dispatch(openProjectContextMenu(event, id)); + } + } + }; diff --git a/src/store/resources/resources.ts b/src/store/resources/resources.ts index 7f213329..add4efef 100644 --- a/src/store/resources/resources.ts +++ b/src/store/resources/resources.ts @@ -7,9 +7,9 @@ import { ResourceKind } from '../../models/resource'; export type ResourcesState = { [key: string]: Resource }; -export const getResource = (id: string) => - (state: ResourcesState): Resource | undefined => - state[id]; +export const getResource = (id: string) => + (state: ResourcesState): T | undefined => + state[id] as T; export const setResource = (id: string, data: T) => (state: ResourcesState) => ({ diff --git a/src/store/side-panel/side-panel-action.ts b/src/store/side-panel/side-panel-action.ts index 8c7ef4a7..d0fde0e0 100644 --- a/src/store/side-panel/side-panel-action.ts +++ b/src/store/side-panel/side-panel-action.ts @@ -6,6 +6,10 @@ import { Dispatch } from 'redux'; import { isSidePanelTreeCategory, SidePanelTreeCategory } from '~/store/side-panel-tree/side-panel-tree-actions'; import { navigateToFavorites, navigateTo } from '../navigation/navigation-action'; import { snackbarActions } from '~/store/snackbar/snackbar-actions'; +import { RootState } from '~/store/store'; +import { extractUuidKind, ResourceKind } from '~/models/resource'; +import { openProjectContextMenu } from '~/store/context-menu/context-menu-actions'; +import { openRootProjectContextMenu } from '../context-menu/context-menu-actions'; export const navigateFromSidePanel = (id: string) => (dispatch: Dispatch) => { diff --git a/src/store/snackbar/snackbar-reducer.ts b/src/store/snackbar/snackbar-reducer.ts index 403c19f0..fc2f4a19 100644 --- a/src/store/snackbar/snackbar-reducer.ts +++ b/src/store/snackbar/snackbar-reducer.ts @@ -20,7 +20,7 @@ const initialState: SnackbarState = { export const snackbarReducer = (state = initialState, action: SnackbarAction) => { return snackbarActions.match(action, { - OPEN_SNACKBAR: data => ({ ...data, open: true }), + OPEN_SNACKBAR: data => ({ ...initialState, ...data, open: true }), CLOSE_SNACKBAR: () => initialState, default: () => state, }); diff --git a/src/views-components/breadcrumbs/breadcrumbs.ts b/src/views-components/breadcrumbs/breadcrumbs.ts index 69eb9e3d..c2f33894 100644 --- a/src/views-components/breadcrumbs/breadcrumbs.ts +++ b/src/views-components/breadcrumbs/breadcrumbs.ts @@ -9,8 +9,7 @@ import { Dispatch } from 'redux'; import { navigateTo } from '~/store/navigation/navigation-action'; import { getProperty } from '../../store/properties/properties'; import { ResourceBreadcrumb, BREADCRUMBS } from '../../store/breadcrumbs/breadcrumbs-actions'; - - +import { openSidePanelContextMenu } from '~/store/context-menu/context-menu-actions'; type BreadcrumbsDataProps = Pick; type BreadcrumbsActionProps = Pick; @@ -23,7 +22,9 @@ const mapDispatchToProps = (dispatch: Dispatch): BreadcrumbsActionProps => ({ onClick: ({ uuid }: ResourceBreadcrumb) => { dispatch(navigateTo(uuid)); }, - onContextMenu: () => { return; } + onContextMenu: (event, breadcrumb: ResourceBreadcrumb) => { + dispatch(openSidePanelContextMenu(event, breadcrumb.uuid)); + } }); export const Breadcrumbs = connect(mapStateToProps(), mapDispatchToProps)(BreadcrumbsComponent); \ No newline at end of file diff --git a/src/views-components/project-tree-picker/project-tree-picker.tsx b/src/views-components/project-tree-picker/project-tree-picker.tsx index cc27806b..51220e65 100644 --- a/src/views-components/project-tree-picker/project-tree-picker.tsx +++ b/src/views-components/project-tree-picker/project-tree-picker.tsx @@ -17,9 +17,10 @@ import { RootState } from "~/store/store"; import { ServiceRepository } from "~/services/services"; import { FilterBuilder } from "~/common/api/filter-builder"; -type ProjectTreePickerProps = Pick; +type ProjectTreePickerProps = Pick; const mapDispatchToProps = (dispatch: Dispatch, props: { onChange: (projectUuid: string) => void }): ProjectTreePickerProps => ({ + onContextMenu: () => { return; }, toggleItemActive: (nodeId, status, pickerId) => { getNotSelectedTreePickerKind(pickerId) .forEach(pickerId => dispatch(treePickerActions.TOGGLE_TREE_PICKER_NODE_SELECT({ nodeId: '', pickerId }))); diff --git a/src/views-components/side-panel-tree/side-panel-tree.tsx b/src/views-components/side-panel-tree/side-panel-tree.tsx index 6445515c..d0b00d6f 100644 --- a/src/views-components/side-panel-tree/side-panel-tree.tsx +++ b/src/views-components/side-panel-tree/side-panel-tree.tsx @@ -12,14 +12,18 @@ import { ListItemTextIcon } from "~/components/list-item-text-icon/list-item-tex import { ProjectIcon, FavoriteIcon, ProjectsIcon, ShareMeIcon, TrashIcon } from '~/components/icon/icon'; import { RecentIcon, WorkflowIcon } from '~/components/icon/icon'; import { activateSidePanelTreeItem, toggleSidePanelTreeItemCollapse, SIDE_PANEL_TREE, SidePanelTreeCategory } from '~/store/side-panel-tree/side-panel-tree-actions'; +import { openSidePanelContextMenu } from '~/store/context-menu/context-menu-actions'; export interface SidePanelTreeProps { onItemActivation: (id: string) => void; } -type SidePanelTreeActionProps = Pick; +type SidePanelTreeActionProps = Pick; const mapDispatchToProps = (dispatch: Dispatch, props: SidePanelTreeProps): SidePanelTreeActionProps => ({ + onContextMenu: (event, id) => { + dispatch(openSidePanelContextMenu(event, id)); + }, toggleItemActive: (nodeId) => { dispatch(activateSidePanelTreeItem(nodeId)); props.onItemActivation(nodeId); diff --git a/src/views-components/tree-picker/tree-picker.ts b/src/views-components/tree-picker/tree-picker.ts index b90f2e42..0cd55f12 100644 --- a/src/views-components/tree-picker/tree-picker.ts +++ b/src/views-components/tree-picker/tree-picker.ts @@ -11,6 +11,7 @@ import { Dispatch } from "redux"; export interface TreePickerProps { pickerId: string; + onContextMenu: (event: React.MouseEvent, nodeId: string, pickerId: string) => void; toggleItemOpen: (nodeId: string, status: TreeItemStatus, pickerId: string) => void; toggleItemActive: (nodeId: string, status: TreeItemStatus, pickerId: string) => void; } @@ -24,7 +25,7 @@ const mapStateToProps = (state: RootState, props: TreePickerProps): Pick, 'onContextMenu' | 'toggleItemOpen' | 'toggleItemActive'> => ({ - onContextMenu: () => { return; }, + onContextMenu: (event, item) => props.onContextMenu(event, item.id, props.pickerId), toggleItemActive: (id, status) => props.toggleItemActive(id, status, props.pickerId), toggleItemOpen: (id, status) => props.toggleItemOpen(id, status, props.pickerId) }); -- 2.30.2