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