Skip to content

Commit 007fbc5

Browse files
author
Matt Lewis
committed
fix(weekView): dont allow events to be resized outside of the calendar component
Closes #99
1 parent 8f16d4a commit 007fbc5

5 files changed

+101
-17
lines changed

src/components/week/calendarWeekView.component.ts

+17-7
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
import { ResizeEvent } from 'angular-resizable-element';
2424
import addDays from 'date-fns/add_days';
2525
import { CalendarDragHelper } from '../../providers/calendarDragHelper.provider';
26+
import { CalendarResizeHelper } from '../../providers/calendarResizeHelper.provider';
2627
import { CalendarEventTimesChangedEvent } from '../../interfaces/calendarEventTimesChangedEvent.interface';
2728

2829
@Component({
@@ -47,16 +48,17 @@ import { CalendarEventTimesChangedEvent } from '../../interfaces/calendarEventTi
4748
[style.marginLeft]="((100 / 7) * weekEvent.offset) + '%'"
4849
mwlResizable
4950
[resizeEdges]="{left: weekEvent.event?.resizable?.beforeStart, right: weekEvent.event?.resizable?.afterEnd}"
50-
[resizeSnapGrid]="{left: getEventWidth(eventRowContainer), right: getEventWidth(eventRowContainer)}"
51-
(resizeStart)="resizeStarted(weekEvent, $event)"
52-
(resizing)="resizing(weekEvent, $event, getEventWidth(eventRowContainer))"
51+
[resizeSnapGrid]="{left: getDayColumnWidth(eventRowContainer), right: getDayColumnWidth(eventRowContainer)}"
52+
[validateResize]="validateResize"
53+
(resizeStart)="resizeStarted(weekViewContainer, weekEvent, $event)"
54+
(resizing)="resizing(weekEvent, $event, getDayColumnWidth(eventRowContainer))"
5355
(resizeEnd)="resizeEnded(weekEvent)"
5456
mwlDraggable
5557
[dragAxis]="{x: weekEvent.event.draggable && !currentResize, y: false}"
56-
[dragSnapGrid]="{x: getEventWidth(eventRowContainer)}"
58+
[dragSnapGrid]="{x: getDayColumnWidth(eventRowContainer)}"
5759
[validateDrag]="validateDrag"
5860
(dragStart)="dragStart(weekViewContainer, event)"
59-
(dragEnd)="eventDragged(weekEvent, $event.x, getEventWidth(eventRowContainer))">
61+
(dragEnd)="eventDragged(weekEvent, $event.x, getDayColumnWidth(eventRowContainer))">
6062
<mwl-calendar-week-view-event
6163
[weekEvent]="weekEvent"
6264
[tooltipPlacement]="tooltipPlacement"
@@ -143,6 +145,11 @@ export class CalendarWeekViewComponent implements OnChanges, OnInit, OnDestroy {
143145
*/
144146
validateDrag: Function;
145147

148+
/**
149+
* @private
150+
*/
151+
validateResize: Function;
152+
146153
/**
147154
* @private
148155
*/
@@ -189,12 +196,15 @@ export class CalendarWeekViewComponent implements OnChanges, OnInit, OnDestroy {
189196
/**
190197
* @private
191198
*/
192-
resizeStarted(weekEvent: WeekViewEvent, resizeEvent: ResizeEvent): void {
199+
resizeStarted(weekViewContainer: HTMLElement, weekEvent: WeekViewEvent, resizeEvent: ResizeEvent): void {
193200
this.currentResize = {
194201
originalOffset: weekEvent.offset,
195202
originalSpan: weekEvent.span,
196203
edge: typeof resizeEvent.edges.left !== 'undefined' ? 'left' : 'right'
197204
};
205+
const resizeHelper: CalendarResizeHelper = new CalendarResizeHelper(weekViewContainer, this.getDayColumnWidth(weekViewContainer));
206+
this.validateResize = ({rectangle}) => resizeHelper.validateResize({rectangle});
207+
this.cdr.markForCheck();
198208
}
199209

200210
/**
@@ -258,7 +268,7 @@ export class CalendarWeekViewComponent implements OnChanges, OnInit, OnDestroy {
258268
/**
259269
* @private
260270
*/
261-
getEventWidth(eventRowContainer: HTMLElement): number {
271+
getDayColumnWidth(eventRowContainer: HTMLElement): number {
262272
return Math.floor(eventRowContainer.offsetWidth / 7);
263273
}
264274

src/providers/calendarDragHelper.provider.ts

+1-10
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,4 @@
1-
function isInside(outer: ClientRect, inner: ClientRect): boolean {
2-
return outer.left <= inner.left &&
3-
inner.left <= outer.right &&
4-
outer.left <= inner.right &&
5-
inner.right <= outer.right &&
6-
outer.top <= inner.top &&
7-
inner.top <= outer.bottom &&
8-
outer.top <= inner.bottom &&
9-
inner.bottom <= outer.bottom;
10-
}
1+
import { isInside } from './calendarUtils.provider';
112

123
export class CalendarDragHelper {
134

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { isInside } from './calendarUtils.provider';
2+
3+
export class CalendarResizeHelper {
4+
5+
constructor(private resizeContainerElement: HTMLElement, private dayColumnWidth: number) {}
6+
7+
validateResize({rectangle}: {rectangle: ClientRect}): boolean {
8+
return isInside(this.resizeContainerElement.getBoundingClientRect(), rectangle) && rectangle.width >= this.dayColumnWidth;
9+
}
10+
11+
}
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export function isInside(outer: ClientRect, inner: ClientRect): boolean {
2+
return outer.left <= inner.left &&
3+
inner.left <= outer.right &&
4+
outer.left <= inner.right &&
5+
inner.right <= outer.right &&
6+
outer.top <= inner.top &&
7+
inner.top <= outer.bottom &&
8+
outer.top <= inner.bottom &&
9+
inner.bottom <= outer.bottom;
10+
}

test/calendarWeekView.component.spec.ts

+62
Original file line numberDiff line numberDiff line change
@@ -329,4 +329,66 @@ describe('calendarWeekView component', () => {
329329
});
330330
});
331331

332+
it('should not allow events to be resized smaller than 1 day', () => {
333+
const fixture: ComponentFixture<CalendarWeekViewComponent> = TestBed.createComponent(CalendarWeekViewComponent);
334+
fixture.componentInstance.viewDate = new Date('2016-06-27');
335+
fixture.componentInstance.events = [{
336+
title: 'foo',
337+
color: {primary: '', secondary: ''},
338+
start: moment('2016-06-27').add(4, 'hours').toDate(),
339+
end: moment('2016-06-27').add(6, 'hours').toDate(),
340+
resizable: {
341+
beforeStart: true
342+
}
343+
}];
344+
fixture.componentInstance.ngOnChanges({viewDate: {}, events: {}});
345+
fixture.detectChanges();
346+
document.body.appendChild(fixture.nativeElement);
347+
const event: HTMLElement = fixture.nativeElement.querySelector('.cal-event-container');
348+
const dayWidth: number = event.parentElement.offsetWidth / 7;
349+
const rect: ClientRect = event.getBoundingClientRect();
350+
triggerDomEvent('mousedown', document.body, {clientX: rect.left, clientY: rect.top});
351+
fixture.detectChanges();
352+
triggerDomEvent('mousemove', document.body, {clientX: rect.left + dayWidth, clientY: rect.top});
353+
fixture.detectChanges();
354+
expect(Math.round(event.getBoundingClientRect().left)).to.equal(Math.round(rect.left));
355+
expect(Math.round(event.getBoundingClientRect().width)).to.equal(Math.round(rect.width));
356+
triggerDomEvent('mouseup', document.body, {clientX: rect.left - dayWidth, clientY: rect.top});
357+
fixture.detectChanges();
358+
fixture.destroy();
359+
});
360+
361+
it('should not allow events to be resized outside of the current view', () => {
362+
const fixture: ComponentFixture<CalendarWeekViewComponent> = TestBed.createComponent(CalendarWeekViewComponent);
363+
fixture.componentInstance.viewDate = new Date('2016-06-27');
364+
fixture.componentInstance.events = [{
365+
title: 'foo',
366+
color: {primary: '', secondary: ''},
367+
start: moment('2016-06-27').add(4, 'hours').toDate(),
368+
end: moment('2016-06-27').add(6, 'hours').toDate(),
369+
resizable: {
370+
beforeStart: true
371+
}
372+
}];
373+
fixture.componentInstance.ngOnChanges({viewDate: {}, events: {}});
374+
fixture.detectChanges();
375+
document.body.appendChild(fixture.nativeElement);
376+
const event: HTMLElement = fixture.nativeElement.querySelector('.cal-event-container');
377+
const dayWidth: number = event.parentElement.offsetWidth / 7;
378+
const rect: ClientRect = event.getBoundingClientRect();
379+
triggerDomEvent('mousedown', document.body, {clientX: rect.left, clientY: rect.top});
380+
fixture.detectChanges();
381+
triggerDomEvent('mousemove', document.body, {clientX: rect.left - dayWidth, clientY: rect.top});
382+
fixture.detectChanges();
383+
expect(Math.round(event.getBoundingClientRect().left)).to.equal(Math.round(rect.left - dayWidth));
384+
expect(Math.round(event.getBoundingClientRect().width)).to.equal(Math.round(rect.width + dayWidth));
385+
triggerDomEvent('mousemove', document.body, {clientX: rect.left - (dayWidth * 2), clientY: rect.top});
386+
fixture.detectChanges();
387+
expect(Math.round(event.getBoundingClientRect().left)).to.equal(Math.round(rect.left - dayWidth));
388+
expect(Math.round(event.getBoundingClientRect().width)).to.equal(Math.round(rect.width + dayWidth));
389+
triggerDomEvent('mouseup', document.body, {clientX: rect.left - (dayWidth * 2), clientY: rect.top});
390+
fixture.detectChanges();
391+
fixture.destroy();
392+
});
393+
332394
});

0 commit comments

Comments
 (0)