From 7a9bab9bab07371763624f30aa20993a8b18e2be Mon Sep 17 00:00:00 2001 From: chenos Date: Thu, 16 Jun 2022 16:38:12 +0800 Subject: [PATCH] fix: datepicker with timezone --- .../antd/date-picker/demos/demo1.tsx | 20 +++-- .../antd/date-picker/demos/demo3.tsx | 59 ++++++++++++++ .../antd/date-picker/index.md | 4 + .../schema-component/antd/date-picker/util.ts | 77 ++++++++++++++++++- 4 files changed, 152 insertions(+), 8 deletions(-) create mode 100644 packages/core/client/src/schema-component/antd/date-picker/demos/demo3.tsx diff --git a/packages/core/client/src/schema-component/antd/date-picker/demos/demo1.tsx b/packages/core/client/src/schema-component/antd/date-picker/demos/demo1.tsx index 7bc5049e9..d8dd7a6d3 100644 --- a/packages/core/client/src/schema-component/antd/date-picker/demos/demo1.tsx +++ b/packages/core/client/src/schema-component/antd/date-picker/demos/demo1.tsx @@ -2,7 +2,7 @@ * title: DatePicker */ import { FormItem } from '@formily/antd'; -import { DatePicker, SchemaComponent, SchemaComponentProvider } from '@nocobase/client'; +import { DatePicker, Input, SchemaComponent, SchemaComponentProvider } from '@nocobase/client'; import React from 'react'; const schema = { @@ -15,10 +15,10 @@ const schema = { 'x-component': 'DatePicker', 'x-component-props': { dateFormat: 'YYYY/MM/DD', - // showTime: true, + showTime: true, }, 'x-reactions': { - target: 'read', + target: '*(read1,read2)', fulfill: { state: { value: '{{$self.value}}', @@ -26,7 +26,7 @@ const schema = { }, }, }, - read: { + read1: { type: 'boolean', title: `Read pretty`, 'x-read-pretty': true, @@ -34,15 +34,23 @@ const schema = { 'x-component': 'DatePicker', 'x-component-props': { dateFormat: 'YYYY/MM/DD', - // showTime: true, + showTime: true, }, }, + read2: { + type: 'string', + title: `Value`, + 'x-read-pretty': true, + 'x-decorator': 'FormItem', + 'x-component': 'Input', + 'x-component-props': {}, + }, }, }; export default () => { return ( - + ); diff --git a/packages/core/client/src/schema-component/antd/date-picker/demos/demo3.tsx b/packages/core/client/src/schema-component/antd/date-picker/demos/demo3.tsx new file mode 100644 index 000000000..48d7fe76c --- /dev/null +++ b/packages/core/client/src/schema-component/antd/date-picker/demos/demo3.tsx @@ -0,0 +1,59 @@ +/** + * title: DatePicker (with timezone) + */ +import { FormItem } from '@formily/antd'; +import { DatePicker, Input, SchemaComponent, SchemaComponentProvider } from '@nocobase/client'; +import React from 'react'; + +const schema = { + type: 'object', + properties: { + input: { + type: 'boolean', + title: `Editable`, + 'x-decorator': 'FormItem', + 'x-component': 'DatePicker', + 'x-component-props': { + dateFormat: 'YYYY/MM/DD', + showTime: true, + withTz: true, + }, + default: '2022-06-04T15:00:00.000Z', + 'x-reactions': { + target: '*(read1,read2)', + fulfill: { + state: { + value: '{{$self.value}}', + }, + }, + }, + }, + read1: { + type: 'string', + title: `Read pretty`, + 'x-read-pretty': true, + 'x-decorator': 'FormItem', + 'x-component': 'DatePicker', + 'x-component-props': { + dateFormat: 'YYYY/MM/DD', + // showTime: true, + }, + }, + read2: { + type: 'string', + title: `Value`, + 'x-read-pretty': true, + 'x-decorator': 'FormItem', + 'x-component': 'Input', + 'x-component-props': {}, + }, + }, +}; + +export default () => { + return ( + + + + ); +}; diff --git a/packages/core/client/src/schema-component/antd/date-picker/index.md b/packages/core/client/src/schema-component/antd/date-picker/index.md index 9b55b9249..b62b8ced8 100644 --- a/packages/core/client/src/schema-component/antd/date-picker/index.md +++ b/packages/core/client/src/schema-component/antd/date-picker/index.md @@ -13,6 +13,10 @@ group: +### DatePicker (with timezone) + + + ### RangePicker diff --git a/packages/core/client/src/schema-component/antd/date-picker/util.ts b/packages/core/client/src/schema-component/antd/date-picker/util.ts index 12bc5ac77..17f468bce 100644 --- a/packages/core/client/src/schema-component/antd/date-picker/util.ts +++ b/packages/core/client/src/schema-component/antd/date-picker/util.ts @@ -1,4 +1,4 @@ -import { formatMomentValue } from '@formily/antd/lib/__builtins__'; +import { isArr, isEmpty, isFn } from '@formily/shared'; import type { DatePickerProps } from 'antd/lib/date-picker'; import moment from 'moment'; @@ -24,6 +24,70 @@ export const getDefaultFormat = (props: DatePickerProps & { dateFormat: string; return props['showTime'] ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD'; }; +const toMoment = (val, format) => { + if (moment.isMoment(val)) { + return val; + } + if (typeof val === 'string' && val.includes('T')) { + return moment(val); + } + return moment(val, format); +}; + +export const momentable = (value: any, format?: string) => { + return Array.isArray(value) + ? value.map((val) => { + return toMoment(val, format); + }) + : value + ? toMoment(value, format) + : value; +}; + +export const formatMomentValue = (value: any, format: any, placeholder?: string): string | string[] => { + const formatDate = (date: any, format: any, i = 0) => { + if (!date) return placeholder; + if (isArr(format)) { + const _format = format[i]; + if (isFn(_format)) { + return _format(date); + } + if (isEmpty(_format)) { + return date; + } + return moment(date).format(_format); + } else { + if (isFn(format)) { + return format(date); + } + if (isEmpty(format)) { + return date; + } + return moment(date).format(format); + } + }; + if (isArr(value)) { + return value.map((val, index) => { + return formatDate(val, format, index); + }); + } else { + return value ? formatDate(value, format) : value || placeholder; + } +}; + + +const momentToString = (value: moment.Moment | moment.Moment[]) => { + if (!value) { + return value; + } + if (Array.isArray(value)) { + return value.map(val => val.toISOString()); + } + if (moment.isMoment(value)) { + return value.toISOString(); + } +} + export const mapDateFormat = function () { return (props: any) => { const format = getDefaultFormat(props) as any; @@ -31,7 +95,16 @@ export const mapDateFormat = function () { return { ...props, format: format, - value: props.value && moment(props.value).isValid() ? moment(props.value) : undefined, + value: momentable(props.value, format === 'YYYY-wo' ? 'YYYY-w' : format), + onChange: (value: moment.Moment | moment.Moment[]) => { + if (onChange) { + if (props.withTz) { + onChange(momentToString(value)); + } else { + onChange(formatMomentValue(value, format)); + } + } + }, }; }; };