From 2d2fcffec54e0b52d689be5eba44115d2f5ef1e9 Mon Sep 17 00:00:00 2001 From: Ludovic Marcotte Date: Mon, 14 Jan 2008 13:57:28 +0000 Subject: [PATCH] see changelog Monotone-Parent: 0f4484bf642d11bc96f9672226ec495c99e2301f Monotone-Revision: b7b4b1f3f729de477db90d41fee55b91ea781b02 Monotone-Author: ludovic@Sophos.ca Monotone-Date: 2008-01-14T13:57:28 Monotone-Branch: ca.inverse.sogo --- ChangeLog | 14 + SOPE/NGCards/iCalDailyRecurrenceCalculator.m | 14 +- UI/Scheduler/GNUmakefile | 3 +- UI/Scheduler/UIxAppointmentEditor.h | 7 - UI/Scheduler/UIxAppointmentEditor.m | 178 ------ UI/Scheduler/UIxComponentEditor.h | 28 + UI/Scheduler/UIxComponentEditor.m | 528 +++++++++++++++++- UI/Scheduler/UIxRecurrenceEditor.h | 54 ++ UI/Scheduler/UIxRecurrenceEditor.m | 244 ++++++++ UI/Scheduler/UIxTaskEditor.h | 3 - UI/Scheduler/UIxTaskEditor.m | 42 -- UI/Scheduler/product.plist | 4 + .../SchedulerUI/UIxAppointmentEditor.wox | 14 - .../SchedulerUI/UIxComponentEditor.wox | 49 ++ .../SchedulerUI/UIxRecurrenceEditor.wox | 154 +++++ UI/Templates/SchedulerUI/UIxTaskEditor.wox | 7 - UI/WebServerResources/HTMLElement.js | 38 ++ UI/WebServerResources/UIxComponentEditor.js | 13 + UI/WebServerResources/UIxRecurrenceEditor.css | 7 + UI/WebServerResources/UIxRecurrenceEditor.js | 135 +++++ 20 files changed, 1282 insertions(+), 254 deletions(-) create mode 100644 UI/Scheduler/UIxRecurrenceEditor.h create mode 100644 UI/Scheduler/UIxRecurrenceEditor.m create mode 100644 UI/Templates/SchedulerUI/UIxRecurrenceEditor.wox create mode 100644 UI/WebServerResources/UIxRecurrenceEditor.css create mode 100644 UI/WebServerResources/UIxRecurrenceEditor.js diff --git a/ChangeLog b/ChangeLog index 2a1643581..ac1b5e78d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2008-01-14 Ludovic Marcotte + + * Added files related to the custom recurrence + editor of the SOGo Web interface. The CSS + needs to be done correctly. + + * Fixed a bug in the daily recurrence generator. + We now consider the byDayMask, if any. + + * Moved the repeat/reminder code to the + UIxComponentEditor class / template. + + * Added a few JavaScript methods to HTMLElement.js + 2008-01-08 Francis Lachapelle * UI/MailerUI/UIxMailAccountActions.m ([UIxMailAccountActions diff --git a/SOPE/NGCards/iCalDailyRecurrenceCalculator.m b/SOPE/NGCards/iCalDailyRecurrenceCalculator.m index 17a1d483e..7c7d2656c 100644 --- a/SOPE/NGCards/iCalDailyRecurrenceCalculator.m +++ b/SOPE/NGCards/iCalDailyRecurrenceCalculator.m @@ -33,6 +33,8 @@ #import "iCalRecurrenceRule.h" #import "NSCalendarDate+ICal.h" +#include + @interface iCalRecurrenceCalculator(PrivateAPI) - (NSCalendarDate *)lastInstanceStartDate; @end @@ -90,13 +92,23 @@ if ((jnTest % interval) == 0) { NSCalendarDate *start, *end; NGCalendarDateRange *r; - + unsigned int mask; + start = [NSCalendarDate dateForJulianNumber:jnCurrent]; [start setTimeZone:[firStart timeZone]]; start = [start hour: [firStart hourOfDay] minute:[firStart minuteOfHour] second:[firStart secondOfMinute]]; end = [start addTimeInterval:[self->firstRange duration]]; + + // We check if our start date is within the byDayMask + // FIXME: Should we also check the end date? We might want + // to check if the end date is also within it. + if ([self->rrule byDayMask]) { + mask = [start dayOfWeek] == 0 ? iCalWeekDaySunday : (unsigned int)exp2([start dayOfWeek]-1); + if (([self->rrule byDayMask]&mask) != mask) continue; + } + r = [NGCalendarDateRange calendarDateRangeWithStartDate:start endDate:end]; if ([_r containsDateRange:r]) diff --git a/UI/Scheduler/GNUmakefile b/UI/Scheduler/GNUmakefile index aab7f0288..92f59324f 100644 --- a/UI/Scheduler/GNUmakefile +++ b/UI/Scheduler/GNUmakefile @@ -41,7 +41,8 @@ SchedulerUI_OBJC_FILES = \ UIxTimeDateControl.m \ UIxCalParticipationStatusView.m \ UIxCalMonthOverview.m \ - UIxCalMonthViewOld.m + UIxCalMonthViewOld.m \ + UIxRecurrenceEditor.m SchedulerUI_RESOURCE_FILES += \ Version \ diff --git a/UI/Scheduler/UIxAppointmentEditor.h b/UI/Scheduler/UIxAppointmentEditor.h index c3ead6856..fba6ed39b 100644 --- a/UI/Scheduler/UIxAppointmentEditor.h +++ b/UI/Scheduler/UIxAppointmentEditor.h @@ -35,7 +35,6 @@ NSCalendarDate *aptStartDate; NSCalendarDate *aptEndDate; NSString *item; - NSString *repeat; } /* template values */ @@ -52,12 +51,6 @@ - (void) setAptEndDate: (NSCalendarDate *) _date; - (NSCalendarDate *) aptEndDate; -- (NSString *) repeat; -- (void) setRepeat: (NSString *) newRepeat; - -- (NSString *) reminder; -- (void) setReminder: (NSString *) newReminder; - @end #endif /* UIXAPPOINTMENTEDITOR_H */ diff --git a/UI/Scheduler/UIxAppointmentEditor.m b/UI/Scheduler/UIxAppointmentEditor.m index 382ff96d1..a1c33099d 100644 --- a/UI/Scheduler/UIxAppointmentEditor.m +++ b/UI/Scheduler/UIxAppointmentEditor.m @@ -51,7 +51,6 @@ aptEndDate = nil; item = nil; event = nil; - repeat = nil; isAllDay = NO; } @@ -61,7 +60,6 @@ - (void) dealloc { [item release]; - [repeat release]; [aptStartDate release]; [aptEndDate release]; [super dealloc]; @@ -121,39 +119,6 @@ return aptEndDate; } -- (NSArray *) repeatList -{ - static NSArray *repeatItems = nil; - - if (!repeatItems) - { - repeatItems = [NSArray arrayWithObjects: @"DAILY", - @"WEEKLY", - @"BI-WEEKLY", - @"EVERY WEEKDAY", - @"MONTHLY", - @"YEARLY", - @"-", - @"CUSTOM", - nil]; - [repeatItems retain]; - } - - return repeatItems; -} - -- (NSString *) itemRepeatText -{ - NSString *text; - - if ([item isEqualToString: @"-"]) - text = item; - else - text = [self labelForKey: [NSString stringWithFormat: @"repeat_%@", item]]; - - return text; -} - - (void) setItem: (NSString *) newItem { ASSIGN (item, newItem); @@ -164,76 +129,6 @@ return item; } -- (NSArray *) reminderList -{ - static NSArray *reminderItems = nil; - - if (!reminderItems) - { - reminderItems = [NSArray arrayWithObjects: @"5_MINUTES_BEFORE", - @"10_MINUTES_BEFORE", - @"15_MINUTES_BEFORE", - @"30_MINUTES_BEFORE", - @"45_MINUTES_BEFORE", - @"-", - @"1_HOUR_BEFORE", - @"2_HOURS_BEFORE", - @"5_HOURS_BEFORE", - @"15_HOURS_BEFORE", - @"-", - @"1_DAY_BEFORE", - @"2_DAYS_BEFORE", - @"1_WEEK_BEFORE", - @"-", - @"CUSTOM", - nil]; - [reminderItems retain]; - } - - return reminderItems; -} - -// - (void) setReminder: (NSString *) reminder -// { -// ASSIGN(reminder, _reminder); -// } - -// - (NSString *) reminder -// { -// return reminder; -// } - -- (NSString *) reminder -{ - return @""; -} - -- (void) setReminder: (NSString *) newReminder -{ -} - -- (NSString *) itemReminderText -{ - NSString *text; - - if ([item isEqualToString: @"-"]) - text = item; - else - text = [self labelForKey: [NSString stringWithFormat: @"reminder_%@", item]]; - - return text; -} - -- (NSString *) repeat -{ - return repeat; -} - -- (void) setRepeat: (NSString *) newRepeat -{ - ASSIGN (repeat, newRepeat); -} - /* actions */ - (NSCalendarDate *) newStartDate { @@ -269,7 +164,6 @@ NSCalendarDate *startDate, *endDate; NSString *duration; unsigned int minutes; - iCalRecurrenceRule *rule; [self event]; if ([[self clientObject] isNew]) @@ -297,41 +191,6 @@ ASSIGN (aptStartDate, startDate); ASSIGN (aptEndDate, endDate); - // We initialize our repeat ivars - if ([event hasRecurrenceRules]) - { - repeat = @"CUSTOM"; - - rule = [[event recurrenceRules] lastObject]; - - if ([rule frequency] == iCalRecurrenceFrequenceWeekly) - { - if ([rule repeatInterval] == 1) - repeat = @"WEEKLY"; - else if ([rule repeatInterval] == 2) - repeat = @"BI-WEEKLY"; - } - else if ([rule frequency] == iCalRecurrenceFrequenceDaily) - { - if ([rule byDayMask] == (iCalWeekDayMonday - | iCalWeekDayTuesday - | iCalWeekDayWednesday - | iCalWeekDayThursday - | iCalWeekDayFriday)) - repeat = @"EVERY WEEKDAY"; - else if (![rule byDayMask]) - repeat = @"DAILY"; - } - else if ([rule frequency] == iCalRecurrenceFrequenceMonthly - && [rule repeatInterval] == 1) - repeat = @"MONTHLY"; - else if ([rule frequency] == iCalRecurrenceFrequenceYearly - && [rule repeatInterval] == 1) - repeat = @"YEARLY"; - } - else - DESTROY(repeat); - return self; } @@ -380,7 +239,6 @@ { SOGoAppointmentObject *clientObject; int nbrDays; - iCalRecurrenceRule *rule; clientObject = [self clientObject]; [self event]; @@ -401,42 +259,6 @@ } if ([clientObject isNew]) [event setTransparency: @"OPAQUE"]; - - // We remove any repeat rules - if (!repeat && [event hasRecurrenceRules]) - [event removeAllRecurrenceRules]; - else if (!([repeat caseInsensitiveCompare: @"-"] == NSOrderedSame - || [repeat caseInsensitiveCompare: @"CUSTOM"] == NSOrderedSame)) - { - rule = [iCalRecurrenceRule new]; - - [rule setInterval: @"1"]; - if ([repeat caseInsensitiveCompare: @"BI-WEEKLY"] == NSOrderedSame) - { - [rule setFrequency: iCalRecurrenceFrequenceWeekly]; - [rule setInterval: @"2"]; - } - else if ([repeat caseInsensitiveCompare: @"EVERY WEEKDAY"] == NSOrderedSame) - { - [rule setByDayMask: (iCalWeekDayMonday - |iCalWeekDayTuesday - |iCalWeekDayWednesday - |iCalWeekDayThursday - |iCalWeekDayFriday)]; - [rule setFrequency: iCalRecurrenceFrequenceDaily]; - } - else if ([repeat caseInsensitiveCompare: @"MONTHLY"] == NSOrderedSame) - { - [rule setNamedValue: @"bymonthday" - to: [NSString stringWithFormat: @"%d", [aptStartDate dayOfMonth]]]; - [rule setFrequency: iCalRecurrenceFrequenceMonthly]; - } - else - [rule setFrequency: - (iCalRecurrenceFrequency) [rule valueForFrequency: repeat]]; - [event setRecurrenceRules: [NSArray arrayWithObject: rule]]; - [rule release]; - } } // TODO: add tentatively diff --git a/UI/Scheduler/UIxComponentEditor.h b/UI/Scheduler/UIxComponentEditor.h index e6172e002..55bf57396 100644 --- a/UI/Scheduler/UIxComponentEditor.h +++ b/UI/Scheduler/UIxComponentEditor.h @@ -64,6 +64,22 @@ NSString *attendeesUIDs; NSString *attendeesEmails; NSString *attendeesStates; + + NSString *repeat; + NSString *reminder; + + /* ugly */ + NSString *repeatType; + NSString *repeat1; + NSString *repeat2; + NSString *repeat3; + NSString *repeat4; + NSString *repeat5; + NSString *repeat6; + NSString *repeat7; + + NSString *range1; + NSString *range2; } - (NSString *) toolbar; @@ -120,6 +136,15 @@ - (void) setAttendeesEmails: (NSString *) newAttendeesEmails; - (NSString *) attendeesEmails; +- (NSString *) repeat; +- (void) setRepeat: (NSString *) newRepeat; + +- (NSString *) reminder; +- (void) setReminder: (NSString *) newReminder; + +////////////////////////////////// JUNK //////////////////////////////////////// +////////////////////////////////// JUNK //////////////////////////////////////// +////////////////////////////////// JUNK //////////////////////////////////////// - (NSArray *) cycles; - (void) setCycle: (NSDictionary *) _cycle; - (NSDictionary *) cycle; @@ -136,6 +161,9 @@ - (BOOL) isCycleEndUntil; - (void) setIsCycleEndUntil; - (void) setIsCycleEndNever; +////////////////////////////////// JUNK //////////////////////////////////////// +////////////////////////////////// JUNK //////////////////////////////////////// +////////////////////////////////// JUNK //////////////////////////////////////// /* access */ - (BOOL) isMyComponent; diff --git a/UI/Scheduler/UIxComponentEditor.m b/UI/Scheduler/UIxComponentEditor.m index cddb44ee5..c4c23f380 100644 --- a/UI/Scheduler/UIxComponentEditor.m +++ b/UI/Scheduler/UIxComponentEditor.m @@ -58,6 +58,14 @@ #import "UIxComponentEditor.h" +#define REPEAT(X) \ +- (NSString *) repeat##X { return repeat##X; } \ +- (void) setRepeat##X: (NSString *) theValue { NSLog(@"setRepeat %@", theValue); ASSIGN(repeat##X, theValue); } \ + +#define RANGE(X) \ +- (NSString *) range##X { return range##X; } \ +- (void) setRange##X: (NSString *) theValue { ASSIGN(range##X, theValue); } + @implementation UIxComponentEditor - (id) init @@ -75,6 +83,18 @@ attendeesEmails = nil; attendeesStates = nil; calendarList = nil; + repeat = nil; + reminder = nil; + repeatType = nil; + repeat1 = nil; + repeat2 = nil; + repeat3 = nil; + repeat4 = nil; + repeat5 = nil; + repeat6 = nil; + repeat7 = nil; + range1 = nil; + range2 = nil; } return self; @@ -100,6 +120,20 @@ [attendeesStates release]; [calendarList release]; + [repeat release]; + [reminder release]; + + [repeatType release]; + [repeat1 release]; + [repeat2 release]; + [repeat3 release]; + [repeat4 release]; + [repeat5 release]; + [repeat6 release]; + [repeat7 release]; + [range1 release]; + [range2 release]; + [component release]; [super dealloc]; @@ -160,6 +194,160 @@ } } +- (NSString *) _dayMaskToInteger: (unsigned int) theMask +{ + NSMutableString *s; + unsigned int i, v; + + unsigned char maskDays[] = { iCalWeekDayMonday, iCalWeekDayTuesday, + iCalWeekDayWednesday, iCalWeekDayThursday, + iCalWeekDayFriday, iCalWeekDaySaturday, + iCalWeekDaySunday }; + + s = [NSMutableString string]; + + for (i = 0; i < 7; i++) + { + if ((theMask&maskDays[i]) == maskDays[i]) + [s appendFormat: @"%d,", i+1]; + } + + if ([s length]) + return [s substringToIndex: [s length]-1]; + + return s; +} + +- (void) _loadRRules +{ + // We initialize our repeat ivars + if ([component hasRecurrenceRules]) + { + iCalRecurrenceRule *rule; + + [self setRepeat: @"CUSTOM"]; + + rule = [[component recurrenceRules] lastObject]; + + // If we either have an end date or a recurrence count + // it's automatically a CUSTOM one. + //if (![rule isInfinite] || [rule repeatInterval] != 1) + // { + // // We initialize the proper ivars + // repeatType = @"1"; + // repeat1 = @"1"; + // repeat2 = @"1,3,5"; + // return; + // } + + if ([rule frequency] == iCalRecurrenceFrequenceDaily) + { + repeatType = @"0"; + + if ([rule byDayMask] == (iCalWeekDayMonday + | iCalWeekDayTuesday + | iCalWeekDayWednesday + | iCalWeekDayThursday + | iCalWeekDayFriday)) + { + if ([rule isInfinite]) + { + repeat = @"EVERY WEEKDAY"; + } + repeat1 = @"1"; + } + else + { + repeat1 = @"0"; + + if ([rule repeatInterval] == 1) + { + repeat = @"DAILY"; + } + + [self setRepeat2: [NSString stringWithFormat: @"%d", [rule repeatInterval]]]; + } + } + else if ([rule frequency] == iCalRecurrenceFrequenceWeekly) + { + repeatType = @"1"; + + if (![rule byDayMask]) + { + if ([rule repeatInterval] == 1) + repeat = @"WEEKLY"; + else if ([rule repeatInterval] == 2) + repeat = @"BI-WEEKLY"; + } + else + { + [self setRepeat1: [NSString stringWithFormat: @"%d", [rule repeatInterval]]]; + [self setRepeat2: [self _dayMaskToInteger: [rule byDayMask]]]; + } + } + else if ([rule frequency] == iCalRecurrenceFrequenceMonthly) + { + repeatType = @"2"; + + if ([rule byDayMask]) + { + // TODO + [self setRepeat2: @"0"]; + } + else if ([[rule byMonthDay] count]) + { + [self setRepeat2: @"1"]; + [self setRepeat5: [[rule byMonthDay] componentsJoinedByString: @","]]; + } + else if ([rule repeatInterval] == 1) + repeat = @"MONTHLY"; + + [self setRepeat1: [NSString stringWithFormat: @"%d", [rule repeatInterval]]]; + } + else + { + repeatType = @"3"; + + if ([rule namedValue: @"bymonth"]) + { + if (![rule byDayMask]) + { + [self setRepeat2: @"0"]; + [self setRepeat3: [rule namedValue: @"bymonthday"]]; + [self setRepeat4: [NSString stringWithFormat: @"%d", [[rule namedValue: @"bymonth"] intValue]-1]]; + } + else + { + // TODO + [self setRepeat2: @"1"]; + } + } + else if ([rule repeatInterval] == 1) + repeat = @"YEARLY"; + + [self setRepeat1: [NSString stringWithFormat: @"%d", [rule repeatInterval]]]; + } + + // We decode the proper end date, recurrences count, etc. + if ([rule repeatCount]) + { + [self setRange1: @"1"]; + [self setRange2: [rule namedValue: @"count"]]; + } + else if ([rule untilDate]) + { + [self setRange1: @"2"]; + [self setRange2: [[rule untilDate] descriptionWithCalendarFormat: @"%Y-%m-%d"]]; + } + else + { + [self setRange1: @"0"]; + } + } + else + DESTROY(repeat); +} + /* warning: we use this method which will be triggered by the template system when the page is instantiated, but we should find another and cleaner way of doing this... for example, when the clientObject is set */ @@ -188,6 +376,7 @@ ASSIGN (organizer, [component organizer]); [self _loadCategories]; [self _loadAttendees]; + [self _loadRRules]; } } // /* cycles */ @@ -454,6 +643,109 @@ [NSString stringWithFormat: @"category_%@", item]]; } +- (NSArray *) repeatList +{ + static NSArray *repeatItems = nil; + + if (!repeatItems) + { + repeatItems = [NSArray arrayWithObjects: @"DAILY", + @"WEEKLY", + @"BI-WEEKLY", + @"EVERY WEEKDAY", + @"MONTHLY", + @"YEARLY", + @"-", + @"CUSTOM", + nil]; + [repeatItems retain]; + } + + return repeatItems; +} + +- (NSString *) itemRepeatText +{ + NSString *text; + + if ([item isEqualToString: @"-"]) + text = item; + else + text = [self labelForKey: [NSString stringWithFormat: @"repeat_%@", item]]; + + return text; +} + +- (NSArray *) reminderList +{ + static NSArray *reminderItems = nil; + + if (!reminderItems) + { + reminderItems = [NSArray arrayWithObjects: @"5_MINUTES_BEFORE", + @"10_MINUTES_BEFORE", + @"15_MINUTES_BEFORE", + @"30_MINUTES_BEFORE", + @"45_MINUTES_BEFORE", + @"-", + @"1_HOUR_BEFORE", + @"2_HOURS_BEFORE", + @"5_HOURS_BEFORE", + @"15_HOURS_BEFORE", + @"-", + @"1_DAY_BEFORE", + @"2_DAYS_BEFORE", + @"1_WEEK_BEFORE", + @"-", + @"CUSTOM", + nil]; + [reminderItems retain]; + } + + return reminderItems; +} + +// - (void) setReminder: (NSString *) reminder +// { +// ASSIGN(reminder, _reminder); +// } + +// - (NSString *) reminder +// { +// return reminder; +// } + +- (NSString *) reminder +{ + return @""; +} + +- (void) setReminder: (NSString *) newReminder +{ +} + +- (NSString *) itemReminderText +{ + NSString *text; + + if ([item isEqualToString: @"-"]) + text = item; + else + text = [self labelForKey: [NSString stringWithFormat: @"reminder_%@", item]]; + + return text; +} + +- (NSString *) repeat +{ + return repeat; +} + +- (void) setRepeat: (NSString *) newRepeat +{ + ASSIGN(repeat, newRepeat); +} + - (NSString *) _permissionForEditing { NSString *perm; @@ -612,6 +904,29 @@ return status; } +- (void) setRepeatType: (NSString *) theValue +{ + ASSIGN (repeatType, theValue); +} + +- (NSString *) repeatType +{ + return repeatType; +} + +REPEAT(1); +REPEAT(2); +REPEAT(3); +REPEAT(4); +REPEAT(5); +REPEAT(6); +REPEAT(7); +RANGE(1); +RANGE(2); + +////////////////////////////////// JUNK //////////////////////////////////////// +////////////////////////////////// JUNK //////////////////////////////////////// +////////////////////////////////// JUNK //////////////////////////////////////// - (NSArray *) cycles { NSBundle *bundle; @@ -779,6 +1094,10 @@ { [self setCycleEnd: @"cycle_end_never"]; } +////////////////////////////////// JUNK //////////////////////////////////////// +////////////////////////////////// JUNK //////////////////////////////////////// +////////////////////////////////// JUNK //////////////////////////////////////// + /* helpers */ - (NSString *) completeURIForMethod: (NSString *) _method @@ -985,11 +1304,171 @@ } } +- (void) _handleCustomRRule: (iCalRecurrenceRule *) theRule + +{ + int type, range; + + // We decode the range + range = [[self range1] intValue]; + + // Create X appointments + if (range == 1) + { + [theRule setRepeatCount: [[self range2] intValue]]; + } + // Repeat until date + else if (range == 2) + { + } + // No end date. + else + { + } + + + // We decode the type and the rest accordingly. + type = [[self repeatType] intValue]; + + switch (type) + { + // DAILY: + // + // repeat1 holds the value of the radio button: + // 0 -> Every X days + // 1 -> Every weekday + // + // repeat2 holds the value of X when repeat1 equals 0 + // + case 0: + { + [theRule setFrequency: iCalRecurrenceFrequenceDaily]; + + if ([[self repeat1] intValue] == 0) + { + [theRule setInterval: [self repeat2]]; + } + else + { + [theRule setByDayMask: (iCalWeekDayMonday + |iCalWeekDayTuesday + |iCalWeekDayWednesday + |iCalWeekDayThursday + |iCalWeekDayFriday)]; + } + } + break; + + // WEEKLY + // + // repeat1 holds the value of "Every X week(s)" + // + // repeat2 holds which days are part of the recurrence rule + // 1 -> Monday + // 2 -> Tuesday .. and so on. + // The list is separated by commas, like: 1,3,4 + case 1: + { + NSArray *v; + int c, mask; + + [theRule setFrequency: iCalRecurrenceFrequenceWeekly]; + [theRule setInterval: [self repeat1]]; + + v = [[self repeat2] componentsSeparatedByString: @","]; + c = [v count]; + mask = 0; + + while (c--) + { + mask |= (unsigned int)exp2([[v objectAtIndex: c] intValue]-1); + } + + [theRule setByDayMask: mask]; + } + break; + + // MONTHLY + // + // repeat1 holds the value of "Every X month(s)" + // + // repeat2 holds the value of the radio-button "The" / "Recur on day(s)" + // 0 -> The + // 1 -> Recur on day(s) + // + // repeat3 holds the value of the first popup + // 0 -> First + // 1 -> Second ... and so on. + // + // repeat4 holds the value of the second popop + // 0 -> Sunday + // 1 -> Monday ... and so on. + // 7 -> Day of the month + // + // repeat5 holds the selected days when "Recur on day(s)" + // is chosen. The value starts at 1. + // + case 2: + { + [theRule setFrequency: iCalRecurrenceFrequenceMonthly]; + [theRule setInterval: [self repeat1]]; + + // We recur on specific days... + if ([[self repeat2] intValue] == 1) + { + [theRule setNamedValue: @"bymonthday" to: [self repeat5]]; + } + else + { + // TODO + } + } + break; + + // YEARLY + // + // repeat1 holds the value of "Every X year(s)" + // + // repeat2 holds the value of the radio-button "Every" / "Every .. of .." + // 0 -> Every + // 1 -> Every .. of .. + // + // repeat3 holds the value of the DAY parameter + // repeat4 holds the value of the MONTH parameter (0 -> January, 1 -> February ... ) + // ex: 3 February + // + // repeat5 holds the value of the OCCURENCE parameter (0 -> First, 1 -> Second ..) + // repeat6 holds the value of the DAY parameter (0 -> Sunday, 1 -> Monday, etc..) + // repeat7 holds the value of the MONTH parameter (0 -> January, 1 -> February ... ) + // + case 3: + default: + { + [theRule setFrequency: iCalRecurrenceFrequenceYearly]; + [theRule setInterval: [self repeat1]]; + + // We recur Every .. of .. + if ([[self repeat2] intValue] == 1) + { + // TODO + } + else + { + [theRule setNamedValue: @"bymonthday" to: [self repeat3]]; + [theRule setNamedValue: @"bymonth" + to: [NSString stringWithFormat: @"%d", ([[self repeat4] intValue]+1)]]; + } + } + break; + } +} + - (void) takeValuesFromRequest: (WORequest *) _rq inContext: (WOContext *) _ctx { - NSCalendarDate *now; SOGoCalendarComponent *clientObject; + iCalRecurrenceRule *rule; + NSCalendarDate *now; [super takeValuesFromRequest: _rq inContext: _ctx]; @@ -1011,6 +1490,53 @@ } [component setPriority: priority]; [component setLastModified: now]; + + // We remove any repeat rules + if (!repeat && [component hasRecurrenceRules]) + [component removeAllRecurrenceRules]; + else if ([repeat caseInsensitiveCompare: @"-"] != NSOrderedSame) + { + rule = [iCalRecurrenceRule new]; + + [rule setInterval: @"1"]; + + if ([repeat caseInsensitiveCompare: @"BI-WEEKLY"] == NSOrderedSame) + { + [rule setFrequency: iCalRecurrenceFrequenceWeekly]; + [rule setInterval: @"2"]; + } + else if ([repeat caseInsensitiveCompare: @"EVERY WEEKDAY"] == NSOrderedSame) + { + [rule setByDayMask: (iCalWeekDayMonday + |iCalWeekDayTuesday + |iCalWeekDayWednesday + |iCalWeekDayThursday + |iCalWeekDayFriday)]; + [rule setFrequency: iCalRecurrenceFrequenceDaily]; + } + else if ([repeat caseInsensitiveCompare: @"MONTHLY"] == NSOrderedSame) + { + [rule setNamedValue: @"bymonthday" + to: [NSString stringWithFormat: @"%d", [[component startDate] dayOfMonth]]]; + [rule setFrequency: iCalRecurrenceFrequenceMonthly]; + } + else if ([repeat caseInsensitiveCompare: @"DAILY"] == NSOrderedSame || + [repeat caseInsensitiveCompare: @"WEEKLY"] == NSOrderedSame || + [repeat caseInsensitiveCompare: @"YEARLY"] == NSOrderedSame) + { + [rule setFrequency: + (iCalRecurrenceFrequency) [rule valueForFrequency: repeat]]; + } + else + { + // We have a CUSTOM recurrence. Let's decode what kind of custome recurrence + // we have and set that. + [self _handleCustomRRule: rule]; + } + + [component setRecurrenceRules: [NSArray arrayWithObject: rule]]; + [rule release]; + } } #warning the following methods probably share some code... diff --git a/UI/Scheduler/UIxRecurrenceEditor.h b/UI/Scheduler/UIxRecurrenceEditor.h new file mode 100644 index 000000000..281ee0e22 --- /dev/null +++ b/UI/Scheduler/UIxRecurrenceEditor.h @@ -0,0 +1,54 @@ +/* UIxRecurrenceEditor.h - this file is part of SOGo + * + * Copyright (C) 2008 Inverse groupe conseil + * + * Author: Ludovic Marcotte + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef UIXRECURRENCEEDITOR_H +#define UIXRECURRENCEEDITOR_H + +#import + +@interface UIxRecurrenceEditor : UIxComponent +{ + NSString *item, *repeat; +} + +- (NSArray *) dailyRadioList; + +- (NSArray *) weeklyCheckBoxList; + +- (NSArray *) dayMonthList; +- (NSArray *) monthlyRepeatList; +- (NSArray *) monthlyDayList; +- (NSArray *) monthlyRadioList; + +- (NSArray *) yearlyMonthList; +- (NSArray *) yearlyDayList; + +- (NSArray *) rangeRadioList; +- (NSArray *) repeatList; +- (NSArray *) yearlyRadioList; + +- (void) setItem: (NSString *) theItem; +- (NSString *) item; + +@end + +#endif /* UIXRECURRENCEEDITOR_H */ diff --git a/UI/Scheduler/UIxRecurrenceEditor.m b/UI/Scheduler/UIxRecurrenceEditor.m new file mode 100644 index 000000000..edb9a661f --- /dev/null +++ b/UI/Scheduler/UIxRecurrenceEditor.m @@ -0,0 +1,244 @@ +/* UIxRecurrenceEditor.m - this file is part of SOGo + * + * Copyright (C) 2008 Inverse groupe conseil + * + * Author: Ludovic Marcotte + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#import +#import + +#import + +#import "UIxRecurrenceEditor.h" + +@implementation UIxRecurrenceEditor + +- (id) defaultAction +{ + [[self parent] setToolbar: @""]; + + return self; +} + +// +// Items used for the "Daily" recurrences. +// +- (NSArray *) dailyRadioList +{ + static NSArray *dailyItems = nil; + + if (!dailyItems) + { + dailyItems = [NSArray arrayWithObjects: @"Every", @"Every weekday", nil]; + [dailyItems retain]; + } + + return dailyItems; +} + + +// +// Items used for the "Weekly" recurrences. +// +- (NSArray *) weeklyCheckBoxList +{ + static NSArray *dayItems = nil; + + if (!dayItems) + { + dayItems = [NSArray arrayWithObjects: @"Mon", @"Tue", @"Wed", + @"Thu", @"Fri", @"Sat", @"Sun", nil]; + [dayItems retain]; + } + + return dayItems; +} + + +// +// Items used for the "Montly" recurrences". +// +- (NSArray *) dayMonthList +{ + static NSArray *dayMonthList = nil; + + if (!dayMonthList) + { + int i; + + dayMonthList = [[NSMutableArray alloc] init]; + + for (i = 1; i <= 31; i++) + { + [(NSMutableArray *)dayMonthList addObject: [NSString stringWithFormat: @"%d", i]]; + } + } + + return dayMonthList; +} + +- (NSArray *) monthlyRepeatList +{ + static NSArray *monthlyRepeatList = nil; + + if (!monthlyRepeatList) + { + monthlyRepeatList = [NSArray arrayWithObjects: @"FIRST", @"SECOND", @"THIRD", + @"FOURTH", @"FIFT", @"LAST", nil]; + [monthlyRepeatList retain]; + } + + return monthlyRepeatList; +} + +- (NSArray *) monthlyDayList +{ + static NSArray *monthlyDayList = nil; + + if (!monthlyDayList) + { + monthlyDayList = [NSArray arrayWithObjects: @"SUNDAY", @"MONDAY", @"TUESDAY", + @"WEDNESDAY", @"THURSDAY", @"FRIDAY", + @"SATURDAY", @"DAYOFTHEMONTH", nil]; + [monthlyDayList retain]; + } + + return monthlyDayList; +} + +- (NSArray *) monthlyRadioList +{ + static NSArray *monthlyRadioList = nil; + + if (!monthlyRadioList) + { + monthlyRadioList = [NSArray arrayWithObjects: @"The", @"Recur on day(s)", nil]; + [monthlyRadioList retain]; + } + + return monthlyRadioList; +} + + +// +// Items used for the "Yearly" recurrences". +// +- (NSArray *) yearlyRadioList +{ + static NSArray *yearlyRadioList = nil; + + if (!yearlyRadioList) + { + yearlyRadioList = [NSArray arrayWithObjects: @"Every", @"Every", nil]; + [yearlyRadioList retain]; + } + + return yearlyRadioList; +} + +- (NSArray *) yearlyMonthList +{ + static NSArray *yearlyMonthList = nil; + + if (!yearlyMonthList) + { + yearlyMonthList = [NSArray arrayWithObjects: @"JANUARY", @"FEBRUARY", @"MARCH", + @"APRIL", @"MAY", @"JUNE", @"JULY", @"AUGUST", + @"SEPTEMBER", @"OCTOBER", @"NOVEMBER", @"DECEMBER", nil]; + [yearlyMonthList retain]; + } + + return yearlyMonthList; +} + +- (NSArray *) yearlyDayList +{ + static NSArray *yearlyDayList = nil; + + if (!yearlyDayList) + { + yearlyDayList = [NSArray arrayWithObjects: @"SUNDAY", @"MONDAY", @"TUESDAY", + @"WEDNESDAY", @"THURSDAY", @"FRIDAY", + @"SATURDAY", nil]; + [yearlyDayList retain]; + } + + return yearlyDayList; +} + + +// +// Items used to specify the range. +// +- (NSArray *) rangeRadioList +{ + static NSArray *rangeRadioList = nil; + + if (!rangeRadioList) + { + rangeRadioList = [NSArray arrayWithObjects: @"No end date", @"Create", + @"Repeat until", nil]; + [rangeRadioList retain]; + } + + return rangeRadioList; +} + + +// +// Items used to specify what kind of recurrence we want +// +- (NSArray *) repeatList +{ + static NSArray *repeatList = nil; + + if (!repeatList) + { + repeatList = [NSArray arrayWithObjects: @"DAILY", @"WEEKLY", + @"MONTHLY", @"YEARLY", nil]; + [repeatList retain]; + } + + return repeatList; +} + + +// +// Accessors +// +- (void) setItem: (NSString *) theItem +{ + item = theItem; +} + +- (NSString *) item +{ + return item; +} + +- (NSString *) itemText +{ + NSString *text; + + text = [self labelForKey: [NSString stringWithFormat: @"repeat_%@", item]]; + + return text; +} + +@end diff --git a/UI/Scheduler/UIxTaskEditor.h b/UI/Scheduler/UIxTaskEditor.h index 871593c41..1b503d34f 100644 --- a/UI/Scheduler/UIxTaskEditor.h +++ b/UI/Scheduler/UIxTaskEditor.h @@ -52,9 +52,6 @@ - (void) setTaskDueDate: (NSCalendarDate *) _date; - (NSCalendarDate *) taskDueDate; -- (NSString *) repeat; -- (void) setRepeat: (NSString *) newRepeat; - @end #endif /* UIXAPPOINTMENTEDITOR_H */ diff --git a/UI/Scheduler/UIxTaskEditor.m b/UI/Scheduler/UIxTaskEditor.m index 295bbcc75..6b129716c 100644 --- a/UI/Scheduler/UIxTaskEditor.m +++ b/UI/Scheduler/UIxTaskEditor.m @@ -138,39 +138,6 @@ return !hasDueDate; } -- (NSArray *) repeatList -{ - static NSArray *repeatItems = nil; - - if (!repeatItems) - { - repeatItems = [NSArray arrayWithObjects: @"DAILY", - @"WEEKLY", - @"BI-WEEKLY", - @"EVERY WEEKDAY", - @"MONTHLY", - @"YEARLY", - @"-", - @"CUSTOM", - nil]; - [repeatItems retain]; - } - - return repeatItems; -} - -- (NSString *) itemRepeatText -{ - NSString *text; - - if ([item isEqualToString: @"-"]) - text = item; - else - text = [self labelForKey: [NSString stringWithFormat: @"repeat_%@", item]]; - - return text; -} - - (NSArray *) statusList { static NSArray *statusItems = nil; @@ -203,15 +170,6 @@ return item; } -- (NSString *) repeat -{ - return @""; -} - -- (void) setRepeat: (NSString *) newRepeat -{ -} - - (NSString *) status { return status; diff --git a/UI/Scheduler/product.plist b/UI/Scheduler/product.plist index 734735ff8..2485672cb 100644 --- a/UI/Scheduler/product.plist +++ b/UI/Scheduler/product.plist @@ -97,6 +97,10 @@ protectedBy = "View"; pageName = "UIxAttendeesEditor"; }; + editRecurrence = { + protectedBy = "View"; + pageName = "UIxRecurrenceEditor"; + }; }; }; diff --git a/UI/Templates/SchedulerUI/UIxAppointmentEditor.wox b/UI/Templates/SchedulerUI/UIxAppointmentEditor.wox index 4244e974e..342634679 100644 --- a/UI/Templates/SchedulerUI/UIxAppointmentEditor.wox +++ b/UI/Templates/SchedulerUI/UIxAppointmentEditor.wox @@ -40,18 +40,4 @@ const:dayStartHour="0" const:dayEndHour="23" /> -
- -
- diff --git a/UI/Templates/SchedulerUI/UIxComponentEditor.wox b/UI/Templates/SchedulerUI/UIxComponentEditor.wox index 044a1d0e9..c2fc0e844 100644 --- a/UI/Templates/SchedulerUI/UIxComponentEditor.wox +++ b/UI/Templates/SchedulerUI/UIxComponentEditor.wox @@ -72,6 +72,21 @@

+ +
+ +