mirror of
https://github.com/collinbarrett/FilterLists.git
synced 2026-03-11 09:04:27 +00:00
implement free-form search on name and description columns
This commit is contained in:
parent
e33e2f16fa
commit
f1913fa6e2
3 changed files with 73 additions and 1 deletions
|
|
@ -2,7 +2,7 @@ import { Table } from 'antd';
|
|||
import React from 'react';
|
||||
import { RouteComponentProps } from 'react-router';
|
||||
|
||||
import { useTablePageSizer } from '../../hooks';
|
||||
import { useSearchColumnFilter, useTablePageSizer } from '../../hooks';
|
||||
import { Language } from '../../interfaces/Language';
|
||||
import { License } from '../../interfaces/License';
|
||||
import { List } from '../../interfaces/List';
|
||||
|
|
@ -28,6 +28,8 @@ interface Props {
|
|||
export const ListsTable = (props: RouteComponentProps & Props) => {
|
||||
const { lists, languages, licenses, software, tags, ...routeComponentProps } = props;
|
||||
const tablePageSize = useTablePageSizer();
|
||||
const searchNameColumn = useSearchColumnFilter<List>(nameof<List>("name"));
|
||||
const searchDescriptionColumn = useSearchColumnFilter<List>(nameof<List>("description"));
|
||||
return (
|
||||
<Table<List>
|
||||
dataSource={lists}
|
||||
|
|
@ -56,6 +58,9 @@ export const ListsTable = (props: RouteComponentProps & Props) => {
|
|||
width={tablePageSize.isNarrowWindow ? undefined : 200}
|
||||
className={styles.nogrow}
|
||||
fixed="left"
|
||||
filterDropdown={searchNameColumn.filterDropdown}
|
||||
filterIcon={searchNameColumn.filterIcon}
|
||||
onFilter={searchNameColumn.onFilter}
|
||||
render={(name: string) =>
|
||||
<div>{name}</div>} />
|
||||
{tablePageSize.isNarrowWindow
|
||||
|
|
@ -64,6 +69,9 @@ export const ListsTable = (props: RouteComponentProps & Props) => {
|
|||
title="Description"
|
||||
dataIndex={nameof<List>("description")}
|
||||
className={styles.nogrow}
|
||||
filterDropdown={searchDescriptionColumn.filterDropdown}
|
||||
filterIcon={searchDescriptionColumn.filterIcon}
|
||||
onFilter={searchDescriptionColumn.onFilter}
|
||||
render={(description: string, list: List) =>
|
||||
<Description
|
||||
description={description}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { useLanguages } from './useLanguages';
|
||||
import { useLicenses } from './useLicenses';
|
||||
import { useLists } from './useLists';
|
||||
import { useSearchColumnFilter } from './useSearchColumnFilter';
|
||||
import { useSoftware } from './useSoftware';
|
||||
import { useSyntaxes } from './useSyntaxes';
|
||||
import { useTablePageSizer } from './useTablePageSizer';
|
||||
|
|
@ -10,6 +11,7 @@ export {
|
|||
useLanguages,
|
||||
useLicenses,
|
||||
useLists,
|
||||
useSearchColumnFilter,
|
||||
useSoftware,
|
||||
useSyntaxes,
|
||||
useTablePageSizer,
|
||||
|
|
|
|||
62
src/FilterLists.Web.V2/src/hooks/useSearchColumnFilter.tsx
Normal file
62
src/FilterLists.Web.V2/src/hooks/useSearchColumnFilter.tsx
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
import { Button, Icon, Input } from 'antd';
|
||||
import { FilterDropdownProps } from 'antd/lib/table';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
interface FilterPropsState<T> {
|
||||
filterDropdown?: React.ReactNode | ((props: FilterDropdownProps) => React.ReactNode);
|
||||
filterIcon?: React.ReactNode | ((filtered: boolean) => React.ReactNode);
|
||||
onFilter?: (value: any, record: T) => boolean;
|
||||
}
|
||||
|
||||
export const useSearchColumnFilter = <T extends {}>(dataIndex: string) => {
|
||||
const [filterProps, setFilterProps] = useState<FilterPropsState<T>>({
|
||||
filterDropdown: undefined,
|
||||
filterIcon: undefined,
|
||||
onFilter: undefined
|
||||
});
|
||||
useEffect(() => {
|
||||
const handleSearch = (confirm?: () => void) => {
|
||||
confirm && confirm();
|
||||
};
|
||||
const handleReset = (clearFilters?: (selectedKeys: string[]) => void) => {
|
||||
clearFilters && clearFilters([]);
|
||||
};
|
||||
setFilterProps({
|
||||
filterDropdown: ({ setSelectedKeys, selectedKeys, confirm, clearFilters }) => (
|
||||
<div style={{ padding: 8 }}>
|
||||
<Input
|
||||
placeholder={`Search ${dataIndex}`}
|
||||
value={selectedKeys && selectedKeys[0]}
|
||||
onChange={e => setSelectedKeys && setSelectedKeys(e.target.value ? [e.target.value] : [])}
|
||||
onPressEnter={() => handleSearch(confirm)}
|
||||
style={{ width: 188, marginBottom: 8, display: 'block' }} />
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => handleSearch(confirm)}
|
||||
icon="search"
|
||||
size="small"
|
||||
style={{ width: 90, marginRight: 8 }} >
|
||||
Search
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => handleReset(clearFilters)}
|
||||
size="small"
|
||||
style={{ width: 90 }}>
|
||||
Reset
|
||||
</Button>
|
||||
</div>
|
||||
),
|
||||
filterIcon: filtered => (
|
||||
<Icon type="search" style={{ color: filtered ? '#1890ff' : undefined }} />
|
||||
),
|
||||
onFilter: (value, record) => {
|
||||
const searchValue = (record as any)[dataIndex];
|
||||
return searchValue && searchValue
|
||||
.toString()
|
||||
.toLowerCase()
|
||||
.includes(value.toLowerCase())
|
||||
}
|
||||
})
|
||||
}, [dataIndex]);
|
||||
return filterProps;
|
||||
};
|
||||
Loading…
Reference in a new issue