Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfix closing the datepicker should cancel the ongoing selection 1836 #1856

Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions components/DateSelector/DateSelector.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,19 @@ function DateSelector({
updateStartDate,
updateEndDate,
}) {
const [expanded, setExpanded] = useState(false);
const [expandedMenu, setExpandedMenu] = useState(false);
const classes = useStyles();

const handleOptionSelect = optionDates => {
const formattedStart = moment(optionDates[0]).format(dateFormat);
const formattedEnd = moment(optionDates[1]).format(dateFormat);
updateStartDate(formattedStart);
updateEndDate(formattedEnd);
setExpanded(false);
setExpandedMenu(false);
};

const closeOptionsOnDateToggle = useCallback(() => {
setExpanded(false);
setExpandedMenu(false);
}, []);

const {
Expand Down Expand Up @@ -64,12 +64,12 @@ function DateSelector({
</div>
</ArrowToolTip>
</Typography>
<SelectorBox onToggle={() => setExpanded(!expanded)} expanded={expanded}>
<SelectorBox onToggle={() => setExpandedMenu(!expandedMenu)} expanded={expandedMenu}>
<SelectorBox.Display>
<div className={classes.selector}>
<DatePicker
range={range}
onToggle={closeOptionsOnDateToggle}
onTogglePresets={closeOptionsOnDateToggle}
/>
<div className={classes.separator} />
</div>
Expand Down
57 changes: 48 additions & 9 deletions components/common/DatePicker/DatePicker.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ import IconButton from '@mui/material/IconButton';
import makeStyles from '@mui/styles/makeStyles';
import useOutsideClick from '@components/common/customHooks/useOutsideClick';
import ReactDayPicker from '@components/common/ReactDayPicker';

import {
updateEndDate as reduxUpdateEndDate,
updateStartDate as reduxUpdateStartDate,
} from '@reducers/filters';
// TODO: Apply gaps (margin, padding) from theme

const useStyles = makeStyles(theme => ({
Expand Down Expand Up @@ -84,17 +87,41 @@ const renderSelectedDays = (dates, classes, range) => {
};

function DatePicker({
open, onToggle, range, startDate, endDate,
open, onTogglePresets, range, startDate, endDate, updateStartDate, updateEndDate,
}) {
const [showCalendar, setShowCalendar] = useState(() => open);
const [initialStartDate, setInitialStartDate] = useState(startDate);
const [initialEndDate, setInitialEndDate] = useState();
const classes = useStyles();

const ref = useRef(null);
const closeCalendar = useCallback(() => setShowCalendar(false), []);

const closeCalendar = useCallback(
() => {
if (startDate && endDate){
setShowCalendar(false);
} else if (startDate && !endDate){
//The calendar was closed with an incomplete date range selection so we need to restart
//startDate and endDate to their initial values
updateStartDate(initialStartDate);
updateEndDate(initialEndDate);
setShowCalendar(false);
} else {
//This should never happen. Log a warning.
console.warn('Try to set a new date selection. Dates were in an invalid state. StartDate: ', startDate, " endDate: ", endDate);
}
}, [startDate, endDate]);
useOutsideClick(ref, closeCalendar);

const openCalendar = () => {
setInitialStartDate(startDate);
setInitialEndDate(endDate);
setShowCalendar(true);
}

useEffect(() => {
setShowCalendar(false);
setInitialStartDate(startDate)
setInitialEndDate(endDate)
}, [open]);

const getCoordinates = () => {
Expand All @@ -110,9 +137,14 @@ function DatePicker({
};

const toggleCalendar = () => {
setShowCalendar(prevState => !prevState);
if (onToggle) onToggle();
if(showCalendar) {
closeCalendar();
} else {
openCalendar();
}
if (onTogglePresets) onTogglePresets();
};

return (
<div ref={ref} className={classes.selector}>
<div onClick={toggleCalendar}>
Expand All @@ -132,6 +164,8 @@ function DatePicker({
{showCalendar ? (
<ReactDayPicker
range={range}
updateStartDate={updateStartDate}
updateEndDate={updateEndDate}
/>
) : null}
</div>
Expand All @@ -142,15 +176,15 @@ function DatePicker({
DatePicker.propTypes = {
range: PropTypes.bool,
open: PropTypes.bool,
onToggle: PropTypes.func,
onTogglePresets: PropTypes.func,
startDate: PropTypes.string,
endDate: PropTypes.string,
};

DatePicker.defaultProps = {
open: false,
range: false,
onToggle: null,
onTogglePresets: null,
startDate: null,
endDate: null,
};
Expand All @@ -160,4 +194,9 @@ const mapStateToProps = state => ({
endDate: state.filters.endDate,
});

export default connect(mapStateToProps)(DatePicker);
const mapDispatchToProps = dispatch => ({
updateStartDate: date => dispatch(reduxUpdateStartDate(date)),
updateEndDate: date => dispatch(reduxUpdateEndDate(date)),
});

export default connect(mapStateToProps, mapDispatchToProps)(DatePicker);
38 changes: 15 additions & 23 deletions components/common/ReactDayPicker/ReactDayPicker.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,6 @@ import DayPicker from 'react-day-picker';
import { connect } from 'react-redux';
import makeStyles from '@mui/styles/makeStyles';
import clsx from 'clsx';
import {
updateEndDate as reduxUpdateEndDate,
updateStartDate as reduxUpdateStartDate,
} from '@reducers/filters';

import fonts from '@theme/fonts';
import colors from '@theme/colors';
import { INTERNAL_DATE_SPEC } from '../CONSTANTS';
Expand Down Expand Up @@ -175,13 +170,16 @@ function ReactDayPicker({
setFromDay(day);
return;
}

// Our date range selection logic is very simple: the user is selecting the
// first day in their date range if from and to are set, or if they're both
// unset. Otherwise, they are selecting the last day.
if (!(startDate && endDate)) {
// If the user picks the first date then picks the second date that is before the first date
// Reassign the From and To Day

//If both startDate and endDate were already selected. Start a new range selection.
if(startDate && endDate){
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: add space after if (lines 175 and 180)

setFromDay(day);
updateEndDate(null);
setEnteredTo(null);
//If startDate is selected and endDate is unselected, complete the range selection.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: for comments, add space between // and start of comment

} else if(startDate && !endDate){
// If the user selects the startDate then chooses an endDate that precedes it,
// swap the values of startDate and endDate
if (moment(day).format(INTERNAL_DATE_SPEC) < startDate) {
const tempDate = startDate;
setToDay(moment(tempDate).toDate());
Expand All @@ -191,11 +189,10 @@ function ReactDayPicker({
} else {
setToDay(day);
}
return;
}
setFromDay(day);
updateEndDate(null);
setEnteredTo(null);
} else {
//This should never happen. Log a warning.
console.warn('Try to set a new date selection. Dates were in an invalid state. StartDate: ', startDate, " endDate: ", endDate);
}
};

const handleDayMouseEnter = day => {
Expand Down Expand Up @@ -248,14 +245,9 @@ ReactDayPicker.defaultProps = {
endDate: null,
};

const mapDispatchToProps = dispatch => ({
updateStartDate: date => dispatch(reduxUpdateStartDate(date)),
updateEndDate: date => dispatch(reduxUpdateEndDate(date)),
});

const mapStateToProps = state => ({
startDate: state.filters.startDate,
endDate: state.filters.endDate,
});

export default connect(mapStateToProps, mapDispatchToProps)(ReactDayPicker);
export default connect(mapStateToProps)(ReactDayPicker);