-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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
Support selecting multiple dates #3999
Conversation
…>> This PR adds 2 props which allow users to select multiple isolated dates on the calendar picker. It adds changes to Picker.onChange(), Day.isSelected(), and adds formatting for the input.
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #3999 +/- ##
==========================================
- Coverage 95.46% 94.74% -0.73%
==========================================
Files 29 29
Lines 2513 2548 +35
Branches 1026 1043 +17
==========================================
+ Hits 2399 2414 +15
- Misses 114 134 +20 ☔ View full report in Codecov by Sentry. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✅ This pull request was sent to the PullRequest network.
@nandorojo you can click here to see the review status or cancel the code review job - or - cancel by adding [!pr] to the title of the pull request.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PullRequest Breakdown
Reviewable lines of change
+ 146
- 13
80% JavaScript
20% JavaScript (tests)
Type of change
Feature - These changes are adding a new feature or improvement to existing code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking like a great start. The code is looking clean, but has no test coverage. I have only one minor note left inline for your consideration.
Reviewed with ❤️ by PullRequest
setSelectedDates(dates); | ||
}; | ||
return ( | ||
<DatePicker |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The examples added here are automatically published to https://reactdatepicker.com/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Normally I would, but I just copied what the other examples did.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps we can start by leading with example here and add the import to show how to get it done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nandorojo Can you add some tests to cover your new functionality? |
Sure, other than the example app updates? |
Ideally, add some automated tests to ensure we don't break this in future changes. You can see the tests folder with examples of how to test. |
Got it, I can do that today if it means getting it merged. Thanks for the feedback. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks to support multiple days as described but given the new functionality it would be great to see some tests and documentation around the new feature
Reviewed with ❤️ by PullRequest
James D and Graham C from PullRequest - any test cases you can recommend to @nandorojo just so he can knock them out? I'm 100% sure he's fully capable, just very busy juggling a lot 1 2. It helps sometimes to just have stuff listed in GitHub even if it's basic and obvious. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For adding tests:
- if there isn't already one, I would add a test around using this component to select a single day
- Using this component to select multiple days
- Using this component to select a single day and then change it
- Using this component to select multiple days and then change one of them
It appears those are supported scenarios that would be useful to add here for coverage
Reviewed with ❤️ by PullRequest
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pending test coverage
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PullRequest reviewed the updates made to #3999 since our last review was posted. This includes comments that have been posted by non-PullRequest reviewers. No further issues were found.
Reviewed by:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Due to inactivity, PullRequest has cancelled this review job. You can reactivate the code review job from the PullRequest dashboard.
any way to just merge this? useful feature and the code looks fine. |
@garrettparris @williamtcastro @nandorojo Seems like it's currently blocked on some missing tests, we recently migrated to jest so hopefully it's easier to add tests now. There's also a merge conflict error. |
Hey guys. Is this worth me going into and fixing merge conflicts? I can do it, but I don't want to spend the time again if it won't get merged. We used the code in prod for months with no issues. However, I just upgraded to 4.14.0 and lost all my changes, so I'm hoping to use this PR now. Please let me know if this is worth doing or not. |
Merge conflicts fixed. |
Not sure where tests are failing, I don't see them on here. |
@nandorojo I've started the workflows for test coverage. You should see those showing up in a minute. Per request, can you add some test coverage for this functionality? I'm happy to get this merged once ready. |
Per workflow results, the codecov check is complaining about missing test coverage. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✅ This pull request was sent to the PullRequest network.
@nandorojo you can click here to see the review status or cancel the code review job - or - cancel by adding [!pr] to the title of the pull request.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I love this component and this looks like a great update. It seems like there are some rather complicated logic improvements that could benefit from unit test coverage, though.
Reviewed with ❤️ by PullRequest
isSelected = () => | ||
this.isSameDay(this.props.selected) || this.isSameWeek(this.props.selected); | ||
|
||
isSelected = () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This multi-selection functionality looks good overall. I just had the one comment suggesting that a code comment be left for readability in one spot that was pretty non-obvious. Other than that, I don't have anything that hasn't already been mentioned by other reviewers.
Reviewed with ❤️ by PullRequest
) && | ||
(this.isSameDay(this.props.preSelection) || | ||
this.isSameWeek(this.props.preSelection)); | ||
isKeyboardSelected = () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
test/multiple_selected_dates.test.js
Outdated
expect(datePicker.input.value).toBe("01/01/2024, 01/15/2024"); | ||
}); | ||
|
||
it("should have multiple highlighted days", () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like you may have forgotten an expect in this test case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I was hoping to get some guidance on how to implement this one. I tried copying some helper functions from other tests but haven't been able to figure it out quite yet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does anyone with more test / internals knowledge have guidance for these tests? I'm not totally sure what the requirement is
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nandorojo As I see it, the displaying of individual selected days should not be tested here.
I have provided a new test that checks if the input text box is rendered properly with 2 and 2+ dates selected.
I have a larger project where this addition could be very useful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Due to inactivity, PullRequest has cancelled this review job. You can reactivate the code review job from the PullRequest dashboard.
@martijnrusschen @nandorojo |
Co-authored-by: Thomas Mørch <[email protected]>
Co-authored-by: Thomas Mørch <[email protected]>
Co-authored-by: Thomas Mørch <[email protected]>
@nandorojo can you resolve the merge conflicts? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Found a couple of minor issues (perhaps some is just nitpicking),
Not entirely sure about code coverage or how I can help with adding that without creating a new PR against @nandorojo s branch (if needed)
const noSelectedDates = !selectedDates || selectedDates.length === 0; | ||
|
||
if (noSelectedDates) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tend to prefer these type of checks here
const noSelectedDates = !selectedDates || selectedDates.length === 0; | |
if (noSelectedDates) { | |
if (!selectedDates?.length) { |
} else { | ||
return !( | ||
this.isSameDay(this.props.selected) || | ||
this.isSameWeek(this.props.selected) | ||
) && ( | ||
this.isSameDay(this.props.preSelection) || | ||
this.isSameWeek(this.props.preSelection) | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the else clause should not be necessary, as the if above ends with a return, so we can skip an indentation here
} else { | |
return !( | |
this.isSameDay(this.props.selected) || | |
this.isSameWeek(this.props.selected) | |
) && ( | |
this.isSameDay(this.props.preSelection) || | |
this.isSameWeek(this.props.preSelection) | |
); | |
} | |
} | |
return !( | |
this.isSameDay(this.props.selected) || | |
this.isSameWeek(this.props.selected) | |
) && ( | |
this.isSameDay(this.props.preSelection) || | |
this.isSameWeek(this.props.preSelection) | |
); |
isSelected = () => { | ||
if (this.props.selectsMultiple && this.props.selectedDates) { | ||
return this.props.selectedDates.some((date) => this.isSameDay(date)); | ||
} | ||
return this.isSameDay(this.props.selected) || this.isSameWeek(this.props.selected); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks sketchy, as it will fall through to checking on props.selected, if this.props.selectsMultiple is true, and this.props.selectedDates is undefined.
Perhaps something in the line of this instead (I added test on this.isSameWeek()
as well, haven't dived enough into the code to see if that actually is necessary?
isSelected = () => { | |
if (this.props.selectsMultiple && this.props.selectedDates) { | |
return this.props.selectedDates.some((date) => this.isSameDay(date)); | |
} | |
return this.isSameDay(this.props.selected) || this.isSameWeek(this.props.selected); | |
}; | |
isSelected = () => { | |
if (this.props.selectsMultiple) { | |
return this.props.selectedDates?.some((date) => this.isSameDay(date) || this.isSameWeek(date)) ?? false; | |
} | |
return this.isSameDay(this.props.selected) || this.isSameWeek(this.props.selected); | |
}; |
@@ -185,6 +185,23 @@ export function safeDateRangeFormat(startDate, endDate, props) { | |||
return `${formattedStartDate} - ${formattedEndDate}`; | |||
} | |||
|
|||
export function safeMultipleDatesFormat(dates, props) { | |||
if (!dates || !dates.length) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (!dates || !dates.length) { | |
if (!dates?.length) { |
@tbowmo Thanks for the suggestions. It would be great to get this PR over the finish line. If it's easier, perhaps we should consider opening a new PR with your changes included. Let me know if you prefer that and I can review the changes once its in. |
So you suggest that I fork @nandorojo working branch, add my suggestions, and then create a new pr? (perhaps add a few tests when I get it figured out) |
if (this.props.disabledKeyboardNavigation) { | ||
return false; | ||
} | ||
if (this.props.selectsMultiple) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @nandorojo 👋
Was digging into this PR to investigate "select multiple months" and I think we need logic similar to this for the months and weeks selection, otherwise there's no selection styles there.
Happy to help with it if I can
React.Datepicker.crafted.by.HackerOne.-.14.April.2023.mp4
What
Closes #3157
This PR adds 2 props which allow users to select multiple isolated dates on the calendar picker.
You can now select multiple dates at once, which is very convenient for products that need users to select multiple dates, such as Calendly and the like.
How
Following the API for
selectsRange
, this PR adds aselectsMultiple
boolean, in addition to aselectedDates
array.I thought it was best for
selectedDates
to be explicitly different fromselected
. This is also following the convention fromselectsRange
, which usesstartDate
andendDate
.Example
As shown in the video above, here is the example code:
Breakdown
This PR adds a few minor changes to achieve adding multiple dates.
First, in the
Picker
component, it adds 2 core changes:safeMultipleDatesFormat
.onChange
.The rest is just prop drilling down to
<Day />
, which has 2 key changes:isKeyboardSelected
needs to account forselectedDates
rather thanselected
.isSelected
also checks forselectedDates
I've tested this out and it all looks good to me!