From 2b588317afbffcff81a01507d2db9c64f8078c5a Mon Sep 17 00:00:00 2001 From: JeevaRamanathan M Date: Sat, 26 Oct 2024 14:26:26 +0000 Subject: [PATCH 1/4] draft: datepicker validation Signed-off-by: JeevaRamanathan M --- .../src/components/Taipy/DateSelector.tsx | 94 ++++++++++++++++--- taipy/gui/_renderers/factory.py | 1 + 2 files changed, 81 insertions(+), 14 deletions(-) diff --git a/frontend/taipy-gui/src/components/Taipy/DateSelector.tsx b/frontend/taipy-gui/src/components/Taipy/DateSelector.tsx index fe1d7b2660..9ff416fd96 100644 --- a/frontend/taipy-gui/src/components/Taipy/DateSelector.tsx +++ b/frontend/taipy-gui/src/components/Taipy/DateSelector.tsx @@ -28,11 +28,21 @@ import { ErrorBoundary } from "react-error-boundary"; import { createSendUpdateAction } from "../../context/taipyReducers"; import { getSuffixedClassNames, TaipyActiveProps, TaipyChangeProps, DateProps, getProps, getCssSize } from "./utils"; import { dateToString, getDateTime, getTimeZonedDate } from "../../utils"; -import { useClassNames, useDispatch, useDynamicProperty, useFormatConfig, useModule } from "../../utils/hooks"; +import { useClassNames, useDispatch, useDynamicProperty, useFormatConfig, useModule, useDynamicJsonProperty } from "../../utils/hooks"; import Field from "./Field"; import ErrorFallback from "../../utils/ErrorBoundary"; import { getComponentClassName } from "./TaipyStyle"; +interface DisableDateConfig { + disableWeekdays?: boolean; + disableWeekends?: boolean; + disablePastDays?: boolean; + disableFutureDays?: boolean; + dayOfWeek?: number; + interval?: number; + oddInterval?:boolean; + occurence?: number; +} interface DateSelectorProps extends TaipyActiveProps, TaipyChangeProps { withTime?: boolean; format?: string; @@ -46,7 +56,9 @@ interface DateSelectorProps extends TaipyActiveProps, TaipyChangeProps { editable?: boolean; label?: string; width?: string | number; - analogic? :boolean; + analogic?: boolean; + disableDateConfig?: string; + defaultDisableDateConfig?: string; } const boxSx = { display: "inline-block" }; @@ -74,6 +86,8 @@ const DateSelector = (props: DateSelectorProps) => { const hover = useDynamicProperty(props.hoverText, props.defaultHoverText, undefined); const min = useDynamicProperty(props.min, props.defaultMin, undefined); const max = useDynamicProperty(props.max, props.defaultMax, undefined); + const emptyDateConfig = {} as Partial; + const disableDateConfig = useDynamicJsonProperty(props.disableDateConfig, props.defaultDisableDateConfig || "", emptyDateConfig); const dateSx = useMemo(() => (props.width ? { maxWidth: getCssSize(props.width) } : undefined), [props.width]); @@ -115,6 +129,56 @@ const DateSelector = (props: DateSelectorProps) => { } }, [props.date, tz, withTime, max, min]); + + const getWeekNumberInMonth = (date: Date) => { + const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate())); + const firstDayOfMonth = new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), 1)); + d.setUTCDate(d.getUTCDate() + 4 - (d.getUTCDay() || 7)); + + const weekNo: number = Math.ceil(((d.getTime() - firstDayOfMonth.getTime()) / 86400000 + 1) / 7); + return weekNo; + } + const isDisabledDate = (date: Date) => { + if (disableDateConfig) { + if (disableDateConfig.disableWeekdays && (date.getDay() == 0 || date.getDay() == 6)) { + return true; + } + if (disableDateConfig.disableWeekdays && (date.getDay() != 0 || date.getDay() != 6)) { + return true; + } + if (disableDateConfig.disablePastDays && (date < new Date())) { + return true + } + if (disableDateConfig.disableFutureDays && (date > new Date())) { + return true; + } + + if (disableDateConfig.dayOfWeek) { + const isCorrectDay = date.getDay() === disableDateConfig.dayOfWeek; + const weekNumberInMonth = getWeekNumberInMonth(date); + const intervalCheck=disableDateConfig.oddInterval?1:0; + if (isCorrectDay && !disableDateConfig.interval && !disableDateConfig.occurence) { + return true; + } + if (isCorrectDay && disableDateConfig.interval) { + if (weekNumberInMonth % disableDateConfig.interval === intervalCheck) { + return true; + } + } + if (isCorrectDay && disableDateConfig.occurence) { + const dayOfMonth = new Date(date.getFullYear(), date.getMonth(), 1); + const dayDifference = (disableDateConfig.dayOfWeek - dayOfMonth.getDay() + 7) % 7; + const occurrenceDate = new Date(date.getFullYear(), date.getMonth(), 1 + dayDifference + (7 * (disableDateConfig.occurence-1))); + if(occurrenceDate.getDate()==date.getDate()){ + return true; + } + } + } + } + return false + + }; + return ( @@ -122,18 +186,19 @@ const DateSelector = (props: DateSelectorProps) => { {editable ? ( withTime ? ( )} - {...(endProps as DateTimePickerProps)} - value={value} - onChange={handleChange} - className={getSuffixedClassNames(className, "-picker")} - disabled={!active} - slotProps={textFieldProps} - label={props.label} - format={props.format} - sx={dateSx} - viewRenderers={ analogic ? analogicRenderers : undefined } - /> + {...(startProps as DateTimePickerProps)} + {...(endProps as DateTimePickerProps)} + value={value} + onChange={handleChange} + className={getSuffixedClassNames(className, "-picker")} + disabled={!active} + slotProps={textFieldProps} + label={props.label} + format={props.format} + sx={dateSx} + viewRenderers={analogic ? analogicRenderers : undefined} + shouldDisableDate={isDisabledDate} + /> ) : ( )} @@ -146,6 +211,7 @@ const DateSelector = (props: DateSelectorProps) => { label={props.label} format={props.format} sx={dateSx} + shouldDisableDate={isDisabledDate} /> ) ) : ( diff --git a/taipy/gui/_renderers/factory.py b/taipy/gui/_renderers/factory.py index a923f0c726..9bd0b08553 100644 --- a/taipy/gui/_renderers/factory.py +++ b/taipy/gui/_renderers/factory.py @@ -169,6 +169,7 @@ class _Factory: ("on_change", PropertyType.function), ("format",), ("width", PropertyType.string_or_number), + ("disable_date_config",PropertyType.dynamic_dict) ] ) ._set_propagate(), From edc53d4b23cea233f0462ac91834fc50c9ad1ab2 Mon Sep 17 00:00:00 2001 From: JeevaRamanathan M Date: Sat, 2 Nov 2024 17:09:16 +0000 Subject: [PATCH 2/4] fix spellings Signed-off-by: JeevaRamanathan M --- frontend/taipy-gui/src/components/Taipy/DateSelector.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/frontend/taipy-gui/src/components/Taipy/DateSelector.tsx b/frontend/taipy-gui/src/components/Taipy/DateSelector.tsx index 9ff416fd96..7ca4a907bf 100644 --- a/frontend/taipy-gui/src/components/Taipy/DateSelector.tsx +++ b/frontend/taipy-gui/src/components/Taipy/DateSelector.tsx @@ -41,7 +41,7 @@ interface DisableDateConfig { dayOfWeek?: number; interval?: number; oddInterval?:boolean; - occurence?: number; + occurrence?: number; } interface DateSelectorProps extends TaipyActiveProps, TaipyChangeProps { withTime?: boolean; @@ -157,7 +157,7 @@ const DateSelector = (props: DateSelectorProps) => { const isCorrectDay = date.getDay() === disableDateConfig.dayOfWeek; const weekNumberInMonth = getWeekNumberInMonth(date); const intervalCheck=disableDateConfig.oddInterval?1:0; - if (isCorrectDay && !disableDateConfig.interval && !disableDateConfig.occurence) { + if (isCorrectDay && !disableDateConfig.interval && !disableDateConfig.occurrence) { return true; } if (isCorrectDay && disableDateConfig.interval) { @@ -165,10 +165,10 @@ const DateSelector = (props: DateSelectorProps) => { return true; } } - if (isCorrectDay && disableDateConfig.occurence) { + if (isCorrectDay && disableDateConfig.occurrence) { const dayOfMonth = new Date(date.getFullYear(), date.getMonth(), 1); const dayDifference = (disableDateConfig.dayOfWeek - dayOfMonth.getDay() + 7) % 7; - const occurrenceDate = new Date(date.getFullYear(), date.getMonth(), 1 + dayDifference + (7 * (disableDateConfig.occurence-1))); + const occurrenceDate = new Date(date.getFullYear(), date.getMonth(), 1 + dayDifference + (7 * (disableDateConfig.occurrence-1))); if(occurrenceDate.getDate()==date.getDate()){ return true; } From 77105c142f05998e7ced887ad645d7b21e93a636 Mon Sep 17 00:00:00 2001 From: JeevaRamanathan M Date: Sat, 9 Nov 2024 16:03:13 +0000 Subject: [PATCH 3/4] changed dynamic_dict to dict Signed-off-by: JeevaRamanathan M --- taipy/gui/_renderers/factory.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/taipy/gui/_renderers/factory.py b/taipy/gui/_renderers/factory.py index bde2e34961..e9c395e9f5 100644 --- a/taipy/gui/_renderers/factory.py +++ b/taipy/gui/_renderers/factory.py @@ -169,7 +169,7 @@ class _Factory: ("on_change", PropertyType.function), ("format",), ("width", PropertyType.string_or_number), - ("disable_date_config",PropertyType.dynamic_dict) + ("disable_date_config",PropertyType.dict) ] ) ._set_propagate(), From d7ae3bb92fd7cd9951a9d6fa0186fb2d8431af90 Mon Sep 17 00:00:00 2001 From: JeevaRamanathan M Date: Sun, 10 Nov 2024 05:24:06 +0000 Subject: [PATCH 4/4] rerun pipeline Signed-off-by: JeevaRamanathan M