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 {
231 - (NSCalendarDate *)referenceDateForFormatter {
232 return [self selectedDate];
235 - (NSCalendarDate *)thisMonth {
236 return [self selectedDate];
239 - (NSCalendarDate *)nextMonth {
240 NSCalendarDate *date = [self thisMonth];
241 return [date dateByAddingYears:0 months:1 days:0
242 hours:0 minutes:0 seconds:0];
246 /* current day related */
248 - (void)setCurrentDay:(NSCalendarDate *)_day {
249 [_day setTimeZone:[self viewTimeZone]];
250 ASSIGN(self->currentDay, _day);
252 - (NSCalendarDate *)currentDay {
253 return self->currentDay;
256 - (NSString *)currentDayName {
257 return [self localizedNameForDayOfWeek:[self->currentDay dayOfWeek]];
264 - (NSArray *)allDayApts {
266 NSMutableArray *filtered;
269 if (self->allDayApts)
270 return self->allDayApts;
272 apts = [self appointments];
273 count = [apts count];
274 filtered = [[NSMutableArray alloc] initWithCapacity:3];
275 for (i = 0; i < count; i++) {
279 apt = [apts objectAtIndex:i];
280 bv = [apt valueForKey:@"isallday"];
282 [filtered addObject:apt];
285 ASSIGN(self->allDayApts, filtered);
287 return self->allDayApts;
291 /* special appointments */
294 return [self hasHoldidayInfo] || [self hasAllDayApts];
297 - (BOOL)hasHoldidayInfo {
298 return [self holidayInfo] != nil;
301 - (BOOL)hasAllDayApts {
302 return [[self allDayApts] count] != 0;
308 - (BOOL)showFullNames {
312 - (BOOL)showAMPMDates {
316 - (unsigned)dayStartHour {
320 - (unsigned)dayEndHour {
324 - (BOOL)shouldDisplayWeekend {
325 return shouldDisplayWeekend;
328 - (BOOL)shouldHideWeekend {
329 return ![self shouldDisplayWeekend];
335 - (NSString *)appointmentViewURL {
338 if (![(pkey = [[self appointment] valueForKey:@"uid"]) isNotNull])
341 return [[[self clientObject] baseURLForAptWithUID:[pkey stringValue]
342 inContext:[self context]]
343 stringByAppendingString:@"/view"];
348 - (NSCalendarDate *)startDate {
349 return [self selectedDate];
351 - (NSCalendarDate *)endDate {
352 return [[self startDate] tomorrow];
355 - (NSArray *)fetchCoreInfos {
356 if (!self->appointments) {
358 NSCalendarDate *sd, *ed;
360 folder = [self clientObject];
361 sd = [self startDate];
363 [self setAppointments:[folder fetchOverviewInfosFrom:sd to:ed]];
365 return self->appointments;
368 /* query parameters */
370 - (BOOL)shouldDisplayRejectedAppointments {
373 bv = [[[self context] request] formValueForKey:@"dr"];
375 return [bv boolValue];
378 - (NSDictionary *)toggleShowRejectedAptsQueryParameters {
379 NSMutableDictionary *qp;
382 shouldDisplay = ![self shouldDisplayRejectedAppointments];
383 qp = [[[self queryParameters] mutableCopy] autorelease];
384 [qp setObject:shouldDisplay ? @"1" : @"0" forKey:@"dr"];
388 - (NSString *)toggleShowRejectedAptsLabel {
389 if (![self shouldDisplayRejectedAppointments])
390 return @"show_rejected_apts";
391 return @"hide_rejected_apts";
394 /* date selection & conversion */
396 - (NSDictionary *)todayQueryParameters {
397 NSCalendarDate *date;
399 date = [NSCalendarDate date]; /* today */
400 return [self queryParametersBySettingSelectedDate:date];
403 - (NSDictionary *)currentDayQueryParameters {
404 return [self queryParametersBySettingSelectedDate:self->currentDay];
409 - (NSString *)formattedCalendarUIDs {
410 return [[[self clientObject] calendarUIDs]
411 componentsJoinedByString:@", "];
416 - (NSString *)_userFolderURI {
421 ctx = [self context];
422 obj = [[ctx objectTraversalStack] objectAtIndex:1];
423 url = [NSURL URLWithString:[obj baseURLInContext:ctx]];
424 return [[url path] stringByUnescapingURL];
427 - (id)redirectForUIDsAction {
428 NSMutableString *uri;
429 NSString *uidsString, *loc, *prevMethod, *userFolderID;
431 id <WOActionResults> r;
435 req = [[self context] request];
437 uidsString = [req formValueForKey:@"userUIDString"];
438 uidsString = [uidsString stringByTrimmingWhiteSpaces];
440 prevMethod = [req formValueForKey:@"previousMethod"];
441 if(prevMethod == nil)
444 uri = [[NSMutableString alloc] initWithString:[self _userFolderURI]];
445 /* if we have more than one entry, use groups - otherwise don't */
446 useGroups = [uidsString rangeOfString:@","].length > 0;
447 userFolderID = [uri lastPathComponent];
451 uids = [uidsString componentsSeparatedByString:@","];
452 /* guarantee that our id is the first */
453 if(((index = [uids indexOfObject:userFolderID]) != NSNotFound) &&
455 uids = [[uids mutableCopy] autorelease];
456 [(NSMutableArray *)uids removeObjectAtIndex:index];
457 [(NSMutableArray *)uids insertObject:userFolderID atIndex:0];
458 uidsString = [uids componentsJoinedByString:@","];
460 [uri appendString:@"Groups/_custom_"];
461 [uri appendString:uidsString];
462 [uri appendString:@"/"];
465 /* check if lastPathComponent is the base that we want to have */
466 if((([uidsString length] != 0) &&
467 (![userFolderID isEqualToString:uidsString]))) {
470 /* uri ends with an '/', so we have to adjust the range a little */
471 r = NSMakeRange(0, [uri length] - 1);
472 r = [uri rangeOfString:@"/"
473 options:NSBackwardsSearch
475 r = NSMakeRange(r.location + 1, [uri length] - r.location - 2);
476 [uri replaceCharactersInRange:r withString:uidsString];
479 [uri appendString:@"Calendar/"];
480 [uri appendString:prevMethod];
483 NSLog(@"%s redirect uri:%@",
487 loc = [self completeHrefForMethod:uri]; /* this might return uri! */
488 r = [self redirectToLocation:loc];
493 @end /* UIxCalView */