//
// SPDX-License-Identifier: AGPL-3.0
-import * as React from "react";
+import React from "react";
import {
WithStyles,
withStyles,
CardActions,
Typography,
CardContent,
- Tooltip
+ Tooltip,
+ IconButton
} from "@material-ui/core";
-import * as classnames from "classnames";
-import { DefaultTransformOrigin } from "~/components/popover/helpers";
-import { createTree } from '~/models/tree';
+import classnames from "classnames";
+import { DefaultTransformOrigin } from "components/popover/helpers";
+import { createTree } from 'models/tree';
import { DataTableFilters, DataTableFiltersTree } from "./data-table-filters-tree";
-import { getNodeDescendants } from '~/models/tree';
+import { getNodeDescendants } from 'models/tree';
-export type CssRules = "root" | "icon" | "active" | "checkbox";
+export type CssRules = "root" | "icon" | "iconButton" | "active" | "checkbox";
const styles: StyleRulesCallback<CssRules> = (theme: Theme) => ({
root: {
},
active: {
color: theme.palette.text.primary,
- '& $icon': {
+ '& $iconButton': {
opacity: 1,
},
},
icon: {
- marginRight: 4,
- marginLeft: 4,
+ fontSize: 12,
+ userSelect: 'none',
+ width: 16,
+ height: 15,
+ marginTop: 1
+ },
+ iconButton: {
+ color: theme.palette.text.primary,
opacity: 0.7,
- userSelect: "none",
- width: 16
},
checkbox: {
width: 24,
}
});
+enum SelectionMode {
+ ALL = 'all',
+ NONE = 'none'
+}
+
export interface DataTableFilterProps {
name: string;
filters: DataTableFilters;
onChange?: (filters: DataTableFilters) => void;
+
+ /**
+ * When set to true, only one filter can be selected at a time.
+ */
+ mutuallyExclusive?: boolean;
+
+ /**
+ * By default `all` filters selection means that label should be grayed out.
+ * Use `none` when label is supposed to be grayed out when no filter is selected.
+ */
+ defaultSelection?: SelectionMode;
}
interface DataTableFilterState {
icon = React.createRef<HTMLElement>();
render() {
- const { name, classes, children } = this.props;
- const isActive = getNodeDescendants('')(this.state.filters).some(f => f.selected);
+ const { name, classes, defaultSelection = SelectionMode.ALL, children } = this.props;
+ const isActive = getNodeDescendants('')(this.state.filters)
+ .some(f => defaultSelection === SelectionMode.ALL
+ ? !f.selected
+ : f.selected
+ );
return <>
- <Tooltip title='Filters'>
+ <Tooltip disableFocusListener title='Filters'>
<ButtonBase
className={classnames([classes.root, { [classes.active]: isActive }])}
component="span"
onClick={this.open}
disableRipple>
{children}
- <i className={classnames(["fas fa-filter", classes.icon])}
- data-fa-transform="shrink-3"
- ref={this.icon} />
+ <IconButton component='span' classes={{ root: classes.iconButton }} tabIndex={-1}>
+ <i className={classnames(["fas fa-filter", classes.icon])}
+ data-fa-transform="shrink-3"
+ ref={this.icon} />
+ </IconButton>
</ButtonBase>
</Tooltip>
<Popover
</CardContent>
<DataTableFiltersTree
filters={this.state.filters}
- onChange={filters => this.setState({ filters })} />
+ mutuallyExclusive={this.props.mutuallyExclusive}
+ onChange={filters => {
+ this.setState({ filters });
+ if (this.props.mutuallyExclusive) {
+ const { onChange } = this.props;
+ if (onChange) {
+ onChange(filters);
+ }
+ this.setState({ anchorEl: undefined });
+ }
+ }} />
+ {this.props.mutuallyExclusive ||
<CardActions>
<Button
color="primary"
Cancel
</Button>
</CardActions >
+ }
</Card>
</Popover>
</>;