]> err.no Git - scalable-opengroupware.org/commitdiff
git-svn-id: http://svn.opengroupware.org/SOGo/trunk@137 d1b88da0-ebda-0310-925b-ed51d...
authorhelge <helge@d1b88da0-ebda-0310-925b-ed51d893ca5b>
Fri, 2 Jul 2004 17:42:14 +0000 (17:42 +0000)
committerhelge <helge@d1b88da0-ebda-0310-925b-ed51d893ca5b>
Fri, 2 Jul 2004 17:42:14 +0000 (17:42 +0000)
19 files changed:
SOGo/SoObjects/Appointments/ChangeLog
SOGo/SoObjects/Appointments/SOGoAppointmentFolder.h
SOGo/SoObjects/Appointments/SOGoAppointmentFolder.m
SOGo/SoObjects/SOGo/ChangeLog
SOGo/SoObjects/SOGo/SOGoFolder.h
SOGo/SoObjects/SOGo/SOGoFolder.m
SOGo/SoObjects/SOGo/SOGoObject.h
SOGo/SoObjects/SOGo/SOGoObject.m
SOGo/UI/SOGoUI/ChangeLog
SOGo/UI/SOGoUI/UIxComponent.h
SOGo/UI/SOGoUI/UIxComponent.m
SOGo/UI/Scheduler/ChangeLog
SOGo/UI/Scheduler/GNUmakefile
SOGo/UI/Scheduler/UIxAppointmentEditor.m
SOGo/UI/Scheduler/UIxAppointmentEditor.wox
SOGo/UI/Scheduler/UIxAppointmentView.h
SOGo/UI/Scheduler/UIxAppointmentView.m
SOGo/UI/Scheduler/UIxCalView.m
SOGo/UI/Scheduler/UIxCalWeekOverview.wox

index b3888f9069faa6563a548d5e6d87cd61dcf3b915..cc4a7037a26288e112eaff4d3bcc873819a7f2b9 100644 (file)
@@ -1,3 +1,8 @@
+2004-07-02  Helge Hess  <helge.hess@opengroupware.org>
+
+       * SOGoAppointmentFolder.m: added method to fetch core info from other
+         OCS folders, correct timezone to MET after fetch core info
+
 2004-07-01  Helge Hess  <helge.hess@opengroupware.org>
        
        * redirect to weekoverview if GET is run on the folder itself
index f143020f5f19e7bc0b958fa00d895bec41bef5a0..243b2fcf86d0e5551f5f5c683103ab53e1170250 100644 (file)
@@ -25,7 +25,8 @@
 
 #include <SOGo/SOGoFolder.h>
 
-@class NSString, NSArray, NSCalendarDate;
+@class NSString, NSArray, NSCalendarDate, NSException;
+@class OCSFolder;
 
 @interface SOGoAppointmentFolder : SOGoFolder
 {
 - (NSArray *)fetchCoreInfosFrom:(NSCalendarDate *)_startDate
   to:(NSCalendarDate *)_endDate;
 
+- (NSArray *)fetchCoreInfosFromFolder:(OCSFolder *)_folder
+  from:(NSCalendarDate *)_startDate
+  to:(NSCalendarDate *)_endDate;
+
 @end
 
 #endif /* __Appointments_SOGoAppointmentFolder_H__ */
index 6019eee564897f1d2a2f174259f546a7c437d477..152869189ea2f5c177449494e94a6802c6038f27 100644 (file)
 
 @implementation SOGoAppointmentFolder
 
-static BOOL debugOn = NO;
+static BOOL       debugOn = NO;
+static NSTimeZone *MET = nil;
+
++ (void)initialize {
+  if (MET == nil) MET = [[NSTimeZone timeZoneWithAbbreviation:@"MET"] retain];
+}
 
 + (NSString *)globallyUniqueObjectId {
-/*
-4C08AE1A-A808-11D8-AC5A-000393BBAFF6
- SOGo-Web-28273-18283-288182
-printf( "%x", *(int *) &f);
- */
-    static int pid = 0;
-    static int sequence = 0;
-    static float rndm = 0;
-    float f;
-
-    if(pid == 0) {
+  /*
+    4C08AE1A-A808-11D8-AC5A-000393BBAFF6
   SOGo-Web-28273-18283-288182
+    printf( "%x", *(int *) &f);
 */
+  static int   pid = 0;
+  static int   sequence = 0;
+  static float rndm = 0;
+  float f;
+
+  if (pid == 0) { /* break if we fork ;-) */
       pid = getpid();
       rndm = random();
-    }
-    sequence++;
-    f = [[NSDate date] timeIntervalSince1970];
-    return [NSString stringWithFormat:@"%0X-%0X-%0X-%0X",
-        pid,
-        *(int *)&f,
-        sequence++,
-        random];
+  }
+  sequence++;
+  f = [[NSDate date] timeIntervalSince1970];
+  return [NSString stringWithFormat:@"%0X-%0X-%0X-%0X",
+                  pid, *(int *)&f, sequence++, random];
 }
 
 - (void)dealloc {
@@ -97,6 +99,13 @@ printf( "%x", *(int *) &f);
   return [NSException exceptionWithHTTPStatus:404 /* Not Found */];
 }
 
+/* timezone */
+
+- (NSTimeZone *)viewTimeZone {
+  // TODO: should use a cookie for configuration? we default to MET
+  return MET;
+}
+
 /* fetching */
 
 - (NSMutableDictionary *)fixupRecord:(NSDictionary *)_record {
@@ -108,6 +117,7 @@ printf( "%x", *(int *) &f);
   if ((tmp = [_record objectForKey:@"startdate"])) {
     tmp = [[NSCalendarDate alloc] initWithTimeIntervalSince1970:
                                    (NSTimeInterval)[tmp unsignedIntValue]];
+    [tmp setTimeZone:[self viewTimeZone]];
     if (tmp) [md setObject:tmp forKey:@"startDate"];
     [tmp release];
   }
@@ -117,6 +127,7 @@ printf( "%x", *(int *) &f);
   if ((tmp = [_record objectForKey:@"enddate"])) {
     tmp = [[NSCalendarDate alloc] initWithTimeIntervalSince1970:
                                    (NSTimeInterval)[tmp unsignedIntValue]];
+    [tmp setTimeZone:[self viewTimeZone]];
     if (tmp) [md setObject:tmp forKey:@"endDate"];
     [tmp release];
   }
@@ -144,21 +155,22 @@ printf( "%x", *(int *) &f);
   return ma;
 }
 
-- (NSArray *)fetchCoreInfosFrom:(NSCalendarDate *)_startDate
+- (NSArray *)fetchCoreInfosFromFolder:(OCSFolder *)_folder
+  from:(NSCalendarDate *)_startDate
   to:(NSCalendarDate *)_endDate 
 {
-  OCSFolder   *folder;
   EOQualifier *qualifier;
   NSArray     *fields, *records;
   NSString    *sql;
   
-  if ((folder = [self ocsFolder]) == nil) {
+  if (_folder == nil) {
     [self logWithFormat:@"ERROR(%s): missing folder for fetch!",
            __PRETTY_FUNCTION__];
     return nil;
   }
   
-  [self logWithFormat:@"should fetch (%@ => %@) ...", _startDate, _endDate];
+  if (debugOn)
+    [self debugWithFormat:@"should fetch (%@=>%@) ...", _startDate, _endDate];
   
   sql = [NSString stringWithFormat:@"(startdate < %d) AND (enddate > %d)",
                  (unsigned int)[_endDate   timeIntervalSince1970],
@@ -169,7 +181,7 @@ printf( "%x", *(int *) &f);
                      @"uid", @"startdate", @"enddate",
                      @"title", @"participants", nil];
   
-  records = [folder fetchFields:fields matchingQualifier:qualifier];
+  records = [_folder fetchFields:fields matchingQualifier:qualifier];
   if (records == nil) {
     [self logWithFormat:@"ERROR(%s): fetch failed!", __PRETTY_FUNCTION__];
     return nil;
@@ -181,6 +193,19 @@ printf( "%x", *(int *) &f);
   return records;
 }
 
+- (NSArray *)fetchCoreInfosFrom:(NSCalendarDate *)_startDate
+  to:(NSCalendarDate *)_endDate 
+{
+  OCSFolder *folder;
+  
+  if ((folder = [self ocsFolder]) == nil) {
+    [self logWithFormat:@"ERROR(%s): missing folder for fetch!",
+           __PRETTY_FUNCTION__];
+    return nil;
+  }
+  return [self fetchCoreInfosFromFolder:folder from:_startDate to:_endDate];
+}
+
 /* GET */
 
 - (id)GETAction:(WOContext *)_ctx {
index 3fc026fdea1c1ec2cc3311819bd53dd94c51ea89..5bf70eebc2e0479af5c3cac7682f315ffbd43004 100644 (file)
@@ -1,3 +1,7 @@
+2004-07-02  Helge Hess  <helge.hess@opengroupware.org>
+
+       * SOGoObject.m: added -delete method (but not yet implemented)
+
 2004-06-30  Helge Hess  <helge.hess@opengroupware.org>
 
        * SOGoContentObject.m: added -contentAsString method
index 2250a3721900117c393d6a683a931d85af18bb7c..df3a330194e11338b671b3ce675d0bf1a96c7eb3 100644 (file)
@@ -38,6 +38,7 @@
 - (void)setOCSPath:(NSString *)_Path;
 - (NSString *)ocsPath;
 
+- (OCSFolder *)ocsFolderForPath:(NSString *)_path;
 - (OCSFolder *)ocsFolder;
 
 @end
index c40c45e84ddc6d47af12b58fd4aee0fe9e5c44c2..c3fff2fa377f140094fe1b9744c67118040f2e23 100644 (file)
 - (OCSFolderManager *)folderManager {
   return [OCSFolderManager defaultFolderManager];
 }
+- (OCSFolder *)ocsFolderForPath:(NSString *)_path {
+  return [[self folderManager] folderAtPath:_path];
+}
 - (OCSFolder *)ocsFolder {
   if (self->ocsFolder != nil)
     return [self->ocsFolder isNotNull] ? self->ocsFolder : nil;
   
-  self->ocsFolder = 
-    [[[self folderManager] folderAtPath:[self ocsPath]] retain];
+  self->ocsFolder = [[self ocsFolderForPath:[self ocsPath]] retain];
   return self->ocsFolder;
 }
 
index fb90b6eb4300aebd872b025ec01d4316fd5b4c65..22e2855673c416e78889060ab57f58a43af81ddf 100644 (file)
@@ -25,7 +25,7 @@
 
 #import <Foundation/NSObject.h>
 
-@class NSString, NSMutableString;
+@class NSString, NSMutableString, NSException;
 @class OCSFolderManager, OCSFolder;
 @class SOGoUserFolder;
 
 
 - (SOGoUserFolder *)lookupUserFolder;
 
+/* operations */
+
+- (NSException *)delete;
+
 /* description */
 
 - (void)appendAttributesToDescription:(NSMutableString *)_ms;
index ad29501b0db42a02f96dff648194bc4bac000ac0..b558aba0114e812b015dc23f9b36f857a10f8b3b 100644 (file)
   return [self->container lookupUserFolder];
 }
 
+/* operations */
+
+- (NSException *)delete {
+  return [NSException exceptionWithHTTPStatus:500 /* not implemented */
+                     reason:@"delete not yet implemented, sorry ..."];
+}
+
 /* KVC hacks */
 
 - (id)valueForUndefinedKey:(NSString *)_key {
   return [self nameInContainer];
 }
 
+- (id)DELETEAction:(id)_ctx {
+  return [self delete];
+}
+
 /* description */
 
 - (void)appendAttributesToDescription:(NSMutableString *)_ms {
index 50aaf5911f18a01a9dd39665fe40f9c7434b32aa..c81828cf499250699748bd6bf5e5018bbb65e9d1 100644 (file)
@@ -1,3 +1,8 @@
+2004-07-02  Helge Hess  <helge.hess@opengroupware.org>
+
+       * UIxComponent.m: introduced 'viewTimeZone' method and adds some
+         timezone correction to date methods
+
 2004-06-30  Helge Hess  <helge.hess@opengroupware.org>
 
        * product.plist: make categories on SOGoObject instead of SxFolder
index d9a0c6ffc51641f4198fc89b699c3c351b55c240..8e99aba961153dbd80c9783997ec95e4572cb9dd 100644 (file)
 
 #include <NGObjWeb/SoComponent.h>
 
-@class NSCalendarDate;
+@class NSCalendarDate, NSTimeZone, NSMutableDictionary;
 
 
 @interface UIxComponent : SoComponent
 {
-    NSMutableDictionary *queryParameters;
+  NSMutableDictionary *queryParameters;
 }
 
 - (NSString *)queryParameterForKey:(NSString *)_key;
@@ -46,6 +46,7 @@
 - (NSString *)ownMethodName;
 
 /* date selection */
+- (NSTimeZone *)viewTimeZone;
 - (NSCalendarDate *)selectedDate;
 - (NSString *)dateStringForDate:(NSCalendarDate *)_date;
 - (NSCalendarDate *)dateForDateString:(NSString *)_dateString;
index 280bcd719383d1febfcef3caad9fbc22d9c7d82e..c52f0b93a0521fcd0dd117cf03534dce89a2347e 100644 (file)
@@ -1,7 +1,7 @@
 /*
-  Copyright (C) 2000-2004 SKYRIX Software AG
+  Copyright (C) 2004 SKYRIX Software AG
 
-  This file is part of OGo
+  This file is part of OpenGroupware.org.
 
   OGo is free software; you can redistribute it and/or modify it under
   the terms of the GNU Lesser General Public License as published by the
 
 @implementation UIxComponent
 
+static NSTimeZone *MET = nil;
+
++ (void)initialize {
+  if (MET == nil) MET = [[NSTimeZone timeZoneWithAbbreviation:@"MET"] retain];
+}
+
 - (id)init {
-    if ((self = [super init])) {
-        self->queryParameters = [[NSMutableDictionary alloc] init];
-    }
-    return self;
+  if ((self = [super init])) {
+    self->queryParameters = [[NSMutableDictionary alloc] init];
+  }
+  return self;
 }
 
 - (void)dealloc {
-    [self->queryParameters release];
-    [super dealloc];
+  [self->queryParameters release];
+  [super dealloc];
 }
 
 
 - (void)awake {
-    WORequest *req;
-    NSString *uri;
-    NSRange r;
+  WORequest *req;
+  NSString  *uri;
+  NSRange   r;
 
-    [super awake];
+  [super awake];
 
-    req = [[self context] request];
-    uri = [req uri];
-    r = [uri rangeOfString:@"?"];
-    if(r.length > 0) {
-        NSString *qs;
-        
-        qs = [uri substringFromIndex:(r.location + r.length)];
-        [self->queryParameters removeAllObjects];
-        [self _parseQueryString:qs];
-    }    
+  req = [[self context] request];
+  uri = [req uri];
+  r   = [uri rangeOfString:@"?"];
+  if (r.length > 0) {
+    NSString *qs;
+    
+    qs = [uri substringFromIndex:(r.location + r.length)];
+    [self->queryParameters removeAllObjects];
+    [self _parseQueryString:qs];
+  }    
 }
 
 - (void)_parseQueryString:(NSString *)_s {
-    NSEnumerator *e;
-    NSString *part;
+  NSEnumerator *e;
+  NSString *part;
     
-    e = [[_s componentsSeparatedByString:@"&"] objectEnumerator];
-    while ((part = [e nextObject])) {
-        NSRange  r;
-        NSString *key, *value;
+  e = [[_s componentsSeparatedByString:@"&"] objectEnumerator];
+  while ((part = [e nextObject])) {
+    NSRange  r;
+    NSString *key, *value;
         
-        r = [part rangeOfString:@"="];
-        if (r.length == 0) {
-            /* missing value of query parameter */
-            key   = [part stringByUnescapingURL];
-            value = @"1";
-        }
-        else {
-            key   = [[part substringToIndex:r.location] stringByUnescapingURL];
-            value = [[part substringFromIndex:(r.location + r.length)] 
+    r = [part rangeOfString:@"="];
+    if (r.length == 0) {
+      /* missing value of query parameter */
+      key   = [part stringByUnescapingURL];
+      value = @"1";
+    }
+    else {
+      key   = [[part substringToIndex:r.location] stringByUnescapingURL];
+      value = [[part substringFromIndex:(r.location + r.length)] 
                 stringByUnescapingURL];
-        }
-        [self->queryParameters setObject:value forKey:key];
     }
+    [self->queryParameters setObject:value forKey:key];
+  }
 }
 
 - (NSString *)queryParameterForKey:(NSString *)_key {
-    return [self->queryParameters objectForKey:_key];
+  return [self->queryParameters objectForKey:_key];
 }
 
 - (void)setQueryParameter:(NSString *)_param forKey:(NSString *)_key {
-    if(_key == nil)
-        return;
+  if(_key == nil)
+    return;
 
-    if(_param != nil)
-        [self->queryParameters setObject:_param forKey:_key];
-    else
-        [self->queryParameters removeObjectForKey:_key];
+  if(_param != nil)
+    [self->queryParameters setObject:_param forKey:_key];
+  else
+    [self->queryParameters removeObjectForKey:_key];
 }
 
 - (NSDictionary *)queryParameters {
-    return self->queryParameters;
+  return self->queryParameters;
 }
 
 - (NSString *)completeHrefForMethod:(NSString *)_method {
-    NSDictionary *qp;
-    NSString *qs;
+  NSDictionary *qp;
+  NSString *qs;
     
-    qp = [self queryParameters];
-    if([qp count] == 0)
-        return _method;
+  qp = [self queryParameters];
+  if([qp count] == 0)
+    return _method;
     
-    qs = [[self context] queryStringFromDictionary:qp];
-    return [_method stringByAppendingFormat:@"?%@", qs];
+  qs = [[self context] queryStringFromDictionary:qp];
+  return [_method stringByAppendingFormat:@"?%@", qs];
 }
 
 - (NSString *)ownMethodName {
-    NSString *uri;
-    NSRange  r;
+  NSString *uri;
+  NSRange  r;
     
-    uri = [[[self context] request] uri];
+  uri = [[[self context] request] uri];
     
-    /* first: cut off query parameters */
+  /* first: cut off query parameters */
     
-    r = [uri rangeOfString:@"?" options:NSBackwardsSearch];
-    if (r.length > 0)
-        uri = [uri substringToIndex:r.location];
+  r = [uri rangeOfString:@"?" options:NSBackwardsSearch];
+  if (r.length > 0)
+    uri = [uri substringToIndex:r.location];
     
-    /* next: strip trailing slash */
+  /* next: strip trailing slash */
     
-    if ([uri hasSuffix:@"/"]) uri = [uri substringToIndex:([uri length] - 1)];
-    r = [uri rangeOfString:@"/" options:NSBackwardsSearch];
+  if ([uri hasSuffix:@"/"]) uri = [uri substringToIndex:([uri length] - 1)];
+  r = [uri rangeOfString:@"/" options:NSBackwardsSearch];
     
-    /* then: cut of last path component */
+  /* then: cut of last path component */
     
-    if (r.length == 0) // no slash? are we at root?
-        return @"/";
+  if (r.length == 0) // no slash? are we at root?
+    return @"/";
     
-    return [uri substringFromIndex:(r.location + 1)];
+  return [uri substringFromIndex:(r.location + 1)];
 }
 
 /* date */
 
+- (NSTimeZone *)viewTimeZone {
+  // Note: also in the folder, should be based on a cookie?
+  return MET;
+}
+
 - (NSCalendarDate *)selectedDate {
-    NSString *s;
-    
-    s = [self queryParameterForKey:@"day"];
-    if(s) {
-        return [self dateForDateString:s];
-    }
-    return [NSCalendarDate date];
+  NSString       *s;
+  NSCalendarDate *cdate;
+  
+  s = [self queryParameterForKey:@"day"];
+  cdate = ([s length] > 0)
+    ? [self dateForDateString:s]
+    : [NSCalendarDate date];
+  [cdate setTimeZone:[self viewTimeZone]];
+  return cdate;
 }
 
 - (NSString *)dateStringForDate:(NSCalendarDate *)_date {
-    return [_date descriptionWithCalendarFormat:@"%Y%m%d"];
+  [_date setTimeZone:[self viewTimeZone]];
+  return [_date descriptionWithCalendarFormat:@"%Y%m%d"];
 }
 
 - (NSCalendarDate *)dateForDateString:(NSString *)_dateString {
-    return [NSCalendarDate dateWithString:_dateString calendarFormat:@"%Y%m%d"];
+  NSTimeZone *tz;
+  
+  tz = [self viewTimeZone];
+  /* Note: we should give a time, best is noon to avoid edge conditions */
+  _dateString = [_dateString stringByAppendingFormat:@"12:00:00 %@",
+                              [tz abbreviation]];
+  return [NSCalendarDate dateWithString:_dateString 
+                        calendarFormat:@"%Y%m%d %H:%M:%S %Z"];
 }
 
-@end
+@end /* UIxComponent */
index a29b19b73c592cac4c9ac2e452e68853e965e8ca..cc48c7ce3b474a7733d7459cd980db784e47592d 100644 (file)
@@ -1,3 +1,7 @@
+2004-07-02  Helge Hess  <helge.hess@opengroupware.org>
+
+       * UIxAppointmentView.m: fixup timezone of start/enddate
+
 2004-06-30  Helge Hess  <helge.hess@opengroupware.org>
 
        * UIxCalWeekOverview.wox, UIxCalMonthOverview.wox: some minor tweaks
index a354a777433397029ec0db2b2084d226a8ab0be3..09d45692108e9ec2a6e0ea99ff94f2e00b1792bd 100644 (file)
@@ -47,7 +47,7 @@ SchedulerUI_RESOURCE_FILES += \
        images/icon_apt_list_inactive.gif       \
 
 ADDITIONAL_INCLUDE_DIRS += \
-       -I..
+       -I.. -I../.. -I../../..
 
 
 # make
index 0a2bf3095bc52d9005604b2507af6f08283f213c..2e6ed61de0129c84c0c4e4d2ad6d9add452e680b 100644 (file)
 }
 
 - (BOOL)isNewAppointment {
-    return ! [[self clientObject] isAppointment];
+  /* that doesn't work! */
+  return ![[self clientObject] isAppointment];
 }
 
 - (NSString *)iCalString {
-    if([self isNewAppointment]) {
-        return [self iCalStringTemplate];
-    }
-    else {
-        return [[self clientObject] valueForKey:@"iCalString"];
-    }
+  // TODO: improve check for new appointment
+  NSString *ical;
+
+  ical = [[self clientObject] valueForKey:@"iCalString"];
+  if ([ical length] == 0) /* a new appointment */
+    ical = [self iCalStringTemplate];
+  
+  return ical;
 }
 
 - (NSString *)iCalStringTemplate {
-    static NSString *iCalStringTemplate = \
-    @"BEGIN:VCALENDAR\nMETHOD:REQUEST\nPRODID:OpenGroupware.org SOGo 0.9\n" \
-    @"VERSION:2.0\nBEGIN:VEVENT\nCLASS:PRIVATE\nSTATUS:CONFIRMED\n" \
-    @"DTSTART:%@\nDTEND:%@\n" \
-    @"TRANSP:OPAQUE\n" \
-    @"END:VEVENT\nEND:VCALENDAR";
-    NSCalendarDate *startDate, *endDate;
-    NSString *template;
-    
-    startDate = [self selectedDate];
-    endDate = [startDate dateByAddingYears:0 months:0 days:0
+  static NSString *iCalStringTemplate = \
+    @"BEGIN:VCALENDAR\nMETHOD:REQUEST\nPRODID:OpenGroupware.org SOGo 0.9\n"
+    @"VERSION:2.0\n"
+    @"BEGIN:VEVENT\n"
+    @"UID:%@\n"
+    @"CLASS:PRIVATE\n"
+    @"STATUS:CONFIRMED\n"
+    @"DTSTAMP:%@\n"
+    @"DTSTART:%@\n"
+    @"DTEND:%@\n"
+    @"TRANSP:OPAQUE\n"
+    @"SEQUENCE:1\n"
+    @"END:VEVENT\n"
+    @"END:VCALENDAR";
+  NSCalendarDate *startDate, *endDate;
+  NSString       *template;
+  
+  startDate = [self selectedDate];
+  endDate   = [startDate dateByAddingYears:0 months:0 days:0
                          hours:1 minutes:0 seconds:0];
-    
-    template = [NSString stringWithFormat:iCalStringTemplate,
-                          [startDate icalString],
-                          [endDate icalString]];
-    
-    return template;
+  
+  template = [NSString stringWithFormat:iCalStringTemplate,
+                        [[self clientObject] nameInContainer],
+                        [[NSCalendarDate date] icalString],
+                        [startDate icalString],
+                        [endDate   icalString]];
+  return template;
 }
 
 
 
 
 - (SOGoAppointment *)appointment {
-    if(self->appointment == nil) {
-        self->appointment = [[SOGoAppointment alloc]
-          initWithICalString:[self iCalString]];
-    }
-    return self->appointment;
+  if(self->appointment == nil) {
+    self->appointment = [[SOGoAppointment alloc]
+                         initWithICalString:[self iCalString]];
+  }
+  return self->appointment;
 }
 
 - (id)participants {
-    if(self->participants == nil) {
-        NSArray *attendees;
-        NSMutableArray *emailAddresses;
-        unsigned i, count;
-
-        attendees = [self->appointment attendees];
-        count = [attendees count];
-        emailAddresses = [[NSMutableArray alloc] initWithCapacity:count];
-        for(i = 0; i < count; i++) {
-            NSString *email;
-            
-            email = [[attendees objectAtIndex:i] rfc822Email];
-            if(email)
-                [emailAddresses addObject:email];
-        }
-        self->participants = [[emailAddresses componentsJoinedByString:@"\n"]
-            retain];
-        [emailAddresses release];
-    }
+  NSArray *attendees;
+  NSMutableArray *emailAddresses;
+  unsigned i, count;
+  
+  if (self->participants)
     return self->participants;
+
+  attendees      = [self->appointment attendees];
+  count          = [attendees count];
+  emailAddresses = [[NSMutableArray alloc] initWithCapacity:count];
+  for (i = 0; i < count; i++) {
+    NSString *email;
+            
+    email = [[attendees objectAtIndex:i] rfc822Email];
+    if (email)
+      [emailAddresses addObject:email];
+  }
+  
+  self->participants = 
+    [[emailAddresses componentsJoinedByString:@"\n"] copy];
+  [emailAddresses release];
+  return self->participants;
 }
 
 
 
 
 - (id)newAction {
+  /*
+    This method creates a unique ID and redirects to the "edit" method on the
+    new ID.
+    It is actually a folder method and should be defined on the folder.
+    
+    Note: 'clientObject' is the SOGoAppointmentFolder!
+  */
   WORequest *req;
   WOResponse *r;
   NSString *uri, *uriFormat, *objectId, *nextMethod;
   
-  /* 
-     clientObject *is* SOGoAppointmentFolder, so this should be an instance 
-     method? 
-  */
   objectId = [NSClassFromString(@"SOGoAppointmentFolder")
                               globallyUniqueObjectId];
   
   nextMethod = [NSString stringWithFormat:@"%@/edit", objectId];
   uriFormat  = [self uriAsFormat];
-  uri = [NSString stringWithFormat:uriFormat, nextMethod];
-
+  uri = [[NSString alloc] initWithFormat:uriFormat, nextMethod];
+  
   req = [[self context] request];
   r = [WOResponse responseWithRequest:req];
   [r setStatus:302 /* moved */];
   [r setHeader:uri forKey:@"location"];
+  [uri release]; uri = nil;
   return r;
 }
 
 
 /* save */
 
+- (NSCalendarDate *)_dateFromString:(NSString *)_str {
+  _str = [_str stringByAppendingString:@" GMT"];
+  return [NSCalendarDate dateWithString:_str 
+                        calendarFormat:@"%Y-%m-%d %H:%M %Z"];
+}
 
 - (id)saveAction {
   SOGoAppointment *apt;
   req = [[self context] request];
 
   /* get iCalString from hidden input */
+  
   iCalString = [req formValueForKey:@"ical"];
+  if ([iCalString length] == 0) {
+    // TODO: improve user experience ... (eg error panel like Zope)
+    return [NSException exceptionWithHTTPStatus:400 /* bad request */
+                       reason:@"missing iCalendar form data in request"];
+  }
+  
   apt = [[SOGoAppointment alloc] initWithICalString:iCalString];
-
+  
   /* merge in form values */
-  sd = [NSCalendarDate dateWithString:[req formValueForKey:@"startDate"]
-                      calendarFormat:@"%Y-%m-%d %H:%M"];
+  
+  sd = [self _dateFromString:[req formValueForKey:@"startDate"]];
+  ed = [self _dateFromString:[req formValueForKey:@"endDate"]];
   [apt setStartDate:sd];
-  ed = [NSCalendarDate dateWithString:[req formValueForKey:@"endDate"]
-                      calendarFormat:@"%Y-%m-%d %H:%M"];
   [apt setEndDate:ed];
+  
   summary = [req formValueForKey:@"summary"];
   [apt setSummary:summary];
   location = [req formValueForKey:@"location"];
index ce2381aad302514d5074c1ddfb365f04817e13a6..0aaaf19e566b34d77da195bb585b0dff1a984317 100644 (file)
 
   <tr>
     <td>
-        <table border="0" cellpadding="2" width="100%" cellspacing="0" bgcolor="#e8e8e0">
+        <table border="0" cellpadding="2" width="100%" 
+               cellspacing="0" bgcolor="#e8e8e0">
           <tr>
             <td align="left" colspan="2">
-              <span class="aptview_title">Appointment on <var:string value="formattedAptStartTime" /></span>
+              <span class="aptview_title">Appointment on 
+                <var:string value="formattedAptStartTime" /></span>
             </td>
           </tr>
           <tr valign="top">
             </td>
             <td align="left" bgcolor="#FFFFF0">
                 <span class="aptview_text">
-                  <input type="text" name="startDate" var:value="appointment.startDate" const:dateformat="%Y-%m-%d %H:%M" const:size="40" />
+                  <input type="text" name="startDate" 
+                         var:value="appointment.startDate" 
+                         const:dateformat="%Y-%m-%d %H:%M %Z" 
+                         const:size="40" />
                 </span>
             </td>
           </tr>
             </td>
             <td align="left" bgcolor="#FFFFF0">
                 <span class="aptview_text">
-                  <input type="text" name="endDate" var:value="appointment.endDate" const:dateformat="%Y-%m-%d %H:%M" const:size="40" />
+                  <input type="text" name="endDate" 
+                         var:value="appointment.endDate" 
+                         const:dateformat="%Y-%m-%d %H:%M %Z" 
+                         const:size="40" />
                 </span>
             </td>
           </tr>
index 22dce8980e51677f074244c640fdceafec5fbc51..03b1ce3eae7fe14d18382c34d855c5eee866de85 100644 (file)
@@ -7,9 +7,9 @@
 
 @interface UIxAppointmentView : UIxComponent
 {
-    NSString *tabSelection;
-    id appointment;
-    id attendee;
+  NSString *tabSelection;
+  id appointment;
+  id attendee;
 }
 
 - (id)appointment;
@@ -18,8 +18,8 @@
 - (NSString *)participantsTabLink;
 
 - (NSString *)completeHrefForMethod:(NSString *)_method
-              withParameter:(NSString *)_param
-              forKey:(NSString *)_key;
+  withParameter:(NSString *)_param
+  forKey:(NSString *)_key;
 
 @end
 
index 62fd16a2c9a9535683890f8890e3b7bfa2a3c306..241fef8a7253dd85ada30ff65a43eaffcd5d81fc 100644 (file)
@@ -8,7 +8,7 @@
 
 - (void)dealloc {
   [self->appointment release];
-  [self->attendee release];
+  [self->attendee    release];
   [super dealloc];
 }
 
@@ -30,7 +30,6 @@
   return self->attendee;
 }
 
-
 - (NSString *)attendeeEmail {
   NSString *s;
   
     return self->appointment;
     
   iCalString = [[self clientObject] valueForKey:@"iCalString"];
+  if ([iCalString length] == 0) {
+    [self logWithFormat:@"ERROR(%s): missing iCal string!", 
+         __PRETTY_FUNCTION__];
+    return nil;
+  }
+  
   self->appointment = [[SOGoAppointment alloc] initWithICalString:iCalString];
   return self->appointment;
 }
   NSCalendarDate *date;
     
   date = [[self appointment] startDate];
-  /* TODO: convert this into display timeZone! */
+  [date setTimeZone:[self viewTimeZone]];
   return [date descriptionWithCalendarFormat:@"%A, %Y-%m-%d %H:%M %Z"];
 }
 
 - (NSString *)formattedAptEndTime {
   NSCalendarDate *date;
-    
+  
   date = [[self appointment] endDate];
-  /* TODO: convert this into display timeZone! */
+  [date setTimeZone:[self viewTimeZone]];
   return [date descriptionWithCalendarFormat:@"%A, %Y-%m-%d %H:%M %Z"];
 }
 
@@ -90,8 +95,8 @@
 }
 
 - (NSString *)completeHrefForMethod:(NSString *)_method
-              withParameter:(NSString *)_param
-              forKey:(NSString *)_key
+  withParameter:(NSString *)_param
+  forKey:(NSString *)_key
 {
     NSString *href;
 
index fe0b42a520cfe4bfad1fa97c425de88f9220f5d1..ec9baee4b093dbd686a7cd4c81e554a55da429dc 100644 (file)
@@ -3,6 +3,8 @@
 #include "UIxCalView.h"
 #include "common.h"
 #include "UIxAppointmentFormatter.h"
+#include <OGoContentStore/OCSFolder.h>
+#include "SoObjects/Appointments/SOGoAppointmentFolder.h"
 
 @implementation UIxCalView
 
@@ -46,6 +48,7 @@
   NSString *ms;
   
   startDate = [[self appointment] valueForKey:@"startDate"];
+  [startDate setTimeZone:[self viewTimeZone]];
   ms = [NSString stringWithFormat:@"%02i:%02i %@",
                 [startDate hourOfDay],
                 [startDate minuteOfHour],
   NSString *title;
     
   title = [self->appointment valueForKey:@"title"];
-  if([title length] > 12) {
-        title = [NSString stringWithFormat:@"%@...",
-            [title substringToIndex:11]];
-  }
+  if ([title length] > 12)
+    title = [[title substringToIndex:11] stringByAppendingString:@"..."];
+  
   return title;
 }
 
 - (NSCalendarDate *)referenceDateForFormatter {
-    return [self selectedDate];
+  return [self selectedDate];
 }
 
 /* current day related */
 
 - (void)setCurrentDay:(NSCalendarDate *)_day {
-    ASSIGN(self->currentDay, _day);
+  ASSIGN(self->currentDay, _day);
 }
 - (NSCalendarDate *)currentDay {
-    return self->currentDay;
+  return self->currentDay;
 }
 
 - (NSString *)currentDayName {
-    // TODO: this is slow, use locale dictionary to speed this up
-    return [self->currentDay descriptionWithCalendarFormat:@"%A"];
+  // TODO: this is slow, use locale dictionary to speed this up
+  [self->currentDay setTimeZone:[self viewTimeZone]];
+  return [self->currentDay descriptionWithCalendarFormat:@"%A"];
 }
 
 - (BOOL)hasDayInfo {
   return [[self startDate] tomorrow];
 }
 
+- (NSArray *)_fetchCoreInfosForUIDs:(NSArray *)_uids 
+  uniqueWithSet:(NSMutableSet *)_uniquer 
+{
+  NSMutableArray *ma;
+  unsigned i, count;
+  
+  count = [_uids count];
+  ma    = [NSMutableArray arrayWithCapacity:count * 10];
+  
+  for (i = 0; i < count; i++) {
+    OCSFolder *folder;
+    NSString *path;
+    NSString *uid;
+    NSArray  *res;
+       
+    uid = [_uids objectAtIndex:i];
+    if ([uid length] == 0) continue;
+
+    path = [[@"/Users/" stringByAppendingString:uid]
+                       stringByAppendingString:@"/Calendar"];
+    
+    if ((folder = [[self clientObject] ocsFolderForPath:path]) == nil) {
+      [self logWithFormat:@"ERROR: did not find user: %@", uid];
+      continue;
+    }
+    
+    res = [[self clientObject] fetchCoreInfosFromFolder:folder 
+                              from:[self startDate] to:[self endDate]];
+    if (res == nil) {
+      [self logWithFormat:@"ERROR: fetch failed for user: %@", uid];
+      continue;
+    }
+
+    /* perform uniquing */
+    {
+      int j, rcount;
+      
+      for (j = 0, rcount = [res count]; j < rcount; j++) {
+       NSDictionary *record;
+       
+       record = [res objectAtIndex:j];
+       
+       if ([_uniquer containsObject:[record valueForKey:@"uid"]])
+         continue;
+       
+       [ma addObject:record];
+       [_uniquer addObject:[record valueForKey:@"uid"]];
+      }
+    }
+  }
+  return ma;
+}
+
 - (NSArray *)fetchCoreInfos {
+  id      aptFolder;
+  NSArray *more;
+  id      uids;
+  
   if (self->appointments)
     return self->appointments;
-
+  
+  aptFolder = [self clientObject];
   self->appointments =
-    [[[self clientObject] fetchCoreInfosFrom:[self startDate] 
-                         to:[self endDate]] retain];
+    [[aptFolder fetchCoreInfosFrom:[self startDate] to:[self endDate]] retain];
+  
+  uids = [[[[self context] request] formValueForKey:@"uids"] stringValue];
+  uids = [uids length] > 0 ? [uids componentsSeparatedByString:@","] : nil;
+  if ([uids count] > 0) {
+    NSMutableSet *availUIDs;
+    id tmp;
+    
+    /* make appointments unique, prefer the own "versions" */
+    tmp = [self->appointments valueForKey:@"uid"];
+    availUIDs = [[NSMutableSet alloc] initWithArray:tmp];
+    
+    more = [self _fetchCoreInfosForUIDs:uids uniqueWithSet:availUIDs];
+    if (more > 0) {
+      NSArray *tmp;
+      
+      tmp = self->appointments;
+      self->appointments = [[tmp arrayByAddingObjectsFromArray:more] retain];
+      [tmp release];
+    }
+    
+    [availUIDs release];
+  }
+  
   return self->appointments;
 }
 
 
 
 - (NSDictionary *)todayQueryParameters {
-    NSCalendarDate *date;
+  NSCalendarDate *date;
     
-    date = [NSCalendarDate date]; /* today */
-    return [self queryParametersBySettingSelectedDate:date];
+  date = [NSCalendarDate date]; /* today */
+  return [self queryParametersBySettingSelectedDate:date];
 }
 
 - (NSDictionary *)currentDayQueryParameters {
-    return [self queryParametersBySettingSelectedDate:self->currentDay];
+  return [self queryParametersBySettingSelectedDate:self->currentDay];
 }
 
 - (NSDictionary *)queryParametersBySettingSelectedDate:(NSCalendarDate *)_date {
 }
 
 - (void)setSelectedDateQueryParameter:(NSCalendarDate *)_newDate
-        inDictionary:(NSMutableDictionary *)_qp;
+  inDictionary:(NSMutableDictionary *)_qp;
 {
-    if(_newDate != nil)
-        [_qp setObject:[self dateStringForDate:_newDate]
-             forKey:@"day"];
-    else
-        [_qp removeObjectForKey:@"day"];
+  if(_newDate != nil)
+    [_qp setObject:[self dateStringForDate:_newDate] forKey:@"day"];
+  else
+    [_qp removeObjectForKey:@"day"];
 }
 
 @end /* UIxCalView */
index 53d61a905d21b859c64e74424ad81df3595f9bc9..e3cffd508faa2ffb4c6b922d8a5ed65d357fa7d0 100644 (file)
       </var:if>
       <var:week>
         <a var:href="appointmentViewURL" 
-          ><small><var:string value="shortTextForApt" /></small></a>
+          ><small><var:string value="shortTextForApt" /></small></a><br />
       </var:week>
     </var:week-overview>
   </var:component>
   </tr>
   <tr bgcolor="#F5F5E9">
   <td align="left" width="10"><var:entity const:name="nbsp"/></td>
-  <td align="right"><img border="0" alt="" src="/sogod.woa/so/ControlPanel/Products/CommonUI/Resources/corner_right.gif"/></td>
+  <td align="right"><img 
+     border="0" alt="" 
+     src="/sogod.woa/so/ControlPanel/Products/CommonUI/Resources/corner_right.gif"/></td>
   </tr>
   <tr>
   <td colspan="2" bgcolor="#F5F5E9">