From 72c1c384a1f05da8eed3fb4667e7553bdb8979ee Mon Sep 17 00:00:00 2001 From: winzlieb Date: Mon, 14 Mar 2022 22:04:11 +0100 Subject: [PATCH] get managed filter working in all cases --- .../config/defaultColumnRawDefinition.ts | 19 +++++++++-- .../components/ngo/HostOfferLookupTable.tsx | 32 ++++++++++++------- .../components/util/datagrid/columnRaw.ts | 4 ++- .../util/datagrid/extendedFilter.ts | 31 ++++++++++++++++++ .../components/util/tableValueMapper.ts | 17 +++++++++- 5 files changed, 88 insertions(+), 15 deletions(-) create mode 100644 frontend/search/components/util/datagrid/extendedFilter.ts diff --git a/frontend/search/components/config/defaultColumnRawDefinition.ts b/frontend/search/components/config/defaultColumnRawDefinition.ts index 28dee3d..8d390b8 100644 --- a/frontend/search/components/config/defaultColumnRawDefinition.ts +++ b/frontend/search/components/config/defaultColumnRawDefinition.ts @@ -62,7 +62,15 @@ const columnsRaw: ColumnRaw[] = [ "group": "time", "header": "From", "type": "date", - "defaultWidth": 90 + "defaultWidth": 90, + "options": { + "dateFormat": "MM/DD/YYYY", + "transform": { + "date2Iso": { + "inputDateFormat": "MM/DD/YYYY" + } + } + } }, { "name": "time_duration_str", @@ -74,7 +82,14 @@ const columnsRaw: ColumnRaw[] = [ "name": "languages", "header": "Languages", "type": "object", - "defaultWidth": 200 + "defaultWidth": 200, + "options": { + "transform": { + array2string: { + join: "," + } + } + } }, { "name": "accessible", diff --git a/frontend/search/components/ngo/HostOfferLookupTable.tsx b/frontend/search/components/ngo/HostOfferLookupTable.tsx index 7411cfe..2ec642b 100644 --- a/frontend/search/components/ngo/HostOfferLookupTable.tsx +++ b/frontend/search/components/ngo/HostOfferLookupTable.tsx @@ -5,7 +5,6 @@ import {CheckBoxOutlineBlank, CheckBox} from '@mui/icons-material' import '@inovua/reactdatagrid-community/index.css' import DataGrid from '@inovua/reactdatagrid-community' -import filter from '@inovua/reactdatagrid-community/filter' import {TypeColumn, TypeFilterValue, TypeSingleFilterValue} from "@inovua/reactdatagrid-community/types" import DateFilter from '@inovua/reactdatagrid-community/DateFilter' import StringFilter from '@inovua/reactdatagrid-community/StringFilter' @@ -26,6 +25,7 @@ import { ColumnRaw } from '../util/datagrid/columnRaw' import columnsRaw from "../config/defaultColumnRawDefinition"; import {transformValue} from "../util/tableValueMapper"; import {filterUndefOrNull} from "../util/notEmpty"; +import extendedFilter from "../util/datagrid/extendedFilter"; global.moment = moment @@ -103,7 +103,7 @@ const columns: TypeColumn[] = defaultColumnRawDefinition })) const defaultFilterValue: TypeFilterValue = columns - .filter(({type}) => type && ['string', 'number', 'date', 'boolean'].includes(type)) + .filter(({type}) => type && ['string', 'number', 'boolean', 'date'].includes(type)) .map(({name, type}) => { return { name, @@ -125,15 +125,25 @@ async function mutate(auth: AuthState, onEditComplete: {value: string, columnId: return result?.write_rw } -const rw_default = {rw_note: ''} // Required for filtering 'Not empty'. TODO: Should be fixed in StringFilter +const rw_default = { + rw_contacted: false, + rw_contact_replied: false, + rw_offer_occupied: false, + rw_note: ''} // Required for filtering 'Not empty'. TODO: Should be fixed in StringFilter const HostOfferLookupTable = ({data_ro, data_rw, refetch_rw, onFilteredDataChange}: HostOfferLookupTableProps) => { const [dataSource, setDataSource] = useState([]); const [filteredData, setFilteredData] = useState([]); - const [filterValue, setFilterValue] = useState(defaultFilterValue); + const [filterValue, setFilterValue] = useState(defaultFilterValue); - const filterValueChangeHandler = useCallback((_filterValue) => { - const data = filter(dataSource, filterValue) as HostOfferLookupTableDataType[] + const filterValueChangeHandler = useCallback((_filterValue: TypeFilterValue) => { + const data = !_filterValue + ? dataSource + : extendedFilter( + dataSource, + _filterValue, + columnsRaw + ) setFilterValue(_filterValue); setFilteredData(data) onFilteredDataChange && onFilteredDataChange(data) @@ -141,13 +151,12 @@ const HostOfferLookupTable = ({data_ro, data_rw, refetch_rw, onFilteredDataChang useEffect(() => { - // @ts-ignore - const data = filterUndefOrNull( data_ro + const data = filterUndefOrNull( data_ro ?.map( e_ro => ({ ...((data_rw?.find((e_rw) => e_ro.id_tmp === e_rw.id || `rw_${e_ro.id}` === e_rw.id ) || rw_default)), ...e_ro - }) ) || []) + }) ) || []).map(v => transformValue(v, columnsRaw)) // @ts-ignore data && setDataSource(data) @@ -171,12 +180,13 @@ const HostOfferLookupTable = ({data_ro, data_rw, refetch_rw, onFilteredDataChang filterable showColumnMenuFilterOptions={true} showFilteringMenuItems={true} - defaultFilterValue={defaultFilterValue} + filterValue={filterValue} + onFilterValueChange={filterValueChangeHandler} rowIndexColumn enableSelection enableColumnAutosize={false} columns={columns} - dataSource={dataSource} + dataSource={filteredData} i18n={reactdatagridi18n || undefined} style={{height: '100%'}} onEditComplete={onEditComplete} diff --git a/frontend/search/components/util/datagrid/columnRaw.ts b/frontend/search/components/util/datagrid/columnRaw.ts index d38e9d5..2d25789 100644 --- a/frontend/search/components/util/datagrid/columnRaw.ts +++ b/frontend/search/components/util/datagrid/columnRaw.ts @@ -1,8 +1,10 @@ -import {Array2StringTransformOptions} from "../tableValueMapper"; +import {Array2StringTransformOptions, DateToISOTransformOptions} from "../tableValueMapper"; export type ColumnOptions = { + dateFormat?: string transform?: { array2string?: Array2StringTransformOptions + date2Iso?: DateToISOTransformOptions } } export interface ColumnRaw { diff --git a/frontend/search/components/util/datagrid/extendedFilter.ts b/frontend/search/components/util/datagrid/extendedFilter.ts new file mode 100644 index 0000000..c6524c4 --- /dev/null +++ b/frontend/search/components/util/datagrid/extendedFilter.ts @@ -0,0 +1,31 @@ +import {TypeColumn, TypeSingleFilterValue} from "@inovua/reactdatagrid-community/types"; +import filter from "@inovua/reactdatagrid-community/filter"; +import moment from "moment"; +import {ColumnRaw} from "./columnRaw"; + +const defaultDateFormat = "MM/DD/YYYY" +const extendedFilter: ( + data: T[], + filterValue: TypeSingleFilterValue[], + columnsRaw: ColumnRaw[] + ) => T[] = (data: T[], filterValue: TypeSingleFilterValue[], columnsRaw: ColumnRaw[] ) => { + const columns = columnsRaw + .filter(({ type }) => type === "date") + .reduce((prev, cur) => + ({...prev ,[cur.name]: { dateFormat: cur.options?.dateFormat || defaultDateFormat }}), {}) + return filter( + data, + filterValue.map(fV => { + if (typeof fV.value == 'string' && fV.type === 'date') { + return { + ...fV, + value: moment(fV.value).format(defaultDateFormat) + } + } + return fV + }), + undefined, + columns) as T[]; + } + + export default extendedFilter diff --git a/frontend/search/components/util/tableValueMapper.ts b/frontend/search/components/util/tableValueMapper.ts index d4744a8..09a71a9 100644 --- a/frontend/search/components/util/tableValueMapper.ts +++ b/frontend/search/components/util/tableValueMapper.ts @@ -1,12 +1,24 @@ import {ColumnRaw} from "./datagrid/columnRaw"; +import moment from "moment" export type Array2StringTransformOptions = { join?: string } +export type DateToISOTransformOptions = { + inputDateFormat: string + outputDateFormat?: string +} + const array2string = (value: string[], options: Array2StringTransformOptions) => value.join(options.join || ',') +const callOneOrMany: (els: T | T[], cb: (d: T, ...rest: any[]) => O, args?: any[]) => O | O [] = (els, cb, args = []) => + Array.isArray(els) ? els.map(v => cb(v, ...args)) : cb(els, ...args) + +const dateToIso: (date: string, options: DateToISOTransformOptions) => string = + (date, { inputDateFormat, outputDateFormat}) => moment(date, inputDateFormat).format(outputDateFormat) + export const transformValue: (values: T, columnsRaw: ColumnRaw[]) => T = (values, columnsRaw) => { const newValues = {...values} columnsRaw @@ -14,8 +26,11 @@ export const transformValue: (values: T, columnsRaw: ColumnRaw[]) => T = (val const transform = c.options?.transform if (!transform) return // @ts-ignore - const value = values[c.name] + let value = values[c.name] if (!value) return + if(transform.date2Iso) { + value = callOneOrMany(value, dateToIso, [ transform.date2Iso ]) + } if (transform.array2string) { try { // @ts-ignore