]> err.no Git - scalable-opengroupware.org/blob - UI/Scheduler/UIxCalListingActions.m
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1185 d1b88da0-ebda-0310...
[scalable-opengroupware.org] / UI / Scheduler / UIxCalListingActions.m
1 /* UIxCalListingActions.m - this file is part of SOGo
2  *
3  * Copyright (C) 2006 Inverse groupe conseil
4  *
5  * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
6  *
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)
10  * any later version.
11  *
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.
16  *
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.
21  */
22
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/NSValue.h>
29
30 #import <NGObjWeb/WOContext.h>
31 #import <NGObjWeb/WOContext+SoObjects.h>
32 #import <NGObjWeb/WORequest.h>
33 #import <NGObjWeb/WOResponse.h>
34 #import <NGExtensions/NSCalendarDate+misc.h>
35
36 #import <SoObjects/SOGo/SOGoUser.h>
37 #import <SoObjects/SOGo/SOGoDateFormatter.h>
38 #import <SoObjects/SOGo/NSCalendarDate+SOGo.h>
39 #import <SoObjects/SOGo/NSArray+Utilities.h>
40 #import <SoObjects/SOGo/NSObject+Utilities.h>
41 #import <SoObjects/Appointments/SOGoAppointmentFolder.h>
42 #import <SoObjects/Appointments/SOGoAppointmentFolders.h>
43
44 #import <UI/Common/WODirectAction+SOGo.h>
45
46 #import "NSArray+Scheduler.h"
47
48 #import "UIxCalListingActions.h"
49
50 @implementation UIxCalListingActions
51
52 - (id) initWithRequest: (WORequest *) newRequest
53 {
54   SOGoUser *user;
55
56   if ((self = [super initWithRequest: newRequest]))
57     {
58       componentsData = [NSMutableDictionary new];
59       startDate = nil;
60       endDate = nil;
61       ASSIGN (request, newRequest);
62       user = [[self context] activeUser];
63       dateFormatter = [user dateFormatterInContext: context];
64       ASSIGN (userTimeZone, [user timeZone]);
65     }
66
67   return self;
68 }
69
70 - (void) dealloc
71 {
72   [dateFormatter release];
73   [request release];
74   [componentsData release];
75   [startDate release];
76   [endDate release];
77   [userTimeZone release];
78   [super dealloc];
79 }
80
81 - (void) _setupDatesWithPopup: (NSString *) popupValue
82                     andUserTZ: (NSTimeZone *) userTZ
83 {
84   NSCalendarDate *newDate;
85   NSString *param;
86
87   if ([popupValue isEqualToString: @"view_today"])
88     {
89       newDate = [NSCalendarDate calendarDate];
90       [newDate setTimeZone: userTZ];
91       startDate = [newDate beginOfDay];
92       endDate = [newDate endOfDay];
93     }
94   else if ([popupValue isEqualToString: @"view_all"])
95     {
96       startDate = nil;
97       endDate = nil;
98     }
99   else if ([popupValue isEqualToString: @"view_next7"])
100     {
101       newDate = [NSCalendarDate calendarDate];
102       [newDate setTimeZone: userTZ];
103       startDate = [newDate beginOfDay];
104       endDate = [[startDate dateByAddingYears: 0 months: 0 days: 6] endOfDay];
105     }
106   else if ([popupValue isEqualToString: @"view_next14"])
107     {
108       newDate = [NSCalendarDate calendarDate];
109       [newDate setTimeZone: userTZ];
110       startDate = [newDate beginOfDay];
111       endDate = [[startDate dateByAddingYears: 0 months: 0 days: 13] endOfDay];
112     }
113   else if ([popupValue isEqualToString: @"view_next31"])
114     {
115       newDate = [NSCalendarDate calendarDate];
116       [newDate setTimeZone: userTZ];
117       startDate = [newDate beginOfDay];
118       endDate = [[startDate dateByAddingYears: 0 months: 0 days: 30] endOfDay];
119     }
120   else if ([popupValue isEqualToString: @"view_thismonth"])
121     {
122       newDate = [NSCalendarDate calendarDate];
123       [newDate setTimeZone: userTZ];
124       startDate = [[newDate firstDayOfMonth] beginOfDay];
125       endDate = [[newDate lastDayOfMonth] endOfDay];
126     }
127   else if ([popupValue isEqualToString: @"view_future"])
128     {
129       newDate = [NSCalendarDate calendarDate];
130       [newDate setTimeZone: userTZ];
131       startDate = [newDate beginOfDay];
132       endDate = [NSCalendarDate distantFuture];
133     }
134   else if ([popupValue isEqualToString: @"view_selectedday"])
135     {
136       param = [request formValueForKey: @"day"];
137       if ([param length] > 0)
138         startDate = [[NSCalendarDate dateFromShortDateString: param
139                                      andShortTimeString: nil
140                                      inTimeZone: userTZ] beginOfDay];
141       else
142         {
143           newDate = [NSCalendarDate calendarDate];
144           [newDate setTimeZone: userTZ];
145           startDate = [newDate beginOfDay];
146         }
147       endDate = [startDate endOfDay];
148     }
149 }
150
151 - (void) _setupContext
152 {
153   SOGoUser *user;
154   NSTimeZone *userTZ;
155   NSString *param;
156
157   user = [context activeUser];
158   userLogin = [user login];
159   userTZ = [user timeZone];
160
161   param = [request formValueForKey: @"filterpopup"];
162   if ([param length] > 0)
163     [self _setupDatesWithPopup: param andUserTZ: userTZ];
164   else
165     {
166       param = [request formValueForKey: @"sd"];
167       if ([param length] > 0)
168         startDate = [[NSCalendarDate dateFromShortDateString: param
169                                      andShortTimeString: nil
170                                      inTimeZone: userTZ] beginOfDay];
171       else
172         startDate = nil;
173       
174       param = [request formValueForKey: @"ed"];
175       if ([param length] > 0)
176         endDate = [[NSCalendarDate dateFromShortDateString: param
177                                    andShortTimeString: nil
178                                    inTimeZone: userTZ] endOfDay];
179       else
180         endDate = nil;
181     }
182 }
183
184 - (void) _updatePrivacyInComponent: (NSMutableDictionary *) component
185                         fromFolder: (SOGoAppointmentFolder *) folder
186 {
187   int privacyFlag;
188   NSString *roleString;
189
190   privacyFlag = [[component objectForKey: @"classification"] intValue];
191   roleString = [folder roleForComponentsWithAccessClass: privacyFlag
192                        forUser: userLogin];
193   if ([roleString isEqualToString: @"ComponentDAndTViewer"])
194     {
195       [component setObject: @"" forKey: @"c_title"];
196       [component setObject: @"" forKey: @"c_location"];
197     }
198 }
199
200 - (SOGoAppointmentFolder *) _aptFolder: (NSString *) folder
201                       withClientObject: (SOGoAppointmentFolder *) clientObject
202 {
203   SOGoAppointmentFolder *aptFolder;
204   NSArray *folderParts;
205
206   if ([folder isEqualToString: @"/"])
207     aptFolder = clientObject;
208   else
209     {
210       folderParts = [folder componentsSeparatedByString: @":"];
211       aptFolder
212         = [clientObject lookupCalendarFolderForUID:
213                           [folderParts objectAtIndex: 0]];
214     }
215
216   return aptFolder;
217 }
218
219 - (NSArray *) _fetchFields: (NSArray *) fields
220         forComponentOfType: (NSString *) component
221 {
222   NSEnumerator *folders, *currentInfos;
223   SOGoAppointmentFolder *currentFolder;
224   NSMutableDictionary *newInfo;
225   NSMutableArray *infos;
226   NSNull *marker;
227   SOGoAppointmentFolders *clientObject;
228
229   marker = [NSNull null];
230
231    clientObject = [self clientObject];
232
233   folders = [[clientObject subFolders] objectEnumerator];
234   currentFolder = [folders nextObject];
235
236   infos = [NSMutableArray array];
237   while (currentFolder)
238     {
239       if ([currentFolder isActive])
240         {
241           currentInfos = [[currentFolder fetchCoreInfosFrom: startDate
242                                          to: endDate
243                                          component: component] objectEnumerator];
244
245           while ((newInfo = [currentInfos nextObject]))
246             {
247               [self _updatePrivacyInComponent: newInfo
248                     fromFolder: currentFolder];
249               [newInfo setObject: [currentFolder nameInContainer]
250                        forKey: @"c_folder"];
251               
252               [infos addObject: [newInfo objectsForKeys: fields
253                                          notFoundMarker: marker]];
254             }
255         }
256       currentFolder = [folders nextObject];
257     }
258
259   return infos;
260 }
261
262 - (WOResponse *) _responseWithData: (NSArray *) data
263 {
264   WOResponse *response;
265
266   response = [self responseWithStatus: 200];
267   [response setHeader: @"text/plain; charset=utf-8"
268             forKey: @"content-type"];
269   [response appendContentString: [data jsonRepresentation]];
270
271   return response;
272 }
273
274 - (NSString *) _formattedDateForSeconds: (unsigned int) seconds
275                               forAllDay: (BOOL) forAllDay
276 {
277   NSCalendarDate *date;
278   NSString *formattedDate;
279
280   date = [NSCalendarDate dateWithTimeIntervalSince1970: seconds];
281   [date setTimeZone: userTimeZone];
282   if (forAllDay)
283     formattedDate = [dateFormatter formattedDate: date];
284   else
285     formattedDate = [dateFormatter formattedDateAndTime: date];
286
287   return formattedDate;    
288 }
289
290 - (WOResponse *) eventsListAction
291 {
292   NSArray *fields, *oldEvent;
293   NSEnumerator *events;
294   NSMutableArray *newEvents, *newEvent;
295   unsigned int interval;
296   BOOL isAllDay;
297
298   [self _setupContext];
299
300   newEvents = [NSMutableArray array];
301   fields = [NSArray arrayWithObjects: @"c_name", @"c_folder", @"c_status",
302                     @"c_title", @"c_startdate", @"c_enddate", @"c_location",
303                     @"c_isallday", nil];
304   events = [[self _fetchFields: fields
305                   forComponentOfType: @"vevent"] objectEnumerator];
306   oldEvent = [events nextObject];
307   while (oldEvent)
308     {
309       newEvent = [NSMutableArray arrayWithArray: oldEvent];
310       isAllDay = [[oldEvent objectAtIndex: 7] boolValue];
311       interval = [[oldEvent objectAtIndex: 4] intValue];
312       [newEvent addObject: [self _formattedDateForSeconds: interval
313                                  forAllDay: isAllDay]];
314       interval = [[oldEvent objectAtIndex: 5] intValue];
315       [newEvent addObject: [self _formattedDateForSeconds: interval
316                                  forAllDay: isAllDay]];
317       [newEvents addObject: newEvent];
318
319       oldEvent = [events nextObject];
320     }
321   [newEvents sortUsingSelector: @selector (compareEventsAscending:)];
322
323   return [self _responseWithData: newEvents];
324 }
325
326 - (NSString *) _getStatusClassForStatusCode: (int) statusCode
327                             andEndDateStamp: (unsigned int) endDateStamp
328 {
329   NSCalendarDate *taskDate, *now;
330   NSString *statusClass;
331
332   if (statusCode == 1)
333     statusClass = @"completed";
334   else
335     {
336       if (endDateStamp)
337         {
338           now = [NSCalendarDate calendarDate];
339           taskDate
340             = [NSCalendarDate dateWithTimeIntervalSince1970: endDateStamp];
341           if ([taskDate earlierDate: now] == taskDate)
342             statusClass = @"overdue";
343           else
344             {
345               if ([taskDate isToday])
346                 statusClass = @"duetoday";
347               else
348                 statusClass = @"duelater";
349             }
350         }
351       else
352         statusClass = @"duelater";
353     }
354
355   return statusClass;
356 }
357
358 - (WOResponse *) tasksListAction
359 {
360   NSEnumerator *tasks;
361   NSMutableArray *filteredTasks, *filteredTask;
362   BOOL showCompleted;
363   NSArray *fields, *task;
364   int statusCode;
365   unsigned int endDateStamp;
366   NSString *statusFlag;
367
368   filteredTasks = [NSMutableArray array];
369
370   [self _setupContext];
371
372   fields = [NSArray arrayWithObjects: @"c_name", @"c_folder", @"c_status",
373                     @"c_title", @"c_enddate", nil];
374
375   tasks = [[self _fetchFields: fields
376                  forComponentOfType: @"vtodo"] objectEnumerator];
377   showCompleted = [[request formValueForKey: @"show-completed"] intValue];
378
379   task = [tasks nextObject];
380   while (task)
381     {
382       statusCode = [[task objectAtIndex: 2] intValue];
383       if (statusCode != 1 || showCompleted)
384         {
385           filteredTask = [NSMutableArray arrayWithArray: task];
386           endDateStamp = [[task objectAtIndex: 4] intValue];
387           statusFlag = [self _getStatusClassForStatusCode: statusCode
388                              andEndDateStamp: endDateStamp];
389           [filteredTask addObject: statusFlag];
390           [filteredTasks addObject: filteredTask];
391         }
392       task = [tasks nextObject];
393     }
394   [filteredTasks sortUsingSelector: @selector (compareTasksAscending:)];
395
396   return [self _responseWithData: filteredTasks];
397 }
398
399 // - (BOOL) shouldDisplayCurrentTask
400 // {
401 //   if (!knowsToShow)
402 //     {
403 //       showCompleted
404 //         = [[self queryParameterForKey: @"show-completed"] intValue];
405 //       knowsToShow = YES;
406 //     }
407
408 //   return ([[currentTask objectForKey: @"status"] intValue] != 1
409 //         || showCompleted);
410 // }
411
412 // - (BOOL) shouldShowCompletedTasks
413 // {
414 //   if (!knowsToShow)
415 //     {
416 //       showCompleted
417 //         = [[self queryParameterForKey: @"show-completed"] intValue];
418 //       knowsToShow = YES;
419 //     }
420
421 //   return showCompleted;
422 // }
423
424 @end