Skip to content

Commit 62c41b9

Browse files
committed
feat(day-view): allow dragging and dropping all day events
Closes #665
1 parent e3d6652 commit 62c41b9

File tree

4 files changed

+172
-24
lines changed

4 files changed

+172
-24
lines changed

src/modules/common/util.ts

+15
Original file line numberDiff line numberDiff line change
@@ -121,3 +121,18 @@ export function isDraggedWithinPeriod(
121121
(period.start <= end && end <= period.end)
122122
);
123123
}
124+
125+
export function shouldFireDroppedEvent(
126+
dropEvent: { dropData?: { event?: CalendarEvent } },
127+
date: Date,
128+
allDay: boolean,
129+
events: CalendarEvent[]
130+
) {
131+
return (
132+
dropEvent.dropData &&
133+
dropEvent.dropData.event &&
134+
(events.indexOf(dropEvent.dropData.event) === -1 ||
135+
(dropEvent.dropData.event.allDay && !allDay) ||
136+
(!dropEvent.dropData.event.allDay && allDay))
137+
);
138+
}

src/modules/day/calendar-day-view.component.ts

+26-16
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ import {
3838
getDefaultEventEnd,
3939
getMinimumEventHeightInMinutes,
4040
trackByDayOrWeekEvent,
41-
isDraggedWithinPeriod
41+
isDraggedWithinPeriod,
42+
shouldFireDroppedEvent
4243
} from '../common/util';
4344
import { DateAdapter } from '../../date-adapters/date-adapter';
4445
import { DragEndEvent } from 'angular-draggable-droppable';
@@ -75,13 +76,24 @@ export interface DayViewEventResize {
7576
selector: 'mwl-calendar-day-view',
7677
template: `
7778
<div class="cal-day-view">
78-
<mwl-calendar-all-day-event
79-
*ngFor="let event of view.allDayEvents; trackBy:trackByEventId"
80-
[event]="event"
81-
[customTemplate]="allDayEventTemplate"
82-
[eventTitleTemplate]="eventTitleTemplate"
83-
(eventClicked)="eventClicked.emit({event: event})">
84-
</mwl-calendar-all-day-event>
79+
<div
80+
class="cal-all-day-events"
81+
mwlDroppable
82+
dragOverClass="cal-drag-over"
83+
dragActiveClass="cal-drag-active"
84+
(drop)="eventDropped($event, view.period.start, true)">
85+
<mwl-calendar-all-day-event
86+
*ngFor="let event of view.allDayEvents; trackBy:trackByEventId"
87+
[event]="event"
88+
[customTemplate]="allDayEventTemplate"
89+
[eventTitleTemplate]="eventTitleTemplate"
90+
(eventClicked)="eventClicked.emit({event: event})"
91+
mwlDraggable
92+
dragActiveClass="cal-drag-active"
93+
[dropData]="{event: event}"
94+
[dragAxis]="{x: !snapDraggedEvents && event.draggable, y: !snapDraggedEvents && event.draggable}">
95+
</mwl-calendar-all-day-event>
96+
</div>
8597
<div
8698
class="cal-hour-rows"
8799
#dayEventsContainer
@@ -139,7 +151,7 @@ export interface DayViewEventResize {
139151
mwlDroppable
140152
dragOverClass="cal-drag-over"
141153
dragActiveClass="cal-drag-active"
142-
(drop)="eventDropped($event, segment)">
154+
(drop)="eventDropped($event, segment.date, false)">
143155
</mwl-calendar-day-view-hour-segment>
144156
</div>
145157
</div>
@@ -424,17 +436,15 @@ export class CalendarDayViewComponent implements OnChanges, OnInit, OnDestroy {
424436

425437
eventDropped(
426438
dropEvent: { dropData?: { event?: CalendarEvent } },
427-
segment: DayViewHourSegment
439+
date: Date,
440+
allDay: boolean
428441
): void {
429-
if (
430-
dropEvent.dropData &&
431-
dropEvent.dropData.event &&
432-
this.events.indexOf(dropEvent.dropData.event) === -1
433-
) {
442+
if (shouldFireDroppedEvent(dropEvent, date, allDay, this.events)) {
434443
this.eventTimesChanged.emit({
435444
type: CalendarEventTimesChangedEventType.Drop,
436445
event: dropEvent.dropData.event,
437-
newStart: segment.date
446+
newStart: date,
447+
allDay
438448
});
439449
}
440450
}

src/modules/week/calendar-week-view.component.ts

+3-8
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ import {
4343
getMinimumEventHeightInMinutes,
4444
addDaysWithExclusions,
4545
trackByDayOrWeekEvent,
46-
isDraggedWithinPeriod
46+
isDraggedWithinPeriod,
47+
shouldFireDroppedEvent
4748
} from '../common/util';
4849
import { DateAdapter } from '../../date-adapters/date-adapter';
4950
import {
@@ -766,13 +767,7 @@ export class CalendarWeekViewComponent implements OnChanges, OnInit, OnDestroy {
766767
date: Date,
767768
allDay: boolean
768769
): void {
769-
if (
770-
dropEvent.dropData &&
771-
dropEvent.dropData.event &&
772-
(this.events.indexOf(dropEvent.dropData.event) === -1 ||
773-
(dropEvent.dropData.event.allDay && !allDay) ||
774-
(!dropEvent.dropData.event.allDay && allDay))
775-
) {
770+
if (shouldFireDroppedEvent(dropEvent, date, allDay, this.events)) {
776771
this.eventTimesChanged.emit({
777772
type: CalendarEventTimesChangedEventType.Drop,
778773
event: dropEvent.dropData.event,

test/calendar-day-view.component.spec.ts

+128
Original file line numberDiff line numberDiff line change
@@ -1400,4 +1400,132 @@ describe('CalendarDayViewComponent component', () => {
14001400
expect(events).to.deep.equal([fixture.componentInstance.events[0]]);
14011401
expect(allDayEvents).to.deep.equal([fixture.componentInstance.events[1]]);
14021402
});
1403+
1404+
it('should drag an all day event onto the time grid', () => {
1405+
const fixture: ComponentFixture<
1406+
CalendarDayViewComponent
1407+
> = TestBed.createComponent(CalendarDayViewComponent);
1408+
fixture.componentInstance.viewDate = new Date('2018-07-29');
1409+
fixture.componentInstance.events = [
1410+
{
1411+
start: moment(new Date('2018-07-29'))
1412+
.startOf('day')
1413+
.add(3, 'hours')
1414+
.toDate(),
1415+
end: moment(new Date('2018-07-29'))
1416+
.startOf('day')
1417+
.add(18, 'hours')
1418+
.toDate(),
1419+
title: 'foo',
1420+
draggable: true,
1421+
allDay: true
1422+
}
1423+
];
1424+
fixture.componentInstance.snapDraggedEvents = false;
1425+
fixture.componentInstance.ngOnChanges({ viewDate: {}, events: {} });
1426+
fixture.detectChanges();
1427+
document.body.appendChild(fixture.nativeElement);
1428+
const event = fixture.nativeElement.querySelector(
1429+
'.cal-all-day-events mwl-calendar-all-day-event'
1430+
);
1431+
const rect: ClientRect = event.getBoundingClientRect();
1432+
let dragEvent: CalendarEventTimesChangedEvent;
1433+
fixture.componentInstance.eventTimesChanged.subscribe(e => {
1434+
dragEvent = e;
1435+
});
1436+
triggerDomEvent('mousedown', event, {
1437+
clientX: rect.left,
1438+
clientY: rect.top
1439+
});
1440+
fixture.detectChanges();
1441+
const hourSegment = fixture.nativeElement.querySelectorAll(
1442+
'mwl-calendar-day-view-hour-segment'
1443+
)[3];
1444+
const hourSegmentPosition = hourSegment.getBoundingClientRect();
1445+
triggerDomEvent('mousemove', hourSegment, {
1446+
clientX: hourSegmentPosition.left,
1447+
clientY: hourSegmentPosition.top
1448+
});
1449+
fixture.detectChanges();
1450+
triggerDomEvent('mouseup', hourSegment, {
1451+
clientX: hourSegmentPosition.left,
1452+
clientY: hourSegmentPosition.top
1453+
});
1454+
fixture.detectChanges();
1455+
fixture.destroy();
1456+
expect(dragEvent).to.deep.equal({
1457+
type: 'drop',
1458+
allDay: false,
1459+
event: fixture.componentInstance.events[0],
1460+
newStart: moment(new Date('2018-07-29'))
1461+
.startOf('day')
1462+
.add(90, 'minutes')
1463+
.toDate()
1464+
});
1465+
});
1466+
1467+
it('should drag a time event onto the all day events', () => {
1468+
const fixture: ComponentFixture<
1469+
CalendarDayViewComponent
1470+
> = TestBed.createComponent(CalendarDayViewComponent);
1471+
fixture.componentInstance.viewDate = new Date('2018-07-29');
1472+
fixture.componentInstance.events = [
1473+
{
1474+
start: moment(new Date('2018-07-29'))
1475+
.startOf('day')
1476+
.add(3, 'hours')
1477+
.toDate(),
1478+
end: moment(new Date('2018-07-29'))
1479+
.startOf('day')
1480+
.add(18, 'hours')
1481+
.toDate(),
1482+
title: 'foo',
1483+
draggable: true,
1484+
allDay: false
1485+
},
1486+
{
1487+
start: new Date('2018-07-29'),
1488+
allDay: true,
1489+
title: 'bar'
1490+
}
1491+
];
1492+
fixture.componentInstance.snapDraggedEvents = false;
1493+
fixture.componentInstance.ngOnChanges({ viewDate: {}, events: {} });
1494+
fixture.detectChanges();
1495+
document.body.appendChild(fixture.nativeElement);
1496+
const event = fixture.nativeElement.querySelector('.cal-event-container');
1497+
const rect: ClientRect = event.getBoundingClientRect();
1498+
let dragEvent: CalendarEventTimesChangedEvent;
1499+
fixture.componentInstance.eventTimesChanged.subscribe(e => {
1500+
dragEvent = e;
1501+
});
1502+
triggerDomEvent('mousedown', event, {
1503+
clientX: rect.left,
1504+
clientY: rect.top
1505+
});
1506+
fixture.detectChanges();
1507+
const allDayEvents = fixture.nativeElement.querySelector(
1508+
'.cal-all-day-events'
1509+
);
1510+
const allDayEventsPosition = allDayEvents.getBoundingClientRect();
1511+
triggerDomEvent('mousemove', allDayEvents, {
1512+
clientX: allDayEventsPosition.left,
1513+
clientY: allDayEventsPosition.top
1514+
});
1515+
fixture.detectChanges();
1516+
triggerDomEvent('mouseup', allDayEvents, {
1517+
clientX: allDayEventsPosition.left,
1518+
clientY: allDayEventsPosition.top
1519+
});
1520+
fixture.detectChanges();
1521+
fixture.destroy();
1522+
expect(dragEvent).to.deep.equal({
1523+
type: 'drop',
1524+
allDay: true,
1525+
event: fixture.componentInstance.events[0],
1526+
newStart: moment(new Date('2018-07-29'))
1527+
.startOf('day')
1528+
.toDate()
1529+
});
1530+
});
14031531
});

0 commit comments

Comments
 (0)