1 /* UIxCalListingActions.m - this file is part of SOGo
3 * Copyright (C) 2006 Inverse groupe conseil
5 * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
7 * This file is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
12 * This file is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; see the file COPYING. If not, write to
19 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
23 #import <Foundation/NSArray.h>
24 #import <Foundation/NSDictionary.h>
25 #import <Foundation/NSEnumerator.h>
26 #import <Foundation/NSNull.h>
27 #import <Foundation/NSString.h>
28 #import <Foundation/NSTimeZone.h>
29 #import <Foundation/NSValue.h>
31 #import <NGObjWeb/WOContext.h>
32 #import <NGObjWeb/WOContext+SoObjects.h>
33 #import <NGObjWeb/WORequest.h>
34 #import <NGObjWeb/WOResponse.h>
35 #import <NGExtensions/NSCalendarDate+misc.h>
37 #import <SoObjects/SOGo/SOGoUser.h>
38 #import <SoObjects/SOGo/SOGoDateFormatter.h>
39 #import <SoObjects/SOGo/NSCalendarDate+SOGo.h>
40 #import <SoObjects/SOGo/NSArray+Utilities.h>
41 #import <SoObjects/SOGo/NSObject+Utilities.h>
42 #import <SoObjects/Appointments/SOGoAppointmentFolder.h>
43 #import <SoObjects/Appointments/SOGoAppointmentFolders.h>
45 #import <UI/Common/WODirectAction+SOGo.h>
47 #import "NSArray+Scheduler.h"
49 #import "UIxCalListingActions.h"
51 @implementation UIxCalListingActions
53 - (id) initWithRequest: (WORequest *) newRequest
57 if ((self = [super initWithRequest: newRequest]))
59 componentsData = [NSMutableDictionary new];
62 ASSIGN (request, newRequest);
63 user = [[self context] activeUser];
64 dateFormatter = [user dateFormatterInContext: context];
65 ASSIGN (userTimeZone, [user timeZone]);
73 [dateFormatter release];
75 [componentsData release];
78 [userTimeZone release];
82 - (void) _setupDatesWithPopup: (NSString *) popupValue
83 andUserTZ: (NSTimeZone *) userTZ
85 NSCalendarDate *newDate;
88 if ([popupValue isEqualToString: @"view_today"])
90 newDate = [NSCalendarDate calendarDate];
91 [newDate setTimeZone: userTZ];
92 startDate = [newDate beginOfDay];
93 endDate = [newDate endOfDay];
95 else if ([popupValue isEqualToString: @"view_all"])
100 else if ([popupValue isEqualToString: @"view_next7"])
102 newDate = [NSCalendarDate calendarDate];
103 [newDate setTimeZone: userTZ];
104 startDate = [newDate beginOfDay];
105 endDate = [[startDate dateByAddingYears: 0 months: 0 days: 6] endOfDay];
107 else if ([popupValue isEqualToString: @"view_next14"])
109 newDate = [NSCalendarDate calendarDate];
110 [newDate setTimeZone: userTZ];
111 startDate = [newDate beginOfDay];
112 endDate = [[startDate dateByAddingYears: 0 months: 0 days: 13] endOfDay];
114 else if ([popupValue isEqualToString: @"view_next31"])
116 newDate = [NSCalendarDate calendarDate];
117 [newDate setTimeZone: userTZ];
118 startDate = [newDate beginOfDay];
119 endDate = [[startDate dateByAddingYears: 0 months: 0 days: 30] endOfDay];
121 else if ([popupValue isEqualToString: @"view_thismonth"])
123 newDate = [NSCalendarDate calendarDate];
124 [newDate setTimeZone: userTZ];
125 startDate = [[newDate firstDayOfMonth] beginOfDay];
126 endDate = [[newDate lastDayOfMonth] endOfDay];
128 else if ([popupValue isEqualToString: @"view_future"])
130 newDate = [NSCalendarDate calendarDate];
131 [newDate setTimeZone: userTZ];
132 startDate = [newDate beginOfDay];
133 endDate = [NSCalendarDate distantFuture];
135 else if ([popupValue isEqualToString: @"view_selectedday"])
137 param = [request formValueForKey: @"day"];
138 if ([param length] > 0)
139 startDate = [[NSCalendarDate dateFromShortDateString: param
140 andShortTimeString: nil
141 inTimeZone: userTZ] beginOfDay];
144 newDate = [NSCalendarDate calendarDate];
145 [newDate setTimeZone: userTZ];
146 startDate = [newDate beginOfDay];
148 endDate = [startDate endOfDay];
152 - (void) _setupContext
158 user = [context activeUser];
159 userLogin = [user login];
160 userTZ = [user timeZone];
162 param = [request formValueForKey: @"filterpopup"];
163 if ([param length] > 0)
164 [self _setupDatesWithPopup: param andUserTZ: userTZ];
167 param = [request formValueForKey: @"sd"];
168 if ([param length] > 0)
169 startDate = [[NSCalendarDate dateFromShortDateString: param
170 andShortTimeString: nil
171 inTimeZone: userTZ] beginOfDay];
175 param = [request formValueForKey: @"ed"];
176 if ([param length] > 0)
177 endDate = [[NSCalendarDate dateFromShortDateString: param
178 andShortTimeString: nil
179 inTimeZone: userTZ] endOfDay];
185 - (void) _updatePrivacyInComponent: (NSMutableDictionary *) component
186 fromFolder: (SOGoAppointmentFolder *) folder
189 NSString *roleString;
191 privacyFlag = [[component objectForKey: @"classification"] intValue];
192 roleString = [folder roleForComponentsWithAccessClass: privacyFlag
194 if ([roleString isEqualToString: @"ComponentDAndTViewer"])
196 [component setObject: @"" forKey: @"c_title"];
197 [component setObject: @"" forKey: @"c_location"];
201 - (SOGoAppointmentFolder *) _aptFolder: (NSString *) folder
202 withClientObject: (SOGoAppointmentFolder *) clientObject
204 SOGoAppointmentFolder *aptFolder;
205 NSArray *folderParts;
207 if ([folder isEqualToString: @"/"])
208 aptFolder = clientObject;
211 folderParts = [folder componentsSeparatedByString: @":"];
213 = [clientObject lookupCalendarFolderForUID:
214 [folderParts objectAtIndex: 0]];
220 - (NSArray *) _fetchFields: (NSArray *) fields
221 forComponentOfType: (NSString *) component
223 NSEnumerator *folders, *currentInfos;
224 SOGoAppointmentFolder *currentFolder;
225 NSMutableDictionary *newInfo;
226 NSMutableArray *infos;
228 SOGoAppointmentFolders *clientObject;
230 marker = [NSNull null];
232 clientObject = [self clientObject];
234 folders = [[clientObject subFolders] objectEnumerator];
235 currentFolder = [folders nextObject];
237 infos = [NSMutableArray array];
238 while (currentFolder)
240 if ([currentFolder isActive])
242 currentInfos = [[currentFolder fetchCoreInfosFrom: startDate
244 component: component] objectEnumerator];
246 while ((newInfo = [currentInfos nextObject]))
248 [self _updatePrivacyInComponent: newInfo
249 fromFolder: currentFolder];
250 [newInfo setObject: [currentFolder nameInContainer]
251 forKey: @"c_folder"];
253 [infos addObject: [newInfo objectsForKeys: fields
254 notFoundMarker: marker]];
257 currentFolder = [folders nextObject];
263 - (WOResponse *) _responseWithData: (NSArray *) data
265 WOResponse *response;
267 response = [self responseWithStatus: 200];
268 [response setHeader: @"text/plain; charset=utf-8"
269 forKey: @"content-type"];
270 [response appendContentString: [data jsonRepresentation]];
275 - (NSString *) _formattedDateForSeconds: (unsigned int) seconds
276 forAllDay: (BOOL) forAllDay
278 NSCalendarDate *date;
279 NSString *formattedDate;
281 date = [NSCalendarDate dateWithTimeIntervalSince1970: seconds];
282 [date setTimeZone: userTimeZone];
284 formattedDate = [dateFormatter formattedDate: date];
286 formattedDate = [dateFormatter formattedDateAndTime: date];
288 return formattedDate;
291 - (NSString *) _adjustedDateForSeconds: (unsigned int) seconds
292 forAllDay: (BOOL) forAllDay
294 NSCalendarDate *date;
295 unsigned int newSeconds, offset;
297 date = [NSCalendarDate dateWithTimeIntervalSince1970: seconds];
298 [date setTimeZone: userTimeZone];
300 offset = [userTimeZone secondsFromGMTForDate: date];
302 newSeconds = seconds + [userTimeZone secondsFromGMT] - offset;
304 newSeconds = seconds + offset;
306 return [NSString stringWithFormat: @"%u", newSeconds];
309 - (WOResponse *) eventsListAction
311 NSArray *fields, *oldEvent;
312 NSEnumerator *events;
313 NSMutableArray *newEvents, *newEvent;
314 unsigned int interval;
317 [self _setupContext];
319 newEvents = [NSMutableArray array];
320 fields = [NSArray arrayWithObjects: @"c_name", @"c_folder", @"c_status",
321 @"c_title", @"c_startdate", @"c_enddate", @"c_location",
323 events = [[self _fetchFields: fields
324 forComponentOfType: @"vevent"] objectEnumerator];
325 oldEvent = [events nextObject];
328 newEvent = [NSMutableArray arrayWithArray: oldEvent];
329 isAllDay = [[oldEvent objectAtIndex: 7] boolValue];
330 interval = [[oldEvent objectAtIndex: 4] intValue];
331 [newEvent replaceObjectAtIndex: 4
332 withObject: [self _adjustedDateForSeconds: interval
333 forAllDay: isAllDay]];
334 [newEvent addObject: [self _formattedDateForSeconds: interval
335 forAllDay: isAllDay]];
336 interval = [[oldEvent objectAtIndex: 5] intValue];
337 [newEvent replaceObjectAtIndex: 5
338 withObject: [self _adjustedDateForSeconds: interval
339 forAllDay: isAllDay]];
340 [newEvent addObject: [self _formattedDateForSeconds: interval
341 forAllDay: isAllDay]];
342 [newEvents addObject: newEvent];
344 oldEvent = [events nextObject];
346 [newEvents sortUsingSelector: @selector (compareEventsAscending:)];
348 return [self _responseWithData: newEvents];
351 - (NSString *) _getStatusClassForStatusCode: (int) statusCode
352 andEndDateStamp: (unsigned int) endDateStamp
354 NSCalendarDate *taskDate, *now;
355 NSString *statusClass;
358 statusClass = @"completed";
363 now = [NSCalendarDate calendarDate];
365 = [NSCalendarDate dateWithTimeIntervalSince1970: endDateStamp];
366 if ([taskDate earlierDate: now] == taskDate)
367 statusClass = @"overdue";
370 if ([taskDate isToday])
371 statusClass = @"duetoday";
373 statusClass = @"duelater";
377 statusClass = @"duelater";
383 - (WOResponse *) tasksListAction
386 NSMutableArray *filteredTasks, *filteredTask;
388 NSArray *fields, *task;
390 unsigned int endDateStamp;
391 NSString *statusFlag;
393 filteredTasks = [NSMutableArray array];
395 [self _setupContext];
397 fields = [NSArray arrayWithObjects: @"c_name", @"c_folder", @"c_status",
398 @"c_title", @"c_enddate", nil];
400 tasks = [[self _fetchFields: fields
401 forComponentOfType: @"vtodo"] objectEnumerator];
402 showCompleted = [[request formValueForKey: @"show-completed"] intValue];
404 task = [tasks nextObject];
407 statusCode = [[task objectAtIndex: 2] intValue];
408 if (statusCode != 1 || showCompleted)
410 filteredTask = [NSMutableArray arrayWithArray: task];
411 endDateStamp = [[task objectAtIndex: 4] intValue];
412 statusFlag = [self _getStatusClassForStatusCode: statusCode
413 andEndDateStamp: endDateStamp];
414 [filteredTask addObject: statusFlag];
415 [filteredTasks addObject: filteredTask];
417 task = [tasks nextObject];
419 [filteredTasks sortUsingSelector: @selector (compareTasksAscending:)];
421 return [self _responseWithData: filteredTasks];
424 // - (BOOL) shouldDisplayCurrentTask
429 // = [[self queryParameterForKey: @"show-completed"] intValue];
430 // knowsToShow = YES;
433 // return ([[currentTask objectForKey: @"status"] intValue] != 1
434 // || showCompleted);
437 // - (BOOL) shouldShowCompletedTasks
442 // = [[self queryParameterForKey: @"show-completed"] intValue];
443 // knowsToShow = YES;
446 // return showCompleted;