Until date of repeat must end after first event
parent
ce5cc6843e
commit
07c66563e8
2
NEWS
2
NEWS
|
@ -5,7 +5,7 @@ New features
|
||||||
-
|
-
|
||||||
|
|
||||||
Enhancements
|
Enhancements
|
||||||
-
|
- [web] don't allow a recurrence rule to end before the first occurrence
|
||||||
|
|
||||||
Bug fixes
|
Bug fixes
|
||||||
- [eas] properly generate the BusyStatus for normal events
|
- [eas] properly generate the BusyStatus for normal events
|
||||||
|
|
|
@ -379,6 +379,8 @@ validate_notitle = "No title is set, continue?";
|
||||||
validate_invalid_startdate = "Incorrect startdate field!";
|
validate_invalid_startdate = "Incorrect startdate field!";
|
||||||
validate_invalid_enddate = "Incorrect enddate field!";
|
validate_invalid_enddate = "Incorrect enddate field!";
|
||||||
validate_endbeforestart = "The end date that you entered occurs before the start date.";
|
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";
|
"Events" = "Events";
|
||||||
"Tasks" = "Tasks";
|
"Tasks" = "Tasks";
|
||||||
"Show completed tasks" = "Show completed tasks";
|
"Show completed tasks" = "Show completed tasks";
|
||||||
|
|
|
@ -187,17 +187,19 @@
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
- (void) _adjustRecurrentRules
|
- (NSException *) _adjustRecurrentRules
|
||||||
{
|
{
|
||||||
iCalEvent *event;
|
iCalEvent *event;
|
||||||
iCalRecurrenceRule *rule;
|
iCalRecurrenceRule *rule;
|
||||||
NSEnumerator *rules;
|
NSEnumerator *rules;
|
||||||
|
NSException *ex;
|
||||||
NSCalendarDate *untilDate;
|
NSCalendarDate *untilDate;
|
||||||
SOGoUserDefaults *ud;
|
SOGoUserDefaults *ud;
|
||||||
NSTimeZone *timeZone;
|
NSTimeZone *timeZone;
|
||||||
|
|
||||||
event = [self event];
|
event = [self event];
|
||||||
rules = [[event recurrenceRules] objectEnumerator];
|
rules = [[event recurrenceRules] objectEnumerator];
|
||||||
|
ex = nil;
|
||||||
ud = [[context activeUser] userDefaults];
|
ud = [[context activeUser] userDefaults];
|
||||||
timeZone = [ud timeZone];
|
timeZone = [ud timeZone];
|
||||||
|
|
||||||
|
@ -206,22 +208,33 @@
|
||||||
untilDate = [rule untilDate];
|
untilDate = [rule untilDate];
|
||||||
if (untilDate)
|
if (untilDate)
|
||||||
{
|
{
|
||||||
// The until date must match the time of the end date
|
if ([untilDate compare: [event endDate]] == NSOrderedAscending)
|
||||||
NSCalendarDate *date;
|
{
|
||||||
|
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 = [[event endDate] copy];
|
||||||
[date setTimeZone: timeZone];
|
[date setTimeZone: timeZone];
|
||||||
[untilDate setTimeZone: timeZone];
|
[untilDate setTimeZone: timeZone];
|
||||||
untilDate = [untilDate dateByAddingYears:0
|
untilDate = [untilDate dateByAddingYears:0
|
||||||
months:0
|
months:0
|
||||||
days:0
|
days:0
|
||||||
hours:[date hourOfDay]
|
hours:[date hourOfDay]
|
||||||
minutes:[date minuteOfHour]
|
minutes:[date minuteOfHour]
|
||||||
seconds:0];
|
seconds:0];
|
||||||
[rule setUntilDate: untilDate];
|
[rule setUntilDate: untilDate];
|
||||||
[date release];
|
[date release];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return ex;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -481,47 +494,50 @@
|
||||||
forceSave = [[params objectForKey: @"ignoreConflicts"] boolValue];
|
forceSave = [[params objectForKey: @"ignoreConflicts"] boolValue];
|
||||||
|
|
||||||
if ([event hasRecurrenceRules])
|
if ([event hasRecurrenceRules])
|
||||||
[self _adjustRecurrentRules];
|
ex = [self _adjustRecurrentRules];
|
||||||
|
|
||||||
if ([co isNew])
|
if (!ex)
|
||||||
{
|
{
|
||||||
if (componentCalendar
|
if ([co isNew])
|
||||||
&& ![[componentCalendar ocsPath]
|
|
||||||
isEqualToString: [previousCalendar ocsPath]])
|
|
||||||
{
|
{
|
||||||
// New event in a different calendar -- make sure the user can
|
if (componentCalendar
|
||||||
// write to the selected calendar since the rights were verified
|
&& ![[componentCalendar ocsPath]
|
||||||
// on the calendar specified in the URL, not on the selected
|
isEqualToString: [previousCalendar ocsPath]])
|
||||||
// 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])
|
|
||||||
{
|
{
|
||||||
|
// 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
|
if (![sm validatePermission: SoPerm_AddDocumentsImagesAndFiles
|
||||||
onObject: componentCalendar
|
onObject: componentCalendar
|
||||||
inContext: context])
|
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];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -214,9 +214,15 @@
|
||||||
<label><var:string label:value="times"/></label>
|
<label><var:string label:value="times"/></label>
|
||||||
<input type="number" label:aria-label="times" ng-model="editor.component.repeat.count"/>
|
<input type="number" label:aria-label="times" ng-model="editor.component.repeat.count"/>
|
||||||
</md-input-container>
|
</md-input-container>
|
||||||
<md-datepicker ng-show="editor.component.repeat.end == 'until'"
|
<md-input-container ng-show="editor.component.repeat.end == 'until'">
|
||||||
ng-model="editor.component.repeat.until"
|
<md-datepicker name="repeat_until"
|
||||||
label:md-placeholder="On Date"><!-- date picker --></md-datepicker>
|
ng-model="editor.component.repeat.until"
|
||||||
|
md-min-date="editor.component.end"
|
||||||
|
label:md-placeholder="On Date"><!-- date picker --></md-datepicker>
|
||||||
|
<div ng-messages="eventForm.repeat_until.$error">
|
||||||
|
<div ng-message="mindate"><var:string label:value="validate_untilbeforeend"/></div>
|
||||||
|
</div>
|
||||||
|
</md-input-container>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- attendees -->
|
<!-- attendees -->
|
||||||
|
@ -296,7 +302,7 @@
|
||||||
<var:string label:value="Reset"/>
|
<var:string label:value="Reset"/>
|
||||||
</md-button>
|
</md-button>
|
||||||
<md-button class="md-primary" type="submit"
|
<md-button class="md-primary" type="submit"
|
||||||
ng-disabled="editor.eventForm.$invalid">
|
ng-disabled="eventForm.$invalid">
|
||||||
<var:string label:value="Save"/>
|
<var:string label:value="Save"/>
|
||||||
</md-button>
|
</md-button>
|
||||||
</md-dialog-actions>
|
</md-dialog-actions>
|
||||||
|
|
Loading…
Reference in New Issue