2 Copyright (C) 2000-2004 SKYRIX Software AG
4 This file is part of OpenGroupware.org.
6 OGo is free software; you can redistribute it and/or modify it under
7 the terms of the GNU Lesser General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 OGo is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with OGo; see the file COPYING. If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 #include <SOGoUI/UIxComponent.h>
26 #include <SOGoLogic/SOGoAppointment.h>
27 #include <NGiCal/NGiCal.h>
30 /* TODO: CLEAN THIS MESS UP */
32 @interface NSDate(UsedPrivates)
33 - (NSString *)icalString; // TODO: this is in NGiCal
36 @interface NSObject (AppointmentHack)
37 - (BOOL)isAppointment;
40 @implementation NSObject (AppointmentHack)
41 - (BOOL)isAppointment {
42 return [self isKindOfClass:NSClassFromString(@"SOGoAppointmentObject")];
46 @interface iCalPerson (Convenience)
47 - (NSString *)rfc822Email;
50 @implementation iCalPerson (Convenience)
51 - (NSString *)rfc822Email {
52 NSString *_email = [self email];
53 NSRange colon = [_email rangeOfString:@":"];
54 if(colon.location != NSNotFound) {
55 return [_email substringFromIndex:colon.location + 1];
61 @interface UIxAppointmentEditor : UIxComponent
67 - (SOGoAppointment *)appointment;
68 - (NSString *)iCalStringTemplate;
69 - (NSString *)iCalString;
70 - (BOOL)isNewAppointment;
74 @implementation UIxAppointmentEditor
77 [self->appointment release];
78 [self->participants release];
86 - (NSString *)formattedAptStartTime {
89 date = [[self appointment] startDate];
90 /* TODO: convert this into display timeZone! */
91 return [date descriptionWithCalendarFormat:@"%A, %Y-%m-%d %H:%M %Z"];
94 - (BOOL)isNewAppointment {
95 return ! [[self clientObject] isAppointment];
98 - (NSString *)iCalString {
99 if([self isNewAppointment]) {
100 return [self iCalStringTemplate];
103 return [[self clientObject] valueForKey:@"iCalString"];
107 - (NSString *)iCalStringTemplate {
108 static NSString *iCalStringTemplate = \
109 @"BEGIN:VCALENDAR\nMETHOD:REQUEST\nPRODID:OpenGroupware.org SOGo 0.9\n" \
110 @"VERSION:2.0\nBEGIN:VEVENT\nCLASS:PRIVATE\nSTATUS:CONFIRMED\n" \
111 @"DTSTART:%@\nDTEND:%@\n" \
113 @"END:VEVENT\nEND:VCALENDAR";
114 NSCalendarDate *startDate, *endDate;
117 startDate = [self selectedDate];
118 endDate = [startDate dateByAddingYears:0 months:0 days:0
119 hours:1 minutes:0 seconds:0];
121 template = [NSString stringWithFormat:iCalStringTemplate,
122 [startDate icalString],
123 [endDate icalString]];
132 - (SOGoAppointment *)appointment {
133 if(self->appointment == nil) {
134 self->appointment = [[SOGoAppointment alloc]
135 initWithICalString:[self iCalString]];
137 return self->appointment;
141 if(self->participants == nil) {
143 NSMutableArray *emailAddresses;
146 attendees = [self->appointment attendees];
147 count = [attendees count];
148 emailAddresses = [[NSMutableArray alloc] initWithCapacity:count];
149 for(i = 0; i < count; i++) {
152 email = [[attendees objectAtIndex:i] rfc822Email];
154 [emailAddresses addObject:email];
156 self->participants = [[emailAddresses componentsJoinedByString:@"\n"]
158 [emailAddresses release];
160 return self->participants;
166 - (NSString *)uriAsFormat {
170 uri = [[[self context] request] uri];
172 /* first: identify query parameters */
173 r = [uri rangeOfString:@"?" options:NSBackwardsSearch];
175 uri = [uri substringToIndex:r.location];
176 qp = [uri substringFromIndex:r.location];
182 /* next: strip trailing slash */
183 if([uri hasSuffix:@"/"])
184 uri = [uri substringToIndex:([uri length] - 1)];
185 r = [uri rangeOfString:@"/" options:NSBackwardsSearch];
187 /* then: cut of last path component */
188 if(r.location == NSNotFound) { // no slash? are we at root?
192 uri = [uri substringToIndex:(r.location + 1)];
194 /* next: append format token */
195 uri = [uri stringByAppendingString:@"%@"];
197 uri = [uri stringByAppendingString:qp];
208 NSString *uri, *uriFormat, *objectId, *nextMethod;
210 /* clientObject *is* SOGoAppointmentFolder, so this should be an instance method? */
211 objectId = [NSClassFromString(@"SOGoAppointmentFolder")
212 globallyUniqueObjectId];
214 nextMethod = [NSString stringWithFormat:@"%@/edit", objectId];
215 uriFormat = [self uriAsFormat];
216 uri = [NSString stringWithFormat:uriFormat, nextMethod];
218 req = [[self context] request];
219 r = [WOResponse responseWithRequest:req];
220 [r setStatus:302 /* moved */];
221 [r setHeader:uri forKey:@"location"];
230 SOGoAppointment *apt;
231 NSString *iCalString, *summary, *location, *nextMethod, *uri, *uriFormat;
232 NSCalendarDate *sd, *ed;
238 req = [[self context] request];
240 /* get iCalString from hidden input */
241 iCalString = [req formValueForKey:@"ical"];
242 apt = [[SOGoAppointment alloc] initWithICalString:iCalString];
244 /* merge in form values */
245 sd = [NSCalendarDate dateWithString:[req formValueForKey:@"startDate"]
246 calendarFormat:@"%Y-%m-%d %H:%M"];
247 [apt setStartDate:sd];
248 ed = [NSCalendarDate dateWithString:[req formValueForKey:@"endDate"]
249 calendarFormat:@"%Y-%m-%d %H:%M"];
251 summary = [req formValueForKey:@"summary"];
252 [apt setSummary:summary];
253 location = [req formValueForKey:@"location"];
254 [apt setLocation:location];
256 [apt removeAllAttendees]; /* clean up */
257 ps = [[req formValueForKey:@"participants"]
258 componentsSeparatedByString:@"\n"];
260 for(i = 0; i < count; i++) {
263 email = [ps objectAtIndex:i];
264 if([email length] > 0) {
268 p = [[iCalPerson alloc] init];
269 [p setEmail:[NSString stringWithFormat:@"mailto:%@", email]];
270 /* construct a fake CN */
271 cnr = [email rangeOfString:@"@"];
272 if(cnr.location != NSNotFound) {
273 [p setCn:[email substringToIndex:cnr.location]];
275 [apt addToAttendees:p];
280 /* receive current representation for save operation */
281 iCalString = [apt iCalString];
285 /* determine what's to do and where to go next */
286 if([self isNewAppointment]) {
287 nextMethod = @"duhduh";
290 nextMethod = @"view";
293 NSLog(@"%s new iCalString:\n%@", __PRETTY_FUNCTION__, iCalString);
295 uriFormat = [self uriAsFormat];
296 uri = [NSString stringWithFormat:uriFormat, nextMethod];
298 r = [WOResponse responseWithRequest:req];
299 [r setStatus:302 /* moved */];
300 [r setHeader:uri forKey:@"location"];