feat: add DatePicker into schema components (#161)

* feat: add DatePicker into schema components

* improve code

Co-authored-by: chenos <chenlinxh@gmail.com>
This commit is contained in:
SemmyWong 2022-01-18 09:21:55 +08:00 committed by GitHub
parent f8c0a7ac69
commit 637b3165ca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 221 additions and 0 deletions

View File

@ -0,0 +1,27 @@
import React from 'react';
import { DatePicker as AntdDatePicker } from 'antd';
import type {
DatePickerProps as AntdDatePickerProps,
RangePickerProps as AntdRangePickerProps,
} from 'antd/lib/date-picker';
import { connect, mapProps, mapReadPretty } from '@formily/react';
import { ReadPretty } from './ReadPretty';
import { mapDateFormat } from './util';
type ComposedDatePicker = React.FC<AntdDatePickerProps> & {
RangePicker?: React.FC<AntdRangePickerProps>;
};
export const DatePicker: ComposedDatePicker = connect(
AntdDatePicker,
mapProps(mapDateFormat()),
mapReadPretty(ReadPretty.DatePicker),
);
DatePicker.RangePicker = connect(
AntdDatePicker.RangePicker,
mapProps(mapDateFormat()),
mapReadPretty(ReadPretty.DateRangePicker),
);
export default DatePicker;

View File

@ -0,0 +1,43 @@
import { formatMomentValue, usePrefixCls } from '@formily/antd/esm/__builtins__';
import { isArr } from '@formily/shared';
import type {
DatePickerProps as AntdDatePickerProps,
RangePickerProps as AntdRangePickerProps,
} from 'antd/lib/date-picker';
import cls from 'classnames';
import moment from 'moment';
import React from 'react';
import { getDefaultFormat } from './util';
type Composed = {
DatePicker: React.FC<AntdDatePickerProps>;
DateRangePicker: React.FC<AntdRangePickerProps>;
};
export const ReadPretty: Composed = () => null;
ReadPretty.DatePicker = (props: any) => {
if (!props.value) {
return <div></div>;
}
const prefixCls = usePrefixCls('description-date-picker', props);
const getLabels = () => {
const d = moment(props.value);
const labels = formatMomentValue(d.isValid() ? d : null, getDefaultFormat(props), props.placeholder);
return isArr(labels) ? labels.join('~') : labels;
};
return <div className={cls(prefixCls, props.className)}>{getLabels()}</div>;
};
ReadPretty.DateRangePicker = (props: any) => {
const prefixCls = usePrefixCls('description-text', props);
const getLabels = () => {
const labels = formatMomentValue(props.value, props.format, props.placeholder);
return isArr(labels) ? labels.join('~') : labels;
};
return (
<div className={cls(prefixCls, props.className)} style={props.style}>
{getLabels()}
</div>
);
};

View File

@ -0,0 +1,49 @@
/**
* title: DatePicker
*/
import { FormItem } from '@formily/antd';
import { DatePicker, 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,
},
'x-reactions': {
target: 'read',
fulfill: {
state: {
value: '{{$self.value}}',
},
},
},
},
read: {
type: 'boolean',
title: `Read pretty`,
'x-read-pretty': true,
'x-decorator': 'FormItem',
'x-component': 'DatePicker',
'x-component-props': {
dateFormat: 'YYYY/MM/DD',
// showTime: true,
},
},
},
};
export default () => {
return (
<SchemaComponentProvider components={{ DatePicker, FormItem }}>
<SchemaComponent schema={schema} />
</SchemaComponentProvider>
);
};

View File

@ -0,0 +1,41 @@
/**
* title: DatePicker.RangePicker
*/
import { FormItem } from '@formily/antd';
import { DatePicker, 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.RangePicker',
'x-reactions': {
target: 'read',
fulfill: {
state: {
value: '{{$self.value}}',
},
},
},
},
read: {
type: 'boolean',
title: `Read pretty`,
'x-read-pretty': true,
'x-decorator': 'FormItem',
'x-component': 'DatePicker.RangePicker',
},
},
};
export default () => {
return (
<SchemaComponentProvider components={{ DatePicker, FormItem }}>
<SchemaComponent schema={schema} />
</SchemaComponentProvider>
);
};

View File

@ -6,3 +6,20 @@ group:
---
# DatePicker
## Examples
### DatePicker
<code src="./demos/demo1.tsx" />
### RangePicker
<code src="./demos/demo2.tsx" />
## API
基于 antd 的 [DatePicker](https://ant.design/components/date-picker/#API),新增了以下扩展属性,用于支持 NocoBase 的日期字段设置。
- `dateFormat` 设置日期格式
- `timeFormat` 设置时间格式

View File

@ -0,0 +1 @@
export * from './DatePicker';

View File

@ -0,0 +1,42 @@
import type { DatePickerProps } from 'antd/lib/date-picker';
import { formatMomentValue, momentable } from '@formily/antd/esm/__builtins__';
export const getDefaultFormat = (props: DatePickerProps & { dateFormat: string; timeFormat: string }) => {
if (props.format) {
return props.format;
}
if (props.dateFormat) {
if (props['showTime']) {
return `${props.dateFormat} ${props.timeFormat || 'HH:mm:ss'}`;
}
return props.dateFormat;
}
if (props['picker'] === 'month') {
return 'YYYY-MM';
} else if (props['picker'] === 'quarter') {
return 'YYYY-\\QQ';
} else if (props['picker'] === 'year') {
return 'YYYY';
} else if (props['picker'] === 'week') {
return 'YYYY-wo';
}
return props['showTime'] ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD';
};
export const mapDateFormat = function () {
return (props: any) => {
const format = getDefaultFormat(props) as any;
const onChange = props.onChange;
return {
...props,
format: format,
value: momentable(props.value, format === 'YYYY-wo' ? 'YYYY-w' : format),
onChange: (value: moment.Moment | moment.Moment[]) => {
if (onChange) {
onChange(formatMomentValue(value, format));
}
},
};
};
};

View File

@ -2,6 +2,7 @@ export * from './action';
export * from './block-item';
export * from './checkbox';
export * from './color-select';
export * from './date-picker';
export * from './dnd-context';
export * from './form';
export * from './form-item';