15768: selection menu all good Arvados-DCO-1.1-Signed-off-by: Lisa Knox <lisa.knox...
[arvados-workbench2.git] / src / components / data-table-multiselect-popover / data-table-multiselect-popover.tsx
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import React, { useEffect } from 'react';
6 import {
7     WithStyles,
8     withStyles,
9     ButtonBase,
10     StyleRulesCallback,
11     Theme,
12     Popover,
13     Button,
14     Card,
15     CardActions,
16     Typography,
17     CardContent,
18     Tooltip,
19     IconButton,
20 } from '@material-ui/core';
21 import classnames from 'classnames';
22 import { DefaultTransformOrigin } from 'components/popover/helpers';
23 import debounce from 'lodash/debounce';
24 import { grey } from '@material-ui/core/colors';
25
26 export type CssRules = 'root' | 'icon' | 'iconButton' | 'optionsContainer' | 'option';
27
28 const styles: StyleRulesCallback<CssRules> = (theme: Theme) => ({
29     root: {
30         borderRadius: '7px',
31         '&:hover': {
32             backgroundColor: grey[200],
33         },
34         '&:focus': {
35             color: theme.palette.text.primary,
36         },
37     },
38     icon: {
39         cursor: 'pointer',
40         fontSize: 20,
41         userSelect: 'none',
42         '&:hover': {
43             color: theme.palette.text.primary,
44         },
45         paddingBottom: '5px',
46     },
47     iconButton: {
48         color: theme.palette.text.primary,
49         opacity: 0.6,
50         padding: 1,
51         paddingBottom: 5,
52     },
53     optionsContainer: {
54         paddingTop: '1rem',
55         flex: 1,
56     },
57     option: {
58         cursor: 'pointer',
59         display: 'flex',
60         padding: '3px 2rem',
61         fontSize: '0.9rem',
62         alignItems: 'center',
63         '&:hover': {
64             backgroundColor: 'rgba(0, 0, 0, 0.08)',
65         },
66     },
67 });
68
69 export type DataTableMultiselectOption = {
70     name: string;
71     fn: (checkedList) => void;
72 };
73
74 export interface DataTableMultiselectProps {
75     name: string;
76     options: DataTableMultiselectOption[];
77     checkedList: Record<string, boolean>;
78 }
79
80 interface DataTableFMultiselectPopState {
81     anchorEl?: HTMLElement;
82 }
83
84 export const DataTableMultiselectPopover = withStyles(styles)(
85     class extends React.Component<DataTableMultiselectProps & WithStyles<CssRules>, DataTableFMultiselectPopState> {
86         state: DataTableFMultiselectPopState = {
87             anchorEl: undefined,
88         };
89         icon = React.createRef<HTMLElement>();
90
91         render() {
92             const { name, classes, children, options, checkedList } = this.props;
93             return (
94                 <>
95                     <Tooltip disableFocusListener title='Select Options'>
96                         <ButtonBase className={classnames(classes.root)} component='span' onClick={this.open} disableRipple>
97                             {children}
98                             <IconButton component='span' classes={{ root: classes.iconButton }} tabIndex={-1}>
99                                 <i className={classnames(['fas fa-sort-down', classes.icon])} data-fa-transform='shrink-3' ref={this.icon} />
100                             </IconButton>
101                         </ButtonBase>
102                     </Tooltip>
103                     <Popover
104                         anchorEl={this.state.anchorEl}
105                         open={!!this.state.anchorEl}
106                         anchorOrigin={DefaultTransformOrigin}
107                         transformOrigin={DefaultTransformOrigin}
108                         onClose={this.close}
109                     >
110                         <Card>
111                             <div className={classes.optionsContainer}>
112                                 {options.length &&
113                                     options.map((option, i) => (
114                                         <div
115                                             key={i}
116                                             className={classes.option}
117                                             onClick={() => {
118                                                 option.fn(checkedList);
119                                                 this.close();
120                                             }}
121                                         >
122                                             {option.name}
123                                         </div>
124                                     ))}
125                             </div>
126                             <CardActions>
127                                 <Button color='primary' variant='outlined' size='small' onClick={this.close}>
128                                     Close
129                                 </Button>
130                             </CardActions>
131                         </Card>
132                     </Popover>
133                     <this.MountHandler />
134                 </>
135             );
136         }
137
138         open = () => {
139             this.setState({ anchorEl: this.icon.current || undefined });
140         };
141
142         submit = debounce(() => {
143             // const { onChange } = this.props;
144             // if (onChange) {
145             //     onChange(this.state.filters);
146             // }
147         }, 1000);
148
149         MountHandler = () => {
150             useEffect(() => {
151                 return () => {
152                     this.submit.cancel();
153                 };
154             }, []);
155             return null;
156         };
157
158         close = () => {
159             this.setState((prev) => ({
160                 ...prev,
161                 anchorEl: undefined,
162             }));
163         };
164     }
165 );