From f442d71fe25698fc462f59e04caf1f26dc778b84 Mon Sep 17 00:00:00 2001 From: Radoslaw Szwajkowski Date: Thu, 12 Oct 2023 12:31:15 +0200 Subject: [PATCH] Extract date operations in DateRangeFilter to utility functions Signed-off-by: Radoslaw Szwajkowski --- .../src/components/Filter/DateRangeFilter.tsx | 63 ++++++++++--------- .../src/components/FilterGroup/matchers.ts | 6 +- packages/common/src/utils/dates.ts | 22 ++++++- 3 files changed, 54 insertions(+), 37 deletions(-) diff --git a/packages/common/src/components/Filter/DateRangeFilter.tsx b/packages/common/src/components/Filter/DateRangeFilter.tsx index 451c50c78..6bd04c22b 100644 --- a/packages/common/src/components/Filter/DateRangeFilter.tsx +++ b/packages/common/src/components/Filter/DateRangeFilter.tsx @@ -1,7 +1,20 @@ import React, { FormEvent, useState } from 'react'; -import { DateTime, Interval } from 'luxon'; +import { DateTime } from 'luxon'; -import { DatePicker, InputGroup, ToolbarFilter } from '@patternfly/react-core'; +import { + DatePicker, + InputGroup, + isValidDate as isValidJSDate, + ToolbarFilter, +} from '@patternfly/react-core'; + +import { + isValidDate, + isValidInterval, + parseISOtoJSDate, + toISODate, + toISODateInterval, +} from '../../utils'; import { FilterTypeProps } from './types'; @@ -24,43 +37,33 @@ export const DateRangeFilter = ({ placeholderLabel, showFilter = true, }: FilterTypeProps) => { - const validFilters = - selectedFilters - ?.map((str) => Interval.fromISO(str)) - ?.filter((range: Interval) => range.isValid) ?? []; - - const [from, setFrom] = useState(); - const [to, setTo] = useState(); + const validFilters = selectedFilters?.filter(isValidInterval) ?? []; - const rangeToOption = (range: Interval): string => range.toISODate().replace('/', ' - '); + const [from, setFrom] = useState(); + const [to, setTo] = useState(); - const optionToRange = (option: string): Interval => Interval.fromISO(option.replace(' - ', '/')); + const rangeToOption = (range: string): string => range.replace('/', ' - '); + const optionToRange = (option: string): string => option.replace(' - ', '/'); const clearSingleRange = (option) => { const target = optionToRange(option); - onFilterUpdate([ - ...validFilters.filter((range) => range.equals(target)).map((range) => range.toISODate()), - ]); + onFilterUpdate([...validFilters.filter((range) => range !== target)]); }; const onFromDateChange = (even: FormEvent, value: string) => { - if (value?.length === 10 && DateTime.fromISO(value).isValid) { - setFrom(DateTime.fromISO(value)); + if (value?.length === 10 && isValidDate(value)) { + setFrom(parseISOtoJSDate(value)); setTo(undefined); } }; const onToDateChange = (even: FormEvent, value: string) => { - if (value?.length === 10 && DateTime.fromISO(value).isValid) { - const newTo = DateTime.fromISO(value); + if (value?.length === 10 && isValidDate(value)) { + const newTo = parseISOtoJSDate(value); setTo(newTo); - const target = Interval.fromDateTimes(from, newTo); - if (target.isValid) { - onFilterUpdate( - [...validFilters.filter((range) => !range.equals(target)), target].map((range) => - range.toISODate(), - ), - ); + const target = toISODateInterval(from, newTo); + if (target) { + onFilterUpdate([...validFilters.filter((range) => range !== target), target]); } } }; @@ -75,7 +78,7 @@ export const DateRangeFilter = ({ > DateTime.fromJSDate(date).toISODate()} dateParse={(str) => DateTime.fromISO(str).toJSDate()} onChange={onFromDateChange} @@ -86,12 +89,12 @@ export const DateRangeFilter = ({ appendTo={document.body} /> diff --git a/packages/common/src/components/FilterGroup/matchers.ts b/packages/common/src/components/FilterGroup/matchers.ts index 8e14c2d00..e160d7210 100644 --- a/packages/common/src/components/FilterGroup/matchers.ts +++ b/packages/common/src/components/FilterGroup/matchers.ts @@ -1,7 +1,6 @@ import jsonpath from 'jsonpath'; -import { DateTime, Interval } from 'luxon'; -import { areSameDayInUTCZero, ResourceField } from '../../utils'; +import { areSameDayInUTCZero, isInRange, ResourceField } from '../../utils'; import { DateFilter, DateRangeFilter, @@ -111,8 +110,7 @@ const dateMatcher = { const dateRangeMatcher = { filterType: 'dateRange', - matchValue: (value: string) => (filter: string) => - Interval.fromISO(filter).contains(DateTime.fromISO(value)), + matchValue: (value: string) => (filter: string) => isInRange(filter, value), }; const sliderMatcher = { diff --git a/packages/common/src/utils/dates.ts b/packages/common/src/utils/dates.ts index feb39e208..1f17d5838 100644 --- a/packages/common/src/utils/dates.ts +++ b/packages/common/src/utils/dates.ts @@ -1,4 +1,4 @@ -import { DateTime } from 'luxon'; +import { DateTime, Interval } from 'luxon'; /** * Converts a given ISO date time string to UTC+00:00 time zone. @@ -28,7 +28,7 @@ export const changeFormatToISODate = (isoDateString: string): string | undefined * @param date * @returns ISO date string if input is valid or undefined otherwise. */ -export const toISODate = (date: Date): string => { +export const toISODate = (date: Date): string | undefined => { const dt = DateTime.fromJSDate(date); return dt.isValid ? dt.toISODate() : undefined; }; @@ -40,7 +40,7 @@ export const isValidDate = (isoDateString: string) => DateTime.fromISO(isoDateSt * @param isoDateString * @returns JS Date instance if input is valid or undefined otherwise. */ -export const parseISOtoJSDate = (isoDateString: string) => { +export const parseISOtoJSDate = (isoDateString: string): Date | undefined => { const date = DateTime.fromISO(isoDateString); return date.isValid ? date.toJSDate() : undefined; }; @@ -56,3 +56,19 @@ export const areSameDayInUTCZero = (dateTime: string, calendarDate: string): boo // which results in shifting to previous day for zones with positive offsets return DateTime.fromISO(dateTime).toUTC().hasSame(DateTime.fromISO(calendarDate), 'day'); }; + +/** + * + * @param interval ISO time interval + * @param date ISO date time + * @returns true if the provided date is in the time interval + */ +export const isInRange = (interval: string, date: string): boolean => + Interval.fromISO(interval).contains(DateTime.fromISO(date)); + +export const isValidInterval = (interval: string): boolean => Interval.fromISO(interval).isValid; + +export const toISODateInterval = (from: Date, to: Date): string | undefined => { + const target = Interval.fromDateTimes(DateTime.fromJSDate(from), DateTime.fromJSDate(to)); + return target.isValid ? target.toISODate() : undefined; +};