2007-06-07 22:49:06 +02:00
|
|
|
/* UIxCalListingActions.m - this file is part of SOGo
|
|
|
|
*
|
2014-06-28 14:31:07 +02:00
|
|
|
* Copyright (C) 2006-2014 Inverse inc.
|
2007-06-07 22:49:06 +02:00
|
|
|
*
|
|
|
|
* This file is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2, or (at your option)
|
|
|
|
* any later version.
|
|
|
|
*
|
|
|
|
* This file is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; see the file COPYING. If not, write to
|
|
|
|
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
|
|
* Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#import <Foundation/NSArray.h>
|
|
|
|
#import <Foundation/NSDictionary.h>
|
|
|
|
#import <Foundation/NSEnumerator.h>
|
|
|
|
#import <Foundation/NSNull.h>
|
|
|
|
#import <Foundation/NSString.h>
|
2007-10-30 22:51:31 +01:00
|
|
|
#import <Foundation/NSTimeZone.h>
|
2007-09-15 00:01:02 +02:00
|
|
|
#import <Foundation/NSValue.h>
|
2007-06-07 22:49:06 +02:00
|
|
|
|
|
|
|
#import <NGObjWeb/WOContext.h>
|
|
|
|
#import <NGObjWeb/WOContext+SoObjects.h>
|
|
|
|
#import <NGObjWeb/WORequest.h>
|
|
|
|
#import <NGObjWeb/WOResponse.h>
|
2009-06-08 19:48:46 +02:00
|
|
|
|
2007-12-12 18:48:19 +01:00
|
|
|
#import <NGCards/iCalPerson.h>
|
2011-01-14 03:54:33 +01:00
|
|
|
#import <NGCards/iCalTimeZone.h>
|
|
|
|
#import <NGCards/iCalDateTime.h>
|
2014-05-08 23:17:05 +02:00
|
|
|
#import <NGCards/iCalCalendar.h>
|
|
|
|
#import <NGCards/iCalObject.h>
|
2009-06-08 19:48:46 +02:00
|
|
|
|
2009-03-16 22:21:43 +01:00
|
|
|
#import <NGExtensions/NGCalendarDateRange.h>
|
2009-06-08 19:48:46 +02:00
|
|
|
#import <NGExtensions/NSCalendarDate+misc.h>
|
2009-07-03 21:46:01 +02:00
|
|
|
#import <NGExtensions/NSObject+Logs.h>
|
2014-02-05 22:02:38 +01:00
|
|
|
#import <NGExtensions/NSString+misc.h>
|
2007-06-07 22:49:06 +02:00
|
|
|
|
2009-11-29 05:19:32 +01:00
|
|
|
#import <SOGo/SOGoDateFormatter.h>
|
2010-01-21 21:44:17 +01:00
|
|
|
#import <SOGo/SOGoPermissions.h>
|
2009-11-29 05:19:32 +01:00
|
|
|
#import <SOGo/SOGoUser.h>
|
|
|
|
#import <SOGo/SOGoUserDefaults.h>
|
|
|
|
#import <SOGo/SOGoUserFolder.h>
|
|
|
|
#import <SOGo/SOGoUserSettings.h>
|
|
|
|
#import <SOGo/NSCalendarDate+SOGo.h>
|
|
|
|
#import <SOGo/NSArray+Utilities.h>
|
|
|
|
#import <SOGo/NSObject+Utilities.h>
|
|
|
|
#import <Appointments/SOGoAppointmentFolder.h>
|
|
|
|
#import <Appointments/SOGoAppointmentFolders.h>
|
|
|
|
#import <Appointments/SOGoAppointmentObject.h>
|
2010-02-19 20:04:19 +01:00
|
|
|
#import <Appointments/SOGoWebAppointmentFolder.h>
|
2007-06-07 22:49:06 +02:00
|
|
|
|
2007-09-11 21:36:40 +02:00
|
|
|
#import <UI/Common/WODirectAction+SOGo.h>
|
|
|
|
|
2007-06-13 21:33:31 +02:00
|
|
|
#import "NSArray+Scheduler.h"
|
2007-06-11 23:28:28 +02:00
|
|
|
|
2007-06-07 22:49:06 +02:00
|
|
|
#import "UIxCalListingActions.h"
|
|
|
|
|
2008-07-16 04:12:18 +02:00
|
|
|
static NSArray *eventsFields = nil;
|
|
|
|
static NSArray *tasksFields = nil;
|
|
|
|
|
2009-10-07 19:40:02 +02:00
|
|
|
#define dayLength 86400
|
2010-04-02 20:50:21 +02:00
|
|
|
#define quarterLength 900 // number of seconds in 15 minutes
|
|
|
|
#define offsetHours (24 * 5) // number of hours in invitation window
|
|
|
|
#define offsetSeconds (offsetHours * 60 * 60) // number of seconds in
|
2014-05-08 23:17:05 +02:00
|
|
|
// invitation window
|
2010-04-02 20:50:21 +02:00
|
|
|
/* 1 block = 15 minutes */
|
|
|
|
#define offsetBlocks (offsetHours * 4) // number of 15-minute blocks in invitation window
|
|
|
|
#define maxBlocks (offsetBlocks * 2) // maximum number of blocks to search
|
2014-05-08 23:17:05 +02:00
|
|
|
// for a free slot (10 days)
|
2009-06-04 16:57:50 +02:00
|
|
|
|
2007-06-07 22:49:06 +02:00
|
|
|
@implementation UIxCalListingActions
|
|
|
|
|
2008-07-16 04:12:18 +02:00
|
|
|
+ (void) initialize
|
|
|
|
{
|
|
|
|
if (!eventsFields)
|
2014-05-08 23:17:05 +02:00
|
|
|
{
|
|
|
|
eventsFields = [NSArray arrayWithObjects: @"c_name", @"c_folder",
|
|
|
|
@"calendarName",
|
|
|
|
@"c_status", @"c_title", @"c_startdate",
|
|
|
|
@"c_enddate", @"c_location", @"c_isallday",
|
|
|
|
@"c_classification", @"c_category",
|
|
|
|
@"c_partmails", @"c_partstates", @"c_owner",
|
|
|
|
@"c_iscycle", @"c_nextalarm",
|
|
|
|
@"c_recurrence_id", @"isException", @"editable",
|
2015-05-13 19:12:15 +02:00
|
|
|
@"erasable", @"ownerIsOrganizer", @"c_description", nil];
|
2014-05-08 23:17:05 +02:00
|
|
|
[eventsFields retain];
|
|
|
|
}
|
2008-07-16 04:12:18 +02:00
|
|
|
if (!tasksFields)
|
2014-05-08 23:17:05 +02:00
|
|
|
{
|
|
|
|
tasksFields = [NSArray arrayWithObjects: @"c_name", @"c_folder",
|
|
|
|
@"calendarName",
|
|
|
|
@"c_status", @"c_title", @"c_enddate",
|
|
|
|
@"c_classification", @"c_location", @"c_category",
|
|
|
|
@"editable", @"erasable",
|
2016-10-21 23:30:47 +02:00
|
|
|
@"c_priority", @"c_owner",
|
|
|
|
@"c_recurrence_id", @"isException", @"c_description", nil];
|
2014-05-08 23:17:05 +02:00
|
|
|
[tasksFields retain];
|
|
|
|
}
|
2008-07-16 04:12:18 +02:00
|
|
|
}
|
|
|
|
|
2007-06-11 23:43:37 +02:00
|
|
|
- (id) initWithRequest: (WORequest *) newRequest
|
2007-06-07 22:49:06 +02:00
|
|
|
{
|
2007-06-19 20:08:16 +02:00
|
|
|
SOGoUser *user;
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2007-06-11 23:43:37 +02:00
|
|
|
if ((self = [super initWithRequest: newRequest]))
|
2014-05-08 23:17:05 +02:00
|
|
|
{
|
|
|
|
componentsData = [NSMutableDictionary new];
|
|
|
|
startDate = nil;
|
|
|
|
endDate = nil;
|
|
|
|
ASSIGN (request, newRequest);
|
|
|
|
user = [[self context] activeUser];
|
|
|
|
ASSIGN (dateFormatter, [user dateFormatterInContext: context]);
|
|
|
|
ASSIGN (userTimeZone, [[user userDefaults] timeZone]);
|
|
|
|
dayBasedView = NO;
|
2014-06-20 19:16:55 +02:00
|
|
|
currentView = nil;
|
2014-05-08 23:17:05 +02:00
|
|
|
}
|
|
|
|
|
2007-06-07 22:49:06 +02:00
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) dealloc
|
|
|
|
{
|
2007-06-11 23:28:28 +02:00
|
|
|
[dateFormatter release];
|
2007-06-11 23:43:37 +02:00
|
|
|
[request release];
|
2007-06-07 22:49:06 +02:00
|
|
|
[componentsData release];
|
2007-06-19 20:08:16 +02:00
|
|
|
[userTimeZone release];
|
2007-06-07 22:49:06 +02:00
|
|
|
[super dealloc];
|
|
|
|
}
|
|
|
|
|
2007-06-08 01:22:14 +02:00
|
|
|
- (void) _setupDatesWithPopup: (NSString *) popupValue
|
2014-05-08 23:17:05 +02:00
|
|
|
andUserTZ: (NSTimeZone *) userTZ
|
2007-06-08 01:22:14 +02:00
|
|
|
{
|
|
|
|
NSCalendarDate *newDate;
|
|
|
|
NSString *param;
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2007-06-08 01:22:14 +02:00
|
|
|
if ([popupValue isEqualToString: @"view_today"])
|
2014-05-08 23:17:05 +02:00
|
|
|
{
|
|
|
|
newDate = [NSCalendarDate calendarDate];
|
|
|
|
[newDate setTimeZone: userTZ];
|
|
|
|
startDate = [newDate beginOfDay];
|
|
|
|
endDate = [newDate endOfDay];
|
|
|
|
}
|
2007-06-08 01:22:14 +02:00
|
|
|
else if ([popupValue isEqualToString: @"view_all"])
|
2014-05-08 23:17:05 +02:00
|
|
|
{
|
|
|
|
startDate = nil;
|
|
|
|
endDate = nil;
|
|
|
|
}
|
2007-06-08 01:22:14 +02:00
|
|
|
else if ([popupValue isEqualToString: @"view_next7"])
|
2014-05-08 23:17:05 +02:00
|
|
|
{
|
|
|
|
newDate = [NSCalendarDate calendarDate];
|
|
|
|
[newDate setTimeZone: userTZ];
|
|
|
|
startDate = [newDate beginOfDay];
|
|
|
|
endDate = [[startDate dateByAddingYears: 0 months: 0 days: 6] endOfDay];
|
|
|
|
}
|
2007-06-08 01:22:14 +02:00
|
|
|
else if ([popupValue isEqualToString: @"view_next14"])
|
2014-05-08 23:17:05 +02:00
|
|
|
{
|
|
|
|
newDate = [NSCalendarDate calendarDate];
|
|
|
|
[newDate setTimeZone: userTZ];
|
|
|
|
startDate = [newDate beginOfDay];
|
|
|
|
endDate = [[startDate dateByAddingYears: 0 months: 0 days: 13] endOfDay];
|
|
|
|
}
|
2007-06-08 01:22:14 +02:00
|
|
|
else if ([popupValue isEqualToString: @"view_next31"])
|
2014-05-08 23:17:05 +02:00
|
|
|
{
|
|
|
|
newDate = [NSCalendarDate calendarDate];
|
|
|
|
[newDate setTimeZone: userTZ];
|
|
|
|
startDate = [newDate beginOfDay];
|
|
|
|
endDate = [[startDate dateByAddingYears: 0 months: 0 days: 30] endOfDay];
|
|
|
|
}
|
2007-06-08 01:22:14 +02:00
|
|
|
else if ([popupValue isEqualToString: @"view_thismonth"])
|
2014-05-08 23:17:05 +02:00
|
|
|
{
|
|
|
|
newDate = [NSCalendarDate calendarDate];
|
|
|
|
[newDate setTimeZone: userTZ];
|
|
|
|
startDate = [[newDate firstDayOfMonth] beginOfDay];
|
|
|
|
endDate = [[newDate lastDayOfMonth] endOfDay];
|
|
|
|
}
|
2007-06-08 01:22:14 +02:00
|
|
|
else if ([popupValue isEqualToString: @"view_future"])
|
2014-05-08 23:17:05 +02:00
|
|
|
{
|
|
|
|
newDate = [NSCalendarDate calendarDate];
|
|
|
|
[newDate setTimeZone: userTZ];
|
|
|
|
startDate = [newDate beginOfDay];
|
|
|
|
endDate = nil;
|
|
|
|
}
|
|
|
|
else if ([popupValue isEqualToString: @"view_selectedday"])
|
|
|
|
{
|
|
|
|
param = [request formValueForKey: @"day"];
|
|
|
|
if ([param length] > 0)
|
|
|
|
startDate = [[NSCalendarDate dateFromShortDateString: param
|
|
|
|
andShortTimeString: nil
|
|
|
|
inTimeZone: userTZ] beginOfDay];
|
|
|
|
else
|
2007-06-08 01:22:14 +02:00
|
|
|
{
|
|
|
|
newDate = [NSCalendarDate calendarDate];
|
|
|
|
[newDate setTimeZone: userTZ];
|
|
|
|
startDate = [newDate beginOfDay];
|
|
|
|
}
|
2014-05-08 23:17:05 +02:00
|
|
|
endDate = [startDate endOfDay];
|
|
|
|
}
|
2007-06-08 01:22:14 +02:00
|
|
|
}
|
|
|
|
|
2007-06-07 22:49:06 +02:00
|
|
|
- (void) _setupContext
|
|
|
|
{
|
|
|
|
SOGoUser *user;
|
|
|
|
NSString *param;
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2007-06-07 22:49:06 +02:00
|
|
|
user = [context activeUser];
|
|
|
|
userLogin = [user login];
|
2014-05-08 23:17:05 +02:00
|
|
|
|
|
|
|
criteria = [request formValueForKey: @"search"];
|
|
|
|
value = [request formValueForKey: @"value"];
|
2007-06-08 01:22:14 +02:00
|
|
|
param = [request formValueForKey: @"filterpopup"];
|
2008-07-16 04:12:18 +02:00
|
|
|
if ([param length])
|
2014-05-08 23:17:05 +02:00
|
|
|
{
|
|
|
|
[self _setupDatesWithPopup: param andUserTZ: userTimeZone];
|
|
|
|
}
|
2007-06-07 22:49:06 +02:00
|
|
|
else
|
2014-05-08 23:17:05 +02:00
|
|
|
{
|
|
|
|
param = [request formValueForKey: @"sd"];
|
|
|
|
if ([param length] > 0)
|
|
|
|
startDate = [[NSCalendarDate dateFromShortDateString: param
|
|
|
|
andShortTimeString: nil
|
|
|
|
inTimeZone: userTimeZone] beginOfDay];
|
|
|
|
else
|
|
|
|
startDate = nil;
|
|
|
|
|
|
|
|
param = [request formValueForKey: @"ed"];
|
|
|
|
if ([param length] > 0)
|
|
|
|
endDate = [[NSCalendarDate dateFromShortDateString: param
|
|
|
|
andShortTimeString: nil
|
|
|
|
inTimeZone: userTimeZone] endOfDay];
|
|
|
|
else
|
|
|
|
endDate = nil;
|
|
|
|
|
|
|
|
param = [request formValueForKey: @"view"];
|
2014-06-20 19:16:55 +02:00
|
|
|
currentView = param;
|
2014-05-08 23:17:05 +02:00
|
|
|
dayBasedView = ![param isEqualToString: @"monthview"];
|
|
|
|
}
|
2007-06-07 22:49:06 +02:00
|
|
|
}
|
|
|
|
|
2007-11-26 18:40:44 +01:00
|
|
|
- (void) _fixComponentTitle: (NSMutableDictionary *) component
|
|
|
|
withType: (NSString *) type
|
|
|
|
{
|
|
|
|
NSString *labelKey;
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2007-11-26 18:40:44 +01:00
|
|
|
labelKey = [NSString stringWithFormat: @"%@_class%@",
|
2014-05-08 23:17:05 +02:00
|
|
|
type, [component objectForKey: @"c_classification"]];
|
2007-11-26 18:40:44 +01:00
|
|
|
[component setObject: [self labelForKey: labelKey]
|
2014-05-08 23:17:05 +02:00
|
|
|
forKey: @"c_title"];
|
2007-11-26 18:40:44 +01:00
|
|
|
}
|
|
|
|
|
2011-01-14 03:54:33 +01:00
|
|
|
/*
|
|
|
|
* Adjust the event start and end dates when there's a time change
|
|
|
|
* in the period covering the view for the user's timezone.
|
|
|
|
* @param theRecord the attributes of the event.
|
|
|
|
*/
|
|
|
|
- (void) _fixDates: (NSMutableDictionary *) theRecord
|
2009-03-16 22:21:43 +01:00
|
|
|
{
|
2011-01-14 16:27:16 +01:00
|
|
|
NSCalendarDate *aDate;
|
2009-03-16 22:21:43 +01:00
|
|
|
NSNumber *aDateValue;
|
|
|
|
NSString *aDateField;
|
2010-03-15 17:26:38 +01:00
|
|
|
int daylightOffset;
|
2009-03-16 22:21:43 +01:00
|
|
|
unsigned int count;
|
|
|
|
static NSString *fields[] = { @"startDate", @"c_startdate",
|
2014-05-08 23:17:05 +02:00
|
|
|
@"endDate", @"c_enddate" };
|
2009-03-16 22:21:43 +01:00
|
|
|
|
2010-10-15 22:51:00 +02:00
|
|
|
/* WARNING: This condition has been put and removed many times, please leave
|
2014-05-08 23:17:05 +02:00
|
|
|
it. Here is the story...
|
|
|
|
If _fixDates: is conditional to dayBasedView, the recurrences are computed
|
|
|
|
properly but the display time is wrong.
|
|
|
|
If _fixDates: is non-conditional, the reverse occurs.
|
|
|
|
If only this part of _fixDates: is conditional, both are right.
|
|
|
|
|
|
|
|
Regarding all day events, we need to execute this code no matter what the
|
|
|
|
date and the view are, otherwise the event will span on two days.
|
|
|
|
|
|
|
|
ref bugs:
|
|
|
|
http://www.sogo.nu/bugs/view.php?id=909
|
|
|
|
http://www.sogo.nu/bugs/view.php?id=678
|
|
|
|
...
|
|
|
|
*/
|
2011-01-14 03:54:33 +01:00
|
|
|
|
2011-06-13 22:28:10 +02:00
|
|
|
//NSLog(@"***[UIxCalListingActions _fixDates:] %@", [theRecord objectForKey: @"c_title"]);
|
2011-01-14 03:54:33 +01:00
|
|
|
if (dayBasedView || [[theRecord objectForKey: @"c_isallday"] boolValue])
|
2014-05-08 23:17:05 +02:00
|
|
|
{
|
|
|
|
for (count = 0; count < 2; count++)
|
2010-07-16 04:21:01 +02:00
|
|
|
{
|
2014-05-08 23:17:05 +02:00
|
|
|
aDateField = fields[count * 2];
|
|
|
|
aDate = [theRecord objectForKey: aDateField];
|
|
|
|
daylightOffset = (int) ([userTimeZone secondsFromGMTForDate: aDate]
|
|
|
|
- [userTimeZone secondsFromGMTForDate: startDate]);
|
|
|
|
//NSLog(@"***[UIxCalListingActions _fixDates:] %@ = %@ (%i)", aDateField, aDate, daylightOffset);
|
|
|
|
if (daylightOffset)
|
|
|
|
{
|
|
|
|
aDate = [aDate dateByAddingYears: 0 months: 0 days: 0 hours: 0
|
|
|
|
minutes: 0 seconds: daylightOffset];
|
|
|
|
[theRecord setObject: aDate forKey: aDateField];
|
|
|
|
aDateValue = [NSNumber numberWithInt: [aDate timeIntervalSince1970]];
|
|
|
|
[theRecord setObject: aDateValue forKey: fields[count * 2 + 1]];
|
|
|
|
}
|
2010-07-16 04:21:01 +02:00
|
|
|
}
|
2014-05-08 23:17:05 +02:00
|
|
|
}
|
2009-03-16 22:21:43 +01:00
|
|
|
}
|
|
|
|
|
2007-06-07 22:49:06 +02:00
|
|
|
- (NSArray *) _fetchFields: (NSArray *) fields
|
2014-05-08 23:17:05 +02:00
|
|
|
forComponentOfType: (NSString *) component
|
2007-06-07 22:49:06 +02:00
|
|
|
{
|
|
|
|
NSEnumerator *folders, *currentInfos;
|
2007-10-09 19:19:20 +02:00
|
|
|
NSMutableDictionary *newInfo;
|
2014-05-08 23:17:05 +02:00
|
|
|
NSMutableArray *infos, *newInfoForComponent, *quickInfos, *allInfos, *quickInfosName;
|
2007-06-07 22:49:06 +02:00
|
|
|
NSNull *marker;
|
2016-10-21 23:30:47 +02:00
|
|
|
NSString *owner, *role, *calendarName, *iCalString;
|
2014-05-08 23:17:05 +02:00
|
|
|
NSRange match;
|
|
|
|
iCalCalendar *calendar;
|
2015-11-05 18:29:26 +01:00
|
|
|
iCalEntityObject *master;
|
2014-05-08 23:17:05 +02:00
|
|
|
SOGoAppointmentFolder *currentFolder;
|
2007-09-15 00:01:02 +02:00
|
|
|
SOGoAppointmentFolders *clientObject;
|
2010-01-21 21:44:17 +01:00
|
|
|
SOGoUser *ownerUser;
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2016-04-12 22:11:21 +02:00
|
|
|
BOOL isErasable, folderIsRemote, searchByTitleOrContent, quickInfosFlag;
|
2014-02-05 22:02:38 +01:00
|
|
|
id currentInfo;
|
|
|
|
int i, count;
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2008-12-31 18:43:20 +01:00
|
|
|
infos = [NSMutableArray array];
|
2007-06-07 22:49:06 +02:00
|
|
|
marker = [NSNull null];
|
2007-11-26 18:40:44 +01:00
|
|
|
clientObject = [self clientObject];
|
2016-04-12 22:11:21 +02:00
|
|
|
quickInfosFlag = searchByTitleOrContent = NO;
|
|
|
|
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2007-09-15 00:01:02 +02:00
|
|
|
folders = [[clientObject subFolders] objectEnumerator];
|
2008-12-31 18:43:20 +01:00
|
|
|
while ((currentFolder = [folders nextObject]))
|
2007-06-07 22:49:06 +02:00
|
|
|
{
|
2014-09-12 14:34:15 +02:00
|
|
|
if ([currentFolder isActive])
|
|
|
|
{
|
|
|
|
folderIsRemote = [currentFolder isKindOfClass: [SOGoWebAppointmentFolder class]];
|
2016-04-12 22:11:21 +02:00
|
|
|
searchByTitleOrContent = ([value length] > 0);
|
|
|
|
|
2014-09-12 14:34:15 +02:00
|
|
|
//
|
|
|
|
// criteria can have the following values: "title", "title_Category_Location" and "entireContent"
|
|
|
|
//
|
|
|
|
if ([criteria isEqualToString:@"title_Category_Location"])
|
|
|
|
{
|
|
|
|
currentInfos = [[currentFolder fetchCoreInfosFrom: startDate
|
|
|
|
to: endDate
|
|
|
|
title: value
|
|
|
|
component: component
|
|
|
|
additionalFilters: criteria] objectEnumerator];
|
|
|
|
}
|
|
|
|
else if ([criteria isEqualToString:@"entireContent"])
|
|
|
|
{
|
|
|
|
// First search : Through the quick table inside the location, category and title columns
|
2015-11-05 18:29:26 +01:00
|
|
|
quickInfos = (NSMutableArray *)[currentFolder fetchCoreInfosFrom: startDate
|
2014-09-12 14:34:15 +02:00
|
|
|
to: endDate
|
|
|
|
title: value
|
|
|
|
component: component
|
|
|
|
additionalFilters: criteria];
|
2016-04-12 22:11:21 +02:00
|
|
|
|
2014-09-12 14:34:15 +02:00
|
|
|
// Save the c_name in another array to compare with
|
|
|
|
if ([quickInfos count] > 0)
|
|
|
|
{
|
|
|
|
quickInfosFlag = YES;
|
|
|
|
quickInfosName = [NSMutableArray arrayWithCapacity:[quickInfos count]];
|
|
|
|
for (i = 0; i < [quickInfos count]; i++)
|
|
|
|
[quickInfosName addObject:[[quickInfos objectAtIndex:i] objectForKey:@"c_name"]];
|
|
|
|
}
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2014-09-12 14:34:15 +02:00
|
|
|
// Second research : Every objects except for those already in the quickInfos array
|
2015-11-05 18:29:26 +01:00
|
|
|
allInfos = (NSMutableArray *)[currentFolder fetchCoreInfosFrom: startDate
|
2014-09-12 14:34:15 +02:00
|
|
|
to: endDate
|
|
|
|
title: nil
|
|
|
|
component: component];
|
|
|
|
if (quickInfosFlag == YES)
|
|
|
|
{
|
|
|
|
for (i = ([allInfos count] - 1); i >= 0 ; i--) {
|
|
|
|
if([quickInfosName containsObject:[[allInfos objectAtIndex:i] objectForKey:@"c_name"]])
|
|
|
|
[allInfos removeObjectAtIndex:i];
|
|
|
|
}
|
|
|
|
}
|
2014-05-16 17:29:37 +02:00
|
|
|
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2014-09-12 14:34:15 +02:00
|
|
|
for (i = 0; i < [allInfos count]; i++)
|
|
|
|
{
|
|
|
|
iCalString = [[allInfos objectAtIndex:i] objectForKey:@"c_content"];
|
|
|
|
calendar = [iCalCalendar parseSingleFromSource: iCalString];
|
2015-11-05 18:29:26 +01:00
|
|
|
master = (iCalEntityObject *)[calendar firstChildWithTag:component];
|
2014-09-12 14:34:15 +02:00
|
|
|
if (master) {
|
|
|
|
if ([[master comment] length] > 0)
|
|
|
|
{
|
|
|
|
match = [[master comment] rangeOfString:value options:NSCaseInsensitiveSearch];
|
|
|
|
if (match.length > 0) {
|
|
|
|
[quickInfos addObject:[allInfos objectAtIndex:i]];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-05-16 17:29:37 +02:00
|
|
|
|
2014-09-12 14:34:15 +02:00
|
|
|
currentInfos = [quickInfos objectEnumerator];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
id foo;
|
2012-03-15 22:01:25 +01:00
|
|
|
|
2014-09-12 14:34:15 +02:00
|
|
|
foo = [currentFolder fetchCoreInfosFrom: startDate
|
2016-04-12 22:11:21 +02:00
|
|
|
to: endDate
|
|
|
|
title: value
|
2014-09-12 14:34:15 +02:00
|
|
|
component: component];
|
|
|
|
currentInfos = [foo objectEnumerator];
|
|
|
|
}
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2014-09-12 14:34:15 +02:00
|
|
|
owner = [currentFolder ownerInContext: context];
|
|
|
|
ownerUser = [SOGoUser userWithLogin: owner];
|
|
|
|
isErasable = ([owner isEqualToString: userLogin] || [[currentFolder aclsForUser: userLogin] containsObject: SOGoRole_ObjectEraser]);
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2014-09-12 14:34:15 +02:00
|
|
|
while ((newInfo = [currentInfos nextObject]))
|
|
|
|
{
|
2016-04-12 22:11:21 +02:00
|
|
|
if (![owner isEqualToString: userLogin])
|
|
|
|
{
|
|
|
|
role = [currentFolder roleForComponentsWithAccessClass: [[newInfo objectForKey: @"c_classification"] intValue]
|
|
|
|
forUser : userLogin];
|
|
|
|
|
|
|
|
if ([role isEqualToString: @"ComponentDAndTViewer"])
|
|
|
|
{
|
|
|
|
// We skip results that could lead to information "exposure".
|
|
|
|
// See http://sogo.nu/bugs/view.php?id=3619
|
|
|
|
if (searchByTitleOrContent)
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2014-09-12 14:34:15 +02:00
|
|
|
if ([fields containsObject: @"editable"])
|
|
|
|
{
|
|
|
|
if (folderIsRemote)
|
|
|
|
// .ics subscriptions are not editable
|
|
|
|
[newInfo setObject: [NSNumber numberWithInt: 0]
|
|
|
|
forKey: @"editable"];
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Identifies whether the active user can edit the event.
|
|
|
|
role = [currentFolder roleForComponentsWithAccessClass:[[newInfo objectForKey: @"c_classification"] intValue]
|
|
|
|
forUser: userLogin];
|
|
|
|
if ([role isEqualToString: @"ComponentModifier"] || [role length] == 0)
|
|
|
|
[newInfo setObject: [NSNumber numberWithInt: 1]
|
|
|
|
forKey: @"editable"];
|
|
|
|
else
|
|
|
|
[newInfo setObject: [NSNumber numberWithInt: 0]
|
|
|
|
forKey: @"editable"];
|
|
|
|
}
|
|
|
|
}
|
2014-05-08 23:17:05 +02:00
|
|
|
if ([fields containsObject: @"ownerIsOrganizer"])
|
2014-09-12 14:34:15 +02:00
|
|
|
{
|
|
|
|
// Identifies whether the active user is the organizer
|
|
|
|
// of this event.
|
|
|
|
NSString *c_orgmail;
|
|
|
|
c_orgmail = [newInfo objectForKey: @"c_orgmail"];
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2014-09-12 14:34:15 +02:00
|
|
|
if ([c_orgmail isKindOfClass: [NSString class]] && [ownerUser hasEmail: c_orgmail])
|
|
|
|
[newInfo setObject: [NSNumber numberWithInt: 1]
|
|
|
|
forKey: @"ownerIsOrganizer"];
|
|
|
|
else
|
|
|
|
[newInfo setObject: [NSNumber numberWithInt: 0]
|
|
|
|
forKey: @"ownerIsOrganizer"];
|
|
|
|
}
|
2010-01-21 21:44:17 +01:00
|
|
|
if (isErasable)
|
2014-09-12 14:34:15 +02:00
|
|
|
[newInfo setObject: [NSNumber numberWithInt: 1]
|
|
|
|
forKey: @"erasable"];
|
2010-01-21 21:44:17 +01:00
|
|
|
else
|
2014-09-12 14:34:15 +02:00
|
|
|
[newInfo setObject: [NSNumber numberWithInt: 0]
|
|
|
|
forKey: @"erasable"];
|
2014-05-13 19:21:18 +02:00
|
|
|
|
2010-01-21 21:44:17 +01:00
|
|
|
[newInfo setObject: [currentFolder nameInContainer]
|
2014-09-12 14:34:15 +02:00
|
|
|
forKey: @"c_folder"];
|
|
|
|
[newInfo setObject: [currentFolder ownerInContext: context]
|
|
|
|
forKey: @"c_owner"];
|
|
|
|
calendarName = [currentFolder displayName];
|
|
|
|
if (calendarName == nil)
|
|
|
|
calendarName = @"";
|
|
|
|
[newInfo setObject: calendarName
|
|
|
|
forKey: @"calendarName"];
|
|
|
|
if (![[newInfo objectForKey: @"c_title"] length])
|
|
|
|
[self _fixComponentTitle: newInfo withType: component];
|
|
|
|
|
2010-04-19 23:05:35 +02:00
|
|
|
// Possible improvement: only call _fixDates if event is recurrent
|
|
|
|
// or the view range span a daylight saving time change
|
2014-09-12 14:34:15 +02:00
|
|
|
[self _fixDates: newInfo];
|
|
|
|
newInfoForComponent = [NSMutableArray arrayWithArray: [newInfo objectsForKeys: fields
|
|
|
|
notFoundMarker: marker]];
|
|
|
|
// Escape HTML
|
|
|
|
count = [newInfoForComponent count];
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
currentInfo = [newInfoForComponent objectAtIndex: i];
|
2016-12-30 16:08:18 +01:00
|
|
|
if (![currentInfo isEqual:[NSNull null]] && [currentInfo respondsToSelector: @selector (stringByEscapingHTMLString)])
|
2014-09-12 14:34:15 +02:00
|
|
|
[newInfoForComponent replaceObjectAtIndex: i withObject: [currentInfo stringByEscapingHTMLString]];
|
|
|
|
}
|
|
|
|
[infos addObject: newInfoForComponent];
|
|
|
|
}
|
2009-07-21 20:06:55 +02:00
|
|
|
}
|
2007-06-07 22:49:06 +02:00
|
|
|
}
|
2015-05-13 20:36:35 +02:00
|
|
|
|
2015-05-13 20:52:10 +02:00
|
|
|
[infos sortUsingSelector: @selector(compareEventsStartDateAscending:)];
|
2015-05-13 20:36:35 +02:00
|
|
|
|
2007-10-09 19:19:20 +02:00
|
|
|
return infos;
|
2007-06-07 22:49:06 +02:00
|
|
|
}
|
|
|
|
|
2014-06-27 23:00:32 +02:00
|
|
|
- (WOResponse *) _responseWithData: (id) data
|
2007-06-07 22:49:06 +02:00
|
|
|
{
|
|
|
|
WOResponse *response;
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2007-09-11 21:36:40 +02:00
|
|
|
response = [self responseWithStatus: 200];
|
2007-06-07 22:49:06 +02:00
|
|
|
[response appendContentString: [data jsonRepresentation]];
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2007-06-07 22:49:06 +02:00
|
|
|
return response;
|
|
|
|
}
|
|
|
|
|
2007-06-19 20:08:16 +02:00
|
|
|
- (NSString *) _formattedDateForSeconds: (unsigned int) seconds
|
2014-05-08 23:17:05 +02:00
|
|
|
forAllDay: (BOOL) forAllDay
|
2007-06-19 20:08:16 +02:00
|
|
|
{
|
|
|
|
NSCalendarDate *date;
|
|
|
|
NSString *formattedDate;
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2007-06-19 20:08:16 +02:00
|
|
|
date = [NSCalendarDate dateWithTimeIntervalSince1970: seconds];
|
2008-11-07 19:56:03 +01:00
|
|
|
// Adjust for daylight saving time? (wrt to startDate)
|
2011-06-13 22:28:10 +02:00
|
|
|
//NSLog(@"***[UIxCalListingActions _formattedDateForSeconds] user timezone is %@", userTimeZone);
|
2007-06-19 20:08:16 +02:00
|
|
|
[date setTimeZone: userTimeZone];
|
|
|
|
if (forAllDay)
|
|
|
|
formattedDate = [dateFormatter formattedDate: date];
|
|
|
|
else
|
|
|
|
formattedDate = [dateFormatter formattedDateAndTime: date];
|
2014-05-08 23:17:05 +02:00
|
|
|
|
|
|
|
return formattedDate;
|
2007-06-19 20:08:16 +02:00
|
|
|
}
|
|
|
|
|
2009-04-21 17:20:52 +02:00
|
|
|
//
|
|
|
|
// We return:
|
2014-05-08 23:17:05 +02:00
|
|
|
//
|
2009-04-22 23:02:11 +02:00
|
|
|
// [[calendar name (full path), complete Event ID (full path), Fire date (UTC)], ..]
|
2009-04-21 17:20:52 +02:00
|
|
|
//
|
|
|
|
// Called when each module is loaded or whenever a calendar component is created, modified, deleted
|
|
|
|
// or whenever there's a {un}subscribe to a calendar.
|
|
|
|
//
|
|
|
|
// Workflow :
|
|
|
|
//
|
|
|
|
// - for ALL subscribed and ACTIVE calendars
|
2009-04-22 23:02:11 +02:00
|
|
|
// - returns alarms that will occur in the next 48 hours or the non-triggered alarms
|
|
|
|
// for non-completed events
|
2009-04-21 17:20:52 +02:00
|
|
|
//
|
|
|
|
- (WOResponse *) alarmsListAction
|
|
|
|
{
|
|
|
|
SOGoAppointmentFolder *currentFolder;
|
|
|
|
SOGoAppointmentFolders *clientObject;
|
|
|
|
NSMutableArray *allAlarms;
|
|
|
|
NSEnumerator *folders;
|
|
|
|
WOResponse *response;
|
2009-04-22 23:02:11 +02:00
|
|
|
unsigned int browserTime, laterTime;
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2009-04-21 17:20:52 +02:00
|
|
|
browserTime = [[[context request] formValueForKey: @"browserTime"] intValue];
|
2017-01-06 17:48:10 +01:00
|
|
|
|
|
|
|
if (browserTime)
|
2009-04-21 17:20:52 +02:00
|
|
|
{
|
2017-01-06 17:48:10 +01:00
|
|
|
// We look for alarms in the next 48 hours
|
|
|
|
laterTime = browserTime + 60*60*48;
|
|
|
|
clientObject = [self clientObject];
|
|
|
|
allAlarms = [NSMutableArray array];
|
|
|
|
|
|
|
|
folders = [[clientObject subFolders] objectEnumerator];
|
|
|
|
while ((currentFolder = [folders nextObject]))
|
2014-05-08 23:17:05 +02:00
|
|
|
{
|
2017-01-06 17:48:10 +01:00
|
|
|
if ([currentFolder isActive] && [currentFolder showCalendarAlarms])
|
|
|
|
{
|
|
|
|
NSDictionary *entry;
|
|
|
|
NSArray *alarms;
|
|
|
|
int i;
|
2014-09-12 14:34:15 +02:00
|
|
|
|
2017-01-06 17:48:10 +01:00
|
|
|
alarms = [currentFolder fetchAlarmInfosFrom: [NSNumber numberWithInt: browserTime]
|
|
|
|
to: [NSNumber numberWithInt: laterTime]];
|
2014-09-12 14:34:15 +02:00
|
|
|
|
2017-01-06 17:48:10 +01:00
|
|
|
for (i = 0; i < [alarms count]; i++)
|
|
|
|
{
|
|
|
|
entry = [alarms objectAtIndex: i];
|
2014-09-12 14:34:15 +02:00
|
|
|
|
2017-01-06 17:48:10 +01:00
|
|
|
[allAlarms addObject: [NSArray arrayWithObjects:
|
|
|
|
[currentFolder nameInContainer],
|
|
|
|
[entry objectForKey: @"c_name"],
|
|
|
|
[entry objectForKey: @"c_nextalarm"],
|
|
|
|
nil]];
|
|
|
|
}
|
2014-09-12 14:34:15 +02:00
|
|
|
}
|
2014-05-08 23:17:05 +02:00
|
|
|
}
|
2017-01-06 17:48:10 +01:00
|
|
|
|
|
|
|
response = [self responseWithStatus: 200];
|
|
|
|
[response appendContentString: [allAlarms jsonRepresentation]];
|
2009-04-21 17:20:52 +02:00
|
|
|
}
|
2017-01-06 17:48:10 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
response = (WOResponse *) [NSException exceptionWithHTTPStatus: 400
|
|
|
|
reason: @"missing 'browserTime' parameter"];
|
|
|
|
}
|
|
|
|
|
2009-04-21 17:20:52 +02:00
|
|
|
return response;
|
|
|
|
}
|
|
|
|
|
2009-08-20 21:20:12 +02:00
|
|
|
- (void) checkFilterValue
|
|
|
|
{
|
|
|
|
NSString *filter;
|
2009-11-29 05:19:32 +01:00
|
|
|
SOGoUserSettings *us;
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2009-08-20 21:20:12 +02:00
|
|
|
filter = [[context request] formValueForKey: @"filterpopup"];
|
2009-11-29 05:19:32 +01:00
|
|
|
if ([filter length]
|
2009-08-20 21:20:12 +02:00
|
|
|
&& ![filter isEqualToString: @"view_all"]
|
|
|
|
&& ![filter isEqualToString: @"view_future"])
|
2014-05-08 23:17:05 +02:00
|
|
|
{
|
|
|
|
us = [[context activeUser] userSettings];
|
|
|
|
[us setObject: filter forKey: @"CalendarDefaultFilter"];
|
|
|
|
[us synchronize];
|
|
|
|
}
|
2009-08-20 21:20:12 +02:00
|
|
|
}
|
|
|
|
|
2007-06-07 22:49:06 +02:00
|
|
|
- (WOResponse *) eventsListAction
|
|
|
|
{
|
2008-07-16 23:48:54 +02:00
|
|
|
NSArray *oldEvent;
|
2007-06-11 23:28:28 +02:00
|
|
|
NSEnumerator *events;
|
|
|
|
NSMutableArray *newEvents, *newEvent;
|
2008-07-16 23:48:54 +02:00
|
|
|
unsigned int interval;
|
2007-06-19 20:08:16 +02:00
|
|
|
BOOL isAllDay;
|
2008-07-16 23:48:54 +02:00
|
|
|
NSString *sort, *ascending;
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2007-06-07 22:49:06 +02:00
|
|
|
[self _setupContext];
|
2009-08-20 21:20:12 +02:00
|
|
|
[self checkFilterValue];
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2007-06-11 23:28:28 +02:00
|
|
|
newEvents = [NSMutableArray array];
|
2008-07-16 04:12:18 +02:00
|
|
|
events = [[self _fetchFields: eventsFields
|
2014-05-08 23:17:05 +02:00
|
|
|
forComponentOfType: @"vevent"] objectEnumerator];
|
2008-07-16 04:12:18 +02:00
|
|
|
while ((oldEvent = [events nextObject]))
|
2014-05-08 23:17:05 +02:00
|
|
|
{
|
|
|
|
newEvent = [NSMutableArray arrayWithArray: oldEvent];
|
|
|
|
isAllDay = [[oldEvent objectAtIndex: eventIsAllDayIndex] boolValue];
|
|
|
|
interval = [[oldEvent objectAtIndex: eventStartDateIndex] intValue];
|
|
|
|
[newEvent addObject: [self _formattedDateForSeconds: interval
|
|
|
|
forAllDay: isAllDay]];
|
|
|
|
interval = [[oldEvent objectAtIndex: eventEndDateIndex] intValue];
|
|
|
|
[newEvent addObject: [self _formattedDateForSeconds: interval
|
|
|
|
forAllDay: isAllDay]];
|
|
|
|
[newEvents addObject: newEvent];
|
|
|
|
}
|
2007-12-06 18:29:32 +01:00
|
|
|
|
|
|
|
sort = [[context request] formValueForKey: @"sort"];
|
|
|
|
if ([sort isEqualToString: @"title"])
|
|
|
|
[newEvents sortUsingSelector: @selector (compareEventsTitleAscending:)];
|
|
|
|
else if ([sort isEqualToString: @"end"])
|
|
|
|
[newEvents sortUsingSelector: @selector (compareEventsEndDateAscending:)];
|
|
|
|
else if ([sort isEqualToString: @"location"])
|
|
|
|
[newEvents sortUsingSelector: @selector (compareEventsLocationAscending:)];
|
2010-10-13 17:08:41 +02:00
|
|
|
else if ([sort isEqualToString: @"calendarName"])
|
2010-10-13 17:02:39 +02:00
|
|
|
[newEvents sortUsingSelector: @selector (compareEventsCalendarNameAscending:)];
|
2007-12-06 18:29:32 +01:00
|
|
|
else
|
|
|
|
[newEvents sortUsingSelector: @selector (compareEventsStartDateAscending:)];
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2007-12-06 18:29:32 +01:00
|
|
|
ascending = [[context request] formValueForKey: @"asc"];
|
|
|
|
if (![ascending boolValue])
|
2007-12-17 16:29:06 +01:00
|
|
|
[newEvents reverseArray];
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2007-06-11 23:28:28 +02:00
|
|
|
return [self _responseWithData: newEvents];
|
2007-06-07 22:49:06 +02:00
|
|
|
}
|
|
|
|
|
2014-05-08 23:17:05 +02:00
|
|
|
static inline void _feedBlockWithDayBasedData (NSMutableDictionary *block, unsigned int start,
|
|
|
|
unsigned int end, unsigned int dayStart)
|
2008-07-16 04:12:18 +02:00
|
|
|
{
|
2008-12-30 21:20:41 +01:00
|
|
|
unsigned int delta, quarterStart, length, swap;
|
|
|
|
|
|
|
|
if (start > end)
|
2014-05-08 23:17:05 +02:00
|
|
|
{
|
|
|
|
swap = end;
|
|
|
|
end = start;
|
|
|
|
start = swap;
|
|
|
|
}
|
2008-07-16 04:12:18 +02:00
|
|
|
quarterStart = (start - dayStart) / quarterLength;
|
|
|
|
delta = end - dayStart;
|
|
|
|
if ((delta % quarterLength))
|
|
|
|
delta += quarterLength;
|
|
|
|
length = (delta / quarterLength) - quarterStart;
|
|
|
|
if (!length)
|
|
|
|
length = 1;
|
|
|
|
[block setObject: [NSNumber numberWithUnsignedInt: quarterStart]
|
2014-05-08 23:17:05 +02:00
|
|
|
forKey: @"start"];
|
2008-07-16 04:12:18 +02:00
|
|
|
[block setObject: [NSNumber numberWithUnsignedInt: length]
|
2014-05-08 23:17:05 +02:00
|
|
|
forKey: @"length"];
|
2008-07-16 04:12:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
2010-10-15 22:51:00 +02:00
|
|
|
_feedBlockWithMonthBasedData (NSMutableDictionary *block, unsigned int start,
|
|
|
|
NSTimeZone *userTimeZone,
|
|
|
|
SOGoDateFormatter *dateFormatter)
|
2008-07-16 04:12:18 +02:00
|
|
|
{
|
|
|
|
NSCalendarDate *eventStartDate;
|
|
|
|
NSString *startHour;
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2008-07-16 04:12:18 +02:00
|
|
|
eventStartDate = [NSCalendarDate dateWithTimeIntervalSince1970: start];
|
|
|
|
[eventStartDate setTimeZone: userTimeZone];
|
|
|
|
startHour = [dateFormatter formattedTime: eventStartDate];
|
|
|
|
[block setObject: startHour forKey: @"starthour"];
|
|
|
|
[block setObject: [NSNumber numberWithUnsignedInt: start]
|
2014-05-08 23:17:05 +02:00
|
|
|
forKey: @"start"];
|
2008-07-16 04:12:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSMutableDictionary *) _eventBlockWithStart: (unsigned int) start
|
2014-05-08 23:17:05 +02:00
|
|
|
end: (unsigned int) end
|
|
|
|
number: (NSNumber *) number
|
|
|
|
onDay: (unsigned int) dayStart
|
|
|
|
recurrenceTime: (unsigned int) recurrenceTime
|
|
|
|
userState: (iCalPersonPartStat) userState
|
2008-07-16 04:12:18 +02:00
|
|
|
{
|
|
|
|
NSMutableDictionary *block;
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2008-07-16 04:12:18 +02:00
|
|
|
block = [NSMutableDictionary dictionary];
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2008-07-16 04:12:18 +02:00
|
|
|
if (dayBasedView)
|
|
|
|
_feedBlockWithDayBasedData (block, start, end, dayStart);
|
|
|
|
else
|
|
|
|
_feedBlockWithMonthBasedData (block, start, userTimeZone, dateFormatter);
|
2008-07-29 18:35:49 +02:00
|
|
|
[block setObject: number forKey: @"nbr"];
|
2008-07-17 23:12:43 +02:00
|
|
|
if (recurrenceTime)
|
|
|
|
[block setObject: [NSNumber numberWithInt: recurrenceTime]
|
2014-05-08 23:17:05 +02:00
|
|
|
forKey: @"recurrenceTime"];
|
2008-07-16 23:48:54 +02:00
|
|
|
if (userState != iCalPersonPartStatOther)
|
|
|
|
[block setObject: [NSNumber numberWithInt: userState]
|
2014-05-08 23:17:05 +02:00
|
|
|
forKey: @"userState"];
|
|
|
|
|
2008-07-16 04:12:18 +02:00
|
|
|
return block;
|
|
|
|
}
|
|
|
|
|
2008-07-16 23:48:54 +02:00
|
|
|
static inline iCalPersonPartStat
|
|
|
|
_userStateInEvent (NSArray *event)
|
|
|
|
{
|
|
|
|
unsigned int count, max;
|
|
|
|
iCalPersonPartStat state;
|
|
|
|
NSString *partList, *stateList;
|
|
|
|
NSArray *participants, *states;
|
|
|
|
SOGoUser *user;
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2008-07-16 23:48:54 +02:00
|
|
|
participants = nil;
|
|
|
|
state = iCalPersonPartStatOther;
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2010-10-13 17:02:39 +02:00
|
|
|
partList = [event objectAtIndex: eventPartMailsIndex];
|
|
|
|
stateList = [event objectAtIndex: eventPartStatesIndex];
|
2008-07-16 23:48:54 +02:00
|
|
|
if ([partList length] && [stateList length])
|
2014-05-08 23:17:05 +02:00
|
|
|
{
|
|
|
|
participants = [partList componentsSeparatedByString: @"\n"];
|
|
|
|
states = [stateList componentsSeparatedByString: @"\n"];
|
|
|
|
count = 0;
|
|
|
|
max = [participants count];
|
|
|
|
while (state == iCalPersonPartStatOther && count < max)
|
2008-07-16 23:48:54 +02:00
|
|
|
{
|
2014-05-08 23:17:05 +02:00
|
|
|
user = [SOGoUser userWithLogin: [event objectAtIndex: eventOwnerIndex]
|
|
|
|
roles: nil];
|
|
|
|
if ([user hasEmail: [participants objectAtIndex: count]])
|
|
|
|
state = [[states objectAtIndex: count] intValue];
|
|
|
|
else
|
|
|
|
count++;
|
2008-07-16 23:48:54 +02:00
|
|
|
}
|
2014-05-08 23:17:05 +02:00
|
|
|
}
|
|
|
|
|
2008-07-16 23:48:54 +02:00
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
2008-07-16 04:12:18 +02:00
|
|
|
- (void) _fillBlocks: (NSArray *) blocks
|
2014-05-08 23:17:05 +02:00
|
|
|
withEvent: (NSArray *) event
|
|
|
|
withNumber: (NSNumber *) number
|
2008-07-16 04:12:18 +02:00
|
|
|
{
|
2009-07-03 21:46:01 +02:00
|
|
|
int currentDayStart, startSecs, endsSecs, currentStart, eventStart,
|
2014-05-08 23:17:05 +02:00
|
|
|
eventEnd, computedEventEnd, offset, recurrenceTime, swap;
|
2008-07-16 04:12:18 +02:00
|
|
|
NSMutableArray *currentDay;
|
|
|
|
NSMutableDictionary *eventBlock;
|
2008-07-16 23:48:54 +02:00
|
|
|
iCalPersonPartStat userState;
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2010-10-13 17:02:39 +02:00
|
|
|
eventStart = [[event objectAtIndex: eventStartDateIndex] intValue];
|
2009-07-03 21:46:01 +02:00
|
|
|
if (eventStart < 0)
|
|
|
|
[self errorWithFormat: @"event '%@' has negative start: %d (skipped)",
|
2014-05-08 23:17:05 +02:00
|
|
|
[event objectAtIndex: eventNameIndex], eventStart];
|
2008-07-16 04:12:18 +02:00
|
|
|
else
|
2014-05-08 23:17:05 +02:00
|
|
|
{
|
|
|
|
eventEnd = [[event objectAtIndex: eventEndDateIndex] intValue];
|
|
|
|
if (eventEnd < 0)
|
|
|
|
[self errorWithFormat: @"event '%@' has negative end: %d (skipped)",
|
|
|
|
[event objectAtIndex: eventNameIndex], eventEnd];
|
|
|
|
else
|
2008-07-16 04:12:18 +02:00
|
|
|
{
|
2014-05-08 23:17:05 +02:00
|
|
|
if (eventEnd < eventStart)
|
|
|
|
{
|
|
|
|
swap = eventStart;
|
|
|
|
eventStart = eventEnd;
|
|
|
|
eventEnd = swap;
|
|
|
|
[self warnWithFormat: @"event '%@' has end < start: %d < %d",
|
|
|
|
[event objectAtIndex: eventNameIndex], eventEnd, eventStart];
|
|
|
|
}
|
|
|
|
|
|
|
|
startSecs = (unsigned int) [startDate timeIntervalSince1970];
|
|
|
|
endsSecs = (unsigned int) [endDate timeIntervalSince1970];
|
|
|
|
|
|
|
|
if ([[event objectAtIndex: eventIsCycleIndex] boolValue])
|
|
|
|
recurrenceTime = [[event objectAtIndex: eventRecurrenceIdIndex] unsignedIntValue];
|
|
|
|
else
|
|
|
|
recurrenceTime = 0;
|
|
|
|
|
|
|
|
currentStart = eventStart;
|
|
|
|
if (currentStart < startSecs)
|
|
|
|
{
|
|
|
|
currentStart = startSecs;
|
|
|
|
offset = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
offset = ((currentStart - startSecs)
|
|
|
|
/ dayLength);
|
|
|
|
if (offset >= [blocks count])
|
|
|
|
[self errorWithFormat: @"event '%@' has a computed offset that"
|
|
|
|
@" overflows the amount of blocks (skipped)",
|
|
|
|
[event objectAtIndex: eventNameIndex]];
|
2009-07-03 21:46:01 +02:00
|
|
|
else
|
2014-05-08 23:17:05 +02:00
|
|
|
{
|
|
|
|
currentDay = [blocks objectAtIndex: offset];
|
|
|
|
currentDayStart = startSecs + dayLength * offset;
|
|
|
|
|
|
|
|
if (eventEnd > endsSecs)
|
|
|
|
eventEnd = endsSecs;
|
|
|
|
|
|
|
|
if (eventEnd < startSecs)
|
|
|
|
// The event doesn't end in the covered period.
|
|
|
|
// This special case occurs with a DST change.
|
|
|
|
return;
|
|
|
|
|
|
|
|
userState = _userStateInEvent (event);
|
|
|
|
while (currentDayStart + dayLength < eventEnd)
|
2009-07-03 21:46:01 +02:00
|
|
|
{
|
2014-05-08 23:17:05 +02:00
|
|
|
eventBlock = [self _eventBlockWithStart: currentStart
|
|
|
|
end: currentDayStart + dayLength - 1
|
|
|
|
number: number
|
|
|
|
onDay: currentDayStart
|
|
|
|
recurrenceTime: recurrenceTime
|
|
|
|
userState: userState];
|
|
|
|
[currentDay addObject: eventBlock];
|
|
|
|
currentDayStart += dayLength;
|
|
|
|
currentStart = currentDayStart;
|
|
|
|
offset++;
|
|
|
|
currentDay = [blocks objectAtIndex: offset];
|
|
|
|
}
|
|
|
|
|
2012-09-19 16:54:57 +02:00
|
|
|
computedEventEnd = eventEnd;
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2012-09-19 16:54:57 +02:00
|
|
|
// We add 5 mins to the end date of an event if the end date
|
|
|
|
// is equal or smaller than the event's start date.
|
|
|
|
if (eventEnd <= currentStart)
|
2014-05-08 23:17:05 +02:00
|
|
|
computedEventEnd = currentStart + (5*60);
|
2012-09-19 16:54:57 +02:00
|
|
|
|
|
|
|
eventBlock = [self _eventBlockWithStart: currentStart
|
2014-05-08 23:17:05 +02:00
|
|
|
end: computedEventEnd
|
|
|
|
number: number
|
|
|
|
onDay: currentDayStart
|
|
|
|
recurrenceTime: recurrenceTime
|
|
|
|
userState: userState];
|
2012-09-19 16:54:57 +02:00
|
|
|
[currentDay addObject: eventBlock];
|
2011-02-22 21:29:04 +01:00
|
|
|
}
|
2008-07-16 04:12:18 +02:00
|
|
|
}
|
2014-05-08 23:17:05 +02:00
|
|
|
}
|
2008-07-16 04:12:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) _prepareEventBlocks: (NSMutableArray **) blocks
|
2014-05-08 23:17:05 +02:00
|
|
|
withAllDays: (NSMutableArray **) allDayBlocks
|
2008-07-16 04:12:18 +02:00
|
|
|
{
|
|
|
|
unsigned int count, nbrDays;
|
|
|
|
int seconds;
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2008-07-16 04:12:18 +02:00
|
|
|
seconds = [endDate timeIntervalSinceDate: startDate];
|
|
|
|
if (seconds > 0)
|
2014-05-08 23:17:05 +02:00
|
|
|
{
|
|
|
|
nbrDays = 1 + (unsigned int) (seconds / dayLength);
|
|
|
|
*blocks = [NSMutableArray arrayWithCapacity: nbrDays];
|
|
|
|
*allDayBlocks = [NSMutableArray arrayWithCapacity: nbrDays];
|
|
|
|
for (count = 0; count < nbrDays; count++)
|
2008-07-16 04:12:18 +02:00
|
|
|
{
|
2014-05-08 23:17:05 +02:00
|
|
|
[*blocks addObject: [NSMutableArray array]];
|
|
|
|
[*allDayBlocks addObject: [NSMutableArray array]];
|
2008-07-16 04:12:18 +02:00
|
|
|
}
|
2014-05-08 23:17:05 +02:00
|
|
|
}
|
2008-07-16 04:12:18 +02:00
|
|
|
else
|
2014-05-08 23:17:05 +02:00
|
|
|
{
|
|
|
|
*blocks = nil;
|
|
|
|
*allDayBlocks = nil;
|
|
|
|
}
|
2008-07-16 04:12:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSArray *) _horizontalBlocks: (NSMutableArray *) day
|
|
|
|
{
|
|
|
|
NSMutableArray *quarters[96];
|
|
|
|
NSMutableArray *currentBlock, *blocks;
|
|
|
|
NSDictionary *currentEvent;
|
|
|
|
unsigned int count, max, qCount, qMax, qOffset;
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2008-07-16 04:12:18 +02:00
|
|
|
blocks = [NSMutableArray array];
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2008-07-16 04:12:18 +02:00
|
|
|
bzero (quarters, 96 * sizeof (NSMutableArray *));
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2008-07-16 04:12:18 +02:00
|
|
|
max = [day count];
|
|
|
|
for (count = 0; count < max; count++)
|
2014-05-08 23:17:05 +02:00
|
|
|
{
|
|
|
|
currentEvent = [day objectAtIndex: count];
|
|
|
|
qMax = [[currentEvent objectForKey: @"length"] unsignedIntValue];
|
|
|
|
qOffset = [[currentEvent objectForKey: @"start"] unsignedIntValue];
|
|
|
|
for (qCount = 0; qCount < qMax; qCount++)
|
2008-07-16 04:12:18 +02:00
|
|
|
{
|
2014-05-08 23:17:05 +02:00
|
|
|
currentBlock = quarters[qCount + qOffset];
|
|
|
|
if (!currentBlock)
|
2008-07-16 04:12:18 +02:00
|
|
|
{
|
|
|
|
currentBlock = [NSMutableArray array];
|
|
|
|
quarters[qCount + qOffset] = currentBlock;
|
|
|
|
[blocks addObject: currentBlock];
|
|
|
|
}
|
2014-05-08 23:17:05 +02:00
|
|
|
[currentBlock addObject: currentEvent];
|
2008-07-16 04:12:18 +02:00
|
|
|
}
|
2014-05-08 23:17:05 +02:00
|
|
|
}
|
|
|
|
|
2008-07-16 04:12:18 +02:00
|
|
|
return blocks;
|
|
|
|
}
|
|
|
|
|
2014-05-08 23:17:05 +02:00
|
|
|
static inline unsigned int _computeMaxBlockSiblings (NSArray *block)
|
2008-07-16 04:12:18 +02:00
|
|
|
{
|
|
|
|
unsigned int count, max, maxSiblings, siblings;
|
|
|
|
NSNumber *nbrEvents;
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2008-07-16 04:12:18 +02:00
|
|
|
max = [block count];
|
|
|
|
maxSiblings = max;
|
|
|
|
for (count = 0; count < max; count++)
|
2014-05-08 23:17:05 +02:00
|
|
|
{
|
|
|
|
nbrEvents = [[block objectAtIndex: count] objectForKey: @"siblings"];
|
|
|
|
if (nbrEvents)
|
2008-07-16 04:12:18 +02:00
|
|
|
{
|
2014-05-08 23:17:05 +02:00
|
|
|
siblings = [nbrEvents unsignedIntValue];
|
|
|
|
if (siblings > maxSiblings)
|
|
|
|
maxSiblings = siblings;
|
2008-07-16 04:12:18 +02:00
|
|
|
}
|
2014-05-08 23:17:05 +02:00
|
|
|
}
|
|
|
|
|
2008-07-16 04:12:18 +02:00
|
|
|
return maxSiblings;
|
|
|
|
}
|
|
|
|
|
2014-05-08 23:17:05 +02:00
|
|
|
static inline void _propagateBlockSiblings (NSArray *block, NSNumber *maxSiblings)
|
2008-07-16 04:12:18 +02:00
|
|
|
{
|
|
|
|
unsigned int count, max;
|
|
|
|
NSMutableDictionary *event;
|
|
|
|
NSNumber *realSiblings;
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2008-07-16 04:12:18 +02:00
|
|
|
max = [block count];
|
|
|
|
realSiblings = [NSNumber numberWithUnsignedInt: max];
|
|
|
|
for (count = 0; count < max; count++)
|
2014-05-08 23:17:05 +02:00
|
|
|
{
|
|
|
|
event = [block objectAtIndex: count];
|
|
|
|
[event setObject: maxSiblings forKey: @"siblings"];
|
|
|
|
[event setObject: realSiblings forKey: @"realSiblings"];
|
|
|
|
}
|
2008-07-16 04:12:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* this requires two vertical passes */
|
2014-05-08 23:17:05 +02:00
|
|
|
static inline void _computeBlocksSiblings (NSArray *blocks)
|
2008-07-16 04:12:18 +02:00
|
|
|
{
|
|
|
|
NSArray *currentBlock;
|
|
|
|
unsigned int count, max, maxSiblings;
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2008-07-16 04:12:18 +02:00
|
|
|
max = [blocks count];
|
|
|
|
for (count = 0; count < max; count++)
|
2014-05-08 23:17:05 +02:00
|
|
|
{
|
|
|
|
currentBlock = [blocks objectAtIndex: count];
|
|
|
|
maxSiblings = _computeMaxBlockSiblings (currentBlock);
|
|
|
|
_propagateBlockSiblings (currentBlock,
|
|
|
|
[NSNumber numberWithUnsignedInt: maxSiblings]);
|
|
|
|
}
|
2008-07-16 04:12:18 +02:00
|
|
|
}
|
|
|
|
|
2014-05-08 23:17:05 +02:00
|
|
|
static inline void _computeBlockPosition (NSArray *block)
|
2008-07-16 04:12:18 +02:00
|
|
|
{
|
|
|
|
unsigned int count, max, j, siblings;
|
|
|
|
NSNumber *position;
|
|
|
|
NSMutableDictionary *event;
|
|
|
|
NSMutableDictionary **positions;
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2008-07-16 04:12:18 +02:00
|
|
|
max = [block count];
|
|
|
|
event = [block objectAtIndex: 0];
|
|
|
|
siblings = [[event objectForKey: @"siblings"] unsignedIntValue];
|
2009-06-04 01:06:52 +02:00
|
|
|
positions = NSZoneCalloc (NULL, siblings, sizeof (NSMutableDictionary *));
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2008-07-16 04:12:18 +02:00
|
|
|
for (count = 0; count < max; count++)
|
2014-05-08 23:17:05 +02:00
|
|
|
{
|
|
|
|
event = [block objectAtIndex: count];
|
|
|
|
position = [event objectForKey: @"position"];
|
|
|
|
if (position)
|
|
|
|
*(positions + [position unsignedIntValue]) = event;
|
|
|
|
else
|
2008-07-16 04:12:18 +02:00
|
|
|
{
|
2014-05-08 23:17:05 +02:00
|
|
|
j = 0;
|
|
|
|
while (j < max && *(positions + j))
|
|
|
|
j++;
|
|
|
|
*(positions + j) = event;
|
|
|
|
[event setObject: [NSNumber numberWithUnsignedInt: j]
|
|
|
|
forKey: @"position"];
|
2008-07-16 04:12:18 +02:00
|
|
|
}
|
2014-05-08 23:17:05 +02:00
|
|
|
}
|
|
|
|
|
2009-06-04 01:06:52 +02:00
|
|
|
NSZoneFree (NULL, positions);
|
2008-07-16 04:12:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// static inline void
|
|
|
|
// _addBlockMultipliers (NSArray *block, NSMutableDictionary **positions)
|
|
|
|
// {
|
|
|
|
// unsigned int count, max, limit, multiplier;
|
|
|
|
// NSMutableDictionary *currentEvent, *event;
|
|
|
|
|
|
|
|
// max = [block count];
|
|
|
|
// event = [block objectAtIndex: 0];
|
|
|
|
// limit = [[event objectForKey: @"siblings"] unsignedIntValue];
|
|
|
|
|
|
|
|
// if (max < limit)
|
|
|
|
// {
|
|
|
|
// currentEvent = nil;
|
|
|
|
// for (count = 0; count < limit; count++)
|
|
|
|
// {
|
|
|
|
// multiplier = 1;
|
|
|
|
// event = positions[count];
|
|
|
|
// if ([[event objectForKey: @"realSiblings"] unsignedIntValue]
|
|
|
|
// < limit)
|
|
|
|
// {
|
|
|
|
// if (event)
|
|
|
|
// {
|
|
|
|
// if (currentEvent && multiplier > 1)
|
|
|
|
// [currentEvent setObject: [NSNumber numberWithUnsignedInt: multiplier]
|
|
|
|
// forKey: @"multiplier"];
|
|
|
|
// currentEvent = event;
|
|
|
|
// multiplier = 1;
|
|
|
|
// }
|
|
|
|
// else
|
|
|
|
// multiplier++;
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
_computeBlocksPosition (NSArray *blocks)
|
|
|
|
{
|
|
|
|
NSArray *block;
|
|
|
|
unsigned int count, max;
|
2014-05-08 23:17:05 +02:00
|
|
|
// NSMutableDictionary **positions;
|
|
|
|
|
2008-07-16 04:12:18 +02:00
|
|
|
max = [blocks count];
|
|
|
|
for (count = 0; count < max; count++)
|
2014-05-08 23:17:05 +02:00
|
|
|
{
|
|
|
|
block = [blocks objectAtIndex: count];
|
|
|
|
_computeBlockPosition (block);
|
|
|
|
// _addBlockMultipliers (block, positions);
|
|
|
|
// NSZoneFree (NULL, positions);
|
|
|
|
}
|
2008-07-16 04:12:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) _addBlocksWidth: (NSMutableArray *) day
|
|
|
|
{
|
|
|
|
NSArray *blocks;
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2008-07-16 04:12:18 +02:00
|
|
|
blocks = [self _horizontalBlocks: day];
|
|
|
|
_computeBlocksSiblings (blocks);
|
|
|
|
_computeBlocksSiblings (blocks);
|
|
|
|
_computeBlocksPosition (blocks);
|
|
|
|
/* ... _computeBlocksMultiplier() ... */
|
|
|
|
}
|
|
|
|
|
2014-06-27 23:21:18 +02:00
|
|
|
- (NSArray *) _selectedCalendars
|
|
|
|
{
|
2014-06-20 19:16:55 +02:00
|
|
|
SOGoAppointmentFolders *co;
|
|
|
|
SOGoAppointmentFolder *folder;
|
|
|
|
NSMutableArray *selectedCalendars;
|
|
|
|
NSArray *folders;
|
2014-06-30 19:36:12 +02:00
|
|
|
NSString *fUID;
|
2014-06-20 19:16:55 +02:00
|
|
|
NSNumber *isActive;
|
|
|
|
unsigned int count, foldersCount;
|
|
|
|
|
|
|
|
co = [self clientObject];
|
|
|
|
folders = [co subFolders];
|
|
|
|
foldersCount = [folders count];
|
|
|
|
selectedCalendars = [[NSMutableArray alloc] initWithCapacity: foldersCount];
|
|
|
|
for (count = 0; count < foldersCount; count++)
|
|
|
|
{
|
|
|
|
folder = [folders objectAtIndex: count];
|
|
|
|
isActive = [NSNumber numberWithBool: [folder isActive]];
|
|
|
|
if ([isActive intValue] != 0) {
|
2014-06-30 19:36:12 +02:00
|
|
|
fUID = [folder nameInContainer];
|
|
|
|
[selectedCalendars addObject: fUID];
|
2014-06-20 19:16:55 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return selectedCalendars;
|
|
|
|
}
|
|
|
|
|
2008-07-16 04:12:18 +02:00
|
|
|
- (WOResponse *) eventsBlocksAction
|
|
|
|
{
|
|
|
|
int count, max;
|
|
|
|
NSArray *events, *event, *eventsBlocks;
|
2014-06-20 19:16:55 +02:00
|
|
|
NSMutableArray *allDayBlocks, *blocks, *currentDay, *calendars, *eventsByCalendars, *eventsForCalendar;
|
2008-07-29 18:35:49 +02:00
|
|
|
NSNumber *eventNbr;
|
2009-10-07 19:40:02 +02:00
|
|
|
BOOL isAllDay;
|
2014-06-20 19:16:55 +02:00
|
|
|
int i, j;
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2008-07-16 04:12:18 +02:00
|
|
|
[self _setupContext];
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2014-06-20 19:16:55 +02:00
|
|
|
events = [self _fetchFields: eventsFields forComponentOfType: @"vevent"];
|
|
|
|
|
|
|
|
if ([currentView isEqualToString: @"multicolumndayview"])
|
2014-05-08 23:17:05 +02:00
|
|
|
{
|
2015-11-05 18:29:26 +01:00
|
|
|
calendars = (NSMutableArray *)[self _selectedCalendars];
|
2014-06-20 19:16:55 +02:00
|
|
|
eventsByCalendars = [NSMutableArray arrayWithCapacity:[calendars count]];
|
|
|
|
for (i = 0; i < [calendars count]; i++) // For each calendar
|
|
|
|
{
|
|
|
|
eventsForCalendar = [NSMutableArray array];
|
|
|
|
[self _prepareEventBlocks: &blocks withAllDays: &allDayBlocks];
|
|
|
|
for (j = 0; j < [events count]; j++) {
|
2014-06-30 19:36:12 +02:00
|
|
|
if ([[[events objectAtIndex:j] objectAtIndex:1] isEqualToString:[calendars objectAtIndex:i]]) {
|
2014-06-20 19:16:55 +02:00
|
|
|
[eventsForCalendar addObject: [events objectAtIndex:j]];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
eventsBlocks = [NSArray arrayWithObjects:eventsForCalendar, allDayBlocks, blocks, nil];
|
|
|
|
max = [eventsForCalendar count];
|
|
|
|
for (count = 0; count < max; count++)
|
|
|
|
{
|
|
|
|
event = [eventsForCalendar objectAtIndex: count];
|
|
|
|
eventNbr = [NSNumber numberWithUnsignedInt: count];
|
|
|
|
isAllDay = [[event objectAtIndex: eventIsAllDayIndex] boolValue];
|
|
|
|
if (dayBasedView && isAllDay)
|
|
|
|
[self _fillBlocks: allDayBlocks withEvent: event withNumber: eventNbr];
|
|
|
|
else
|
|
|
|
[self _fillBlocks: blocks withEvent: event withNumber: eventNbr];
|
|
|
|
}
|
|
|
|
max = [blocks count];
|
|
|
|
for (count = 0; count < max; count++)
|
|
|
|
{
|
|
|
|
currentDay = [blocks objectAtIndex: count];
|
|
|
|
[currentDay sortUsingSelector: @selector (compareEventByStart:)];
|
|
|
|
[self _addBlocksWidth: currentDay];
|
|
|
|
}
|
|
|
|
|
|
|
|
[eventsByCalendars insertObject:eventsBlocks atIndex:i];
|
|
|
|
}
|
|
|
|
return [self _responseWithData: eventsByCalendars];
|
2014-05-08 23:17:05 +02:00
|
|
|
}
|
2014-06-20 19:16:55 +02:00
|
|
|
else
|
2014-05-08 23:17:05 +02:00
|
|
|
{
|
2014-06-20 19:16:55 +02:00
|
|
|
[self _prepareEventBlocks: &blocks withAllDays: &allDayBlocks];
|
|
|
|
eventsBlocks = [NSArray arrayWithObjects: events, allDayBlocks, blocks, nil];
|
|
|
|
max = [events count];
|
|
|
|
for (count = 0; count < max; count++)
|
|
|
|
{
|
|
|
|
event = [events objectAtIndex: count];
|
|
|
|
// NSLog(@"***[UIxCalListingActions eventsBlocksAction] %i = %@ : %@ / %@ / %@", count,
|
|
|
|
// [event objectAtIndex: eventTitleIndex],
|
|
|
|
// [event objectAtIndex: eventStartDateIndex],
|
|
|
|
// [event objectAtIndex: eventEndDateIndex],
|
|
|
|
// [event objectAtIndex: eventRecurrenceIdIndex]);
|
|
|
|
eventNbr = [NSNumber numberWithUnsignedInt: count];
|
|
|
|
isAllDay = [[event objectAtIndex: eventIsAllDayIndex] boolValue];
|
|
|
|
if (dayBasedView && isAllDay)
|
|
|
|
[self _fillBlocks: allDayBlocks withEvent: event withNumber: eventNbr];
|
|
|
|
else
|
|
|
|
[self _fillBlocks: blocks withEvent: event withNumber: eventNbr];
|
|
|
|
}
|
|
|
|
|
|
|
|
max = [blocks count];
|
|
|
|
for (count = 0; count < max; count++)
|
|
|
|
{
|
|
|
|
currentDay = [blocks objectAtIndex: count];
|
|
|
|
[currentDay sortUsingSelector: @selector (compareEventByStart:)];
|
|
|
|
[self _addBlocksWidth: currentDay];
|
|
|
|
}
|
|
|
|
return [self _responseWithData: eventsBlocks];
|
2014-05-08 23:17:05 +02:00
|
|
|
}
|
2008-07-16 04:12:18 +02:00
|
|
|
}
|
|
|
|
|
2007-06-07 22:49:06 +02:00
|
|
|
- (NSString *) _getStatusClassForStatusCode: (int) statusCode
|
2014-05-08 23:17:05 +02:00
|
|
|
andEndDateStamp: (unsigned int) endDateStamp
|
2007-06-07 22:49:06 +02:00
|
|
|
{
|
|
|
|
NSCalendarDate *taskDate, *now;
|
|
|
|
NSString *statusClass;
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2007-06-07 22:49:06 +02:00
|
|
|
if (statusCode == 1)
|
|
|
|
statusClass = @"completed";
|
|
|
|
else
|
2014-05-08 23:17:05 +02:00
|
|
|
{
|
|
|
|
if (endDateStamp)
|
2007-06-07 22:49:06 +02:00
|
|
|
{
|
2014-05-08 23:17:05 +02:00
|
|
|
now = [NSCalendarDate calendarDate];
|
|
|
|
taskDate
|
2007-06-07 22:49:06 +02:00
|
|
|
= [NSCalendarDate dateWithTimeIntervalSince1970: endDateStamp];
|
2014-05-08 23:17:05 +02:00
|
|
|
[taskDate setTimeZone: userTimeZone];
|
|
|
|
if ([taskDate earlierDate: now] == taskDate)
|
|
|
|
statusClass = @"overdue";
|
2007-06-07 22:49:06 +02:00
|
|
|
else
|
2014-05-08 23:17:05 +02:00
|
|
|
{
|
|
|
|
if ([taskDate isToday])
|
|
|
|
statusClass = @"duetoday";
|
|
|
|
else
|
|
|
|
statusClass = @"duelater";
|
|
|
|
}
|
2007-06-07 22:49:06 +02:00
|
|
|
}
|
2014-05-08 23:17:05 +02:00
|
|
|
else
|
|
|
|
statusClass = @"noduedate";
|
|
|
|
}
|
|
|
|
|
2007-06-07 22:49:06 +02:00
|
|
|
return statusClass;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (WOResponse *) tasksListAction
|
|
|
|
{
|
2012-09-28 21:42:49 +02:00
|
|
|
NSMutableArray *filteredTasks, *filteredTask;
|
|
|
|
NSString *sort, *ascending;
|
2014-05-08 23:17:05 +02:00
|
|
|
NSString *statusFlag, *tasksView;
|
2009-11-29 05:19:32 +01:00
|
|
|
SOGoUserSettings *us;
|
2007-06-07 22:49:06 +02:00
|
|
|
NSEnumerator *tasks;
|
2008-07-16 04:12:18 +02:00
|
|
|
NSArray *task;
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2007-06-07 22:49:06 +02:00
|
|
|
unsigned int endDateStamp;
|
2012-09-28 21:42:49 +02:00
|
|
|
BOOL showCompleted;
|
|
|
|
int statusCode;
|
2014-05-08 23:17:05 +02:00
|
|
|
int startSecs;
|
|
|
|
|
2007-06-07 22:49:06 +02:00
|
|
|
filteredTasks = [NSMutableArray array];
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2007-06-07 22:49:06 +02:00
|
|
|
[self _setupContext];
|
2014-05-08 23:17:05 +02:00
|
|
|
|
|
|
|
startSecs = (unsigned int) [startDate timeIntervalSince1970];
|
|
|
|
tasksView = [request formValueForKey: @"filterpopup"];
|
|
|
|
|
2009-11-29 05:19:32 +01:00
|
|
|
#warning see TODO in SchedulerUI.js about "setud"
|
2007-06-07 22:49:06 +02:00
|
|
|
showCompleted = [[request formValueForKey: @"show-completed"] intValue];
|
2009-11-29 05:19:32 +01:00
|
|
|
if ([request formValueForKey: @"setud"])
|
2014-05-08 23:17:05 +02:00
|
|
|
{
|
|
|
|
us = [[context activeUser] userSettings];
|
|
|
|
[us setBool: showCompleted forKey: @"ShowCompletedTasks"];
|
|
|
|
[us synchronize];
|
|
|
|
}
|
|
|
|
|
2009-11-29 05:19:32 +01:00
|
|
|
tasks = [[self _fetchFields: tasksFields
|
2014-05-08 23:17:05 +02:00
|
|
|
forComponentOfType: @"vtodo"] objectEnumerator];
|
|
|
|
|
2009-08-18 18:22:20 +02:00
|
|
|
while ((task = [tasks nextObject]))
|
2014-05-08 23:17:05 +02:00
|
|
|
{
|
2016-10-21 23:30:47 +02:00
|
|
|
statusCode = [[task objectAtIndex: taskStatusIndex] intValue];
|
2014-05-08 23:17:05 +02:00
|
|
|
if (statusCode != 1 || showCompleted)
|
2007-06-07 22:49:06 +02:00
|
|
|
{
|
2014-05-08 23:17:05 +02:00
|
|
|
filteredTask = [NSMutableArray arrayWithArray: task];
|
2016-10-21 23:30:47 +02:00
|
|
|
endDateStamp = [[task objectAtIndex: taskEndDateIndex] intValue];
|
2014-05-08 23:17:05 +02:00
|
|
|
statusFlag = [self _getStatusClassForStatusCode: statusCode
|
|
|
|
andEndDateStamp: endDateStamp];
|
|
|
|
[filteredTask addObject: statusFlag];
|
|
|
|
if (endDateStamp > 0)
|
|
|
|
[filteredTask addObject: [self _formattedDateForSeconds: endDateStamp
|
|
|
|
forAllDay: NO]];
|
|
|
|
|
|
|
|
if (([tasksView isEqualToString:@"view_today"] ||
|
|
|
|
[tasksView isEqualToString:@"view_next7"] ||
|
|
|
|
[tasksView isEqualToString:@"view_next14"] ||
|
|
|
|
[tasksView isEqualToString:@"view_next31"] ||
|
2016-10-21 23:30:47 +02:00
|
|
|
[tasksView isEqualToString:@"view_thismonth"]) &&
|
|
|
|
(endDateStamp == 0 || endDateStamp >= startSecs))
|
2014-05-08 23:17:05 +02:00
|
|
|
[filteredTasks addObject: filteredTask];
|
|
|
|
else if ([tasksView isEqualToString:@"view_all"])
|
|
|
|
[filteredTasks addObject: filteredTask];
|
2016-10-21 23:30:47 +02:00
|
|
|
else if (([tasksView isEqualToString:@"view_overdue"]) &&
|
|
|
|
([[filteredTask objectAtIndex:taskStatusFlagIndex] isEqualToString:@"overdue"]))
|
2014-05-08 23:17:05 +02:00
|
|
|
[filteredTasks addObject: filteredTask];
|
2016-10-21 23:30:47 +02:00
|
|
|
else if ([tasksView isEqualToString:@"view_incomplete"] &&
|
|
|
|
(![[filteredTask objectAtIndex:taskStatusFlagIndex] isEqualToString:@"completed"]))
|
2014-05-08 23:17:05 +02:00
|
|
|
[filteredTasks addObject: filteredTask];
|
2016-10-21 23:30:47 +02:00
|
|
|
else if ([tasksView isEqualToString:@"view_not_started"] &&
|
|
|
|
([[[filteredTask objectAtIndex:taskStatusIndex] stringValue] isEqualToString:@"0"]))
|
2014-05-08 23:17:05 +02:00
|
|
|
[filteredTasks addObject: filteredTask];
|
2007-06-07 22:49:06 +02:00
|
|
|
}
|
2014-05-08 23:17:05 +02:00
|
|
|
}
|
2012-09-28 21:42:49 +02:00
|
|
|
sort = [[context request] formValueForKey: @"sort"];
|
|
|
|
if ([sort isEqualToString: @"title"])
|
|
|
|
[filteredTasks sortUsingSelector: @selector (compareTasksTitleAscending:)];
|
|
|
|
else if ([sort isEqualToString: @"priority"])
|
|
|
|
[filteredTasks sortUsingSelector: @selector (compareTasksPriorityAscending:)];
|
|
|
|
else if ([sort isEqualToString: @"end"])
|
|
|
|
[filteredTasks sortUsingSelector: @selector (compareTasksEndAscending:)];
|
|
|
|
else if ([sort isEqualToString: @"location"])
|
|
|
|
[filteredTasks sortUsingSelector: @selector (compareTasksLocationAscending:)];
|
|
|
|
else if ([sort isEqualToString: @"category"])
|
|
|
|
[filteredTasks sortUsingSelector: @selector (compareTasksCategoryAscending:)];
|
|
|
|
else if ([sort isEqualToString: @"calendarname"])
|
|
|
|
[filteredTasks sortUsingSelector: @selector (compareTasksCalendarNameAscending:)];
|
2014-05-08 23:17:05 +02:00
|
|
|
else
|
2012-09-28 21:42:49 +02:00
|
|
|
[filteredTasks sortUsingSelector: @selector (compareTasksAscending:)];
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2012-09-28 21:42:49 +02:00
|
|
|
ascending = [[context request] formValueForKey: @"asc"];
|
|
|
|
if (![ascending boolValue])
|
|
|
|
[filteredTasks reverseArray];
|
2014-05-08 23:17:05 +02:00
|
|
|
|
2007-06-07 22:49:06 +02:00
|
|
|
return [self _responseWithData: filteredTasks];
|
|
|
|
}
|
|
|
|
|
2014-06-27 23:00:32 +02:00
|
|
|
- (WOResponse *) activeTasksAction
|
|
|
|
{
|
2014-06-28 14:31:07 +02:00
|
|
|
NSMutableDictionary *activeTasksByCalendars;
|
2014-06-27 23:00:32 +02:00
|
|
|
SOGoAppointmentFolder *folder;
|
2014-06-28 14:31:07 +02:00
|
|
|
SOGoAppointmentFolders *co;
|
2014-06-27 23:00:32 +02:00
|
|
|
NSArray *folders;
|
2014-06-28 14:31:07 +02:00
|
|
|
|
|
|
|
int i;
|
2014-06-27 23:00:32 +02:00
|
|
|
|
|
|
|
co = [self clientObject];
|
|
|
|
folders = [co subFolders];
|
2014-06-28 14:31:07 +02:00
|
|
|
activeTasksByCalendars = [NSMutableDictionary dictionaryWithCapacity: [folders count]];
|
|
|
|
|
|
|
|
for (i = 0; i < [folders count]; i++)
|
|
|
|
{
|
|
|
|
folder = [folders objectAtIndex: i];
|
|
|
|
|
|
|
|
[activeTasksByCalendars setObject: [folder activeTasks]
|
|
|
|
forKey: [folder nameInContainer]];
|
2014-06-27 23:00:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return [self _responseWithData: activeTasksByCalendars];
|
|
|
|
}
|
|
|
|
|
2007-06-07 22:49:06 +02:00
|
|
|
@end
|