Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DataGrid] Improve filters #635

Merged
merged 15 commits into from
Nov 25, 2020
4 changes: 2 additions & 2 deletions packages/grid/_modules_/grid/GridComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import { GridDataContainer } from './components/styled-wrappers/GridDataContaine
import { GridRoot } from './components/styled-wrappers/GridRoot';
import { GridWindow } from './components/styled-wrappers/GridWindow';
import { GridToolbar } from './components/styled-wrappers/GridToolbar';
import { ColumnsToolbarButton } from './components/toolbar/columnsToolbarButton';
import { FilterToolbarButton } from './components/toolbar/filterToolbarButton';
import { ColumnsToolbarButton } from './components/toolbar/ColumnsToolbarButton';
import { FilterToolbarButton } from './components/toolbar/FilterToolbarButton';
import { Viewport } from './components/viewport';
import { Watermark } from './components/watermark';
import { DATA_CONTAINER_CSS_CLASS } from './constants/cssClassesConstants';
Expand Down
5 changes: 5 additions & 0 deletions packages/grid/_modules_/grid/components/icons/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,8 @@ export const LoadIcon = createSvgIcon(
<path d="M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01-.25 1.97-.7 2.8l1.46 1.46C19.54 15.03 20 13.57 20 12c0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-1.01.25-1.97.7-2.8L5.24 7.74C4.46 8.97 4 10.43 4 12c0 4.42 3.58 8 8 8v3l4-4-4-4v3z" />,
'Load',
);

export const DragIcon = createSvgIcon(
<path d="M11 18c0 1.1-.9 2-2 2s-2-.9-2-2 .9-2 2-2 2 .9 2 2zm-2-8c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0-6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm6 4c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z" />,
'Drag',
);
6 changes: 5 additions & 1 deletion packages/grid/_modules_/grid/components/menu/GridMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { ClickAwayListener, Grow, MenuList, Paper, Popper } from '@material-ui/core';
import * as React from 'react';
import ClickAwayListener from '@material-ui/core/ClickAwayListener';
import Grow from '@material-ui/core/Grow';
import MenuList from '@material-ui/core/MenuList';
import Paper from '@material-ui/core/Paper';
import Popper from '@material-ui/core/Popper';

export interface MenuProps {
open: boolean;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { MenuItem } from '@material-ui/core';
import * as React from 'react';
import MenuItem from '@material-ui/core/MenuItem';
import { useGridSelector } from '../../../hooks/features/core/useGridSelector';
import { optionsSelector } from '../../../hooks/utils/useOptionsProp';
import { ApiContext } from '../../api-context';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { MenuItem } from '@material-ui/core';
import * as React from 'react';
import MenuItem from '@material-ui/core/MenuItem';
import { ApiContext } from '../../api-context';
import { FilterItemProps } from './FilterItemProps';

Expand All @@ -14,5 +14,9 @@ export const HideColMenuItem: React.FC<FilterItemProps> = ({ column, onClick })
[apiRef, column?.field, onClick],
);

if (!column) {
return null;
}

return <MenuItem onClick={toggleColumn}>Hide</MenuItem>;
};
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { MenuItem } from '@material-ui/core';
import * as React from 'react';
import MenuItem from '@material-ui/core/MenuItem';
import { useGridSelector } from '../../../hooks/features/core/useGridSelector';
import { sortModelSelector } from '../../../hooks/features/sorting/sortingSelector';
import { SortDirection } from '../../../models/sortModel';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,7 @@ export const useStyles = makeStyles(
'& .MuiDataGrid-toolbar': {
display: 'flex',
alignItems: 'center',
minHeight: 35, // Match MUI Small Button height
backgroundColor: theme.palette.background.default,
border: `1px solid ${borderColor}`,
padding: 4,
},
'& .MuiDataGrid-columnsContainer': {
position: 'absolute',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { IconButton } from '@material-ui/core';
import * as React from 'react';
import Button from '@material-ui/core/Button';
import { PreferencePanelsValue } from '../../hooks/features/preferencesPanel/preferencesPanelValue';
import { useIcons } from '../../hooks/utils/useIcons';
import { ApiContext } from '../api-context';
Expand All @@ -14,8 +14,13 @@ export const ColumnsToolbarButton: React.FC<{}> = () => {
}, [apiRef]);

return (
<IconButton onClick={showColumns} color="primary" aria-label="Show Column Selector">
{iconElement}
</IconButton>
<Button
onClick={showColumns}
color="primary"
aria-label="Show Column Selector"
startIcon={iconElement}
>
Columns
</Button>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import Badge from '@material-ui/core/Badge';
import Button from '@material-ui/core/Button';
import Tooltip from '@material-ui/core/Tooltip';
import * as React from 'react';
import { columnLookupSelector } from '../../hooks/features/columns/columnsSelector';
import { useGridSelector } from '../../hooks/features/core/useGridSelector';
import {
activeFilterItemsSelector,
filterItemsCounterSelector,
} from '../../hooks/features/filter/filterSelector';
import { useIcons } from '../../hooks/utils/useIcons';
import { optionsSelector } from '../../hooks/utils/useOptionsProp';
import { ApiContext } from '../api-context';

export const FilterToolbarButton: React.FC<{}> = () => {
const apiRef = React.useContext(ApiContext);
const options = useGridSelector(apiRef, optionsSelector);
const counter = useGridSelector(apiRef, filterItemsCounterSelector);
const activeFilters = useGridSelector(apiRef, activeFilterItemsSelector);
const lookup = useGridSelector(apiRef, columnLookupSelector);
const tooltipContentNode = React.useMemo(() => {
if (counter === 0) {
return 'Show Filters';
}
return (
<div>
{counter} active filter(s)
<ul>
{activeFilters.map((item) => (
<li key={item.id}>
{lookup[item.columnField!].headerName || item.columnField} {item.operatorValue}{' '}
{item.value}
</li>
))}
</ul>
</div>
);
}, [counter, activeFilters, lookup]);

const icons = useIcons();
const filterIconElement = React.createElement(icons.ColumnFiltering!, {});
const showFilter = React.useCallback(() => {
apiRef!.current.showFilterPanel();
}, [apiRef]);

if (options.disableColumnFilter) {
return null;
}

return (
<Tooltip title={tooltipContentNode} enterDelay={1000}>
<Button
onClick={showFilter}
color="primary"
aria-label="Show Filters"
startIcon={
<Badge badgeContent={counter} color="primary">
{filterIconElement}
</Badge>
}
>
Filters
</Button>
</Tooltip>
);
};

This file was deleted.

112 changes: 84 additions & 28 deletions packages/grid/_modules_/grid/components/tools/ColumnsPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,41 +1,50 @@
import * as React from 'react';
import FormControl from '@material-ui/core/FormControl';
import IconButton from '@material-ui/core/IconButton';
import Switch from '@material-ui/core/Switch';
import Button from '@material-ui/core/Button';
import Checkbox from '@material-ui/core/Checkbox';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import GridList from '@material-ui/core/GridList';
import ListItem from '@material-ui/core/ListItem';
import * as React from 'react';
import TextField from '@material-ui/core/TextField';
import { makeStyles } from '@material-ui/core/styles';
import { allColumnsSelector } from '../../hooks/features/columns/columnsSelector';
import { useGridSelector } from '../../hooks/features/core/useGridSelector';
import { PREVENT_HIDE_PREFERENCES } from '../../constants/index';
import { optionsSelector } from '../../hooks/utils/useOptionsProp';
import { ApiContext } from '../api-context';
import { DragIcon } from '../icons/index';

const useStyles = makeStyles(() => ({
gridListRoot: {
maxWidth: '100%',
columnsListContainer: {
paddingTop: 8,
paddingLeft: 12,
},
column: {
display: 'flex',
justifyContent: 'space-between',
padding: '2px 4px',
},
switch: {
marginRight: 4,
},
dragIconRoot: {
justifyContent: 'flex-end',
},
}));

export const ColumnsPanel: React.FC<{}> = () => {
const classes = useStyles();

const apiRef = React.useContext(ApiContext);
const searchInputRef = React.useRef<HTMLInputElement>(null);
const columns = useGridSelector(apiRef, allColumnsSelector);

const dontHidePreferences = React.useCallback(
(event: React.ChangeEvent<{}>) => {
apiRef!.current.publishEvent(PREVENT_HIDE_PREFERENCES, {});
event.preventDefault();
},
[apiRef],
);
const { disableColumnReorder } = useGridSelector(apiRef, optionsSelector);
const [searchValue, setSearchValue] = React.useState('');

const toggleColumn = React.useCallback(
(event: React.ChangeEvent<HTMLInputElement>) => {
dontHidePreferences(event);
apiRef!.current.toggleColumn(event.target.name, !event.target.checked);
(event: React.MouseEvent<HTMLButtonElement>) => {
const { name } = event.target as HTMLInputElement;
apiRef!.current.toggleColumn(name);
},
[apiRef, dontHidePreferences],
[apiRef],
);

const toggleAllColumns = React.useCallback(
Expand All @@ -52,28 +61,75 @@ export const ColumnsPanel: React.FC<{}> = () => {
const showAllColumns = React.useCallback(() => toggleAllColumns(false), [toggleAllColumns]);
const hideAllColumns = React.useCallback(() => toggleAllColumns(true), [toggleAllColumns]);

const onSearchColumnValueChange = React.useCallback((event) => {
setSearchValue(event.target.value.toLowerCase());
}, []);

const currentColumns = React.useMemo(
() =>
!searchValue
? columns
: columns.filter(
(column) =>
column.field.toLowerCase().indexOf(searchValue) > -1 ||
(column.headerName && column.headerName.toLowerCase().indexOf(searchValue) > -1),
),
[columns, searchValue],
);

React.useEffect(() => {
if (searchInputRef && searchInputRef.current) {
searchInputRef.current.focus();
}
});

return (
<React.Fragment>
<div className="panelMainContainer">
<GridList cellHeight={'auto'} className={classes.gridListRoot}>
{columns.map((column) => (
<ListItem key={column.field}>
<div className="MuiDataGridPanel-header">
<TextField
label="Find column"
placeholder="Column Title"
inputRef={searchInputRef}
value={searchValue}
onChange={onSearchColumnValueChange}
type="text"
fullWidth
/>
</div>
<div className="MuiDataGridPanel-container">
<div className={classes.columnsListContainer}>
{currentColumns.map((column) => (
<div key={column.field} className={classes.column}>
<FormControlLabel
control={
<Checkbox
<Switch
className={classes.switch}
checked={!column.hide}
onChange={toggleColumn}
onClick={toggleColumn}
name={column.field}
color="primary"
size="small"
/>
}
label={column.headerName || column.field}
/>
</ListItem>
{!disableColumnReorder && (
<FormControl draggable className={classes.dragIconRoot}>
<IconButton
aria-label="Drag to reorder column"
title="Reorder Column"
size="small"
disabled
>
<DragIcon />
</IconButton>
</FormControl>
)}
</div>
))}
</GridList>
</div>
</div>
<div className="panelFooter">
<div className="MuiDataGridPanel-footer">
<Button onClick={hideAllColumns} color="primary">
Hide All
</Button>
Expand Down
Loading