]> err.no Git - scalable-opengroupware.org/blob - SOGo/UI/Scheduler/UIxCalView.m
bugfix
[scalable-opengroupware.org] / SOGo / UI / Scheduler / UIxCalView.m
1 // $Id$
2
3 #include "UIxCalView.h"
4 #include "common.h"
5 #include "UIxAppointmentFormatter.h"
6 #include <OGoContentStore/OCSFolder.h>
7 #include "SoObjects/Appointments/SOGoAppointmentFolder.h"
8 #include <NGObjWeb/SoUser.h>
9 #include <SOGoUI/SOGoAptFormatter.h>
10 #include <SOGoLogic/AgenorUserManager.h>
11 #include "UIxComponent+Agenor.h"
12
13 @interface UIxCalView (PrivateAPI)
14 - (NSString *)_userFolderURI;
15 @end
16
17 @implementation UIxCalView
18
19 static BOOL shouldDisplayWeekend = NO;
20
21 + (void)initialize {
22     NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
23     shouldDisplayWeekend = [ud boolForKey:@"SOGoShouldDisplayWeekend"];
24 }
25
26 - (void)dealloc {
27   [self->appointments        release];
28   [self->allDayApts          release];
29   [self->appointment         release];
30   [self->currentDay          release];
31   [self->aptFormatter        release];
32   [self->aptTooltipFormatter release];
33   [super dealloc];
34 }
35
36 /* accessors */
37
38 - (void)setAppointments:(NSArray *)_apts {
39   ASSIGN(self->appointments, _apts);
40 }
41 - (NSArray *)appointments {
42   return self->appointments;
43 }
44
45 - (void)setAppointment:(id)_apt {
46   ASSIGN(self->appointment, _apt);
47 }
48 - (id)appointment {
49   return self->appointment;
50 }
51
52 - (NSDictionary *)aptTypeDict {
53   return nil;
54 }
55 - (NSString *)aptTypeLabel {
56   return @"aptLabel";
57 }
58 - (NSString *)aptTypeIcon {
59   return @"";
60 }
61
62 - (SOGoAptFormatter *)aptFormatter {
63   if (self->aptFormatter)
64     return self->aptFormatter;
65   
66   self->aptFormatter = [[SOGoAptFormatter alloc]
67                          initWithDisplayTimeZone:[self viewTimeZone]];
68   [self->aptFormatter setFullDetails];
69   return self->aptFormatter;
70 }
71
72 - (SOGoAptFormatter *)aptTooltipFormatter {
73   if (self->aptTooltipFormatter)
74     return self->aptTooltipFormatter;
75   self->aptTooltipFormatter = [[SOGoAptFormatter alloc]
76                                 initWithDisplayTimeZone:[self viewTimeZone]];
77   [self->aptTooltipFormatter setTooltip];
78   return self->aptTooltipFormatter;
79 }
80
81 /* TODO: remove this */
82 - (NSString *)shortTextForApt {
83   return [[self aptFormatter] stringForObjectValue:self->appointment];
84 }
85
86 - (NSString *)shortTitleForApt {
87   NSString *title;
88     
89   title = [self->appointment valueForKey:@"title"];
90   if ([title length] > 12)
91     title = [[title substringToIndex:11] stringByAppendingString:@"..."];
92   
93   return title;
94 }
95
96 - (NSString *)tooltipForApt {
97   return [[self aptTooltipFormatter] stringForObjectValue:self->appointment];
98 }
99
100 - (BOOL)isMyApt {
101   NSString *mailtoChunk;
102   NSString *myEmail;
103
104   mailtoChunk = [self->appointment valueForKey:@"partmails"];
105   myEmail = [self emailForUser];
106   if ([mailtoChunk rangeOfString:myEmail].length > 0)
107     return YES;
108   return NO;
109 }
110
111 - (NSString *)aptStyle {
112   if (![self isMyApt])
113     return @"apt_other";
114   return nil;
115 }
116
117 - (NSCalendarDate *)referenceDateForFormatter {
118   return [self selectedDate];
119 }
120
121 - (NSCalendarDate *)thisMonth {
122   return [self selectedDate];
123 }
124
125 - (NSCalendarDate *)nextMonth {
126   NSCalendarDate *date = [self thisMonth];
127   return [date dateByAddingYears:0 months:1 days:0
128                hours:0 minutes:0 seconds:0];
129 }
130
131
132 /* current day related */
133
134 - (void)setCurrentDay:(NSCalendarDate *)_day {
135   [_day setTimeZone:[self viewTimeZone]];
136   ASSIGN(self->currentDay, _day);
137 }
138 - (NSCalendarDate *)currentDay {
139   return self->currentDay;
140 }
141
142 - (NSString *)currentDayName {
143   return [self localizedNameForDayOfWeek:[self->currentDay dayOfWeek]];
144 }
145
146 - (id)holidayInfo {
147   return nil;
148 }
149
150 - (NSArray *)allDayApts {
151   NSArray        *apts;
152   NSMutableArray *filtered;
153   unsigned i, count;
154
155   if (self->allDayApts)
156     return self->allDayApts;
157
158   apts     = [self appointments];
159   count    = [apts count];
160   filtered = [[NSMutableArray alloc] initWithCapacity:3];
161   for (i = 0; i < count; i++) {
162     id apt;
163     NSNumber *bv;
164
165     apt = [apts objectAtIndex:i];
166 #warning !! check if isAllDay is correct
167     bv = [apt valueForKey:@"isAllDay"];
168     if ([bv boolValue])
169       [filtered addObject:apt];
170   }
171     
172   ASSIGN(self->allDayApts, filtered);
173   [filtered release];
174   return self->allDayApts;
175 }
176
177
178 /* special appointments */
179
180 - (BOOL)hasDayInfo {
181   return [self hasHoldidayInfo] || [self hasAllDayApts];
182 }
183
184 - (BOOL)hasHoldidayInfo {
185   return [self holidayInfo] != nil;
186 }
187
188 - (BOOL)hasAllDayApts {
189   return [[self allDayApts] count] != 0;
190 }
191
192
193 /* defaults */
194
195 - (BOOL)showFullNames {
196   return YES;
197 }
198
199 - (BOOL)showAMPMDates {
200   return NO;
201 }
202
203 - (unsigned)dayStartHour {
204   return 8;
205 }
206
207 - (unsigned)dayEndHour {
208   return 18;
209 }
210
211 - (BOOL)shouldDisplayWeekend {
212   return shouldDisplayWeekend;
213 }
214
215 - (BOOL)shouldHideWeekend {
216   return ![self shouldDisplayWeekend];
217 }
218
219
220 /* URLs */
221
222 - (NSString *)appointmentViewURL {
223   id pkey;
224   
225   if (![(pkey = [[self appointment] valueForKey:@"uid"]) isNotNull])
226     return nil;
227   
228   return [[[self clientObject] baseURLForAptWithUID:[pkey stringValue]
229                                inContext:[self context]]
230                                stringByAppendingString:@"/view"];
231 }
232
233 /* backend */
234
235 /* resource URLs (TODO?) */
236
237 - (NSString *)resourcePath {
238   // TODO: broken
239   // TODO: where is this used?
240   return @"/sogod.woa/WebServerResources/";
241 }
242
243 - (NSString *)favIconPath {
244   return [[self resourcePath] stringByAppendingPathComponent:@"favicon.ico"];
245 }
246 - (NSString *)cssPath {
247   NSString *path;
248   
249   // TODO: there should be reusable functionality for that!
250 #warning ZideStore specific?
251   path = @"ControlPanel/Products/ZideStoreUI/Resources/uix.css";
252   return [[self context] urlWithRequestHandlerKey:@"so"
253                          path:path
254                          queryString:nil];
255 }
256
257 - (NSString *)calCSSPath {
258   NSString *path;
259   
260   // TODO: there should be reusable functionality for that!
261 #warning ZideStore specific?
262   path = @"ControlPanel/Products/ZideStoreUI/Resources/calendar.css";
263   return [[self context] urlWithRequestHandlerKey:@"so"
264                          path:path
265                          queryString:nil];
266 }
267
268 /* fetching */
269
270 - (NSCalendarDate *)startDate {
271   return [self selectedDate];
272 }
273 - (NSCalendarDate *)endDate {
274   return [[self startDate] tomorrow];
275 }
276
277 - (NSArray *)_fetchCoreInfosForUIDs:(NSArray *)_uids 
278   uniqueWithSet:(NSMutableSet *)_uniquer 
279 {
280   NSMutableArray *ma;
281   unsigned i, count;
282   
283   count = [_uids count];
284   ma    = [NSMutableArray arrayWithCapacity:count * 10];
285   
286   for (i = 0; i < count; i++) {
287     OCSFolder *folder;
288     NSString *path;
289     NSString *uid;
290     NSArray  *res;
291         
292     uid = [_uids objectAtIndex:i];
293     if ([uid length] == 0) continue;
294
295     path = [[@"/Users/" stringByAppendingString:uid]
296                         stringByAppendingString:@"/Calendar"];
297     
298     if ((folder = [[self clientObject] ocsFolderForPath:path]) == nil) {
299       [self logWithFormat:@"ERROR: did not find user: %@", uid];
300       continue;
301     }
302     
303     res = [[self clientObject] fetchCoreInfosFromFolder:folder 
304                                from:[self startDate] to:[self endDate]];
305     if (res == nil) {
306       [self logWithFormat:@"ERROR: fetch failed for user: %@", uid];
307       continue;
308     }
309
310     /* perform uniquing */
311     {
312       int j, rcount;
313       
314       for (j = 0, rcount = [res count]; j < rcount; j++) {
315         NSDictionary *record;
316         
317         record = [res objectAtIndex:j];
318     
319         if ([_uniquer containsObject:[record valueForKey:@"uid"]])
320           continue;
321         
322         [ma addObject:record];
323         [_uniquer addObject:[record valueForKey:@"uid"]];
324       }
325     }
326   }
327   return ma;
328 }
329
330 - (NSArray *)fetchCoreInfos {
331   id      aptFolder;
332   NSArray *more;
333   id      uids;
334   
335   if (self->appointments)
336     return self->appointments;
337   
338   aptFolder = [self clientObject];
339   self->appointments =
340     [[aptFolder fetchCoreInfosFrom:[self startDate] to:[self endDate]] retain];
341   
342   uids = [[[[self context] request] formValueForKey:@"uids"] stringValue];
343   uids = [uids length] > 0 ? [uids componentsSeparatedByString:@","] : nil;
344   if ([uids count] > 0) {
345     NSMutableSet *availUIDs;
346     id tmp;
347     
348     /* make appointments unique, prefer the own "versions" */
349     tmp = [self->appointments valueForKey:@"uid"];
350     availUIDs = [[NSMutableSet alloc] initWithArray:tmp];
351     
352     more = [self _fetchCoreInfosForUIDs:uids uniqueWithSet:availUIDs];
353     if (more > 0) {
354       NSArray *tmp;
355       
356       tmp = self->appointments;
357       self->appointments = [[tmp arrayByAddingObjectsFromArray:more] retain];
358       [tmp release];
359     }
360     
361     [availUIDs release];
362   }
363   
364   return self->appointments;
365 }
366
367 /* date selection & conversion */
368
369 - (NSDictionary *)todayQueryParameters {
370   NSCalendarDate *date;
371     
372   date = [NSCalendarDate date]; /* today */
373   return [self queryParametersBySettingSelectedDate:date];
374 }
375
376 - (NSDictionary *)currentDayQueryParameters {
377   return [self queryParametersBySettingSelectedDate:self->currentDay];
378 }
379
380 /* calendarUIDs */
381
382 - (NSString *)formattedCalendarUIDs {
383     return [[[self clientObject] calendarUIDs]
384                                  componentsJoinedByString:@", "];
385 }
386
387 /* Actions */
388
389 - (NSString *)_userFolderURI {
390   WOContext *ctx;
391   id        obj;
392   NSURL     *url;
393
394   ctx = [self context];
395   obj = [[ctx objectTraversalStack] objectAtIndex:1];
396   url = [NSURL URLWithString:[obj baseURLInContext:ctx]];
397   return [[url path] stringByUnescapingURL];
398 }
399
400 - (id)redirectForUIDsAction {
401   NSMutableString *uri;
402   NSString   *uidsString, *loc, *prevMethod, *userFolderID;
403   WORequest  *req;
404   id <WOActionResults> r;
405   BOOL useGroups;
406   unsigned index;
407
408   req = [[self context] request];
409
410   uidsString = [req formValueForKey:@"anaisUIDString"];
411   uidsString = [uidsString stringByTrimmingWhiteSpaces];
412
413   prevMethod = [req formValueForKey:@"previousMethod"];
414   if(prevMethod == nil)
415     prevMethod = @"";
416
417   uri = [[NSMutableString alloc] initWithString:[self _userFolderURI]];
418   /* if we have more than one entry, use groups - otherwise don't */
419   useGroups = [uidsString rangeOfString:@","].length > 0;
420   userFolderID = [uri lastPathComponent];
421   if(useGroups) {
422     NSArray *uids;
423
424     uids = [uidsString componentsSeparatedByString:@","];
425     /* guarantee that our id is the first */
426     if(((index = [uids indexOfObject:userFolderID]) != NSNotFound) &&
427        (index != 0)) {
428         uids = [[uids mutableCopy] autorelease];
429         [(NSMutableArray *)uids removeObjectAtIndex:index];
430         [(NSMutableArray *)uids insertObject:userFolderID atIndex:0];
431         uidsString = [uids componentsJoinedByString:@","];
432     }
433     [uri appendString:@"Groups/_custom_"];
434     [uri appendString:uidsString];
435     [uri appendString:@"/"];
436   }
437   else {
438       /* check if lastPathComponent is the base that we want to have */
439       if((([uidsString length] != 0) &&
440           (![userFolderID isEqualToString:uidsString]))) {
441           NSRange r;
442           
443           /* uri ends with an '/', so we have to adjust the range a little */
444           r = NSMakeRange(0, [uri length] - 1);
445           r = [uri rangeOfString:@"/"
446                          options:NSBackwardsSearch
447                            range:r];
448           r = NSMakeRange(r.location + 1, [uri length] - r.location - 2);
449           [uri replaceCharactersInRange:r withString:uidsString];
450       }
451   }
452   [uri appendString:@"Calendar/"];
453   [uri appendString:prevMethod];
454
455 #if 0
456   NSLog(@"%s redirect uri:%@",
457           __PRETTY_FUNCTION__,
458           uri);
459 #endif
460   loc = [self completeHrefForMethod:uri]; /* this might return uri! */
461   r = [self redirectToLocation:loc];
462   [uri release];
463   return r;
464 }
465
466 @end /* UIxCalView */