Merge branch 'master' into 14120-rich-text-editor
[arvados-workbench2.git] / src / store / context-menu / context-menu-actions.ts
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import { unionize, ofType, UnionOf } from '~/common/unionize';
6 import { ContextMenuPosition } from "./context-menu-reducer";
7 import { ContextMenuKind } from '~/views-components/context-menu/context-menu';
8 import { Dispatch } from 'redux';
9 import { RootState } from '~/store/store';
10 import { getResource } from '../resources/resources';
11 import { ProjectResource } from '~/models/project';
12 import { UserResource } from '~/models/user';
13 import { isSidePanelTreeCategory } from '~/store/side-panel-tree/side-panel-tree-actions';
14 import { extractUuidKind, ResourceKind } from '~/models/resource';
15 import { matchProcessRoute } from '~/routes/routes';
16 import { Process } from '~/store/processes/process';
17
18 export const contextMenuActions = unionize({
19     OPEN_CONTEXT_MENU: ofType<{ position: ContextMenuPosition, resource: ContextMenuResource }>(),
20     CLOSE_CONTEXT_MENU: ofType<{}>()
21 });
22
23 export type ContextMenuAction = UnionOf<typeof contextMenuActions>;
24
25 export type ContextMenuResource = {
26     name: string;
27     uuid: string;
28     ownerUuid: string;
29     description?: string;
30     kind: ResourceKind,
31     menuKind: ContextMenuKind;
32     isTrashed?: boolean;
33 };
34 export const isKeyboardClick = (event: React.MouseEvent<HTMLElement>) =>
35     event.nativeEvent.detail === 0;
36 export const openContextMenu = (event: React.MouseEvent<HTMLElement>, resource: ContextMenuResource) =>
37     (dispatch: Dispatch) => {
38         event.preventDefault();
39         const { left, top } = event.currentTarget.getBoundingClientRect();
40         dispatch(
41             contextMenuActions.OPEN_CONTEXT_MENU({
42                 position: {
43                     x: event.clientX || left,
44                     y: event.clientY || top,
45                 },
46                 resource
47             })
48         );
49     };
50
51 export const openRootProjectContextMenu = (event: React.MouseEvent<HTMLElement>, projectUuid: string) =>
52     (dispatch: Dispatch, getState: () => RootState) => {
53         const res = getResource<UserResource>(projectUuid)(getState().resources);
54         if (res) {
55             dispatch<any>(openContextMenu(event, {
56                 name: '',
57                 uuid: res.uuid,
58                 ownerUuid: res.uuid,
59                 kind: res.kind,
60                 menuKind: ContextMenuKind.ROOT_PROJECT,
61                 isTrashed: false
62             }));
63         }
64     };
65
66 export const openProjectContextMenu = (event: React.MouseEvent<HTMLElement>, projectUuid: string) =>
67     (dispatch: Dispatch, getState: () => RootState) => {
68         const res = getResource<ProjectResource>(projectUuid)(getState().resources);
69         if (res) {
70             dispatch<any>(openContextMenu(event, {
71                 name: res.name,
72                 uuid: res.uuid,
73                 kind: res.kind,
74                 menuKind: ContextMenuKind.PROJECT,
75                 ownerUuid: res.ownerUuid,
76                 isTrashed: res.isTrashed
77             }));
78         }
79     };
80
81 export const openSidePanelContextMenu = (event: React.MouseEvent<HTMLElement>, id: string) =>
82     (dispatch: Dispatch, getState: () => RootState) => {
83         if (!isSidePanelTreeCategory(id)) {
84             const kind = extractUuidKind(id);
85             if (kind === ResourceKind.USER) {
86                 dispatch<any>(openRootProjectContextMenu(event, id));
87             } else if (kind === ResourceKind.PROJECT) {
88                 dispatch<any>(openProjectContextMenu(event, id));
89             }
90         }
91     };
92
93 export const openProcessContextMenu = (event: React.MouseEvent<HTMLElement>, process: Process) =>
94     (dispatch: Dispatch, getState: () => RootState) => {
95         const resource = {
96             uuid: process.containerRequest.uuid,
97             ownerUuid: '',
98             kind: ResourceKind.PROCESS,
99             name: '',
100             description: '',
101             menuKind: ContextMenuKind.PROCESS
102         };
103         dispatch<any>(openContextMenu(event, resource));
104     };
105
106 export const resourceKindToContextMenuKind = (uuid: string) => {
107     const kind = extractUuidKind(uuid);
108     switch (kind) {
109         case ResourceKind.PROJECT:
110             return ContextMenuKind.PROJECT;
111         case ResourceKind.COLLECTION:
112             return ContextMenuKind.COLLECTION_RESOURCE;
113         case ResourceKind.PROCESS:
114             return ContextMenuKind.PROCESS_RESOURCE;
115         case ResourceKind.USER:
116             return ContextMenuKind.ROOT_PROJECT;
117         default:
118             return;
119     }
120 };