Quick action for resetting all datatable filters

Summary:
As we persist column filters between sessions - sometimes it's not obvious that they are applied.

This diff adds "Reset filters" action just near message "No records match the current search / filter criteria" to make it obvious that some records are hidden because of filters and let user quickly disable filters to see all items.

The same action also added to datatable's context menu.

Changelog:
Quick action "Reset filters" for datatable-based plugins which is shown in context menu and in empty table when all items filtered out.

Reviewed By: timur-valiev

Differential Revision: D36600535

fbshipit-source-id: 782e7f863f2f52d7f6017685bdebcb1feeb97dbd
This commit is contained in:
Anton Nikolaev
2022-05-24 04:51:19 -07:00
committed by Facebook GitHub Bot
parent 02058a14d0
commit 8d07b7b644
3 changed files with 44 additions and 7 deletions

View File

@@ -534,8 +534,9 @@ export function DataTable<T extends object>(
const emptyRenderer =
props.onRenderEmpty === undefined
? props.onRenderEmpty
? createDefaultEmptyRenderer(tableManager)
: props.onRenderEmpty;
let mainSection: JSX.Element;
if (props.scrollable) {
const dataSourceRenderer = (
@@ -620,7 +621,7 @@ DataTable.defaultProps = {
enableMultiSelect: true,
enableContextMenu: true,
enablePersistSettings: true,
onRenderEmpty: emptyRenderer,
onRenderEmpty: undefined,
} as Partial<DataTableProps<any>>;
/* eslint-disable react-hooks/rules-of-hooks */
@@ -662,16 +663,27 @@ function syncRecordsToDataSource<T>(
}
}
function emptyRenderer(dataSource: DataSource<any>) {
return <EmptyTable dataSource={dataSource} />;
function createDefaultEmptyRenderer<T>(dataTableManager?: DataTableManager<T>) {
return (dataSource?: DataSource<T, T[keyof T]>) => (
<EmptyTable dataSource={dataSource} dataManager={dataTableManager} />
);
}
function EmptyTable({dataSource}: {dataSource: DataSource<any>}) {
function EmptyTable<T>({
dataSource,
dataManager,
}: {
dataSource?: DataSource<T, T[keyof T]>;
dataManager?: DataTableManager<T>;
}) {
const resetFilters = useCallback(() => {
dataManager?.resetFilters();
}, [dataManager]);
return (
<Layout.Container
center
style={{width: '100%', padding: 40, color: theme.textColorSecondary}}>
{dataSource.size === 0 ? (
{dataSource?.size === 0 ? (
<>
<CoffeeOutlined style={{fontSize: '2em', margin: 8}} />
<Typography.Text type="secondary">No records yet</Typography.Text>
@@ -680,7 +692,12 @@ function EmptyTable({dataSource}: {dataSource: DataSource<any>}) {
<>
<SearchOutlined style={{fontSize: '2em', margin: 8}} />
<Typography.Text type="secondary">
No records match the current search / filter criteria
No records match the current search / filter criteria.
</Typography.Text>
<Typography.Text>
<Typography.Link onClick={resetFilters}>
Reset filters
</Typography.Link>
</Typography.Text>
</>
)}

View File

@@ -51,6 +51,8 @@ type Action<Name extends string, Args = {}> = {type: Name} & Args;
type DataManagerActions<T> =
/** Reset the current table preferences, including column widths an visibility, back to the default */
| Action<'reset'>
/** Disable the current column filters */
| Action<'resetFilters'>
/** Resizes the column with the given key to the given width */
| Action<'resizeColumn', {column: keyof T; width: number | Percentage}>
/** Sort by the given column. This toggles statefully between ascending, descending, none (insertion order of the data source) */
@@ -142,6 +144,13 @@ export const dataTableManagerReducer = produce<
draft.selection = castDraft(emptySelection);
break;
}
case 'resetFilters': {
draft.columns.forEach((c) =>
c.filters?.forEach((f) => (f.enabled = false)),
);
draft.searchValue = '';
break;
}
case 'resizeColumn': {
const {column, width} = action;
const col = draft.columns.find((c) => c.key === column)!;
@@ -288,6 +297,7 @@ export const dataTableManagerReducer = produce<
*/
export type DataTableManager<T> = {
reset(): void;
resetFilters(): void;
selectItem(
index: number | ((currentSelection: number) => number),
addToSelection?: boolean,
@@ -319,6 +329,9 @@ export function createDataTableManager<T>(
reset() {
dispatch({type: 'reset'});
},
resetFilters() {
dispatch({type: 'resetFilters'});
},
selectItem(index: number, addToSelection = false, allowUnselect = false) {
dispatch({
type: 'selectItem',

View File

@@ -160,6 +160,13 @@ export function tableContextMenuFactory<T>(
</Menu.Item>
))}
</SubMenu>
<Menu.Item
key="resetFilters"
onClick={() => {
dispatch({type: 'resetFilters'});
}}>
Reset filters
</Menu.Item>
<Menu.Item
key="reset"
onClick={() => {