From 93d76ce8a263d6edcdce6713ee4351b1a55663cd Mon Sep 17 00:00:00 2001 From: Jordan Lawrence Date: Thu, 30 Jan 2025 14:07:46 +0000 Subject: [PATCH] fix: resolving dateTime picker bugs with content releases (#8455) --- .../inputs/DateInputs/DatePicker.tsx | 1 + .../inputs/DateInputs/DateTimeInput.tsx | 32 +++++- .../inputs/DateInputs/calendar/Calendar.tsx | 5 + .../DateInputs/calendar/CalendarDay.tsx | 5 +- .../DateInputs/calendar/CalendarMonth.tsx | 2 + .../sanity/src/core/i18n/bundles/studio.ts | 10 +- .../components/ScheduleDatePicker.tsx | 72 +++++++++++++ .../components/dialog/CreateReleaseDialog.tsx | 49 +++++++-- .../components/dialog/ReleaseForm.tsx | 80 +++++++------- .../__tests__/CreateReleaseDialog.test.tsx | 7 ++ .../dialog/CopyToNewReleaseDialog.tsx | 46 ++++++-- .../src/core/releases/i18n/resources.ts | 3 + .../ReleaseScheduleButton.tsx | 54 ++++++++-- .../tool/detail/ReleaseTypePicker.tsx | 100 +++++++++++------- .../__tests__/ReleaseTypePicker.test.tsx | 12 ++- .../releases/util/getIsScheduledDateInPast.ts | 11 ++ 16 files changed, 374 insertions(+), 115 deletions(-) create mode 100644 packages/sanity/src/core/releases/components/ScheduleDatePicker.tsx create mode 100644 packages/sanity/src/core/releases/util/getIsScheduledDateInPast.ts diff --git a/packages/sanity/src/core/components/inputs/DateInputs/DatePicker.tsx b/packages/sanity/src/core/components/inputs/DateInputs/DatePicker.tsx index 2d65a13bc12..cbdef111aa7 100644 --- a/packages/sanity/src/core/components/inputs/DateInputs/DatePicker.tsx +++ b/packages/sanity/src/core/components/inputs/DateInputs/DatePicker.tsx @@ -13,6 +13,7 @@ export const DatePicker = forwardRef(function DatePicker( monthPickerVariant?: CalendarProps['monthPickerVariant'] padding?: number showTimezone?: boolean + isPastDisabled?: boolean }, ref: ForwardedRef, ) { diff --git a/packages/sanity/src/core/components/inputs/DateInputs/DateTimeInput.tsx b/packages/sanity/src/core/components/inputs/DateInputs/DateTimeInput.tsx index a89e6c66702..7d3a40f2ecc 100644 --- a/packages/sanity/src/core/components/inputs/DateInputs/DateTimeInput.tsx +++ b/packages/sanity/src/core/components/inputs/DateInputs/DateTimeInput.tsx @@ -1,12 +1,15 @@ import {CalendarIcon} from '@sanity/icons' -import {Box, Flex, LayerProvider, useClickOutsideEvent} from '@sanity/ui' +import {Box, Card, Flex, LayerProvider, Text, useClickOutsideEvent} from '@sanity/ui' +import {isPast} from 'date-fns' import { type FocusEvent, type ForwardedRef, forwardRef, type KeyboardEvent, useCallback, + useEffect, useImperativeHandle, + useMemo, useRef, useState, } from 'react' @@ -14,6 +17,7 @@ import FocusLock from 'react-focus-lock' import {Button} from '../../../../ui-components/button/Button' import {Popover} from '../../../../ui-components/popover/Popover' +import {useTranslation} from '../../../i18n' import {type CalendarProps} from './calendar/Calendar' import {type CalendarLabels} from './calendar/types' import {DatePicker} from './DatePicker' @@ -35,6 +39,7 @@ export interface DateTimeInputProps { monthPickerVariant?: CalendarProps['monthPickerVariant'] padding?: number disableInput?: boolean + isPastDisabled?: boolean } export const DateTimeInput = forwardRef(function DateTimeInput( @@ -53,17 +58,28 @@ export const DateTimeInput = forwardRef(function DateTimeInput( constrainSize = true, monthPickerVariant, padding, + disableInput, + isPastDisabled, ...rest } = props + const {t} = useTranslation() const popoverRef = useRef(null) const ref = useRef(null) const buttonRef = useRef(null) + const [referenceElement, setReferenceElement] = useState(null) + useImperativeHandle( forwardedRef, () => ref.current, ) + /** + * Setting referenceElement in effect makes sure it's up to date after the initial render + * cycle - avoiding referenceElement used byPopover from being out of sync with render state + */ + useEffect(() => setReferenceElement(ref.current), []) + const [isPickerOpen, setPickerOpen] = useState(false) useClickOutsideEvent( @@ -84,6 +100,11 @@ export const DateTimeInput = forwardRef(function DateTimeInput( const handleClick = useCallback(() => setPickerOpen(true), []) + const isDateInPastWarningShown = useMemo( + () => inputValue && isPastDisabled && isPast(new Date(inputValue)), + [inputValue, isPastDisabled], + ) + const suffix = readOnly ? null : (