4 //#import <OGoContentStore/OCSFolder.h>
6 #import <NGObjWeb/SoSecurityManager.h>
7 #import <NGObjWeb/SoUser.h>
8 #import <NGExtensions/NGCalendarDateRange.h>
9 #import <NGCards/NGCards.h>
11 #import <SOGoUI/SOGoAptFormatter.h>
12 #import "UIxComponent+Scheduler.h"
14 #import "SoObjects/Appointments/SOGoAppointmentFolder.h"
15 #import <SOGo/NSArray+Utilities.h>
16 #import <SOGo/SOGoUser.h>
17 #import <SOGo/SOGoObject.h>
19 #import "UIxCalView.h"
21 @interface UIxCalView (PrivateAPI)
22 - (NSString *) _userFolderURI;
25 @implementation UIxCalView
27 static BOOL shouldDisplayWeekend = NO;
31 static BOOL didInit = NO;
36 ud = [NSUserDefaults standardUserDefaults];
37 shouldDisplayWeekend = [ud boolForKey: @"SOGoShouldDisplayWeekend"];
46 timeZone = [[context activeUser] timeZone];
49 = [[SOGoAptFormatter alloc] initWithDisplayTimeZone: timeZone];
51 = [[SOGoAptFormatter alloc] initWithDisplayTimeZone: timeZone];
53 = [[SOGoAptFormatter alloc] initWithDisplayTimeZone: timeZone];
54 privateAptTooltipFormatter
55 = [[SOGoAptFormatter alloc] initWithDisplayTimeZone: timeZone];
56 [self configureFormatters];
57 componentsData = [NSMutableDictionary new];
65 [componentsData release];
66 [appointments release];
68 [appointment release];
70 [aptFormatter release];
71 [aptTooltipFormatter release];
72 [privateAptFormatter release];
73 [privateAptTooltipFormatter release];
78 /* subclasses should override this */
79 - (void) configureFormatters
83 [aptFormatter setFullDetails];
84 [aptTooltipFormatter setTooltip];
85 [privateAptFormatter setPrivateDetails];
86 [privateAptTooltipFormatter setPrivateTooltip];
88 title = [self labelForKey: @"empty title"];
89 [aptFormatter setTitlePlaceholder: title];
90 [aptTooltipFormatter setTitlePlaceholder: title];
92 title = [self labelForKey: @"private appointment"];
93 [privateAptFormatter setPrivateTitle: title];
94 [privateAptTooltipFormatter setPrivateTitle: title];
97 - (NSArray *) filterAppointments:(NSArray *) _apts
99 NSMutableArray *filtered;
106 NSString *partmailsString;
111 if ([self shouldDisplayRejectedAppointments])
114 count = [_apts count];
115 filtered = [[[NSMutableArray alloc] initWithCapacity: count] autorelease];
116 email = [[context activeUser] primaryEmail];
118 for (i = 0; i < count; i++)
121 info = [_apts objectAtIndex: i];
122 partmailsString = [info objectForKey: @"partmails"];
123 if ([partmailsString isNotNull])
125 partmails = [partmailsString componentsSeparatedByString: @"\n"];
126 pCount = [partmails count];
127 for (p = 0; p < pCount; p++)
129 pEmail = [partmails objectAtIndex: p];
130 if ([pEmail isEqualToString: email])
132 partstates = [[info objectForKey: @"partstates"]
133 componentsSeparatedByString: @"\n"];
134 state = [partstates objectAtIndex: p];
135 if ([state intValue] == iCalPersonPartStatDeclined)
142 [filtered addObject: info];
151 - (void) setAppointments:(NSArray *) _apts
153 _apts = [self filterAppointments: _apts];
154 ASSIGN(appointments, _apts);
157 - (NSArray *) appointments
162 - (void) setAppointment:(id) _apt
164 ASSIGN (appointment, _apt);
167 // - (void) setAppointment:(id) _apt
169 // NSString *mailtoChunk;
170 // NSString *myEmail;
171 // NSString *partmails;
173 // ASSIGN(appointment, _apt);
175 // /* cache some info about apt for faster access */
177 // mailtoChunk = [_apt valueForKey: @"orgmail"];
178 // myEmail = [self emailForUser];
179 // if ([mailtoChunk rangeOfString: myEmail].length > 0)
181 // aptFlags.isMyApt = YES;
182 // aptFlags.canAccessApt = YES;
186 // aptFlags.isMyApt = NO;
188 // partmails = [_apt valueForKey: @"partmails"];
189 // if ([partmails rangeOfString: myEmail].length)
190 // aptFlags.canAccessApt = YES;
192 // aptFlags.canAccessApt
193 // = ([[_apt valueForKey: @"classification"] intValue]
194 // == iCalAccessPublic);
205 return aptFlags.isMyApt ? YES : NO;
208 - (BOOL) canAccessApt
210 return aptFlags.canAccessApt ? YES : NO;
213 - (BOOL) canNotAccessApt
215 return aptFlags.canAccessApt ? NO : YES;
218 - (NSDictionary *) aptTypeDict
222 - (NSString *) aptTypeLabel
226 - (NSString *) aptTypeIcon
231 - (SOGoAptFormatter *) aptFormatter
233 if (aptFlags.canAccessApt)
235 return privateAptFormatter;
238 - (SOGoAptFormatter *) aptTooltipFormatter
240 if (aptFlags.canAccessApt)
241 return aptTooltipFormatter;
242 return privateAptTooltipFormatter;
245 - (void) setTasks: (NSArray *) _tasks
247 ASSIGN(tasks, _tasks);
255 /* TODO: remove this */
256 - (NSString *) shortTextForApt
258 [self warnWithFormat: @"%s IS DEPRECATED!", __PRETTY_FUNCTION__];
259 if (![self canAccessApt])
261 return [[self aptFormatter] stringForObjectValue: appointment];
264 - (NSString *) shortTitleForApt
268 [self warnWithFormat: @"%s IS DEPRECATED!", __PRETTY_FUNCTION__];
270 if (![self canAccessApt])
272 title = [appointment valueForKey: @"title"];
273 if ([title length] > 12)
274 title = [[title substringToIndex: 11] stringByAppendingString: @"..."];
279 - (NSString *) tooltipForApt
281 [self warnWithFormat: @"%s IS DEPRECATED!", __PRETTY_FUNCTION__];
282 return [[self aptTooltipFormatter] stringForObjectValue: appointment
283 referenceDate: [self currentDay]];
286 - (NSString *) aptStyle
291 - (NSCalendarDate *) referenceDateForFormatter
293 return [self selectedDate];
296 - (NSCalendarDate *) thisMonth
298 return [self selectedDate];
301 - (NSCalendarDate *) nextMonth
303 NSCalendarDate *date = [self thisMonth];
304 return [date dateByAddingYears: 0 months: 1 days: 0
305 hours: 0 minutes: 0 seconds: 0];
308 - (NSCalendarDate *) prevMonth
310 NSCalendarDate *date = [self thisMonth];
311 return [date dateByAddingYears: 0 months:-1 days: 0
312 hours: 0 minutes: 0 seconds: 0];
315 - (NSString *) prevMonthAsString
317 return [self dateStringForDate: [self prevMonth]];
320 - (NSString *) nextMonthAsString
322 return [self dateStringForDate: [self nextMonth]];
325 /* current day related */
327 - (void) setCurrentDay:(NSCalendarDate *) _day
329 [_day setTimeZone: timeZone];
330 ASSIGN (currentDay, _day);
333 - (NSCalendarDate *) currentDay
338 - (NSString *) currentDayName
340 return [self localizedNameForDayOfWeek: [currentDay dayOfWeek]];
348 - (NSArray *) allDayApts
351 NSMutableArray *filtered;
357 apts = [self appointments];
358 count = [apts count];
359 filtered = [[NSMutableArray alloc] initWithCapacity: 3];
360 for (i = 0; i < count; i++)
365 apt = [apts objectAtIndex: i];
366 bv = [apt valueForKey: @"isallday"];
368 [filtered addObject: apt];
371 ASSIGN(allDayApts, filtered);
377 /* special appointments */
381 return [self hasHoldidayInfo] || [self hasAllDayApts];
384 - (BOOL) hasHoldidayInfo
386 return [self holidayInfo] != nil;
389 - (BOOL) hasAllDayApts
391 return [[self allDayApts] count] != 0;
397 - (BOOL) showFullNames
402 - (BOOL) showAMPMDates
407 - (unsigned) dayStartHour
412 - (unsigned) dayEndHour
417 - (BOOL) shouldDisplayWeekend
419 return shouldDisplayWeekend;
422 - (BOOL) shouldHideWeekend
424 return ![self shouldDisplayWeekend];
430 - (NSString *) appointmentViewURL
434 if (![(pkey = [[self appointment] valueForKey: @"uid"]) isNotNull])
437 return [[[self clientObject] baseURLForAptWithUID: [pkey stringValue]
438 inContext: [self context]]
439 stringByAppendingString: @"/view"];
444 - (NSCalendarDate *) startDate
446 return [self selectedDate];
449 - (NSCalendarDate *) endDate
451 return [[self startDate] tomorrow];
454 /* query parameters */
456 - (BOOL) shouldDisplayRejectedAppointments
460 bv = [self queryParameterForKey: @"dr"];
462 return [bv boolValue];
465 - (NSDictionary *) toggleShowRejectedAptsQueryParameters
467 NSMutableDictionary *qp;
470 shouldDisplay = ![self shouldDisplayRejectedAppointments];
471 qp = [[[self queryParameters] mutableCopy] autorelease];
472 [qp setObject: shouldDisplay ? @"1" : @"0" forKey: @"dr"];
476 - (NSString *) toggleShowRejectedAptsLabel
478 if (![self shouldDisplayRejectedAppointments])
479 return @"show_rejected_apts";
480 return @"hide_rejected_apts";
483 /* date selection & conversion */
485 - (NSDictionary *) _dateQueryParametersWithOffset: (int) daysOffset
487 NSCalendarDate *date;
489 date = [[self startDate] dateByAddingYears: 0 months: 0
491 hours: 0 minutes: 0 seconds: 0];
492 return [self queryParametersBySettingSelectedDate: date];
495 - (NSDictionary *) todayQueryParameters
497 return [self queryParametersBySettingSelectedDate: [NSCalendarDate date]];
500 - (NSDictionary *) currentDayQueryParameters
502 return [self queryParametersBySettingSelectedDate: currentDay];
507 - (NSString *) _userFolderURI
513 ctx = [self context];
514 obj = [[ctx objectTraversalStack] objectAtIndex: 1];
515 url = [NSURL URLWithString: [obj baseURLInContext: ctx]];
516 return [[url path] stringByUnescapingURL];
519 - (id) redirectForUIDsAction
521 NSMutableString *uri;
522 NSString *uidsString, *loc, *prevMethod, *userFolderID;
523 id <WOActionResults> r;
527 uidsString = [self queryParameterForKey: @"userUIDString"];
528 uidsString = [uidsString stringByTrimmingSpaces];
529 [self setQueryParameter: nil forKey: @"userUIDString"];
531 prevMethod = [self queryParameterForKey: @"previousMethod"];
532 if (prevMethod == nil)
535 uri = [[NSMutableString alloc] initWithString: [self _userFolderURI]];
536 /* if we have more than one entry, use groups - otherwise don't */
537 useGroups = [uidsString rangeOfString: @","].length > 0;
538 userFolderID = [uri lastPathComponent];
543 uids = [uidsString componentsSeparatedByString: @","];
544 /* guarantee that our id is the first */
545 if (((index = [uids indexOfObject: userFolderID]) != NSNotFound)
548 uids = [[uids mutableCopy] autorelease];
549 [(NSMutableArray *) uids removeObjectAtIndex: index];
550 [(NSMutableArray *) uids insertObject: userFolderID atIndex: 0];
551 uidsString = [uids componentsJoinedByString: @","];
553 [uri appendString: @"Groups/_custom_"];
554 [uri appendString: uidsString];
555 [uri appendString: @"/"];
556 NSLog (@"Group URI = '%@'", uri);
560 /* check if lastPathComponent is the base that we want to have */
561 if ((([uidsString length] != 0)
562 && (![userFolderID isEqualToString: uidsString])))
566 /* uri ends with an '/', so we have to adjust the range a little */
567 r = NSMakeRange(0, [uri length] - 1);
568 r = [uri rangeOfString: @"/"
569 options: NSBackwardsSearch
571 r = NSMakeRange(r.location + 1, [uri length] - r.location - 2);
572 [uri replaceCharactersInRange: r withString: uidsString];
575 [uri appendString: @"Calendar/"];
576 [uri appendString: prevMethod];
579 NSLog(@"%s redirect uri:%@",
583 loc = [self completeHrefForMethod: uri]; /* this might return uri! */
584 r = [self redirectToLocation: loc];
589 @end /* UIxCalView */