feat: remove copied date-picker component, add schema-settings date presets
This commit is contained in:
parent
d675e2815c
commit
7d508d0fc4
@ -1,12 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {
|
import { Menu, Plugin, RemoteSchemaTemplateManagerProvider, EditTitleField, useCollection } from '@nocobase/client';
|
||||||
Menu,
|
|
||||||
Plugin,
|
|
||||||
RemoteSchemaTemplateManagerProvider,
|
|
||||||
EditTitleField,
|
|
||||||
useCollection,
|
|
||||||
SchemaSettingsDateFormat,
|
|
||||||
} from '@nocobase/client';
|
|
||||||
import { remove } from 'lodash';
|
import { remove } from 'lodash';
|
||||||
import { useFieldSchema } from '@formily/react';
|
import { useFieldSchema } from '@formily/react';
|
||||||
import { isValid } from '@formily/shared';
|
import { isValid } from '@formily/shared';
|
||||||
@ -49,7 +42,7 @@ import {
|
|||||||
Expression,
|
Expression,
|
||||||
SignatureInput,
|
SignatureInput,
|
||||||
} from './components';
|
} from './components';
|
||||||
import { AutoComplete, DatePicker, InternalPDFViewer, MenuDesigner } from './schema-components';
|
import { AutoComplete, InternalPDFViewer, MenuDesigner } from './schema-components';
|
||||||
import {
|
import {
|
||||||
CreateSubmitActionInitializer,
|
CreateSubmitActionInitializer,
|
||||||
FilterFormItem,
|
FilterFormItem,
|
||||||
@ -73,6 +66,11 @@ import {
|
|||||||
} from './schema-initializer/blocks/SheetBlockInitializer';
|
} from './schema-initializer/blocks/SheetBlockInitializer';
|
||||||
import AssociationCascader from './schema-components/association-cascader/AssociationCascader';
|
import AssociationCascader from './schema-components/association-cascader/AssociationCascader';
|
||||||
import { SchemaSettingsDatePickerType } from './schema-settings/SchemaSettingsDatePickerType';
|
import { SchemaSettingsDatePickerType } from './schema-settings/SchemaSettingsDatePickerType';
|
||||||
|
import {
|
||||||
|
SchemaSettingsDatePresets,
|
||||||
|
useCustomPresets,
|
||||||
|
useCustomPresets1,
|
||||||
|
} from './schema-settings/SchemaSettingsDatePresets';
|
||||||
export { usePDFViewerRef } from './schema-initializer';
|
export { usePDFViewerRef } from './schema-initializer';
|
||||||
export * from './components/custom-components/custom-components';
|
export * from './components/custom-components/custom-components';
|
||||||
|
|
||||||
@ -100,6 +98,9 @@ export class PluginCoreClient extends Plugin {
|
|||||||
this.schemaSettingsManager.addItem('fieldSettings:component:DatePicker', 'datePickerType', {
|
this.schemaSettingsManager.addItem('fieldSettings:component:DatePicker', 'datePickerType', {
|
||||||
Component: SchemaSettingsDatePickerType,
|
Component: SchemaSettingsDatePickerType,
|
||||||
});
|
});
|
||||||
|
this.schemaSettingsManager.addItem('fieldSettings:component:DatePicker', 'datePresets', {
|
||||||
|
Component: SchemaSettingsDatePresets,
|
||||||
|
});
|
||||||
|
|
||||||
this.schemaSettingsManager.addItem('FormItemSettings', 'hera-divider', {
|
this.schemaSettingsManager.addItem('FormItemSettings', 'hera-divider', {
|
||||||
type: 'divider',
|
type: 'divider',
|
||||||
@ -153,6 +154,8 @@ export class PluginCoreClient extends Plugin {
|
|||||||
useGetCustomAssociatedComponents,
|
useGetCustomAssociatedComponents,
|
||||||
useGetCustomComponents,
|
useGetCustomComponents,
|
||||||
usePDFViewerPrintActionProps,
|
usePDFViewerPrintActionProps,
|
||||||
|
useCustomPresets1,
|
||||||
|
useCustomPresets,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.app.addComponents({
|
this.app.addComponents({
|
||||||
@ -166,7 +169,6 @@ export class PluginCoreClient extends Plugin {
|
|||||||
CustomComponentDispatcher,
|
CustomComponentDispatcher,
|
||||||
CustomComponentStub,
|
CustomComponentStub,
|
||||||
CustomField,
|
CustomField,
|
||||||
DatePicker,
|
|
||||||
EditTitle,
|
EditTitle,
|
||||||
EditTitleField,
|
EditTitleField,
|
||||||
Expression,
|
Expression,
|
||||||
|
@ -1,64 +0,0 @@
|
|||||||
import { connect, mapProps, mapReadPretty } from '@formily/react';
|
|
||||||
import { DatePicker as AntdDatePicker } from 'antd';
|
|
||||||
import type {
|
|
||||||
DatePickerProps as AntdDatePickerProps,
|
|
||||||
RangePickerProps as AntdRangePickerProps,
|
|
||||||
} from 'antd/es/date-picker';
|
|
||||||
import React from 'react';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import { ReadPretty } from './ReadPretty';
|
|
||||||
import { getDateRanges, mapDatePicker, mapRangePicker } from './util';
|
|
||||||
import dayjs from 'dayjs';
|
|
||||||
|
|
||||||
interface IDatePickerProps {
|
|
||||||
utc?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
type ComposedDatePicker = React.FC<AntdDatePickerProps> & {
|
|
||||||
ReadPretty?: React.FC<AntdDatePickerProps>;
|
|
||||||
RangePicker?: React.FC<AntdRangePickerProps>;
|
|
||||||
};
|
|
||||||
|
|
||||||
const DatePickerContext = React.createContext<IDatePickerProps>({ utc: true });
|
|
||||||
|
|
||||||
export const useDatePickerContext = () => React.useContext(DatePickerContext);
|
|
||||||
export const DatePickerProvider = DatePickerContext.Provider;
|
|
||||||
|
|
||||||
const InternalDatePicker: ComposedDatePicker = connect(
|
|
||||||
AntdDatePicker,
|
|
||||||
mapProps(mapDatePicker()),
|
|
||||||
mapReadPretty(ReadPretty.DatePicker),
|
|
||||||
);
|
|
||||||
|
|
||||||
const InternalRangePicker = connect(
|
|
||||||
AntdDatePicker.RangePicker,
|
|
||||||
mapProps(mapRangePicker()),
|
|
||||||
mapReadPretty(ReadPretty.DateRangePicker),
|
|
||||||
);
|
|
||||||
|
|
||||||
export const DatePicker = (props) => {
|
|
||||||
const { utc = true } = useDatePickerContext();
|
|
||||||
const value = Array.isArray(props.value) ? props.value[0] : props.value;
|
|
||||||
props = { utc, ...props };
|
|
||||||
return <InternalDatePicker {...props} value={value} />;
|
|
||||||
};
|
|
||||||
|
|
||||||
DatePicker.ReadPretty = ReadPretty.DatePicker;
|
|
||||||
|
|
||||||
DatePicker.RangePicker = function RangePicker(props) {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const { utc = true } = useDatePickerContext();
|
|
||||||
const rangesValue = getDateRanges();
|
|
||||||
const presets = [
|
|
||||||
{ label: t('This year'), value: rangesValue.thisYear },
|
|
||||||
...Array(5)
|
|
||||||
.fill(0)
|
|
||||||
.map((_, i) => ({ label: dayjs().year() - i - 1 + '年', value: rangesValue.year(dayjs().year() - i - 1) })),
|
|
||||||
{ label: t('This month'), value: rangesValue.thisMonth },
|
|
||||||
{ label: t('Last month'), value: rangesValue.lastMonth },
|
|
||||||
];
|
|
||||||
props = { utc, presets, ...props };
|
|
||||||
return <InternalRangePicker {...props} />;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default DatePicker;
|
|
@ -1,51 +0,0 @@
|
|||||||
import { usePrefixCls } from '@formily/antd-v5/esm/__builtins__';
|
|
||||||
import { isArr } from '@formily/shared';
|
|
||||||
import { getDefaultFormat, str2moment } from '@nocobase/utils/client';
|
|
||||||
import type {
|
|
||||||
DatePickerProps as AntdDatePickerProps,
|
|
||||||
RangePickerProps as AntdRangePickerProps,
|
|
||||||
} from 'antd/es/date-picker';
|
|
||||||
import cls from 'classnames';
|
|
||||||
import dayjs from 'dayjs';
|
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
type Composed = {
|
|
||||||
DatePicker: React.FC<AntdDatePickerProps>;
|
|
||||||
DateRangePicker: React.FC<AntdRangePickerProps>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ReadPretty: Composed = () => null;
|
|
||||||
|
|
||||||
ReadPretty.DatePicker = function DatePicker(props: any) {
|
|
||||||
const prefixCls = usePrefixCls('description-date-picker', props);
|
|
||||||
|
|
||||||
if (!props.value) {
|
|
||||||
return <div></div>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const getLabels = () => {
|
|
||||||
const format = getDefaultFormat(props) as string;
|
|
||||||
const m = str2moment(props.value, props);
|
|
||||||
const labels = dayjs.isDayjs(m) ? m.format(format) : '';
|
|
||||||
return isArr(labels) ? labels.join('~') : labels;
|
|
||||||
};
|
|
||||||
return <div className={cls(prefixCls, props.className)}>{getLabels()}</div>;
|
|
||||||
};
|
|
||||||
|
|
||||||
ReadPretty.DateRangePicker = function DateRangePicker(props: any) {
|
|
||||||
const prefixCls = usePrefixCls('description-text', props);
|
|
||||||
const format = getDefaultFormat(props);
|
|
||||||
const getLabels = () => {
|
|
||||||
const m = str2moment(props.value, props);
|
|
||||||
if (!m) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
const labels = m.map((m) => m.format(format));
|
|
||||||
return isArr(labels) ? labels.join('~') : labels;
|
|
||||||
};
|
|
||||||
return (
|
|
||||||
<div className={cls(prefixCls, props.className)} style={props.style}>
|
|
||||||
{getLabels()}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,252 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { render, screen, sleep, userEvent, waitFor } from 'testUtils';
|
|
||||||
import App1 from '../demos/demo1';
|
|
||||||
import App11 from '../demos/demo11';
|
|
||||||
import App2 from '../demos/demo2';
|
|
||||||
import App3 from '../demos/demo3';
|
|
||||||
import App4 from '../demos/demo4';
|
|
||||||
import App5 from '../demos/demo5';
|
|
||||||
import App6 from '../demos/demo6';
|
|
||||||
import App7 from '../demos/demo7';
|
|
||||||
import App8 from '../demos/demo8';
|
|
||||||
import App9 from '../demos/demo9';
|
|
||||||
|
|
||||||
describe('DatePicker', () => {
|
|
||||||
it('basic', async () => {
|
|
||||||
const { container, getByText } = render(<App1 />);
|
|
||||||
|
|
||||||
await sleep();
|
|
||||||
|
|
||||||
const picker = container.querySelector('.ant-picker') as HTMLElement;
|
|
||||||
const input = container.querySelector('input') as HTMLElement;
|
|
||||||
|
|
||||||
await userEvent.click(picker);
|
|
||||||
await userEvent.type(input, '2023/05/01 00:00:00');
|
|
||||||
await userEvent.click(getByText('OK'));
|
|
||||||
|
|
||||||
await waitFor(() => {
|
|
||||||
expect(input).toHaveValue('2023/05/01 00:00:00');
|
|
||||||
// Read pretty
|
|
||||||
expect(screen.getByText('2023/05/01 00:00:00', { selector: '.ant-description-date-picker' })).toBeInTheDocument();
|
|
||||||
|
|
||||||
// TODO: 需要有个方法来固定测试环境的时区
|
|
||||||
if (!process.env.GITHUB_ACTIONS) {
|
|
||||||
// Value
|
|
||||||
expect(screen.getByText('2023-04-30T16:00:00.000Z')).toBeInTheDocument();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('GMT', async () => {
|
|
||||||
const { container, getByText } = render(<App2 />);
|
|
||||||
|
|
||||||
await sleep();
|
|
||||||
|
|
||||||
const picker = container.querySelector('.ant-picker') as HTMLElement;
|
|
||||||
const input = container.querySelector('input') as HTMLElement;
|
|
||||||
|
|
||||||
await userEvent.click(picker);
|
|
||||||
// 清空默认值
|
|
||||||
await userEvent.clear(input);
|
|
||||||
await userEvent.type(input, '2023/05/01 00:00:00');
|
|
||||||
await userEvent.click(getByText('OK'));
|
|
||||||
|
|
||||||
expect(input).toHaveValue('2023/05/01 00:00:00');
|
|
||||||
// Read pretty
|
|
||||||
expect(screen.getByText('2023/05/01 00:00:00', { selector: '.ant-description-date-picker' })).toBeInTheDocument();
|
|
||||||
// Value
|
|
||||||
expect(screen.getByText('2023-05-01T00:00:00.000Z')).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('non-UTC', async () => {
|
|
||||||
const { container } = render(<App3 />);
|
|
||||||
|
|
||||||
await sleep();
|
|
||||||
|
|
||||||
const picker = container.querySelector('.ant-picker') as HTMLElement;
|
|
||||||
const input = container.querySelector('input') as HTMLElement;
|
|
||||||
|
|
||||||
await userEvent.click(picker);
|
|
||||||
await userEvent.type(input, '2023/05/01');
|
|
||||||
|
|
||||||
let selected;
|
|
||||||
await waitFor(() => {
|
|
||||||
selected = document.querySelector('.ant-picker-cell-selected') as HTMLElement;
|
|
||||||
expect(selected).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
await userEvent.click(selected);
|
|
||||||
|
|
||||||
expect(input).toHaveValue('2023/05/01');
|
|
||||||
// Read pretty
|
|
||||||
expect(screen.getByText('2023/05/01 00:00:00', { selector: '.ant-description-date-picker' })).toBeInTheDocument();
|
|
||||||
// Value
|
|
||||||
expect(screen.getByText('2023-05-01')).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('RangePicker', () => {
|
|
||||||
it('GMT', async () => {
|
|
||||||
const { container, getByPlaceholderText } = render(<App4 />);
|
|
||||||
|
|
||||||
await sleep();
|
|
||||||
|
|
||||||
const picker = container.querySelector('.ant-picker') as HTMLElement;
|
|
||||||
const startInput = getByPlaceholderText('Start date');
|
|
||||||
const endInput = getByPlaceholderText('End date');
|
|
||||||
|
|
||||||
await userEvent.click(picker);
|
|
||||||
await userEvent.click(document.querySelector('[title="2023-05-01"]') as HTMLElement);
|
|
||||||
await userEvent.click(document.querySelector('[title="2023-05-02"]') as HTMLElement);
|
|
||||||
|
|
||||||
await waitFor(() => expect(startInput).toHaveValue('2023-05-01'));
|
|
||||||
await waitFor(() => expect(endInput).toHaveValue('2023-05-02'));
|
|
||||||
// Read pretty
|
|
||||||
expect(screen.getByText('2023-05-01~2023-05-02', { selector: '.ant-description-text' })).toBeInTheDocument();
|
|
||||||
// Value
|
|
||||||
expect(screen.getByText('2023-05-01T00:00:00.000Z ~ 2023-05-02T23:59:59.999Z')).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('non-GMT', async () => {
|
|
||||||
const { container, getByPlaceholderText } = render(<App5 />);
|
|
||||||
|
|
||||||
await sleep();
|
|
||||||
|
|
||||||
const picker = container.querySelector('.ant-picker') as HTMLElement;
|
|
||||||
const startInput = getByPlaceholderText('Start date');
|
|
||||||
const endInput = getByPlaceholderText('End date');
|
|
||||||
|
|
||||||
await userEvent.click(picker);
|
|
||||||
await userEvent.click(document.querySelector('[title="2023-05-01"]') as HTMLElement);
|
|
||||||
await userEvent.click(document.querySelector('[title="2023-05-02"]') as HTMLElement);
|
|
||||||
|
|
||||||
await waitFor(() => {
|
|
||||||
expect(startInput).toHaveValue('2023-05-01');
|
|
||||||
expect(endInput).toHaveValue('2023-05-02');
|
|
||||||
// Read pretty
|
|
||||||
expect(screen.getByText('2023-05-01~2023-05-02', { selector: '.ant-description-text' })).toBeInTheDocument();
|
|
||||||
|
|
||||||
if (!process.env.GITHUB_ACTIONS) {
|
|
||||||
// Value
|
|
||||||
expect(screen.getByText(/2023-04-30t16:00:00\.000z ~ 2023-05-02t15:59:59\.999z/i)).toBeInTheDocument();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('non-UTC', async () => {
|
|
||||||
const { container, getByPlaceholderText } = render(<App6 />);
|
|
||||||
|
|
||||||
await sleep();
|
|
||||||
|
|
||||||
const picker = container.querySelector('.ant-picker') as HTMLElement;
|
|
||||||
const startInput = getByPlaceholderText('Start date');
|
|
||||||
const endInput = getByPlaceholderText('End date');
|
|
||||||
|
|
||||||
await userEvent.click(picker);
|
|
||||||
await sleep();
|
|
||||||
await userEvent.click(document.querySelector('[title="2023-05-01"]') as HTMLElement);
|
|
||||||
await userEvent.click(document.querySelector('[title="2023-05-02"]') as HTMLElement);
|
|
||||||
|
|
||||||
await waitFor(() => expect(startInput).toHaveValue('2023-05-01'));
|
|
||||||
await waitFor(() => expect(endInput).toHaveValue('2023-05-02'));
|
|
||||||
|
|
||||||
// Read pretty
|
|
||||||
await waitFor(() =>
|
|
||||||
expect(screen.getByText('2023-05-01~2023-05-02', { selector: '.ant-description-text' })).toBeInTheDocument(),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Value
|
|
||||||
await waitFor(() => expect(screen.getByText('2023-05-01 ~ 2023-05-02')).toBeInTheDocument());
|
|
||||||
});
|
|
||||||
|
|
||||||
it('showTime=false,gmt=true,utc=true', async () => {
|
|
||||||
const { container } = render(<App7 />);
|
|
||||||
|
|
||||||
await sleep();
|
|
||||||
|
|
||||||
const picker = container.querySelector('.ant-picker') as HTMLElement;
|
|
||||||
const input = container.querySelector('input') as HTMLElement;
|
|
||||||
|
|
||||||
await userEvent.click(picker);
|
|
||||||
await userEvent.type(input, '2023/05/01');
|
|
||||||
await userEvent.click(document.querySelector('[title="2023-05-01"]') as HTMLElement);
|
|
||||||
|
|
||||||
await waitFor(() => {
|
|
||||||
expect(input).toHaveValue('2023/05/01');
|
|
||||||
// Read pretty
|
|
||||||
expect(screen.getByText('2023/05/01', { selector: '.ant-description-date-picker' })).toBeInTheDocument();
|
|
||||||
|
|
||||||
// Value
|
|
||||||
expect(screen.getByText('2023-05-01T00:00:00.000Z')).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('showTime=false,gmt=false,utc=true', async () => {
|
|
||||||
const { container } = render(<App8 />);
|
|
||||||
|
|
||||||
await sleep();
|
|
||||||
|
|
||||||
const picker = container.querySelector('.ant-picker') as HTMLElement;
|
|
||||||
const input = container.querySelector('input') as HTMLElement;
|
|
||||||
|
|
||||||
await userEvent.click(picker);
|
|
||||||
await userEvent.type(input, '2023/05/01');
|
|
||||||
await userEvent.click(document.querySelector('[title="2023-05-01"]') as HTMLElement);
|
|
||||||
|
|
||||||
await waitFor(() => {
|
|
||||||
expect(input).toHaveValue('2023/05/01');
|
|
||||||
// Read pretty
|
|
||||||
expect(screen.getByText('2023/05/01', { selector: '.ant-description-date-picker' })).toBeInTheDocument();
|
|
||||||
|
|
||||||
if (!process.env.GITHUB_ACTIONS) {
|
|
||||||
// Value
|
|
||||||
// 当 gmt 为 false 时是按照客户端本地时区进行计算的,但是这里的测试环境是 UTC+8,所以会有 8 小时的误差
|
|
||||||
expect(screen.getByText('2023-04-30T16:00:00.000Z')).toBeInTheDocument();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('showTime=false,gmt=true,utc=true & not input', async () => {
|
|
||||||
const currentDateString = new Date().toISOString().split('T')[0];
|
|
||||||
const { container } = render(<App9 />);
|
|
||||||
|
|
||||||
await sleep();
|
|
||||||
|
|
||||||
const picker = container.querySelector('.ant-picker') as HTMLElement;
|
|
||||||
|
|
||||||
await userEvent.click(picker);
|
|
||||||
const btn = document.querySelector(`[title="${currentDateString}"]`);
|
|
||||||
expect(btn).toBeInTheDocument();
|
|
||||||
await userEvent.click(btn as HTMLElement);
|
|
||||||
|
|
||||||
await waitFor(() => {
|
|
||||||
// Read pretty
|
|
||||||
expect(
|
|
||||||
screen.getByText(currentDateString.replace(/-/g, '/'), { selector: '.ant-description-date-picker' }),
|
|
||||||
).toBeInTheDocument();
|
|
||||||
|
|
||||||
// Value
|
|
||||||
expect(screen.getByText(`${currentDateString}T00:00:00.000Z`)).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// fix T-1506
|
|
||||||
it('shortcut', async () => {
|
|
||||||
const { container } = render(<App11 />);
|
|
||||||
|
|
||||||
await sleep();
|
|
||||||
|
|
||||||
const picker = container.querySelector('.ant-picker') as HTMLElement;
|
|
||||||
const startInput = screen.getByPlaceholderText('Start date');
|
|
||||||
const endInput = screen.getByPlaceholderText('End date');
|
|
||||||
|
|
||||||
await userEvent.click(picker);
|
|
||||||
|
|
||||||
// shortcut: Today
|
|
||||||
await userEvent.click(screen.getByText(/today/i));
|
|
||||||
await sleep();
|
|
||||||
|
|
||||||
// 因为 Today 快捷键的值是动态生成的,所以这里没有断言具体的值
|
|
||||||
await waitFor(() => expect(startInput.getAttribute('value')).toBeTruthy());
|
|
||||||
await waitFor(() => expect(endInput.getAttribute('value')).toBeTruthy());
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,132 +0,0 @@
|
|||||||
import dayjs from 'dayjs';
|
|
||||||
import { getDateRanges } from '../util';
|
|
||||||
|
|
||||||
describe('getDateRanges', () => {
|
|
||||||
const dateRanges = getDateRanges();
|
|
||||||
|
|
||||||
it('today', () => {
|
|
||||||
const [start, end] = dateRanges.today();
|
|
||||||
expect(start.toISOString()).toBe(dayjs().startOf('day').toISOString());
|
|
||||||
expect(end.toISOString()).toBe(dayjs().endOf('day').toISOString());
|
|
||||||
});
|
|
||||||
|
|
||||||
test('yesterday', () => {
|
|
||||||
const [start, end] = dateRanges.yesterday();
|
|
||||||
expect(dayjs(start).isSame(dayjs().subtract(1, 'day'), 'day')).toBe(true);
|
|
||||||
expect(dayjs(end).isSame(dayjs().subtract(1, 'day'), 'day')).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('tomorrow', () => {
|
|
||||||
const [start, end] = dateRanges.tomorrow();
|
|
||||||
expect(dayjs(start).isSame(dayjs().add(1, 'day'), 'day')).toBe(true);
|
|
||||||
expect(dayjs(end).isSame(dayjs().add(1, 'day'), 'day')).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('lastWeek', () => {
|
|
||||||
const [start, end] = dateRanges.lastWeek();
|
|
||||||
expect(start.toISOString()).toBe(dayjs().add(-1, 'week').startOf('isoWeek').toISOString());
|
|
||||||
expect(end.toISOString()).toBe(dayjs().add(-1, 'week').endOf('isoWeek').toISOString());
|
|
||||||
});
|
|
||||||
|
|
||||||
it('thisWeek', () => {
|
|
||||||
const [start, end] = dateRanges.thisWeek();
|
|
||||||
expect(start.toISOString()).toBe(dayjs().startOf('isoWeek').toISOString());
|
|
||||||
expect(end.toISOString()).toBe(dayjs().endOf('isoWeek').toISOString());
|
|
||||||
});
|
|
||||||
|
|
||||||
it('nextWeek', () => {
|
|
||||||
const [start, end] = dateRanges.nextWeek();
|
|
||||||
expect(start.toISOString()).toBe(dayjs().add(1, 'week').startOf('isoWeek').toISOString());
|
|
||||||
expect(end.toISOString()).toBe(dayjs().add(1, 'week').endOf('isoWeek').toISOString());
|
|
||||||
});
|
|
||||||
|
|
||||||
it('lastMonth', () => {
|
|
||||||
const [start, end] = dateRanges.lastMonth();
|
|
||||||
expect(start.toISOString()).toBe(dayjs().add(-1, 'month').startOf('month').toISOString());
|
|
||||||
expect(end.toISOString()).toBe(dayjs().add(-1, 'month').endOf('month').toISOString());
|
|
||||||
});
|
|
||||||
|
|
||||||
it('thisMonth', () => {
|
|
||||||
const [start, end] = dateRanges.thisMonth();
|
|
||||||
expect(start.toISOString()).toBe(dayjs().startOf('month').toISOString());
|
|
||||||
expect(end.toISOString()).toBe(dayjs().endOf('month').toISOString());
|
|
||||||
});
|
|
||||||
|
|
||||||
it('nextMonth', () => {
|
|
||||||
const [start, end] = dateRanges.nextMonth();
|
|
||||||
expect(start.toISOString()).toBe(dayjs().add(1, 'month').startOf('month').toISOString());
|
|
||||||
expect(end.toISOString()).toBe(dayjs().add(1, 'month').endOf('month').toISOString());
|
|
||||||
});
|
|
||||||
|
|
||||||
it('lastQuarter', () => {
|
|
||||||
const [start, end] = dateRanges.lastQuarter();
|
|
||||||
expect(start.toISOString()).toBe(dayjs().add(-1, 'quarter').startOf('quarter').toISOString());
|
|
||||||
expect(end.toISOString()).toBe(dayjs().add(-1, 'quarter').endOf('quarter').toISOString());
|
|
||||||
});
|
|
||||||
|
|
||||||
it('thisQuarter', () => {
|
|
||||||
const [start, end] = dateRanges.thisQuarter();
|
|
||||||
expect(start.toISOString()).toBe(dayjs().startOf('quarter').toISOString());
|
|
||||||
expect(end.toISOString()).toBe(dayjs().endOf('quarter').toISOString());
|
|
||||||
});
|
|
||||||
|
|
||||||
it('nextQuarter', () => {
|
|
||||||
const [start, end] = dateRanges.nextQuarter();
|
|
||||||
expect(start.toISOString()).toBe(dayjs().add(1, 'quarter').startOf('quarter').toISOString());
|
|
||||||
expect(end.toISOString()).toBe(dayjs().add(1, 'quarter').endOf('quarter').toISOString());
|
|
||||||
});
|
|
||||||
|
|
||||||
it('lastYear', () => {
|
|
||||||
const [start, end] = dateRanges.lastYear();
|
|
||||||
expect(start.toISOString()).toBe(dayjs().add(-1, 'year').startOf('year').toISOString());
|
|
||||||
expect(end.toISOString()).toBe(dayjs().add(-1, 'year').endOf('year').toISOString());
|
|
||||||
});
|
|
||||||
|
|
||||||
it('thisYear', () => {
|
|
||||||
const [start, end] = dateRanges.thisYear();
|
|
||||||
expect(start.toISOString()).toBe(dayjs().startOf('year').toISOString());
|
|
||||||
expect(end.toISOString()).toBe(dayjs().endOf('year').toISOString());
|
|
||||||
});
|
|
||||||
|
|
||||||
it('nextYear', () => {
|
|
||||||
const [start, end] = dateRanges.nextYear();
|
|
||||||
expect(start.toISOString()).toBe(dayjs().add(1, 'year').startOf('year').toISOString());
|
|
||||||
expect(end.toISOString()).toBe(dayjs().add(1, 'year').endOf('year').toISOString());
|
|
||||||
});
|
|
||||||
|
|
||||||
it('last7Days', () => {
|
|
||||||
const [start, end] = dateRanges.last7Days();
|
|
||||||
expect(start.toISOString()).toBe(dayjs().add(-6, 'days').startOf('days').toISOString());
|
|
||||||
expect(end.toISOString()).toBe(dayjs().endOf('days').toISOString());
|
|
||||||
});
|
|
||||||
|
|
||||||
it('next7Days', () => {
|
|
||||||
const [start, end] = dateRanges.next7Days();
|
|
||||||
expect(start.toISOString()).toBe(dayjs().add(1, 'day').startOf('day').toISOString());
|
|
||||||
expect(end.toISOString()).toBe(dayjs().add(7, 'days').endOf('days').toISOString());
|
|
||||||
});
|
|
||||||
|
|
||||||
it('last30Days', () => {
|
|
||||||
const [start, end] = dateRanges.last30Days();
|
|
||||||
expect(start.toISOString()).toBe(dayjs().add(-29, 'days').startOf('days').toISOString());
|
|
||||||
expect(end.toISOString()).toBe(dayjs().endOf('days').toISOString());
|
|
||||||
});
|
|
||||||
|
|
||||||
it('next30Days', () => {
|
|
||||||
const [start, end] = dateRanges.next30Days();
|
|
||||||
expect(start.toISOString()).toBe(dayjs().add(1, 'day').startOf('day').toISOString());
|
|
||||||
expect(end.toISOString()).toBe(dayjs().add(30, 'days').endOf('days').toISOString());
|
|
||||||
});
|
|
||||||
|
|
||||||
it('last90Days', () => {
|
|
||||||
const [start, end] = dateRanges.last90Days();
|
|
||||||
expect(start.toISOString()).toBe(dayjs().add(-89, 'days').startOf('days').toISOString());
|
|
||||||
expect(end.toISOString()).toBe(dayjs().endOf('days').toISOString());
|
|
||||||
});
|
|
||||||
|
|
||||||
it('next90Days', () => {
|
|
||||||
const [start, end] = dateRanges.next90Days();
|
|
||||||
expect(start.toISOString()).toBe(dayjs().add(1, 'day').startOf('day').toISOString());
|
|
||||||
expect(end.toISOString()).toBe(dayjs().add(90, 'days').endOf('days').toISOString());
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,221 +0,0 @@
|
|||||||
import dayjs from 'dayjs';
|
|
||||||
import { mapDatePicker } from '../util';
|
|
||||||
import { vi } from 'vitest';
|
|
||||||
|
|
||||||
describe('mapDatePicker', () => {
|
|
||||||
it('showTime is true and gmt is true', () => {
|
|
||||||
const props = {
|
|
||||||
value: '2022-02-22T22:22:22.000Z',
|
|
||||||
showTime: true,
|
|
||||||
gmt: true,
|
|
||||||
};
|
|
||||||
const result = mapDatePicker()(props);
|
|
||||||
expect(result.value.format('YYYY-MM-DD HH:mm:ss')).toBe('2022-02-22 22:22:22');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('showTime is true and gmt is false', () => {
|
|
||||||
const props = {
|
|
||||||
value: '2022-02-22T22:22:22.000Z',
|
|
||||||
showTime: true,
|
|
||||||
gmt: false,
|
|
||||||
};
|
|
||||||
const result = mapDatePicker()(props);
|
|
||||||
expect(result.value.format('YYYY-MM-DD HH:mm:ss')).toBe(
|
|
||||||
dayjs('2022-02-22T22:22:22.000Z').format('YYYY-MM-DD HH:mm:ss'),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('showTime is false and gmt is true', () => {
|
|
||||||
const props = {
|
|
||||||
value: '2022-02-22T00:00:00.000Z',
|
|
||||||
showTime: false,
|
|
||||||
gmt: true,
|
|
||||||
};
|
|
||||||
const result = mapDatePicker()(props);
|
|
||||||
expect(result.value.format('YYYY-MM-DD HH:mm:ss')).toBe('2022-02-22 00:00:00');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('showTime is false and gmt is false', () => {
|
|
||||||
const props = {
|
|
||||||
value: '2022-02-22',
|
|
||||||
showTime: false,
|
|
||||||
gmt: false,
|
|
||||||
};
|
|
||||||
const result = mapDatePicker()(props);
|
|
||||||
expect(result.value.format('YYYY-MM-DD HH:mm:ss')).toBe('2022-02-22 00:00:00');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call onChange with correct value when showTime is true and gmt is true', () => {
|
|
||||||
const props = {
|
|
||||||
showTime: true,
|
|
||||||
gmt: true,
|
|
||||||
onChange: vi.fn(),
|
|
||||||
};
|
|
||||||
const result = mapDatePicker()(props);
|
|
||||||
result.onChange(dayjs.utc('2022-02-22 22:22:22'));
|
|
||||||
expect(props.onChange).toHaveBeenCalledWith('2022-02-22T22:22:22.000Z');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call onChange with correct value when showTime is true and gmt is false', () => {
|
|
||||||
const props = {
|
|
||||||
showTime: true,
|
|
||||||
gmt: false,
|
|
||||||
onChange: vi.fn(),
|
|
||||||
};
|
|
||||||
const result = mapDatePicker()(props);
|
|
||||||
const m = dayjs('2022-02-22 22:22:22');
|
|
||||||
result.onChange(m);
|
|
||||||
expect(props.onChange).toHaveBeenCalledWith(m.toISOString());
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call onChange with correct value when showTime is false and gmt is true', () => {
|
|
||||||
const props = {
|
|
||||||
showTime: false,
|
|
||||||
gmt: true,
|
|
||||||
onChange: vi.fn(),
|
|
||||||
};
|
|
||||||
const result = mapDatePicker()(props);
|
|
||||||
result.onChange(dayjs.utc('2022-02-22'));
|
|
||||||
expect(props.onChange).toHaveBeenCalledWith('2022-02-22T00:00:00.000Z');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call onChange with correct value when showTime is false and gmt is false', () => {
|
|
||||||
const props = {
|
|
||||||
showTime: false,
|
|
||||||
gmt: false,
|
|
||||||
onChange: vi.fn(),
|
|
||||||
};
|
|
||||||
const result = mapDatePicker()(props);
|
|
||||||
const m = dayjs('2022-02-22');
|
|
||||||
result.onChange(m);
|
|
||||||
expect(props.onChange).toHaveBeenCalledWith(m.toISOString());
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call onChange with correct value when picker is year and gmt is true', () => {
|
|
||||||
const props = {
|
|
||||||
picker: 'year',
|
|
||||||
gmt: true,
|
|
||||||
onChange: vi.fn(),
|
|
||||||
};
|
|
||||||
const result = mapDatePicker()(props);
|
|
||||||
result.onChange(dayjs.utc('2022-01-01T00:00:00.000Z'));
|
|
||||||
expect(props.onChange).toHaveBeenCalledWith('2022-01-01T00:00:00.000Z');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call onChange with correct value when picker is year and gmt is false', () => {
|
|
||||||
const props = {
|
|
||||||
picker: 'year',
|
|
||||||
gmt: false,
|
|
||||||
onChange: vi.fn(),
|
|
||||||
};
|
|
||||||
const result = mapDatePicker()(props);
|
|
||||||
const m = dayjs('2022-02-01 00:00:00');
|
|
||||||
result.onChange(m);
|
|
||||||
expect(props.onChange).toHaveBeenCalledWith(m.startOf('year').toISOString());
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call onChange with correct value when picker is month and gmt is true', () => {
|
|
||||||
const props = {
|
|
||||||
picker: 'month',
|
|
||||||
gmt: true,
|
|
||||||
onChange: vi.fn(),
|
|
||||||
};
|
|
||||||
const result = mapDatePicker()(props);
|
|
||||||
result.onChange(dayjs.utc('2022-02-22T00:00:00.000Z'));
|
|
||||||
expect(props.onChange).toHaveBeenCalledWith('2022-02-01T00:00:00.000Z');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call onChange with correct value when picker is month and gmt is false', () => {
|
|
||||||
const props = {
|
|
||||||
picker: 'month',
|
|
||||||
gmt: false,
|
|
||||||
onChange: vi.fn(),
|
|
||||||
};
|
|
||||||
const result = mapDatePicker()(props);
|
|
||||||
const m = dayjs('2022-02-01 00:00:00');
|
|
||||||
result.onChange(m);
|
|
||||||
expect(props.onChange).toHaveBeenCalledWith(m.startOf('month').toISOString());
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call onChange with correct value when picker is quarter and gmt is true', () => {
|
|
||||||
const props = {
|
|
||||||
picker: 'quarter',
|
|
||||||
gmt: true,
|
|
||||||
onChange: vi.fn(),
|
|
||||||
};
|
|
||||||
const result = mapDatePicker()(props);
|
|
||||||
result.onChange(dayjs.utc('2022-02-22T00:00:00.000Z'));
|
|
||||||
expect(props.onChange).toHaveBeenCalledWith('2022-01-01T00:00:00.000Z');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call onChange with correct value when picker is quarter and gmt is false', () => {
|
|
||||||
const props = {
|
|
||||||
picker: 'quarter',
|
|
||||||
gmt: false,
|
|
||||||
onChange: vi.fn(),
|
|
||||||
};
|
|
||||||
const result = mapDatePicker()(props);
|
|
||||||
const m = dayjs('2022-02-01 00:00:00');
|
|
||||||
result.onChange(m);
|
|
||||||
expect(props.onChange).toHaveBeenCalledWith(m.startOf('quarter').toISOString());
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call onChange with correct value when picker is week and gmt is true', () => {
|
|
||||||
const props = {
|
|
||||||
picker: 'week',
|
|
||||||
gmt: true,
|
|
||||||
onChange: vi.fn(),
|
|
||||||
};
|
|
||||||
const result = mapDatePicker()(props);
|
|
||||||
const m = dayjs.utc('2022-02-21T00:00:00.000Z');
|
|
||||||
result.onChange(m);
|
|
||||||
expect(props.onChange).toHaveBeenCalledWith(m.startOf('week').add(1, 'day').toISOString());
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call onChange with correct value when picker is week and gmt is false', () => {
|
|
||||||
const props = {
|
|
||||||
picker: 'week',
|
|
||||||
gmt: false,
|
|
||||||
onChange: vi.fn(),
|
|
||||||
};
|
|
||||||
const result = mapDatePicker()(props);
|
|
||||||
const m = dayjs('2022-02-21 00:00:00');
|
|
||||||
result.onChange(m);
|
|
||||||
expect(props.onChange).toHaveBeenCalledWith(m.startOf('week').add(1, 'day').toISOString());
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call onChange with correct value when utc is false', () => {
|
|
||||||
const props = {
|
|
||||||
showTime: true,
|
|
||||||
gmt: true,
|
|
||||||
utc: false,
|
|
||||||
onChange: vi.fn(),
|
|
||||||
};
|
|
||||||
const result = mapDatePicker()(props);
|
|
||||||
result.onChange(dayjs('2022-02-22 22:22:22'));
|
|
||||||
expect(props.onChange).toHaveBeenCalledWith('2022-02-22 22:22:22');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call onChange with correct value when picker is year and utc is false', () => {
|
|
||||||
const props = {
|
|
||||||
showTime: false,
|
|
||||||
gmt: true,
|
|
||||||
utc: false,
|
|
||||||
onChange: vi.fn(),
|
|
||||||
};
|
|
||||||
const result = mapDatePicker()(props);
|
|
||||||
result.onChange(dayjs('2022-01-01 23:00:00'));
|
|
||||||
expect(props.onChange).toHaveBeenCalledWith('2022-01-01');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('utc is false and gmt is true', () => {
|
|
||||||
const props = {
|
|
||||||
value: '2022-01-01 23:00:00',
|
|
||||||
showTime: true,
|
|
||||||
gmt: true,
|
|
||||||
utc: false,
|
|
||||||
};
|
|
||||||
const result = mapDatePicker()(props);
|
|
||||||
expect(result.value.format('YYYY-MM-DD HH:mm:ss')).toBe('2022-01-01 23:00:00');
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,43 +0,0 @@
|
|||||||
import dayjs from 'dayjs';
|
|
||||||
import { mapRangePicker } from '../util';
|
|
||||||
|
|
||||||
describe('mapRangePicker', () => {
|
|
||||||
it('should work with showTime=false, gmt=true, utc=true', () => {
|
|
||||||
const props = {
|
|
||||||
showTime: false,
|
|
||||||
gmt: true,
|
|
||||||
utc: true,
|
|
||||||
onChange: vi.fn(),
|
|
||||||
};
|
|
||||||
const { onChange } = mapRangePicker()(props);
|
|
||||||
const value = [dayjs.utc('2023-01-01T00:00:00.000Z'), dayjs.utc('2023-01-02T00:00:00.000Z')];
|
|
||||||
onChange(value);
|
|
||||||
expect(props.onChange).toHaveBeenCalledWith(['2023-01-01T00:00:00.000Z', '2023-01-02T23:59:59.999Z']);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should work with showTime=true, gmt=true, utc=true', () => {
|
|
||||||
const props = {
|
|
||||||
showTime: true,
|
|
||||||
gmt: true,
|
|
||||||
utc: true,
|
|
||||||
onChange: vi.fn(),
|
|
||||||
};
|
|
||||||
const { onChange } = mapRangePicker()(props);
|
|
||||||
const value = [dayjs.utc('2023-01-01T00:00:00.000Z'), dayjs.utc('2023-01-02T00:00:00.000Z')];
|
|
||||||
onChange(value);
|
|
||||||
expect(props.onChange).toHaveBeenCalledWith(['2023-01-01T00:00:00.000Z', '2023-01-02T00:00:00.000Z']);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should work with showTime=false, gmt=true, utc=false', () => {
|
|
||||||
const props = {
|
|
||||||
showTime: false,
|
|
||||||
gmt: true,
|
|
||||||
utc: false,
|
|
||||||
onChange: vi.fn(),
|
|
||||||
};
|
|
||||||
const { onChange } = mapRangePicker()(props);
|
|
||||||
const value = [dayjs.utc('2023-01-01T00:00:00.000Z'), dayjs.utc('2023-01-02T00:00:00.000Z')];
|
|
||||||
onChange(value);
|
|
||||||
expect(props.onChange).toHaveBeenCalledWith(['2023-01-01', '2023-01-02']);
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,140 +0,0 @@
|
|||||||
import { str2moment } from '@nocobase/utils/client';
|
|
||||||
import dayjs from 'dayjs';
|
|
||||||
import { moment2str } from '../util';
|
|
||||||
|
|
||||||
describe('str2moment', () => {
|
|
||||||
describe('string value', () => {
|
|
||||||
test('gmt date', async () => {
|
|
||||||
const m = str2moment('2022-06-21T00:00:00.000Z', { gmt: true });
|
|
||||||
expect(m.format('YYYY-MM-DD HH:mm:ss')).toBe('2022-06-21 00:00:00');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('local date', async () => {
|
|
||||||
const m = str2moment('2022-06-21T00:00:00.000Z');
|
|
||||||
expect(m.toISOString()).toBe('2022-06-21T00:00:00.000Z');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('value is null', async () => {
|
|
||||||
const m = str2moment(null);
|
|
||||||
expect(m).toBeNull();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('picker is month', async () => {
|
|
||||||
const m = str2moment('2022-06-01T00:00:00.000Z', { picker: 'month' });
|
|
||||||
expect(m.format('YYYY-MM-DD HH:mm:ss')).toBe('2022-06-01 00:00:00');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('array value', () => {
|
|
||||||
test('gmt date', async () => {
|
|
||||||
const arr = str2moment(['2022-06-21T00:00:00.000Z', '2022-06-21T00:00:00.000Z'], { gmt: true });
|
|
||||||
for (const m of arr) {
|
|
||||||
expect(m.format('YYYY-MM-DD HH:mm:ss')).toBe('2022-06-21 00:00:00');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test('local date', async () => {
|
|
||||||
const arr = str2moment(['2022-06-21T00:00:00.000Z', '2022-06-21T00:00:00.000Z']);
|
|
||||||
for (const m of arr) {
|
|
||||||
expect(m.toISOString()).toBe('2022-06-21T00:00:00.000Z');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('moment2str', () => {
|
|
||||||
test('gmt date', () => {
|
|
||||||
const m = dayjs('2023-06-21 10:10:00');
|
|
||||||
const str = moment2str(m, { showTime: true, gmt: true });
|
|
||||||
expect(str).toBe('2023-06-21T10:10:00.000Z');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('showTime is true, gmt is false', () => {
|
|
||||||
const m = dayjs('2023-06-21 10:10:00');
|
|
||||||
const str = moment2str(m, { showTime: true, gmt: false });
|
|
||||||
expect(str).toBe(m.toISOString());
|
|
||||||
});
|
|
||||||
|
|
||||||
test('gmt is true', () => {
|
|
||||||
const m = dayjs('2023-06-21 10:10:00');
|
|
||||||
const str = moment2str(m, { gmt: true });
|
|
||||||
expect(str).toBe('2023-06-21T10:10:00.000Z');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('gmt is false', () => {
|
|
||||||
const m = dayjs('2023-06-21 10:10:00');
|
|
||||||
const str = moment2str(m, { gmt: false });
|
|
||||||
expect(str).toBe(dayjs('2023-06-21 10:10:00').toISOString());
|
|
||||||
});
|
|
||||||
|
|
||||||
test('with time', () => {
|
|
||||||
const m = dayjs('2023-06-21 10:10:00');
|
|
||||||
const str = moment2str(m, { showTime: true });
|
|
||||||
expect(str).toBe(m.toISOString());
|
|
||||||
});
|
|
||||||
|
|
||||||
test('picker is year, gmt is false', () => {
|
|
||||||
const m = dayjs('2023-06-21 10:10:00');
|
|
||||||
const str = moment2str(m, { picker: 'year', gmt: false });
|
|
||||||
expect(str).toBe(dayjs('2023-01-01 00:00:00').toISOString());
|
|
||||||
});
|
|
||||||
|
|
||||||
test('picker is year, gmt is true', () => {
|
|
||||||
const m = dayjs('2023-06-21 10:10:00');
|
|
||||||
const str = moment2str(m, { picker: 'year', gmt: true });
|
|
||||||
expect(str).toBe('2023-01-01T00:00:00.000Z');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('picker is year', () => {
|
|
||||||
const m = dayjs('2023-06-21 10:10:00');
|
|
||||||
const str = moment2str(m, { picker: 'year' });
|
|
||||||
expect(str).toBe('2023-01-01T00:00:00.000Z');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('picker is quarter, gmt is false', () => {
|
|
||||||
const m = dayjs('2023-06-21 10:10:00');
|
|
||||||
const str = moment2str(m, { picker: 'quarter', gmt: false });
|
|
||||||
expect(str).toBe(dayjs('2023-04-01 00:00:00').toISOString());
|
|
||||||
});
|
|
||||||
|
|
||||||
test('picker is quarter, gmt is true', () => {
|
|
||||||
const m = dayjs('2023-06-21 10:10:00');
|
|
||||||
const str = moment2str(m, { picker: 'quarter', gmt: true });
|
|
||||||
expect(str).toBe('2023-04-01T00:00:00.000Z');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('picker is month, gmt is false', () => {
|
|
||||||
const m = dayjs('2023-06-21 10:10:00');
|
|
||||||
const str = moment2str(m, { picker: 'month', gmt: false });
|
|
||||||
expect(str).toBe(dayjs('2023-06-01 00:00:00').toISOString());
|
|
||||||
});
|
|
||||||
|
|
||||||
test('picker is month, gmt is true', () => {
|
|
||||||
const m = dayjs('2023-06-21 10:10:00');
|
|
||||||
const str = moment2str(m, { picker: 'month', gmt: true });
|
|
||||||
expect(str).toBe('2023-06-01T00:00:00.000Z');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('picker is month', () => {
|
|
||||||
const m = dayjs('2023-06-21 10:10:00');
|
|
||||||
const str = moment2str(m, { picker: 'month' });
|
|
||||||
expect(str).toBe('2023-06-01T00:00:00.000Z');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('picker is week, gmt is false', () => {
|
|
||||||
const m = dayjs('2023-06-21 10:10:00');
|
|
||||||
const str = moment2str(m, { picker: 'week', gmt: false });
|
|
||||||
expect(str).toBe(dayjs('2023-06-19 00:00:00').toISOString());
|
|
||||||
});
|
|
||||||
|
|
||||||
test('picker is week, gmt is true', () => {
|
|
||||||
const m = dayjs('2023-06-21 10:10:00');
|
|
||||||
const str = moment2str(m, { picker: 'week', gmt: true });
|
|
||||||
expect(str).toBe('2023-06-19T00:00:00.000Z');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('value is null', async () => {
|
|
||||||
const m = moment2str(null);
|
|
||||||
expect(m).toBeNull();
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,57 +0,0 @@
|
|||||||
/**
|
|
||||||
* title: DatePicker
|
|
||||||
*/
|
|
||||||
import { FormItem } from '@formily/antd-v5';
|
|
||||||
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,
|
|
||||||
},
|
|
||||||
'x-reactions': {
|
|
||||||
target: '*(read1,read2)',
|
|
||||||
fulfill: {
|
|
||||||
state: {
|
|
||||||
value: '{{$self.value}}',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
read1: {
|
|
||||||
type: 'boolean',
|
|
||||||
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 (
|
|
||||||
<SchemaComponentProvider components={{ Input, DatePicker, FormItem }}>
|
|
||||||
<SchemaComponent schema={schema} />
|
|
||||||
</SchemaComponentProvider>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,61 +0,0 @@
|
|||||||
/**
|
|
||||||
* title: DatePicker
|
|
||||||
*/
|
|
||||||
import { FormItem } from '@formily/antd-v5';
|
|
||||||
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: false,
|
|
||||||
gmt: false,
|
|
||||||
utc: true,
|
|
||||||
},
|
|
||||||
'x-reactions': {
|
|
||||||
target: '*(read1,read2)',
|
|
||||||
fulfill: {
|
|
||||||
state: {
|
|
||||||
value: '{{$self.value}}',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
read1: {
|
|
||||||
type: 'boolean',
|
|
||||||
title: `Read pretty`,
|
|
||||||
'x-read-pretty': true,
|
|
||||||
'x-decorator': 'FormItem',
|
|
||||||
'x-component': 'DatePicker',
|
|
||||||
'x-component-props': {
|
|
||||||
dateFormat: 'YYYY/MM/DD',
|
|
||||||
showTime: false,
|
|
||||||
gmt: false,
|
|
||||||
utc: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
read2: {
|
|
||||||
type: 'string',
|
|
||||||
title: `Value`,
|
|
||||||
'x-read-pretty': true,
|
|
||||||
'x-decorator': 'FormItem',
|
|
||||||
'x-component': 'Input',
|
|
||||||
'x-component-props': {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default () => {
|
|
||||||
return (
|
|
||||||
<SchemaComponentProvider components={{ Input, DatePicker, FormItem }}>
|
|
||||||
<SchemaComponent schema={schema} />
|
|
||||||
</SchemaComponentProvider>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,65 +0,0 @@
|
|||||||
/**
|
|
||||||
* title: DatePicker.RangePicker
|
|
||||||
*/
|
|
||||||
import { FormItem } from '@formily/antd-v5';
|
|
||||||
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.RangePicker',
|
|
||||||
'x-component-props': {
|
|
||||||
gmt: true,
|
|
||||||
},
|
|
||||||
'x-reactions': [
|
|
||||||
{
|
|
||||||
target: 'read1',
|
|
||||||
fulfill: {
|
|
||||||
state: {
|
|
||||||
value: '{{$self.value}}',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
target: 'read2',
|
|
||||||
fulfill: {
|
|
||||||
state: {
|
|
||||||
value: '{{$self.value && $self.value.join(" ~ ")}}',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
read1: {
|
|
||||||
type: 'boolean',
|
|
||||||
title: `Read pretty`,
|
|
||||||
'x-read-pretty': true,
|
|
||||||
'x-decorator': 'FormItem',
|
|
||||||
'x-component': 'DatePicker.RangePicker',
|
|
||||||
'x-component-props': {
|
|
||||||
gmt: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
read2: {
|
|
||||||
type: 'string',
|
|
||||||
title: `Value`,
|
|
||||||
'x-read-pretty': true,
|
|
||||||
'x-decorator': 'FormItem',
|
|
||||||
'x-component': 'Input',
|
|
||||||
'x-component-props': {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default () => {
|
|
||||||
return (
|
|
||||||
<SchemaComponentProvider components={{ Input, DatePicker, FormItem }}>
|
|
||||||
<SchemaComponent schema={schema} />
|
|
||||||
</SchemaComponentProvider>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,60 +0,0 @@
|
|||||||
/**
|
|
||||||
* title: DatePicker (GMT)
|
|
||||||
*/
|
|
||||||
import { FormItem } from '@formily/antd-v5';
|
|
||||||
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,
|
|
||||||
gmt: 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,
|
|
||||||
gmt: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
read2: {
|
|
||||||
type: 'string',
|
|
||||||
title: `Value`,
|
|
||||||
'x-read-pretty': true,
|
|
||||||
'x-decorator': 'FormItem',
|
|
||||||
'x-component': 'Input',
|
|
||||||
'x-component-props': {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default () => {
|
|
||||||
return (
|
|
||||||
<SchemaComponentProvider components={{ Input, DatePicker, FormItem }}>
|
|
||||||
<SchemaComponent schema={schema} />
|
|
||||||
</SchemaComponentProvider>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,58 +0,0 @@
|
|||||||
/**
|
|
||||||
* title: DatePicker
|
|
||||||
*/
|
|
||||||
import { FormItem } from '@formily/antd-v5';
|
|
||||||
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: false,
|
|
||||||
utc: false,
|
|
||||||
},
|
|
||||||
'x-reactions': {
|
|
||||||
target: '*(read1,read2)',
|
|
||||||
fulfill: {
|
|
||||||
state: {
|
|
||||||
value: '{{$self.value}}',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
read1: {
|
|
||||||
type: 'boolean',
|
|
||||||
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 (
|
|
||||||
<SchemaComponentProvider components={{ Input, DatePicker, FormItem }}>
|
|
||||||
<SchemaComponent schema={schema} />
|
|
||||||
</SchemaComponentProvider>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,68 +0,0 @@
|
|||||||
/**
|
|
||||||
* title: DatePicker.RangePicker
|
|
||||||
*/
|
|
||||||
import { FormItem } from '@formily/antd-v5';
|
|
||||||
import { DatePicker, Input, SchemaComponent, SchemaComponentProvider } from '@nocobase/client';
|
|
||||||
import dayjs from 'dayjs';
|
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
const schema = {
|
|
||||||
type: 'object',
|
|
||||||
properties: {
|
|
||||||
input: {
|
|
||||||
type: 'boolean',
|
|
||||||
title: `Editable`,
|
|
||||||
'x-decorator': 'FormItem',
|
|
||||||
'x-component': 'DatePicker.RangePicker',
|
|
||||||
'x-component-props': {
|
|
||||||
gmt: true,
|
|
||||||
defaultPickerValue: [dayjs('2023-05-01')],
|
|
||||||
},
|
|
||||||
'x-reactions': [
|
|
||||||
{
|
|
||||||
target: 'read1',
|
|
||||||
fulfill: {
|
|
||||||
state: {
|
|
||||||
value: '{{$self.value}}',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
target: 'read2',
|
|
||||||
fulfill: {
|
|
||||||
state: {
|
|
||||||
value: '{{$self.value && $self.value.join(" ~ ")}}',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
read1: {
|
|
||||||
type: 'boolean',
|
|
||||||
title: `Read pretty`,
|
|
||||||
'x-read-pretty': true,
|
|
||||||
'x-decorator': 'FormItem',
|
|
||||||
'x-component': 'DatePicker.RangePicker',
|
|
||||||
'x-component-props': {
|
|
||||||
gmt: true,
|
|
||||||
defaultPickerValue: [dayjs('2023-05-01')],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
read2: {
|
|
||||||
type: 'string',
|
|
||||||
title: `Value`,
|
|
||||||
'x-read-pretty': true,
|
|
||||||
'x-decorator': 'FormItem',
|
|
||||||
'x-component': 'Input',
|
|
||||||
'x-component-props': {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default () => {
|
|
||||||
return (
|
|
||||||
<SchemaComponentProvider components={{ Input, DatePicker, FormItem }}>
|
|
||||||
<SchemaComponent schema={schema} />
|
|
||||||
</SchemaComponentProvider>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,67 +0,0 @@
|
|||||||
/**
|
|
||||||
* title: DatePicker.RangePicker
|
|
||||||
*/
|
|
||||||
import { FormItem } from '@formily/antd-v5';
|
|
||||||
import { DatePicker, Input, SchemaComponent, SchemaComponentProvider } from '@nocobase/client';
|
|
||||||
import dayjs from 'dayjs';
|
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
const schema = {
|
|
||||||
type: 'object',
|
|
||||||
properties: {
|
|
||||||
input: {
|
|
||||||
type: 'boolean',
|
|
||||||
title: `Editable`,
|
|
||||||
'x-decorator': 'FormItem',
|
|
||||||
'x-component': 'DatePicker.RangePicker',
|
|
||||||
'x-component-props': {
|
|
||||||
gmt: false,
|
|
||||||
defaultPickerValue: [dayjs('2023-05-01')],
|
|
||||||
},
|
|
||||||
'x-reactions': [
|
|
||||||
{
|
|
||||||
target: 'read1',
|
|
||||||
fulfill: {
|
|
||||||
state: {
|
|
||||||
value: '{{$self.value}}',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
target: 'read2',
|
|
||||||
fulfill: {
|
|
||||||
state: {
|
|
||||||
value: '{{$self.value && $self.value.join(" ~ ")}}',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
read1: {
|
|
||||||
type: 'boolean',
|
|
||||||
title: `Read pretty`,
|
|
||||||
'x-read-pretty': true,
|
|
||||||
'x-decorator': 'FormItem',
|
|
||||||
'x-component': 'DatePicker.RangePicker',
|
|
||||||
'x-component-props': {
|
|
||||||
defaultPickerValue: [dayjs('2023-05-01')],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
read2: {
|
|
||||||
type: 'string',
|
|
||||||
title: `Value`,
|
|
||||||
'x-read-pretty': true,
|
|
||||||
'x-decorator': 'FormItem',
|
|
||||||
'x-component': 'Input',
|
|
||||||
'x-component-props': {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default () => {
|
|
||||||
return (
|
|
||||||
<SchemaComponentProvider components={{ Input, DatePicker, FormItem }}>
|
|
||||||
<SchemaComponent schema={schema} />
|
|
||||||
</SchemaComponentProvider>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,67 +0,0 @@
|
|||||||
/**
|
|
||||||
* title: DatePicker.RangePicker
|
|
||||||
*/
|
|
||||||
import { FormItem } from '@formily/antd-v5';
|
|
||||||
import { DatePicker, Input, SchemaComponent, SchemaComponentProvider } from '@nocobase/client';
|
|
||||||
import dayjs from 'dayjs';
|
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
const schema = {
|
|
||||||
type: 'object',
|
|
||||||
properties: {
|
|
||||||
input: {
|
|
||||||
type: 'boolean',
|
|
||||||
title: `Editable`,
|
|
||||||
'x-decorator': 'FormItem',
|
|
||||||
'x-component': 'DatePicker.RangePicker',
|
|
||||||
'x-component-props': {
|
|
||||||
utc: false,
|
|
||||||
defaultPickerValue: [dayjs('2023-05-01')],
|
|
||||||
},
|
|
||||||
'x-reactions': [
|
|
||||||
{
|
|
||||||
target: 'read1',
|
|
||||||
fulfill: {
|
|
||||||
state: {
|
|
||||||
value: '{{$self.value}}',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
target: 'read2',
|
|
||||||
fulfill: {
|
|
||||||
state: {
|
|
||||||
value: '{{$self.value && $self.value.join(" ~ ")}}',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
read1: {
|
|
||||||
type: 'boolean',
|
|
||||||
title: `Read pretty`,
|
|
||||||
'x-read-pretty': true,
|
|
||||||
'x-decorator': 'FormItem',
|
|
||||||
'x-component': 'DatePicker.RangePicker',
|
|
||||||
'x-component-props': {
|
|
||||||
defaultPickerValue: [dayjs('2023-05-01')],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
read2: {
|
|
||||||
type: 'string',
|
|
||||||
title: `Value`,
|
|
||||||
'x-read-pretty': true,
|
|
||||||
'x-decorator': 'FormItem',
|
|
||||||
'x-component': 'Input',
|
|
||||||
'x-component-props': {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default () => {
|
|
||||||
return (
|
|
||||||
<SchemaComponentProvider components={{ Input, DatePicker, FormItem }}>
|
|
||||||
<SchemaComponent schema={schema} />
|
|
||||||
</SchemaComponentProvider>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,61 +0,0 @@
|
|||||||
/**
|
|
||||||
* title: DatePicker
|
|
||||||
*/
|
|
||||||
import { FormItem } from '@formily/antd-v5';
|
|
||||||
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: false,
|
|
||||||
gmt: true,
|
|
||||||
utc: true,
|
|
||||||
},
|
|
||||||
'x-reactions': {
|
|
||||||
target: '*(read1,read2)',
|
|
||||||
fulfill: {
|
|
||||||
state: {
|
|
||||||
value: '{{$self.value}}',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
read1: {
|
|
||||||
type: 'boolean',
|
|
||||||
title: `Read pretty`,
|
|
||||||
'x-read-pretty': true,
|
|
||||||
'x-decorator': 'FormItem',
|
|
||||||
'x-component': 'DatePicker',
|
|
||||||
'x-component-props': {
|
|
||||||
dateFormat: 'YYYY/MM/DD',
|
|
||||||
showTime: false,
|
|
||||||
gmt: true,
|
|
||||||
utc: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
read2: {
|
|
||||||
type: 'string',
|
|
||||||
title: `Value`,
|
|
||||||
'x-read-pretty': true,
|
|
||||||
'x-decorator': 'FormItem',
|
|
||||||
'x-component': 'Input',
|
|
||||||
'x-component-props': {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default () => {
|
|
||||||
return (
|
|
||||||
<SchemaComponentProvider components={{ Input, DatePicker, FormItem }}>
|
|
||||||
<SchemaComponent schema={schema} />
|
|
||||||
</SchemaComponentProvider>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,61 +0,0 @@
|
|||||||
/**
|
|
||||||
* title: DatePicker
|
|
||||||
*/
|
|
||||||
import { FormItem } from '@formily/antd-v5';
|
|
||||||
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: false,
|
|
||||||
gmt: false,
|
|
||||||
utc: true,
|
|
||||||
},
|
|
||||||
'x-reactions': {
|
|
||||||
target: '*(read1,read2)',
|
|
||||||
fulfill: {
|
|
||||||
state: {
|
|
||||||
value: '{{$self.value}}',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
read1: {
|
|
||||||
type: 'boolean',
|
|
||||||
title: `Read pretty`,
|
|
||||||
'x-read-pretty': true,
|
|
||||||
'x-decorator': 'FormItem',
|
|
||||||
'x-component': 'DatePicker',
|
|
||||||
'x-component-props': {
|
|
||||||
dateFormat: 'YYYY/MM/DD',
|
|
||||||
showTime: false,
|
|
||||||
gmt: false,
|
|
||||||
utc: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
read2: {
|
|
||||||
type: 'string',
|
|
||||||
title: `Value`,
|
|
||||||
'x-read-pretty': true,
|
|
||||||
'x-decorator': 'FormItem',
|
|
||||||
'x-component': 'Input',
|
|
||||||
'x-component-props': {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default () => {
|
|
||||||
return (
|
|
||||||
<SchemaComponentProvider components={{ Input, DatePicker, FormItem }}>
|
|
||||||
<SchemaComponent schema={schema} />
|
|
||||||
</SchemaComponentProvider>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,61 +0,0 @@
|
|||||||
/**
|
|
||||||
* title: DatePicker
|
|
||||||
*/
|
|
||||||
import { FormItem } from '@formily/antd-v5';
|
|
||||||
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: false,
|
|
||||||
gmt: true,
|
|
||||||
utc: true,
|
|
||||||
},
|
|
||||||
'x-reactions': {
|
|
||||||
target: '*(read1,read2)',
|
|
||||||
fulfill: {
|
|
||||||
state: {
|
|
||||||
value: '{{$self.value}}',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
read1: {
|
|
||||||
type: 'boolean',
|
|
||||||
title: `Read pretty`,
|
|
||||||
'x-read-pretty': true,
|
|
||||||
'x-decorator': 'FormItem',
|
|
||||||
'x-component': 'DatePicker',
|
|
||||||
'x-component-props': {
|
|
||||||
dateFormat: 'YYYY/MM/DD',
|
|
||||||
showTime: false,
|
|
||||||
gmt: true,
|
|
||||||
utc: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
read2: {
|
|
||||||
type: 'string',
|
|
||||||
title: `Value`,
|
|
||||||
'x-read-pretty': true,
|
|
||||||
'x-decorator': 'FormItem',
|
|
||||||
'x-component': 'Input',
|
|
||||||
'x-component-props': {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default () => {
|
|
||||||
return (
|
|
||||||
<SchemaComponentProvider components={{ Input, DatePicker, FormItem }}>
|
|
||||||
<SchemaComponent schema={schema} />
|
|
||||||
</SchemaComponentProvider>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,51 +0,0 @@
|
|||||||
---
|
|
||||||
group:
|
|
||||||
title: Schema Components
|
|
||||||
order: 3
|
|
||||||
---
|
|
||||||
|
|
||||||
# DatePicker
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
### Basic
|
|
||||||
|
|
||||||
<code src="./demos/demo1.tsx"></code>
|
|
||||||
|
|
||||||
### DatePicker (GMT)
|
|
||||||
|
|
||||||
<code src="./demos/demo2.tsx"></code>
|
|
||||||
|
|
||||||
### DatePicker (showTime=false,gmt=true,utc=true)
|
|
||||||
|
|
||||||
<code src="./demos/demo7.tsx"></code>
|
|
||||||
|
|
||||||
|
|
||||||
### DatePicker (showTime=false,gmt=false,utc=true)
|
|
||||||
|
|
||||||
<code src="./demos/demo8.tsx"></code>
|
|
||||||
|
|
||||||
|
|
||||||
### DatePicker (non-UTC)
|
|
||||||
|
|
||||||
<code src="./demos/demo3.tsx"></code>
|
|
||||||
|
|
||||||
### RangePicker (GMT)
|
|
||||||
|
|
||||||
<code src="./demos/demo4.tsx"></code>
|
|
||||||
|
|
||||||
### RangePicker (non-GMT)
|
|
||||||
|
|
||||||
<code src="./demos/demo5.tsx"></code>
|
|
||||||
|
|
||||||
### RangePicker (non-UTC)
|
|
||||||
|
|
||||||
<code src="./demos/demo6.tsx"></code>
|
|
||||||
|
|
||||||
|
|
||||||
## API
|
|
||||||
|
|
||||||
基于 antd 的 [DatePicker](https://ant.design/components/date-picker/#API),新增了以下扩展属性,用于支持 NocoBase 的日期字段设置。
|
|
||||||
|
|
||||||
- `dateFormat` 设置日期格式
|
|
||||||
- `timeFormat` 设置时间格式
|
|
@ -1 +0,0 @@
|
|||||||
export * from './DatePicker';
|
|
@ -1,168 +0,0 @@
|
|||||||
import { getDefaultFormat, str2moment, toGmt, toLocal } from '@nocobase/utils/client';
|
|
||||||
import type { Dayjs } from 'dayjs';
|
|
||||||
import dayjs from 'dayjs';
|
|
||||||
|
|
||||||
const toStringByPicker = (value, picker, timezone: 'gmt' | 'local') => {
|
|
||||||
if (!dayjs.isDayjs(value)) return value;
|
|
||||||
if (timezone === 'local') {
|
|
||||||
const offset = new Date().getTimezoneOffset();
|
|
||||||
return dayjs(toStringByPicker(value, picker, 'gmt'))
|
|
||||||
.add(offset, 'minutes')
|
|
||||||
.toISOString();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (picker === 'year') {
|
|
||||||
return value.format('YYYY') + '-01-01T00:00:00.000Z';
|
|
||||||
}
|
|
||||||
if (picker === 'month') {
|
|
||||||
return value.format('YYYY-MM') + '-01T00:00:00.000Z';
|
|
||||||
}
|
|
||||||
if (picker === 'quarter') {
|
|
||||||
return value.startOf('quarter').format('YYYY-MM') + '-01T00:00:00.000Z';
|
|
||||||
}
|
|
||||||
if (picker === 'week') {
|
|
||||||
return value.startOf('week').add(1, 'day').format('YYYY-MM-DD') + 'T00:00:00.000Z';
|
|
||||||
}
|
|
||||||
return value.format('YYYY-MM-DDTHH:mm:ss.SSS') + 'Z';
|
|
||||||
};
|
|
||||||
|
|
||||||
const toGmtByPicker = (value: Dayjs, picker?: any) => {
|
|
||||||
if (!value || !dayjs.isDayjs(value)) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
return toStringByPicker(value, picker, 'gmt');
|
|
||||||
};
|
|
||||||
|
|
||||||
const toLocalByPicker = (value: Dayjs, picker?: any) => {
|
|
||||||
if (!value || !dayjs.isDayjs(value)) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
return toStringByPicker(value, picker, 'local');
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface Moment2strOptions {
|
|
||||||
showTime?: boolean;
|
|
||||||
gmt?: boolean;
|
|
||||||
utc?: boolean;
|
|
||||||
picker?: 'year' | 'month' | 'week' | 'quarter';
|
|
||||||
}
|
|
||||||
|
|
||||||
export const moment2str = (value?: Dayjs | null, options: Moment2strOptions = {}) => {
|
|
||||||
const { showTime, gmt, picker, utc = true } = options;
|
|
||||||
if (!value) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
if (!utc) {
|
|
||||||
const format = showTime ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD';
|
|
||||||
return value.format(format);
|
|
||||||
}
|
|
||||||
if (showTime) {
|
|
||||||
return gmt ? toGmt(value) : toLocal(value);
|
|
||||||
}
|
|
||||||
if (typeof gmt === 'boolean') {
|
|
||||||
return gmt ? toGmtByPicker(value, picker) : toLocalByPicker(value, picker);
|
|
||||||
}
|
|
||||||
return toGmtByPicker(value, picker);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const mapDatePicker = function () {
|
|
||||||
return (props: any) => {
|
|
||||||
const format = getDefaultFormat(props) as any;
|
|
||||||
const onChange = props.onChange;
|
|
||||||
|
|
||||||
return {
|
|
||||||
...props,
|
|
||||||
format: format,
|
|
||||||
value: str2moment(props.value, props),
|
|
||||||
onChange: (value: Dayjs | null) => {
|
|
||||||
if (onChange) {
|
|
||||||
if (!props.showTime && value) {
|
|
||||||
value = value.startOf('day');
|
|
||||||
}
|
|
||||||
onChange(moment2str(value, props));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const mapRangePicker = function () {
|
|
||||||
return (props: any) => {
|
|
||||||
const format = getDefaultFormat(props) as any;
|
|
||||||
const onChange = props.onChange;
|
|
||||||
|
|
||||||
return {
|
|
||||||
...props,
|
|
||||||
format: format,
|
|
||||||
value: str2moment(props.value, props),
|
|
||||||
onChange: (value: Dayjs[]) => {
|
|
||||||
if (onChange) {
|
|
||||||
onChange(
|
|
||||||
value
|
|
||||||
? [moment2str(getRangeStart(value[0], props), props), moment2str(getRangeEnd(value[1], props), props)]
|
|
||||||
: [],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
} as any;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
function getRangeStart(value: Dayjs, options: Moment2strOptions) {
|
|
||||||
const { showTime } = options;
|
|
||||||
if (showTime) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
return value.startOf('day');
|
|
||||||
}
|
|
||||||
|
|
||||||
function getRangeEnd(value: Dayjs, options: Moment2strOptions) {
|
|
||||||
const { showTime } = options;
|
|
||||||
if (showTime) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
return value.endOf('day');
|
|
||||||
}
|
|
||||||
|
|
||||||
const getStart = (offset: any, unit: any) => {
|
|
||||||
return dayjs()
|
|
||||||
.add(offset, unit === 'isoWeek' ? 'week' : unit)
|
|
||||||
.startOf(unit);
|
|
||||||
};
|
|
||||||
|
|
||||||
const getEnd = (offset: any, unit: any) => {
|
|
||||||
return dayjs()
|
|
||||||
.add(offset, unit === 'isoWeek' ? 'week' : unit)
|
|
||||||
.endOf(unit);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getDateRanges = () => {
|
|
||||||
return {
|
|
||||||
now: () => dayjs().toISOString(),
|
|
||||||
today: () => [getStart(0, 'day'), getEnd(0, 'day')],
|
|
||||||
yesterday: () => [getStart(-1, 'day'), getEnd(-1, 'day')],
|
|
||||||
tomorrow: () => [getStart(1, 'day'), getEnd(1, 'day')],
|
|
||||||
thisWeek: () => [getStart(0, 'isoWeek'), getEnd(0, 'isoWeek')],
|
|
||||||
lastWeek: () => [getStart(-1, 'isoWeek'), getEnd(-1, 'isoWeek')],
|
|
||||||
nextWeek: () => [getStart(1, 'isoWeek'), getEnd(1, 'isoWeek')],
|
|
||||||
year: (year: number) => [getStart(year - dayjs().year(), 'year'), getEnd(year - dayjs().year(), 'year')],
|
|
||||||
thisIsoWeek: () => [getStart(0, 'isoWeek'), getEnd(0, 'isoWeek')],
|
|
||||||
lastIsoWeek: () => [getStart(-1, 'isoWeek'), getEnd(-1, 'isoWeek')],
|
|
||||||
nextIsoWeek: () => [getStart(1, 'isoWeek'), getEnd(1, 'isoWeek')],
|
|
||||||
thisMonth: () => [getStart(0, 'month'), getEnd(0, 'month')],
|
|
||||||
lastMonth: () => [getStart(-1, 'month'), getEnd(-1, 'month')],
|
|
||||||
nextMonth: () => [getStart(1, 'month'), getEnd(1, 'month')],
|
|
||||||
thisQuarter: () => [getStart(0, 'quarter'), getEnd(0, 'quarter')],
|
|
||||||
lastQuarter: () => [getStart(-1, 'quarter'), getEnd(-1, 'quarter')],
|
|
||||||
nextQuarter: () => [getStart(1, 'quarter'), getEnd(1, 'quarter')],
|
|
||||||
thisYear: () => [getStart(0, 'year'), getEnd(0, 'year')],
|
|
||||||
lastYear: () => [getStart(-1, 'year'), getEnd(-1, 'year')],
|
|
||||||
nextYear: () => [getStart(1, 'year'), getEnd(1, 'year')],
|
|
||||||
last7Days: () => [getStart(-6, 'days'), getEnd(0, 'days')],
|
|
||||||
next7Days: () => [getStart(1, 'day'), getEnd(7, 'days')],
|
|
||||||
last30Days: () => [getStart(-29, 'days'), getEnd(0, 'days')],
|
|
||||||
next30Days: () => [getStart(1, 'day'), getEnd(30, 'days')],
|
|
||||||
last90Days: () => [getStart(-89, 'days'), getEnd(0, 'days')],
|
|
||||||
next90Days: () => [getStart(1, 'day'), getEnd(90, 'days')],
|
|
||||||
};
|
|
||||||
};
|
|
@ -1,5 +1,4 @@
|
|||||||
export * from './auto-complete/AutoComplete';
|
export * from './auto-complete/AutoComplete';
|
||||||
export * from './blocks/GroupBlock';
|
export * from './blocks/GroupBlock';
|
||||||
export * from './blocks/PDFViewer';
|
export * from './blocks/PDFViewer';
|
||||||
export * from './date-picker';
|
|
||||||
export * from './deprecated/ExtendedMenuDesigner';
|
export * from './deprecated/ExtendedMenuDesigner';
|
||||||
|
@ -0,0 +1,132 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { ISchema, useFieldSchema } from '@formily/react';
|
||||||
|
import { SchemaSettingsModalItem, useCollectionManager, useDesignable } from '@nocobase/client';
|
||||||
|
import { tval, useTranslation } from '../locale';
|
||||||
|
import { dayjs } from '@nocobase/utils/client';
|
||||||
|
|
||||||
|
export const useCustomPresets1 = () => {
|
||||||
|
const fieldSchema = useFieldSchema();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const rangesValue = getDateRanges();
|
||||||
|
const presets = [
|
||||||
|
{ label: t('This year'), value: rangesValue.thisYear },
|
||||||
|
...Array(5)
|
||||||
|
.fill(0)
|
||||||
|
.map((_, i) => ({ label: dayjs().year() - i - 1 + t('year'), value: rangesValue.year(dayjs().year() - i - 1) })),
|
||||||
|
{ label: t('This month'), value: rangesValue.thisMonth },
|
||||||
|
{ label: t('Last month'), value: rangesValue.lastMonth },
|
||||||
|
];
|
||||||
|
if (fieldSchema.name === 'presets') {
|
||||||
|
return '{{ useCustomPresets1() }}';
|
||||||
|
}
|
||||||
|
return presets;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useCustomPresets = (name: string) => {
|
||||||
|
return '{{ ' + name + '() }}';
|
||||||
|
};
|
||||||
|
|
||||||
|
export const SchemaSettingsDatePresets: React.FC = () => {
|
||||||
|
const fieldSchema = useFieldSchema();
|
||||||
|
const { dn } = useDesignable();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const cm = useCollectionManager();
|
||||||
|
const collectionField = cm.getCollectionField(fieldSchema?.['x-collection-field']) || {};
|
||||||
|
const defaultPresets =
|
||||||
|
fieldSchema?.['x-component-props']?.presets || collectionField?.uiSchema?.['x-component-props']?.presets || '';
|
||||||
|
return (
|
||||||
|
<SchemaSettingsModalItem
|
||||||
|
title={t('Date presets')}
|
||||||
|
schema={
|
||||||
|
{
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
presets: {
|
||||||
|
type: 'string',
|
||||||
|
title: tval('Date presets'),
|
||||||
|
'x-component': 'Select',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
'x-decorator-props': {},
|
||||||
|
default: defaultPresets,
|
||||||
|
enum: [
|
||||||
|
{
|
||||||
|
label: t('default'),
|
||||||
|
value: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('Chuangxing presets'),
|
||||||
|
value: '{{ useCustomPresets("useCustomPresets1") }}',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as ISchema
|
||||||
|
}
|
||||||
|
onSubmit={(data) => {
|
||||||
|
if (!data['presets']) {
|
||||||
|
// 强制清空来达到默认值的效果
|
||||||
|
data['presets'] = undefined;
|
||||||
|
}
|
||||||
|
const schema = {
|
||||||
|
['x-uid']: fieldSchema['x-uid'],
|
||||||
|
};
|
||||||
|
schema['x-component-props'] = fieldSchema['x-component-props'] || {};
|
||||||
|
fieldSchema['x-component-props'] = {
|
||||||
|
...(fieldSchema['x-component-props'] || {}),
|
||||||
|
...data,
|
||||||
|
};
|
||||||
|
schema['x-component-props'] = fieldSchema['x-component-props'];
|
||||||
|
// 这里有意不做直接刷新,直接刷新需要解析 {{ }} 对应的值,待完成后才可以做
|
||||||
|
dn.emit('patch', {
|
||||||
|
schema,
|
||||||
|
});
|
||||||
|
dn.refresh();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
SchemaSettingsDatePresets.displayName = 'SchemaSettingsDatePresets';
|
||||||
|
|
||||||
|
const getDateRanges = () => {
|
||||||
|
return {
|
||||||
|
now: () => dayjs().toISOString(),
|
||||||
|
today: () => [getStart(0, 'day'), getEnd(0, 'day')],
|
||||||
|
yesterday: () => [getStart(-1, 'day'), getEnd(-1, 'day')],
|
||||||
|
tomorrow: () => [getStart(1, 'day'), getEnd(1, 'day')],
|
||||||
|
thisWeek: () => [getStart(0, 'isoWeek'), getEnd(0, 'isoWeek')],
|
||||||
|
lastWeek: () => [getStart(-1, 'isoWeek'), getEnd(-1, 'isoWeek')],
|
||||||
|
nextWeek: () => [getStart(1, 'isoWeek'), getEnd(1, 'isoWeek')],
|
||||||
|
year: (year: number) => [getStart(year - dayjs().year(), 'year'), getEnd(year - dayjs().year(), 'year')],
|
||||||
|
thisIsoWeek: () => [getStart(0, 'isoWeek'), getEnd(0, 'isoWeek')],
|
||||||
|
lastIsoWeek: () => [getStart(-1, 'isoWeek'), getEnd(-1, 'isoWeek')],
|
||||||
|
nextIsoWeek: () => [getStart(1, 'isoWeek'), getEnd(1, 'isoWeek')],
|
||||||
|
thisMonth: () => [getStart(0, 'month'), getEnd(0, 'month')],
|
||||||
|
lastMonth: () => [getStart(-1, 'month'), getEnd(-1, 'month')],
|
||||||
|
nextMonth: () => [getStart(1, 'month'), getEnd(1, 'month')],
|
||||||
|
thisQuarter: () => [getStart(0, 'quarter'), getEnd(0, 'quarter')],
|
||||||
|
lastQuarter: () => [getStart(-1, 'quarter'), getEnd(-1, 'quarter')],
|
||||||
|
nextQuarter: () => [getStart(1, 'quarter'), getEnd(1, 'quarter')],
|
||||||
|
thisYear: () => [getStart(0, 'year'), getEnd(0, 'year')],
|
||||||
|
lastYear: () => [getStart(-1, 'year'), getEnd(-1, 'year')],
|
||||||
|
nextYear: () => [getStart(1, 'year'), getEnd(1, 'year')],
|
||||||
|
last7Days: () => [getStart(-6, 'days'), getEnd(0, 'days')],
|
||||||
|
next7Days: () => [getStart(1, 'day'), getEnd(7, 'days')],
|
||||||
|
last30Days: () => [getStart(-29, 'days'), getEnd(0, 'days')],
|
||||||
|
next30Days: () => [getStart(1, 'day'), getEnd(30, 'days')],
|
||||||
|
last90Days: () => [getStart(-89, 'days'), getEnd(0, 'days')],
|
||||||
|
next90Days: () => [getStart(1, 'day'), getEnd(90, 'days')],
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const getStart = (offset: any, unit: any) => {
|
||||||
|
return dayjs()
|
||||||
|
.add(offset, unit === 'isoWeek' ? 'week' : unit)
|
||||||
|
.startOf(unit);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getEnd = (offset: any, unit: any) => {
|
||||||
|
return dayjs()
|
||||||
|
.add(offset, unit === 'isoWeek' ? 'week' : unit)
|
||||||
|
.endOf(unit);
|
||||||
|
};
|
@ -1,12 +1,14 @@
|
|||||||
{
|
{
|
||||||
"Add custom component": "Add custom component",
|
"Add custom component": "Add custom component",
|
||||||
"Association field": "Association field",
|
"Association field": "Association field",
|
||||||
|
"Chuangxing presets": "Chuangxing presets",
|
||||||
"Configure": "Configure",
|
"Configure": "Configure",
|
||||||
"Custom filter": "Custom filter",
|
"Custom filter": "Custom filter",
|
||||||
"Custom option label": "Custom option label",
|
"Custom option label": "Custom option label",
|
||||||
"Group": "Group",
|
|
||||||
"Group block": "Group block",
|
"Group block": "Group block",
|
||||||
|
"Group": "Group",
|
||||||
"HomePage Config": "HomePage Config",
|
"HomePage Config": "HomePage Config",
|
||||||
|
"Last month": "Last month",
|
||||||
"Mobile UI": "Mobile UI",
|
"Mobile UI": "Mobile UI",
|
||||||
"Navigate to new page": "Navigate to new page",
|
"Navigate to new page": "Navigate to new page",
|
||||||
"Page style": "Page Style",
|
"Page style": "Page Style",
|
||||||
@ -16,10 +18,14 @@
|
|||||||
"Signature input": "Signature input",
|
"Signature input": "Signature input",
|
||||||
"Something went wrong. Please contact the developer to resolve the issue.": "Something went wrong. Please contact the developer to resolve the issue.",
|
"Something went wrong. Please contact the developer to resolve the issue.": "Something went wrong. Please contact the developer to resolve the issue.",
|
||||||
"System setting": "System setting",
|
"System setting": "System setting",
|
||||||
|
"This month": "This month",
|
||||||
|
"This year": "This year",
|
||||||
"classical": "classical",
|
"classical": "classical",
|
||||||
"component": "component",
|
"component": "component",
|
||||||
|
"default": "default",
|
||||||
"error": "error",
|
"error": "error",
|
||||||
"loading...": "loading...",
|
"loading...": "loading...",
|
||||||
"preview block": "preview block",
|
"preview block": "preview block",
|
||||||
"tabs": "tabs"
|
"tabs": "tabs",
|
||||||
|
"year": "year"
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
{
|
{
|
||||||
"Add custom component": "添加自定义组件",
|
"Add custom component": "添加自定义组件",
|
||||||
"Association field": "关联字段",
|
"Association field": "关联字段",
|
||||||
|
"Chuangxing presets": "创兴预置",
|
||||||
"Configure": "配置",
|
"Configure": "配置",
|
||||||
"Custom filter": "自定义筛选",
|
"Custom filter": "自定义筛选",
|
||||||
"Custom option label": "自定义选项标签",
|
"Custom option label": "自定义选项标签",
|
||||||
"Group": "汇总",
|
"Group": "汇总",
|
||||||
"Group block": "汇总区块",
|
"Group block": "汇总区块",
|
||||||
"HomePage Config": "主页配置",
|
"HomePage Config": "主页配置",
|
||||||
|
"Last month": "上月",
|
||||||
"Mobile UI": "移动端页面",
|
"Mobile UI": "移动端页面",
|
||||||
"Navigate to new page": "导航到新页面",
|
"Navigate to new page": "导航到新页面",
|
||||||
"Page style": "页面版本",
|
"Page style": "页面版本",
|
||||||
@ -16,10 +18,14 @@
|
|||||||
"Signature input": "手写签名",
|
"Signature input": "手写签名",
|
||||||
"Something went wrong. Please contact the developer to resolve the issue.": "系统内部错误,请联系开发者解决",
|
"Something went wrong. Please contact the developer to resolve the issue.": "系统内部错误,请联系开发者解决",
|
||||||
"System setting": "系统设置",
|
"System setting": "系统设置",
|
||||||
|
"This month": "本月",
|
||||||
|
"This year": "今年",
|
||||||
"classical": "经典版",
|
"classical": "经典版",
|
||||||
"component": "组件",
|
"component": "组件",
|
||||||
|
"default": "默认",
|
||||||
"error": "出错了",
|
"error": "出错了",
|
||||||
"loading...": "加载中...",
|
"loading...": "加载中...",
|
||||||
"preview block": "预览区块",
|
"preview block": "预览区块",
|
||||||
"tabs": "多标签"
|
"tabs": "多标签",
|
||||||
|
"year": "年"
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user