diff --git a/demo/demo.component.ts b/demo/demo.component.ts index cbea04602..d98d825b1 100644 --- a/demo/demo.component.ts +++ b/demo/demo.component.ts @@ -85,7 +85,8 @@ const colors: any = { *ngSwitchCase="'week'" [viewDate]="viewDate" [events]="events" - [refresh]="refresh"> + [refresh]="refresh" + (eventTimesChanged)="eventTimesChanged($event)"> - = new EventEmitter<{newStart: Date, newEnd: Date, event: CalendarEvent}>(); + @Output() eventTimesChanged: EventEmitter = new EventEmitter(); hours: DayViewHour[] = []; view: DayView; diff --git a/src/components/week/calendarWeekView.component.ts b/src/components/week/calendarWeekView.component.ts index 17ddbf59c..3d1d1bf6f 100644 --- a/src/components/week/calendarWeekView.component.ts +++ b/src/components/week/calendarWeekView.component.ts @@ -16,10 +16,14 @@ import { Subscription } from 'rxjs/Subscription'; import { WeekDay, CalendarEvent, + WeekViewEvent, WeekViewEventRow, getWeekViewHeader, getWeekView } from 'calendar-utils'; +import { ResizeEvent } from 'angular-resizable-element'; +import addDays from 'date-fns/add_days'; +import { CalendarEventTimesChangedEvent } from './../../interfaces/calendarEventTimesChangedEvent.interface'; @Component({ selector: 'mwl-calendar-week-view', @@ -34,12 +38,18 @@ import { (click)="dayClicked.emit({date: day.date})"> -
+
+ [style.marginLeft]="((100 / 7) * weekEvent.offset) + '%'" + mwlResizable + [resizeEdges]="{left: weekEvent.event?.resizable?.beforeStart, right: weekEvent.event?.resizable?.afterEnd}" + [resizeSnapGrid]="{left: container.offsetWidth / 7, right: container.offsetWidth / 7}" + (resizeStart)="resizeStarted(weekEvent, $event)" + (resizing)="resizing(weekEvent, $event, container.offsetWidth / 7)" + (resizeEnd)="resizeEnded(weekEvent)"> = new EventEmitter<{event: CalendarEvent}>(); + /** + * Called when an event is resized or dragged and dropped + */ + @Output() eventTimesChanged: EventEmitter = new EventEmitter(); + days: WeekDay[]; + eventRows: WeekViewEventRow[] = []; + refreshSubscription: Subscription; + currentResize: { + originalOffset: number, + originalSpan: number, + edge: string + }; + constructor(private cdr: ChangeDetectorRef, @Inject(LOCALE_ID) locale: string) { this.locale = locale; } @@ -127,6 +150,50 @@ export class CalendarWeekViewComponent implements OnChanges, OnInit, OnDestroy { } } + resizeStarted(weekEvent: WeekViewEvent, resizeEvent: ResizeEvent): void { + this.currentResize = { + originalOffset: weekEvent.offset, + originalSpan: weekEvent.span, + edge: typeof resizeEvent.edges.left !== 'undefined' ? 'left' : 'right' + }; + } + + resizing(weekEvent: WeekViewEvent, resizeEvent: ResizeEvent, dayWidth: number): void { + if (resizeEvent.edges.left) { + const diff: number = Math.round(+resizeEvent.edges.left / dayWidth); + weekEvent.offset = this.currentResize.originalOffset + diff; + weekEvent.span = this.currentResize.originalSpan - diff; + } else if (resizeEvent.edges.right) { + const diff: number = Math.round(+resizeEvent.edges.right / dayWidth); + weekEvent.span = this.currentResize.originalSpan + diff; + } + + } + + resizeEnded(weekEvent: WeekViewEvent): void { + + let daysDiff: number; + if (this.currentResize.edge === 'left') { + daysDiff = weekEvent.offset - this.currentResize.originalOffset; + } else { + daysDiff = weekEvent.span - this.currentResize.originalSpan; + } + + weekEvent.offset = this.currentResize.originalOffset; + weekEvent.span = this.currentResize.originalSpan; + + let newStart: Date = weekEvent.event.start; + let newEnd: Date = weekEvent.event.end; + if (this.currentResize.edge === 'left') { + newStart = addDays(newStart, daysDiff); + } else if (newEnd) { + newEnd = addDays(newEnd, daysDiff); + } + + this.eventTimesChanged.emit({newStart, newEnd, event: weekEvent.event}); + + } + private refreshHeader(): void { this.days = getWeekViewHeader({ viewDate: this.viewDate, diff --git a/test/calendarWeekView.component.spec.ts b/test/calendarWeekView.component.spec.ts index 254ad1035..d71299a14 100644 --- a/test/calendarWeekView.component.spec.ts +++ b/test/calendarWeekView.component.spec.ts @@ -11,7 +11,8 @@ import { CalendarMomentDateFormatter, CalendarDateFormatter, CalendarModule, - MOMENT + MOMENT, + CalendarEventTimesChangedEvent } from './../src'; import { CalendarWeekViewComponent } from './../src/components/week/calendarWeekView.component'; import { Subject } from 'rxjs/Rx'; @@ -217,4 +218,80 @@ describe('calendarWeekView component', () => { fixture.destroy(); }); + it('should resize the event by dragging from the left edge', () => { + const fixture: ComponentFixture = TestBed.createComponent(CalendarWeekViewComponent); + fixture.componentInstance.viewDate = new Date('2016-06-27'); + fixture.componentInstance.events = [{ + title: 'foo', + color: {primary: '', secondary: ''}, + start: moment('2016-06-27').add(4, 'hours').toDate(), + end: moment('2016-06-27').add(6, 'hours').toDate(), + resizable: { + beforeStart: true + } + }]; + fixture.componentInstance.ngOnChanges({viewDate: {}, events: {}}); + fixture.detectChanges(); + document.body.appendChild(fixture.nativeElement); + const event: HTMLElement = fixture.nativeElement.querySelector('.cal-event-container'); + const dayWidth: number = event.parentElement.offsetWidth / 7; + const rect: ClientRect = event.getBoundingClientRect(); + let resizeEvent: CalendarEventTimesChangedEvent; + fixture.componentInstance.eventTimesChanged.subscribe(event => { + resizeEvent = event; + }); + triggerDomEvent('mousedown', document.body, {clientX: rect.left, clientY: rect.top}); + fixture.detectChanges(); + triggerDomEvent('mousemove', document.body, {clientX: rect.left - dayWidth, clientY: rect.top}); + fixture.detectChanges(); + expect(Math.round(event.getBoundingClientRect().left)).to.equal(Math.round(rect.left - dayWidth)); + expect(Math.round(event.getBoundingClientRect().width)).to.equal(Math.round(rect.width + dayWidth)); + triggerDomEvent('mouseup', document.body, {clientX: rect.left - dayWidth, clientY: rect.top}); + fixture.detectChanges(); + fixture.destroy(); + expect(resizeEvent).to.deep.equal({ + event: fixture.componentInstance.events[0], + newStart: moment('2016-06-27').add(4, 'hours').subtract(1, 'day').toDate(), + newEnd: moment('2016-06-27').add(6, 'hours').toDate() + }); + }); + + it('should resize the event by dragging from the right edge', () => { + const fixture: ComponentFixture = TestBed.createComponent(CalendarWeekViewComponent); + fixture.componentInstance.viewDate = new Date('2016-06-27'); + fixture.componentInstance.events = [{ + title: 'foo', + color: {primary: '', secondary: ''}, + start: moment('2016-06-27').add(4, 'hours').toDate(), + end: moment('2016-06-27').add(6, 'hours').toDate(), + resizable: { + afterEnd: true + } + }]; + fixture.componentInstance.ngOnChanges({viewDate: {}, events: {}}); + fixture.detectChanges(); + document.body.appendChild(fixture.nativeElement); + const event: HTMLElement = fixture.nativeElement.querySelector('.cal-event-container'); + const dayWidth: number = event.parentElement.offsetWidth / 7; + const rect: ClientRect = event.getBoundingClientRect(); + let resizeEvent: CalendarEventTimesChangedEvent; + fixture.componentInstance.eventTimesChanged.subscribe(event => { + resizeEvent = event; + }); + triggerDomEvent('mousedown', document.body, {clientX: rect.right, clientY: rect.top}); + fixture.detectChanges(); + triggerDomEvent('mousemove', document.body, {clientX: rect.right + dayWidth, clientY: rect.top}); + fixture.detectChanges(); + expect(Math.round(event.getBoundingClientRect().left)).to.equal(Math.round(rect.left)); + expect(Math.round(event.getBoundingClientRect().width)).to.equal(Math.round(rect.width + dayWidth)); + triggerDomEvent('mouseup', document.body, {clientX: rect.right + dayWidth, clientY: rect.top}); + fixture.detectChanges(); + fixture.destroy(); + expect(resizeEvent).to.deep.equal({ + event: fixture.componentInstance.events[0], + newStart: moment('2016-06-27').add(4, 'hours').toDate(), + newEnd: moment('2016-06-27').add(6, 'hours').add(1, 'day').toDate() + }); + }); + }); diff --git a/webpack.config.umd.ts b/webpack.config.umd.ts index 6bf9bc004..02d72166a 100644 --- a/webpack.config.umd.ts +++ b/webpack.config.umd.ts @@ -64,6 +64,11 @@ module.exports = { commonjs: 'date-fns/add_minutes/index', commonjs2: 'date-fns/add_minutes/index' }, + 'date-fns/add_days': { + root: ['dateFns', 'addDays'], + commonjs: 'date-fns/add_days/index', + commonjs2: 'date-fns/add_days/index' + }, 'angular-resizable-element': { root: 'angularResizableElement', commonjs: 'angular-resizable-element',