]> err.no Git - scalable-opengroupware.org/blob - UI/Scheduler/UIxCalListingActions.m
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1173 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 *infos, *currentInfo, *newInfo;
225   NSString *owner, *uid;
226   NSNull *marker;
227   SOGoAppointmentFolders *clientObject;
228
229   marker = [NSNull null];
230
231   infos = [NSMutableDictionary dictionary];
232   clientObject = [self clientObject];
233
234   folders = [[clientObject subFolders] objectEnumerator];
235   currentFolder = [folders nextObject];
236   while (currentFolder)
237     {
238       if ([currentFolder isActive])
239         {
240           owner = [currentFolder ownerInContext: context];
241           currentInfos = [[currentFolder fetchCoreInfosFrom: startDate
242                                          to: endDate
243                                          component: component] objectEnumerator];
244           newInfo = [currentInfos nextObject];
245           while (newInfo)
246             {
247               uid = [newInfo objectForKey: @"c_uid"];
248               currentInfo = [infos objectForKey: uid];
249               if (!currentInfo
250                   || [owner isEqualToString: userLogin])
251                 {
252                   [self _updatePrivacyInComponent: newInfo
253                         fromFolder: currentFolder];
254                   [newInfo setObject: [currentFolder nameInContainer]
255                            forKey: @"c_folder"];
256                   //          [newInfo setObject: owner forKey: @"c_owner"];
257                   [infos setObject: [newInfo objectsForKeys: fields
258                                              notFoundMarker: marker]
259                          forKey: uid];
260                 }
261               newInfo = [currentInfos nextObject];
262             }
263         }
264       currentFolder = [folders nextObject];
265     }
266
267   return [infos allValues];
268 }
269
270 - (WOResponse *) _responseWithData: (NSArray *) data
271 {
272   WOResponse *response;
273
274   response = [self responseWithStatus: 200];
275   [response setHeader: @"text/plain; charset=utf-8"
276             forKey: @"content-type"];
277   [response appendContentString: [data jsonRepresentation]];
278
279   return response;
280 }
281
282 - (NSString *) _formattedDateForSeconds: (unsigned int) seconds
283                               forAllDay: (BOOL) forAllDay
284 {
285   NSCalendarDate *date;
286   NSString *formattedDate;
287
288   date = [NSCalendarDate dateWithTimeIntervalSince1970: seconds];
289   [date setTimeZone: userTimeZone];
290   if (forAllDay)
291     formattedDate = [dateFormatter formattedDate: date];
292   else
293     formattedDate = [dateFormatter formattedDateAndTime: date];
294
295   return formattedDate;    
296 }
297
298 - (WOResponse *) eventsListAction
299 {
300   NSArray *fields, *oldEvent;
301   NSEnumerator *events;
302   NSMutableArray *newEvents, *newEvent;
303   unsigned int interval;
304   BOOL isAllDay;
305
306   [self _setupContext];
307
308   newEvents = [NSMutableArray array];
309   fields = [NSArray arrayWithObjects: @"c_name", @"c_folder", @"c_status",
310                     @"c_title", @"c_startdate", @"c_enddate", @"c_location",
311                     @"c_isallday", nil];
312   events = [[self _fetchFields: fields
313                   forComponentOfType: @"vevent"] objectEnumerator];
314   oldEvent = [events nextObject];
315   while (oldEvent)
316     {
317       newEvent = [NSMutableArray arrayWithArray: oldEvent];
318       isAllDay = [[oldEvent objectAtIndex: 7] boolValue];
319       interval = [[oldEvent objectAtIndex: 4] intValue];
320       [newEvent addObject: [self _formattedDateForSeconds: interval
321                                  forAllDay: isAllDay]];
322       interval = [[oldEvent objectAtIndex: 5] intValue];
323       [newEvent addObject: [self _formattedDateForSeconds: interval
324                                  forAllDay: isAllDay]];
325       [newEvents addObject: newEvent];
326
327       oldEvent = [events nextObject];
328     }
329   [newEvents sortUsingSelector: @selector (compareEventsAscending:)];
330
331   return [self _responseWithData: newEvents];
332 }
333
334 - (NSString *) _getStatusClassForStatusCode: (int) statusCode
335                             andEndDateStamp: (unsigned int) endDateStamp
336 {
337   NSCalendarDate *taskDate, *now;
338   NSString *statusClass;
339
340   if (statusCode == 1)
341     statusClass = @"completed";
342   else
343     {
344       if (endDateStamp)
345         {
346           now = [NSCalendarDate calendarDate];
347           taskDate
348             = [NSCalendarDate dateWithTimeIntervalSince1970: endDateStamp];
349           if ([taskDate earlierDate: now] == taskDate)
350             statusClass = @"overdue";
351           else
352             {
353               if ([taskDate isToday])
354                 statusClass = @"duetoday";
355               else
356                 statusClass = @"duelater";
357             }
358         }
359       else
360         statusClass = @"duelater";
361     }
362
363   return statusClass;
364 }
365
366 - (WOResponse *) tasksListAction
367 {
368   NSEnumerator *tasks;
369   NSMutableArray *filteredTasks, *filteredTask;
370   BOOL showCompleted;
371   NSArray *fields, *task;
372   int statusCode;
373   unsigned int endDateStamp;
374   NSString *statusFlag;
375
376   filteredTasks = [NSMutableArray array];
377
378   [self _setupContext];
379
380   fields = [NSArray arrayWithObjects: @"c_name", @"c_folder", @"c_status",
381                     @"c_title", @"c_enddate", nil];
382
383   tasks = [[self _fetchFields: fields
384                  forComponentOfType: @"vtodo"] objectEnumerator];
385   showCompleted = [[request formValueForKey: @"show-completed"] intValue];
386
387   task = [tasks nextObject];
388   while (task)
389     {
390       statusCode = [[task objectAtIndex: 2] intValue];
391       if (statusCode != 1 || showCompleted)
392         {
393           filteredTask = [NSMutableArray arrayWithArray: task];
394           endDateStamp = [[task objectAtIndex: 4] intValue];
395           statusFlag = [self _getStatusClassForStatusCode: statusCode
396                              andEndDateStamp: endDateStamp];
397           [filteredTask addObject: statusFlag];
398           [filteredTasks addObject: filteredTask];
399         }
400       task = [tasks nextObject];
401     }
402   [filteredTasks sortUsingSelector: @selector (compareTasksAscending:)];
403
404   return [self _responseWithData: filteredTasks];
405 }
406
407 // - (BOOL) shouldDisplayCurrentTask
408 // {
409 //   if (!knowsToShow)
410 //     {
411 //       showCompleted
412 //         = [[self queryParameterForKey: @"show-completed"] intValue];
413 //       knowsToShow = YES;
414 //     }
415
416 //   return ([[currentTask objectForKey: @"status"] intValue] != 1
417 //         || showCompleted);
418 // }
419
420 // - (BOOL) shouldShowCompletedTasks
421 // {
422 //   if (!knowsToShow)
423 //     {
424 //       showCompleted
425 //         = [[self queryParameterForKey: @"show-completed"] intValue];
426 //       knowsToShow = YES;
427 //     }
428
429 //   return showCompleted;
430 // }
431
432 @end