1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
5 import * as React from "react";
23 } from "@material-ui/core";
24 import * as classnames from "classnames";
25 import { DefaultTransformOrigin } from "../popover/helpers";
26 import { createTree, initTreeNode, mapTree } from '~/models/tree';
27 import { DataTableFilters as DataTableFiltersModel, DataTableFiltersTree } from "./data-table-filters-tree";
28 import { pipe } from 'lodash/fp';
29 import { setNode } from '~/models/tree';
31 export type CssRules = "root" | "icon" | "active" | "checkbox";
33 const styles: StyleRulesCallback<CssRules> = (theme: Theme) => ({
36 display: "inline-flex",
37 justifyContent: "flex-start",
38 flexDirection: "inherit",
41 color: theme.palette.text.primary,
44 color: theme.palette.text.primary,
48 color: theme.palette.text.primary,
66 export interface DataTableFilterItem {
71 export interface DataTableFilterProps {
73 filters: DataTableFilterItem[];
74 onChange?: (filters: DataTableFilterItem[]) => void;
77 interface DataTableFilterState {
78 anchorEl?: HTMLElement;
79 filters: DataTableFilterItem[];
80 prevFilters: DataTableFilterItem[];
81 filtersTree: DataTableFiltersModel;
84 const filters: DataTableFiltersModel = pipe(
86 setNode(initTreeNode({ id: 'Project', value: { name: 'Project' } })),
87 setNode(initTreeNode({ id: 'Process', value: { name: 'Process' } })),
88 setNode(initTreeNode({ id: 'Data collection', value: { name: 'Data collection' } })),
89 setNode(initTreeNode({ id: 'General', parent: 'Data collection', value: { name: 'General' } })),
90 setNode(initTreeNode({ id: 'Output', parent: 'Data collection', value: { name: 'Output' } })),
91 setNode(initTreeNode({ id: 'Log', parent: 'Data collection', value: { name: 'Log' } })),
92 mapTree(node => ({...node, selected: true})),
95 export const DataTableFilters = withStyles(styles)(
96 class extends React.Component<DataTableFilterProps & WithStyles<CssRules>, DataTableFilterState> {
97 state: DataTableFilterState = {
101 filtersTree: filters,
103 icon = React.createRef<HTMLElement>();
106 const { name, classes, children } = this.props;
107 const isActive = this.state.filters.some(f => f.selected);
109 <Tooltip title='Filters'>
111 className={classnames([classes.root, { [classes.active]: isActive }])}
116 <i className={classnames(["fas fa-filter", classes.icon])}
117 data-fa-transform="shrink-3"
122 anchorEl={this.state.anchorEl}
123 open={!!this.state.anchorEl}
124 anchorOrigin={DefaultTransformOrigin}
125 transformOrigin={DefaultTransformOrigin}
126 onClose={this.cancel}>
129 <Typography variant="caption">
134 {this.state.filters.map((filter, index) =>
138 onClick={this.toggleFilter(filter)}
140 checked={filter.selected}
141 className={classes.checkbox} />
148 <DataTableFiltersTree
149 filters={this.state.filtersTree}
150 onChange={filtersTree => this.setState({ filtersTree })} />
156 onClick={this.submit}>
163 onClick={this.cancel}>
172 static getDerivedStateFromProps(props: DataTableFilterProps, state: DataTableFilterState): DataTableFilterState {
173 return props.filters !== state.prevFilters
174 ? { ...state, filters: props.filters, prevFilters: props.filters }
179 this.setState({ anchorEl: this.icon.current || undefined });
183 const { onChange } = this.props;
185 onChange(this.state.filters);
187 this.setState({ anchorEl: undefined });
191 this.setState(prev => ({
193 filters: prev.prevFilters,
198 toggleFilter = (toggledFilter: DataTableFilterItem) => () => {
199 this.setState(prev => ({
201 filters: prev.filters.map(filter =>
202 filter === toggledFilter
203 ? { ...filter, selected: !filter.selected }