Skip to content

Commit

Permalink
undo event deletion
Browse files Browse the repository at this point in the history
  • Loading branch information
georgehrke committed Nov 8, 2016
1 parent ce14199 commit 24683d1
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 14 deletions.
19 changes: 17 additions & 2 deletions js/app/controllers/calcontroller.js
Original file line number Diff line number Diff line change
Expand Up @@ -232,9 +232,24 @@ app.controller('CalController', ['$scope', 'Calendar', 'CalendarService', 'VEven
createAndRenderEvent(result.calendar, result.vevent.data, view.start, view.end, $scope.defaulttimezone);
}
}).catch(function(reason) {
if (reason === 'delete') {
deleteAndRemoveEvent(vevent, fcEvent);
if (reason !== 'delete') {
return true;
}

fc.elm.fullCalendar('removeEvents', fcEvent.id);
fcEvent.delete().then(function() {
return VEventService.delete(vevent).catch(function() {
throw new Error();
});
}).catch(function() {
const start = view.start.subtract(1, 'day');
const end = view.end.add(1, 'day');

const eventsToRender = vevent.getFcEvent(start, end, $scope.defaulttimezone);
angular.forEach(eventsToRender, function (event) {
fc.elm.fullCalendar('renderEvent', event);
});
});
});
},
eventResize: function (fcEvent, delta, revertFunc) {
Expand Down
38 changes: 28 additions & 10 deletions js/app/models/fcEventModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
*
*/

app.factory('FcEvent', function(SimpleEvent) {
app.factory('FcEvent', function($timeout, SimpleEvent) {
'use strict';

/**
Expand All @@ -33,6 +33,7 @@ app.factory('FcEvent', function(SimpleEvent) {
function FcEvent(vevent, event, start, end) {
const context = {vevent, event};
context.iCalEvent = new ICAL.Event(event);
context.isDeleted = false;

let id = context.vevent.uri;
if (event.hasProperty('recurrence-id')) {
Expand Down Expand Up @@ -192,17 +193,34 @@ app.factory('FcEvent', function(SimpleEvent) {
};

/**
* lock fc event for editing
* Show undo notification for deletion
* @returns {Promise}
*/
iface.lock = function() {
context.lock = true;
};
iface.delete = function() {
return new Promise(function(resolve, reject) {
context.isDeleted = true;

/**
* unlock fc event
*/
iface.unlock = function() {
context.lock = false;
const timeout = $timeout(function() {
if (context.isDeleted) {
resolve();
}
}, 7500);

const msg = t('calendar', '<strong>{title}</strong> has been deleted. <strong>Undo?</strong>', {
title: iface.title
});
const html = $('<div/>').append($(msg));

const elm = OC.Notification.showTemporary(html, {
isHTML: true
});
angular.element(elm[0]).click(function() {
context.isDeleted = false;
OC.Notification.hide(elm);
$timeout.cancel(timeout);
reject('Deletion cancelled by user');
});
});
};

return iface;
Expand Down
111 changes: 109 additions & 2 deletions tests/js/unit/models/fcEventModelSpec.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
describe('The FullCalendar Event factory', function () {
'use strict';

let FcEvent, SimpleEvent;
let FcEvent, SimpleEvent, $timeout, $rootScope;

const ics1 = `BEGIN:VCALENDAR
VERSION:2.0
Expand Down Expand Up @@ -221,11 +221,23 @@ END:STANDARD
END:VTIMEZONE`)));
ICAL.TimezoneService.register('Europe/Berlin', tzBerlin);

OC.Notification = {};
OC.Notification.hide = jasmine.createSpy();
OC.Notification.showTemporary = jasmine.createSpy();

$provide.value('SimpleEvent', SimpleEvent);
}));

beforeEach(inject(function (_FcEvent_) {
beforeEach(inject(function (_FcEvent_, $q, _$timeout_, _$rootScope_) {
FcEvent = _FcEvent_;
$timeout = _$timeout_;
$rootScope = _$rootScope_;

// mixing ES6 Promises and $q ain't no good
// ES6 Promises will be replaced with $q for the unit tests
if (window.Promise !== $q) {
window.Promise = $q;
}
}));

it ('should initialize correctly', function() {
Expand Down Expand Up @@ -1085,4 +1097,99 @@ DTEND;TZID=America/New_York:20161106T015900
END:VEVENT`.split("\n").join("\r\n"));
expect(vevent.touch).toHaveBeenCalled();
});

it('should resolve the delete promise after 7.5s when not cancelled', function() {
let called = false;
const comp = new ICAL.Component(ICAL.parse(ics3));
const vevent = {
calendar: {
color: '#000',
textColor: '#fff',
tmpId: '3.1415926536',
isWritable: jasmine.createSpy()
},
uri: 'fancy1337',
touch: jasmine.createSpy()
};
const event = comp.getFirstSubcomponent('vevent');
const start = event.getFirstPropertyValue('dtstart');

const fcEvent = FcEvent(vevent, event, start, start);

const elm = angular.element('<div/>');
const elms = [elm];

OC.Notification.showTemporary.and.returnValue(elms);

const promise = fcEvent.delete();

expect(OC.Notification.showTemporary.calls.count()).toEqual(1);
expect(OC.Notification.showTemporary.calls.argsFor(0)[0].html()).toEqual('<strong>{title}</strong> has been deleted. <strong>Undo?</strong>');
expect(OC.Notification.showTemporary.calls.argsFor(0)[1]).toEqual({isHTML: true});

$timeout.flush(7499);
expect(promise.$$state.status).toEqual(0);

promise.then(function() {
called = true;
}).catch(function() {
fail();
});

$timeout.flush(1);
expect(promise.$$state.status).toEqual(1);
expect(called).toEqual(true);
});

it('should reject the delete promise when cancelled by the user', function() {
let called = false;
const comp = new ICAL.Component(ICAL.parse(ics3));
const vevent = {
calendar: {
color: '#000',
textColor: '#fff',
tmpId: '3.1415926536',
isWritable: jasmine.createSpy()
},
uri: 'fancy1337',
touch: jasmine.createSpy()
};
const event = comp.getFirstSubcomponent('vevent');
const start = event.getFirstPropertyValue('dtstart');

const fcEvent = FcEvent(vevent, event, start, start);

const elm = angular.element('<div/>');
const elms = [elm];

OC.Notification.showTemporary.and.returnValue(elms);

const promise = fcEvent.delete();

expect(OC.Notification.showTemporary.calls.count()).toEqual(1);
expect(OC.Notification.showTemporary.calls.argsFor(0)[0].html()).toEqual('<strong>{title}</strong> has been deleted. <strong>Undo?</strong>');
expect(OC.Notification.showTemporary.calls.argsFor(0)[1]).toEqual({isHTML: true});

$timeout.flush(7499);
expect(promise.$$state.status).toEqual(0);

promise.then(function() {
fail();
}).catch(function() {
called = true;
});

angular.element(elm).click();

$rootScope.$apply();

expect(called).toEqual(true);
expect(promise.$$state.status).toEqual(2);
expect(OC.Notification.hide).toHaveBeenCalledWith(elms);

$timeout.flush(1);
$rootScope.$apply();

expect(promise.$$state.status).toEqual(2);
});
});

0 comments on commit 24683d1

Please sign in to comment.