Skip to content
This repository has been archived by the owner on Jun 19, 2018. It is now read-only.

Commit

Permalink
feat(weekView): bucket sort events into columns rather than having ea…
Browse files Browse the repository at this point in the history
…ch event sit on its own line

BREAKING CHANGE: the UX of the week view has now changed. The template has also changed heavily if
you were using a custom template.

Closes #381
  • Loading branch information
Matt Lewis committed Jun 29, 2016
1 parent 0f07fa9 commit fdaea2d
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 88 deletions.
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"html-loader": "~0.4.0",
"htmlhint-loader": "~0.1.0",
"istanbul-instrumenter-loader": "~0.2.0",
"karma": "~1.1.0",
"karma": "~0.13.22",
"karma-chai-plugins": "~0.7.0",
"karma-coverage": "~1.0.0",
"karma-mocha": "~1.1.1",
Expand Down Expand Up @@ -82,5 +82,9 @@
"commitizen": {
"path": "node_modules/cz-conventional-changelog"
}
},
"dependencies": {
"calendar-utils": "0.0.1",
"es6-set": "~0.1.4"
}
}
30 changes: 30 additions & 0 deletions src/less/week.less
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.cal-week-box {
position: relative;

[data-event-class] {
white-space: nowrap;
height: 30px;
Expand All @@ -15,6 +16,35 @@
.cal-day-panel {
border: 0px !important;
}

}

.cal-week-box:not(.cal-day-box) {

.cal-row-fluid {
margin-bottom: 2px;
}

.cal-row-fluid:hover,
[class*="cal-cell"]:hover {
background-color: inherit !important;
}

[data-event-class] {
margin-left: 2px;
margin-right: 2px;
}

.border-left-rounded {
border-top-left-radius: 5px;
border-bottom-left-radius: 5px;
}

.border-right-rounded {
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
}

}

.cal-week-box.cal-day-box {
Expand Down
59 changes: 32 additions & 27 deletions src/services/calendarHelper.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
'use strict';

var angular = require('angular');
require('es6-set/implement');
var calendarUtils = require('calendar-utils');

angular
.module('mwl.calendar')
Expand Down Expand Up @@ -195,41 +197,34 @@ angular
dayCounter.add(1, 'day');
}

var eventsSorted = filterEventsInPeriod(events, startOfWeek, endOfWeek).map(function(event) {
var eventRows = calendarUtils.getWeekView({
viewDate: viewDate,
events: filterEventsInPeriod(events, startOfWeek, endOfWeek).map(function(event) {

var weekViewStart = moment(startOfWeek).startOf('day');
var weekViewEnd = moment(endOfWeek).startOf('day');
var weekViewStart = moment(startOfWeek).startOf('day');

var eventPeriod = getRecurringEventPeriod({
start: moment(event.startsAt).startOf('day'),
end: moment(event.endsAt || event.startsAt).startOf('day')
}, event.recursOn, weekViewStart);
var eventPeriod = getRecurringEventPeriod({
start: moment(event.startsAt).startOf('day'),
end: moment(event.endsAt || event.startsAt).startOf('day').add(1, 'second')
}, event.recursOn, weekViewStart);

var eventStart = eventPeriod.start;
var eventEnd = eventPeriod.end;
eventPeriod.originalEvent = event;

var offset;
if (eventStart.isBefore(weekViewStart) || eventStart.isSame(weekViewStart)) {
offset = 0;
} else {
offset = eventStart.diff(weekViewStart, 'days');
}
return eventPeriod;

if (eventEnd.isAfter(weekViewEnd)) {
eventEnd = weekViewEnd;
}
})
}).map(function(eventRow) {

if (eventStart.isBefore(weekViewStart)) {
eventStart = weekViewStart;
}
eventRow.row = eventRow.row.map(function(rowEvent) {
rowEvent.event = rowEvent.event.originalEvent;
return rowEvent;
});

event.daySpan = moment(eventEnd).diff(eventStart, 'days') + 1;
event.dayOffset = offset;
return eventRow;

return event;
});

return {days: days, events: eventsSorted};
return {days: days, eventRows: eventRows};

}

Expand Down Expand Up @@ -316,8 +311,14 @@ angular
function getWeekViewWithTimes(events, viewDate, dayViewStart, dayViewEnd, dayViewSplit) {
var weekView = getWeekView(events, viewDate);
var newEvents = [];
var flattenedEvents = [];
weekView.eventRows.forEach(function(row) {
row.row.forEach(function(eventRow) {
flattenedEvents.push(eventRow.event);
});
});
weekView.days.forEach(function(day) {
var dayEvents = weekView.events.filter(function(event) {
var dayEvents = flattenedEvents.filter(function(event) {
return moment(event.startsAt).startOf('day').isSame(moment(day.date).startOf('day'));
});
var newDayEvents = getDayView(
Expand All @@ -329,7 +330,11 @@ angular
);
newEvents = newEvents.concat(newDayEvents);
});
weekView.events = newEvents;
weekView.eventRows = [{
row: newEvents.map(function(event) {
return {event: event};
})
}];
return weekView;
}

Expand Down
57 changes: 30 additions & 27 deletions src/templates/calendarWeekView.html
Original file line number Diff line number Diff line change
Expand Up @@ -41,38 +41,41 @@
ng-if="vm.showTimes">
</mwl-calendar-hour-list>

<div class="row">
<div class="row" ng-repeat="row in vm.view.eventRows track by $index">
<div class="col-xs-12">
<div
class="cal-row-fluid"
ng-repeat="event in vm.view.events track by event.$id">
<div class="cal-row-fluid">
<div
ng-class="'cal-cell' + (vm.showTimes ? 1 : event.daySpan) + (vm.showTimes ? '' : ' cal-offset' + event.dayOffset) + ' day-highlight dh-event-' + event.type + ' ' + event.cssClass"
ng-repeat="eventRow in row.row track by eventRow.event.$id"
ng-class="'cal-cell' + (vm.showTimes ? 1 : eventRow.span) + (vm.showTimes ? '' : ' cal-offset' + eventRow.offset)"
ng-style="{
top: vm.showTimes ? ((event.top + 2) + 'px') : 'auto',
top: vm.showTimes ? ((eventRow.event.top + 2) + 'px') : 'auto',
position: vm.showTimes ? 'absolute' : 'inherit',
width: vm.showTimes ? (vm.dayColumnDimensions.width + 'px') : '',
left: vm.showTimes ? (vm.dayColumnDimensions.width * event.dayOffset) + 15 + 'px' : ''
}"
data-event-class
mwl-draggable="event.draggable === true"
axis="vm.showTimes ? 'xy' : 'x'"
snap-grid="vm.showTimes ? {x: vm.dayColumnDimensions.width, y: vm.dayViewEventChunkSize || 30} : {x: vm.dayColumnDimensions.width}"
on-drag="vm.tempTimeChanged(event, y / 30)"
on-drag-end="vm.weekDragged(event, x / vm.dayColumnDimensions.width, y / 30)"
mwl-resizable="event.resizable === true && event.endsAt && !vm.showTimes"
resize-edges="{left: true, right: true}"
on-resize-end="vm.weekResized(event, edge, x / vm.dayColumnDimensions.width)">
<strong ng-bind="(event.tempStartsAt || event.startsAt) | calendarDate:'time':true" ng-show="vm.showTimes"></strong>
<a
href="javascript:;"
ng-click="vm.onEventClick({calendarEvent: event})"
class="event-item"
ng-bind-html="vm.calendarEventTitle.weekView(event) | calendarTrustAsHtml"
uib-tooltip-html="vm.calendarEventTitle.weekViewTooltip(event) | calendarTrustAsHtml"
tooltip-placement="left"
tooltip-append-to-body="true">
</a>
left: vm.showTimes ? (vm.dayColumnDimensions.width * eventRow.offset) + 15 + 'px' : ''
}">
<div
class="day-highlight"
ng-class="['dh-event-' + eventRow.event.type, eventRow.event.cssClass, eventRow.extendsLeft ? '' : 'border-left-rounded', eventRow.extendsRight ? '' : 'border-right-rounded']"
data-event-class
mwl-draggable="eventRow.event.draggable === true"
axis="vm.showTimes ? 'xy' : 'x'"
snap-grid="vm.showTimes ? {x: vm.dayColumnDimensions.width, y: vm.dayViewEventChunkSize || 30} : {x: vm.dayColumnDimensions.width}"
on-drag="vm.tempTimeChanged(eventRow.event, y / 30)"
on-drag-end="vm.weekDragged(eventRow.event, x / vm.dayColumnDimensions.width, y / 30)"
mwl-resizable="eventRow.event.resizable === true && eventRow.event.endsAt && !vm.showTimes"
resize-edges="{left: true, right: true}"
on-resize-end="vm.weekResized(eventRow.event, edge, x / vm.dayColumnDimensions.width)">
<strong ng-bind="(eventRow.event.tempStartsAt || eventRow.event.startsAt) | calendarDate:'time':true" ng-show="vm.showTimes"></strong>
<a
href="javascript:;"
ng-click="vm.onEventClick({calendarEvent: eventRow.event})"
class="event-item"
ng-bind-html="vm.calendarEventTitle.weekView(eventRow.event) | calendarTrustAsHtml"
uib-tooltip-html="vm.calendarEventTitle.weekViewTooltip(eventRow.event) | calendarTrustAsHtml"
tooltip-placement="left"
tooltip-append-to-body="true">
</a>
</div>
</div>
</div>
</div>
Expand Down
67 changes: 34 additions & 33 deletions test/unit/services/calendarHelper.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,8 @@ describe('calendarHelper', function() {
});

it('should only contain events for that week', function() {
expect(weekView.events).to.eql([events[0], events[1]]);
expect(weekView.eventRows[0].row[0].event).to.eql(events[0]);
expect(weekView.eventRows[1].row[0].event).to.eql(events[1]);
});

describe('setting the correct span and offset', function() {
Expand All @@ -455,35 +456,35 @@ describe('calendarHelper', function() {
startsAt: new Date(2015, 9, 20, 1),
endsAt: new Date(2015, 9, 21, 15)
}], calendarDay);
expect(weekView.events[0].daySpan).to.equal(2);
expect(weekView.events[0].dayOffset).to.equal(2);
expect(weekView.eventRows[0].row[0].span).to.equal(2);
expect(weekView.eventRows[0].row[0].offset).to.equal(2);
});

it('should pass when the event starts before the current week view and ends within it', function() {
weekView = calendarHelper.getWeekView([{
startsAt: new Date(2015, 8, 20, 1),
endsAt: new Date(2015, 9, 21, 15)
}], calendarDay);
expect(weekView.events[0].daySpan).to.equal(4);
expect(weekView.events[0].dayOffset).to.equal(0);
expect(weekView.eventRows[0].row[0].span).to.equal(4);
expect(weekView.eventRows[0].row[0].offset).to.equal(0);
});

it('should pass when the event starts before the current week view and ends after the end of the week', function() {
weekView = calendarHelper.getWeekView([{
startsAt: new Date(2015, 8, 20, 1),
endsAt: new Date(2015, 10, 21, 15)
}], calendarDay);
expect(weekView.events[0].daySpan).to.equal(7);
expect(weekView.events[0].dayOffset).to.equal(0);
expect(weekView.eventRows[0].row[0].span).to.equal(7);
expect(weekView.eventRows[0].row[0].offset).to.equal(0);
});

it('should pass when the event starts within the current week but ends after it', function() {
weekView = calendarHelper.getWeekView([{
startsAt: new Date(2015, 9, 20, 1),
endsAt: new Date(2015, 10, 21, 15)
}], calendarDay);
expect(weekView.events[0].daySpan).to.equal(5);
expect(weekView.events[0].dayOffset).to.equal(2);
expect(weekView.eventRows[0].row[0].span).to.equal(5);
expect(weekView.eventRows[0].row[0].offset).to.equal(2);
});

});
Expand All @@ -495,8 +496,8 @@ describe('calendarHelper', function() {
startsAt: new Date(2016, 0, 9, 1),
recursOn: 'month'
}], new Date(2016, 1, 9, 1));
expect(weekView.events[0].daySpan).to.equal(1);
expect(weekView.events[0].dayOffset).to.equal(2);
expect(weekView.eventRows[0].row[0].span).to.equal(1);
expect(weekView.eventRows[0].row[0].offset).to.equal(2);
});

});
Expand Down Expand Up @@ -620,36 +621,36 @@ describe('calendarHelper', function() {
it('should calculate the week view with times', function() {
var expectedEventsWeekView = [
{
startsAt: new Date('October 19, 2015 11:00:00'),
endsAt: new Date('October 21, 2015 11:00:00'),
daySpan: 3,
dayOffset: 1,
top: 658,
height: 782,
left: 0
event: {
top: 658,
height: 782,
left: 0,
startsAt: new Date('October 19, 2015 11:00:00'),
endsAt: new Date('October 21, 2015 11:00:00')
}
},
{
startsAt: new Date('October 20, 2015 11:00:00'),
endsAt: new Date('October 21, 2015 11:00:00'),
daySpan: 2,
dayOffset: 2,
top: 658,
height: 782,
left: 0
event: {
top: 658,
height: 782,
left: 0,
startsAt: new Date('October 20, 2015 11:00:00'),
endsAt: new Date('October 21, 2015 11:00:00')
}
},
{
startsAt: new Date('October 20, 2015 11:00:00'),
endsAt: new Date('October 20, 2015 12:00:00'),
daySpan: 1,
dayOffset: 2,
top: 658,
height: 60,
left: 150
event: {
startsAt: new Date('October 20, 2015 11:00:00'),
endsAt: new Date('October 20, 2015 12:00:00'),
top: 658,
height: 60,
left: 150
}
}
];

expect(weekViewWithTimes.days.length).to.equal(7);
expect(weekViewWithTimes.events).to.eql(expectedEventsWeekView);
expect(weekViewWithTimes.eventRows[0].row).to.eql(expectedEventsWeekView);
});
});

Expand Down

0 comments on commit fdaea2d

Please sign in to comment.