Monotone-Parent: 9004babc502ac0232d7659ba8ada6726ad286662

Monotone-Revision: fe15a52bbb65b7147dfd596fd4f0791b716d1b26

Monotone-Author: flachapelle@inverse.ca
Monotone-Date: 2008-11-22T07:20:22
Monotone-Branch: ca.inverse.sogo
This commit is contained in:
Francis Lachapelle
2008-11-22 07:20:22 +00:00
parent d00bd0dca8
commit ff9a299ed8
10 changed files with 159 additions and 59 deletions

View File

@@ -47,6 +47,8 @@
@interface SOGoAppointmentObject : SOGoCalendarComponent
- (NSException *) changeParticipationStatus: (NSString *) _status;
- (NSException *) changeParticipationStatus: (NSString *) _status
forRecurrenceId: (NSCalendarDate *) _recurrenceId;
- (void) takeAttendeeStatus: (iCalPerson *) attendee from: (NSString *) originator;

View File

@@ -50,6 +50,7 @@
#import "NSArray+Appointments.h"
#import "SOGoAppointmentFolder.h"
#import "SOGoAppointmentOccurence.h"
#import "SOGoCalendarComponent.h"
#import "SOGoAppointmentObject.h"
@@ -162,6 +163,7 @@
NSString *possibleName;
folder = [container lookupCalendarFolderForUID: uid];
// should call lookupCalendarFoldersForUIDs to search among all folders
object = [folder lookupName: nameInContainer
inContext: context acquire: NO];
if ([object isKindOfClass: [NSException class]])
@@ -324,7 +326,7 @@
if ([attendees count])
{
[self _handleAddedUsers: attendees fromEvent: newEvent];
[self sendEMailUsingTemplateNamed: @"Invitation"
[self sendEMailUsingTemplateNamed: @"Update"
forObject: [newEvent itipEntryWithMethod: @"request"]
previousObject: oldEvent
toAttendees: attendees];
@@ -379,14 +381,18 @@
- (NSException *) _updateAttendee: (iCalPerson *) attendee
ownerUser: (SOGoUser *) theOwnerUser
forEventUID: (NSString *) eventUID
withRecurrenceId: (NSCalendarDate *) recurrenceId
withSequence: (NSNumber *) sequence
forUID: (NSString *) uid
shouldAddSentBy: (BOOL) b
{
SOGoAppointmentObject *eventObject;
iCalEvent *event;
//iCalEvent *event;
iCalCalendar *calendar;
iCalEntityObject *event;
iCalPerson *otherAttendee;
NSString *iCalString;
NSArray *events;
NSString *iCalString, *recurrenceTime;
NSException *error;
error = nil;
@@ -394,32 +400,55 @@
eventObject = [self _lookupEvent: eventUID forUID: uid];
if (![eventObject isNew])
{
event = [eventObject component: NO secure: NO];
if (recurrenceId == nil)
{
// We must update main event and all its occurences (if any).
calendar = [eventObject calendar: NO secure: NO];
event = [calendar firstChildWithTag: [self componentTag]];
events = [calendar allObjects];
}
else
{
// If recurrenceId is defined, find the specified occurence
// within the repeating vEvent.
recurrenceTime = [NSString stringWithFormat: @"%f", [recurrenceId timeIntervalSince1970]];
event = [eventObject lookupOccurence: recurrenceTime];
if (event == nil)
event = [eventObject newOccurenceWithID: recurrenceTime];
events = [NSArray arrayWithObject: event];
}
if ([[event sequence] compare: sequence]
== NSOrderedSame)
{
SOGoUser *currentUser;
//otherAttendee = [event findParticipant: [context activeUser]];
otherAttendee = [event findParticipant: theOwnerUser];
[otherAttendee setPartStat: [attendee partStat]];
// If one has accepted / declined an invitation on behalf of
// the attendee, we add the user to the SENT-BY attribute.
currentUser = [context activeUser];
if (b && ![[currentUser login] isEqualToString: [theOwnerUser login]])
int i;
for (i = 0; i < [events count]; i++)
{
NSString *currentEmail;
currentEmail = [[currentUser allEmails] objectAtIndex: 0];
[otherAttendee addAttribute: @"SENT-BY"
value: [NSString stringWithFormat: @"\"MAILTO:%@\"", currentEmail]];
}
else
{
// We must REMOVE any SENT-BY here. This is important since if A accepted
// the event for B and then, B changes by himself his participation status,
// we don't want to keep the previous SENT-BY attribute there.
[(NSMutableDictionary *)[otherAttendee attributes] removeObjectForKey: @"SENT-BY"];
event = [events objectAtIndex: i];
otherAttendee = [event findParticipant: theOwnerUser];
[otherAttendee setPartStat: [attendee partStat]];
// If one has accepted / declined an invitation on behalf of
// the attendee, we add the user to the SENT-BY attribute.
currentUser = [context activeUser];
if (b && ![[currentUser login] isEqualToString: [theOwnerUser login]])
{
NSString *currentEmail;
currentEmail = [[currentUser allEmails] objectAtIndex: 0];
[otherAttendee addAttribute: @"SENT-BY"
value: [NSString stringWithFormat: @"\"MAILTO:%@\"", currentEmail]];
}
else
{
// We must REMOVE any SENT-BY here. This is important since if A accepted
// the event for B and then, B changes by himself his participation status,
// we don't want to keep the previous SENT-BY attribute there.
[(NSMutableDictionary *)[otherAttendee attributes] removeObjectForKey: @"SENT-BY"];
}
}
iCalString = [[event parent] versitString];
@@ -489,10 +518,16 @@
from: ownerUser];
organizerUID = [[event organizer] uid];
if (!organizerUID)
// event is an recurrence; retrieve organizer from master event
organizerUID = [[(iCalEntityObject*)[[event parent] firstChildWithTag: [self componentTag]] organizer] uid];
if (organizerUID)
ex = [self _updateAttendee: attendee
ownerUser: theOwnerUser
forEventUID: [event uid]
withRecurrenceId: [event recurrenceId]
withSequence: [event sequence]
forUID: organizerUID
shouldAddSentBy: YES];
@@ -523,6 +558,7 @@
[self _updateAttendee: attendee
ownerUser: theOwnerUser
forEventUID: [event uid]
withRecurrenceId: [event recurrenceId]
withSequence: [event sequence]
forUID: uid
shouldAddSentBy: YES];
@@ -687,6 +723,7 @@
[self _updateAttendee: attendee
ownerUser: ownerUser
forEventUID: [event uid]
withRecurrenceId: [event recurrenceId]
withSequence: [event sequence]
forUID: uid
shouldAddSentBy: NO];
@@ -713,6 +750,7 @@
[self _updateAttendee: attendee
ownerUser: ownerUser
forEventUID: [event uid]
withRecurrenceId: [event recurrenceId]
withSequence: [event sequence]
forUID: uid
shouldAddSentBy: NO];
@@ -778,14 +816,38 @@
//
- (NSException *) changeParticipationStatus: (NSString *) _status
{
return [self changeParticipationStatus: _status forRecurrenceId: nil];
}
- (NSException *) changeParticipationStatus: (NSString *) _status forRecurrenceId: (NSCalendarDate *) _recurrenceId
{
iCalCalendar *calendar;
iCalEvent *event;
iCalPerson *attendee;
NSException *ex;
SOGoUser *ownerUser;
NSString *recurrenceTime;
event = nil;
ex = nil;
event = [self component: NO secure: NO];
calendar = [self calendar: NO secure: NO];
if (calendar)
{
if (_recurrenceId)
{
// If _recurrenceId is defined, find the specified occurence
// within the repeating vEvent.
recurrenceTime = [NSString stringWithFormat: @"%f", [_recurrenceId timeIntervalSince1970]];
event = [self lookupOccurence: recurrenceTime];
// If no occurence found, create one
event = [self newOccurenceWithID: recurrenceTime];
}
else
// No specific occurence specified; return the first vEvent of
// the vCalendar.
event = [calendar firstChildWithTag: [self componentTag]];
}
if (event)
{
// owerUser will actually be the owner of the calendar
@@ -794,7 +856,7 @@
// course be on the attendee that is the owner of the
// calendar where the participation change has occured.
ownerUser = [SOGoUser userWithLogin: owner roles: nil];
attendee = [event findParticipant: ownerUser];
if (attendee)
ex = [self _handleAttendee: attendee
@@ -802,14 +864,14 @@
statusChange: _status
inEvent: event];
else
ex = [NSException exceptionWithHTTPStatus: 404 /* Not Found */
ex = [NSException exceptionWithHTTPStatus: 404 // Not Found
reason: @"user does not participate in this "
@"calendar event"];
}
else
ex = [NSException exceptionWithHTTPStatus: 500 /* Server Error */
ex = [NSException exceptionWithHTTPStatus: 500 // Server Error
reason: @"unable to parse event record"];
return ex;
}
@@ -827,7 +889,7 @@
occurence = event;
if ([event userIsOrganizer: ownerUser])
{
currentUser = [context activeUser];
currentUser = [context activeUser]; // is this correct?
attendees = [occurence attendeesWithoutUser: currentUser];
if (![attendees count] && event != occurence)
attendees = [event attendeesWithoutUser: currentUser];

View File

@@ -79,6 +79,7 @@
- (NSArray *) getUIDsForICalPersons: (NSArray *) iCalPersons;
/* recurrences */
- (iCalRepeatableEntityObject *) lookupOccurence: (NSString *) recID;
- (SOGoComponentOccurence *)
occurence: (iCalRepeatableEntityObject *) component;
- (iCalRepeatableEntityObject *) newOccurenceWithID: (NSString *) recID;

View File

@@ -532,6 +532,8 @@ _occurenceHasID (iCalRepeatableEntityObject *occurence, NSString *recID)
subject = [p getSubject];
text = [p getBody];
NSLog(@"Template: %@", pageName);
NSLog(@"Email: %@ => %@ (%@)", senderEmail, recipient, subject);
/* construct message */
headerMap = [NGMutableHashMap hashMapWithCapacity: 5];

View File

@@ -34,7 +34,7 @@
- (iCalRepeatableEntityObject *) occurence;
- (BOOL) isNew;
- (NSException *) delete;
- (NSException *) prepareDelete;
@end

View File

@@ -27,9 +27,11 @@
#import <NGCards/iCalCalendar.h>
#import <NGCards/iCalRepeatableEntityObject.h>
#import "SOGoAppointmentObject.h"
#import "SOGoCalendarComponent.h"
#import "SOGoComponentOccurence.h"
#import "SOGoCalendarComponent.h"
@interface SOGoCalendarComponent (OccurenceExtensions)
- (void) prepareDeleteOccurence: (iCalRepeatableEntityObject *) component;
@@ -135,7 +137,7 @@
return component;
}
- (NSException *) delete;
- (NSException *) prepareDelete;
{
NSException *error;
iCalCalendar *parent;
@@ -149,7 +151,10 @@
[master addToExceptionDates: [component startDate]];
parent = [component parent];
[[parent children] removeObject: component];
// changes participant status & send invitation email - as if it was a new event! :(
[container saveComponent: master];
error = nil;
}
@@ -163,9 +168,13 @@
#warning most of SOGoCalendarComponent and SOGoComponentOccurence share the same external interface... \
they should be siblings or SOGoComponentOccurence the parent class of SOGoCalendarComponent...
- (NSException *) changeParticipationStatus: (NSString *) newPartStat
- (NSException *) changeParticipationStatus: (NSString *) newStatus
{
return [container changeParticipationStatus: newPartStat];
NSCalendarDate *date;
date = [component recurrenceId];
return [container changeParticipationStatus: newStatus forRecurrenceId: date];
}
@end

View File

@@ -116,11 +116,11 @@
doesOccur = [self isRecurrent];
if (doesOccur)
{
tz = [occurenceDate timeZone];
if ([tz isDaylightSavingTimeForDate: occurenceDate] != [tz isDaylightSavingTimeForDate: [self startDate]]) {
daylightOffset = [tz secondsFromGMTForDate: occurenceDate] - [tz secondsFromGMTForDate: [self startDate]];
occurenceDate = [occurenceDate dateByAddingYears: 0 months: 0 days: 0 hours: 0 minutes: 0 seconds: daylightOffset];
}
// tz = [occurenceDate timeZone];
// if ([tz isDaylightSavingTimeForDate: occurenceDate] != [tz isDaylightSavingTimeForDate: [self startDate]]) {
// daylightOffset = [tz secondsFromGMTForDate: occurenceDate] - [tz secondsFromGMTForDate: [self startDate]];
// occurenceDate = [occurenceDate dateByAddingYears: 0 months: 0 days: 0 hours: 0 minutes: 0 seconds: daylightOffset];
// }
endDate = [occurenceDate addTimeInterval: [self occurenceInterval]];
checkRange = [NGCalendarDateRange calendarDateRangeWithStartDate: occurenceDate

View File

@@ -87,4 +87,17 @@
return self;
}
- (WOResponse *) deleteAction
{
SOGoCalendarComponent *component;
WOResponse *response;
component = [self clientObject];
response = (WOResponse *) [component prepareDelete];
if (!response)
response = [self responseWithStatus: 204];
return response;
}
@end

View File

@@ -251,7 +251,7 @@
confirmDeletion = {
protectedBy = "ModifyComponent";
pageName = "UIxOccurenceDialog";
actionName = "confirmDeletion";
actionName = "confirmDeletion";
};
};
};
@@ -273,6 +273,11 @@
pageName = "UIxAppointmentEditor";
actionName = "save";
};
delete = {
protectedBy = "Delete Objects";
pageName = "UIxOccurenceDialog";
actionName = "delete";
};
};
};

View File

@@ -396,7 +396,7 @@ function onViewEventCallback(http) {
}
}
else {
log("onViewEventCallback ajax error:" + http.url);
log("onViewEventCallback ajax error: " + http.url);
}
}
@@ -414,23 +414,29 @@ function performEventEdition(folder, event, recurrence) {
}
function performEventDeletion(folder, event, recurrence) {
if (calendarEvents) {
var urlstr = ApplicationBaseURL + folder + "/" + event;
var occurenceTime;
if (calendarEvents) {
if (recurrence) {
urlstr += "/" + recurrence;
occurenceTime = recurrence.substring(9);
// Only one recurrence
var occurenceTime = recurrence.substring(9);
var nodes = _eventBlocksMatching(folder, event, occurenceTime);
var urlstr = ApplicationBaseURL + folder + "/" + event + "/" + recurrence + "/delete";
if (nodes)
document.deleteEventAjaxRequest = triggerAjaxRequest(urlstr,
performDeleteEventCallback,
{ nodes: nodes,
occurence: occurenceTime });
}
else
occurenceTime = null;
urlstr += "/delete";
var nodes = _eventBlocksMatching(folder, event, occurenceTime);
if (nodes)
document.deleteEventAjaxRequest = triggerAjaxRequest(urlstr,
performDeleteEventCallback,
{ nodes: nodes,
occurence: occurenceTime });
else {
// All recurrences
if (document.deleteEventAjaxRequest) {
document.deleteEventAjaxRequest.aborted = true;
document.deleteEventAjaxRequest.abort();
}
eventsToDelete.push([event]);
calendarsOfEventsToDelete.push(folder);
_batchDeleteEvents();
}
}
}
@@ -443,7 +449,6 @@ function performDeleteEventCallback(http) {
var calendar = nodes[0].calendar;
for (var i = 0; i < nodes.length; i++) {
var node = nodes[i];
// log("node: " + node);
node.parentNode.removeChild(node);
}
var basename = calendar + "-" + cname;
@@ -453,11 +458,12 @@ function performDeleteEventCallback(http) {
if (row)
row.parentNode.removeChild(row);
// Update calendar events cache
var occurences = calendarEvents[calendar][cname];
var newOccurences = [];
for (var i = 0; i < occurences.length; i++) {
var occurence = occurences[i];
if (occurence[13] != recurrenceTime)
if (occurence[13] != occurenceTime)
newOccurences.push(occurence);
}
calendarEvents[calendar][cname] = newOccurences;