From 1fea825cf5eabecc95b24935ebe04821fa167a7d Mon Sep 17 00:00:00 2001 From: jacekkarczmarczyk Date: Sat, 27 Jan 2018 17:53:06 +0700 Subject: [PATCH 1/3] feat (v-date-picker): lazy prop --- .../VDatePicker/VDatePicker.date.spec.js | 15 --- src/components/VDatePicker/VDatePicker.js | 111 +++++++----------- .../VDatePicker/VDatePicker.month.spec.js | 15 --- .../VDatePicker/VDatePickerTitle.js | 2 +- 4 files changed, 41 insertions(+), 102 deletions(-) diff --git a/src/components/VDatePicker/VDatePicker.date.spec.js b/src/components/VDatePicker/VDatePicker.date.spec.js index 42fbea43fe5..71d2bff7dfd 100644 --- a/src/components/VDatePicker/VDatePicker.date.spec.js +++ b/src/components/VDatePicker/VDatePicker.date.spec.js @@ -332,21 +332,6 @@ test('VDatePicker.js', ({ mount, compileToFunctions }) => { expect(wrapper.vm.tableDate).toBe('2004-11') }) - it('should calculate the first allowed date', () => { - const now = new Date() - const year = now.getFullYear() - const month = now.getMonth() - const date = now.getDate() - - const wrapper2 = mount(VDatePicker, { - propsData: { - value: null, - allowedDates: value => value === `${year}-${(month < 9 ? '0' : '') + (month + 1)}-03` - } - }) - expect(wrapper2.vm.inputDate).toBe(`${year}-${(month < 9 ? '0' : '') + (month + 1)}-03`) - }) - it('should set the table date when value has changed', () => { const wrapper = mount(VDatePicker, { propsData: { diff --git a/src/components/VDatePicker/VDatePicker.js b/src/components/VDatePicker/VDatePicker.js index 771419ffcfa..a15c262882f 100644 --- a/src/components/VDatePicker/VDatePicker.js +++ b/src/components/VDatePicker/VDatePicker.js @@ -36,6 +36,9 @@ export default { return { activePicker: this.type.toUpperCase(), defaultColor: 'accent', + inputDay: null, + inputMonth: null, + inputYear: null, isReversing: false, now, // tableDate is a string in 'YYYY' / 'YYYY-M' format (leading zero for month is not required) @@ -79,6 +82,7 @@ export default { type: Function, default: null }, + lazy: Boolean, locale: { type: String, default: 'en-us' @@ -128,62 +132,10 @@ export default { return this.showCurrent || null }, - firstAllowedDate () { - const year = this.now.getFullYear() - const month = this.now.getMonth() - - if (this.allowedDates) { - for (let date = 1; date <= 31; date++) { - const dateString = `${year}-${month + 1}-${date}` - if (isNaN(new Date(dateString).getDate())) break - - const sanitizedDateString = this.sanitizeDateString(dateString, 'date') - if (this.isDateAllowed(sanitizedDateString)) { - return sanitizedDateString - } - } - } - - return this.sanitizeDateString(`${year}-${month + 1}-${this.now.getDate()}`, 'date') - }, - firstAllowedMonth () { - const year = this.now.getFullYear() - - if (this.allowedDates) { - for (let month = 0; month < 12; month++) { - const dateString = `${year}-${pad(month + 1)}` - if (this.isDateAllowed(dateString)) { - return dateString - } - } - } - - return `${year}-${pad(this.now.getMonth() + 1)}` - }, - // inputDate MUST be a string in ISO 8601 format (including leading zero for month/day) - // YYYY-MM for month picker - // YYYY-MM-DD for date picker - inputDate: { - get () { - if (this.value) { - return this.sanitizeDateString(this.value, this.type) - } - - return this.type === 'month' ? this.firstAllowedMonth : this.firstAllowedDate - }, - set (value) { - const date = value ? this.sanitizeDateString(value, this.type) : null - this.$emit('input', date) - } - }, - day () { - return this.inputDate.split('-')[2] * 1 - }, - month () { - return this.inputDate.split('-')[1] - 1 - }, - year () { - return this.inputDate.split('-')[0] * 1 + inputDate () { + return this.type === 'date' + ? `${this.inputYear}-${pad(this.inputMonth + 1)}-${pad(this.inputDay)}` + : `${this.inputYear}-${pad(this.inputMonth + 1)}` }, tableMonth () { return (this.pickerDate || this.tableDate).split('-')[1] - 1 @@ -247,8 +199,9 @@ export default { } }, value () { + this.setInputDate() if (this.value && !this.pickerDate) { - this.tableDate = this.type === 'month' ? `${this.year}` : `${this.year}-${pad(this.month + 1)}` + this.tableDate = this.sanitizeDateString(this.inputDate, this.type === 'month' ? 'year' : 'month') } }, type (type) { @@ -266,39 +219,40 @@ export default { return isDateAllowed(value, this.min, this.max, this.allowedDates) }, yearClick (value) { + this.inputYear = value if (this.type === 'month') { - const date = `${value}-${pad(this.month + 1)}` - if (this.isDateAllowed(date)) this.inputDate = date this.tableDate = `${value}` } else { - const date = `${value}-${pad(this.tableMonth + 1)}-${pad(this.day)}` - if (this.isDateAllowed(date)) this.inputDate = date this.tableDate = `${value}-${pad(this.tableMonth + 1)}` } this.activePicker = 'MONTH' + !this.lazy && this.isDateAllowed(this.inputDate) && this.$emit('input', this.inputDate) }, monthClick (value) { - // Updates inputDate setting 'YYYY-MM' or 'YYYY-MM-DD' format, depending on the picker type + this.inputYear = parseInt(value.split('-')[0], 10) + this.inputMonth = parseInt(value.split('-')[1], 10) - 1 if (this.type === 'date') { - const date = `${value}-${pad(this.day)}` - if (this.isDateAllowed(date)) this.inputDate = date this.tableDate = value this.activePicker = 'DATE' + !this.lazy && this.isDateAllowed(this.inputDate) && this.$emit('input', this.inputDate) } else { - this.inputDate = value - this.$emit('change', value) + this.$emit('input', this.inputDate) + this.$emit('change', this.inputDate) } }, dateClick (value) { - this.inputDate = value - this.$emit('change', value) + this.inputYear = parseInt(value.split('-')[0], 10) + this.inputMonth = parseInt(value.split('-')[1], 10) - 1 + this.inputDay = parseInt(value.split('-')[2], 10) + this.$emit('input', this.inputDate) + this.$emit('change', this.inputDate) }, genPickerTitle () { return this.$createElement('v-date-picker-title', { props: { - date: this.formatters.titleDate(this.inputDate), + date: this.value ? this.formatters.titleDate(this.value) : '', selectingYear: this.activePicker === 'YEAR', - year: this.formatters.year(`${this.year}`), + year: this.formatters.year(`${this.inputYear}`), yearIcon: this.yearIcon }, slot: 'title', @@ -411,13 +365,28 @@ export default { sanitizeDateString (dateString, type) { const [year, month = 1, date = 1] = dateString.split('-') return `${year}-${pad(month)}-${pad(date)}`.substr(0, { date: 10, month: 7, year: 4 }[type]) + }, + setInputDate () { + if (this.value) { + const array = this.value.split('-') + this.inputYear = parseInt(array[0], 10) + this.inputMonth = parseInt(array[1], 10) - 1 + if (this.type === 'date') { + this.inputDay = parseInt(array[2], 10) + } + } else { + this.inputYear = this.inputYear || this.now.getFullYear() + this.inputMonth = this.inputMonth == null ? this.inputMonth : this.now.getMonth() + this.inputDay = this.inputDay || this.now.getDate() + } } }, - mounted () { + created () { if (this.pickerDate !== this.tableDate) { this.$emit('update:pickerDate', this.tableDate) } + this.setInputDate() }, render (h) { diff --git a/src/components/VDatePicker/VDatePicker.month.spec.js b/src/components/VDatePicker/VDatePicker.month.spec.js index 5711aa701db..1fed40db53b 100755 --- a/src/components/VDatePicker/VDatePicker.month.spec.js +++ b/src/components/VDatePicker/VDatePicker.month.spec.js @@ -174,21 +174,6 @@ test('VDatePicker.js', ({ mount, compileToFunctions }) => { expect(wrapper.vm.tableDate).toBe('2004') }) - it('should calculate the first allowed date', () => { - const now = new Date() - const year = now.getFullYear() - const month = now.getMonth() - - const wrapper2 = mount(VDatePicker, { - propsData: { - value: null, - type: 'month', - allowedDates: value => value === `${year}-03` - } - }) - expect(wrapper2.vm.inputDate).toBe(`${year}-03`) - }) - it('should set the table date when value has changed', () => { const wrapper = mount(VDatePicker, { propsData: { diff --git a/src/components/VDatePicker/VDatePickerTitle.js b/src/components/VDatePicker/VDatePickerTitle.js index 48383f34c5a..fe1857538ca 100644 --- a/src/components/VDatePicker/VDatePickerTitle.js +++ b/src/components/VDatePicker/VDatePickerTitle.js @@ -66,7 +66,7 @@ export default { } }, [ this.$createElement('div', { - domProps: { innerHTML: this.date }, + domProps: { innerHTML: this.date || ' ' }, key: this.date }) ]) From 39e693e715f3a74fe5f32329b68488ff4ab1ee98 Mon Sep 17 00:00:00 2001 From: jacekkarczmarczyk Date: Wed, 31 Jan 2018 19:57:45 +0700 Subject: [PATCH 2/3] test (v-date-picker): lazy prop tests --- .../VDatePicker/VDatePicker.date.spec.js | 57 ++++++++++++++++++- 1 file changed, 54 insertions(+), 3 deletions(-) diff --git a/src/components/VDatePicker/VDatePicker.date.spec.js b/src/components/VDatePicker/VDatePicker.date.spec.js index 71d2bff7dfd..63476c0176e 100644 --- a/src/components/VDatePicker/VDatePicker.date.spec.js +++ b/src/components/VDatePicker/VDatePicker.date.spec.js @@ -40,16 +40,21 @@ test('VDatePicker.js', ({ mount, compileToFunctions }) => { }) it('should emit input event on date click', async () => { - const cb = jest.fn() const wrapper = mount(VDatePicker, { propsData: { value: '2013-05-07' } }) - wrapper.vm.$on('input', cb); + const input = jest.fn() + wrapper.vm.$on('input', input) + + const change = jest.fn() + wrapper.vm.$on('change', change) + wrapper.find('.date-picker-table--date tbody tr+tr td:first-child button')[0].trigger('click') - expect(cb).toBeCalledWith('2013-05-05') + expect(input).toBeCalledWith('2013-05-05') + expect(change).toBeCalledWith('2013-05-05') }) it('should emit input event on month click', async () => { @@ -436,4 +441,50 @@ test('VDatePicker.js', ({ mount, compileToFunctions }) => { await wrapper.vm.$nextTick() expect(wrapper.html()).toMatchSnapshot() }) + + it('should emit @input and not emit @change when month is clicked (not lazy picker)', async () => { + const wrapper = mount(VDatePicker, { + propsData: { + value: '2013-02-07', + lazy: false + }, + data: { + activePicker: 'MONTH' + } + }) + + const input = jest.fn() + wrapper.vm.$on('input', input) + + const change = jest.fn() + wrapper.vm.$on('change', change) + + wrapper.find('tbody tr td button')[0].trigger('click') + wrapper.vm.$nextTick() + expect(change).not.toBeCalled() + expect(input).toBeCalledWith('2013-01-07') + }) + + it('should not emit @input and not emit @change when month is clicked (lazy picker)', async () => { + const wrapper = mount(VDatePicker, { + propsData: { + value: '2013-02-07', + lazy: true + }, + data: { + activePicker: 'MONTH' + } + }) + + const input = jest.fn() + wrapper.vm.$on('input', input) + + const change = jest.fn() + wrapper.vm.$on('change', change) + + wrapper.find('tbody tr td button')[0].trigger('click') + wrapper.vm.$nextTick() + expect(change).not.toBeCalled() + expect(input).not.toBeCalled() + }) }) From f601392fb5ce0e43b4d9118161b9b5b89bfb4220 Mon Sep 17 00:00:00 2001 From: jacekkarczmarczyk Date: Wed, 31 Jan 2018 23:15:51 +0700 Subject: [PATCH 3/3] renamed lazy prop to reactive --- .../VDatePicker/VDatePicker.date.spec.js | 39 +++++++------------ src/components/VDatePicker/VDatePicker.js | 6 +-- .../VDatePicker/VDatePicker.month.spec.js | 16 +++++--- 3 files changed, 28 insertions(+), 33 deletions(-) diff --git a/src/components/VDatePicker/VDatePicker.date.spec.js b/src/components/VDatePicker/VDatePicker.date.spec.js index 63476c0176e..43c47d0fbe0 100644 --- a/src/components/VDatePicker/VDatePicker.date.spec.js +++ b/src/components/VDatePicker/VDatePicker.date.spec.js @@ -57,22 +57,6 @@ test('VDatePicker.js', ({ mount, compileToFunctions }) => { expect(change).toBeCalledWith('2013-05-05') }) - it('should emit input event on month click', async () => { - const cb = jest.fn() - const wrapper = mount(VDatePicker, { - propsData: { - value: '2013-05-13' - }, - data: { - activePicker: 'MONTH' - } - }) - - wrapper.vm.$on('input', cb); - wrapper.find('.date-picker-table--month button')[0].trigger('click') - expect(cb).toBeCalledWith('2013-01-13') - }) - it('should not emit input event on month click if date is not allowed', async () => { const cb = jest.fn() const wrapper = mount(VDatePicker, { @@ -90,20 +74,26 @@ test('VDatePicker.js', ({ mount, compileToFunctions }) => { expect(cb).not.toBeCalled() }) - it('should emit input event on year click', async () => { - const cb = jest.fn() + it('should emit input event on year click (reactive picker)', async () => { const wrapper = mount(VDatePicker, { propsData: { - value: '2013-05-13' + value: '2013-05-13', + reactive: true }, data: { activePicker: 'YEAR' } }) - wrapper.vm.$on('input', cb); + const input = jest.fn() + wrapper.vm.$on('input', input); + + const change = jest.fn() + wrapper.vm.$on('change', input); + wrapper.find('.date-picker-years li.active + li')[0].trigger('click') - expect(cb).toBeCalledWith('2012-05-13') + expect(input).toBeCalledWith('2012-05-13') + expect(change).not.toBeCalled() }) it('should not emit input event on year click if date is not allowed', async () => { @@ -442,11 +432,11 @@ test('VDatePicker.js', ({ mount, compileToFunctions }) => { expect(wrapper.html()).toMatchSnapshot() }) - it('should emit @input and not emit @change when month is clicked (not lazy picker)', async () => { + it('should emit @input and not emit @change when month is clicked (not reative picker)', async () => { const wrapper = mount(VDatePicker, { propsData: { value: '2013-02-07', - lazy: false + reactive: true }, data: { activePicker: 'MONTH' @@ -468,8 +458,7 @@ test('VDatePicker.js', ({ mount, compileToFunctions }) => { it('should not emit @input and not emit @change when month is clicked (lazy picker)', async () => { const wrapper = mount(VDatePicker, { propsData: { - value: '2013-02-07', - lazy: true + value: '2013-02-07' }, data: { activePicker: 'MONTH' diff --git a/src/components/VDatePicker/VDatePicker.js b/src/components/VDatePicker/VDatePicker.js index a15c262882f..ef238f6031f 100644 --- a/src/components/VDatePicker/VDatePicker.js +++ b/src/components/VDatePicker/VDatePicker.js @@ -82,7 +82,6 @@ export default { type: Function, default: null }, - lazy: Boolean, locale: { type: String, default: 'en-us' @@ -99,6 +98,7 @@ export default { type: String, default: 'chevron_left' }, + reactive: Boolean, readonly: Boolean, scrollable: Boolean, showCurrent: { @@ -226,7 +226,7 @@ export default { this.tableDate = `${value}-${pad(this.tableMonth + 1)}` } this.activePicker = 'MONTH' - !this.lazy && this.isDateAllowed(this.inputDate) && this.$emit('input', this.inputDate) + this.reactive && this.isDateAllowed(this.inputDate) && this.$emit('input', this.inputDate) }, monthClick (value) { this.inputYear = parseInt(value.split('-')[0], 10) @@ -234,7 +234,7 @@ export default { if (this.type === 'date') { this.tableDate = value this.activePicker = 'DATE' - !this.lazy && this.isDateAllowed(this.inputDate) && this.$emit('input', this.inputDate) + this.reactive && this.isDateAllowed(this.inputDate) && this.$emit('input', this.inputDate) } else { this.$emit('input', this.inputDate) this.$emit('change', this.inputDate) diff --git a/src/components/VDatePicker/VDatePicker.month.spec.js b/src/components/VDatePicker/VDatePicker.month.spec.js index 1fed40db53b..8b49dab5d23 100755 --- a/src/components/VDatePicker/VDatePicker.month.spec.js +++ b/src/components/VDatePicker/VDatePicker.month.spec.js @@ -4,21 +4,27 @@ import VDatePicker from './VDatePicker' import VMenu from '@components/VMenu' test('VDatePicker.js', ({ mount, compileToFunctions }) => { - it('should emit input event on year click', async () => { - const cb = jest.fn() + it('should emit input event on year click (reactive picker)', async () => { const wrapper = mount(VDatePicker, { propsData: { value: '2013-05', - type: 'month' + type: 'month', + reactive: true }, data: { activePicker: 'YEAR' } }) - wrapper.vm.$on('input', cb); + const input = jest.fn() + wrapper.vm.$on('input', input); + + const change = jest.fn() + wrapper.vm.$on('change', input); + wrapper.find('.date-picker-years li.active + li')[0].trigger('click') - expect(cb).toBeCalledWith('2012-05') + expect(input).toBeCalledWith('2012-05') + expect(change).not.toBeCalled() }) it('should not emit input event on year click if month is not allowed', async () => {