forked from marmelab/react-admin
-
Notifications
You must be signed in to change notification settings - Fork 1
/
FilterButton.tsx
122 lines (111 loc) · 3.51 KB
/
FilterButton.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import * as React from 'react';
import {
useState,
useCallback,
useRef,
ReactNode,
HtmlHTMLAttributes,
} from 'react';
import PropTypes from 'prop-types';
import Menu from '@material-ui/core/Menu';
import { makeStyles } from '@material-ui/core/styles';
import ContentFilter from '@material-ui/icons/FilterList';
import classnames from 'classnames';
import lodashGet from 'lodash/get';
import { FilterButtonMenuItem } from './FilterButtonMenuItem';
import Button from '../../button/Button';
import { ClassesOverride } from '../../types';
import { useResourceContext } from 'ra-core';
const useStyles = makeStyles(
{
root: { display: 'inline-block' },
},
{ name: 'RaFilterButton' }
);
const FilterButton = (props: FilterButtonProps): JSX.Element => {
const {
filters,
displayedFilters = {},
filterValues,
showFilter,
classes: classesOverride,
className,
resource: propsResource,
...rest
} = props;
const resource = useResourceContext(props);
const [open, setOpen] = useState(false);
const anchorEl = useRef();
const classes = useStyles(props);
const hiddenFilters = filters.filter(
(filterElement: JSX.Element) =>
!filterElement.props.alwaysOn &&
!displayedFilters[filterElement.props.source] &&
typeof lodashGet(filterValues, filterElement.props.source) ===
'undefined'
);
const handleClickButton = useCallback(
event => {
// This prevents ghost click.
event.preventDefault();
setOpen(true);
anchorEl.current = event.currentTarget;
},
[anchorEl, setOpen]
);
const handleRequestClose = useCallback(() => {
setOpen(false);
}, [setOpen]);
const handleShow = useCallback(
({ source, defaultValue }) => {
showFilter(source, defaultValue);
setOpen(false);
},
[showFilter, setOpen]
);
if (hiddenFilters.length === 0) return null;
return (
<div className={classnames(classes.root, className)} {...rest}>
<Button
className="add-filter"
label="ra.action.add_filter"
onClick={handleClickButton}
>
<ContentFilter />
</Button>
<Menu
open={open}
anchorEl={anchorEl.current}
onClose={handleRequestClose}
>
{hiddenFilters.map((filterElement: JSX.Element) => (
<FilterButtonMenuItem
key={filterElement.props.source}
filter={filterElement}
resource={resource}
onShow={handleShow}
/>
))}
</Menu>
</div>
);
};
FilterButton.propTypes = {
resource: PropTypes.string,
filters: PropTypes.arrayOf(PropTypes.node).isRequired,
displayedFilters: PropTypes.object,
filterValues: PropTypes.object.isRequired,
showFilter: PropTypes.func.isRequired,
classes: PropTypes.object,
className: PropTypes.string,
};
export interface FilterButtonProps extends HtmlHTMLAttributes<HTMLDivElement> {
classes?: ClassesOverride<typeof useStyles>;
className?: string;
resource?: string;
filterValues: any;
showFilter: (filterName: string, defaultValue: any) => void;
displayedFilters: any;
filters: ReactNode[];
}
export default FilterButton;