(feat) now able to copy/move events and also duplicate them (fixes #3196)
parent
01f9f68d88
commit
49f1c30e77
|
@ -1235,6 +1235,36 @@
|
|||
return uids;
|
||||
}
|
||||
|
||||
- (NSException *) _copyComponent: (iCalCalendar *) calendar
|
||||
toFolder: (SOGoGCSFolder *) newFolder
|
||||
updateUID: (BOOL) updateUID
|
||||
{
|
||||
NSString *newUID;
|
||||
SOGoCalendarComponent *newComponent;
|
||||
|
||||
if (updateUID)
|
||||
{
|
||||
NSArray *elements;
|
||||
unsigned int count, max;
|
||||
|
||||
newUID = [self globallyUniqueObjectId];
|
||||
elements = [calendar allObjects];
|
||||
max = [elements count];
|
||||
for (count = 0; count < max; count++)
|
||||
[[elements objectAtIndex: count] setUid: newUID];
|
||||
}
|
||||
else
|
||||
{
|
||||
newUID = [[[calendar events] objectAtIndex: 0] uid];
|
||||
}
|
||||
|
||||
newComponent = [[self class] objectWithName:
|
||||
[NSString stringWithFormat: @"%@.ics", newUID]
|
||||
inContainer: newFolder];
|
||||
|
||||
return [newComponent saveCalendar: calendar];
|
||||
}
|
||||
|
||||
- (NSException *) copyToFolder: (SOGoGCSFolder *) newFolder
|
||||
{
|
||||
return [self copyComponent: [self calendar: NO secure: NO]
|
||||
|
@ -1244,29 +1274,18 @@
|
|||
- (NSException *) copyComponent: (iCalCalendar *) calendar
|
||||
toFolder: (SOGoGCSFolder *) newFolder
|
||||
{
|
||||
NSArray *elements;
|
||||
NSString *newUID;
|
||||
unsigned int count, max;
|
||||
SOGoCalendarComponent *newComponent;
|
||||
|
||||
newUID = [self globallyUniqueObjectId];
|
||||
elements = [calendar allObjects];
|
||||
max = [elements count];
|
||||
for (count = 0; count < max; count++)
|
||||
[[elements objectAtIndex: count] setUid: newUID];
|
||||
|
||||
newComponent = [[self class] objectWithName:
|
||||
[NSString stringWithFormat: @"%@.ics", newUID]
|
||||
inContainer: newFolder];
|
||||
|
||||
return [newComponent saveCalendar: calendar];
|
||||
return [self _copyComponent: calendar
|
||||
toFolder: newFolder
|
||||
updateUID: YES];
|
||||
}
|
||||
|
||||
- (NSException *) moveToFolder: (SOGoGCSFolder *) newFolder
|
||||
{
|
||||
NSException *ex;
|
||||
|
||||
ex = [self copyToFolder: newFolder];
|
||||
ex = [self _copyComponent: [self calendar: NO secure: NO]
|
||||
toFolder: newFolder
|
||||
updateUID: NO];
|
||||
|
||||
if (!ex)
|
||||
ex = [self delete];
|
||||
|
|
|
@ -172,21 +172,21 @@
|
|||
return response;
|
||||
}
|
||||
|
||||
- (WOResponse *) copyAction
|
||||
- (WOResponse *) _copyOrMoveAction: (BOOL) moving
|
||||
{
|
||||
NSString *destination;
|
||||
NSArray *events;
|
||||
iCalCalendar *calendar;
|
||||
iCalRepeatableEntityObject *masterOccurence;
|
||||
SOGoAppointmentObject *thisEvent;
|
||||
SOGoAppointmentFolder *sourceCalendar, *destinationCalendar;
|
||||
SOGoAppointmentObject *thisEvent;
|
||||
iCalCalendar *calendar;
|
||||
NSString *destination;
|
||||
SoSecurityManager *sm;
|
||||
NSDictionary *params;
|
||||
WOResponse *response;
|
||||
WORequest *rq;
|
||||
|
||||
rq = [context request];
|
||||
params = [[rq contentAsString] objectFromJSONString];
|
||||
destination = [params objectForKey: @"destination"];
|
||||
|
||||
destination = [rq formValueForKey: @"destination"];
|
||||
if (![destination length])
|
||||
destination = @"personal";
|
||||
|
||||
|
@ -206,40 +206,50 @@
|
|||
response = [NSException exceptionWithHTTPStatus: 403
|
||||
reason: @"Can't add event to destination calendar."];
|
||||
}
|
||||
// Verify that the destination calendar is not the source calendar
|
||||
else if ([[destinationCalendar nameInContainer] isEqualToString: [sourceCalendar nameInContainer]])
|
||||
{
|
||||
response = [NSException exceptionWithHTTPStatus: 400
|
||||
reason: @"Destination calendar is the source calendar."];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remove attendees, recurrence exceptions and single occurences from the event
|
||||
calendar = [thisEvent calendar: NO secure: NO];
|
||||
events = [calendar events];
|
||||
masterOccurence = [events objectAtIndex: 0];
|
||||
|
||||
if ([masterOccurence hasAlarms])
|
||||
[masterOccurence removeAllAlarms];
|
||||
if ([masterOccurence hasRecurrenceRules])
|
||||
{
|
||||
[masterOccurence removeAllExceptionRules];
|
||||
[masterOccurence removeAllExceptionDates];
|
||||
}
|
||||
if ([[masterOccurence attendees] count] > 0)
|
||||
{
|
||||
[masterOccurence setOrganizer: nil];
|
||||
[masterOccurence removeAllAttendees];
|
||||
}
|
||||
[calendar setUniqueChild: masterOccurence];
|
||||
calendar = [thisEvent calendar: NO secure: NO];
|
||||
|
||||
// Perform the copy
|
||||
if ([thisEvent copyComponent: calendar
|
||||
toFolder: (SOGoGCSFolder *) destinationCalendar])
|
||||
response = [NSException exceptionWithHTTPStatus: 500
|
||||
reason: @"Can't copy event to destination calendar."];
|
||||
else
|
||||
response = [self responseWith204];
|
||||
if (moving)
|
||||
{
|
||||
// Perform the move
|
||||
if ([thisEvent moveToFolder: (SOGoGCSFolder *) destinationCalendar])
|
||||
response = [NSException exceptionWithHTTPStatus: 500
|
||||
reason: @"Can't move event to destination calendar."];
|
||||
else
|
||||
response = [self responseWith204];
|
||||
}
|
||||
else
|
||||
{
|
||||
iCalRepeatableEntityObject *masterOccurence;
|
||||
NSArray *events;
|
||||
|
||||
// Remove attendees, recurrence exceptions and single occurences from the event
|
||||
events = [calendar events];
|
||||
masterOccurence = [events objectAtIndex: 0];
|
||||
|
||||
if ([masterOccurence hasAlarms])
|
||||
[masterOccurence removeAllAlarms];
|
||||
if ([masterOccurence hasRecurrenceRules])
|
||||
{
|
||||
[masterOccurence removeAllExceptionRules];
|
||||
[masterOccurence removeAllExceptionDates];
|
||||
}
|
||||
if ([[masterOccurence attendees] count] > 0)
|
||||
{
|
||||
[masterOccurence setOrganizer: nil];
|
||||
[masterOccurence removeAllAttendees];
|
||||
}
|
||||
[calendar setUniqueChild: masterOccurence];
|
||||
|
||||
// Perform the copy
|
||||
if ([thisEvent copyComponent: calendar
|
||||
toFolder: (SOGoGCSFolder *) destinationCalendar])
|
||||
response = [NSException exceptionWithHTTPStatus: 500
|
||||
reason: @"Can't copy event to destination calendar."];
|
||||
else
|
||||
response = [self responseWith204];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -251,4 +261,14 @@
|
|||
return response;
|
||||
}
|
||||
|
||||
- (WOResponse *) copyAction
|
||||
{
|
||||
return [self _copyOrMoveAction: NO];
|
||||
}
|
||||
|
||||
- (WOResponse *) moveAction
|
||||
{
|
||||
return [self _copyOrMoveAction: YES];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -269,9 +269,14 @@
|
|||
};
|
||||
copy = {
|
||||
protectedBy = "ViewAllComponent";
|
||||
actionClass = "UIxAppointmentActions";
|
||||
actionClass = "UIxAppointmentActions";
|
||||
actionName = "copy";
|
||||
};
|
||||
move = {
|
||||
protectedBy = "ViewAllComponent";
|
||||
actionClass = "UIxAppointmentActions";
|
||||
actionName = "move";
|
||||
};
|
||||
raw = {
|
||||
protectedBy = "ViewAllComponent";
|
||||
actionClass = "UIxAppointmentEditor";
|
||||
|
|
|
@ -28,6 +28,41 @@
|
|||
<var:string label:value="View Raw Source"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item>
|
||||
<md-menu>
|
||||
<md-button label:aria-label="Copy To" ng-click="$mdOpenMenu($event)">
|
||||
<var:string label:value="Copy To"/>
|
||||
</md-button>
|
||||
<md-menu-content width="4">
|
||||
<div ng-repeat="calendar in editor.calendarService.$findAll(null, true) track by calendar.id">
|
||||
<md-menu-item>
|
||||
<md-button class="sg-no-wrap"
|
||||
ng-click="editor.copySelectedComponent(calendar.id)">
|
||||
<span>{{calendar.name}}</span>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
</div>
|
||||
</md-menu-content>
|
||||
</md-menu>
|
||||
</md-menu-item>
|
||||
<md-menu-item>
|
||||
<md-menu>
|
||||
<md-button label:aria-label="Move To" ng-click="$mdOpenMenu($event)">
|
||||
<var:string label:value="Move To"/>
|
||||
</md-button>
|
||||
<md-menu-content width="4">
|
||||
<div ng-repeat="calendar in editor.calendarService.$findAll(null, true) track by calendar.id">
|
||||
<md-menu-item>
|
||||
<md-button class="sg-no-wrap"
|
||||
ng-disabled="editor.component.destinationCalendar == calendar.id"
|
||||
ng-click="editor.moveSelectedComponent(calendar.id)">
|
||||
<span>{{calendar.name}}</span>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
</div>
|
||||
</md-menu-content>
|
||||
</md-menu>
|
||||
</md-menu-item>
|
||||
</md-menu-content>
|
||||
</md-menu>
|
||||
<md-button class="md-icon-button" ng-click="editor.close()">
|
||||
|
|
|
@ -1229,6 +1229,28 @@
|
|||
return localizedString;
|
||||
};
|
||||
|
||||
/**
|
||||
* @function copyTo
|
||||
* @memberof Component.prototype
|
||||
* @desc Copy an event to a calendar
|
||||
* @param {string} calendar - a target calendar UID
|
||||
* @returns a promise of the HTTP operation
|
||||
*/
|
||||
Component.prototype.copyTo = function(calendar) {
|
||||
return Component.$$resource.post(this.pid + '/' + this.id, 'copy', {destination: calendar});
|
||||
};
|
||||
|
||||
/**
|
||||
* @function moveTo
|
||||
* @memberof Component.prototype
|
||||
* @desc Move an event to a calendar
|
||||
* @param {string} calendar - a target calendar UID
|
||||
* @returns a promise of the HTTP operation
|
||||
*/
|
||||
Component.prototype.moveTo = function(calendar) {
|
||||
return Component.$$resource.post(this.pid + '/' + this.id, 'move', {destination: calendar});
|
||||
};
|
||||
|
||||
Component.prototype.toString = function() {
|
||||
return '[Component ' + this.id + ']';
|
||||
};
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
function ComponentController($rootScope, $mdDialog, Calendar, Component, AddressBook, Alarm, stateComponent) {
|
||||
var vm = this, component;
|
||||
|
||||
vm.calendarService = Calendar;
|
||||
vm.service = Component;
|
||||
vm.component = stateComponent;
|
||||
vm.close = close;
|
||||
|
@ -21,6 +22,8 @@
|
|||
vm.deleteOccurrence = deleteOccurrence;
|
||||
vm.deleteAllOccurrences = deleteAllOccurrences;
|
||||
vm.toggleRawSource = toggleRawSource;
|
||||
vm.copySelectedComponent = copySelectedComponent;
|
||||
vm.moveSelectedComponent = moveSelectedComponent;
|
||||
|
||||
// Load all attributes of component
|
||||
if (angular.isUndefined(vm.component.$futureComponentData)) {
|
||||
|
@ -141,6 +144,20 @@
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
function copySelectedComponent(calendar) {
|
||||
vm.component.copyTo(calendar).then(function() {
|
||||
$mdDialog.hide();
|
||||
$rootScope.$emit('calendars:list');
|
||||
});
|
||||
}
|
||||
|
||||
function moveSelectedComponent(calendar) {
|
||||
vm.component.moveTo(calendar).then(function() {
|
||||
$mdDialog.hide();
|
||||
$rootScope.$emit('calendars:list');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue