Skip to content
This repository has been archived by the owner on Aug 30, 2019. It is now read-only.

Calendar component - Issue #36 (WIP) #45

Merged
merged 7 commits into from Mar 21, 2017
Merged

Conversation

mAiNiNfEcTiOn
Copy link
Contributor

@mAiNiNfEcTiOn mAiNiNfEcTiOn commented Mar 17, 2017

What does this PR do:

  • Adds a new helper function that normalizes a Date object's hours, minutes, seconds and milliseconds.
  • Adds the Calendar component to the kit.
  • Changes the _default.yaml to contain a basic default style of the calendar.
  • Changes the builder to ouput errors via util.inspect() which colorizes the output as well
  • Configures the rule jsx-indent on the .eslintrc to enable the indentLogicalExpressions, overriding its default behavior to the one of v6.10.0: v6.10.1 breaks v6.10.0 builds (related to jsx-indent) jsx-eslint/eslint-plugin-react#1117 (comment)
  • Locks the snapshots and tests to run on UTC (using the TZ env variable) so that it runs in the same timezone as Travis CI.

Documentation also is a WIP... Won't merge without having it properly set.

screen shot 2017-03-17 at 11 46 49

screen shot 2017-03-17 at 11 46 17

screen shot 2017-03-17 at 11 45 20

screen shot 2017-03-17 at 11 39 03

Where should the reviewer start:

  • components/calendar.js

Unit and/or functional tests:

Being added (WIP). But you can start the code review without them :)

@coveralls
Copy link

Coverage Status

Coverage decreased (-11.2%) to 88.797% when pulling 4945877 on add-calendar-component into 0070bb3 on master.

@@ -0,0 +1,268 @@
import React from 'react';
Copy link
Contributor

Choose a reason for hiding this comment

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

why not
import React, { PropTypes, Component } from 'react';?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Indeed... would make it more readable... will do 👍

const { initialDates, maxDate, minDate } = props;
const maxLimit = maxDate ? new Date(maxDate) : null;
const renderDate = (initialDates && initialDates.length) ? new Date(initialDates[0]) : new Date();
const selectedDates = initialDates ? initialDates.map(item => (item ? new Date(item) : null)) : [null, null];
Copy link
Contributor

Choose a reason for hiding this comment

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

two inlined ternary operators with arrow function - hard to read\understand, please consider simplifying and\or extract

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, no problem. 👍

constructor(props) {
super();

const { initialDates, maxDate, minDate } = props;
Copy link
Contributor

Choose a reason for hiding this comment

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

is it possible by any chance that props will be changed during the lifetime of the component? if so, should you handle it somehow by componentWillReceiveProps?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@asci will add a test for that 👍


Calendar.defaultProps = {
dataAttrs: {},
mods: [],
Copy link
Contributor

Choose a reason for hiding this comment

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

potential reference issue

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@asci how come? AFAIK, React's props are immutable since 0.14, are they not?

Copy link
Contributor

Choose a reason for hiding this comment

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

unless you're not modifying it in the render function it's ok. but somebody else could not notice it and add some
mods.push('some-mod') and it will change mods across all instances of this component. It is not a bug in your code, but potential weak point and I consider as a "better practice" not to put objects\arrays into default props object

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmmm I see... good point. Will prevent that then :) 👍 thanks.

import { getClassNamesWithMods } from '../../_helpers';
import DaysView from '../views/days';

export default class Days extends React.Component {
Copy link
Contributor

Choose a reason for hiding this comment

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

could be replaced by stateless component

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes indeed... Will take care of that.

const limits = selectedDates.map(item => (item ? item.getTime() : null));
const selectedDatesAreEqual = (limits.length === 2) && (limits[0] === limits[1]);

while (counter < 42) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Answer to the Ultimate Question of Life, the Universe, and Everything?:D

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Well I can add a description but 7 days * 6 rows = 42 options/buttons.

const selectedDatesAreEqual = (limits.length === 2) && (limits[0] === limits[1]);

while (counter < 42) {
const extraClasses = [];
Copy link
Contributor

Choose a reason for hiding this comment

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

maybe mods?

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 I just didn't want it to be confused with the render's mods :)

disabled={isPreviousMonthDisabled}
onClick={onNavPreviousMonth}
type="button"
>&lt;</button>
Copy link
Contributor

Choose a reason for hiding this comment

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

here should be an icon, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes :) That's my next challenge 😄 ... Probably will expose via props what you can pass as nav buttons (next and previous).

@@ -23,8 +23,11 @@ generic:
accent-darker: &accent-darker '#0B4848'
accent-dark: &accent-dark '#177D7D'
accent: &accent '#2A9595'
accent-border: &accent-border '#E6BB00'
Copy link
Contributor

Choose a reason for hiding this comment

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

this is yellow, not Lochinvar color, wich we use for an accent color in the default theme

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not what? :| the accent border was not there I added it lol.

Didn't even knew that we had any specific system to choose the colors 😮 .

Then you'll have to tell me how to select them ;-) (And I have to admit that the calendar colors look a little bit bad now 😄 )

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@asci are those colors better?

@coveralls
Copy link

Coverage Status

Coverage remained the same at 100.0% when pulling 18eae2f on add-calendar-component into 895767e on master.

@coveralls
Copy link

Coverage Status

Coverage remained the same at 100.0% when pulling 8306d42 on add-calendar-component into 895767e on master.

@coveralls
Copy link

Coverage Status

Coverage remained the same at 100.0% when pulling 3ea23a5 on add-calendar-component into 895767e on master.

@mAiNiNfEcTiOn
Copy link
Contributor Author

Now, let's go onto the icons and accessibility!

@coveralls
Copy link

Coverage Status

Coverage remained the same at 100.0% when pulling 982df55 on add-calendar-component into 895767e on master.

@coveralls
Copy link

Coverage Status

Coverage remained the same at 100.0% when pulling a447aef on add-calendar-component into 895767e on master.

@coveralls
Copy link

Coverage Status

Coverage remained the same at 100.0% when pulling 6754fab on add-calendar-component into 895767e on master.

@coveralls
Copy link

Coverage Status

Coverage remained the same at 100.0% when pulling 2c60581 on add-calendar-component into 895767e on master.

@coveralls
Copy link

Coverage Status

Coverage remained the same at 100.0% when pulling 87342a9 on add-calendar-component into 895767e on master.

@coveralls
Copy link

Coverage Status

Coverage remained the same at 100.0% when pulling 9ce15f9 on add-calendar-component into 895767e on master.

@mAiNiNfEcTiOn
Copy link
Contributor Author

Ok, now tackling the componentWillReceiveProps ... 😄

@coveralls
Copy link

Coverage Status

Coverage remained the same at 100.0% when pulling 786e2e2 on add-calendar-component into 895767e on master.

@mAiNiNfEcTiOn
Copy link
Contributor Author

Ok... now, support for setting the content of the next and previous buttons! 😄

Also, I'll be adding the possibility to set the 'aria-label' sentence.

Adds the Calendar component

Updates the example to show the dates (not final)

Changes the DaysPanel to export directly the class

Makes the code more explicit on the calendar.js

Makes the styles customizable

Fixes the _default.yaml to be able to build

Fixes SCSS to build :D

Changes the builder to actually output (and colorize) when an error happens

Adds classNames to elements to make them more specific

Fixes bug where an error would be triggered when the initialDates attribute was not set. Also resets the minLimit to the passed one when provided via attributes or to null when none is available

Hides the nav button when not enabled

Changes the _default.yaml to have decent colors for the rendering :P

Adds the function leftPad() to the helpers to do left padding of the months and days

Improves the code based on the reviews' feedback. Also makes it more testable and fixes some bugs detected when developing the unit tests

Converts the DaysPanel to a stateless component with no mods (for now)

Improves the code based on reviews' feedback. Also makes it more testable and introduces a new method to merge the locale definitions

Removes the enzyme-to-json package and brings jest-serializdr-enzyme which is then configured in the jest config

Reverts the removal to give time to migrate the other unit tests. Adds the serializer configuration to the jest.config.json

Adds the unit tests and its snapshots

Updates the tests for UTC

Removes the mods and the dataAttrs from the 'defaultProps'.

Updates the snapshots

Attempt to set some colors matching the defined color pattern

Updates the snapshots

Adds some aria-labels to increase accessibility

Adds updated snapshots

Fixes a lint error :P

Adds a function to normalize the dates on the time

Changes the code to use the newly added function

Updates the tests to use the normalizeDate() and updates the snapshots

Moves the 'bind' to its own declaration, to prevent warnings from linting

Changed the 'extraClasses' variable to be named 'mods'

Changes the 'npm test' to set the testing to be always UTC (to solve CI issues)

Also added the TZ=utc to the update-snapshots script

Adds a function processProps() to be used by both the constructor and the componentWillReceiveProps() from the Calendar component

Adds a wrapper component to make the test of the props being changed. Also adds a test to verify the componentWillReceiveProps. Updates the snapshots

Improves coverage of the componentWillReceiveProps

Downgraded eslint-plugin-react due to a bug on the jsx-indent rule: jsx-eslint/eslint-plugin-react#1117

Fixes the issue with the eslint-plugin-react's version, enabling the indentLogicalExpressions

Adds the possibility to override the display text in the navigation buttons, as well as the aria-label attribute
@coveralls
Copy link

Coverage Status

Coverage remained the same at 100.0% when pulling 71b681b on add-calendar-component into 895767e on master.

@coveralls
Copy link

Coverage Status

Coverage remained the same at 100.0% when pulling 71b681b on add-calendar-component into 895767e on master.

@mAiNiNfEcTiOn
Copy link
Contributor Author

Now, only missing the documentation (finally).

@fahad19
Copy link

fahad19 commented Mar 20, 2017

that's a LOT of work! 👏

@mAiNiNfEcTiOn
Copy link
Contributor Author

@asci , @reaktivo , @fahad19, @AlexDudar, @EduardTrutsyk and @iwwwi , can you please review it now?

@asci
Copy link
Contributor

asci commented Mar 21, 2017

Are we going to reuse this calendar on our platfrom apart from home page? So far we have only one place where use calendar.

@mAiNiNfEcTiOn
Copy link
Contributor Author

@asci The CarTrawler widget will have a Search box which will use the calendar as well...

Copy link
Contributor

@AlexDudar AlexDudar left a comment

Choose a reason for hiding this comment

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

well done Ricardo!

function processProps(props) {
const { initialDates, maxDate, minDate, selectionType } = props;
const maxLimit = maxDate ? normalizeDate(new Date(maxDate), 23, 59, 59, 999) : null;
const renderDate = normalizeDate(((initialDates && initialDates.length && initialDates[0])
Copy link

Choose a reason for hiding this comment

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

does it have any side-effect?

what happens to the original Date object, that is passed to this Calendar component from parent component?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@fahad19 it is mutated. But that's what happens when you call .setHours() or any of it's sister functions :)

But that's why it's called normalizeDate and not returnNewNormalizedDate or something 😄

However, side effects imply that the function is changing things that are not passed to it - implying knowledge of variables outside it's scope, etc - which is not the case.

Regarding your last question, if you check this exact code, it's doing a new Date() of the string coming from the initialDates[0] (when applicable)...

I will improve a little bit the readability.

Copy link

Choose a reason for hiding this comment

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

is there any specific reason for choosing the approach of normalizeDate() over returnNewNormalizedDate()?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@fahad19 check if it's better :)

Copy link

Choose a reason for hiding this comment

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

I agree with you about what you mentioned about side-effects. The only problem we have here is that it is still referencing the parent Component's props.

I would always avoid props mutation of any kind in React. If I really need to transform the value in some way, and expect the Component to re-render on further changes, I would use .setState(), and scope it under the current Component only. Without affecting parent(s).

Similar issue was found in another PR few weeks ago. I think @asci wanted to created a Story out of it so all affected components are updated to avoid this issue.

@coveralls
Copy link

Coverage Status

Coverage remained the same at 100.0% when pulling 0d85c3d on add-calendar-component into 895767e on master.

@mAiNiNfEcTiOn
Copy link
Contributor Author

@AlexDudar thanks ;)

@coveralls
Copy link

Coverage Status

Coverage remained the same at 100.0% when pulling c929a9a on add-calendar-component into 895767e on master.

@mAiNiNfEcTiOn mAiNiNfEcTiOn merged commit c83a57f into master Mar 21, 2017
@mAiNiNfEcTiOn mAiNiNfEcTiOn deleted the add-calendar-component branch March 21, 2017 12:50
@mAiNiNfEcTiOn mAiNiNfEcTiOn added this to Done in Components Sep 7, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
Development

Successfully merging this pull request may close these issues.

None yet

5 participants