From ef84985025024d406fb3f25dc533d457ebf487f7 Mon Sep 17 00:00:00 2001 From: Francis Lachapelle Date: Fri, 21 Oct 2016 17:30:47 -0400 Subject: [PATCH] Fix support for recurrent tasks --- NEWS | 6 +++ .../Appointments/SOGoAppointmentFolder.m | 42 +++++++++++++------ SoObjects/Appointments/SOGoTaskObject.m | 23 +++++----- UI/Scheduler/NSArray+Scheduler.h | 5 +++ UI/Scheduler/UIxCalListingActions.m | 24 ++++++----- 5 files changed, 67 insertions(+), 33 deletions(-) diff --git a/NEWS b/NEWS index 00dc609ca..7000f5472 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,9 @@ +2.3.18 (2016-11-DD) +------------------- + +Bug fixes + - [web] fixed support for recurrent tasks + 2.3.17 (2016-10-20) ------------------- diff --git a/SoObjects/Appointments/SOGoAppointmentFolder.m b/SoObjects/Appointments/SOGoAppointmentFolder.m index e9a795b04..3df07ce87 100644 --- a/SoObjects/Appointments/SOGoAppointmentFolder.m +++ b/SoObjects/Appointments/SOGoAppointmentFolder.m @@ -869,16 +869,22 @@ static Class iCalEventK = nil; } [record setObject: dateSecs forKey: @"c_recurrence_id"]; - date = [theCycle endDate]; - if (theEventTimeZone) + date = [record valueForKey: @"c_enddate"]; + if ([date isNotNull]) { - secondsOffsetFromGMT = (int) [[theEventTimeZone periodForDate: date] secondsOffsetFromGMT]; - date = [date dateByAddingYears: 0 months: 0 days: 0 hours: 0 minutes: 0 seconds: -secondsOffsetFromGMT]; + date = [theCycle endDate]; + if (theEventTimeZone) + { + secondsOffsetFromGMT = (int) [[theEventTimeZone periodForDate: date] secondsOffsetFromGMT]; + date = [date dateByAddingYears: 0 months: 0 days: 0 hours: 0 minutes: 0 seconds: -secondsOffsetFromGMT]; + } + [date setTimeZone: timeZone]; + [record setObject: date forKey: @"endDate"]; + dateSecs = [NSNumber numberWithInt: [date timeIntervalSince1970]]; + [record setObject: dateSecs forKey: @"c_enddate"]; } - [date setTimeZone: timeZone]; - [record setObject: date forKey: @"endDate"]; - dateSecs = [NSNumber numberWithInt: [date timeIntervalSince1970]]; - [record setObject: dateSecs forKey: @"c_enddate"]; + else + [record removeObjectForKey: @"endDate"]; return record; } @@ -980,7 +986,7 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir toArray: (NSMutableArray *) ma { NGCalendarDateRange *recurrenceIdRange; - NSCalendarDate *recurrenceId; + NSCalendarDate *recurrenceId, *masterEndDate, *endDate; NSMutableDictionary *newRecord; NGCalendarDateRange *newRecordRange; NSComparisonResult compare; @@ -1010,8 +1016,20 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir [recurrenceId setTimeZone: tz]; } - master = [[[component parent] events] objectAtIndex: 0]; - delta = [[master endDate] timeIntervalSinceDate: [master startDate]]; + if ([component isKindOfClass: [iCalEvent class]]) + { + master = [[[component parent] events] objectAtIndex: 0]; + masterEndDate = [master endDate]; + endDate = [component endDate]; + } + else + { + master = [[[component parent] todos] objectAtIndex: 0]; + masterEndDate = [master due]; + endDate = [component due]; + } + + delta = [masterEndDate timeIntervalSinceDate: [master startDate]]; recurrenceIdRange = [NGCalendarDateRange calendarDateRangeWithStartDate: recurrenceId endDate: [recurrenceId dateByAddingYears:0 months:0 days:0 hours:0 minutes:0 seconds: delta]]; if ([dateRange doesIntersectWithDateRange: recurrenceIdRange]) @@ -1022,7 +1040,7 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir if (recordIndex > -1) { if ([dateRange containsDate: [component startDate]] || - [dateRange containsDate: [component endDate]]) + [dateRange containsDate: endDate]) { // We must pass nil to :container here in order to avoid re-entrancy issues. newRecord = [self _fixupRecord: [component quickRecordFromContent: nil container: nil]]; diff --git a/SoObjects/Appointments/SOGoTaskObject.m b/SoObjects/Appointments/SOGoTaskObject.m index e51641556..4cbf1a996 100644 --- a/SoObjects/Appointments/SOGoTaskObject.m +++ b/SoObjects/Appointments/SOGoTaskObject.m @@ -93,20 +93,23 @@ newOccurence = (iCalToDo *) [super newOccurenceWithID: theRecurrenceID]; date = [newOccurence recurrenceId]; + [newOccurence setStartDate: date]; master = [self component: NO secure: NO]; - firstDate = [master startDate]; - interval = [[master due] - timeIntervalSinceDate: (NSDate *)firstDate]; + if ([master due]) + { + firstDate = [master startDate]; + interval = [[master due] + timeIntervalSinceDate: (NSDate *)firstDate]; - [newOccurence setStartDate: date]; - [newOccurence setDue: [date addYear: 0 - month: 0 - day: 0 - hour: 0 - minute: 0 - second: interval]]; + [newOccurence setDue: [date addYear: 0 + month: 0 + day: 0 + hour: 0 + minute: 0 + second: interval]]; + } return newOccurence; } diff --git a/UI/Scheduler/NSArray+Scheduler.h b/UI/Scheduler/NSArray+Scheduler.h index ed3ae2434..fcd096987 100644 --- a/UI/Scheduler/NSArray+Scheduler.h +++ b/UI/Scheduler/NSArray+Scheduler.h @@ -61,6 +61,11 @@ #define taskEditableIndex 9 #define taskErasableIndex 10 #define taskPriorityIndex 11 +#define taskOwnerIndex 12 +#define taskRecurrenceIdIndex 13 +#define taskIsExceptionIndex 14 +#define taskDescriptionIndex 15 +#define taskStatusFlagIndex 16 @interface NSArray (SOGoEventComparison) diff --git a/UI/Scheduler/UIxCalListingActions.m b/UI/Scheduler/UIxCalListingActions.m index c02e82a0a..86f26a97b 100644 --- a/UI/Scheduler/UIxCalListingActions.m +++ b/UI/Scheduler/UIxCalListingActions.m @@ -99,7 +99,8 @@ static NSArray *tasksFields = nil; @"c_status", @"c_title", @"c_enddate", @"c_classification", @"c_location", @"c_category", @"editable", @"erasable", - @"c_priority", @"c_owner", @"c_recurrence_id", @"isException", @"c_description", nil]; + @"c_priority", @"c_owner", + @"c_recurrence_id", @"isException", @"c_description", nil]; [tasksFields retain]; } } @@ -313,7 +314,7 @@ static NSArray *tasksFields = nil; NSMutableDictionary *newInfo; NSMutableArray *infos, *newInfoForComponent, *quickInfos, *allInfos, *quickInfosName; NSNull *marker; - NSString *owner, *role, *calendarName, *filters, *iCalString; + NSString *owner, *role, *calendarName, *iCalString; NSRange match; iCalCalendar *calendar; iCalEntityObject *master; @@ -1072,7 +1073,6 @@ _computeBlocksPosition (NSArray *blocks) NSString *fUID; NSNumber *isActive; unsigned int count, foldersCount; - int max=0, i; co = [self clientObject]; folders = [co subFolders]; @@ -1218,14 +1218,12 @@ _computeBlocksPosition (NSArray *blocks) BOOL showCompleted; int statusCode; int startSecs; - int endsSecs; filteredTasks = [NSMutableArray array]; [self _setupContext]; startSecs = (unsigned int) [startDate timeIntervalSince1970]; - endsSecs = (unsigned int) [endDate timeIntervalSince1970]; tasksView = [request formValueForKey: @"filterpopup"]; #warning see TODO in SchedulerUI.js about "setud" @@ -1242,11 +1240,11 @@ _computeBlocksPosition (NSArray *blocks) while ((task = [tasks nextObject])) { - statusCode = [[task objectAtIndex: 3] intValue]; + statusCode = [[task objectAtIndex: taskStatusIndex] intValue]; if (statusCode != 1 || showCompleted) { filteredTask = [NSMutableArray arrayWithArray: task]; - endDateStamp = [[task objectAtIndex: 5] intValue]; + endDateStamp = [[task objectAtIndex: taskEndDateIndex] intValue]; statusFlag = [self _getStatusClassForStatusCode: statusCode andEndDateStamp: endDateStamp]; [filteredTask addObject: statusFlag]; @@ -1258,15 +1256,19 @@ _computeBlocksPosition (NSArray *blocks) [tasksView isEqualToString:@"view_next7"] || [tasksView isEqualToString:@"view_next14"] || [tasksView isEqualToString:@"view_next31"] || - [tasksView isEqualToString:@"view_thismonth"]) && ((endDateStamp <= endsSecs) && (endDateStamp >= startSecs))) + [tasksView isEqualToString:@"view_thismonth"]) && + (endDateStamp == 0 || endDateStamp >= startSecs)) [filteredTasks addObject: filteredTask]; else if ([tasksView isEqualToString:@"view_all"]) [filteredTasks addObject: filteredTask]; - else if (([tasksView isEqualToString:@"view_overdue"]) && ([[filteredTask objectAtIndex:15] isEqualToString:@"overdue"])) + else if (([tasksView isEqualToString:@"view_overdue"]) && + ([[filteredTask objectAtIndex:taskStatusFlagIndex] isEqualToString:@"overdue"])) [filteredTasks addObject: filteredTask]; - else if ([tasksView isEqualToString:@"view_incomplete"] && (![[filteredTask objectAtIndex:15] isEqualToString:@"completed"])) + else if ([tasksView isEqualToString:@"view_incomplete"] && + (![[filteredTask objectAtIndex:taskStatusFlagIndex] isEqualToString:@"completed"])) [filteredTasks addObject: filteredTask]; - else if ([tasksView isEqualToString:@"view_not_started"] && ([[[filteredTask objectAtIndex:3] stringValue] isEqualToString:@"0"])) + else if ([tasksView isEqualToString:@"view_not_started"] && + ([[[filteredTask objectAtIndex:taskStatusIndex] stringValue] isEqualToString:@"0"])) [filteredTasks addObject: filteredTask]; } }