From 5100fd35dc796c5862ef9fd7261abdcba925b020 Mon Sep 17 00:00:00 2001 From: Jarrod Flesch Date: Tue, 29 Dec 2020 12:41:15 -0500 Subject: [PATCH] fix: updates typing on DatePicker component and joi schema --- demo/collections/AllFields.ts | 31 +++++++++++ .../elements/DatePicker/DatePicker.tsx | 29 +++++------ .../components/elements/DatePicker/index.scss | 2 +- .../components/elements/DatePicker/types.ts | 51 ++++++++++++------- .../forms/field-types/DateTime/index.tsx | 10 ++-- src/fields/config/schema.ts | 16 +++++- src/fields/config/types.ts | 5 ++ 7 files changed, 106 insertions(+), 38 deletions(-) diff --git a/demo/collections/AllFields.ts b/demo/collections/AllFields.ts index 31acdbcd54..a946fb451c 100644 --- a/demo/collections/AllFields.ts +++ b/demo/collections/AllFields.ts @@ -85,6 +85,37 @@ const AllFields: PayloadCollectionConfig = { required: true, hasMany: true, }, + { + name: 'dateFieldExample', + label: 'Day and Time', + type: 'date', + admin: { + date: { + timeIntervals: 30, + }, + }, + }, + { + name: 'dayOnlyDateFieldExample', + label: 'Day Only', + type: 'date', + admin: { + date: { + pickerAppearance: 'dayOnly', + monthsToShow: 2, + }, + }, + }, + { + name: 'timeOnlyDateFieldExample', + label: 'Time Only', + type: 'date', + admin: { + date: { + pickerAppearance: 'timeOnly', + }, + }, + }, { name: 'radioGroupExample', label: 'Radio Group Example', diff --git a/src/admin/components/elements/DatePicker/DatePicker.tsx b/src/admin/components/elements/DatePicker/DatePicker.tsx index 798f622a68..64701431ec 100644 --- a/src/admin/components/elements/DatePicker/DatePicker.tsx +++ b/src/admin/components/elements/DatePicker/DatePicker.tsx @@ -10,29 +10,26 @@ const baseClass = 'date-time-picker'; const DateTime: React.FC = (props) => { const { - inputDateTimeFormat, - useDate = true, + value, + onChange, + displayFormat, + pickerAppearance = 'dayAndTime', minDate, maxDate, - monthsShown = 1, - useTime = true, + monthsToShow = 1, minTime, maxTime, timeIntervals = 30, timeFormat = 'h:mm aa', + readOnly, placeholder: placeholderText, - value, - onChange, - admin: { - readOnly, - } = {}, } = props; - let dateTimeFormat = inputDateTimeFormat; + let dateTimeFormat = displayFormat; - if (!dateTimeFormat) { - if (useTime && useDate) dateTimeFormat = 'MMM d, yyy h:mm a'; - else if (useTime) dateTimeFormat = 'h:mm a'; + if (dateTimeFormat === undefined) { + if (pickerAppearance === 'dayAndTime') dateTimeFormat = 'MMM d, yyy h:mm a'; + else if (pickerAppearance === 'timeOnly') dateTimeFormat = 'h:mm a'; else dateTimeFormat = 'MMM d, yyy'; } @@ -40,8 +37,8 @@ const DateTime: React.FC = (props) => { minDate, maxDate, dateFormat: dateTimeFormat, - monthsShown: Math.min(2, monthsShown), - showTimeSelect: useTime, + monthsShown: Math.min(2, monthsToShow), + showTimeSelect: pickerAppearance === 'dayAndTime' || pickerAppearance === 'timeOnly', minTime, maxTime, timeIntervals, @@ -56,7 +53,7 @@ const DateTime: React.FC = (props) => { const classes = [ baseClass, - !useDate && `${baseClass}--hide-dates`, + `${baseClass}__appearance--${pickerAppearance}`, ].filter(Boolean).join(' '); return ( diff --git a/src/admin/components/elements/DatePicker/index.scss b/src/admin/components/elements/DatePicker/index.scss index 871b26d88a..b1b364a5dc 100644 --- a/src/admin/components/elements/DatePicker/index.scss +++ b/src/admin/components/elements/DatePicker/index.scss @@ -8,7 +8,7 @@ $cal-icon-width: 18px; width: 120px; } - &--hide-dates { + &__appearance--timeOnly { .react-datepicker { width: 100%; diff --git a/src/admin/components/elements/DatePicker/types.ts b/src/admin/components/elements/DatePicker/types.ts index 823b4f0ecb..c7ba02d0f0 100644 --- a/src/admin/components/elements/DatePicker/types.ts +++ b/src/admin/components/elements/DatePicker/types.ts @@ -1,18 +1,35 @@ -export type Props = { - placeholder?: string, - useDate?: boolean, - minDate?: Date, - maxDate?: Date, - monthsShown?: number, - inputDateTimeFormat?: string, - useTime?: boolean, - minTime?: Date, - maxTime?: Date, - timeIntervals?: number, - timeFormat?: string, - value?: Date, - onChange?: (val: Date) => void, - admin?: { - readOnly?: boolean, - } +type SharedProps = { + displayFormat?: string | undefined + pickerAppearance?: 'dayAndTime' | 'timeOnly' | 'dayOnly' +} + +type TimePickerProps = { + minTime?: Date + maxTime?: Date + timeIntervals?: number + timeFormat?: string +} + +type DayPickerProps = { + monthsToShow?: 1 | 2 + minDate?: Date + maxDate?: Date +} + +export type ConditionalDateProps = + | SharedProps & DayPickerProps & TimePickerProps & { + pickerAppearance?: 'dayAndTime' + } + | SharedProps & TimePickerProps & { + pickerAppearance: 'timeOnly' + } + | SharedProps & DayPickerProps & { + pickerAppearance: 'dayOnly' + } + +export type Props = SharedProps & DayPickerProps & TimePickerProps & { + value?: Date + onChange?: (val: Date) => void + readOnly?: boolean + placeholder?: string } diff --git a/src/admin/components/forms/field-types/DateTime/index.tsx b/src/admin/components/forms/field-types/DateTime/index.tsx index ddf510f230..49fb0861b5 100644 --- a/src/admin/components/forms/field-types/DateTime/index.tsx +++ b/src/admin/components/forms/field-types/DateTime/index.tsx @@ -5,7 +5,7 @@ import withCondition from '../../withCondition'; import useFieldType from '../../useFieldType'; import Label from '../../Label'; import Error from '../../Error'; -import { date } from '../../../../../fields/validations'; +import { date as dateValidation } from '../../../../../fields/validations'; import { Props } from './types'; import './index.scss'; @@ -17,12 +17,14 @@ const DateTime: React.FC = (props) => { path: pathFromProps, name, required, - validate = date, + validate = dateValidation, label, admin: { + placeholder, readOnly, style, width, + date, } = {}, } = props; @@ -69,7 +71,9 @@ const DateTime: React.FC = (props) => { />
diff --git a/src/fields/config/schema.ts b/src/fields/config/schema.ts index 777e303f8d..4044b2354c 100644 --- a/src/fields/config/schema.ts +++ b/src/fields/config/schema.ts @@ -225,7 +225,21 @@ export const date = baseField.keys({ type: joi.string().valid('date').required(), name: joi.string().required(), defaultValue: joi.string(), -}).unknown(true); // remove when we better specify options allowed to pass to React Datepicker + admin: baseAdminFields.keys({ + date: joi.object({ + displayFormat: joi.string(), + pickerAppearance: joi.string(), + minDate: joi.date(), + maxDate: joi.date(), + minTime: joi.date(), + maxTime: joi.date(), + timeIntervals: joi.number(), + timeFormat: joi.string(), + monthsToShow: joi.number(), + + }), + }), +}); const fieldSchema = joi.alternatives() .try( diff --git a/src/fields/config/types.ts b/src/fields/config/types.ts index ab73367321..e3cf5e8af5 100644 --- a/src/fields/config/types.ts +++ b/src/fields/config/types.ts @@ -4,6 +4,7 @@ import { Editor } from 'slate'; import { PayloadRequest } from '../../express/types'; import { Access } from '../../config/types'; import { Document } from '../../types'; +import { ConditionalDateProps } from '../../admin/components/elements/DatePicker/types'; export type FieldHook = (args: { value?: unknown, @@ -112,6 +113,10 @@ export type CheckboxField = FieldBase & { export type DateField = FieldBase & { type: 'date'; + admin?: Admin & { + placeholder?: string + date?: ConditionalDateProps + } } export type GroupField = FieldBase & {