From 07c66563e81e2747f3b741e989d7f697e0745f41 Mon Sep 17 00:00:00 2001 From: Francis Lachapelle Date: Mon, 29 Aug 2016 14:06:46 -0400 Subject: [PATCH] Until date of repeat must end after first event --- NEWS | 2 +- .../English.lproj/Localizable.strings | 2 + UI/Scheduler/UIxAppointmentEditor.m | 112 ++++++++++-------- .../UIxAppointmentEditorTemplate.wox | 14 ++- 4 files changed, 77 insertions(+), 53 deletions(-) diff --git a/NEWS b/NEWS index 0369dbd2c..17702560b 100644 --- a/NEWS +++ b/NEWS @@ -5,7 +5,7 @@ New features - Enhancements - - + - [web] don't allow a recurrence rule to end before the first occurrence Bug fixes - [eas] properly generate the BusyStatus for normal events diff --git a/UI/Scheduler/English.lproj/Localizable.strings b/UI/Scheduler/English.lproj/Localizable.strings index 67800b4b1..0dd662120 100644 --- a/UI/Scheduler/English.lproj/Localizable.strings +++ b/UI/Scheduler/English.lproj/Localizable.strings @@ -379,6 +379,8 @@ validate_notitle = "No title is set, continue?"; validate_invalid_startdate = "Incorrect startdate field!"; validate_invalid_enddate = "Incorrect enddate field!"; validate_endbeforestart = "The end date that you entered occurs before the start date."; +validate_untilbeforeend = "The recurrence must end after the first occurrence."; + "Events" = "Events"; "Tasks" = "Tasks"; "Show completed tasks" = "Show completed tasks"; diff --git a/UI/Scheduler/UIxAppointmentEditor.m b/UI/Scheduler/UIxAppointmentEditor.m index c8fc7bcd2..e05d55fd1 100644 --- a/UI/Scheduler/UIxAppointmentEditor.m +++ b/UI/Scheduler/UIxAppointmentEditor.m @@ -187,17 +187,19 @@ } */ -- (void) _adjustRecurrentRules +- (NSException *) _adjustRecurrentRules { iCalEvent *event; iCalRecurrenceRule *rule; NSEnumerator *rules; + NSException *ex; NSCalendarDate *untilDate; SOGoUserDefaults *ud; NSTimeZone *timeZone; event = [self event]; rules = [[event recurrenceRules] objectEnumerator]; + ex = nil; ud = [[context activeUser] userDefaults]; timeZone = [ud timeZone]; @@ -206,22 +208,33 @@ untilDate = [rule untilDate]; if (untilDate) { - // The until date must match the time of the end date - NSCalendarDate *date; + if ([untilDate compare: [event endDate]] == NSOrderedAscending) + { + ex = [NSException exceptionWithHTTPStatus: 500 + reason: [self labelForKey: @"validate_untilbeforeend"]]; + break; + } + else + { + // The until date must match the time of the end date + NSCalendarDate *date; - date = [[event endDate] copy]; - [date setTimeZone: timeZone]; - [untilDate setTimeZone: timeZone]; - untilDate = [untilDate dateByAddingYears:0 - months:0 - days:0 - hours:[date hourOfDay] - minutes:[date minuteOfHour] - seconds:0]; - [rule setUntilDate: untilDate]; - [date release]; + date = [[event endDate] copy]; + [date setTimeZone: timeZone]; + [untilDate setTimeZone: timeZone]; + untilDate = [untilDate dateByAddingYears:0 + months:0 + days:0 + hours:[date hourOfDay] + minutes:[date minuteOfHour] + seconds:0]; + [rule setUntilDate: untilDate]; + [date release]; + } } } + + return ex; } /** @@ -481,47 +494,50 @@ forceSave = [[params objectForKey: @"ignoreConflicts"] boolValue]; if ([event hasRecurrenceRules]) - [self _adjustRecurrentRules]; + ex = [self _adjustRecurrentRules]; - if ([co isNew]) + if (!ex) { - if (componentCalendar - && ![[componentCalendar ocsPath] - isEqualToString: [previousCalendar ocsPath]]) + if ([co isNew]) { - // New event in a different calendar -- make sure the user can - // write to the selected calendar since the rights were verified - // on the calendar specified in the URL, not on the selected - // calendar of the popup menu. - if (![sm validatePermission: SoPerm_AddDocumentsImagesAndFiles - onObject: componentCalendar - inContext: context]) - co = [componentCalendar lookupName: [co nameInContainer] - inContext: context - acquire: NO]; - } - - // Save the event. - ex = [co saveComponent: event force: forceSave]; - } - else - { - // The event was modified -- save it. - ex = [co saveComponent: event force: forceSave]; - - if (componentCalendar - && ![[componentCalendar ocsPath] - isEqualToString: [previousCalendar ocsPath]]) - { - // The event was moved to a different calendar. - if (![sm validatePermission: SoPerm_DeleteObjects - onObject: previousCalendar - inContext: context]) + if (componentCalendar + && ![[componentCalendar ocsPath] + isEqualToString: [previousCalendar ocsPath]]) { + // New event in a different calendar -- make sure the user can + // write to the selected calendar since the rights were verified + // on the calendar specified in the URL, not on the selected + // calendar of the popup menu. if (![sm validatePermission: SoPerm_AddDocumentsImagesAndFiles onObject: componentCalendar inContext: context]) - ex = [co moveToFolder: componentCalendar]; + co = [componentCalendar lookupName: [co nameInContainer] + inContext: context + acquire: NO]; + } + + // Save the event. + ex = [co saveComponent: event force: forceSave]; + } + else + { + // The event was modified -- save it. + ex = [co saveComponent: event force: forceSave]; + + if (componentCalendar + && ![[componentCalendar ocsPath] + isEqualToString: [previousCalendar ocsPath]]) + { + // The event was moved to a different calendar. + if (![sm validatePermission: SoPerm_DeleteObjects + onObject: previousCalendar + inContext: context]) + { + if (![sm validatePermission: SoPerm_AddDocumentsImagesAndFiles + onObject: componentCalendar + inContext: context]) + ex = [co moveToFolder: componentCalendar]; + } } } } diff --git a/UI/Templates/SchedulerUI/UIxAppointmentEditorTemplate.wox b/UI/Templates/SchedulerUI/UIxAppointmentEditorTemplate.wox index 9376bfff1..55669bdc4 100644 --- a/UI/Templates/SchedulerUI/UIxAppointmentEditorTemplate.wox +++ b/UI/Templates/SchedulerUI/UIxAppointmentEditorTemplate.wox @@ -214,9 +214,15 @@ - + + +
+
+
+
@@ -296,7 +302,7 @@ + ng-disabled="eventForm.$invalid">