Skip to content

Commit

Permalink
feat(datepicker): Make from/to dates inclusive
Browse files Browse the repository at this point in the history
  • Loading branch information
mst101 committed Oct 13, 2023
1 parent d6689f0 commit b27f3a4
Show file tree
Hide file tree
Showing 17 changed files with 104 additions and 94 deletions.
6 changes: 3 additions & 3 deletions docs/guide/DisabledDates/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ var state = {
}
```

All dates before 2016-01-05 are disabled.
2016-01-05 and all earlier dates are disabled.

## Disable from a specific date

Expand All @@ -37,7 +37,7 @@ var state = {
}
```

All dates after 2016-01-26 are disabled.
2016-01-26 and all later dates are disabled.

## Disable specific days of the week

Expand Down Expand Up @@ -102,7 +102,7 @@ var state = {
}
```

The dates from 2016-12-26 to 2016-12-29 (inclusive) and 2017-02-13 to 2017-03-24
The dates from 2016-12-25 to 2016-12-30 (inclusive) and 2017-02-12 to 2017-03-25
(inclusive) are disabled.

## Disable based on custom logic
Expand Down
4 changes: 2 additions & 2 deletions docs/guide/HighlightedDates/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ var state = {
}
```

Everything before 2016-01-05 is highlighted.
2016-01-05 and all earlier dates are highlighted.

## Highlight from a specific date

Expand All @@ -35,7 +35,7 @@ var state = {
}
```

Everything after 2016-01-26 is highlighted.
2016-01-26 and all later dates are highlighted.

## Highlight specific days of the week

Expand Down
5 changes: 5 additions & 0 deletions docs/guide/Migration/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
# Migration

## 5.x.x to 6.x.x

- disabled and highlighted `to`/`from` dates are now **inclusive** e.g. `<DatePicker :disabled-dates="{ from: new Date(2023, 6, 15) }" />` now disables 15th July 2023 and all dates beyond.

## 4.x.x to 5.x.x

- the datepicker now supports Vue 3. Please use version 4.x.x for Vue 2 compatibility.
- the `selected` event has been deprecated in favour of `input`. You should therefore listen to `input` events on the datepicker, or simply bind your date via v-model: `<DatePicker v-model="myDate" />`
- a `typeable` datepicker no longer selects the date each time the input string can be parsed to a date. Instead, a typed date is only selected - and an `input` event fired - when the input field is focused and the `enter` key is pressed, or when the datepicker loses focus entirely.
- a new `changed` event is emitted whenever the selected date deviates from its previous value.
Expand Down
20 changes: 10 additions & 10 deletions src/components/PickerDay.vue
Original file line number Diff line number Diff line change
Expand Up @@ -204,11 +204,7 @@ export default {
return false
}
const { from } = this.disabledConfig
const disabledFromMonth = this.utils.monthYearDate(from.year, from.month)
const pageMonth = this.utils.monthYearDate(this.pageYear, this.pageMonth)
return disabledFromMonth <= pageMonth
return this.latestPossibleDate < this.firstOfNextMonth
},
/**
* Is the previous month disabled?
Expand All @@ -219,11 +215,15 @@ export default {
return false
}
const { to } = this.disabledConfig
const disabledToMonth = this.utils.monthYearDate(to.year, to.month)
const pageMonth = this.utils.monthYearDate(this.pageYear, this.pageMonth)
return disabledToMonth >= pageMonth
return this.earliestPossibleDate > this.lastOfPreviousMonth
},
/**
* The first day of the next page's month.
* @return {Date}
*/
lastOfPreviousMonth() {
const d = new Date(this.pageDate)
return new Date(this.utils.setDate(d, 0))
},
/**
* Returns the current page's month as an integer.
Expand Down
4 changes: 2 additions & 2 deletions src/components/PickerMonth.vue
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export default {
if (!this.disabledConfig.has.from) {
return false
}
return this.disabledConfig.from.year <= this.pageYear
return this.latestPossibleDate <= new Date(this.pageYear, 11, 31)
},
/**
* Is the previous year disabled?
Expand All @@ -113,7 +113,7 @@ export default {
if (!this.disabledConfig.has.to) {
return false
}
return this.disabledConfig.to.year >= this.pageYear
return this.earliestPossibleDate >= new Date(this.pageYear, 0, 1)
},
/**
* Display the current page's year as the title.
Expand Down
6 changes: 4 additions & 2 deletions src/components/PickerYear.vue
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,8 @@ export default {
if (!this.disabledConfig.has.from) {
return false
}
return this.disabledConfig.from.year <= this.pageDecadeEnd
const firstDayOfNextDecade = new Date(this.pageDecadeEnd + 1, 0, 1)
return this.latestPossibleDate < firstDayOfNextDecade
},
/**
* Is the previous decade disabled?
Expand All @@ -123,7 +124,8 @@ export default {
if (!this.disabledConfig.has.to) {
return false
}
return this.disabledConfig.to.year >= this.pageDecadeStart
const lastDayOfPreviousDecade = new Date(this.pageDecadeStart - 1, 11, 31)
return this.earliestPossibleDate > lastDayOfPreviousDecade
},
/**
* The year at which the current yearRange starts
Expand Down
12 changes: 0 additions & 12 deletions src/utils/DateUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -390,18 +390,6 @@ const utils = {
)
},

/**
* Create a date object from a month and year, using UTC or not
* @param {Number} year
* @param {Number} monthIndex
* @return {Date}
*/
monthYearDate(year, monthIndex) {
return this.useUtc
? new Date(Date.UTC(year, monthIndex, 1))
: new Date(year, monthIndex, 1)
},

/**
* Return a new date object with hours/minutes/seconds/milliseconds removed.
* Defaults to today's date, if no parameter is provided
Expand Down
6 changes: 3 additions & 3 deletions src/utils/DisabledDate.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ export default class DisabledDate {

return {
to: () => {
return has.to && date < disabledDates.to
return has.to && date <= disabledDates.to
},
from: () => {
return has.from && date > disabledDates.from
return has.from && date >= disabledDates.from
},
range: () => {
if (!has.ranges) return false
Expand All @@ -58,7 +58,7 @@ export default class DisabledDate {
const hasTo = u.isDefined(thisRange, 'to')

return (
hasFrom && hasTo && date < thisRange.to && date > thisRange.from
hasFrom && hasTo && date <= thisRange.to && date >= thisRange.from
)
})
},
Expand Down
4 changes: 2 additions & 2 deletions src/utils/HighlightedDate.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,10 @@ export default class HighlightedDate {

return {
to: () => {
return has.to && date < highlightedDates.to
return has.to && date <= highlightedDates.to
},
from: () => {
return has.from && date > highlightedDates.from
return has.from && date >= highlightedDates.from
},
range: () => {
if (!has.ranges) return false
Expand Down
8 changes: 4 additions & 4 deletions test/e2e/specs/CellNavigation.feature
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ Feature: Cell Navigation

Examples:
| # | openDate | direction | view | toOrFrom | disabled | page | focusedCell |
| 1 | 2020-01-01 | up | day | to | 2019-12-26 | previous | 26 |
| 2 | 2020-01-31 | down | day | from | 2020-02-05 | next | 5 |
| 1 | 2020-01-01 | up | day | to | 2019-12-25 | previous | 26 |
| 2 | 2020-01-31 | down | day | from | 2020-02-06 | next | 5 |
| 3 | 2020-01-01 | up | month | to | 2019-12-01 | previous | December |
| 4 | 2019-12-31 | down | month | from | 2020-01-31 | next | January |
| 5 | 2022-01-01 | up | year | to | 2019-01-01 | previous | 2019 |
Expand All @@ -59,8 +59,8 @@ Feature: Cell Navigation

Examples:
| # | openDate | direction | view | toOrFrom | disabled | focusedCell |
| 1 | 2020-01-15 | left | day | to | 2020-01-14 | 14 |
| 2 | 2020-01-15 | right | day | from | 2020-01-16 | 16 |
| 1 | 2020-01-15 | left | day | to | 2020-01-13 | 14 |
| 2 | 2020-01-15 | right | day | from | 2020-01-17 | 16 |
| 3 | 2020-06-01 | left | month | to | 2020-05-15 | May |
| 4 | 2020-06-01 | right | month | from | 2020-07-15 | July |
| 5 | 2023-01-01 | left | year | to | 2022-06-01 | 2022 |
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/specs/InitialFocus/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ describe('Set the initial focus', () => {
})

Then('the {string} day cell has focus', (firstAvailableCell) => {
const cellId = firstAvailableCell === 'next-day' ? 19 : 4
const cellId = firstAvailableCell === 'next-day' ? 20 : 4

cy.get(`[data-id=${cellId}]`).should('have.focus')
})
Expand Down
4 changes: 2 additions & 2 deletions test/unit/specs/DatePicker/Datepicker.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -696,8 +696,8 @@ describe('Datepicker mounted and attached to body with openDate', () => {
it('cannot arrow to a disabled page', async () => {
await wrapper.setProps({
disabledDates: {
to: new Date(2020, 0, 1),
from: new Date(2020, 0, 31),
to: new Date(2019, 11, 31),
from: new Date(2020, 1, 1),
},
})

Expand Down
7 changes: 0 additions & 7 deletions test/unit/specs/DateUtils.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -309,11 +309,4 @@ describe('UTC functions', () => {
expect(dateUtils.getTime()).toEqual('T00:00:00')
expect(utcUtils.getTime()).toEqual('T00:00:00Z')
})

it('monthYearDate', () => {
expect(dateUtils.monthYearDate(2000, 0)).toEqual(new Date(2000, 0, 1))
expect(utcUtils.monthYearDate(2000, 0)).toEqual(
new Date(Date.UTC(2000, 0, 1)),
)
})
})
36 changes: 23 additions & 13 deletions test/unit/specs/PickerDay/disabledDates.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,10 @@ describe('PickerDay mounted', () => {
},
})

expect(wrapper.vm.isDisabledDate(new Date(2005, 6, 5))).toEqual(false)
expect(wrapper.vm.isDisabledDate(new Date(2005, 6, 6))).toEqual(true)
expect(wrapper.vm.isDisabledDate(new Date(2030, 11, 24))).toEqual(true)
expect(wrapper.vm.isDisabledDate(new Date(2030, 11, 25))).toEqual(false)
expect(wrapper.vm.isDisabledDate(new Date(2005, 6, 4))).toEqual(false)
expect(wrapper.vm.isDisabledDate(new Date(2005, 6, 5))).toEqual(true)
expect(wrapper.vm.isDisabledDate(new Date(2030, 11, 25))).toEqual(true)
expect(wrapper.vm.isDisabledDate(new Date(2030, 11, 26))).toEqual(false)
})

it('accepts an array of disabled days of the week', async () => {
Expand Down Expand Up @@ -117,16 +117,26 @@ describe('PickerDay mounted', () => {
expect(wrapper.vm.isDisabledDate(new Date(2016, 9, 11))).toEqual(false)
})

it('sets `isNextDisabled` and `isPreviousDisabled` correctly', async () => {
it.only('sets `isNextDisabled` and `isPreviousDisabled` correctly', async () => {
await wrapper.setProps({
disabledDates: {
from: new Date(2016, 9, 26),
to: new Date(2016, 9, 4),
to: new Date(2016, 8, 30),
from: new Date(2016, 10, 1),
},
})

expect(wrapper.vm.isNextDisabled).toBeTruthy()
expect(wrapper.vm.isPreviousDisabled).toBeTruthy()

await wrapper.setProps({
disabledDates: {
to: new Date(2016, 8, 29),
from: new Date(2016, 10, 2),
},
})

expect(wrapper.vm.isNextDisabled).toBeFalsy()
expect(wrapper.vm.isPreviousDisabled).toBeFalsy()
})

it('knows the earliest possible date', async () => {
Expand All @@ -135,7 +145,7 @@ describe('PickerDay mounted', () => {
await wrapper.setProps({
disabledDates: {
dates: [new Date(2016, 9, 4)],
to: new Date(2016, 9, 4),
to: new Date(2016, 9, 3),
},
})

Expand All @@ -154,7 +164,7 @@ describe('PickerDay mounted', () => {
},
})

expect(wrapper.vm.earliestPossibleDate).toEqual(new Date(2016, 9, 8))
expect(wrapper.vm.earliestPossibleDate).toEqual(new Date(2016, 9, 9))
})

it('knows the latest possible date', async () => {
Expand All @@ -163,25 +173,25 @@ describe('PickerDay mounted', () => {
await wrapper.setProps({
disabledDates: {
dates: [new Date(2016, 9, 26)],
from: new Date(2016, 9, 26),
from: new Date(2016, 9, 27),
},
})

expect(wrapper.vm.latestPossibleDate).toEqual(new Date(2016, 9, 25))

await wrapper.setProps({
disabledDates: {
dates: [new Date(2016, 9, 26)],
dates: [new Date(2016, 9, 19)],
ranges: [
{
from: new Date(2016, 9, 20),
to: new Date(2016, 9, 28),
},
],
from: new Date(2016, 9, 26),
from: new Date(2016, 9, 29),
},
})

expect(wrapper.vm.latestPossibleDate).toEqual(new Date(2016, 9, 20))
expect(wrapper.vm.latestPossibleDate).toEqual(new Date(2016, 9, 25))
})
})
Loading

0 comments on commit b27f3a4

Please sign in to comment.