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:
committed by
Facebook GitHub Bot
parent
02058a14d0
commit
8d07b7b644
@@ -534,8 +534,9 @@ export function DataTable<T extends object>(
|
|||||||
|
|
||||||
const emptyRenderer =
|
const emptyRenderer =
|
||||||
props.onRenderEmpty === undefined
|
props.onRenderEmpty === undefined
|
||||||
? props.onRenderEmpty
|
? createDefaultEmptyRenderer(tableManager)
|
||||||
: props.onRenderEmpty;
|
: props.onRenderEmpty;
|
||||||
|
|
||||||
let mainSection: JSX.Element;
|
let mainSection: JSX.Element;
|
||||||
if (props.scrollable) {
|
if (props.scrollable) {
|
||||||
const dataSourceRenderer = (
|
const dataSourceRenderer = (
|
||||||
@@ -620,7 +621,7 @@ DataTable.defaultProps = {
|
|||||||
enableMultiSelect: true,
|
enableMultiSelect: true,
|
||||||
enableContextMenu: true,
|
enableContextMenu: true,
|
||||||
enablePersistSettings: true,
|
enablePersistSettings: true,
|
||||||
onRenderEmpty: emptyRenderer,
|
onRenderEmpty: undefined,
|
||||||
} as Partial<DataTableProps<any>>;
|
} as Partial<DataTableProps<any>>;
|
||||||
|
|
||||||
/* eslint-disable react-hooks/rules-of-hooks */
|
/* eslint-disable react-hooks/rules-of-hooks */
|
||||||
@@ -662,16 +663,27 @@ function syncRecordsToDataSource<T>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function emptyRenderer(dataSource: DataSource<any>) {
|
function createDefaultEmptyRenderer<T>(dataTableManager?: DataTableManager<T>) {
|
||||||
return <EmptyTable dataSource={dataSource} />;
|
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 (
|
return (
|
||||||
<Layout.Container
|
<Layout.Container
|
||||||
center
|
center
|
||||||
style={{width: '100%', padding: 40, color: theme.textColorSecondary}}>
|
style={{width: '100%', padding: 40, color: theme.textColorSecondary}}>
|
||||||
{dataSource.size === 0 ? (
|
{dataSource?.size === 0 ? (
|
||||||
<>
|
<>
|
||||||
<CoffeeOutlined style={{fontSize: '2em', margin: 8}} />
|
<CoffeeOutlined style={{fontSize: '2em', margin: 8}} />
|
||||||
<Typography.Text type="secondary">No records yet</Typography.Text>
|
<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}} />
|
<SearchOutlined style={{fontSize: '2em', margin: 8}} />
|
||||||
<Typography.Text type="secondary">
|
<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>
|
</Typography.Text>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -51,6 +51,8 @@ type Action<Name extends string, Args = {}> = {type: Name} & Args;
|
|||||||
type DataManagerActions<T> =
|
type DataManagerActions<T> =
|
||||||
/** Reset the current table preferences, including column widths an visibility, back to the default */
|
/** Reset the current table preferences, including column widths an visibility, back to the default */
|
||||||
| Action<'reset'>
|
| Action<'reset'>
|
||||||
|
/** Disable the current column filters */
|
||||||
|
| Action<'resetFilters'>
|
||||||
/** Resizes the column with the given key to the given width */
|
/** Resizes the column with the given key to the given width */
|
||||||
| Action<'resizeColumn', {column: keyof T; width: number | Percentage}>
|
| 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) */
|
/** 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);
|
draft.selection = castDraft(emptySelection);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'resetFilters': {
|
||||||
|
draft.columns.forEach((c) =>
|
||||||
|
c.filters?.forEach((f) => (f.enabled = false)),
|
||||||
|
);
|
||||||
|
draft.searchValue = '';
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'resizeColumn': {
|
case 'resizeColumn': {
|
||||||
const {column, width} = action;
|
const {column, width} = action;
|
||||||
const col = draft.columns.find((c) => c.key === column)!;
|
const col = draft.columns.find((c) => c.key === column)!;
|
||||||
@@ -288,6 +297,7 @@ export const dataTableManagerReducer = produce<
|
|||||||
*/
|
*/
|
||||||
export type DataTableManager<T> = {
|
export type DataTableManager<T> = {
|
||||||
reset(): void;
|
reset(): void;
|
||||||
|
resetFilters(): void;
|
||||||
selectItem(
|
selectItem(
|
||||||
index: number | ((currentSelection: number) => number),
|
index: number | ((currentSelection: number) => number),
|
||||||
addToSelection?: boolean,
|
addToSelection?: boolean,
|
||||||
@@ -319,6 +329,9 @@ export function createDataTableManager<T>(
|
|||||||
reset() {
|
reset() {
|
||||||
dispatch({type: 'reset'});
|
dispatch({type: 'reset'});
|
||||||
},
|
},
|
||||||
|
resetFilters() {
|
||||||
|
dispatch({type: 'resetFilters'});
|
||||||
|
},
|
||||||
selectItem(index: number, addToSelection = false, allowUnselect = false) {
|
selectItem(index: number, addToSelection = false, allowUnselect = false) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'selectItem',
|
type: 'selectItem',
|
||||||
|
|||||||
@@ -160,6 +160,13 @@ export function tableContextMenuFactory<T>(
|
|||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
))}
|
))}
|
||||||
</SubMenu>
|
</SubMenu>
|
||||||
|
<Menu.Item
|
||||||
|
key="resetFilters"
|
||||||
|
onClick={() => {
|
||||||
|
dispatch({type: 'resetFilters'});
|
||||||
|
}}>
|
||||||
|
Reset filters
|
||||||
|
</Menu.Item>
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
key="reset"
|
key="reset"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user