Monotone-Parent: fe67bff0ab967ccf03cfe54c248865c9df889c21

Monotone-Revision: 7342d9cd31675160736e0f2db8a83047d9babea9

Monotone-Author: flachapelle@inverse.ca
Monotone-Date: 2007-10-09T17:19:20
Monotone-Branch: ca.inverse.sogo
maint-2.0.2
Francis Lachapelle 2007-10-09 17:19:20 +00:00
parent 084ffb7bc8
commit 03382298b8
10 changed files with 128 additions and 42 deletions

View File

@ -1,3 +1,14 @@
2007-10-05 Ludovic Marcotte <ludovic@inverse.ca>
* UI/WebServerResources/MailerUI.js
We check if at least one message is selected
before performing a Reply/Reply All/Forward
* SoObjects/Appointments/SOGoAppointmentFolder.m
and others - implemented support for recurring
events (with some known limitations right now,
all soon to be fixed).
2007-10-04 Francis Lachapelle <flachapelle@inverse.ca>
* Main/SOGo.m ([SOGo -isUserName:_keyinContext:_ctx]): removed

View File

@ -262,10 +262,9 @@ static void NGMonthDaySet_fillWithByDayX(NGMonthDaySet *daySet,
interval = [self->rrule repeatInterval];
until = [self lastInstanceStartDate]; // TODO: maybe replace
byMonthDay = [self->rrule byMonthDay];
/* check whether the range to be processed is beyond the 'until' date */
/* check whether the range to be processed is beyond the 'until' date */
if (until != nil) {
if ([until compare:rStart] == NSOrderedAscending) /* until before start */
return nil;
@ -314,7 +313,7 @@ static void NGMonthDaySet_fillWithByDayX(NGMonthDaySet *daySet,
continue;
/* first check whether we are in the interval */
if ((monthIdxInRecurrence % interval) != 0)
continue;

View File

@ -100,9 +100,10 @@ static Class yearlyCalcClass = Nil;
rule = [_rRules objectAtIndex:i];
if (![rule isKindOfClass:iCalRecurrenceRuleClass])
rule = [iCalRecurrenceRule recurrenceRuleWithICalRepresentation:rule];
calc = [self recurrenceCalculatorForRecurrenceRule:rule
withFirstInstanceCalendarDateRange:_fir];
rs = [calc recurrenceRangesWithinCalendarDateRange:_r];
[ranges addObjectsFromArray:rs];
}
@ -158,6 +159,7 @@ static Class yearlyCalcClass = Nil;
unsigned k;
exDate = [exDates objectAtIndex:i];
for (k = 0; k < rCount; k++) {
unsigned rIdx;

View File

@ -568,13 +568,16 @@ static NSNumber *sharedYes = nil;
md = [[_record mutableCopy] autorelease];
/* cycle is in _r */
/* cycle is in _r. We also have to override the c_startdate/c_enddate with the date values of
the reccurence since we use those when displaying events in SOGo Web */
tmp = [_r startDate];
[tmp setTimeZone: timeZone];
[md setObject:tmp forKey:@"startDate"];
[md setObject: [NSNumber numberWithInt: [tmp timeIntervalSince1970]] forKey: @"c_startdate"];
tmp = [_r endDate];
[tmp setTimeZone: timeZone];
[md setObject:tmp forKey:@"endDate"];
[md setObject: [NSNumber numberWithInt: [tmp timeIntervalSince1970]] forKey: @"c_enddate"];
return md;
}
@ -633,20 +636,24 @@ static NSNumber *sharedYes = nil;
rules = [cycleinfo objectForKey:@"rules"];
exRules = [cycleinfo objectForKey:@"exRules"];
exDates = [cycleinfo objectForKey:@"exDates"];
ranges = [iCalRecurrenceCalculator recurrenceRangesWithinCalendarDateRange:_r
firstInstanceCalendarDateRange:fir
recurrenceRules:rules
exceptionRules:exRules
exceptionDates:exDates];
count = [ranges count];
for (i = 0; i < count; i++) {
NGCalendarDateRange *rRange;
id fixedRow;
rRange = [ranges objectAtIndex:i];
fixedRow = [self fixupCycleRecord:row cycleRange:rRange];
if (fixedRow != nil) [_ma addObject:fixedRow];
if (fixedRow != nil)
{
[_ma addObject:fixedRow];
}
}
}
@ -845,21 +852,20 @@ static NSNumber *sharedYes = nil;
ma = [NSMutableArray arrayWithArray: records];
}
/* fetch recurrent apts now */
sql = [NSString stringWithFormat: @"(c_iscycle = 1)%@%@%@",
dateSqlString, componentSqlString, privacySqlString];
/* fetch recurrent apts now. we do NOT consider the date range when doing that
as the c_startdate/c_enddate of a recurring event is always set to the first
recurrence - others are generated on the fly */
sql = [NSString stringWithFormat: @"(c_iscycle = 1)%@%@", componentSqlString, privacySqlString];
qualifier = [EOQualifier qualifierWithQualifierFormat: sql];
[fields addObject: @"c_cycleinfo"];
records = [_folder fetchFields: fields matchingQualifier: qualifier];
if (records)
{
if (logger)
[self debugWithFormat: @"fetched %i cyclic records: %@",
[records count], records];
if (r)
if (r) {
records = [self fixupCyclicRecords: records fetchRange: r];
}
if (!ma)
ma = [NSMutableArray arrayWithCapacity: [records count]];

View File

@ -153,5 +153,6 @@
"quotasFormat" = "Quotas: %{0} used on %{1} Kb; %{2}%";
"Please select a message." = "Please select a message.";
"Please select a message to print." = "Please select a message to print.";
"Please select only one message to print." = "Please select only one message to print.";

View File

@ -203,5 +203,6 @@
"quotasFormat" = "Quotas: %{0} Ko utilisés sur %{1}; %{2}%";
"Please select a message." = "Veuillez sélectionner un message.";
"Please select a message to print." = "Veuillez sélectionner un message à imprimer.";
"Please select only one message to print." = "Veuillez ne sélectionner qu'un seul message à imprimer.";

View File

@ -186,5 +186,6 @@
"quotasFormat" = "Quota: %{0} von %{1} KB verwendet; %{2}%";
"Please select a message." = "Sie müssen eine Nachricht auswählen.";
"Please select a message to print." = "Sie müssen eine Nachricht zum Drucken auswählen.";
"Please select only one message to print." = "Bitte wählen Sie nur eine Nachricht zum Drucken aus.";

View File

@ -35,6 +35,7 @@
NSCalendarDate *aptStartDate;
NSCalendarDate *aptEndDate;
NSString *item;
NSString *repeat;
}
/* template values */

View File

@ -20,6 +20,8 @@
* Boston, MA 02111-1307, USA.
*/
#warning WE LEAK IVARS LIKE CRAZY HERE
#include <math.h>
#import <NGObjWeb/SoObject.h>
@ -29,6 +31,7 @@
#import <NGCards/iCalEvent.h>
#import <NGCards/iCalPerson.h>
#import <NGCards/iCalRecurrenceRule.h>
#import <SoObjects/SOGo/SOGoUser.h>
#import <SoObjects/SOGo/SOGoContentObject.h>
@ -48,12 +51,19 @@
aptEndDate = nil;
item = nil;
event = nil;
repeat = nil;
isAllDay = NO;
}
return self;
}
- (void) dealloc
{
RELEASE(repeat);
[super dealloc];
}
/* template values */
- (iCalEvent *) event
{
@ -132,6 +142,8 @@
else
text = [self labelForKey: [NSString stringWithFormat: @"repeat_%@", item]];
NSLog(@"itemRepeatText: %@", text);
return text;
}
@ -198,11 +210,12 @@
- (NSString *) repeat
{
return @"";
return repeat;
}
- (void) setRepeat: (NSString *) newRepeat
{
ASSIGN(repeat, newRepeat);
}
- (NSString *) reminder
@ -276,8 +289,32 @@
ASSIGN (aptStartDate, startDate);
ASSIGN (aptEndDate, endDate);
// We initialize our repeat ivars
if ([event hasRecurrenceRules])
{
iCalRecurrenceRule *rule;
repeat = @"CUSTOM";
/* here comes the code for initializing repeat, reminder and isAllDay... */
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;
}
@ -310,7 +347,11 @@
NSString *iCalString;
clientObject = [self clientObject];
NSLog(@"saveAction, clientObject = %@", clientObject);
iCalString = [[clientObject calendar: NO] versitString];
NSLog(@"saveAction, iCalString = %@", iCalString);
[clientObject saveContentString: iCalString];
return [self jsCloseWithRefreshMethod: @"refreshEventsAndDisplay()"];
@ -352,6 +393,37 @@
}
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))
{
iCalRecurrenceRule *rule;
rule = [[iCalRecurrenceRule alloc] init];
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];
[rule setInterval: @"1"];
}
else
{
[rule setFrequency: (iCalRecurrenceFrequency)[rule valueForFrequency: repeat]];
[rule setInterval: @"1"];
}
[event setRecurrenceRules: [NSArray arrayWithObject: rule]];
RELEASE(rule);
}
}
// TODO: add tentatively

View File

@ -221,50 +221,42 @@
{
NSEnumerator *folders, *currentInfos;
SOGoAppointmentFolder *currentFolder;
NSMutableDictionary *infos, *currentInfo, *newInfo;
NSString *owner, *uid;
NSMutableDictionary *newInfo;
NSMutableArray *infos;
NSNull *marker;
SOGoAppointmentFolders *clientObject;
marker = [NSNull null];
infos = [NSMutableDictionary dictionary];
clientObject = [self clientObject];
clientObject = [self clientObject];
folders = [[clientObject subFolders] objectEnumerator];
currentFolder = [folders nextObject];
infos = [NSMutableArray array];
while (currentFolder)
{
if ([currentFolder isActive])
{
owner = [currentFolder ownerInContext: context];
currentInfos = [[currentFolder fetchCoreInfosFrom: startDate
to: endDate
component: component] objectEnumerator];
newInfo = [currentInfos nextObject];
while (newInfo)
while ((newInfo = [currentInfos nextObject]))
{
uid = [newInfo objectForKey: @"c_uid"];
currentInfo = [infos objectForKey: uid];
if (!currentInfo
|| [owner isEqualToString: userLogin])
{
[self _updatePrivacyInComponent: newInfo
fromFolder: currentFolder];
[newInfo setObject: [currentFolder nameInContainer]
forKey: @"c_folder"];
// [newInfo setObject: owner forKey: @"c_owner"];
[infos setObject: [newInfo objectsForKeys: fields
notFoundMarker: marker]
forKey: uid];
}
newInfo = [currentInfos nextObject];
[self _updatePrivacyInComponent: newInfo
fromFolder: currentFolder];
[newInfo setObject: [currentFolder nameInContainer]
forKey: @"c_folder"];
[infos addObject: [newInfo objectsForKeys: fields
notFoundMarker: marker]];
}
}
currentFolder = [folders nextObject];
}
return [infos allValues];
return infos;
}
- (WOResponse *) _responseWithData: (NSArray *) data