3 #include "UIxCalView.h"
5 //#include <OGoContentStore/OCSFolder.h>
6 #include "SoObjects/Appointments/SOGoAppointmentFolder.h"
7 #include <NGObjWeb/SoUser.h>
8 #include <SOGoUI/SOGoAptFormatter.h>
9 #include <NGExtensions/NGCalendarDateRange.h>
10 #include <NGiCal/NGiCal.h>
11 #include "UIxComponent+Agenor.h"
13 @interface UIxCalView (PrivateAPI)
14 - (NSString *)_userFolderURI;
17 @implementation UIxCalView
19 static BOOL shouldDisplayWeekend = NO;
22 static BOOL didInit = NO;
27 ud = [NSUserDefaults standardUserDefaults];
28 shouldDisplayWeekend = [ud boolForKey:@"SOGoShouldDisplayWeekend"];
36 tz = [self viewTimeZone];
38 [[SOGoAptFormatter alloc] initWithDisplayTimeZone:tz];
39 self->aptTooltipFormatter =
40 [[SOGoAptFormatter alloc] initWithDisplayTimeZone:tz];
41 self->privateAptFormatter =
42 [[SOGoAptFormatter alloc] initWithDisplayTimeZone:tz];
43 self->privateAptTooltipFormatter =
44 [[SOGoAptFormatter alloc] initWithDisplayTimeZone:tz];
45 [self configureFormatters];
51 [self->appointments release];
52 [self->allDayApts release];
53 [self->appointment release];
54 [self->currentDay release];
55 [self->aptFormatter release];
56 [self->aptTooltipFormatter release];
57 [self->privateAptFormatter release];
58 [self->privateAptTooltipFormatter release];
62 /* subclasses should override this */
63 - (void)configureFormatters {
66 [self->aptFormatter setFullDetails];
67 [self->aptTooltipFormatter setTooltip];
68 [self->privateAptFormatter setPrivateDetails];
69 [self->privateAptTooltipFormatter setPrivateTooltip];
71 title = [self labelForKey:@"empty title"];
72 [self->aptFormatter setTitlePlaceholder:title];
73 [self->aptTooltipFormatter setTitlePlaceholder:title];
75 title = [self labelForKey:@"private appointment"];
76 [self->privateAptFormatter setPrivateTitle:title];
77 [self->privateAptTooltipFormatter setPrivateTitle:title];
80 - (NSArray *)filterAppointments:(NSArray *)_apts {
81 NSMutableArray *filtered;
85 count = [_apts count];
86 if (!count) return _apts;
87 if ([self shouldDisplayRejectedAppointments]) return _apts;
89 filtered = [[[NSMutableArray alloc] initWithCapacity:count] autorelease];
90 email = [self emailForUser];
92 for (i = 0; i < count; i++) {
99 info = [_apts objectAtIndex:i];
100 partmails = [[info objectForKey:@"partmails"]
101 componentsSeparatedByString:@"\n"];
102 pCount = [partmails count];
103 for (p = 0; p < pCount; p++) {
106 pEmail = [partmails objectAtIndex:p];
107 if ([pEmail isEqualToString:email]) {
111 partstates = [[info objectForKey:@"partstates"]
112 componentsSeparatedByString:@"\n"];
113 state = [partstates objectAtIndex:p];
114 if ([state intValue] != iCalPersonPartStatDeclined)
120 [filtered addObject:info];
127 - (void)setAppointments:(NSArray *)_apts {
128 _apts = [self filterAppointments:_apts];
129 ASSIGN(self->appointments, _apts);
131 - (NSArray *)appointments {
132 return self->appointments;
135 - (void)setAppointment:(id)_apt {
136 NSString *mailtoChunk;
139 ASSIGN(self->appointment, _apt);
141 /* cache some info about apt for faster access */
143 mailtoChunk = [_apt valueForKey:@"orgmail"];
144 myEmail = [self emailForUser];
145 if ([mailtoChunk rangeOfString:myEmail].length > 0) {
146 self->aptFlags.isMyApt = YES;
147 self->aptFlags.canAccessApt = YES;
152 self->aptFlags.isMyApt = NO;
154 partmails = [_apt valueForKey:@"partmails"];
155 if ([partmails rangeOfString:myEmail].length)
156 self->aptFlags.canAccessApt = YES;
158 self->aptFlags.canAccessApt = [[_apt valueForKey:@"ispublic"] boolValue];
162 return self->appointment;
166 return self->aptFlags.isMyApt ? YES : NO;
169 - (BOOL)canAccessApt {
170 return self->aptFlags.canAccessApt ? YES : NO;
173 - (BOOL)canNotAccessApt {
174 return self->aptFlags.canAccessApt ? NO : YES;
177 - (NSDictionary *)aptTypeDict {
180 - (NSString *)aptTypeLabel {
183 - (NSString *)aptTypeIcon {
187 - (SOGoAptFormatter *)aptFormatter {
188 if(self->aptFlags.canAccessApt)
189 return self->aptFormatter;
190 return self->privateAptFormatter;
193 - (SOGoAptFormatter *)aptTooltipFormatter {
194 if(self->aptFlags.canAccessApt)
195 return self->aptTooltipFormatter;
196 return self->privateAptTooltipFormatter;
199 /* TODO: remove this */
200 - (NSString *)shortTextForApt {
201 [self warnWithFormat:@"%s IS DEPRECATED!", __PRETTY_FUNCTION__];
202 if (![self canAccessApt])
204 return [[self aptFormatter] stringForObjectValue:self->appointment];
207 - (NSString *)shortTitleForApt {
210 [self warnWithFormat:@"%s IS DEPRECATED!", __PRETTY_FUNCTION__];
212 if (![self canAccessApt])
214 title = [self->appointment valueForKey:@"title"];
215 if ([title length] > 12)
216 title = [[title substringToIndex:11] stringByAppendingString:@"..."];
221 - (NSString *)tooltipForApt {
222 [self warnWithFormat:@"%s IS DEPRECATED!", __PRETTY_FUNCTION__];
223 return [[self aptTooltipFormatter] stringForObjectValue:self->appointment
224 referenceDate:[self currentDay]];
227 - (NSString *)aptStyle {
233 - (NSCalendarDate *)referenceDateForFormatter {
234 return [self selectedDate];
237 - (NSCalendarDate *)thisMonth {
238 return [self selectedDate];
241 - (NSCalendarDate *)nextMonth {
242 NSCalendarDate *date = [self thisMonth];
243 return [date dateByAddingYears:0 months:1 days:0
244 hours:0 minutes:0 seconds:0];
248 /* current day related */
250 - (void)setCurrentDay:(NSCalendarDate *)_day {
251 [_day setTimeZone:[self viewTimeZone]];
252 ASSIGN(self->currentDay, _day);
254 - (NSCalendarDate *)currentDay {
255 return self->currentDay;
258 - (NSString *)currentDayName {
259 return [self localizedNameForDayOfWeek:[self->currentDay dayOfWeek]];
266 - (NSArray *)allDayApts {
268 NSMutableArray *filtered;
271 if (self->allDayApts)
272 return self->allDayApts;
274 apts = [self appointments];
275 count = [apts count];
276 filtered = [[NSMutableArray alloc] initWithCapacity:3];
277 for (i = 0; i < count; i++) {
281 apt = [apts objectAtIndex:i];
282 bv = [apt valueForKey:@"isallday"];
284 [filtered addObject:apt];
287 ASSIGN(self->allDayApts, filtered);
289 return self->allDayApts;
293 /* special appointments */
296 return [self hasHoldidayInfo] || [self hasAllDayApts];
299 - (BOOL)hasHoldidayInfo {
300 return [self holidayInfo] != nil;
303 - (BOOL)hasAllDayApts {
304 return [[self allDayApts] count] != 0;
310 - (BOOL)showFullNames {
314 - (BOOL)showAMPMDates {
318 - (unsigned)dayStartHour {
322 - (unsigned)dayEndHour {
326 - (BOOL)shouldDisplayWeekend {
327 return shouldDisplayWeekend;
330 - (BOOL)shouldHideWeekend {
331 return ![self shouldDisplayWeekend];
337 - (NSString *)appointmentViewURL {
340 if (![(pkey = [[self appointment] valueForKey:@"uid"]) isNotNull])
343 return [[[self clientObject] baseURLForAptWithUID:[pkey stringValue]
344 inContext:[self context]]
345 stringByAppendingString:@"/view"];
350 - (NSCalendarDate *)startDate {
351 return [self selectedDate];
353 - (NSCalendarDate *)endDate {
354 return [[self startDate] tomorrow];
357 - (NSArray *)fetchCoreInfos {
358 if (!self->appointments) {
360 NSCalendarDate *sd, *ed;
362 folder = [self clientObject];
363 sd = [self startDate];
365 [self setAppointments:[folder fetchOverviewInfosFrom:sd to:ed]];
367 return self->appointments;
370 /* query parameters */
372 - (BOOL)shouldDisplayRejectedAppointments {
375 bv = [[[self context] request] formValueForKey:@"dr"];
377 return [bv boolValue];
380 - (NSDictionary *)toggleShowRejectedAptsQueryParameters {
381 NSMutableDictionary *qp;
384 shouldDisplay = ![self shouldDisplayRejectedAppointments];
385 qp = [[[self queryParameters] mutableCopy] autorelease];
386 [qp setObject:shouldDisplay ? @"1" : @"0" forKey:@"dr"];
390 - (NSString *)toggleShowRejectedAptsLabel {
391 if (![self shouldDisplayRejectedAppointments])
392 return @"show_rejected_apts";
393 return @"hide_rejected_apts";
396 /* date selection & conversion */
398 - (NSDictionary *)todayQueryParameters {
399 NSCalendarDate *date;
401 date = [NSCalendarDate date]; /* today */
402 return [self queryParametersBySettingSelectedDate:date];
405 - (NSDictionary *)currentDayQueryParameters {
406 return [self queryParametersBySettingSelectedDate:self->currentDay];
411 - (NSString *)formattedCalendarUIDs {
412 return [[[self clientObject] calendarUIDs]
413 componentsJoinedByString:@", "];
418 - (NSString *)_userFolderURI {
423 ctx = [self context];
424 obj = [[ctx objectTraversalStack] objectAtIndex:1];
425 url = [NSURL URLWithString:[obj baseURLInContext:ctx]];
426 return [[url path] stringByUnescapingURL];
429 - (id)redirectForUIDsAction {
430 NSMutableString *uri;
431 NSString *uidsString, *loc, *prevMethod, *userFolderID;
433 id <WOActionResults> r;
437 req = [[self context] request];
439 uidsString = [req formValueForKey:@"anaisUIDString"];
440 uidsString = [uidsString stringByTrimmingWhiteSpaces];
442 prevMethod = [req formValueForKey:@"previousMethod"];
443 if(prevMethod == nil)
446 uri = [[NSMutableString alloc] initWithString:[self _userFolderURI]];
447 /* if we have more than one entry, use groups - otherwise don't */
448 useGroups = [uidsString rangeOfString:@","].length > 0;
449 userFolderID = [uri lastPathComponent];
453 uids = [uidsString componentsSeparatedByString:@","];
454 /* guarantee that our id is the first */
455 if(((index = [uids indexOfObject:userFolderID]) != NSNotFound) &&
457 uids = [[uids mutableCopy] autorelease];
458 [(NSMutableArray *)uids removeObjectAtIndex:index];
459 [(NSMutableArray *)uids insertObject:userFolderID atIndex:0];
460 uidsString = [uids componentsJoinedByString:@","];
462 [uri appendString:@"Groups/_custom_"];
463 [uri appendString:uidsString];
464 [uri appendString:@"/"];
467 /* check if lastPathComponent is the base that we want to have */
468 if((([uidsString length] != 0) &&
469 (![userFolderID isEqualToString:uidsString]))) {
472 /* uri ends with an '/', so we have to adjust the range a little */
473 r = NSMakeRange(0, [uri length] - 1);
474 r = [uri rangeOfString:@"/"
475 options:NSBackwardsSearch
477 r = NSMakeRange(r.location + 1, [uri length] - r.location - 2);
478 [uri replaceCharactersInRange:r withString:uidsString];
481 [uri appendString:@"Calendar/"];
482 [uri appendString:prevMethod];
485 NSLog(@"%s redirect uri:%@",
489 loc = [self completeHrefForMethod:uri]; /* this might return uri! */
490 r = [self redirectToLocation:loc];
495 @end /* UIxCalView */