]> err.no Git - scalable-opengroupware.org/blob - ZideStore/UI-X/Scheduler/UIxAppointmentEditor.m
see changelog
[scalable-opengroupware.org] / ZideStore / UI-X / Scheduler / UIxAppointmentEditor.m
1 /*
2   Copyright (C) 2000-2004 SKYRIX Software AG
3
4   This file is part of OGo
5
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
9   later version.
10
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.
15
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
19   02111-1307, USA.
20 */
21 // $Id$
22
23
24 #include "common.h"
25 #include <Common/UIxComponent.h>
26 #include <SOGoLogic/SOGoAppointment.h>
27 #include <NGiCal/NGiCal.h>
28
29
30 /* TODO: CLEAN THIS MESS UP */
31
32
33 @interface NSObject (AppointmentHack)
34 - (BOOL)isAppointment;
35 @end
36
37 @implementation NSObject (AppointmentHack)
38 - (BOOL)isAppointment {
39   return [self isKindOfClass:NSClassFromString(@"SxAppointment")];
40 }
41 @end
42
43 @interface iCalPerson (Convenience)
44 - (NSString *)rfc822Email;
45 @end
46
47 @implementation iCalPerson (Convenience)
48 - (NSString *)rfc822Email {
49     NSString *_email = [self email];
50     NSRange colon = [_email rangeOfString:@":"];
51     if(colon.location != NSNotFound) {
52         return [_email substringFromIndex:colon.location + 1];
53     }
54     return _email;
55 }
56 @end
57
58 @interface UIxAppointmentEditor : UIxComponent
59 {
60     id appointment;
61     id participants;
62 }
63
64 - (SOGoAppointment *)appointment;
65 - (NSString *)iCalStringTemplate;
66 - (NSString *)iCalString;
67 - (BOOL)isNewAppointment;
68
69 @end
70
71 @implementation UIxAppointmentEditor
72
73 - (void)dealloc {
74     [self->appointment release];
75     [self->participants release];
76     [super dealloc];
77 }
78
79
80 /* accessors */
81
82
83 - (NSString *)formattedAptStartTime {
84     NSCalendarDate *date;
85     
86     date = [[self appointment] startDate];
87     /* TODO: convert this into display timeZone! */
88     return [date descriptionWithCalendarFormat:@"%A, %Y-%m-%d %H:%M %Z"];
89 }
90
91 - (BOOL)isNewAppointment {
92     return ! [[self clientObject] isAppointment];
93 }
94
95 - (NSString *)iCalString {
96     if([self isNewAppointment]) {
97         return [self iCalStringTemplate];
98     }
99     else {
100         return [[self clientObject] valueForKey:@"iCalString"];
101     }
102 }
103
104 - (NSString *)iCalStringTemplate {
105     static NSString *iCalStringTemplate = \
106     @"BEGIN:VCALENDAR\nMETHOD:REQUEST\nPRODID:OpenGroupware.org ZideStore 1.2\n" \
107     @"VERSION:2.0\nBEGIN:VEVENT\nCLASS:PRIVATE\nSTATUS:CONFIRMED\n" \
108     @"DTSTART:%@\nDTEND:%@\n" \
109     @"TRANSP:OPAQUE\n" \
110     @"END:VEVENT\nEND:VCALENDAR";
111     NSCalendarDate *startDate, *endDate;
112     NSString *template;
113     
114     startDate = [self selectedDate];
115     endDate = [startDate dateByAddingYears:0 months:0 days:0
116                          hours:1 minutes:0 seconds:0];
117     
118     template = [NSString stringWithFormat:iCalStringTemplate,
119                                           [startDate icalString],
120                                           [endDate icalString]];
121     
122     return template;
123 }
124
125
126 /* backend */
127
128
129 - (SOGoAppointment *)appointment {
130     if(self->appointment == nil) {
131         self->appointment = [[SOGoAppointment alloc]
132           initWithICalString:[self iCalString]];
133     }
134     return self->appointment;
135 }
136
137 - (id)participants {
138     if(self->participants == nil) {
139         NSArray *attendees;
140         NSMutableArray *emailAddresses;
141         unsigned i, count;
142
143         attendees = [self->appointment attendees];
144         count = [attendees count];
145         emailAddresses = [[NSMutableArray alloc] initWithCapacity:count];
146         for(i = 0; i < count; i++) {
147             NSString *email;
148             
149             email = [[attendees objectAtIndex:i] rfc822Email];
150             if(email)
151                 [emailAddresses addObject:email];
152         }
153         self->participants = [[emailAddresses componentsJoinedByString:@"\n"]
154             retain];
155         [emailAddresses release];
156     }
157     return self->participants;
158 }
159
160
161 /* helper */
162
163 - (NSString *)uriAsFormat {
164     NSString *uri, *qp;
165     NSRange r;
166
167     uri = [[[self context] request] uri];
168     
169     /* first: identify query parameters */
170     r = [uri rangeOfString:@"?" options:NSBackwardsSearch];
171     if (r.length > 0) {
172         uri = [uri substringToIndex:r.location];
173         qp = [uri substringFromIndex:r.location];
174     }
175     else {
176         qp = nil;
177     }
178     
179     /* next: strip trailing slash */
180     if([uri hasSuffix:@"/"])
181         uri = [uri substringToIndex:([uri length] - 1)];
182     r = [uri rangeOfString:@"/" options:NSBackwardsSearch];
183     
184     /* then: cut of last path component */
185     if(r.location == NSNotFound) { // no slash? are we at root?
186         uri = @"/";
187     }
188     else {
189         uri = [uri substringToIndex:(r.location + 1)];
190     }
191     /* next: append format token */
192     uri = [uri stringByAppendingString:@"%@"];
193     if(qp != nil)
194         uri = [uri stringByAppendingString:qp];
195     return uri;
196 }
197
198
199 /* save */
200
201
202 - (id)saveAction {
203     SOGoAppointment *apt;
204     NSString *iCalString, *summary, *location, *nextMethod, *uri, *uriFormat;
205     NSCalendarDate *sd, *ed;
206     NSArray *ps;
207     unsigned i, count;
208     WOResponse *r;
209     WORequest *req;
210
211     req = [[self context] request];
212
213     /* get iCalString from hidden input */
214     iCalString = [req formValueForKey:@"ical"];
215     apt = [[SOGoAppointment alloc] initWithICalString:iCalString];
216
217     /* merge in form values */
218     sd = [NSCalendarDate dateWithString:[req formValueForKey:@"startDate"]
219                          calendarFormat:@"%Y-%m-%d %H:%M"];
220     [apt setStartDate:sd];
221     ed = [NSCalendarDate dateWithString:[req formValueForKey:@"endDate"]
222                          calendarFormat:@"%Y-%m-%d %H:%M"];
223     [apt setEndDate:ed];
224     summary = [req formValueForKey:@"summary"];
225     [apt setSummary:title];
226     location = [req formValueForKey:@"location"];
227     [apt setLocation:location];
228
229     [apt removeAllAttendees]; /* clean up */
230     ps = [[req formValueForKey:@"participants"]
231         componentsSeparatedByString:@"\n"];
232     count = [ps count];
233     for(i = 0; i < count; i++) {
234         NSString *email;
235         
236         email = [ps objectAtIndex:i];
237         if([email length] > 0) {
238             iCalPerson *p;
239             NSRange cnr;
240
241             p = [[iCalPerson alloc] init];
242             [p setEmail:[NSString stringWithFormat:@"mailto:%@", email]];
243             /* construct a fake CN */
244             cnr = [email rangeOfString:@"@"];
245             if(cnr.location != NSNotFound) {
246                 [p setCn:[email substringToIndex:cnr.location]];
247             }
248             [apt addToAttendees:p];
249             [p release];
250         }
251     }
252
253     /* receive current representation for save operation */
254     iCalString = [apt iCalString];
255     [apt release];
256     
257
258     /* determine what's to do and where to go next */
259     if([self isNewAppointment]) {
260         nextMethod = @"duhduh";
261     }
262     else {
263         nextMethod = @"view";
264     }
265
266     NSLog(@"%s new iCalString:\n%@", __PRETTY_FUNCTION__, iCalString);
267
268     uriFormat = [self uriAsFormat];
269     uri = [NSString stringWithFormat:uriFormat, nextMethod];
270
271     r = [WOResponse responseWithRequest:req];
272     [r setStatus:302 /* moved */];
273     [r setHeader:uri forKey:@"location"];
274     return r;
275 }
276
277 @end