15768: cleanup Arvados-DCO-1.1-Signed-off-by: Lisa Knox <lisa.knox@curii.com>
[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     },
46     iconButton: {
47         color: theme.palette.text.primary,
48         opacity: 0.6,
49         padding: 1,
50         paddingBottom: 5,
51     },
52     optionsContainer: {
53         padding: '3px 15px',
54         flex: 1,
55     },
56     option: {
57         cursor: 'pointer',
58         display: 'flex',
59         padding: '3px',
60         fontSize: '1rem',
61         alignItems: 'center',
62         '&:hover': {
63             backgroundColor: 'rgba(0, 0, 0, 0.08)',
64         },
65     },
66 });
67
68 export type DataTableMultiselectOption = {
69     name: string;
70     fn: (checkedList) => void;
71 };
72
73 export interface DataTableMultiselectProps {
74     name: string;
75     options: DataTableMultiselectOption[];
76     checkedList: Record<string, boolean>;
77 }
78
79 interface DataTableFMultiselectPopState {
80     anchorEl?: HTMLElement;
81 }
82
83 export const DataTableMultiselectPopover = withStyles(styles)(
84     class extends React.Component<DataTableMultiselectProps & WithStyles<CssRules>, DataTableFMultiselectPopState> {
85         state: DataTableFMultiselectPopState = {
86             anchorEl: undefined,
87         };
88         icon = React.createRef<HTMLElement>();
89
90         render() {
91             const { name, classes, children, options, checkedList } = this.props;
92             return (
93                 <>
94                     <Tooltip disableFocusListener title='Multiselect Actions'>
95                         <ButtonBase className={classnames(classes.root)} component='span' onClick={this.open} disableRipple>
96                             {children}
97                             <IconButton component='span' classes={{ root: classes.iconButton }} tabIndex={-1}>
98                                 <i className={classnames(['fas fa-sort-down', classes.icon])} data-fa-transform='shrink-3' ref={this.icon} />
99                             </IconButton>
100                         </ButtonBase>
101                     </Tooltip>
102                     <Popover
103                         anchorEl={this.state.anchorEl}
104                         open={!!this.state.anchorEl}
105                         anchorOrigin={DefaultTransformOrigin}
106                         transformOrigin={DefaultTransformOrigin}
107                         onClose={this.close}
108                     >
109                         <Card>
110                             <CardContent>
111                                 <Typography variant='caption'>{name}</Typography>
112                             </CardContent>
113                             <div className={classes.optionsContainer}>
114                                 {options.length &&
115                                     options.map((option, i) => (
116                                         <div key={i} className={classes.option} onClick={() => option.fn(checkedList)}>
117                                             {option.name}
118                                         </div>
119                                     ))}
120                             </div>
121                             <CardActions>
122                                 <Button color='primary' variant='outlined' size='small' onClick={this.close}>
123                                     Close
124                                 </Button>
125                             </CardActions>
126                         </Card>
127                     </Popover>
128                     <this.MountHandler />
129                 </>
130             );
131         }
132
133         open = () => {
134             this.setState({ anchorEl: this.icon.current || undefined });
135         };
136
137         submit = debounce(() => {
138             // const { onChange } = this.props;
139             // if (onChange) {
140             //     onChange(this.state.filters);
141             // }
142         }, 1000);
143
144         MountHandler = () => {
145             useEffect(() => {
146                 return () => {
147                     this.submit.cancel();
148                 };
149             }, []);
150             return null;
151         };
152
153         close = () => {
154             this.setState((prev) => ({
155                 ...prev,
156                 anchorEl: undefined,
157             }));
158         };
159     }
160 );