From bdaecc68ed71df17f3eac82050ac770856e2e8a1 Mon Sep 17 00:00:00 2001 From: David Matejka Date: Tue, 4 Jun 2024 14:29:37 +0200 Subject: [PATCH 1/3] feat(react-dataview): DataViewDateFilterResetTrigger can reset just one side of interval --- .../date/DataViewDateFilterResetTrigger.tsx | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/packages/react-dataview/src/components/filtering/date/DataViewDateFilterResetTrigger.tsx b/packages/react-dataview/src/components/filtering/date/DataViewDateFilterResetTrigger.tsx index 2618bea0e..63c2e1314 100644 --- a/packages/react-dataview/src/components/filtering/date/DataViewDateFilterResetTrigger.tsx +++ b/packages/react-dataview/src/components/filtering/date/DataViewDateFilterResetTrigger.tsx @@ -8,21 +8,26 @@ import { useDataViewFilterName } from '../../../contexts' export type DataViewDateFilterResetTriggerProps = { name?: string children: ReactElement + type?: 'start' | 'end' } -export const DataViewDateFilterResetTrigger = ({ name, ...props }: DataViewDateFilterResetTriggerProps) => { +export const DataViewDateFilterResetTrigger = ({ name, type, ...props }: DataViewDateFilterResetTriggerProps) => { // eslint-disable-next-line react-hooks/rules-of-hooks name ??= useDataViewFilterName() const [state, setFilter] = useDataViewFilter(name) const cb = useCallback(() => { setFilter(it => ({ ...it, - start: undefined, - end: undefined, + start: !type || type === 'start' ? undefined : it?.start, + end: !type || type === 'end' ? undefined : it?.end, })) - }, [setFilter]) - - if (state?.start === undefined && state?.end === undefined) { + }, [setFilter, type]) + const hasStart = state?.start !== undefined + const hasEnd = state?.end !== undefined + if (!hasStart && !hasEnd) { + return null + } + if (type === 'start' && !hasStart || type === 'end' && !hasEnd) { return null } From c0a588d580be9b5346ba92b2bd9592c206c6272f Mon Sep 17 00:00:00 2001 From: David Matejka Date: Tue, 4 Jun 2024 10:51:39 +0200 Subject: [PATCH 2/3] feat(playground): improve date range filter --- packages/playground/admin/app/pages/grid.tsx | 15 ++- .../lib/components/datagrid/filters/date.tsx | 112 ++++++++++++++---- packages/playground/admin/lib/dict.ts | 5 +- 3 files changed, 103 insertions(+), 29 deletions(-) diff --git a/packages/playground/admin/app/pages/grid.tsx b/packages/playground/admin/app/pages/grid.tsx index a43413a85..297b487f9 100644 --- a/packages/playground/admin/app/pages/grid.tsx +++ b/packages/playground/admin/app/pages/grid.tsx @@ -2,6 +2,7 @@ import { Component, Field, HasMany, HasOne, If } from '@contember/interface' import { Slots } from '../../lib/components/slots' import { DataViewEachRow, DataViewElement, DataViewLayout } from '@contember/react-dataview' import { + createDataGridDateRange, DataGrid, DataGridActionColumn, DataGridBooleanColumn, @@ -21,6 +22,7 @@ import { DataGridNumberColumn, DataGridNumberFilter, DataGridPagination, + DataGridPredefinedDateRange, DataGridQueryFilter, DataGridTable, DataGridTextColumn, @@ -29,6 +31,7 @@ import { DataGridTooltipLabel, } from '../../lib/components/datagrid' import * as React from 'react' +import { ReactNode } from 'react' import { DefaultDropdown, DropdownMenuItem, DropdownMenuSeparator } from '../../lib/components/ui/dropdown' import { Binding, DeleteEntityDialog } from '../../lib/components/binding' import { GridArticleStateLabels } from '../labels' @@ -167,7 +170,17 @@ const CustomGridFilters = Component(() => { <> - + diff --git a/packages/playground/admin/lib/components/datagrid/filters/date.tsx b/packages/playground/admin/lib/components/datagrid/filters/date.tsx index aa2421a9a..06e2842f3 100644 --- a/packages/playground/admin/lib/components/datagrid/filters/date.tsx +++ b/packages/playground/admin/lib/components/datagrid/filters/date.tsx @@ -1,5 +1,5 @@ import * as React from 'react' -import { ReactNode } from 'react' +import { ReactNode, useId } from 'react' import { DataViewDateFilter, DataViewDateFilterInput, DataViewDateFilterProps, DataViewDateFilterResetTrigger, DataViewNullFilterTrigger, DateRangeFilterArtifacts, useDataViewFilter, useDataViewFilterName } from '@contember/react-dataview' import { Component } from '@contember/interface' import { Popover, PopoverContent, PopoverTrigger } from '../../ui/popover' @@ -9,18 +9,22 @@ import { formatDate } from '../../../utils/formatting' import { dict } from '../../../dict' import { DataGridNullFilter } from './common' import { DataGridFilterMobileHiding } from './mobile' +import { Button } from '../../ui/button' +import { Label } from '../../ui/label' +import { XIcon } from 'lucide-react' export type DataGridDateFilterProps = & Omit & { label: ReactNode + ranges?: DataGridPredefinedDateRange[] } -export const DataGridDateFilter = Component(({ label, ...props }: DataGridDateFilterProps) => ( +export const DataGridDateFilter = Component(({ label, ranges, ...props }: DataGridDateFilterProps) => ( - + @@ -65,29 +69,85 @@ const DataGridDateFilterList = () => ( ) +export const createDataGridDateRange = (label: ReactNode, dayDeltaStart: number, dayDeltaEnd: number): DataGridPredefinedDateRange => { + const start = new Date(new Date().setDate(new Date().getDate() + dayDeltaStart)) + const end = new Date(new Date().setDate(new Date().getDate() + dayDeltaEnd)) + return { + label, + start: `${start.getFullYear()}-${String(start.getMonth() + 1).padStart(2, '0')}-${String(start.getDate()).padStart(2, '0')}`, + end: `${end.getFullYear()}-${String(end.getMonth() + 1).padStart(2, '0')}-${String(end.getDate()).padStart(2, '0')}`, + } +} -const DataGridDateFilterSelect = ({ label }: { +const defaultRanges = [createDataGridDateRange(dict.datagrid.today, 0, 0)] + +const DataGridDateFilterSelect = ({ label, ranges = defaultRanges }: { label?: ReactNode -}) => ( - - - {label} - - -
-
- - - - - – - - - - + ranges?: DataGridPredefinedDateRange[] +}) => { + const id = useId() + return ( + + + {label} + + +
+ {ranges?.length > 0 &&
+ {ranges.map(({ start, end, label }) => ( + + ))} +
} +
+
+
+
+ + + + +
+ + + +
+
+
+ + + + +
+ + + +
+
+
+ +
+
- -
- - -) + + + ) +} + +export type DataGridPredefinedDateRange = { start: string, end: string, label: ReactNode } +const DataGridRangeFilter = ({ start, end, label }: DataGridPredefinedDateRange) => { + const name = useDataViewFilterName() + const [filter, setFilter] = useDataViewFilter(name) + const isActive = filter?.start === start && filter?.end === end + return ( + + ) +} diff --git a/packages/playground/admin/lib/dict.ts b/packages/playground/admin/lib/dict.ts index 82f7e21f3..e4ef67d6d 100644 --- a/packages/playground/admin/lib/dict.ts +++ b/packages/playground/admin/lib/dict.ts @@ -27,8 +27,9 @@ export const dict = { }, datagrid: { na: 'N/A', - dateStart: 'Start', - dateEnd: 'End', + dateStart: 'From', + today: 'Today', + dateEnd: 'To', numberFrom: 'From', numberTo: 'To', textReset: 'Reset filter', From 32c374c53e42b9cdbdcab7222014cecd1d695948 Mon Sep 17 00:00:00 2001 From: David Matejka Date: Tue, 4 Jun 2024 14:42:37 +0200 Subject: [PATCH 3/3] chore: ae up --- build/api/react-dataview.api.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build/api/react-dataview.api.md b/build/api/react-dataview.api.md index 18ae239ed..bdcc91f9f 100644 --- a/build/api/react-dataview.api.md +++ b/build/api/react-dataview.api.md @@ -188,12 +188,13 @@ export interface DataViewDateFilterProps { } // @public (undocumented) -export const DataViewDateFilterResetTrigger: ({ name, ...props }: DataViewDateFilterResetTriggerProps) => JSX_2.Element | null; +export const DataViewDateFilterResetTrigger: ({ name, type, ...props }: DataViewDateFilterResetTriggerProps) => JSX_2.Element | null; // @public (undocumented) export type DataViewDateFilterResetTriggerProps = { name?: string; children: ReactElement; + type?: 'start' | 'end'; }; // @internal (undocumented)