Skip to content

Commit

Permalink
refactor(datepicker): code clean up
Browse files Browse the repository at this point in the history
  • Loading branch information
Lukeybooi committed Jul 18, 2023
1 parent c3287f7 commit ec58b2f
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 98 deletions.
116 changes: 18 additions & 98 deletions shesha-reactjs/src/designer-components/dateField/dateField.tsx
Original file line number Diff line number Diff line change
@@ -1,70 +1,29 @@
import React, { FC, Fragment } from 'react';
import { IToolboxComponent } from '../../interfaces';
import { FormMarkup, IConfigurableFormComponent } from '../../providers/form/models';
import { CalendarOutlined } from '@ant-design/icons';
import { DatePicker, message } from 'antd';
import moment, { Moment, isMoment } from 'moment';
import React, { FC, Fragment } from 'react';
import ConfigurableFormItem from '../../components/formDesigner/components/formItem';
import settingsFormJson from './settingsForm.json';
import moment, { isMoment, Moment } from 'moment';
import { getStyle, validateConfigurableComponentSettings } from '../../providers/form/utils';
import { customDateEventHandler } from '../../components/formDesigner/components/utils';
import { HiddenFormItem } from '../../components/hiddenFormItem';
import { useForm, useFormData, useGlobalState, useMetaProperties, useSheshaApplication } from '../../providers';
import { DataTypes } from '../../interfaces/dataTypes';
import ReadOnlyDisplayFormItem from '../../components/readOnlyDisplayFormItem';
import { getPropertyMetadata, getMoment } from '../../utils/date';
import { customDateEventHandler } from '../../components/formDesigner/components/utils';
import { axiosHttp } from '../../utils/fetchers';
import { IToolboxComponent } from '../../interfaces';
import { DataTypes } from '../../interfaces/dataTypes';
import { ProperyDataType } from '../../interfaces/metadata';

const DATE_TIME_FORMATS = {
time: 'HH:mm:ss',
week: 'YYYY-wo',
date: 'DD/MM/YYYY',
quarter: 'YYYY-\\QQ',
month: 'YYYY-MM',
year: 'YYYY',
};
import { useForm, useFormData, useGlobalState, useMetaProperties, useSheshaApplication } from '../../providers';
import { FormMarkup } from '../../providers/form/models';
import { getStyle, validateConfigurableComponentSettings } from '../../providers/form/utils';
import { getMoment, getPropertyMetadata } from '../../utils/date';
import { axiosHttp } from '../../utils/fetchers';
import { IDateFieldProps, IRangeInfo, RangePickerChangeEvent, TimePickerChangeEvent } from './interfaces';
import settingsFormJson from './settingsForm.json';
import { DATE_TIME_FORMATS, disabledDate, getFormat, getRangePickerValues } from './utils';

const META_DATA_FILTERS: ProperyDataType[] = ['date', 'date-time', 'time'];

const MIDNIGHT_MOMENT = moment('00:00:00', 'HH:mm:ss');

const { RangePicker } = DatePicker;

type RangeType = 'start' | 'end';

interface IRangeInfo {
range: RangeType;
}

type RangeValue = [moment.Moment, moment.Moment];

type TimePickerChangeEvent = (value: any | null, dateString: string) => void;
type RangePickerChangeEvent = (values: any, formatString: [string, string]) => void;

export interface IDateFieldProps extends IConfigurableFormComponent {
dateFormat?: string;
value?: any;
hideBorder?: boolean;
showTime?: boolean;
showNow?: boolean;
defaultToMidnight?: boolean;
showToday?: boolean;
timeFormat?: string;
yearFormat?: string;
quarterFormat?: string;
monthFormat?: string;
weekFormat?: string;
range?: boolean;
dateOnly?: boolean;
picker?: 'time' | 'date' | 'week' | 'month' | 'quarter' | 'year';
disablePastDates?: boolean;
onChange?: TimePickerChangeEvent | RangePickerChangeEvent;
disabledDateMode?: 'none' | 'functionTemplate' | 'customFunction';
disabledDateTemplate?: string;
disabledDateFunc?: string;
}

const settingsForm = settingsFormJson as FormMarkup;

const DateField: IToolboxComponent<IDateFieldProps> = {
Expand Down Expand Up @@ -156,10 +115,6 @@ export const DatePickerWrapper: FC<IDateFieldProps> = (props) => {

const dateFormat = props?.dateFormat || getPropertyMetadata(properties, name) || DATE_TIME_FORMATS.date;
const timeFormat = props?.timeFormat || DATE_TIME_FORMATS.time;
const yearFormat = props?.yearFormat || DATE_TIME_FORMATS.year;
const quarterFormat = props?.quarterFormat || DATE_TIME_FORMATS.quarter;
const monthFormat = props?.monthFormat || DATE_TIME_FORMATS.month;
const weekFormat = props?.weekFormat || DATE_TIME_FORMATS.week;

const defaultFormat = dateOnly ? 'YYYY-MM-DD' : null;

Expand All @@ -169,34 +124,10 @@ export const DatePickerWrapper: FC<IDateFieldProps> = (props) => {

const isReadOnly = readOnly || formMode === 'readonly';

const getFormat = () => {
switch (picker) {
case 'date':
return showTime ? `${dateFormat} ${timeFormat}` : dateFormat;
case 'year':
return yearFormat;
case 'month':
return monthFormat;
case 'quarter':
return quarterFormat;
case 'time':
return timeFormat;
case 'week':
return weekFormat;
default:
return dateFormat;
}
};

const pickerFormat = getFormat();
const pickerFormat = getFormat(props, properties);

const formattedValue = getMoment(value, pickerFormat);

const getRangePickerValues = (valueToUse: any) =>
(Array.isArray(valueToUse) && valueToUse?.length === 2
? valueToUse?.map((v) => moment(new Date(v), pickerFormat))
: [null, null]) as RangeValue;

const handleDatePickerChange = (localValue: any | null, dateString: string) => {
if (!dateString?.trim()) {
(onChange as TimePickerChangeEvent)(null, '');
Expand Down Expand Up @@ -235,17 +166,6 @@ export const DatePickerWrapper: FC<IDateFieldProps> = (props) => {
}
};

function disabledDate(current) {
if (disabledDateMode === 'none') return false;

const disabledTimeExpression = disabledDateMode === 'functionTemplate' ? disabledDateTemplate : disabledDateFunc;

// tslint:disable-next-line:function-constructor
const disabledFunc = new Function('current', 'moment', disabledTimeExpression);

return disabledFunc(current, moment);
}

if (isReadOnly) {
const format = `${dateFormat}${showTime ? timeFormat : ''}`;

Expand All @@ -264,12 +184,12 @@ export const DatePickerWrapper: FC<IDateFieldProps> = (props) => {
return (
<RangePicker
className="sha-range-picker"
disabledDate={disabledDate}
disabledDate={(e) => disabledDate(props, e)}
onCalendarChange={onCalendarChange}
onChange={handleRangePicker}
format={pickerFormat}
value={getRangePickerValues(value)}
defaultValue={getRangePickerValues(defaultValue)}
value={getRangePickerValues(value, pickerFormat)}
defaultValue={getRangePickerValues(defaultValue, pickerFormat)}
{...rest}
picker={picker}
showTime={showTime ? (defaultToMidnight ? { defaultValue: [MIDNIGHT_MOMENT, MIDNIGHT_MOMENT] } : true) : false}
Expand All @@ -285,7 +205,7 @@ export const DatePickerWrapper: FC<IDateFieldProps> = (props) => {
<DatePicker
className="sha-date-picker"
value={formattedValue}
disabledDate={disabledDate}
disabledDate={(e) => disabledDate(props, e)}
disabled={isDisabled}
onChange={handleDatePickerChange}
bordered={!hideBorder}
Expand Down
35 changes: 35 additions & 0 deletions shesha-reactjs/src/designer-components/dateField/interfaces.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { IConfigurableFormComponent } from '../../providers/form/models';

export type RangeType = 'start' | 'end';

export interface IRangeInfo {
range: RangeType;
}

export type RangeValue = [moment.Moment, moment.Moment];

export type TimePickerChangeEvent = (value: any | null, dateString: string) => void;
export type RangePickerChangeEvent = (values: any, formatString: [string, string]) => void;

export interface IDateFieldProps extends IConfigurableFormComponent {
dateFormat?: string;
value?: any;
hideBorder?: boolean;
showTime?: boolean;
showNow?: boolean;
defaultToMidnight?: boolean;
showToday?: boolean;
timeFormat?: string;
yearFormat?: string;
quarterFormat?: string;
monthFormat?: string;
weekFormat?: string;
range?: boolean;
dateOnly?: boolean;
picker?: 'time' | 'date' | 'week' | 'month' | 'quarter' | 'year';
disablePastDates?: boolean;
onChange?: TimePickerChangeEvent | RangePickerChangeEvent;
disabledDateMode?: 'none' | 'functionTemplate' | 'customFunction';
disabledDateTemplate?: string;
disabledDateFunc?: string;
}
59 changes: 59 additions & 0 deletions shesha-reactjs/src/designer-components/dateField/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { IPropertyMetadata } from 'interfaces/metadata';
import { getPropertyMetadata } from '../../utils/date';
import { IDateFieldProps, RangeValue } from './interfaces';
import moment from 'moment';

export const DATE_TIME_FORMATS = {
time: 'HH:mm:ss',
week: 'YYYY-wo',
date: 'DD/MM/YYYY',
quarter: 'YYYY-\\QQ',
month: 'YYYY-MM',
year: 'YYYY',
};

export function disabledDate(props: IDateFieldProps, current) {
const { disabledDateMode, disabledDateTemplate, disabledDateFunc } = props;

if (disabledDateMode === 'none') return false;

const disabledTimeExpression = disabledDateMode === 'functionTemplate' ? disabledDateTemplate : disabledDateFunc;

// tslint:disable-next-line:function-constructor
const disabledFunc = new Function('current', 'moment', disabledTimeExpression);

return disabledFunc(current, moment);
}

export const getFormat = (props: IDateFieldProps, properties: IPropertyMetadata[]) => {
const { name, picker, showTime } = props || {};

const dateFormat = props?.dateFormat || getPropertyMetadata(properties, name) || DATE_TIME_FORMATS.date;
const timeFormat = props?.timeFormat || DATE_TIME_FORMATS.time;
const yearFormat = props?.yearFormat || DATE_TIME_FORMATS.year;
const quarterFormat = props?.quarterFormat || DATE_TIME_FORMATS.quarter;
const monthFormat = props?.monthFormat || DATE_TIME_FORMATS.month;
const weekFormat = props?.weekFormat || DATE_TIME_FORMATS.week;

switch (picker) {
case 'date':
return showTime ? `${dateFormat} ${timeFormat}` : dateFormat;
case 'year':
return yearFormat;
case 'month':
return monthFormat;
case 'quarter':
return quarterFormat;
case 'time':
return timeFormat;
case 'week':
return weekFormat;
default:
return dateFormat;
}
};

export const getRangePickerValues = (valueToUse: any, pickerFormat: string) =>
(Array.isArray(valueToUse) && valueToUse?.length === 2
? valueToUse?.map((v) => moment(new Date(v), pickerFormat))
: [null, null]) as RangeValue;

0 comments on commit ec58b2f

Please sign in to comment.