mirror of
https://gitee.com/baidu/amis.git
synced 2024-11-29 18:48:45 +08:00
同步1.2版本的时间范围选择改动 (#2183)
This commit is contained in:
parent
fc2f792bbd
commit
927e8107b3
@ -45,6 +45,7 @@ export interface DateRangePickerProps extends ThemeProps, LocaleProps {
|
||||
popOverContainer?: any;
|
||||
dateFormat?: string;
|
||||
embed?: boolean;
|
||||
viewMode?: 'days' | 'months' | 'years' | 'time' | 'quarters';
|
||||
}
|
||||
|
||||
export interface DateRangePickerState {
|
||||
@ -54,7 +55,7 @@ export interface DateRangePickerState {
|
||||
endDate?: moment.Moment;
|
||||
}
|
||||
|
||||
const availableRanges: {[propName: string]: any} = {
|
||||
export const availableRanges: {[propName: string]: any} = {
|
||||
'today': {
|
||||
label: 'Date.today',
|
||||
startDate: (now: moment.Moment) => {
|
||||
@ -262,6 +263,7 @@ export class DateRangePicker extends React.Component<
|
||||
this.handleKeyPress = this.handleKeyPress.bind(this);
|
||||
this.handlePopOverClick = this.handlePopOverClick.bind(this);
|
||||
this.renderDay = this.renderDay.bind(this);
|
||||
this.renderQuarter = this.renderQuarter.bind(this);
|
||||
const {format, joinValues, delimiter, value} = this.props;
|
||||
|
||||
this.state = {
|
||||
@ -271,11 +273,11 @@ export class DateRangePicker extends React.Component<
|
||||
};
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps: DateRangePickerProps) {
|
||||
componentDidUpdate(prevProps: DateRangePickerProps) {
|
||||
const props = this.props;
|
||||
const {value, format, joinValues, delimiter} = nextProps;
|
||||
const {value, format, joinValues, delimiter} = props;
|
||||
|
||||
if (props.value !== value) {
|
||||
if (prevProps.value !== value) {
|
||||
this.setState({
|
||||
...DateRangePicker.unFormatValue(value, format, joinValues, delimiter)
|
||||
});
|
||||
@ -384,6 +386,8 @@ export class DateRangePicker extends React.Component<
|
||||
value = value[type === 'start' ? 'startOf' : 'endOf']('minute');
|
||||
} else if (typeof timeFormat === 'string' && /HH/i.test(timeFormat)) {
|
||||
value = value[type === 'start' ? 'startOf' : 'endOf']('hour');
|
||||
} else if (typeof timeFormat === 'string' && /Q/i.test(timeFormat)) {
|
||||
value = value[type === 'start' ? 'startOf' : 'endOf']('quarter');
|
||||
} else {
|
||||
value = value[type === 'start' ? 'startOf' : 'endOf']('day');
|
||||
}
|
||||
@ -527,8 +531,8 @@ export class DateRangePicker extends React.Component<
|
||||
|
||||
checkStartIsValidDate(currentDate: moment.Moment) {
|
||||
let {endDate, startDate} = this.state;
|
||||
|
||||
let {minDate, maxDate, minDuration, maxDuration} = this.props;
|
||||
let {minDate, maxDate, minDuration, maxDuration, viewMode} = this.props;
|
||||
const precision = viewMode === 'time' ? 'hours' : viewMode || 'day';
|
||||
|
||||
maxDate =
|
||||
maxDate && endDate
|
||||
@ -537,9 +541,9 @@ export class DateRangePicker extends React.Component<
|
||||
: endDate
|
||||
: maxDate || endDate;
|
||||
|
||||
if (minDate && currentDate.isBefore(minDate, 'day')) {
|
||||
if (minDate && currentDate.isBefore(minDate, precision)) {
|
||||
return false;
|
||||
} else if (maxDate && currentDate.isAfter(maxDate, 'day')) {
|
||||
} else if (maxDate && currentDate.isAfter(maxDate, precision)) {
|
||||
return false;
|
||||
} else if (
|
||||
// 如果配置了 minDuration 那么 EndDate - minDuration 之后的天数也不能选
|
||||
@ -561,8 +565,8 @@ export class DateRangePicker extends React.Component<
|
||||
|
||||
checkEndIsValidDate(currentDate: moment.Moment) {
|
||||
let {startDate} = this.state;
|
||||
|
||||
let {minDate, maxDate, minDuration, maxDuration} = this.props;
|
||||
let {minDate, maxDate, minDuration, maxDuration, viewMode} = this.props;
|
||||
const precision = viewMode === 'time' ? 'hours' : viewMode || 'day';
|
||||
|
||||
minDate =
|
||||
minDate && startDate
|
||||
@ -571,9 +575,9 @@ export class DateRangePicker extends React.Component<
|
||||
: startDate
|
||||
: minDate || startDate;
|
||||
|
||||
if (minDate && currentDate.isBefore(minDate, 'day')) {
|
||||
if (minDate && currentDate.isBefore(minDate, precision)) {
|
||||
return false;
|
||||
} else if (maxDate && currentDate.isAfter(maxDate, 'day')) {
|
||||
} else if (maxDate && currentDate.isAfter(maxDate, precision)) {
|
||||
return false;
|
||||
} else if (
|
||||
startDate &&
|
||||
@ -606,18 +610,38 @@ export class DateRangePicker extends React.Component<
|
||||
return <td {...props}>{currentDate.date()}</td>;
|
||||
}
|
||||
|
||||
renderQuarter(props: any, quarter: number, year: number) {
|
||||
const currentDate = moment().year(year).quarter(quarter);
|
||||
const {startDate, endDate} = this.state;
|
||||
|
||||
if (
|
||||
startDate &&
|
||||
endDate &&
|
||||
currentDate.isBetween(startDate, endDate, 'quarter', '[]')
|
||||
) {
|
||||
props.className += ' rdtBetween';
|
||||
}
|
||||
|
||||
return (
|
||||
<td {...props}>
|
||||
<span>Q{quarter}</span>
|
||||
</td>
|
||||
);
|
||||
}
|
||||
|
||||
renderCalendar() {
|
||||
const {
|
||||
classPrefix: ns,
|
||||
classnames: cx,
|
||||
dateFormat,
|
||||
timeFormat,
|
||||
inputFormat,
|
||||
ranges,
|
||||
locale,
|
||||
embed
|
||||
embed,
|
||||
viewMode = 'days'
|
||||
} = this.props;
|
||||
const __ = this.props.translate;
|
||||
let viewMode: 'days' | 'months' | 'years' | 'time' = 'days';
|
||||
|
||||
const {startDate, endDate} = this.state;
|
||||
return (
|
||||
@ -630,12 +654,14 @@ export class DateRangePicker extends React.Component<
|
||||
onChange={this.handleStartChange}
|
||||
requiredConfirm={false}
|
||||
dateFormat={dateFormat}
|
||||
inputFormat={inputFormat}
|
||||
timeFormat={timeFormat}
|
||||
isValidDate={this.checkStartIsValidDate}
|
||||
viewMode={viewMode}
|
||||
input={false}
|
||||
onClose={this.close}
|
||||
renderDay={this.renderDay}
|
||||
renderQuarter={this.renderQuarter}
|
||||
locale={locale}
|
||||
/>
|
||||
|
||||
@ -645,6 +671,7 @@ export class DateRangePicker extends React.Component<
|
||||
onChange={this.handleEndChange}
|
||||
requiredConfirm={false}
|
||||
dateFormat={dateFormat}
|
||||
inputFormat={inputFormat}
|
||||
timeFormat={timeFormat}
|
||||
viewDate={this.nextMonth}
|
||||
isEndDate
|
||||
@ -653,6 +680,7 @@ export class DateRangePicker extends React.Component<
|
||||
input={false}
|
||||
onClose={this.close}
|
||||
renderDay={this.renderDay}
|
||||
renderQuarter={this.renderQuarter}
|
||||
locale={locale}
|
||||
/>
|
||||
|
||||
|
@ -18,6 +18,8 @@ import {noop} from '../utils/helper';
|
||||
import {LocaleProps, localeable} from '../locale';
|
||||
import {DateRangePicker} from './DateRangePicker';
|
||||
import capitalize from 'lodash/capitalize';
|
||||
import {ShortCuts, ShortCutDateRange} from './DatePicker';
|
||||
import {availableRanges} from './DateRangePicker';
|
||||
|
||||
export interface MonthRangePickerProps extends ThemeProps, LocaleProps {
|
||||
className?: string;
|
||||
@ -27,7 +29,8 @@ export interface MonthRangePickerProps extends ThemeProps, LocaleProps {
|
||||
format: string;
|
||||
utc?: boolean;
|
||||
inputFormat?: string;
|
||||
// ranges?: string | Array<ShortCuts>;
|
||||
timeFormat?: string;
|
||||
ranges?: string | Array<ShortCuts>;
|
||||
clearable?: boolean;
|
||||
minDate?: moment.Moment;
|
||||
maxDate?: moment.Moment;
|
||||
@ -103,11 +106,11 @@ export class MonthRangePicker extends React.Component<
|
||||
};
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps: MonthRangePickerProps) {
|
||||
componentDidUpdate(prevProps: MonthRangePickerProps) {
|
||||
const props = this.props;
|
||||
const {value, format, joinValues, delimiter} = nextProps;
|
||||
const {value, format, joinValues, delimiter} = props;
|
||||
|
||||
if (props.value !== value) {
|
||||
if (prevProps.value !== value) {
|
||||
this.setState({
|
||||
...DateRangePicker.unFormatValue(value, format, joinValues, delimiter)
|
||||
});
|
||||
@ -275,6 +278,68 @@ export class MonthRangePicker extends React.Component<
|
||||
);
|
||||
}
|
||||
|
||||
selectRannge(range: PlainObject) {
|
||||
const {closeOnSelect, minDate, maxDate} = this.props;
|
||||
this.setState(
|
||||
{
|
||||
startDate: minDate
|
||||
? moment.max(range.startDate(moment()), minDate)
|
||||
: range.startDate(moment()),
|
||||
endDate: maxDate
|
||||
? moment.min(maxDate, range.endDate(moment()))
|
||||
: range.endDate(moment())
|
||||
},
|
||||
closeOnSelect ? this.confirm : noop
|
||||
);
|
||||
}
|
||||
|
||||
renderRanges(ranges: string | Array<ShortCuts> | undefined) {
|
||||
if (!ranges) {
|
||||
return null;
|
||||
}
|
||||
const {classPrefix: ns} = this.props;
|
||||
let rangeArr: Array<string | ShortCuts>;
|
||||
if (typeof ranges === 'string') {
|
||||
rangeArr = ranges.split(',');
|
||||
} else {
|
||||
rangeArr = ranges;
|
||||
}
|
||||
const __ = this.props.translate;
|
||||
|
||||
return (
|
||||
<ul className={`${ns}DateRangePicker-rangers`}>
|
||||
{rangeArr.map(item => {
|
||||
if (!item) {
|
||||
return null;
|
||||
}
|
||||
let range: PlainObject = {};
|
||||
if (typeof item === 'string') {
|
||||
range = availableRanges[item];
|
||||
range.key = item;
|
||||
} else if (
|
||||
(item as ShortCutDateRange).startDate &&
|
||||
(item as ShortCutDateRange).endDate
|
||||
) {
|
||||
range = {
|
||||
...item,
|
||||
startDate: () => (item as ShortCutDateRange).startDate,
|
||||
endDate: () => (item as ShortCutDateRange).endDate
|
||||
};
|
||||
}
|
||||
return (
|
||||
<li
|
||||
className={`${ns}DateRangePicker-ranger`}
|
||||
onClick={() => this.selectRannge(range)}
|
||||
key={range.key || range.label}
|
||||
>
|
||||
<a>{__(range.label)}</a>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
|
||||
clearValue(e: React.MouseEvent<any>) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
@ -375,7 +440,7 @@ export class MonthRangePicker extends React.Component<
|
||||
}
|
||||
|
||||
renderCalendar() {
|
||||
const {classPrefix: ns, classnames: cx, locale, embed} = this.props;
|
||||
const {classPrefix: ns, classnames: cx, locale, embed, ranges, inputFormat, timeFormat} = this.props;
|
||||
const __ = this.props.translate;
|
||||
const viewMode: 'months' = 'months';
|
||||
const dateFormat = 'YYYY-MM';
|
||||
@ -383,12 +448,15 @@ export class MonthRangePicker extends React.Component<
|
||||
|
||||
return (
|
||||
<div className={`${ns}DateRangePicker-wrap`}>
|
||||
{this.renderRanges(ranges)}
|
||||
<Calendar
|
||||
className={`${ns}DateRangePicker-start`}
|
||||
value={startDate}
|
||||
onChange={this.handleStartChange}
|
||||
requiredConfirm={false}
|
||||
dateFormat={dateFormat}
|
||||
inputFormat={inputFormat}
|
||||
timeFormat={timeFormat}
|
||||
isValidDate={this.checkStartIsValidDate}
|
||||
viewMode={viewMode}
|
||||
input={false}
|
||||
@ -406,6 +474,8 @@ export class MonthRangePicker extends React.Component<
|
||||
onChange={this.handleEndChange}
|
||||
requiredConfirm={false}
|
||||
dateFormat={dateFormat}
|
||||
inputFormat={inputFormat}
|
||||
timeFormat={timeFormat}
|
||||
viewDate={this.nextMonth}
|
||||
isEndDate
|
||||
isValidDate={this.checkEndIsValidDate}
|
||||
|
@ -21,6 +21,12 @@ interface BaseDatePickerProps
|
||||
currentDate: moment.Moment,
|
||||
selectedDate: moment.Moment
|
||||
) => JSX.Element;
|
||||
renderQuarter?: (
|
||||
props: any,
|
||||
quartar: number,
|
||||
year?: number,
|
||||
date?: moment.Moment
|
||||
) => JSX.Element;
|
||||
}
|
||||
|
||||
class BaseDatePicker extends ReactDatePicker {
|
||||
@ -106,7 +112,7 @@ class BaseDatePicker extends ReactDatePicker {
|
||||
.startOf(type),
|
||||
currentView: nextViews[type]
|
||||
});
|
||||
this.props.onViewModeChange!(nextViews[type]);
|
||||
this.props.onViewModeChange?.(nextViews[type]);
|
||||
};
|
||||
};
|
||||
|
||||
@ -135,6 +141,7 @@ class BaseDatePicker extends ReactDatePicker {
|
||||
date = viewDate
|
||||
.clone()
|
||||
.quarter(parseInt(target.getAttribute('data-value')!, 10))
|
||||
.startOf('quarter')
|
||||
.date(currentDate.date());
|
||||
} else if (target.className.indexOf('rdtYear') !== -1) {
|
||||
date = viewDate
|
||||
@ -173,12 +180,18 @@ class BaseDatePicker extends ReactDatePicker {
|
||||
|
||||
render() {
|
||||
const Component = CustomCalendarContainer as any;
|
||||
const viewProps = this.getComponentProps();
|
||||
|
||||
if (this.props.viewMode === 'quarters') {
|
||||
[viewProps.updateOn, viewProps.renderQuarter] = ['quarters', this.props.renderQuarter];
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={cx('rdt rdtStatic rdtOpen', this.props.className)}>
|
||||
<div key="dt" className="rdtPicker">
|
||||
<Component
|
||||
view={this.state.currentView}
|
||||
viewProps={this.getComponentProps()}
|
||||
viewProps={viewProps}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,3 +1,4 @@
|
||||
import moment from 'moment';
|
||||
import React from 'react';
|
||||
import {localeable, LocaleProps} from '../../locale';
|
||||
import {ThemeProps} from '../../theme';
|
||||
@ -21,12 +22,10 @@ export interface QuarterViewProps extends LocaleProps, ThemeProps {
|
||||
showView: (view: string) => () => void;
|
||||
updateSelectedDate: (e: any, close?: boolean) => void;
|
||||
renderQuarter: any;
|
||||
isValidDate: any;
|
||||
isValidDate: (date: moment.Moment) => boolean;
|
||||
}
|
||||
|
||||
export class QuarterView extends React.Component<QuarterViewProps> {
|
||||
alwaysValidDate: any;
|
||||
|
||||
renderYear() {
|
||||
const __ = this.props.translate;
|
||||
const showYearHead = !/^mm$/i.test(this.props.inputFormat || '');
|
||||
@ -67,47 +66,24 @@ export class QuarterView extends React.Component<QuarterViewProps> {
|
||||
}
|
||||
renderQuarters() {
|
||||
let date = this.props.selectedDate,
|
||||
month = this.props.viewDate.month(),
|
||||
quarter = this.props.viewDate.quarter(),
|
||||
year = this.props.viewDate.year(),
|
||||
rows = [],
|
||||
i = 1,
|
||||
months = [],
|
||||
quarters = [],
|
||||
renderer = this.props.renderQuarter || this.renderQuarter,
|
||||
isValid = this.props.isValidDate || this.alwaysValidDate,
|
||||
classes,
|
||||
props: any,
|
||||
currentMonth: moment.Moment,
|
||||
isDisabled,
|
||||
noOfDaysInMonth,
|
||||
daysInMonth,
|
||||
validDay,
|
||||
// Date is irrelevant because we're only interested in month
|
||||
irrelevantDate = 1;
|
||||
isDisabled;
|
||||
|
||||
while (i < 5) {
|
||||
classes = 'rdtQuarter';
|
||||
currentMonth = this.props.viewDate
|
||||
.clone()
|
||||
.set({year: year, quarter: i, date: irrelevantDate});
|
||||
|
||||
noOfDaysInMonth = currentMonth.endOf('quarter').format('Q');
|
||||
daysInMonth = Array.from(
|
||||
{length: parseInt(noOfDaysInMonth, 10)},
|
||||
function (e, i) {
|
||||
return i + 1;
|
||||
}
|
||||
);
|
||||
|
||||
validDay = daysInMonth.find(function (d) {
|
||||
var day = currentMonth.clone().set('date', d);
|
||||
return isValid(day);
|
||||
});
|
||||
|
||||
isDisabled = validDay === undefined;
|
||||
isDisabled = !isValid(moment(`${year}-${i}`, 'YYYY-Q'));
|
||||
|
||||
if (isDisabled) classes += ' rdtDisabled';
|
||||
|
||||
if (date && i === date.quarter() && year === date.year())
|
||||
classes += ' rdtActive';
|
||||
if (date && i === date.quarter() && year === date.year()) classes += ' rdtActive';
|
||||
|
||||
props = {
|
||||
'key': i,
|
||||
@ -122,13 +98,13 @@ export class QuarterView extends React.Component<QuarterViewProps> {
|
||||
: this.props.setDate('quarter');
|
||||
}
|
||||
|
||||
months.push(renderer(props, i, year, date && date.clone()));
|
||||
quarters.push(renderer(props, i, year, date && date.clone()));
|
||||
|
||||
if (months.length === 2) {
|
||||
if (quarters.length === 2) {
|
||||
rows.push(
|
||||
React.createElement('tr', {key: month + '_' + rows.length}, months)
|
||||
React.createElement('tr', {key: quarter + '_' + rows.length}, quarters)
|
||||
);
|
||||
months = [];
|
||||
quarters = [];
|
||||
}
|
||||
|
||||
i++;
|
||||
@ -154,6 +130,10 @@ export class QuarterView extends React.Component<QuarterViewProps> {
|
||||
this.props.updateSelectedDate(event);
|
||||
};
|
||||
|
||||
alwaysValidDate() {
|
||||
return true;
|
||||
}
|
||||
|
||||
render() {
|
||||
const {classnames: cx} = this.props;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user