diff --git a/client/src/components/CustomDateInput.js b/client/src/components/CustomDateInput.js index 45399c5b41..2d8d17da35 100644 --- a/client/src/components/CustomDateInput.js +++ b/client/src/components/CustomDateInput.js @@ -30,18 +30,21 @@ const CustomDateInput = ({ withTime, value, onChange, - onBlur + onBlur, + fullWidth, + allDay }) => { const inputRef = useRef() const rightElement = showIcon && CalendarIcon(inputRef.current) const width = 8 + (showIcon ? 3 : 0) + (withTime ? 3 : 0) - const style = { width: `${width}em`, fontSize: "1.1em" } - const dateFormats = withTime - ? Settings.dateFormats.forms.input.withTime - : Settings.dateFormats.forms.input.date + const style = { width: fullWidth ? "100%" : `${width}em`, fontSize: "1.1em" } + const dateFormats = + withTime && !allDay + ? Settings.dateFormats.forms.input.withTime + : Settings.dateFormats.forms.input.date const inputFormat = dateFormats[0] const timePickerProps = !withTime - ? {} + ? undefined : { precision: TimePrecision.MINUTE, selectAllOnFocus: true @@ -70,6 +73,7 @@ const CustomDateInput = ({ timePickerProps={timePickerProps} popoverProps={{ usePortal: false }} disabled={disabled} + fill={fullWidth} /> ) } @@ -84,12 +88,16 @@ CustomDateInput.propTypes = { PropTypes.instanceOf(Date) ]), onChange: PropTypes.func, - onBlur: PropTypes.func + onBlur: PropTypes.func, + fullWidth: PropTypes.bool, + allDay: PropTypes.bool } CustomDateInput.defaultProps = { disabled: false, showIcon: true, - withTime: false + withTime: false, + fullWidth: false, + allDay: true } export default CustomDateInput diff --git a/client/src/index.css b/client/src/index.css index 334ad06d49..58ebb7ebef 100644 --- a/client/src/index.css +++ b/client/src/index.css @@ -147,7 +147,7 @@ fieldset.danger { } #duration { - width: 10em; + width: 100%; } .shortcut-list { diff --git a/client/src/pages/reports/EngagementDateFormPartial.js b/client/src/pages/reports/EngagementDateFormPartial.js index f5e7879d2d..a3686d6ab6 100644 --- a/client/src/pages/reports/EngagementDateFormPartial.js +++ b/client/src/pages/reports/EngagementDateFormPartial.js @@ -1,10 +1,12 @@ +import { Checkbox } from "@blueprintjs/core" import CustomDateInput from "components/CustomDateInput" import * as FieldHelper from "components/FieldHelper" -import { FastField } from "formik" +import { FastField, Field } from "formik" import { Report } from "models" +import moment from "moment" import PropTypes from "prop-types" -import React from "react" -import { HelpBlock } from "react-bootstrap" +import React, { useEffect, useState } from "react" +import { Col, ControlLabel, FormGroup, HelpBlock } from "react-bootstrap" import Settings from "settings" const futureEngagementHint = ( @@ -13,6 +15,109 @@ const futureEngagementHint = ( ) +function isStartOfDay(date) { + return date && moment(date).isSame(moment(date).startOf("day")) +} + +const EngagementDatePartialFormWithDuration = ({ + setFieldValue, + setFieldTouched, + validateFieldDebounced, + initialValues, + edit, + values +}) => { + const [isAllDay, setIsAllDay] = useState(true) + useEffect(() => { + if (!edit || !initialValues.engagementDate) { + setIsAllDay(true) + } else if (!isStartOfDay(initialValues.engagementDate)) { + setIsAllDay(false) + } else { + setIsAllDay(initialValues?.duration === null) + } + }, [edit, initialValues, validateFieldDebounced]) + + return ( + + + Engagement planning + + + { + setFieldTouched("engagementDate", true, false) // onBlur doesn't work when selecting a date + setFieldValue("engagementDate", value, true) + if (!value) { + setIsAllDay(true) + } else if (!isStartOfDay(value)) { + setIsAllDay(false) + } + }} + onBlur={() => setFieldTouched("engagementDate")} + widget={ + + } + vertical + > + {Report.isFuture(values.engagementDate) && futureEngagementHint} + + + + { + setFieldTouched("duration", true, false) + setFieldValue("duration", event.target.value, false) + validateFieldDebounced("duration") + setIsAllDay(false) + }} + vertical + disabled={isAllDay} + /> + + + { + setIsAllDay(e.target.checked) + if (e.target.checked) { + setFieldValue("duration", null, true) + validateFieldDebounced("duration") + if (values.engagementDate) { + setFieldValue( + "engagementDate", + moment(values.engagementDate).startOf("day").toDate(), + false + ) + } + } + }} + /> + + + ) +} + +EngagementDatePartialFormWithDuration.propTypes = { + setFieldValue: PropTypes.func.isRequired, + setFieldTouched: PropTypes.func.isRequired, + validateFieldDebounced: PropTypes.func.isRequired, + values: PropTypes.object.isRequired, + initialValues: PropTypes.instanceOf(Report).isRequired, + edit: PropTypes.bool.isRequired +} + const EngagementDateFormPartial = ({ setFieldValue, setFieldTouched, @@ -27,10 +132,9 @@ const EngagementDateFormPartial = ({ name="engagementDate" component={FieldHelper.SpecialField} onChange={value => { - setFieldTouched("engagementDate", true, false) // onBlur doesn't work when selecting a date - setFieldValue("engagementDate", value, true) + const val = value ? moment(value).startOf("day").toDate() : null + setFieldValue("engagementDate", val, true) }} - onBlur={() => setFieldTouched("engagementDate")} widget={} > {Report.isFuture(values.engagementDate) && futureEngagementHint} @@ -39,31 +143,14 @@ const EngagementDateFormPartial = ({ } return ( - <> - { - setFieldTouched("engagementDate", true, false) // onBlur doesn't work when selecting a date - setFieldValue("engagementDate", value, true) - }} - onBlur={() => setFieldTouched("engagementDate")} - widget={} - > - {Report.isFuture(values.engagementDate) && futureEngagementHint} - - - { - setFieldTouched("duration", true, false) - setFieldValue("duration", event.target.value, false) - validateFieldDebounced("duration") - }} - /> - + ) } diff --git a/client/tests/e2e/report.js b/client/tests/e2e/report.js index df25161ca7..6e24d45df9 100644 --- a/client/tests/e2e/report.js +++ b/client/tests/e2e/report.js @@ -456,7 +456,7 @@ test.serial( ) await $input.sendKeys("user input") - await $input.sendKeys(t.context.Key.TAB) // fire blur event + await $searchBarInput.click() // fire blur event t.false( _includes(await $fieldGroup.getAttribute("class"), warningClass), `After typing in ${fieldName} field, warning state goes away`