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+Agenor.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"];
48 tz = [[self clientObject] userTimeZone];
50 = [[SOGoAptFormatter alloc] initWithDisplayTimeZone: tz];
52 = [[SOGoAptFormatter alloc] initWithDisplayTimeZone: tz];
54 = [[SOGoAptFormatter alloc] initWithDisplayTimeZone: tz];
55 privateAptTooltipFormatter
56 = [[SOGoAptFormatter alloc] initWithDisplayTimeZone: tz];
57 [self configureFormatters];
58 componentsData = [NSMutableDictionary new];
66 [componentsData release];
67 [appointments release];
69 [appointment release];
71 [aptFormatter release];
72 [aptTooltipFormatter release];
73 [privateAptFormatter release];
74 [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 = [self emailForUser];
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 NSString *mailtoChunk;
167 ASSIGN(appointment, _apt);
169 /* cache some info about apt for faster access */
171 mailtoChunk = [_apt valueForKey: @"orgmail"];
172 myEmail = [self emailForUser];
173 if ([mailtoChunk rangeOfString: myEmail].length > 0)
175 aptFlags.isMyApt = YES;
176 aptFlags.canAccessApt = YES;
182 aptFlags.isMyApt = NO;
184 partmails = [_apt valueForKey: @"partmails"];
185 if ([partmails rangeOfString: myEmail].length)
186 aptFlags.canAccessApt = YES;
188 aptFlags.canAccessApt
189 = ([[_apt valueForKey: @"classification"] intValue]
190 == iCalAccessPublic);
194 - (void) setTasks: (NSArray *) _tasks
196 ASSIGN(tasks, _tasks);
211 return aptFlags.isMyApt ? YES : NO;
214 - (BOOL) canAccessApt
216 return aptFlags.canAccessApt ? YES : NO;
219 - (BOOL) canNotAccessApt
221 return aptFlags.canAccessApt ? NO : YES;
224 - (NSDictionary *) aptTypeDict
228 - (NSString *) aptTypeLabel
232 - (NSString *) aptTypeIcon
237 - (SOGoAptFormatter *) aptFormatter
239 if (aptFlags.canAccessApt)
241 return privateAptFormatter;
244 - (SOGoAptFormatter *) aptTooltipFormatter
246 if (aptFlags.canAccessApt)
247 return aptTooltipFormatter;
248 return privateAptTooltipFormatter;
251 /* TODO: remove this */
252 - (NSString *) shortTextForApt
254 [self warnWithFormat: @"%s IS DEPRECATED!", __PRETTY_FUNCTION__];
255 if (![self canAccessApt])
257 return [[self aptFormatter] stringForObjectValue: appointment];
260 - (NSString *) shortTitleForApt
264 [self warnWithFormat: @"%s IS DEPRECATED!", __PRETTY_FUNCTION__];
266 if (![self canAccessApt])
268 title = [appointment valueForKey: @"title"];
269 if ([title length] > 12)
270 title = [[title substringToIndex: 11] stringByAppendingString: @"..."];
275 - (NSString *) tooltipForApt
277 [self warnWithFormat: @"%s IS DEPRECATED!", __PRETTY_FUNCTION__];
278 return [[self aptTooltipFormatter] stringForObjectValue: appointment
279 referenceDate: [self currentDay]];
282 - (NSString *) aptStyle
287 - (NSCalendarDate *) referenceDateForFormatter
289 return [self selectedDate];
292 - (NSCalendarDate *) thisMonth
294 return [self selectedDate];
297 - (NSCalendarDate *) nextMonth
299 NSCalendarDate *date = [self thisMonth];
300 return [date dateByAddingYears: 0 months: 1 days: 0
301 hours: 0 minutes: 0 seconds: 0];
304 - (NSCalendarDate *) prevMonth
306 NSCalendarDate *date = [self thisMonth];
307 return [date dateByAddingYears: 0 months:-1 days: 0
308 hours: 0 minutes: 0 seconds: 0];
311 - (NSString *) prevMonthAsString
313 return [self dateStringForDate: [self prevMonth]];
316 - (NSString *) nextMonthAsString
318 return [self dateStringForDate: [self nextMonth]];
321 /* current day related */
323 - (void) setCurrentDay:(NSCalendarDate *) _day
325 [_day setTimeZone: [[self clientObject] userTimeZone]];
326 ASSIGN(currentDay, _day);
329 - (NSCalendarDate *) currentDay
334 - (NSString *) currentDayName
336 return [self localizedNameForDayOfWeek: [currentDay dayOfWeek]];
344 - (NSArray *) allDayApts
347 NSMutableArray *filtered;
353 apts = [self appointments];
354 count = [apts count];
355 filtered = [[NSMutableArray alloc] initWithCapacity: 3];
356 for (i = 0; i < count; i++)
361 apt = [apts objectAtIndex: i];
362 bv = [apt valueForKey: @"isallday"];
364 [filtered addObject: apt];
367 ASSIGN(allDayApts, filtered);
373 /* special appointments */
377 return [self hasHoldidayInfo] || [self hasAllDayApts];
380 - (BOOL) hasHoldidayInfo
382 return [self holidayInfo] != nil;
385 - (BOOL) hasAllDayApts
387 return [[self allDayApts] count] != 0;
393 - (BOOL) showFullNames
398 - (BOOL) showAMPMDates
403 - (unsigned) dayStartHour
408 - (unsigned) dayEndHour
413 - (BOOL) shouldDisplayWeekend
415 return shouldDisplayWeekend;
418 - (BOOL) shouldHideWeekend
420 return ![self shouldDisplayWeekend];
426 - (NSString *) appointmentViewURL
430 if (![(pkey = [[self appointment] valueForKey: @"uid"]) isNotNull])
433 return [[[self clientObject] baseURLForAptWithUID: [pkey stringValue]
434 inContext: [self context]]
435 stringByAppendingString: @"/view"];
440 - (NSCalendarDate *) startDate
442 return [self selectedDate];
445 - (NSCalendarDate *) endDate
447 return [[self startDate] tomorrow];
450 - (SOGoAppointmentFolder *) _aptFolder: (NSString *) folder
451 withClientObject: (SOGoAppointmentFolder *) clientObject
453 SOGoAppointmentFolder *aptFolder;
454 NSArray *folderParts;
456 if ([folder isEqualToString: @"/"])
457 aptFolder = clientObject;
460 folderParts = [folder componentsSeparatedByString: @":"];
462 = [clientObject lookupCalendarFolderForUID:
463 [folderParts objectAtIndex: 0]];
469 - (NSArray *) _activeCalendarFolders
471 NSMutableArray *activeFolders;
472 NSEnumerator *folders;
473 NSDictionary *currentFolderDict;
474 SOGoAppointmentFolder *currentFolder, *clientObject;
476 activeFolders = [NSMutableArray new];
477 [activeFolders autorelease];
479 clientObject = [self clientObject];
481 folders = [[clientObject calendarFoldersInContext: context]
483 currentFolderDict = [folders nextObject];
484 while (currentFolderDict)
486 if ([[currentFolderDict objectForKey: @"active"] boolValue])
489 = [self _aptFolder: [currentFolderDict objectForKey: @"folder"]
490 withClientObject: clientObject];
491 [activeFolders addObject: currentFolder];
494 currentFolderDict = [folders nextObject];
497 return activeFolders;
500 - (NSArray *) _fetchCoreInfosForComponent: (NSString *) component
502 NSArray *currentInfos;
503 NSMutableArray *infos;
504 NSEnumerator *folders;
505 SOGoAppointmentFolder *currentFolder;
507 infos = [componentsData objectForKey: component];
510 infos = [NSMutableArray array];
511 folders = [[self _activeCalendarFolders] objectEnumerator];
512 currentFolder = [folders nextObject];
513 while (currentFolder)
515 currentInfos = [currentFolder fetchCoreInfosFrom: [[self startDate] beginOfDay]
516 to: [[self endDate] endOfDay]
517 component: component];
518 [currentInfos makeObjectsPerform: @selector (setObject:forKey:)
519 withObject: [currentFolder ownerInContext: nil]
520 withObject: @"owner"];
521 [infos addObjectsFromArray: currentInfos];
522 currentFolder = [folders nextObject];
524 [componentsData setObject: infos forKey: component];
530 - (NSArray *) fetchCoreAppointmentsInfos
533 [self setAppointments: [self _fetchCoreInfosForComponent: @"vevent"]];
538 - (NSArray *) fetchCoreTasksInfos
541 [self setTasks: [self _fetchCoreInfosForComponent: @"vtodo"]];
546 /* query parameters */
548 - (BOOL) shouldDisplayRejectedAppointments
552 bv = [self queryParameterForKey: @"dr"];
554 return [bv boolValue];
557 - (NSDictionary *) toggleShowRejectedAptsQueryParameters
559 NSMutableDictionary *qp;
562 shouldDisplay = ![self shouldDisplayRejectedAppointments];
563 qp = [[[self queryParameters] mutableCopy] autorelease];
564 [qp setObject: shouldDisplay ? @"1" : @"0" forKey: @"dr"];
568 - (NSString *) toggleShowRejectedAptsLabel
570 if (![self shouldDisplayRejectedAppointments])
571 return @"show_rejected_apts";
572 return @"hide_rejected_apts";
575 /* date selection & conversion */
577 - (NSDictionary *) _dateQueryParametersWithOffset: (int) daysOffset
579 NSCalendarDate *date;
581 date = [[self startDate] dateByAddingYears: 0 months: 0
583 hours: 0 minutes: 0 seconds: 0];
584 return [self queryParametersBySettingSelectedDate: date];
587 - (NSDictionary *) todayQueryParameters
589 return [self queryParametersBySettingSelectedDate: [NSCalendarDate date]];
592 - (NSDictionary *) currentDayQueryParameters
594 return [self queryParametersBySettingSelectedDate: currentDay];
599 - (NSString *) _userFolderURI
605 ctx = [self context];
606 obj = [[ctx objectTraversalStack] objectAtIndex: 1];
607 url = [NSURL URLWithString: [obj baseURLInContext: ctx]];
608 return [[url path] stringByUnescapingURL];
611 - (id) redirectForUIDsAction
613 NSMutableString *uri;
614 NSString *uidsString, *loc, *prevMethod, *userFolderID;
615 id <WOActionResults> r;
619 uidsString = [self queryParameterForKey: @"userUIDString"];
620 uidsString = [uidsString stringByTrimmingSpaces];
621 [self setQueryParameter: nil forKey: @"userUIDString"];
623 prevMethod = [self queryParameterForKey: @"previousMethod"];
624 if (prevMethod == nil)
627 uri = [[NSMutableString alloc] initWithString: [self _userFolderURI]];
628 /* if we have more than one entry, use groups - otherwise don't */
629 useGroups = [uidsString rangeOfString: @","].length > 0;
630 userFolderID = [uri lastPathComponent];
635 uids = [uidsString componentsSeparatedByString: @","];
636 /* guarantee that our id is the first */
637 if (((index = [uids indexOfObject: userFolderID]) != NSNotFound)
640 uids = [[uids mutableCopy] autorelease];
641 [(NSMutableArray *) uids removeObjectAtIndex: index];
642 [(NSMutableArray *) uids insertObject: userFolderID atIndex: 0];
643 uidsString = [uids componentsJoinedByString: @","];
645 [uri appendString: @"Groups/_custom_"];
646 [uri appendString: uidsString];
647 [uri appendString: @"/"];
648 NSLog (@"Group URI = '%@'", uri);
652 /* check if lastPathComponent is the base that we want to have */
653 if ((([uidsString length] != 0)
654 && (![userFolderID isEqualToString: uidsString])))
658 /* uri ends with an '/', so we have to adjust the range a little */
659 r = NSMakeRange(0, [uri length] - 1);
660 r = [uri rangeOfString: @"/"
661 options: NSBackwardsSearch
663 r = NSMakeRange(r.location + 1, [uri length] - r.location - 2);
664 [uri replaceCharactersInRange: r withString: uidsString];
667 [uri appendString: @"Calendar/"];
668 [uri appendString: prevMethod];
671 NSLog(@"%s redirect uri:%@",
675 loc = [self completeHrefForMethod: uri]; /* this might return uri! */
676 r = [self redirectToLocation: loc];
681 @end /* UIxCalView */