repositories-panel-init
[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 { Process } from '~/store/processes/process';
16
17 export const contextMenuActions = unionize({
18     OPEN_CONTEXT_MENU: ofType<{ position: ContextMenuPosition, resource: ContextMenuResource }>(),
19     CLOSE_CONTEXT_MENU: ofType<{}>()
20 });
21
22 export type ContextMenuAction = UnionOf<typeof contextMenuActions>;
23
24 export type ContextMenuResource = {
25     name: string;
26     uuid: string;
27     ownerUuid: string;
28     description?: string;
29     kind: ResourceKind,
30     menuKind: ContextMenuKind;
31     isTrashed?: boolean;
32 };
33 export const isKeyboardClick = (event: React.MouseEvent<HTMLElement>) =>
34     event.nativeEvent.detail === 0;
35 export const openContextMenu = (event: React.MouseEvent<HTMLElement>, resource: ContextMenuResource) =>
36     (dispatch: Dispatch) => {
37         event.preventDefault();
38         const { left, top } = event.currentTarget.getBoundingClientRect();
39         dispatch(
40             contextMenuActions.OPEN_CONTEXT_MENU({
41                 position: {
42                     x: event.clientX || left,
43                     y: event.clientY || top,
44                 },
45                 resource
46             })
47         );
48     };
49
50 export const openCollectionFilesContextMenu = (event: React.MouseEvent<HTMLElement>) =>
51     (dispatch: Dispatch, getState: () => RootState) => {
52         const isCollectionFileSelected = JSON.stringify(getState().collectionPanelFiles).includes('"selected":true');
53         dispatch<any>(openContextMenu(event, {
54             name: '',
55             uuid: '',
56             ownerUuid: '',
57             kind: ResourceKind.COLLECTION,
58             menuKind: isCollectionFileSelected ? ContextMenuKind.COLLECTION_FILES : ContextMenuKind.COLLECTION_FILES_NOT_SELECTED
59         }));
60     };
61
62 export const openRepositoryContextMenu = (event: React.MouseEvent<HTMLElement>) =>
63     (dispatch: Dispatch, getState: () => RootState) => {
64         dispatch<any>(openContextMenu(event, {
65             name: '',
66             uuid: '',
67             ownerUuid: '',
68             kind: ResourceKind.REPOSITORY,
69             menuKind: ContextMenuKind.REPOSITORY
70         }));
71     };
72
73 export const openRootProjectContextMenu = (event: React.MouseEvent<HTMLElement>, projectUuid: string) =>
74     (dispatch: Dispatch, getState: () => RootState) => {
75         const res = getResource<UserResource>(projectUuid)(getState().resources);
76         if (res) {
77             dispatch<any>(openContextMenu(event, {
78                 name: '',
79                 uuid: res.uuid,
80                 ownerUuid: res.uuid,
81                 kind: res.kind,
82                 menuKind: ContextMenuKind.ROOT_PROJECT,
83                 isTrashed: false
84             }));
85         }
86     };
87
88 export const openProjectContextMenu = (event: React.MouseEvent<HTMLElement>, projectUuid: string) =>
89     (dispatch: Dispatch, getState: () => RootState) => {
90         const res = getResource<ProjectResource>(projectUuid)(getState().resources);
91         if (res) {
92             dispatch<any>(openContextMenu(event, {
93                 name: res.name,
94                 uuid: res.uuid,
95                 kind: res.kind,
96                 menuKind: ContextMenuKind.PROJECT,
97                 ownerUuid: res.ownerUuid,
98                 isTrashed: res.isTrashed
99             }));
100         }
101     };
102
103 export const openSidePanelContextMenu = (event: React.MouseEvent<HTMLElement>, id: string) =>
104     (dispatch: Dispatch, getState: () => RootState) => {
105         if (!isSidePanelTreeCategory(id)) {
106             const kind = extractUuidKind(id);
107             if (kind === ResourceKind.USER) {
108                 dispatch<any>(openRootProjectContextMenu(event, id));
109             } else if (kind === ResourceKind.PROJECT) {
110                 dispatch<any>(openProjectContextMenu(event, id));
111             }
112         }
113     };
114
115 export const openProcessContextMenu = (event: React.MouseEvent<HTMLElement>, process: Process) =>
116     (dispatch: Dispatch, getState: () => RootState) => {
117         const resource = {
118             uuid: process.containerRequest.uuid,
119             ownerUuid: '',
120             kind: ResourceKind.PROCESS,
121             name: '',
122             description: '',
123             menuKind: ContextMenuKind.PROCESS
124         };
125         dispatch<any>(openContextMenu(event, resource));
126     };
127
128 export const resourceKindToContextMenuKind = (uuid: string) => {
129     const kind = extractUuidKind(uuid);
130     switch (kind) {
131         case ResourceKind.PROJECT:
132             return ContextMenuKind.PROJECT;
133         case ResourceKind.COLLECTION:
134             return ContextMenuKind.COLLECTION_RESOURCE;
135         case ResourceKind.PROCESS:
136             return ContextMenuKind.PROCESS_RESOURCE;
137         case ResourceKind.USER:
138             return ContextMenuKind.ROOT_PROJECT;
139         default:
140             return;
141     }
142 };