one process copies Arvados-DCO-1.1-Signed-off-by: Lisa Knox <lisa.knox@curii.com>
[arvados.git] / src / components / multiselectToolbar / MultiselectToolbar.tsx
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import React, { ReactElement } from 'react';
6 import { connect } from 'react-redux';
7 import { StyleRulesCallback, withStyles, WithStyles, Toolbar, Button } from '@material-ui/core';
8 import { ArvadosTheme } from 'common/custom-theme';
9 import { RootState } from 'store/store';
10 import { Dispatch } from 'redux';
11 import { CopyToClipboardSnackbar } from 'components/copy-to-clipboard-snackbar/copy-to-clipboard-snackbar';
12 import { TCheckedList } from 'components/data-table/data-table';
13 import { openRemoveProcessDialog, openRemoveManyProcessesDialog } from 'store/processes/processes-actions';
14 import { processResourceActionSet } from '../../views-components/context-menu/action-sets/process-resource-action-set';
15 import { ContextMenuResource } from 'store/context-menu/context-menu-actions';
16 import { ResourceKind, extractUuidKind } from 'models/resource';
17 import { openMoveProcessDialog } from 'store/processes/process-move-actions';
18 import { openCopyProcessDialog } from 'store/processes/process-copy-actions';
19 import { getResource } from 'store/resources/resources';
20 import { ResourceName } from 'views-components/data-explorer/renderers';
21 import { ProcessResource } from 'models/process';
22 import { ResourcesState } from 'store/resources/resources';
23 import { Resource } from 'models/resource';
24 import { getProcess } from 'store/processes/process';
25
26 type CssRules = 'root' | 'button';
27
28 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
29     root: {
30         display: 'flex',
31         flexDirection: 'row',
32         width: 0,
33         padding: 0,
34         margin: '1rem auto auto 0.5rem',
35         overflow: 'hidden',
36         transition: 'width 150ms',
37     },
38     button: {
39         backgroundColor: '#017ead',
40         color: 'white',
41         fontSize: '0.75rem',
42         width: 'auto',
43         margin: 'auto',
44         padding: '1px',
45     },
46 });
47
48 type MultiselectToolbarAction = {
49     name: string;
50     funcName: string;
51     relevantKinds: Set<ResourceKind>;
52 };
53
54 //gleaned from src/views-components/context-menu/action-sets
55 export const defaultActions: Array<MultiselectToolbarAction> = [
56     {
57         name: 'copy and re-run',
58         funcName: 'copySelected',
59         relevantKinds: new Set([ResourceKind.PROCESS]),
60     },
61     {
62         name: 'move',
63         funcName: 'moveSelected',
64         relevantKinds: new Set([ResourceKind.PROCESS, ResourceKind.PROJECT]),
65     },
66     {
67         name: 'remove',
68         funcName: 'removeSelected',
69         relevantKinds: new Set([ResourceKind.PROCESS, ResourceKind.COLLECTION]),
70     },
71     {
72         name: 'favorite',
73         funcName: 'favoriteSelected',
74         relevantKinds: new Set([ResourceKind.PROCESS, ResourceKind.PROJECT, ResourceKind.COLLECTION]),
75     },
76 ];
77
78 export type MultiselectToolbarProps = {
79     actions: Array<MultiselectToolbarAction>;
80     isVisible: boolean;
81     checkedList: TCheckedList;
82     resources: ResourcesState;
83     copySelected: (checkedList: TCheckedList, resources: ResourcesState) => void;
84     moveSelected: (resource) => void;
85     barSelected: () => void;
86     removeSelected: (checkedList: TCheckedList) => void;
87 };
88
89 export const MultiselectToolbar = connect(
90     mapStateToProps,
91     mapDispatchToProps
92 )(
93     withStyles(styles)((props: MultiselectToolbarProps & WithStyles<CssRules>) => {
94         // console.log(props);
95         const { classes, actions, isVisible, checkedList, resources } = props;
96
97         const currentResourceKinds = Array.from(selectedToKindSet(checkedList));
98         const buttons = actions.filter((action) => currentResourceKinds.length && currentResourceKinds.every((kind) => action.relevantKinds.has(kind as ResourceKind)));
99
100         return (
101             <Toolbar className={classes.root} style={{ width: `${buttons.length * 5.5}rem` }}>
102                 {buttons.length ? (
103                     buttons.map((btn) => (
104                         <Button key={btn.name} className={classes.button} onClick={() => props[btn.funcName](checkedList, resources)}>
105                             {btn.name}
106                         </Button>
107                     ))
108                 ) : (
109                     <></>
110                 )}
111             </Toolbar>
112         );
113     })
114 );
115
116 function selectedToArray(checkedList: TCheckedList): Array<string> {
117     const arrayifiedSelectedList: Array<string> = [];
118     for (const [key, value] of Object.entries(checkedList)) {
119         if (value === true) {
120             arrayifiedSelectedList.push(key);
121         }
122     }
123     return arrayifiedSelectedList;
124 }
125
126 function selectedToKindSet(checkedList: TCheckedList): Set<string> {
127     const setifiedList = new Set<string>();
128     for (const [key, value] of Object.entries(checkedList)) {
129         if (value === true) {
130             setifiedList.add(extractUuidKind(key) as string);
131         }
132     }
133     return setifiedList;
134 }
135
136 function mapStateToProps(state: RootState) {
137     // console.log(state);
138     // console.log(getResource<ProcessResource>('tordo-dz642-0p7xefqdr4nw4pw')(state.resources));
139     const { isVisible, checkedList } = state.multiselect;
140     return {
141         isVisible: isVisible,
142         checkedList: checkedList as TCheckedList,
143         resources: state.resources,
144     };
145 }
146
147 function mapDispatchToProps(dispatch: Dispatch) {
148     return {
149         copySelected: (checkedList: TCheckedList, resources: ResourcesState) => copyMoveMulti(dispatch, checkedList, resources),
150         moveSelected: (checkedList: TCheckedList) => {},
151         barSelected: () => {},
152         removeSelected: (checkedList: TCheckedList) => removeMultiProcesses(dispatch, checkedList),
153     };
154 }
155
156 function copyMoveMulti(dispatch: Dispatch, checkedList: TCheckedList, resources: ResourcesState) {
157     const selectedList: Array<string> = selectedToArray(checkedList);
158     const single = getProcess(selectedList[0])(resources)?.containerRequest;
159     console.log(single);
160     const { name, uuid } = single as any;
161     console.log(name, uuid);
162     dispatch<any>(openCopyProcessDialog({ name, uuid }));
163 }
164
165 function moveMultiProcesses(dispatch: Dispatch, checkedList: TCheckedList): void {
166     const selectedList: Array<string> = selectedToArray(checkedList);
167     // if (selectedList.length === 1) dispatch<any>(openMoveProcessDialog(selectedList[0]));
168 }
169
170 const RemoveFunctions = {
171     ONE_PROCESS: (uuid: string) => openRemoveProcessDialog(uuid),
172     MANY_PROCESSES: (list: Array<string>) => openRemoveManyProcessesDialog(list),
173 };
174
175 function removeMultiProcesses(dispatch: Dispatch, checkedList: TCheckedList): void {
176     const selectedList: Array<string> = selectedToArray(checkedList);
177     dispatch<any>(selectedList.length === 1 ? RemoveFunctions.ONE_PROCESS(selectedList[0]) : RemoveFunctions.MANY_PROCESSES(selectedList));
178 }
179
180 //onRemove
181 //go through the array of selected and choose the appropriate removal function
182 //have a constant with [ResourceKind]: different removal methods