+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
#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__ */
@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 {
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 {
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];
}
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];
}
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],
@"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;
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 {
+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
- (void)setOCSPath:(NSString *)_Path;
- (NSString *)ocsPath;
+- (OCSFolder *)ocsFolderForPath:(NSString *)_path;
- (OCSFolder *)ocsFolder;
@end
- (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;
}
#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;
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 {
+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
#include <NGObjWeb/SoComponent.h>
-@class NSCalendarDate;
+@class NSCalendarDate, NSTimeZone, NSMutableDictionary;
@interface UIxComponent : SoComponent
{
- NSMutableDictionary *queryParameters;
+ NSMutableDictionary *queryParameters;
}
- (NSString *)queryParameterForKey:(NSString *)_key;
- (NSString *)ownMethodName;
/* date selection */
+- (NSTimeZone *)viewTimeZone;
- (NSCalendarDate *)selectedDate;
- (NSString *)dateStringForDate:(NSCalendarDate *)_date;
- (NSCalendarDate *)dateForDateString:(NSString *)_dateString;
/*
- 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 */
+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
images/icon_apt_list_inactive.gif \
ADDITIONAL_INCLUDE_DIRS += \
- -I..
+ -I.. -I../.. -I../../..
# make
}
- (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"];
<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>
@interface UIxAppointmentView : UIxComponent
{
- NSString *tabSelection;
- id appointment;
- id attendee;
+ NSString *tabSelection;
+ id appointment;
+ id attendee;
}
- (id)appointment;
- (NSString *)participantsTabLink;
- (NSString *)completeHrefForMethod:(NSString *)_method
- withParameter:(NSString *)_param
- forKey:(NSString *)_key;
+ withParameter:(NSString *)_param
+ forKey:(NSString *)_key;
@end
- (void)dealloc {
[self->appointment release];
- [self->attendee release];
+ [self->attendee release];
[super dealloc];
}
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"];
}
}
- (NSString *)completeHrefForMethod:(NSString *)_method
- withParameter:(NSString *)_param
- forKey:(NSString *)_key
+ withParameter:(NSString *)_param
+ forKey:(NSString *)_key
{
NSString *href;
#include "UIxCalView.h"
#include "common.h"
#include "UIxAppointmentFormatter.h"
+#include <OGoContentStore/OCSFolder.h>
+#include "SoObjects/Appointments/SOGoAppointmentFolder.h"
@implementation UIxCalView
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 */
</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">