Now possible to set alarms on event invitations

This commit is contained in:
Ludovic Marcotte
2014-12-16 09:20:27 -05:00
parent 3eac0f5261
commit fb6ef3aa8a
23 changed files with 461 additions and 281 deletions
-3
View File
@@ -52,9 +52,6 @@ SchedulerUI_RESOURCE_FILES += \
SchedulerUI_RESOURCE_FILES += \
Toolbars/SOGoAppointmentFolders.toolbar \
Toolbars/SOGoAppointmentObject.toolbar \
Toolbars/SOGoAppointmentObjectAccept.toolbar \
Toolbars/SOGoAppointmentObjectDecline.toolbar \
Toolbars/SOGoAppointmentObjectAcceptOrDecline.toolbar \
Toolbars/SOGoTaskObject.toolbar \
Toolbars/SOGoComponentClose.toolbar \
Toolbars/SOGoEmpty.toolbar
@@ -1,7 +0,0 @@
( /* the toolbar groups -*-cperl-*- */
( { link = "#";
isSafe = NO;
label = "accept";
onclick = "return modifyEvent(this, 'accept');";
image = "tb-ab-properties-flat-24x24.png"; } )
)
@@ -1,12 +0,0 @@
( /* the toolbar groups -*-cperl-*- */
( { link = "#";
isSafe = NO;
label = "accept";
onclick = "return modifyEvent(this, 'accept');";
image = "tb-ab-properties-flat-24x24.png"; },
{ link = "#";
isSafe = NO;
label = "decline";
onclick = "return modifyEvent(this, 'decline');";
image = "tb-mail-stop-flat-24x24.png"; } )
)
@@ -1,7 +0,0 @@
( /* the toolbar groups -*-cperl-*- */
( { link = "#";
isSafe = NO;
label = "decline";
onclick = "return modifyEvent(this, 'decline');";
image = "tb-mail-stop-flat-24x24.png"; } )
)
+139 -79
View File
@@ -51,6 +51,7 @@
#import <SOGo/SOGoPermissions.h>
#import <SOGo/SOGoUser.h>
#import <SOGo/SOGoUserDefaults.h>
#import <Appointments/iCalAlarm+SOGo.h>
#import <Appointments/iCalCalendar+SOGo.h>
#import <Appointments/iCalEntityObject+SOGo.h>
#import <Appointments/iCalPerson+SOGo.h>
@@ -80,7 +81,7 @@
isTransparent = NO;
sendAppointmentNotifications = YES;
componentCalendar = nil;
user = [[self context] activeUser];
ASSIGN (dateFormatter, [user dateFormatterInContext: context]);
}
@@ -111,6 +112,11 @@
return event;
}
- (NSString *) rsvpURL
{
return [NSString stringWithFormat: @"%@/rsvpAppointment",
[[self clientObject] baseURL]];
}
- (NSString *) saveURL
{
return [NSString stringWithFormat: @"%@/saveAsAppointment",
@@ -390,6 +396,137 @@
}
}
//
//
//
- (id <WOActionResults>) rsvpAction
{
iCalPerson *delegatedAttendee;
NSDictionary *message;
WOResponse *response;
WORequest *request;
iCalAlarm *anAlarm;
NSString *status;
int replyList, reminderList;
request = [context request];
message = [[request contentAsString] objectFromJSONString];
delegatedAttendee = nil;
anAlarm = nil;
status = nil;
replyList = [[message objectForKey: @"replyList"] intValue];
switch (replyList)
{
case 0:
status = @"ACCEPTED";
break;
case 1:
status = @"DECLINED";
break;
case 2:
status = @"NEEDS-ACTION";
break;
case 3:
status = @"TENTATIVE";
break;
case 4:
default:
{
NSString *delegatedEmail, *delegatedUid;
SOGoUser *user;
status = @"DELEGATED";
delegatedEmail = [[message objectForKey: @"delegatedTo"] stringByTrimmingSpaces];
if ([delegatedEmail length])
{
user = [context activeUser];
delegatedAttendee = [iCalPerson new];
[delegatedAttendee autorelease];
[delegatedAttendee setEmail: delegatedEmail];
delegatedUid = [delegatedAttendee uid];
if (delegatedUid)
{
SOGoUser *delegatedUser;
delegatedUser = [SOGoUser userWithLogin: delegatedUid];
[delegatedAttendee setCn: [delegatedUser cn]];
}
[delegatedAttendee setRole: @"REQ-PARTICIPANT"];
[delegatedAttendee setRsvp: @"TRUE"];
[delegatedAttendee setParticipationStatus: iCalPersonPartStatNeedsAction];
[delegatedAttendee setDelegatedFrom:
[NSString stringWithFormat: @"mailto:%@", [[user allEmails] objectAtIndex: 0]]];
}
else
return [NSException exceptionWithHTTPStatus: 400
reason: @"missing 'to' parameter"];
}
break;
}
// Extract the user alarm, if any
reminderList = [[message objectForKey: @"reminderList"] intValue];
if ([[message objectForKey: @"reminderList"] isEqualToString: @"WONoSelectionString"] || reminderList == 5 || reminderList == 10 || reminderList == 14)
{
// No selection, wipe alarm which will be done in changeParticipationStatus...
}
else if (reminderList == 15)
{
// Custom
anAlarm = [iCalAlarm alarmForEvent: [self event]
owner: [[self clientObject] ownerInContext: context]
action: [message objectForKey: @"reminderAction"]
unit: [message objectForKey: @"reminderUnit"]
quantity: [message objectForKey: @"reminderQuantity"]
reference: [message objectForKey: @"reminderReference"]
reminderRelation: [message objectForKey: @"reminderRelation"]
emailAttendees: [[message objectForKey: @"reminderEmailAttendees"] boolValue]
emailOrganizer: [[message objectForKey: @"reminderEmailOrganizer"] boolValue]];
}
else
{
// Standard
NSString *aValue;
aValue = [[UIxComponentEditor reminderValues] objectAtIndex: reminderList];
// Predefined alarm
if ([aValue length])
{
iCalTrigger *aTrigger;
anAlarm = [[[iCalAlarm alloc] init] autorelease];
aTrigger = [iCalTrigger elementWithTag: @"TRIGGER"];
[aTrigger setValueType: @"DURATION"];
[anAlarm setTrigger: aTrigger];
[anAlarm setAction: @"DISPLAY"];
[aTrigger setSingleValue: aValue forKey: @""];
}
}
response = (WOResponse *)[[self clientObject] changeParticipationStatus: status
withDelegate: delegatedAttendee
alarm: anAlarm];
if (!response)
response = [self responseWith204];
return response;
}
//
//
//
- (id <WOActionResults>) saveAction
{
SOGoAppointmentFolder *previousCalendar;
@@ -560,7 +697,7 @@
actionName = [[request requestHandlerPath] lastPathComponent];
return ([[self clientObject] conformsToProtocol: @protocol (SOGoComponentOccurence)]
&& [actionName hasPrefix: @"save"]);
&& ([actionName hasPrefix: @"save"] || [actionName hasPrefix: @"rsvp"]));
}
- (void) takeValuesFromRequest: (WORequest *) _rq
@@ -637,81 +774,4 @@
}
- (id) _statusChangeAction: (NSString *) newStatus
{
[[self clientObject] changeParticipationStatus: newStatus
withDelegate: nil];
return [self responseWith204];
}
- (id) acceptAction
{
return [self _statusChangeAction: @"ACCEPTED"];
}
- (id) declineAction
{
return [self _statusChangeAction: @"DECLINED"];
}
- (id) needsActionAction
{
return [self _statusChangeAction: @"NEEDS-ACTION"];
}
- (id) tentativeAction
{
return [self _statusChangeAction: @"TENTATIVE"];
}
- (id) delegateAction
{
// BOOL receiveUpdates;
NSString *delegatedEmail, *delegatedUid;
iCalPerson *delegatedAttendee;
SOGoUser *user;
WORequest *request;
WOResponse *response;
response = nil;
request = [context request];
delegatedEmail = [request formValueForKey: @"to"];
if ([delegatedEmail length])
{
user = [context activeUser];
delegatedAttendee = [iCalPerson new];
[delegatedAttendee autorelease];
[delegatedAttendee setEmail: delegatedEmail];
delegatedUid = [delegatedAttendee uid];
if (delegatedUid)
{
SOGoUser *delegatedUser;
delegatedUser = [SOGoUser userWithLogin: delegatedUid];
[delegatedAttendee setCn: [delegatedUser cn]];
}
[delegatedAttendee setRole: @"REQ-PARTICIPANT"];
[delegatedAttendee setRsvp: @"TRUE"];
[delegatedAttendee setParticipationStatus: iCalPersonPartStatNeedsAction];
[delegatedAttendee setDelegatedFrom:
[NSString stringWithFormat: @"mailto:%@", [[user allEmails] objectAtIndex: 0]]];
// receiveUpdates = [[request formValueForKey: @"receiveUpdates"] boolValue];
// if (receiveUpdates)
// [delegatedAttendee setRole: @"NON-PARTICIPANT"];
response = (WOResponse*)[[self clientObject] changeParticipationStatus: @"DELEGATED"
withDelegate: delegatedAttendee];
}
else
response = [NSException exceptionWithHTTPStatus: 400
reason: @"missing 'to' parameter"];
if (!response)
response = [self responseWith204];
return response;
}
@end
+4 -1
View File
@@ -38,6 +38,7 @@
id item;
id attendee;
NSString *rsvpURL;
NSString *saveURL;
NSMutableArray *calendarList;
NSDictionary *organizerProfile;
@@ -62,7 +63,7 @@
NSString *dateFormat;
NSMutableDictionary *jsonAttendees;
NSString *reminder;
NSString *reminderQuantity;
NSString *reminderUnit;
@@ -184,6 +185,8 @@
- (BOOL) isWriteableClientObject;
- (NSException *) validateObjectForStatusChange;
+ (NSArray *) reminderValues;
@end
#endif /* UIXCOMPONENTEDITOR_H */
+44 -92
View File
@@ -51,6 +51,7 @@
#import <NGExtensions/NSNull+misc.h>
#import <NGExtensions/NSString+misc.h>
#import <Appointments/iCalAlarm+SOGo.h>
#import <Appointments/iCalEntityObject+SOGo.h>
#import <Appointments/iCalPerson+SOGo.h>
#import <Appointments/SOGoAppointmentFolder.h>
@@ -225,7 +226,7 @@ iRANGE(2);
[attendee release];
[jsonAttendees release];
[calendarList release];
[reminder release];
[reminderQuantity release];
[reminderUnit release];
@@ -683,12 +684,16 @@ iRANGE(2);
ASSIGN (ownerAsAttendee, [component findAttendeeWithEmail: (id)ownerEmail]);
}
}
// /* cycles */
// if ([component isRecurrent])
// {
// rrule = [[component recurrenceRules] objectAtIndex: 0];
// [self adjustCycleControlsForRRule: rrule];
// }
}
- (void) setRSVPURL: (NSString *) theURL
{
rsvpURL = theURL;
}
- (NSString *) rsvpURL
{
return rsvpURL;
}
- (void) setSaveURL: (NSString *) newSaveURL
@@ -2168,40 +2173,7 @@ RANGE(2);
}
}
- (void) _appendAttendees: (NSArray *) attendees
toEmailAlarm: (iCalAlarm *) alarm
{
NSMutableArray *aAttendees;
int count, max;
iCalPerson *currentAttendee, *aAttendee;
max = [attendees count];
aAttendees = [NSMutableArray arrayWithCapacity: max];
for (count = 0; count < max; count++)
{
currentAttendee = [attendees objectAtIndex: count];
aAttendee = [iCalPerson elementWithTag: @"attendee"];
[aAttendee setCn: [currentAttendee cn]];
[aAttendee setEmail: [currentAttendee rfc822Email]];
[aAttendees addObject: aAttendee];
}
[alarm setAttendees: aAttendees];
}
- (void) _appendOrganizerToEmailAlarm: (iCalAlarm *) alarm
{
NSString *uid;
NSDictionary *ownerIdentity;
iCalPerson *aAttendee;
uid = [[self clientObject] ownerInContext: context];
ownerIdentity = [[SOGoUser userWithLogin: uid roles: nil]
defaultIdentity];
aAttendee = [iCalPerson elementWithTag: @"attendee"];
[aAttendee setCn: [ownerIdentity objectForKey: @"fullName"]];
[aAttendee setEmail: [ownerIdentity objectForKey: @"email"]];
[alarm addChild: aAttendee];
}
- (void) takeValuesFromRequest: (WORequest *) _rq
inContext: (WOContext *) _ctx
@@ -2236,68 +2208,43 @@ RANGE(2);
[component removeAllAlarms];
else
{
iCalTrigger *aTrigger;
iCalAlarm *anAlarm;
NSString *aValue;
NSUInteger index;
anAlarm = [iCalAlarm new];
index = [reminderItems indexOfObject: reminder];
aTrigger = [iCalTrigger elementWithTag: @"TRIGGER"];
[aTrigger setValueType: @"DURATION"];
[anAlarm setTrigger: aTrigger];
aValue = [reminderValues objectAtIndex: index];
if ([aValue length]) {
// Predefined alarm
[anAlarm setAction: @"DISPLAY"];
[aTrigger setSingleValue: aValue forKey: @""];
}
else {
// Custom alarm
if ([reminderAction length] > 0 && [reminderUnit length] > 0)
{
[anAlarm setAction: [reminderAction uppercaseString]];
if ([reminderAction isEqualToString: @"email"])
{
[anAlarm removeAllAttendees];
if (reminderEmailAttendees)
[self _appendAttendees: [component attendees]
toEmailAlarm: anAlarm];
if (reminderEmailOrganizer)
[self _appendOrganizerToEmailAlarm: anAlarm];
[anAlarm setSummary: [component summary]];
[anAlarm setComment: [component comment]];
}
if ([reminderReference caseInsensitiveCompare: @"BEFORE"] == NSOrderedSame)
aValue = [NSString stringWithString: @"-P"];
else
aValue = [NSString stringWithString: @"P"];
if ([reminderUnit caseInsensitiveCompare: @"MINUTES"] == NSOrderedSame ||
[reminderUnit caseInsensitiveCompare: @"HOURS"] == NSOrderedSame)
aValue = [aValue stringByAppendingString: @"T"];
aValue = [aValue stringByAppendingFormat: @"%i%@",
[reminderQuantity intValue],
[reminderUnit substringToIndex: 1]];
[aTrigger setSingleValue: aValue forKey: @""];
[aTrigger setRelationType: reminderRelation];
}
else
{
[anAlarm release];
anAlarm = nil;
}
}
// Predefined alarm
if ([aValue length])
{
iCalTrigger *aTrigger;
anAlarm = [[[iCalAlarm alloc] init] autorelease];
aTrigger = [iCalTrigger elementWithTag: @"TRIGGER"];
[aTrigger setValueType: @"DURATION"];
[anAlarm setTrigger: aTrigger];
[anAlarm setAction: @"DISPLAY"];
[aTrigger setSingleValue: aValue forKey: @""];
}
else
{
// Custom alarm
anAlarm = [iCalAlarm alarmForEvent: component
owner: [[self clientObject] ownerInContext: context]
action: reminderAction
unit: reminderUnit
quantity: reminderQuantity
reference: reminderReference
reminderRelation: reminderRelation
emailAttendees: reminderEmailAttendees
emailOrganizer: reminderEmailOrganizer];
}
if (anAlarm)
{
[component removeAllAlarms];
[component addToAlarms: anAlarm];
[anAlarm release];
}
}
@@ -2597,4 +2544,9 @@ RANGE(2);
return response;
}
+ (NSArray *) reminderValues
{
return reminderValues;
}
@end
+5 -25
View File
@@ -241,6 +241,11 @@
pageName = "UIxAppointmentEditor";
actionName = "save";
};
rsvpAppointment = {
protectedBy = "RespondToComponent";
pageName = "UIxAppointmentEditor";
actionName = "rsvp";
};
saveAsAppointment = {
protectedBy = "ModifyComponent";
pageName = "UIxAppointmentEditor";
@@ -256,31 +261,6 @@
actionClass = "UIxComponentEditor";
actionName = "raw";
};
accept = {
protectedBy = "RespondToComponent";
pageName = "UIxAppointmentEditor";
actionName = "accept";
};
decline = {
protectedBy = "RespondToComponent";
pageName = "UIxAppointmentEditor";
actionName = "decline";
};
delegate = {
protectedBy = "RespondToComponent";
pageName = "UIxAppointmentEditor";
actionName = "delegate";
};
tentative = {
protectedBy = "RespondToComponent";
pageName = "UIxAppointmentEditor";
actionName = "tentative";
};
needsaction = {
protectedBy = "RespondToComponent";
pageName = "UIxAppointmentEditor";
actionName = "needsAction";
};
adjust = {
protectedBy = "ModifyComponent";
actionClass = "UIxAppointmentActions";