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