2020-01-21 12:48:42 +00:00
|
|
|
import React from "react";
|
|
|
|
|
import styled from "styled-components";
|
2020-01-28 08:21:22 +00:00
|
|
|
import { labelStyle } from "constants/DefaultTheme";
|
2020-01-21 12:48:42 +00:00
|
|
|
import { ControlGroup, Classes, Label } from "@blueprintjs/core";
|
2019-11-25 05:07:27 +00:00
|
|
|
import { ComponentProps } from "components/designSystems/appsmith/BaseComponent";
|
2021-02-03 11:30:19 +00:00
|
|
|
import { DateInput } from "@blueprintjs/datetime";
|
2019-11-06 12:12:41 +00:00
|
|
|
import moment from "moment-timezone";
|
|
|
|
|
import "../../../../node_modules/@blueprintjs/datetime/lib/css/blueprint-datetime.css";
|
2019-11-25 05:07:27 +00:00
|
|
|
import { DatePickerType } from "widgets/DatePickerWidget";
|
2020-01-21 12:48:42 +00:00
|
|
|
import { WIDGET_PADDING } from "constants/WidgetConstants";
|
2020-04-15 11:42:11 +00:00
|
|
|
import { TimePrecision } from "@blueprintjs/datetime";
|
2020-03-13 07:24:03 +00:00
|
|
|
import { Colors } from "constants/Colors";
|
2021-02-02 14:42:49 +00:00
|
|
|
import { ISO_DATE_FORMAT } from "constants/WidgetValidation";
|
2019-11-06 12:12:41 +00:00
|
|
|
|
2020-01-21 12:48:42 +00:00
|
|
|
const StyledControlGroup = styled(ControlGroup)`
|
|
|
|
|
&&& {
|
2020-03-13 07:24:03 +00:00
|
|
|
.${Classes.INPUT} {
|
|
|
|
|
box-shadow: none;
|
|
|
|
|
border: 1px solid;
|
|
|
|
|
border-color: ${Colors.GEYSER_LIGHT};
|
2020-12-24 04:32:25 +00:00
|
|
|
border-radius: ${(props) => props.theme.radii[1]}px;
|
2020-03-13 07:24:03 +00:00
|
|
|
width: 100%;
|
|
|
|
|
height: inherit;
|
|
|
|
|
align-items: center;
|
|
|
|
|
&:active {
|
|
|
|
|
border-color: ${Colors.HIT_GRAY};
|
|
|
|
|
}
|
|
|
|
|
&:focus {
|
|
|
|
|
border-color: ${Colors.MYSTIC};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
.${Classes.INPUT_GROUP} {
|
|
|
|
|
display: block;
|
|
|
|
|
margin: 0;
|
|
|
|
|
}
|
|
|
|
|
.${Classes.CONTROL_GROUP} {
|
|
|
|
|
justify-content: flex-start;
|
|
|
|
|
}
|
2020-01-21 12:48:42 +00:00
|
|
|
label {
|
2020-01-28 08:21:22 +00:00
|
|
|
${labelStyle}
|
2020-01-21 12:48:42 +00:00
|
|
|
flex: 0 1 30%;
|
2020-03-13 07:24:03 +00:00
|
|
|
margin: 7px ${WIDGET_PADDING * 2}px 0 0;
|
2020-01-21 12:48:42 +00:00
|
|
|
text-align: right;
|
2020-03-13 07:24:03 +00:00
|
|
|
align-self: flex-start;
|
|
|
|
|
max-width: calc(30% - ${WIDGET_PADDING}px);
|
2020-01-21 12:48:42 +00:00
|
|
|
}
|
|
|
|
|
}
|
2020-03-20 11:03:50 +00:00
|
|
|
&&& {
|
|
|
|
|
input {
|
2020-04-15 11:42:11 +00:00
|
|
|
border: 1px solid ${Colors.HIT_GRAY};
|
2020-12-24 04:32:25 +00:00
|
|
|
border-radius: ${(props) => props.theme.radii[1]}px;
|
2020-03-20 11:03:50 +00:00
|
|
|
box-shadow: none;
|
2020-04-15 11:42:11 +00:00
|
|
|
color: ${Colors.OXFORD_BLUE};
|
2020-12-24 04:32:25 +00:00
|
|
|
font-size: ${(props) => props.theme.fontSizes[3]}px;
|
2020-03-20 11:03:50 +00:00
|
|
|
}
|
|
|
|
|
}
|
2020-01-21 12:48:42 +00:00
|
|
|
`;
|
2020-03-20 11:03:50 +00:00
|
|
|
|
2020-04-29 10:29:02 +00:00
|
|
|
class DatePickerComponent extends React.Component<
|
|
|
|
|
DatePickerComponentProps,
|
|
|
|
|
DatePickerComponentState
|
|
|
|
|
> {
|
|
|
|
|
constructor(props: DatePickerComponentProps) {
|
|
|
|
|
super(props);
|
|
|
|
|
this.state = {
|
|
|
|
|
selectedDate: props.selectedDate,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
componentDidUpdate(prevProps: DatePickerComponentProps) {
|
2021-02-02 14:42:49 +00:00
|
|
|
const dateFormat = this.props.dateFormat || ISO_DATE_FORMAT;
|
2020-04-29 10:29:02 +00:00
|
|
|
if (
|
2020-05-14 14:00:22 +00:00
|
|
|
this.props.selectedDate !== this.state.selectedDate &&
|
2021-02-02 14:42:49 +00:00
|
|
|
!moment(this.props.selectedDate, dateFormat).isSame(
|
|
|
|
|
moment(prevProps.selectedDate, dateFormat),
|
2020-04-29 10:29:02 +00:00
|
|
|
"seconds",
|
|
|
|
|
)
|
|
|
|
|
) {
|
|
|
|
|
this.setState({ selectedDate: this.props.selectedDate });
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-02-03 11:30:19 +00:00
|
|
|
getValidDate = (date: string, format: string) => {
|
|
|
|
|
const _date = moment(date, format);
|
|
|
|
|
return _date.isValid() ? _date.toDate() : undefined;
|
|
|
|
|
};
|
2020-04-29 10:29:02 +00:00
|
|
|
|
2019-11-06 12:12:41 +00:00
|
|
|
render() {
|
2020-04-15 11:42:11 +00:00
|
|
|
const now = moment();
|
|
|
|
|
const year = now.get("year");
|
2021-02-02 14:42:49 +00:00
|
|
|
const dateFormat = this.props.dateFormat || ISO_DATE_FORMAT;
|
2020-11-27 08:48:38 +00:00
|
|
|
const minDate = this.props.minDate
|
2021-02-03 11:30:19 +00:00
|
|
|
? this.getValidDate(this.props.minDate, dateFormat)
|
|
|
|
|
: now
|
|
|
|
|
.clone()
|
|
|
|
|
.set({ month: 0, date: 1, year: year - 100 })
|
|
|
|
|
.toDate();
|
2020-11-27 08:48:38 +00:00
|
|
|
const maxDate = this.props.maxDate
|
2021-02-03 11:30:19 +00:00
|
|
|
? this.getValidDate(this.props.maxDate, dateFormat)
|
|
|
|
|
: now
|
|
|
|
|
.clone()
|
|
|
|
|
.set({ month: 11, date: 31, year: year + 20 })
|
|
|
|
|
.toDate();
|
|
|
|
|
|
2020-01-21 12:48:42 +00:00
|
|
|
return (
|
2020-04-15 11:42:11 +00:00
|
|
|
<StyledControlGroup
|
|
|
|
|
fill
|
|
|
|
|
onClick={(e: any) => {
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
}}
|
|
|
|
|
>
|
2020-01-28 11:46:04 +00:00
|
|
|
{this.props.label && (
|
2020-01-31 11:13:16 +00:00
|
|
|
<Label
|
|
|
|
|
className={
|
|
|
|
|
this.props.isLoading
|
|
|
|
|
? Classes.SKELETON
|
|
|
|
|
: Classes.TEXT_OVERFLOW_ELLIPSIS
|
|
|
|
|
}
|
|
|
|
|
>
|
2020-01-28 11:46:04 +00:00
|
|
|
{this.props.label}
|
|
|
|
|
</Label>
|
|
|
|
|
)}
|
2021-02-03 11:30:19 +00:00
|
|
|
{
|
2020-01-21 12:48:42 +00:00
|
|
|
<DateInput
|
|
|
|
|
className={this.props.isLoading ? "bp3-skeleton" : ""}
|
|
|
|
|
formatDate={this.formatDate}
|
|
|
|
|
parseDate={this.parseDate}
|
2020-06-09 08:44:13 +00:00
|
|
|
placeholder={"Select Date"}
|
2020-01-21 12:48:42 +00:00
|
|
|
disabled={this.props.isDisabled}
|
|
|
|
|
showActionsBar={true}
|
2020-04-23 06:12:13 +00:00
|
|
|
timePrecision={TimePrecision.MINUTE}
|
2020-04-15 11:42:11 +00:00
|
|
|
closeOnSelection
|
2020-01-21 12:48:42 +00:00
|
|
|
onChange={this.onDateSelected}
|
2020-04-29 10:29:02 +00:00
|
|
|
value={
|
|
|
|
|
this.state.selectedDate
|
2020-06-09 13:04:47 +00:00
|
|
|
? this.parseDate(this.state.selectedDate)
|
2020-04-29 10:29:02 +00:00
|
|
|
: null
|
|
|
|
|
}
|
2021-02-03 11:30:19 +00:00
|
|
|
minDate={minDate}
|
|
|
|
|
maxDate={maxDate}
|
2020-01-21 12:48:42 +00:00
|
|
|
/>
|
2021-02-03 11:30:19 +00:00
|
|
|
}
|
2020-01-21 12:48:42 +00:00
|
|
|
</StyledControlGroup>
|
2019-11-06 12:12:41 +00:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
formatDate = (date: Date): string => {
|
2021-02-02 14:42:49 +00:00
|
|
|
const dateFormat = this.props.dateFormat || ISO_DATE_FORMAT;
|
|
|
|
|
return moment(date).format(dateFormat);
|
2019-11-06 12:12:41 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
parseDate = (dateStr: string): Date => {
|
2021-02-02 14:42:49 +00:00
|
|
|
const dateFormat = this.props.dateFormat || ISO_DATE_FORMAT;
|
2021-02-03 11:30:19 +00:00
|
|
|
const date = moment(dateStr, dateFormat);
|
|
|
|
|
|
|
|
|
|
if (date.isValid()) return moment(dateStr, dateFormat).toDate();
|
|
|
|
|
else return moment().toDate();
|
2019-11-06 12:12:41 +00:00
|
|
|
};
|
|
|
|
|
|
2020-11-11 11:29:45 +00:00
|
|
|
/**
|
|
|
|
|
* checks if selelectedDate is null or not,
|
|
|
|
|
* sets state and calls props onDateSelected
|
|
|
|
|
* if its null, don't call onDateSelected
|
|
|
|
|
*
|
|
|
|
|
* @param selectedDate
|
|
|
|
|
*/
|
2021-02-02 14:42:49 +00:00
|
|
|
onDateSelected = (selectedDate: Date, isUserChange: boolean) => {
|
|
|
|
|
if (isUserChange) {
|
|
|
|
|
const { onDateSelected } = this.props;
|
2020-11-11 11:29:45 +00:00
|
|
|
|
2021-02-02 14:42:49 +00:00
|
|
|
const date = selectedDate ? this.formatDate(selectedDate) : "";
|
|
|
|
|
this.setState({ selectedDate: date });
|
2020-11-11 11:29:45 +00:00
|
|
|
|
2021-02-02 14:42:49 +00:00
|
|
|
// if date is null ( if date is cleared ), don't call onDateSelected
|
|
|
|
|
if (!selectedDate) return false;
|
2020-11-11 11:29:45 +00:00
|
|
|
|
2021-02-02 14:42:49 +00:00
|
|
|
onDateSelected(date);
|
|
|
|
|
}
|
2019-11-06 12:12:41 +00:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-29 10:29:02 +00:00
|
|
|
interface DatePickerComponentProps extends ComponentProps {
|
2019-11-06 12:12:41 +00:00
|
|
|
label: string;
|
|
|
|
|
dateFormat: string;
|
|
|
|
|
enableTimePicker?: boolean;
|
2020-06-09 13:04:47 +00:00
|
|
|
selectedDate?: string;
|
2020-11-27 08:48:38 +00:00
|
|
|
minDate?: string;
|
|
|
|
|
maxDate?: string;
|
2019-11-12 07:57:12 +00:00
|
|
|
timezone?: string;
|
2019-11-06 12:12:41 +00:00
|
|
|
datePickerType: DatePickerType;
|
2020-03-20 11:03:50 +00:00
|
|
|
isDisabled: boolean;
|
2020-04-29 10:29:02 +00:00
|
|
|
onDateSelected: (selectedDate: string) => void;
|
2019-12-03 04:41:10 +00:00
|
|
|
isLoading: boolean;
|
2019-11-06 12:12:41 +00:00
|
|
|
}
|
|
|
|
|
|
2020-04-29 10:29:02 +00:00
|
|
|
interface DatePickerComponentState {
|
2020-06-09 13:04:47 +00:00
|
|
|
selectedDate?: string;
|
2020-04-29 10:29:02 +00:00
|
|
|
}
|
|
|
|
|
|
2019-11-06 12:12:41 +00:00
|
|
|
export default DatePickerComponent;
|