-
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
Create new class for DateRangePicker state internals #619
Create new class for DateRangePicker state internals #619
Conversation
@palantir/blueprint i'm gonna keep going ahead along these lines if this looks good |
export function getDateNextMonth(date: Date): Date { | ||
const nextMonth = getNextMonth([date.getMonth(), date.getFullYear()]); | ||
return new Date(nextMonth[1], nextMonth[0]); | ||
} |
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.
nit: Missing newline?
|
||
// returns 1 if left < right | ||
// returns -1 if left > right | ||
// returns 0 if left === right |
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 comparator scheme is backward, no? Should return -1
if the left one is lesser, +1
if the left one is greater.
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 was going for "in-order is truthy", but agree that following standard convention is easier to understand. Updated
|
||
type MonthAndYear = [number, number]; | ||
|
||
function getPreviousMonth([month, year]: MonthAndYear): MonthAndYear { |
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.
Looks like this function isn't referenced anywhere. Do we still need it?
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.
return month === Months.JANUARY ? [Months.DECEMBER, year - 1] : [month - 1, year]; | ||
} | ||
|
||
function getNextMonth([month, year]: MonthAndYear): MonthAndYear { |
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.
Same.
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.
@@ -16,7 +16,7 @@ import * as Errors from "../src/common/errors"; | |||
import { Months } from "../src/common/months"; | |||
import { Classes as DateClasses, DateRange, DateRangePicker, IDateRangePickerProps } from "../src/index"; | |||
|
|||
describe("<DateRangePicker>", () => { | |||
xdescribe("<DateRangePicker>", () => { |
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.
Reasoning behind xdescribe
vs. describe.skip
? Reads more clearly if it'll behave equivalently for you.
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 prefer describe.skip
for readability. also we have lint rules banning describe.skip
so you won't accidentally commit merge it.
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.
oh nice, i can't find those rules - is it possible to also lint for the xit
and xdescribe
variants?
private date: Date; | ||
|
||
constructor (month: number, year: number) { | ||
if (month !== null && year !== null) { |
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 they are optional then mark them as such.
constructor(month?: number, year?: number)
|
||
type MonthAndYear = [number, number]; | ||
|
||
function getPreviousMonth([month, year]: MonthAndYear): MonthAndYear { |
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.
return month === Months.JANUARY ? [Months.DECEMBER, year - 1] : [month - 1, year]; | ||
} | ||
|
||
function getNextMonth([month, year]: MonthAndYear): MonthAndYear { |
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.
} | ||
|
||
public isAfter(displayMonth: DisplayMonth): boolean { | ||
return compareDisplayMonth(this, displayMonth) === -1; |
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.
do > 0
and < 0
--more readable and robust, as comparators can return other positive/negative values with same semantics.
|
||
import { Months } from "./months"; | ||
|
||
export class DisplayMonth { |
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 might advocate for calling this MonthAndYear
cuz that's what it 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.
yup! made a big rename
rightDisplayMonth: rightDisplay[0], | ||
rightDisplayYear: rightDisplay[1], | ||
}); | ||
private setDisplay(leftDisplayMonth: DisplayMonth, rightDisplayMonth: DisplayMonth) { |
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 function doesn't seem very helpful anymore. could just inline it when used.
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's useful mainly so the setState
in the other methods don't become a pain to read because they're named potentialXXXX
. It's also nice to limit the places we have setState
in this complicated component.
let potentialLeftDisplay: DisplayMonth = [state.leftDisplayMonth, state.leftDisplayYear]; | ||
let potentialRightDisplay: DisplayMonth = [state.rightDisplayMonth, state.rightDisplayYear]; | ||
let potentialLeftDisplay: DisplayMonth = state.leftDisplayMonth.clone(); | ||
let potentialRightDisplay: DisplayMonth = state.rightDisplayMonth.clone(); |
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.
def don't need to explicitly type these vars
if (compareDisplayMonth(potentialLeftDisplay, potentialRightDisplay) !== DisplayMonthOrder.IN_ORDER) { | ||
potentialLeftDisplay = getPreviousMonth(potentialRightDisplay); | ||
const nextValueEndMonthDisplay: DisplayMonth = | ||
new DisplayMonth(nextValueEnd.getMonth(), nextValueEnd.getFullYear()); |
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 like a .clone()
const nextValueStartMonthDisplay: DisplayMonth = | ||
new DisplayMonth(nextValueStart.getMonth(), nextValueStart.getFullYear()); | ||
const nextValueEndMonthDisplay: DisplayMonth = | ||
new DisplayMonth(nextValueEnd.getMonth(), nextValueEnd.getFullYear()); |
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.
these are both .clone
s?
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 and above are converting Date
s to MonthAndYear
s
if (firstMonth > secondMonth) { | ||
return 1; | ||
} | ||
} |
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 (firstYear === secondYear) {
return firstMonth - secondMonth; // positive number means first is larger
} else {
return firstYear - secondYear; // negative number means second is larger
}
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.
well aint that neat, updated!
@@ -415,53 +415,51 @@ export class DateRangePicker | |||
* and rectify appropriately. | |||
*/ | |||
private handleLeftYearSelectChange = (leftDisplayYear: number) => { | |||
let potentialLeftDisplay = new DisplayMonth(this.state.leftDisplayMonth.getMonth(), leftDisplayYear); | |||
let potentialLeftMonthAndYear = new MonthAndYear(this.state.leftMonthAndYear.getMonth(), leftDisplayYear); |
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.
ok we get it, there's a month and a year! 😛
leftDisplayMonth: potentialLeftDisplay, | ||
rightDisplayMonth: potentialRightDisplay, | ||
leftMonthAndYear: potentialLeftMonthAndYear, | ||
rightMonthAndYear: potentialRightMonthAndYear, |
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.
but actually renaming all these variables makes this thing dang near impossible to read. what if all the variables called it a View
instead of MonthAndYear
? so much shorter and more digestible.
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.
even better! the logic's pretty readable now
The current way that we handle the
displayMonth
and in the state inDateRangePicker
makes the code pretty unreadable if you do the obvious extension to the state as in #575.Want to see how folks feel about creating a new class with all the comparison and helper methods. Caveat is that in the edge cases, you can end up cloning and recreating a lot of classes, but they're just functions anyway so shouldn't hit any perf problems.
This change along with the comments in the blocks from #575 should make things a lot easier to parse.
NB. Want some feedback if this is an awful idea before I clean up the duplication and un-disable the tests