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:
parent
f8c0a7ac69
commit
637b3165ca
@ -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;
|
@ -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>
|
||||
);
|
||||
};
|
@ -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>
|
||||
);
|
||||
};
|
@ -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>
|
||||
);
|
||||
};
|
@ -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` 设置时间格式
|
||||
|
@ -0,0 +1 @@
|
||||
export * from './DatePicker';
|
@ -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));
|
||||
}
|
||||
},
|
||||
};
|
||||
};
|
||||
};
|
@ -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';
|
||||
|
Loading…
Reference in New Issue
Block a user