Restore context menu in side bar and breadcrumbs
authorMichal Klobukowski <michal.klobukowski@contractors.roche.com>
Sat, 25 Aug 2018 22:32:20 +0000 (00:32 +0200)
committerMichal Klobukowski <michal.klobukowski@contractors.roche.com>
Sat, 25 Aug 2018 22:32:20 +0000 (00:32 +0200)
Feature #14102

Arvados-DCO-1.1-Signed-off-by: Michal Klobukowski <michal.klobukowski@contractors.roche.com>

src/store/context-menu/context-menu-actions.ts
src/store/resources/resources.ts
src/store/side-panel/side-panel-action.ts
src/store/snackbar/snackbar-reducer.ts
src/views-components/breadcrumbs/breadcrumbs.ts
src/views-components/project-tree-picker/project-tree-picker.tsx
src/views-components/side-panel-tree/side-panel-tree.tsx
src/views-components/tree-picker/tree-picker.ts

index b517503d149dfe8df960da4aa05bebf3bd40b3ae..26e25c3df3a6db4511f39b126667d4321d2b8b6e 100644 (file)
@@ -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<HTMLElement>, resource:
                 resource
             })
         );
-    };
\ No newline at end of file
+    };
+
+export const openRootProjectContextMenu = (event: React.MouseEvent<HTMLElement>, projectUuid: string) =>
+    (dispatch: Dispatch, getState: () => RootState) => {
+        const userResource = getResource<UserResource>(projectUuid)(getState().resources);
+        if (userResource) {
+            dispatch<any>(openContextMenu(event, {
+                name: '',
+                uuid: userResource.uuid,
+                kind: ContextMenuKind.ROOT_PROJECT
+            }));
+        }
+    };
+
+export const openProjectContextMenu = (event: React.MouseEvent<HTMLElement>, projectUuid: string) =>
+    (dispatch: Dispatch, getState: () => RootState) => {
+        const projectResource = getResource<ProjectResource>(projectUuid)(getState().resources);
+        if (projectResource) {
+            dispatch<any>(openContextMenu(event, {
+                name: projectResource.name,
+                uuid: projectResource.uuid,
+                kind: ContextMenuKind.PROJECT
+            }));
+        }
+    };
+
+export const openSidePanelContextMenu = (event: React.MouseEvent<HTMLElement>, id: string) =>
+    (dispatch: Dispatch, getState: () => RootState) => {
+        if (!isSidePanelTreeCategory(id)) {
+            const kind = extractUuidKind(id);
+            if (kind === ResourceKind.USER) {
+                dispatch<any>(openRootProjectContextMenu(event, id));
+            } else if (kind === ResourceKind.PROJECT) {
+                dispatch<any>(openProjectContextMenu(event, id));
+            }
+        }
+    };
index 7f21332969113f7c66c0809e8f50c03a0dfd5df8..add4efef54b4cd4d63178e0239927f4619587160 100644 (file)
@@ -7,9 +7,9 @@ import { ResourceKind } from '../../models/resource';
 
 export type ResourcesState = { [key: string]: Resource };
 
-export const getResource = <T extends Resource>(id: string) =>
-    (state: ResourcesState): Resource | undefined =>
-        state[id];
+export const getResource = <T extends Resource = Resource>(id: string) =>
+    (state: ResourcesState): T | undefined =>
+        state[id] as T;
 
 export const setResource = <T extends Resource>(id: string, data: T) =>
     (state: ResourcesState) => ({
index 8c7ef4a7a1ff7ff6d8d3f1023e8d7d93cefd6f08..d0fde0e0c4f65965d9bac996eef13445436f8754 100644 (file)
@@ -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) => {
index 403c19f0071d4eac0949becc10fbb389082c40bb..fc2f4a1964e27627ff5d02e63150713bbe78eb3b 100644 (file)
@@ -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,
     });
index 69eb9e3dfcf1abaa2929b8e6fbf2c5e556a9f9f1..c2f33894ba0a57932000de4271414a1c494d145c 100644 (file)
@@ -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<BreadcrumbsProps, 'items'>;
 type BreadcrumbsActionProps = Pick<BreadcrumbsProps, 'onClick' | 'onContextMenu'>;
@@ -23,7 +22,9 @@ const mapDispatchToProps = (dispatch: Dispatch): BreadcrumbsActionProps => ({
     onClick: ({ uuid }: ResourceBreadcrumb) => {
         dispatch<any>(navigateTo(uuid));
     },
-    onContextMenu: () => { return; }
+    onContextMenu: (event, breadcrumb: ResourceBreadcrumb) => {
+        dispatch<any>(openSidePanelContextMenu(event, breadcrumb.uuid));
+    }
 });
 
 export const Breadcrumbs = connect(mapStateToProps(), mapDispatchToProps)(BreadcrumbsComponent);
\ No newline at end of file
index cc27806bbe8e4bf4c19f428567355e3ad51bf414..51220e655ddea6db395460fb963a14f5051b4aa8 100644 (file)
@@ -17,9 +17,10 @@ import { RootState } from "~/store/store";
 import { ServiceRepository } from "~/services/services";
 import { FilterBuilder } from "~/common/api/filter-builder";
 
-type ProjectTreePickerProps = Pick<TreePickerProps, 'toggleItemActive' | 'toggleItemOpen'>;
+type ProjectTreePickerProps = Pick<TreePickerProps, 'onContextMenu' | 'toggleItemActive' | 'toggleItemOpen'>;
 
 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 })));
index 6445515cf2428a5724e40c9dfabf4e264e88d92c..d0b00d6fb50c4576a9e8190311ec056c826c32bc 100644 (file)
@@ -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<TreePickerProps, 'toggleItemActive' | 'toggleItemOpen'>;
+type SidePanelTreeActionProps = Pick<TreePickerProps, 'onContextMenu' | 'toggleItemActive' | 'toggleItemOpen'>;
 
 const mapDispatchToProps = (dispatch: Dispatch, props: SidePanelTreeProps): SidePanelTreeActionProps => ({
+    onContextMenu: (event, id) => {
+        dispatch<any>(openSidePanelContextMenu(event, id));
+    },
     toggleItemActive: (nodeId) => {
         dispatch<any>(activateSidePanelTreeItem(nodeId));
         props.onItemActivation(nodeId);
index b90f2e420656dd1365b37869c65779830726a589..0cd55f121ffa9a7ac88bc8229fc2ae53643b97aa 100644 (file)
@@ -11,6 +11,7 @@ import { Dispatch } from "redux";
 
 export interface TreePickerProps {
     pickerId: string;
+    onContextMenu: (event: React.MouseEvent<HTMLElement>, 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<TreePro
 };
 
 const mapDispatchToProps = (dispatch: Dispatch, props: TreePickerProps): Pick<TreeProps<any>, '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)
 });