UNPKG

glass-app-manager

Version:

Informatica's Glass Framework CLI for bootstrapping

225 lines (189 loc) 6.8 kB
// @flow import * as React from "react"; import classNames from "classnames"; import Button from "../button/Button"; import Dialog from "../dialog/Dialog"; import type { DialogProps } from "../dialog/Dialog"; import CalendarTimePicker from "./CalendarTimePicker"; import { TranslationContext, t } from "../withTranslation/withTranslation"; import moment from "moment"; import momentLocalizer from "react-widgets-moment"; type State = {| start: moment, end: moment, |}; type Props = { /** * Callback to execute after the OK button has been clicked. */ onOk: (args: State) => void, /** * Callback to execute after the range has been changed. * If you need to restrict what the user can enter into the * time component, be sure to do that here. */ onRangeChange: (args: State) => void, /** * Control the date range picker closed/open state. You are required * to control this yourself. */ closed: boolean, /** * Optionally specify the locale of the date range picker. */ locale?: string, /** * Restrict the minimum time allowed as a Date object. */ min?: Date, /** * Restrict the maximum time allowed as a Date object. */ max?: Date, /** * For more fine-grained control of react-widgets, pass your own props down to * the `Calendar` and `DateTimePicker` component from `react-widgets`. */ startProps?: {}, /** * For more fine-grained control of react-widgets, pass your own props down to * the `Calendar` and `DateTimePicker` component from `react-widgets`. */ endProps?: {}, /** * Additional className values to pass to the component. */ className?: string, ...DialogProps, }; const DatePickerDialog = ({ title, children, onCancel, onOk, locale, ...rest }: Props) => ( <Dialog {...rest} data-testid="date-range-picker-dialog" id="date-range-picker"> <Dialog.Header title={title} /> <Dialog.Content>{() => children}</Dialog.Content> <Dialog.Footer> {() => ( <> <Button variant="primary" onClick={onOk}> {t("OK", locale)} </Button> <Button onClick={onCancel}>{t("Cancel", locale)}</Button> </> )} </Dialog.Footer> </Dialog> ); /** * Generic change handler. * @param {Date} time The date object send from react-wigdets onChange handler. * @param {boolean} start Set true for start date, false for end date. * @param {boolean} date Set true for date, false for time. */ const handleChange = (time: Date, source, start = true, date = true) => { const m = moment(time); if (moment.isMoment(source) && source.diff(m)) { if (date) { m.set("hour", source.hours()); m.set("minute", source.minutes()); m.set("second", source.seconds()); } else { m.set("date", source.date()); m.set("month", source.month()); m.set("year", source.year()); } return m; } }; export default function DateRangePicker(props: Props) { const context = React.useContext(TranslationContext); const [range, setRange] = React.useState({ start: moment(), end: moment().add(1, "day"), }); const [error, setError] = React.useState(false); const handleOkClick = React.useCallback(() => { props.onOk(range); }, [range, props.onOk]); const handleStartChangeDate = React.useCallback( (e: Date) => { const newRange = { ...range, start: handleChange(e, range.start), }; setRange(newRange); props.onRangeChange(newRange); }, [range, props.onRangeChange] ); const handleStartChangeTime = React.useCallback( (e: Date) => { const newRange = { ...range, start: handleChange(e, range.start, true, false), }; setRange(newRange); props.onRangeChange(newRange); }, [range, props.onRangeChange] ); const handleEndChangeDate = React.useCallback( (e: Date) => { const newRange = { ...range, end: handleChange(e, range.end, false, true), }; setRange(newRange); props.onRangeChange(newRange); }, [range, props.onRangeChange] ); const handleEndChangeTime = React.useCallback( (e: Date) => { const newRange = { ...range, end: handleChange(e, range.end, false, false), }; setRange(newRange); props.onRangeChange(newRange); }, [range, props.onRangeChange] ); // $FlowFixMe locale is not exported by moment type despite it being present moment.locale(context ? context.locale : props.locale); momentLocalizer(); const { min, max, className, startProps, endProps } = props; let locale = context ? context.locale : props.locale; return ( <DatePickerDialog {...props} locale={locale} onOk={handleOkClick}> <div className={classNames("date-range-picker", className)} data-testid="date-range-picker"> <section className="date-range-picker__start"> <p>{t("From", locale)}:</p> <CalendarTimePicker locale={locale} rwProps={startProps} min={min} max={max} value={range.start.toDate()} onDateChange={handleStartChangeDate} onTimeChange={handleStartChangeTime} /> </section> <section className="date-range-picker__end"> <p>{t("To", locale)}:</p> <CalendarTimePicker locale={locale} rwProps={endProps} min={min} max={max} value={range.end.toDate()} onDateChange={handleEndChangeDate} onTimeChange={handleEndChangeTime} /> </section> </div> </DatePickerDialog> ); } DateRangePicker.defaultProps = { locale: "en", closed: true, };