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

Feature: add firstDayOfWeek prop #371

Merged
merged 3 commits into from
Jul 15, 2017

Conversation

daltones
Copy link
Contributor

@daltones daltones commented Mar 13, 2017

This PR tries to provide a solution to fix #363.

We urgently needed this feature in our app. Right now a forked react-dates with this implementation is running in production, all good. We use just <DayPicker /> components in two different pages.

For now it's missing passing along prop firstDayOfWeek from DateRangePicker and SingleDatePicker and write some new tests for this functionality.

The big change here is the [almost] rewrite of getCalendarMonthWeeks. The logic now is that every operation involving weekdays needs the firstDayOfWeek parameter (0-Sun...6-Sat locale independent). And then firstDayOfWeek prop from components gets the default value according to Moment's global locale (so we're not breaking anything).

I'd be happy if I receive feedback of this implementation. I'll update the PR very soon with the rest.

@daltones
Copy link
Contributor Author

daltones commented Mar 13, 2017

Oh, I forgot to mention. This implementation also fixes a bug in an edge case I found:

// We have Moment's global locale starting the week on Sundays
moment.locale('some-sunday-based-locale');

// For some reason in initialVisibleMonth we return a moment object set
// with another locale that starts the week on Mondays
<DayPicker initialVisibleMonth={() => moment().locale('some-monday-based-locale')} />

In react-dates v8.1.1 we'll have a calendar that shows the weekdays header starting on Monday, but the actual days arranged as starting on Sunday.

@coveralls
Copy link

Coverage Status

Coverage decreased (-0.2%) to 81.981% when pulling 092e01c on daltones:feat/first-weekday into abd0b1b on airbnb:master.

Copy link
Member

@ljharb ljharb left a comment

Choose a reason for hiding this comment

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

A few comments on the implementation.

Looks good overall tho, but it requires test coverage on all affected files.

@@ -44,6 +45,7 @@ const defaultProps = {
onDayMouseEnter() {},
onDayMouseLeave() {},
renderDay: null,
firstDayOfWeek: moment.localeData().firstDayOfWeek(),
Copy link
Member

Choose a reason for hiding this comment

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

this will freeze the default at parse time (and the locale could be changed at any time) - i think this default needs to be calculated in the render path, and have it default to -1 or null here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, sure. I think null is better.

@@ -52,6 +53,7 @@ const defaultProps = {
onMonthTransitionEnd() {},
renderDay: null,
transformValue: 'none',
firstDayOfWeek: moment.localeData().firstDayOfWeek(),
Copy link
Member

Choose a reason for hiding this comment

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

same here

@@ -65,6 +66,7 @@ const defaultProps = {
onOutsideClick() {},
hidden: false,
initialVisibleMonth: () => moment(),
firstDayOfWeek: moment.localeData().firstDayOfWeek(),
Copy link
Member

Choose a reason for hiding this comment

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

and here

export default function getCalendarMonthWeeks(
month,
enableOutsideDays,
firstDayOfWeek = moment.localeData().firstDayOfWeek(),
Copy link
Member

Choose a reason for hiding this comment

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

can something validate that this value is an integer 0-6, and throw a TypeError if not?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I thought about that, but I didn't see any other example of this kind of validation. Even here we call month.clone() without knowing if month is in fact a moment object. Moreover, like all these parameters of utils functions, values came from component props that already pass by some propTypes validation in dev.

Copy link
Member

Choose a reason for hiding this comment

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

The propType should ensure that. I think that in general the utils functions should not assume safe inputs.

@ljharb ljharb added the semver-minor: new stuff Any feature or API addition. label Mar 14, 2017
@coveralls
Copy link

Coverage Status

Coverage increased (+0.1%) to 87.436% when pulling b62a3aa on daltones:feat/first-weekday into b90ee78 on airbnb:master.

@ljharb
Copy link
Member

ljharb commented Mar 23, 2017

@daltones would you please rebase this branch to ensure there's no merge commits in it?

@daltones daltones force-pushed the feat/first-weekday branch 2 times, most recently from d570d5b to 4b38335 Compare March 24, 2017 03:15
@coveralls
Copy link

Coverage Status

Coverage increased (+0.1%) to 87.436% when pulling 4b38335 on daltones:feat/first-weekday into b90ee78 on airbnb:master.

@daltones
Copy link
Contributor Author

@ljharb done!

@coveralls
Copy link

Coverage Status

Coverage increased (+0.1%) to 87.436% when pulling 4b38335 on daltones:feat/first-weekday into b90ee78 on airbnb:master.

ljharb
ljharb previously requested changes Mar 24, 2017
weeks: getCalendarMonthWeeks(
props.month,
props.enableOutsideDays,
props.firstDayOfWeek === null ? moment.localeData().firstDayOfWeek() : props.firstDayOfWeek,
Copy link
Member

Choose a reason for hiding this comment

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

This should probably use == null to avoid distinguishing from undefined

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Okay, I can do this. But you're saying just because code style? If firstDayOfWeek has a defaultValue set to null, it would never be undefined, right?

Copy link
Member

Choose a reason for hiding this comment

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

I do think you're right; that a value of undefined would trigger the default, and a value of null would not, so === null would work fine - but in general for style, yes. Not a huge deal, ofc.

weeks: getCalendarMonthWeeks(
month,
enableOutsideDays,
firstDayOfWeek === null ? moment.localeData().firstDayOfWeek() : firstDayOfWeek,
Copy link
Member

Choose a reason for hiding this comment

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

Also here

@@ -350,11 +352,16 @@ export default class DayPicker extends React.Component {

const style = this.isHorizontal() ? horizontalStyle : {};

let { firstDayOfWeek } = this.props;
if (firstDayOfWeek === null) {
Copy link
Member

Choose a reason for hiding this comment

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

And here

@@ -52,6 +52,7 @@ const propTypes = forbidExtraProps({
onOutsideClick: PropTypes.func,
renderDay: PropTypes.func,
renderCalendarInfo: PropTypes.func,
firstDayOfWeek: PropTypes.oneOf([0, 1, 2, 3, 4, 5, 6]),
Copy link
Member

Choose a reason for hiding this comment

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

I think this propType should be shared and exported up from the components that need it - ie, this component shouldn't du-locate the definition, it should just import the propType from DayPicker and delegate the authority to it.

Same applies to any component where the prop is merely proxied down.

Effectively I'd prefer the oneOf to only appear in one place.

const currentDay = firstOfMonth.clone();
let currentWeek = [];
const weeksInMonth = [];
const WEEKDAYS = [0, 1, 2, 3, 4, 5, 6];
Copy link
Member

Choose a reason for hiding this comment

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

Could this array be shared, and used inside the oneOf?

@coveralls
Copy link

Coverage Status

Coverage increased (+0.2%) to 87.563% when pulling c2c333f on daltones:feat/first-weekday into b90ee78 on airbnb:master.

@ljharb ljharb dismissed their stale review March 24, 2017 05:26

code LGTM. deferring to @majapw

@ljharb ljharb requested a review from majapw March 24, 2017 05:26
@CarlRosell
Copy link

What's the current status of this PR?
I'm glad to see someone else also having this issue. I've made the same changes for other "date-picker"-libraries as this is a major blocker for the company where I work. 👍

@majapw
Copy link
Collaborator

majapw commented Jun 9, 2017

Hi @CarlRosell, I can take a look at this tomorrow/early next week.

@daspete
Copy link

daspete commented Jul 6, 2017

Hi there, is this feature in the todo pipeline? It would be great to see this one working, because our company need to set the first day to monday.... or is there another way to set this?

@majapw majapw force-pushed the feat/first-weekday branch 2 times, most recently from dfbf84e to 071d78b Compare July 14, 2017 22:04
majapw
majapw previously approved these changes Jul 14, 2017
Copy link
Collaborator

@majapw majapw left a comment

Choose a reason for hiding this comment

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

Seems legit to me!

@majapw
Copy link
Collaborator

majapw commented Jul 14, 2017

@ljharb since I updated this PR with my own changes/rebase/etc. can you please sanity-check it for me before I merge it in?

@coveralls
Copy link

Coverage Status

Coverage increased (+0.04%) to 86.243% when pulling dfbf84e on daltones:feat/first-weekday into 1031985 on airbnb:master.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.04%) to 86.243% when pulling 071d78b on daltones:feat/first-weekday into 1031985 on airbnb:master.

Copy link
Member

@ljharb ljharb left a comment

Choose a reason for hiding this comment

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

LGTM pending the one test change

});

describe('locale with Monday as first day of week', () => {
before(() => {
Copy link
Member

Choose a reason for hiding this comment

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

we need to use beforeEach here; before is beforeAll, and we don't want that.

const january2017End = january2017Start.clone().endOf('month'); // Tuesday

describe('locale with Sunday as first day of week', () => {
before(() => {
Copy link
Member

Choose a reason for hiding this comment

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

we need to use beforeEach here; before is beforeAll, and we don't want that.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.04%) to 86.243% when pulling 55c7d37 on daltones:feat/first-weekday into 19a10f7 on airbnb:master.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.04%) to 86.243% when pulling 55c7d37 on daltones:feat/first-weekday into 19a10f7 on airbnb:master.

@majapw
Copy link
Collaborator

majapw commented Jul 14, 2017

@ljharb addressed your comments!

Copy link
Member

@ljharb ljharb left a comment

Choose a reason for hiding this comment

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

K last thing, I swear :-)

@@ -0,0 +1,5 @@
import { PropTypes } from 'react';
Copy link
Member

Choose a reason for hiding this comment

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

This needs to use the prop-types package

…stDayOfWeek prop working with the SDP again
@majapw
Copy link
Collaborator

majapw commented Jul 15, 2017

Naw this is good! You're catching all the things I've missed. :) I addressed the prop types issue @ljharb, can you take another look?

@coveralls
Copy link

Coverage Status

Coverage increased (+0.04%) to 86.243% when pulling 139e274 on daltones:feat/first-weekday into 19a10f7 on airbnb:master.

@majapw majapw merged commit f149c68 into react-dates:master Jul 15, 2017
@CarlRosell
Copy link

🎉

cchanningallen pushed a commit to cchanningallen/react-dates that referenced this pull request Jul 17, 2017
@cesalberca
Copy link

Nice! Just in time for a component I'm doing in spanish ^^ Any ideas when this patch will be released?

@majapw
Copy link
Collaborator

majapw commented Jul 24, 2017

Should be live in v12.3.0! :)

drewda added a commit to opentraffic/analyst-ui that referenced this pull request Sep 28, 2017
closes #128

Required an upgrade of react-dates, to include react-dates/react-dates#371
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
semver-minor: new stuff Any feature or API addition.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Feature: prop firstDayOfTheWeek
7 participants