From df398cb4213e0b49d2338b371f2dcd12ca005622 Mon Sep 17 00:00:00 2001 From: Matt Lewis Date: Sat, 28 Jan 2017 18:28:28 +0000 Subject: [PATCH] feat: add helper directives for changing the current view See the documentation or the kitchen sink demo to see usage Closes #124 --- .../demo-utils/calendar-header.component.ts | 74 ++++++++----------- demos/demo-modules/kitchen-sink/component.ts | 32 -------- demos/demo-modules/kitchen-sink/template.html | 38 ++++++++-- src/calendar.module.ts | 15 +++- src/directives/calendarNextView.directive.ts | 54 ++++++++++++++ .../calendarPreviousView.directive.ts | 54 ++++++++++++++ src/directives/calendarToday.directive.ts | 38 ++++++++++ test/calendarNextView.directive.spec.ts | 56 ++++++++++++++ test/calendarPreviousView.directive.spec.ts | 56 ++++++++++++++ test/calendarToday.directive.spec.ts | 33 +++++++++ tsconfig-compodoc.json | 5 +- 11 files changed, 372 insertions(+), 83 deletions(-) create mode 100644 src/directives/calendarNextView.directive.ts create mode 100644 src/directives/calendarPreviousView.directive.ts create mode 100644 src/directives/calendarToday.directive.ts create mode 100644 test/calendarNextView.directive.spec.ts create mode 100644 test/calendarPreviousView.directive.spec.ts create mode 100644 test/calendarToday.directive.spec.ts diff --git a/demos/demo-modules/demo-utils/calendar-header.component.ts b/demos/demo-modules/demo-utils/calendar-header.component.ts index 7fbb61a46..a73b05a89 100644 --- a/demos/demo-modules/demo-utils/calendar-header.component.ts +++ b/demos/demo-modules/demo-utils/calendar-header.component.ts @@ -1,12 +1,4 @@ import { Component, Input, Output, EventEmitter } from '@angular/core'; -import { - subDays, - addDays, - addWeeks, - subWeeks, - addMonths, - subMonths -} from 'date-fns'; @Component({ selector: 'mwl-calendar-header', @@ -14,13 +6,24 @@ import {
-
+
Previous
-
+
Today
-
+
Next
@@ -30,9 +33,24 @@ import {
-
Month
-
Week
-
Day
+
+ Month +
+
+ Week +
+
+ Day +
@@ -51,32 +69,4 @@ export class CalendarHeaderComponent { @Output() viewDateChange: EventEmitter = new EventEmitter(); - increment(): void { - - const addFn: any = { - day: addDays, - week: addWeeks, - month: addMonths - }[this.view]; - - this.viewDateChange.emit(addFn(this.viewDate, 1)); - - } - - decrement(): void { - - const subFn: any = { - day: subDays, - week: subWeeks, - month: subMonths - }[this.view]; - - this.viewDateChange.emit(subFn(this.viewDate, 1)); - - } - - today(): void { - this.viewDateChange.emit(new Date()); - } - } \ No newline at end of file diff --git a/demos/demo-modules/kitchen-sink/component.ts b/demos/demo-modules/kitchen-sink/component.ts index 3fba76757..8e34d06a6 100644 --- a/demos/demo-modules/kitchen-sink/component.ts +++ b/demos/demo-modules/kitchen-sink/component.ts @@ -7,10 +7,6 @@ import { endOfMonth, isSameDay, isSameMonth, - addWeeks, - subWeeks, - addMonths, - subMonths, addHours } from 'date-fns'; import { Subject } from 'rxjs/Subject'; @@ -103,34 +99,6 @@ export class DemoComponent { constructor(private modal: NgbModal) {} - increment(): void { - - const addFn: any = { - day: addDays, - week: addWeeks, - month: addMonths - }[this.view]; - - this.viewDate = addFn(this.viewDate, 1); - - } - - decrement(): void { - - const subFn: any = { - day: subDays, - week: subWeeks, - month: subMonths - }[this.view]; - - this.viewDate = subFn(this.viewDate, 1); - - } - - today(): void { - this.viewDate = new Date(); - } - dayClicked({date, events}: {date: Date, events: CalendarEvent[]}): void { if (isSameMonth(date, this.viewDate)) { diff --git a/demos/demo-modules/kitchen-sink/template.html b/demos/demo-modules/kitchen-sink/template.html index 032c33ec6..b38b980c2 100644 --- a/demos/demo-modules/kitchen-sink/template.html +++ b/demos/demo-modules/kitchen-sink/template.html @@ -25,13 +25,24 @@
-
+
Previous
-
+
Today
-
+
Next
@@ -41,9 +52,24 @@

{{ viewDate | calendarDate:(view + 'ViewTitle'):'en' }}

-
Month
-
Week
-
Day
+
+ Month +
+
+ Week +
+
+ Day +
diff --git a/src/calendar.module.ts b/src/calendar.module.ts index d3bfb24bb..89473f529 100644 --- a/src/calendar.module.ts +++ b/src/calendar.module.ts @@ -15,6 +15,9 @@ import { CalendarAllDayEventComponent } from './components/day/calendarAllDayEve import { CalendarDayViewHourSegmentComponent } from './components/day/calendarDayViewHourSegment.component'; import { CalendarDayViewEventComponent } from './components/day/calendarDayViewEvent.component'; import { CalendarTooltipWindowComponent, CalendarTooltipDirective } from './directives/calendarTooltip.directive'; +import { CalendarPreviousViewDirective } from './directives/calendarPreviousView.directive'; +import { CalendarNextViewDirective } from './directives/calendarNextView.directive'; +import { CalendarTodayDirective } from './directives/calendarToday.directive'; import { CalendarDatePipe } from './pipes/calendarDate.pipe'; import { CalendarEventTitlePipe } from './pipes/calendarEventTitle.pipe'; import { CalendarEventTitleFormatter } from './providers/calendarEventTitle.provider'; @@ -51,6 +54,9 @@ import { CalendarDateFormatter } from './providers/calendarDateFormatter.provide CalendarDayViewEventComponent, CalendarTooltipWindowComponent, CalendarTooltipDirective, + CalendarPreviousViewDirective, + CalendarNextViewDirective, + CalendarTodayDirective, CalendarDatePipe, CalendarEventTitlePipe ], @@ -63,9 +69,14 @@ import { CalendarDateFormatter } from './providers/calendarDateFormatter.provide CalendarDayViewComponent, CalendarWeekViewComponent, CalendarMonthViewComponent, - CalendarDatePipe + CalendarDatePipe, + CalendarPreviousViewDirective, + CalendarNextViewDirective, + CalendarTodayDirective ], - entryComponents: [CalendarTooltipWindowComponent] + entryComponents: [ + CalendarTooltipWindowComponent + ] }) export class CalendarModule { diff --git a/src/directives/calendarNextView.directive.ts b/src/directives/calendarNextView.directive.ts new file mode 100644 index 000000000..4e02176ad --- /dev/null +++ b/src/directives/calendarNextView.directive.ts @@ -0,0 +1,54 @@ +import { Directive, HostListener, Input, Output, EventEmitter } from '@angular/core'; +import addDays from 'date-fns/add_days'; +import addWeeks from 'date-fns/add_weeks'; +import addMonths from 'date-fns/add_months'; + +/** + * Change the view date to the next view. For example: + * + * ``` + * <button + * mwlCalendarNextView + * [(viewDate)]="viewDate" + * [view]="view"> + * Next + * </button> + * ``` + */ +@Directive({ + selector: '[mwlCalendarNextView]' +}) +export class CalendarNextViewDirective { + + /** + * The current view + */ + @Input() view: string; + + /** + * The current view date + */ + @Input() viewDate: Date; + + /** + * Called when the view date is changed + */ + @Output() viewDateChange: EventEmitter = new EventEmitter(); + + /** + * @hidden + */ + @HostListener('click') + onClick(): void { + + const addFn: any = { + day: addDays, + week: addWeeks, + month: addMonths + }[this.view]; + + this.viewDateChange.emit(addFn(this.viewDate, 1)); + + } + +} \ No newline at end of file diff --git a/src/directives/calendarPreviousView.directive.ts b/src/directives/calendarPreviousView.directive.ts new file mode 100644 index 000000000..2737ea80a --- /dev/null +++ b/src/directives/calendarPreviousView.directive.ts @@ -0,0 +1,54 @@ +import { Directive, HostListener, Input, Output, EventEmitter } from '@angular/core'; +import subDays from 'date-fns/sub_days'; +import subWeeks from 'date-fns/sub_weeks'; +import subMonths from 'date-fns/sub_months'; + +/** + * Change the view date to the previous view. For example: + * + * ``` + * <button + * mwlCalendarPreviousView + * [(viewDate)]="viewDate" + * [view]="view"> + * Previous + * </button> + * ``` + */ +@Directive({ + selector: '[mwlCalendarPreviousView]' +}) +export class CalendarPreviousViewDirective { + + /** + * The current view + */ + @Input() view: string; + + /** + * The current view date + */ + @Input() viewDate: Date; + + /** + * Called when the view date is changed + */ + @Output() viewDateChange: EventEmitter = new EventEmitter(); + + /** + * @hidden + */ + @HostListener('click') + onClick(): void { + + const subFn: any = { + day: subDays, + week: subWeeks, + month: subMonths + }[this.view]; + + this.viewDateChange.emit(subFn(this.viewDate, 1)); + + } + +} \ No newline at end of file diff --git a/src/directives/calendarToday.directive.ts b/src/directives/calendarToday.directive.ts new file mode 100644 index 000000000..9d5ee6e6b --- /dev/null +++ b/src/directives/calendarToday.directive.ts @@ -0,0 +1,38 @@ +import { Directive, HostListener, Input, Output, EventEmitter } from '@angular/core'; +import startOfToday from 'date-fns/start_of_today'; + +/** + * Change the view date to the current day. For example: + * + * ``` + * <button + * mwlCalendarToday + * [(viewDate)]="viewDate"> + * Today + * </button> + * ``` + */ +@Directive({ + selector: '[mwlCalendarToday]' +}) +export class CalendarTodayDirective { + + /** + * The current view date + */ + @Input() viewDate: Date; + + /** + * Called when the view date is changed + */ + @Output() viewDateChange: EventEmitter = new EventEmitter(); + + /** + * @hidden + */ + @HostListener('click') + onClick(): void { + this.viewDateChange.emit(startOfToday()); + } + +} \ No newline at end of file diff --git a/test/calendarNextView.directive.spec.ts b/test/calendarNextView.directive.spec.ts new file mode 100644 index 000000000..cb2a73e35 --- /dev/null +++ b/test/calendarNextView.directive.spec.ts @@ -0,0 +1,56 @@ +import { Component } from '@angular/core'; +import { + ComponentFixture, + TestBed +} from '@angular/core/testing'; +import { expect } from 'chai'; +import { CalendarModule } from '../src'; + +@Component({ + template: '' +}) +class TestComponent { + public view: string; + public viewDate: Date; +} + +describe('mwlCalendarNextView directive', () => { + + beforeEach(() => { + TestBed.configureTestingModule({imports: [CalendarModule.forRoot()], declarations: [TestComponent]}); + }); + + it('should increase the view date by 1 month', () => { + const fixture: ComponentFixture = TestBed.createComponent(TestComponent); + fixture.componentInstance.view = 'month'; + fixture.componentInstance.viewDate = new Date('2017-01-28'); + fixture.detectChanges(); + fixture.nativeElement.querySelector('button').click(); + fixture.detectChanges(); + expect(fixture.componentInstance.viewDate).to.deep.equal(new Date('2017-02-28')); + fixture.destroy(); + }); + + it('should increase the view date by 1 week', () => { + const fixture: ComponentFixture = TestBed.createComponent(TestComponent); + fixture.componentInstance.view = 'week'; + fixture.componentInstance.viewDate = new Date('2017-01-28'); + fixture.detectChanges(); + fixture.nativeElement.querySelector('button').click(); + fixture.detectChanges(); + expect(fixture.componentInstance.viewDate).to.deep.equal(new Date('2017-02-04')); + fixture.destroy(); + }); + + it('should increase the view date by 1 day', () => { + const fixture: ComponentFixture = TestBed.createComponent(TestComponent); + fixture.componentInstance.view = 'day'; + fixture.componentInstance.viewDate = new Date('2017-01-28'); + fixture.detectChanges(); + fixture.nativeElement.querySelector('button').click(); + fixture.detectChanges(); + expect(fixture.componentInstance.viewDate).to.deep.equal(new Date('2017-01-29')); + fixture.destroy(); + }); + +}); \ No newline at end of file diff --git a/test/calendarPreviousView.directive.spec.ts b/test/calendarPreviousView.directive.spec.ts new file mode 100644 index 000000000..beff18642 --- /dev/null +++ b/test/calendarPreviousView.directive.spec.ts @@ -0,0 +1,56 @@ +import { Component } from '@angular/core'; +import { + ComponentFixture, + TestBed +} from '@angular/core/testing'; +import { expect } from 'chai'; +import { CalendarModule } from '../src'; + +@Component({ + template: '' +}) +class TestComponent { + public view: string; + public viewDate: Date; +} + +describe('calendarPreviousView directive', () => { + + beforeEach(() => { + TestBed.configureTestingModule({imports: [CalendarModule.forRoot()], declarations: [TestComponent]}); + }); + + it('should decrease the view date by 1 month', () => { + const fixture: ComponentFixture = TestBed.createComponent(TestComponent); + fixture.componentInstance.view = 'month'; + fixture.componentInstance.viewDate = new Date('2017-02-28'); + fixture.detectChanges(); + fixture.nativeElement.querySelector('button').click(); + fixture.detectChanges(); + expect(fixture.componentInstance.viewDate).to.deep.equal(new Date('2017-01-28')); + fixture.destroy(); + }); + + it('should decrease the view date by 1 week', () => { + const fixture: ComponentFixture = TestBed.createComponent(TestComponent); + fixture.componentInstance.view = 'week'; + fixture.componentInstance.viewDate = new Date('2017-01-28'); + fixture.detectChanges(); + fixture.nativeElement.querySelector('button').click(); + fixture.detectChanges(); + expect(fixture.componentInstance.viewDate).to.deep.equal(new Date('2017-01-21')); + fixture.destroy(); + }); + + it('should decrease the view date by 1 day', () => { + const fixture: ComponentFixture = TestBed.createComponent(TestComponent); + fixture.componentInstance.view = 'day'; + fixture.componentInstance.viewDate = new Date('2017-01-28'); + fixture.detectChanges(); + fixture.nativeElement.querySelector('button').click(); + fixture.detectChanges(); + expect(fixture.componentInstance.viewDate).to.deep.equal(new Date('2017-01-27')); + fixture.destroy(); + }); + +}); \ No newline at end of file diff --git a/test/calendarToday.directive.spec.ts b/test/calendarToday.directive.spec.ts new file mode 100644 index 000000000..3985ea1fb --- /dev/null +++ b/test/calendarToday.directive.spec.ts @@ -0,0 +1,33 @@ +import { Component } from '@angular/core'; +import { + ComponentFixture, + TestBed +} from '@angular/core/testing'; +import { expect } from 'chai'; +import startOfToday from 'date-fns/start_of_today'; +import { CalendarModule } from '../src'; + +@Component({ + template: '' +}) +class TestComponent { + public viewDate: Date; +} + +describe('mwlCalendarNextView directive', () => { + + beforeEach(() => { + TestBed.configureTestingModule({imports: [CalendarModule.forRoot()], declarations: [TestComponent]}); + }); + + it('should set the view date to the start of today', () => { + const fixture: ComponentFixture = TestBed.createComponent(TestComponent); + fixture.componentInstance.viewDate = new Date('2017-01-28'); + fixture.detectChanges(); + fixture.nativeElement.querySelector('button').click(); + fixture.detectChanges(); + expect(fixture.componentInstance.viewDate).to.deep.equal(startOfToday()); + fixture.destroy(); + }); + +}); \ No newline at end of file diff --git a/tsconfig-compodoc.json b/tsconfig-compodoc.json index e29fac099..acad5a787 100644 --- a/tsconfig-compodoc.json +++ b/tsconfig-compodoc.json @@ -17,6 +17,9 @@ "src/providers/calendarDateFormatter.provider.ts", "src/providers/calendarEventTitle.provider.ts", "src/providers/calendarMomentDateFormatter.provider.ts", - "src/providers/calendarNativeDateFormatter.provider.ts" + "src/providers/calendarNativeDateFormatter.provider.ts", + "src/directives/calendarNextView.directive.ts", + "src/directives/calendarPreviousView.directive.ts", + "src/directives/calendarToday.directive.ts" ] } \ No newline at end of file