Monotone-Parent: 95b1c285d67a034685e2ef30e56e10e7c253438d
Monotone-Revision: 2609687767884b123c1ff765253fde7c75ef81b3 Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2008-07-16T02:12:18 Monotone-Branch: ca.inverse.sogomaint-2.0.2
parent
8078250b1a
commit
7512f5d512
18
ChangeLog
18
ChangeLog
|
@ -1,3 +1,21 @@
|
|||
2008-07-15 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
|
||||
* UI/Scheduler/NSDictionary+Scheduler.m: new category module that
|
||||
implement helper methods for the Scheduler module.
|
||||
([NSDictionary -compareEventByStart:otherEvent]): new method that
|
||||
compares event block dictionaries based on their value for
|
||||
"start".
|
||||
|
||||
* UI/Scheduler/UIxCalListingActions.m ([UIxCalListingActions
|
||||
-eventsBlocksAction]): new web method that returns the list of
|
||||
events as well as the precomputed blocks of events, whether "all
|
||||
day" or not.
|
||||
|
||||
* SoObjects/Appointments/SOGoAppointmentFolder.m
|
||||
([SOGoAppointmentFolder
|
||||
-fetchCoreInfosFrom:_startDateto:_endDatetitle:titlecomponent:_componentadditionalFilters:filters]):
|
||||
requests "c_iscycle".
|
||||
|
||||
2008-07-14 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
|
||||
* SoObjects/SOGo/SOGoContentObject.m ([SOGoContentObject
|
||||
|
|
|
@ -1399,7 +1399,6 @@ static Class sogoAppointmentFolderKlass = Nil;
|
|||
|
||||
- (NSString *) davCalendarOrder
|
||||
{
|
||||
NSArray *siblings;
|
||||
unsigned int order;
|
||||
|
||||
order = [[container subFolders] indexOfObject: self];
|
||||
|
@ -1409,8 +1408,6 @@ static Class sogoAppointmentFolderKlass = Nil;
|
|||
|
||||
- (NSException *) setDavCalendarOrder: (NSString *) newColor
|
||||
{
|
||||
NSException *error;
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
@ -2218,7 +2215,7 @@ static Class sogoAppointmentFolderKlass = Nil;
|
|||
@"c_classification", @"c_isallday",
|
||||
@"c_isopaque", @"c_participants", @"c_partmails",
|
||||
@"c_partstates", @"c_sequence", @"c_priority",
|
||||
@"c_cycleinfo", nil];
|
||||
@"c_cycleinfo", @"c_iscycle", nil];
|
||||
|
||||
return [self fetchFields: infos from: _startDate to: _endDate title: title
|
||||
component: _component
|
||||
|
|
|
@ -11,6 +11,7 @@ SchedulerUI_LANGUAGES = Dutch English French German Italian Spanish
|
|||
SchedulerUI_OBJC_FILES = \
|
||||
SchedulerUIProduct.m \
|
||||
NSArray+Scheduler.m \
|
||||
NSDictionary+Scheduler.m \
|
||||
\
|
||||
UIxCalMainView.m \
|
||||
UIxCalendarProperties.m \
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/* NSDictionary+Scheduler.h - this file is part of SOGo
|
||||
*
|
||||
* Copyright (C) 2008 Inverse groupe conseil
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
* 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/NSDictionary.h>
|
||||
|
||||
@interface NSDictionary (SOGoEventComparison)
|
||||
|
||||
- (NSComparisonResult) compareEventByStart: (NSDictionary *) otherEvent;
|
||||
|
||||
@end
|
|
@ -0,0 +1,35 @@
|
|||
/* NSDictionary+Scheduler.m - this file is part of SOGo
|
||||
*
|
||||
* Copyright (C) 2008 Inverse groupe conseil
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
* 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/NSString.h>
|
||||
|
||||
#import "NSDictionary+Scheduler.h"
|
||||
|
||||
@implementation NSDictionary (SOGoEventComparison)
|
||||
|
||||
- (NSComparisonResult) compareEventByStart: (NSDictionary *) otherEvent
|
||||
{
|
||||
return [[self objectForKey: @"start"]
|
||||
compare: [otherEvent objectForKey: @"start"]];
|
||||
}
|
||||
|
||||
@end
|
|
@ -42,6 +42,7 @@
|
|||
NSCalendarDate *endDate;
|
||||
NSString *title;
|
||||
NSString *userLogin;
|
||||
BOOL dayBasedView;
|
||||
WORequest *request;
|
||||
SOGoDateFormatter *dateFormatter;
|
||||
NSTimeZone *userTimeZone;
|
||||
|
|
|
@ -49,8 +49,34 @@
|
|||
|
||||
#import "UIxCalListingActions.h"
|
||||
|
||||
static NSArray *eventsFields = nil;
|
||||
static NSArray *tasksFields = nil;
|
||||
|
||||
#define dayLength 86400
|
||||
#define quarterLength 900
|
||||
|
||||
@implementation UIxCalListingActions
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (!eventsFields)
|
||||
{
|
||||
eventsFields = [NSArray arrayWithObjects: @"c_name", @"c_folder",
|
||||
@"c_status", @"c_title", @"c_startdate",
|
||||
@"c_enddate", @"c_location", @"c_isallday",
|
||||
@"c_classification", @"c_partmails",
|
||||
@"c_partstates", @"c_owner", @"c_iscycle", nil];
|
||||
[eventsFields retain];
|
||||
}
|
||||
if (!tasksFields)
|
||||
{
|
||||
tasksFields = [NSArray arrayWithObjects: @"c_name", @"c_folder",
|
||||
@"c_status", @"c_title", @"c_enddate",
|
||||
@"c_classification", nil];
|
||||
[tasksFields retain];
|
||||
}
|
||||
}
|
||||
|
||||
- (id) initWithRequest: (WORequest *) newRequest
|
||||
{
|
||||
SOGoUser *user;
|
||||
|
@ -64,6 +90,7 @@
|
|||
user = [[self context] activeUser];
|
||||
dateFormatter = [user dateFormatterInContext: context];
|
||||
ASSIGN (userTimeZone, [user timeZone]);
|
||||
dayBasedView = NO;
|
||||
}
|
||||
|
||||
return self;
|
||||
|
@ -161,7 +188,7 @@
|
|||
userTZ = [user timeZone];
|
||||
|
||||
param = [request formValueForKey: @"filterpopup"];
|
||||
if ([param length] > 0)
|
||||
if ([param length])
|
||||
{
|
||||
[self _setupDatesWithPopup: param andUserTZ: userTZ];
|
||||
title = [request formValueForKey: @"search"];
|
||||
|
@ -175,7 +202,7 @@
|
|||
inTimeZone: userTZ] beginOfDay];
|
||||
else
|
||||
startDate = nil;
|
||||
|
||||
|
||||
param = [request formValueForKey: @"ed"];
|
||||
if ([param length] > 0)
|
||||
endDate = [[NSCalendarDate dateFromShortDateString: param
|
||||
|
@ -183,6 +210,9 @@
|
|||
inTimeZone: userTZ] endOfDay];
|
||||
else
|
||||
endDate = nil;
|
||||
|
||||
param = [request formValueForKey: @"view"];
|
||||
dayBasedView = ![param isEqualToString: @"monthview"];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -291,27 +321,9 @@
|
|||
return formattedDate;
|
||||
}
|
||||
|
||||
- (NSString *) _adjustedDateForSeconds: (unsigned int) seconds
|
||||
forAllDay: (BOOL) forAllDay
|
||||
{
|
||||
NSCalendarDate *date;
|
||||
unsigned int newSeconds, offset;
|
||||
|
||||
date = [NSCalendarDate dateWithTimeIntervalSince1970: seconds];
|
||||
[date setTimeZone: userTimeZone];
|
||||
|
||||
offset = [userTimeZone secondsFromGMTForDate: date];
|
||||
if (forAllDay)
|
||||
newSeconds = seconds + [userTimeZone secondsFromGMT] - offset;
|
||||
else
|
||||
newSeconds = seconds + offset;
|
||||
|
||||
return [NSString stringWithFormat: @"%u", newSeconds];
|
||||
}
|
||||
|
||||
- (WOResponse *) eventsListAction
|
||||
{
|
||||
NSArray *fields, *oldEvent, *participants, *states;
|
||||
NSArray *oldEvent, *participants, *states;
|
||||
NSEnumerator *events;
|
||||
NSMutableArray *newEvents, *newEvent;
|
||||
unsigned int interval, i;
|
||||
|
@ -322,27 +334,16 @@
|
|||
[self _setupContext];
|
||||
|
||||
newEvents = [NSMutableArray array];
|
||||
fields = [NSArray arrayWithObjects: @"c_name", @"c_folder", @"c_status",
|
||||
@"c_title", @"c_startdate", @"c_enddate", @"c_location",
|
||||
@"c_isallday", @"c_classification", @"c_partmails", @"c_partstates",
|
||||
@"c_owner", nil];
|
||||
events = [[self _fetchFields: fields
|
||||
events = [[self _fetchFields: eventsFields
|
||||
forComponentOfType: @"vevent"] objectEnumerator];
|
||||
oldEvent = [events nextObject];
|
||||
while (oldEvent)
|
||||
while ((oldEvent = [events nextObject]))
|
||||
{
|
||||
newEvent = [NSMutableArray arrayWithArray: oldEvent];
|
||||
isAllDay = [[oldEvent objectAtIndex: 7] boolValue];
|
||||
interval = [[oldEvent objectAtIndex: 4] intValue];
|
||||
[newEvent replaceObjectAtIndex: 4
|
||||
withObject: [self _adjustedDateForSeconds: interval
|
||||
forAllDay: isAllDay]];
|
||||
[newEvent addObject: [self _formattedDateForSeconds: interval
|
||||
forAllDay: isAllDay]];
|
||||
interval = [[oldEvent objectAtIndex: 5] intValue];
|
||||
[newEvent replaceObjectAtIndex: 5
|
||||
withObject: [self _adjustedDateForSeconds: interval
|
||||
forAllDay: isAllDay]];
|
||||
[newEvent addObject: [self _formattedDateForSeconds: interval
|
||||
forAllDay: isAllDay]];
|
||||
|
||||
|
@ -380,8 +381,6 @@
|
|||
[newEvent removeObjectAtIndex: 10];
|
||||
|
||||
[newEvents addObject: newEvent];
|
||||
|
||||
oldEvent = [events nextObject];
|
||||
}
|
||||
|
||||
sort = [[context request] formValueForKey: @"sort"];
|
||||
|
@ -393,7 +392,7 @@
|
|||
[newEvents sortUsingSelector: @selector (compareEventsLocationAscending:)];
|
||||
else
|
||||
[newEvents sortUsingSelector: @selector (compareEventsStartDateAscending:)];
|
||||
|
||||
|
||||
ascending = [[context request] formValueForKey: @"asc"];
|
||||
if (![ascending boolValue])
|
||||
[newEvents reverseArray];
|
||||
|
@ -401,6 +400,361 @@
|
|||
return [self _responseWithData: newEvents];
|
||||
}
|
||||
|
||||
static inline void
|
||||
_feedBlockWithDayBasedData(NSMutableDictionary *block, unsigned int start,
|
||||
unsigned int end, unsigned int dayStart)
|
||||
{
|
||||
unsigned int delta, quarterStart, length;
|
||||
|
||||
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]
|
||||
forKey: @"start"];
|
||||
[block setObject: [NSNumber numberWithUnsignedInt: length]
|
||||
forKey: @"length"];
|
||||
}
|
||||
|
||||
static inline void
|
||||
_feedBlockWithMonthBasedData(NSMutableDictionary *block, unsigned int start,
|
||||
NSTimeZone *userTimeZone,
|
||||
SOGoDateFormatter *dateFormatter)
|
||||
{
|
||||
NSCalendarDate *eventStartDate;
|
||||
NSString *startHour;
|
||||
|
||||
eventStartDate = [NSCalendarDate dateWithTimeIntervalSince1970: start];
|
||||
[eventStartDate setTimeZone: userTimeZone];
|
||||
startHour = [dateFormatter formattedTime: eventStartDate];
|
||||
[block setObject: startHour forKey: @"starthour"];
|
||||
[block setObject: [NSNumber numberWithUnsignedInt: start]
|
||||
forKey: @"start"];
|
||||
}
|
||||
|
||||
- (NSMutableDictionary *) _eventBlockWithStart: (unsigned int) start
|
||||
end: (unsigned int) end
|
||||
cname: (NSString *) cName
|
||||
onDay: (unsigned int) dayStart
|
||||
recurrence: (BOOL) recurrence
|
||||
{
|
||||
NSMutableDictionary *block;
|
||||
|
||||
block = [NSMutableDictionary dictionary];
|
||||
|
||||
if (dayBasedView)
|
||||
_feedBlockWithDayBasedData (block, start, end, dayStart);
|
||||
else
|
||||
_feedBlockWithMonthBasedData (block, start, userTimeZone, dateFormatter);
|
||||
[block setObject: cName forKey: @"cname"];
|
||||
if (recurrence)
|
||||
[block setObject: @"1" forKey: @"recurrence"];
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
- (void) _fillBlocks: (NSArray *) blocks
|
||||
withEvent: (NSArray *) event
|
||||
{
|
||||
unsigned int currentDayStart, startSecs, endsSecs, currentStart, eventStart,
|
||||
eventEnd, offset;
|
||||
NSMutableArray *currentDay;
|
||||
NSMutableDictionary *eventBlock;
|
||||
NSString *eventCName;
|
||||
BOOL recurrence;
|
||||
|
||||
startSecs = (unsigned int) [startDate timeIntervalSince1970];
|
||||
endsSecs = (unsigned int) [endDate timeIntervalSince1970];
|
||||
eventStart = [[event objectAtIndex: 4] unsignedIntValue];
|
||||
eventEnd = [[event objectAtIndex: 5] unsignedIntValue];
|
||||
|
||||
recurrence = [[event objectAtIndex: 12] boolValue];
|
||||
|
||||
currentStart = eventStart;
|
||||
if (currentStart < startSecs)
|
||||
{
|
||||
currentStart = startSecs;
|
||||
offset = 0;
|
||||
}
|
||||
else
|
||||
offset = ((currentStart - startSecs)
|
||||
/ dayLength);
|
||||
currentDay = [blocks objectAtIndex: offset];
|
||||
currentDayStart = startSecs + dayLength * offset;
|
||||
|
||||
if (eventEnd > endsSecs)
|
||||
eventEnd = endsSecs;
|
||||
|
||||
eventCName = [event objectAtIndex: 0];
|
||||
while (currentStart + dayLength < eventEnd)
|
||||
{
|
||||
eventBlock = [self _eventBlockWithStart: currentStart
|
||||
end: currentDayStart + 86399
|
||||
cname: eventCName
|
||||
onDay: currentDayStart
|
||||
recurrence: recurrence];
|
||||
[currentDay addObject: eventBlock];
|
||||
currentDayStart += dayLength;
|
||||
currentStart = currentDayStart;
|
||||
offset++;
|
||||
currentDay = [blocks objectAtIndex: offset];
|
||||
}
|
||||
eventBlock = [self _eventBlockWithStart: currentStart
|
||||
end: eventEnd
|
||||
cname: eventCName
|
||||
onDay: currentDayStart
|
||||
recurrence: recurrence];
|
||||
[currentDay addObject: eventBlock];
|
||||
}
|
||||
|
||||
- (void) _prepareEventBlocks: (NSMutableArray **) blocks
|
||||
withAllDays: (NSMutableArray **) allDayBlocks
|
||||
{
|
||||
unsigned int count, nbrDays;
|
||||
int seconds;
|
||||
|
||||
seconds = [endDate timeIntervalSinceDate: startDate];
|
||||
if (seconds > 0)
|
||||
{
|
||||
nbrDays = 1 + (unsigned int) (seconds / dayLength);
|
||||
*blocks = [NSMutableArray arrayWithCapacity: nbrDays];
|
||||
*allDayBlocks = [NSMutableArray arrayWithCapacity: nbrDays];
|
||||
for (count = 0; count < nbrDays; count++)
|
||||
{
|
||||
[*blocks addObject: [NSMutableArray array]];
|
||||
[*allDayBlocks addObject: [NSMutableArray array]];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*blocks = nil;
|
||||
*allDayBlocks = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSArray *) _horizontalBlocks: (NSMutableArray *) day
|
||||
{
|
||||
NSMutableArray *quarters[96];
|
||||
NSMutableArray *currentBlock, *blocks;
|
||||
NSDictionary *currentEvent;
|
||||
unsigned int count, max, qCount, qMax, qOffset;
|
||||
|
||||
blocks = [NSMutableArray array];
|
||||
|
||||
bzero (quarters, 96 * sizeof (NSMutableArray *));
|
||||
|
||||
max = [day count];
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
currentEvent = [day objectAtIndex: count];
|
||||
qMax = [[currentEvent objectForKey: @"length"] unsignedIntValue];
|
||||
qOffset = [[currentEvent objectForKey: @"start"] unsignedIntValue];
|
||||
for (qCount = 0; qCount < qMax; qCount++)
|
||||
{
|
||||
currentBlock = quarters[qCount + qOffset];
|
||||
if (!currentBlock)
|
||||
{
|
||||
currentBlock = [NSMutableArray array];
|
||||
quarters[qCount + qOffset] = currentBlock;
|
||||
[blocks addObject: currentBlock];
|
||||
}
|
||||
[currentBlock addObject: currentEvent];
|
||||
}
|
||||
}
|
||||
|
||||
return blocks;
|
||||
}
|
||||
|
||||
static inline unsigned int
|
||||
_computeMaxBlockSiblings (NSArray *block)
|
||||
{
|
||||
unsigned int count, max, maxSiblings, siblings;
|
||||
NSNumber *nbrEvents;
|
||||
|
||||
max = [block count];
|
||||
maxSiblings = max;
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
nbrEvents = [[block objectAtIndex: count] objectForKey: @"siblings"];
|
||||
if (nbrEvents)
|
||||
{
|
||||
siblings = [nbrEvents unsignedIntValue];
|
||||
if (siblings > maxSiblings)
|
||||
maxSiblings = siblings;
|
||||
}
|
||||
}
|
||||
|
||||
return maxSiblings;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_propagateBlockSiblings (NSArray *block, NSNumber *maxSiblings)
|
||||
{
|
||||
unsigned int count, max;
|
||||
NSMutableDictionary *event;
|
||||
NSNumber *realSiblings;
|
||||
|
||||
max = [block count];
|
||||
realSiblings = [NSNumber numberWithUnsignedInt: max];
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
event = [block objectAtIndex: count];
|
||||
[event setObject: maxSiblings forKey: @"siblings"];
|
||||
[event setObject: realSiblings forKey: @"realSiblings"];
|
||||
}
|
||||
}
|
||||
|
||||
/* this requires two vertical passes */
|
||||
static inline void
|
||||
_computeBlocksSiblings (NSArray *blocks)
|
||||
{
|
||||
NSArray *currentBlock;
|
||||
unsigned int count, max, maxSiblings;
|
||||
|
||||
max = [blocks count];
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
currentBlock = [blocks objectAtIndex: count];
|
||||
maxSiblings = _computeMaxBlockSiblings (currentBlock);
|
||||
_propagateBlockSiblings (currentBlock,
|
||||
[NSNumber numberWithUnsignedInt: maxSiblings]);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_computeBlockPosition (NSArray *block)
|
||||
{
|
||||
unsigned int count, max, j, siblings;
|
||||
NSNumber *position;
|
||||
NSMutableDictionary *event;
|
||||
NSMutableDictionary **positions;
|
||||
|
||||
max = [block count];
|
||||
event = [block objectAtIndex: 0];
|
||||
siblings = [[event objectForKey: @"siblings"] unsignedIntValue];
|
||||
positions = calloc (siblings, sizeof (NSMutableDictionary *));
|
||||
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
event = [block objectAtIndex: count];
|
||||
position = [event objectForKey: @"position"];
|
||||
if (position)
|
||||
*(positions + [position unsignedIntValue]) = event;
|
||||
else
|
||||
{
|
||||
j = 0;
|
||||
while (j < max && *(positions + j))
|
||||
j++;
|
||||
*(positions + j) = event;
|
||||
[event setObject: [NSNumber numberWithUnsignedInt: j]
|
||||
forKey: @"position"];
|
||||
}
|
||||
}
|
||||
|
||||
free (positions);
|
||||
}
|
||||
|
||||
// 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;
|
||||
// NSMutableDictionary **positions;
|
||||
|
||||
max = [blocks count];
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
block = [blocks objectAtIndex: count];
|
||||
_computeBlockPosition (block);
|
||||
// _addBlockMultipliers (block, positions);
|
||||
// free (positions);
|
||||
}
|
||||
}
|
||||
|
||||
- (void) _addBlocksWidth: (NSMutableArray *) day
|
||||
{
|
||||
NSArray *blocks;
|
||||
|
||||
blocks = [self _horizontalBlocks: day];
|
||||
_computeBlocksSiblings (blocks);
|
||||
_computeBlocksSiblings (blocks);
|
||||
_computeBlocksPosition (blocks);
|
||||
/* ... _computeBlocksMultiplier() ... */
|
||||
}
|
||||
|
||||
- (WOResponse *) eventsBlocksAction
|
||||
{
|
||||
int count, max;
|
||||
NSArray *events, *event, *eventsBlocks;
|
||||
NSMutableArray *allDayBlocks, *blocks, *currentDay;
|
||||
|
||||
[self _setupContext];
|
||||
|
||||
[self _prepareEventBlocks: &blocks withAllDays: &allDayBlocks];
|
||||
events = [self _fetchFields: eventsFields
|
||||
forComponentOfType: @"vevent"];
|
||||
eventsBlocks
|
||||
= [NSArray arrayWithObjects: events, allDayBlocks, blocks, nil];
|
||||
max = [events count];
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
event = [events objectAtIndex: count];
|
||||
if (dayBasedView && [[event objectAtIndex: 7] boolValue])
|
||||
[self _fillBlocks: allDayBlocks withEvent: event];
|
||||
else
|
||||
[self _fillBlocks: blocks withEvent: event];
|
||||
}
|
||||
|
||||
max = [blocks count];
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
currentDay = [blocks objectAtIndex: count];
|
||||
[currentDay sortUsingSelector: @selector (compareEventByStart:)];
|
||||
[self _addBlocksWidth: currentDay];
|
||||
}
|
||||
|
||||
return [self _responseWithData: eventsBlocks];
|
||||
// timeIntervalSinceDate:
|
||||
}
|
||||
|
||||
- (NSString *) _getStatusClassForStatusCode: (int) statusCode
|
||||
andEndDateStamp: (unsigned int) endDateStamp
|
||||
{
|
||||
|
@ -438,7 +792,7 @@
|
|||
NSEnumerator *tasks;
|
||||
NSMutableArray *filteredTasks, *filteredTask;
|
||||
BOOL showCompleted;
|
||||
NSArray *fields, *task;
|
||||
NSArray *task;
|
||||
int statusCode;
|
||||
unsigned int endDateStamp;
|
||||
NSString *statusFlag;
|
||||
|
@ -447,10 +801,7 @@
|
|||
|
||||
[self _setupContext];
|
||||
|
||||
fields = [NSArray arrayWithObjects: @"c_name", @"c_folder", @"c_status",
|
||||
@"c_title", @"c_enddate", @"c_classification", nil];
|
||||
|
||||
tasks = [[self _fetchFields: fields
|
||||
tasks = [[self _fetchFields: tasksFields
|
||||
forComponentOfType: @"vtodo"] objectEnumerator];
|
||||
showCompleted = [[request formValueForKey: @"show-completed"] intValue];
|
||||
|
||||
|
|
|
@ -59,6 +59,11 @@
|
|||
actionClass = "UIxCalListingActions";
|
||||
actionName = "eventsList";
|
||||
};
|
||||
eventsblocks = {
|
||||
protectedBy = "View";
|
||||
actionClass = "UIxCalListingActions";
|
||||
actionName = "eventsBlocks";
|
||||
};
|
||||
taskslist = {
|
||||
protectedBy = "View";
|
||||
actionClass = "UIxCalListingActions";
|
||||
|
|
|
@ -42,20 +42,6 @@
|
|||
var:day="currentTableDay.shortDateString"
|
||||
var:hour="currentAppointmentHour">
|
||||
</div></var:foreach>
|
||||
<!-- <var:foreach list="appointmentsForCurrentDay" item="currentAppointment"
|
||||
><var:component className="UIxCalInlineAptView"
|
||||
dayStartHour="dayStartHour"
|
||||
dayEndHour="dayEndHour"
|
||||
appointment="currentAppointment"
|
||||
formatter="aptFormatter"
|
||||
tooltipFormatter="aptTooltipFormatter"
|
||||
url="appointmentViewURL"
|
||||
const:style="dayoverview"
|
||||
queryDictionary="currentDateQueryParameters"
|
||||
referenceDate="selectedDate"
|
||||
canAccess="canAccessApt"
|
||||
/></var:foreach
|
||||
> -->
|
||||
</div>
|
||||
</div>
|
||||
</var:foreach>
|
||||
|
|
|
@ -47,89 +47,15 @@
|
|||
><var:string value="labelForCurrentDayToDisplay"
|
||||
/></div></var:foreach>
|
||||
<div class="days" const:id="monthDaysView"
|
||||
><var:foreach list="daysToDisplay" item="currentTableColumn">
|
||||
<var:foreach list="currentTableColumn" item="currentTableDay">
|
||||
<div var:class="dayCellClasses"
|
||||
><var:foreach list="daysToDisplay" item="currentTableColumn"
|
||||
><var:foreach list="currentTableColumn" item="currentTableDay"
|
||||
><div var:class="dayCellClasses"
|
||||
var:day="currentTableDay.shortDateString">
|
||||
<div class="dayHeader"><var:string value="dayHeaderNumber"/></div>
|
||||
<!-- var:foreach
|
||||
list="aptsForCurrentDate"
|
||||
item="appointment"
|
||||
var:component className="UIxCalInlineMdsadsadsaonthAptView"
|
||||
appointment="appointment"
|
||||
formatter="monthAptFormatter"
|
||||
tooltipFormatter="aptTooltipFormatter"
|
||||
url="appointmentViewURL"
|
||||
const:style="dayoverview"
|
||||
queryDictionary="currentDayQueryParameters"
|
||||
referenceDate="currentTableDay"
|
||||
canAccess="canAccessApt"
|
||||
var:foreach -->
|
||||
</div>
|
||||
<div class="dayHeader"><var:string value="dayHeaderNumber"/></div
|
||||
></div>
|
||||
</var:foreach>
|
||||
</var:foreach>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</container>
|
||||
|
||||
<!-- <table class="monthOverview">
|
||||
<tr>
|
||||
</tr>
|
||||
|
||||
<var:if condition="hasHolidayInfo">
|
||||
<tr>
|
||||
<td class="hourOfDay" colspan="2">
|
||||
<b><var:string value="holidayInfo.title" /></b>
|
||||
</td>
|
||||
</tr>
|
||||
</var:if> -->
|
||||
|
||||
<!-- <var:foreach list="allDayApts" item="appointment">
|
||||
<tr>
|
||||
<td class="hourOfDay">
|
||||
<var:entity name="nbsp" />
|
||||
</td>
|
||||
<td class="day" width="90%">
|
||||
<var:foreach list="allDayApts" item="appointment">
|
||||
<var:component className="UIxCaaaaalInlineAptView"
|
||||
appointment="appointment"
|
||||
formatter="aptFormatter"
|
||||
tooltipFormatter="aptTooltipFormatter"
|
||||
url="appointmentViewURL"
|
||||
const:style="dayoverview"
|
||||
queryDictionary="currentDateQueryParameters"
|
||||
referenceDate="selectedDate"
|
||||
canAccess="canAccessApt"
|
||||
/>
|
||||
</var:foreach>
|
||||
</td>
|
||||
</tr>
|
||||
</var:foreach> -->
|
||||
|
||||
<!-- <var:foreach list="rangesOf7Days" item="currentRangeOf7Days">
|
||||
<tr>
|
||||
<var:foreach list="currentRangeOf7Days" item="currentTableDay"
|
||||
><td var:class="dayCellClasses"
|
||||
var:day="currentTableDay.shortDateString"
|
||||
const:hour="0800"
|
||||
><div class="dayContent"><span class="dayCellLabel"
|
||||
><var:string value="labelForCurrentDayCell" /></span
|
||||
><br /><var:foreach
|
||||
list="aptsForCurrentDate"
|
||||
item="appointment"
|
||||
><var:component className="UIxCalInlineAptxxxxView"
|
||||
appointment="appointment"
|
||||
formatter="monthAptFormatter"
|
||||
tooltipFormatter="aptTooltipFormatter"
|
||||
url="appointmentViewURL"
|
||||
const:style="dayoverview"
|
||||
queryDictionary="currentDayQueryParameters"
|
||||
referenceDate="currentTableDay"
|
||||
canAccess="canAccessApt"
|
||||
/>
|
||||
</var:foreach></div></td>
|
||||
</var:foreach>
|
||||
</tr>
|
||||
</var:foreach>
|
||||
</table> -->
|
||||
|
|
|
@ -10,16 +10,19 @@ var showCompletedTasks = 0;
|
|||
var currentDay = '';
|
||||
var currentView = "weekview";
|
||||
|
||||
var cachedDateSelectors = new Array();
|
||||
var cachedDateSelectors = [];
|
||||
|
||||
var contactSelectorAction = 'calendars-contacts';
|
||||
|
||||
var eventsToDelete = new Array();
|
||||
var calendarsOfEventsToDelete = new Array();
|
||||
var eventsToDelete = [];
|
||||
var calendarsOfEventsToDelete = [];
|
||||
|
||||
var usersRightsWindowHeight = 250;
|
||||
var usersRightsWindowWidth = 502;
|
||||
|
||||
var eventsBlocks;
|
||||
var calendarEvents = null;
|
||||
|
||||
function newEvent(sender, type) {
|
||||
var day = $(sender).readAttribute("day");
|
||||
if (!day)
|
||||
|
@ -34,7 +37,7 @@ function newEvent(sender, type) {
|
|||
folderID = "/personal";
|
||||
}
|
||||
var urlstr = ApplicationBaseURL + folderID + "/new" + type;
|
||||
var params = new Array();
|
||||
var params = [];
|
||||
if (day)
|
||||
params.push("day=" + day);
|
||||
if (hour)
|
||||
|
@ -67,7 +70,7 @@ function onMenuNewTaskClick(event) {
|
|||
}
|
||||
|
||||
function _editEventId(id, calendar) {
|
||||
var urlstr = ApplicationBaseURL + "/" + calendar + "/" + id + "/edit";
|
||||
var urlstr = ApplicationBaseURL + calendar + "/" + id + "/edit";
|
||||
var targetname = "SOGo_edit_" + id;
|
||||
var win = window.open(urlstr, "_blank",
|
||||
"width=490,height=470,resizable=0");
|
||||
|
@ -100,7 +103,7 @@ function editEvent() {
|
|||
function _batchDeleteEvents() {
|
||||
var events = eventsToDelete.shift();
|
||||
var calendar = calendarsOfEventsToDelete.shift();
|
||||
var urlstr = (ApplicationBaseURL + "/" + calendar
|
||||
var urlstr = (ApplicationBaseURL + calendar
|
||||
+ "/batchDelete?ids=" + events.join('/'));
|
||||
document.deleteEventAjaxRequest = triggerAjaxRequest(urlstr,
|
||||
deleteEventCallback,
|
||||
|
@ -123,13 +126,13 @@ function deleteEvent() {
|
|||
document.deleteEventAjaxRequest.aborted = true;
|
||||
document.deleteEventAjaxRequest.abort();
|
||||
}
|
||||
var sortedNodes = new Array();
|
||||
var calendars = new Array();
|
||||
var sortedNodes = [];
|
||||
var calendars = [];
|
||||
|
||||
for (var i = 0; i < nodes.length; i++) {
|
||||
var calendar = nodes[i].calendar;
|
||||
if (!sortedNodes[calendar]) {
|
||||
sortedNodes[calendar] = new Array();
|
||||
sortedNodes[calendar] = [];
|
||||
calendars.push(calendar);
|
||||
}
|
||||
sortedNodes[calendar].push(nodes[i].cname);
|
||||
|
@ -228,19 +231,41 @@ function deleteEventCallback(http) {
|
|||
_batchDeleteEvents();
|
||||
else {
|
||||
document.deleteEventAjaxRequest = null;
|
||||
if (isTask)
|
||||
refreshTasks();
|
||||
else {
|
||||
refreshEvents();
|
||||
changeCalendarDisplay();
|
||||
}
|
||||
}
|
||||
if (isTask)
|
||||
deleteTasksFromViews(nodes);
|
||||
else
|
||||
deleteEventsFromViews(nodes)
|
||||
}
|
||||
else
|
||||
log ("deleteEventCallback Ajax error");
|
||||
}
|
||||
}
|
||||
|
||||
function deleteTasksFromViews(tasks) {
|
||||
}
|
||||
|
||||
function deleteEventsFromViews(events) {
|
||||
if (calendarEvents) {
|
||||
for (var i = 0; i < events.length; i++) {
|
||||
var cname = events[i];
|
||||
var event = calendarEvents[cname];
|
||||
if (event) {
|
||||
if (event.siblings) {
|
||||
for (var j = 0; j < event.siblings.length; j++) {
|
||||
var eventDiv = event.siblings[j];
|
||||
eventDiv.parentNode.removeChild(eventDiv);
|
||||
}
|
||||
}
|
||||
delete calendarEvents[cname]
|
||||
}
|
||||
var row = $(cname);
|
||||
if (row)
|
||||
row.parentNode.removeChild(row);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function editDoubleClickedEvent(event) {
|
||||
_editEventId(this.cname, this.calendar);
|
||||
|
||||
|
@ -364,12 +389,12 @@ function eventsListCallback(http) {
|
|||
td = $(document.createElement("td"));
|
||||
row.appendChild(td);
|
||||
td.observe("mousedown", listRowMouseDownHandler, true);
|
||||
td.appendChild(document.createTextNode(data[i][10]));
|
||||
td.appendChild(document.createTextNode(data[i][11]));
|
||||
|
||||
td = $(document.createElement("td"));
|
||||
row.appendChild(td);
|
||||
td.observe("mousedown", listRowMouseDownHandler, true);
|
||||
td.appendChild(document.createTextNode(data[i][11]));
|
||||
td.appendChild(document.createTextNode(data[i][12]));
|
||||
|
||||
td = $(document.createElement("td"));
|
||||
row.appendChild(td);
|
||||
|
@ -603,10 +628,8 @@ function scrollDayView(scrollEvent) {
|
|||
var divs;
|
||||
|
||||
// Select event in calendar view
|
||||
if (scrollEvent) {
|
||||
divs = $$("div#calendarContent div." + eventClass(scrollEvent));
|
||||
selectCalendarEvent(divs[0]);
|
||||
}
|
||||
if (scrollEvent)
|
||||
selectCalendarEvent(scrollEvent);
|
||||
|
||||
// Don't scroll if in month view
|
||||
if (currentView == "monthview")
|
||||
|
@ -614,22 +637,23 @@ function scrollDayView(scrollEvent) {
|
|||
|
||||
var offset = 0;
|
||||
var daysView = $("daysView");
|
||||
var hours =
|
||||
$(daysView.childNodesWithTag("div")[0]).childNodesWithTag("div");
|
||||
var hours = $(daysView.childNodesWithTag("div")[0])
|
||||
.childNodesWithTag("div");
|
||||
|
||||
if (scrollEvent) {
|
||||
divs = $$("div#calendarContent div." + eventClass(scrollEvent));
|
||||
var classes = $w(divs[0].className);
|
||||
for (var i = 0; i < classes.length; i++) {
|
||||
if (classes[i].startsWith("starts")) {
|
||||
var starts = Math.floor(parseInt(classes[i].substr(6)) / 4);
|
||||
offset = hours[starts].offsetTop;
|
||||
}
|
||||
// Scroll to 8 AM by default
|
||||
offset = hours[8].offsetTop;
|
||||
|
||||
if (scrollEvent && calendarEvents) {
|
||||
var event = calendarEvents[scrollEvent];
|
||||
if (event) {
|
||||
var classes = $w(event.siblings[0].className);
|
||||
for (var i = 0; i < classes.length; i++)
|
||||
if (classes[i].startsWith("starts")) {
|
||||
var starts = Math.floor(parseInt(classes[i].substr(6)) / 4);
|
||||
offset = hours[starts].offsetTop;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
// Scroll to 8 AM
|
||||
offset = hours[8].offsetTop;
|
||||
|
||||
daysView.scrollTop = offset - 5;
|
||||
}
|
||||
|
@ -684,7 +708,8 @@ function refreshCalendarEvents(scrollEvent) {
|
|||
document.refreshCalendarEventsAjaxRequest.aborted = true;
|
||||
document.refreshCalendarEventsAjaxRequest.abort();
|
||||
}
|
||||
var url = ApplicationBaseURL + "eventslist?sd=" + sd + "&ed=" + ed;
|
||||
var url = (ApplicationBaseURL + "eventsblocks?sd=" + sd + "&ed=" + ed
|
||||
+ "&view=" + currentView);
|
||||
document.refreshCalendarEventsAjaxRequest
|
||||
= triggerAjaxRequest(url, refreshCalendarEventsCallback,
|
||||
{"startDate": sd, "endDate": ed,
|
||||
|
@ -695,142 +720,13 @@ function refreshCalendarEventsCallback(http) {
|
|||
if (http.readyState == 4
|
||||
&& http.status == 200) {
|
||||
if (http.responseText.length > 0) {
|
||||
var data = http.responseText.evalJSON(true);
|
||||
// log("refresh calendar events: " + data.length);
|
||||
var dateTuples = new Array();
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
var dates = drawCalendarEvent(data[i],
|
||||
http.callbackData["startDate"],
|
||||
http.callbackData["endDate"]);
|
||||
dates.each(function(tuple) {
|
||||
if (tuple[3] == 0) tuple[3] = 96;
|
||||
dateTuples.push(tuple);
|
||||
});
|
||||
}
|
||||
|
||||
var c = {
|
||||
div: 0,
|
||||
day: 1,
|
||||
start: 2,
|
||||
end: 3,
|
||||
siblingsCount: 4,
|
||||
siblingsPosition: 5,
|
||||
siblingsMaxCount: 6
|
||||
};
|
||||
for (var i = 0; i < dateTuples.length; i++) {
|
||||
if (dateTuples[i].length < 6) {
|
||||
dateTuples[i][c.siblingsCount] = 1;
|
||||
dateTuples[i][c.siblingsPosition] = 0;
|
||||
}
|
||||
for (var j = 0; j < dateTuples.length; j++) {
|
||||
if (j == i) continue;
|
||||
if (dateTuples[i][c.day] == dateTuples[j][c.day]) {
|
||||
// Same day
|
||||
if (dateTuples[j][c.start] > dateTuples[i][c.start] &&
|
||||
dateTuples[j][c.start] < dateTuples[i][c.end] ||
|
||||
|
||||
dateTuples[j][c.start] == dateTuples[i][c.start] &&
|
||||
dateTuples[j][c.end] < dateTuples[i][c.end] ||
|
||||
|
||||
dateTuples[j][c.start] == dateTuples[i][c.start] &&
|
||||
dateTuples[j][c.end] == dateTuples[i][c.end] &&
|
||||
i < j) {
|
||||
// Same period
|
||||
if (dateTuples[j].length < 6) {
|
||||
dateTuples[j][c.siblingsCount] = 2;
|
||||
dateTuples[j][c.siblingsPosition] = dateTuples[i][c.siblingsPosition] + 1;
|
||||
}
|
||||
else {
|
||||
dateTuples[j][c.siblingsCount]++;
|
||||
dateTuples[j][c.siblingsPosition]++;
|
||||
}
|
||||
dateTuples[i][c.siblingsCount]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Second loop; adjust total number of siblings for each event
|
||||
for (var i = 0; i < dateTuples.length; i++) {
|
||||
//log (i + " " + dateTuples[i].inspect());
|
||||
var maxCount = 0;
|
||||
for (var j = 0; j < dateTuples.length; j++) {
|
||||
if (j == i) continue;
|
||||
if (dateTuples[i][c.day] == dateTuples[j][c.day]) {
|
||||
// Same day
|
||||
if (dateTuples[j][c.start] > dateTuples[i][c.start] &&
|
||||
dateTuples[j][c.start] < dateTuples[i][c.end] ||
|
||||
|
||||
dateTuples[j][c.start] == dateTuples[i][c.start] &&
|
||||
dateTuples[j][c.end] < dateTuples[i][c.end] ||
|
||||
|
||||
dateTuples[j][c.start] == dateTuples[i][c.start] &&
|
||||
dateTuples[j][c.end] == dateTuples[i][c.end] &&
|
||||
i < j) {
|
||||
// Same period
|
||||
if (dateTuples[j][c.siblingsCount] > maxCount)
|
||||
maxCount = dateTuples[j][c.siblingsCount];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (maxCount > 0) {
|
||||
dateTuples[i][c.siblingsCount] = maxCount;
|
||||
dateTuples[i][c.siblingsMaxCount] = maxCount;
|
||||
}
|
||||
}
|
||||
|
||||
// Third loop; adjust position and total number of siblings for each event
|
||||
for (var i = 0; i < dateTuples.length; i++) {
|
||||
//log (i + " " + dateTuples[i].inspect());
|
||||
for (var j = 0; j < dateTuples.length; j++) {
|
||||
if (j == i) continue;
|
||||
if (dateTuples[i][c.day] == dateTuples[j][c.day]) {
|
||||
// Same day
|
||||
if (dateTuples[j][c.start] > dateTuples[i][c.start] &&
|
||||
dateTuples[j][c.start] < dateTuples[i][c.end] ||
|
||||
|
||||
dateTuples[j][c.start] == dateTuples[i][c.start] &&
|
||||
dateTuples[j][c.end] < dateTuples[i][c.end] ||
|
||||
|
||||
dateTuples[j][c.start] == dateTuples[i][c.start] &&
|
||||
dateTuples[j][c.end] == dateTuples[i][c.end] &&
|
||||
i < j) {
|
||||
// Overlapping period
|
||||
if (dateTuples[j][c.siblingsPosition] == dateTuples[i][c.siblingsPosition]) {
|
||||
// Same position
|
||||
dateTuples[j][c.siblingsPosition]--; // not very clever
|
||||
}
|
||||
if (dateTuples[j].length < 7 ||
|
||||
dateTuples[j][c.siblingsMaxCount] < dateTuples[i][c.siblingsMaxCount])
|
||||
dateTuples[j][c.siblingsMaxCount] = dateTuples[i][c.siblingsMaxCount];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dateTuples[i].length < 7)
|
||||
dateTuples[i][c.siblingsMaxCount] = dateTuples[i][c.siblingsCount];
|
||||
}
|
||||
|
||||
// Final loop; draw the events
|
||||
//log ("[div, day, start index, end index, siblings count, siblings position, siblings max count]");
|
||||
for (var i = 0; i < dateTuples.length; i++) {
|
||||
//log (i + " " + dateTuples[i].inspect());
|
||||
|
||||
var base = dateTuples[i][c.siblingsCount] * dateTuples[i][c.siblingsMaxCount];
|
||||
var length = 1;
|
||||
var maxLength = 1 * dateTuples[i][c.siblingsMaxCount];
|
||||
|
||||
for (var j = dateTuples[i][c.siblingsCount];
|
||||
j < maxLength;
|
||||
j += dateTuples[i][c.siblingsCount]) { }
|
||||
|
||||
if (j > maxLength) {
|
||||
j -= dateTuples[i][c.siblingsCount];
|
||||
}
|
||||
|
||||
var width = 100 * j / base;
|
||||
var left = width * dateTuples[i][c.siblingsPosition];
|
||||
dateTuples[i][0].setStyle({ width: width + "%",
|
||||
left: left + "%" });
|
||||
var eventsBlocks = http.responseText.evalJSON(true);
|
||||
calendarEvents = _prepareCalendarEventsCache(eventsBlocks[0]);
|
||||
if (currentView == "monthview")
|
||||
_drawMonthCalendarEvents(eventsBlocks[2]);
|
||||
else {
|
||||
_drawCalendarAllDaysEvents(eventsBlocks[1]);
|
||||
_drawCalendarEvents(eventsBlocks[2]);
|
||||
}
|
||||
}
|
||||
scrollDayView(http.callbackData["scrollEvent"]);
|
||||
|
@ -839,133 +735,42 @@ function refreshCalendarEventsCallback(http) {
|
|||
log("AJAX error when refreshing calendar events");
|
||||
}
|
||||
|
||||
function drawCalendarEvent(eventData, sd, ed) {
|
||||
var dateTuples = new Array();
|
||||
function _prepareCalendarEventsCache(events) {
|
||||
var cache = {};
|
||||
|
||||
// log ("drawCalendarEvent...");
|
||||
var viewStartDate = sd.asDate();
|
||||
var viewEndDate = ed.asDate();
|
||||
for (var i = 0; i < events.length; i++) {
|
||||
cache[events[i][0]] = events[i];
|
||||
}
|
||||
|
||||
var startDate = new Date();
|
||||
startDate.setTime(eventData[4] * 1000);
|
||||
var endDate = new Date();
|
||||
endDate.setTime(eventData[5] * 1000);
|
||||
return cache;
|
||||
}
|
||||
|
||||
// log ("s: " + startDate + "; e: " + endDate);
|
||||
|
||||
var days = startDate.daysUpTo(endDate);
|
||||
|
||||
var title;
|
||||
if (currentView == "monthview"
|
||||
&& (eventData[7] == 0))
|
||||
title = startDate.getDisplayHoursString() + " " + eventData[3];
|
||||
else
|
||||
title = eventData[3];
|
||||
|
||||
// log("title: " + title);
|
||||
// log("viewS: " + viewStartDate);
|
||||
var startHour = null;
|
||||
var endHour = null;
|
||||
|
||||
var siblings = new Array();
|
||||
for (var i = 0; i < days.length; i++)
|
||||
if (days[i].earlierDate(viewStartDate) == viewStartDate
|
||||
&& days[i].laterDate(viewEndDate) == viewEndDate) {
|
||||
var starts;
|
||||
|
||||
// log("day: " + days[i]);
|
||||
if (i == 0) {
|
||||
var quarters = (startDate.getUTCHours() * 4
|
||||
+ Math.floor(startDate.getUTCMinutes() / 15));
|
||||
starts = quarters;
|
||||
startHour = startDate.getDisplayHoursString();
|
||||
endHour = endDate.getDisplayHoursString();
|
||||
}
|
||||
else
|
||||
starts = 0;
|
||||
|
||||
var ends;
|
||||
var lasts;
|
||||
if (i == days.length - 1) {
|
||||
var quarters = (endDate.getUTCHours() * 4
|
||||
+ Math.ceil(endDate.getUTCMinutes() / 15));
|
||||
ends = quarters;
|
||||
}
|
||||
else
|
||||
ends = 96;
|
||||
lasts = ends - starts;
|
||||
if (!lasts)
|
||||
lasts = 1;
|
||||
|
||||
var eventDiv = newEventDIV(eventData[0], eventData[1], starts, lasts,
|
||||
null, null, title);
|
||||
siblings.push(eventDiv);
|
||||
eventDiv.siblings = siblings;
|
||||
if (eventData[9].length > 0)
|
||||
eventDiv.addClassName(eventData[9]); // event owner status
|
||||
//eventDiv.setStyle({ width: '50%' });
|
||||
if (currentView != "monthview" &&
|
||||
eventData[7] == 0) // not "all day"
|
||||
dateTuples.push(new Array(eventDiv, days[i].getDayString(), starts, ends));
|
||||
var dayString = days[i].getDayString();
|
||||
// log("day: " + dayString);
|
||||
var parentDiv = null;
|
||||
if (currentView == "monthview") {
|
||||
var dayDivs = $("monthDaysView").childNodesWithTag("div");
|
||||
var j = 0;
|
||||
while (!parentDiv && j < dayDivs.length) {
|
||||
if (dayDivs[j].getAttribute("day") == dayString)
|
||||
parentDiv = dayDivs[j];
|
||||
else
|
||||
j++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (eventData[7] == 0) {
|
||||
var daysView = $("daysView");
|
||||
var eventsDiv = $(daysView).childNodesWithTag("div")[1];
|
||||
var dayDivs = $(eventsDiv).childNodesWithTag("div");
|
||||
var j = 0;
|
||||
while (!parentDiv && j < dayDivs.length) {
|
||||
if (dayDivs[j].getAttribute("day") == dayString)
|
||||
parentDiv = dayDivs[j].childNodesWithTag("div")[0];
|
||||
else
|
||||
j++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
var header = $("calendarHeader");
|
||||
var daysDiv = $(header).childNodesWithTag("div")[1];
|
||||
var dayDivs = $(daysDiv).childNodesWithTag("div");
|
||||
var j = 0;
|
||||
while (!parentDiv && j < dayDivs.length) {
|
||||
if (dayDivs[j].getAttribute("day") == dayString)
|
||||
parentDiv = dayDivs[j];
|
||||
else
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (parentDiv)
|
||||
parentDiv.appendChild(eventDiv);
|
||||
function _drawCalendarAllDaysEvents(events) {
|
||||
var daysView = $("calendarHeader");
|
||||
var subdivs = daysView.childNodesWithTag("div");
|
||||
var days = subdivs[1].childNodesWithTag("div");
|
||||
for (var i = 0; i < events.length; i++) {
|
||||
var parentDiv = days[i];
|
||||
for (var j = 0; j < events[i].length; j++) {
|
||||
var eventRep = events[i][j];
|
||||
var eventDiv = newAllDayEventDIV(eventRep);
|
||||
parentDiv.appendChild(eventDiv);
|
||||
}
|
||||
|
||||
return dateTuples;
|
||||
}
|
||||
}
|
||||
|
||||
function eventClass(cname) {
|
||||
return escape(cname.replace(".", "-"));
|
||||
}
|
||||
|
||||
function newEventDIV(cname, calendar, starts, lasts,
|
||||
startHour, endHour, title) {
|
||||
function newAllDayEventDIV(eventRep) {
|
||||
// cname, calendar, starts, lasts,
|
||||
// startHour, endHour, title) {
|
||||
var eventDiv = document.createElement("div");
|
||||
eventDiv.cname = escape(cname);
|
||||
eventDiv.calendar = calendar;
|
||||
var event = calendarEvents[eventRep.cname];
|
||||
if (!event.siblings)
|
||||
event.siblings = [];
|
||||
eventDiv.event = event;
|
||||
eventDiv.cname = event[0];
|
||||
eventDiv.calendar = event[1];
|
||||
|
||||
$(eventDiv).addClassName("event");
|
||||
$(eventDiv).addClassName(eventClass(cname));
|
||||
$(eventDiv).addClassName("starts" + starts);
|
||||
$(eventDiv).addClassName("lasts" + lasts);
|
||||
for (var i = 1; i < 5; i++) {
|
||||
var shadowDiv = document.createElement("div");
|
||||
eventDiv.appendChild(shadowDiv);
|
||||
|
@ -975,7 +780,7 @@ function newEventDIV(cname, calendar, starts, lasts,
|
|||
var innerDiv = document.createElement("div");
|
||||
eventDiv.appendChild(innerDiv);
|
||||
$(innerDiv).addClassName("eventInside");
|
||||
$(innerDiv).addClassName("calendarFolder" + calendar);
|
||||
$(innerDiv).addClassName("calendarFolder" + event[1]);
|
||||
|
||||
var gradientDiv = document.createElement("div");
|
||||
innerDiv.appendChild(gradientDiv);
|
||||
|
@ -987,20 +792,151 @@ function newEventDIV(cname, calendar, starts, lasts,
|
|||
var textDiv = document.createElement("div");
|
||||
innerDiv.appendChild(textDiv);
|
||||
$(textDiv).addClassName("text");
|
||||
if (startHour) {
|
||||
var headerSpan = document.createElement("span");
|
||||
textDiv.appendChild(headerSpan);
|
||||
$(headerSpan).addClassName("eventHeader");
|
||||
headerSpan.appendChild(document.createTextNode(startHour + " - "
|
||||
+ endHour));
|
||||
textDiv.appendChild(document.createElement("br"));
|
||||
}
|
||||
textDiv.appendChild(document.createTextNode(title));
|
||||
textDiv.appendChild(document.createTextNode(event[3]));
|
||||
|
||||
eventDiv.observe("mousedown", listRowMouseDownHandler);
|
||||
eventDiv.observe("click", onCalendarSelectEvent);
|
||||
eventDiv.observe("dblclick", editDoubleClickedEvent);
|
||||
|
||||
event.siblings.push(eventDiv);
|
||||
|
||||
return eventDiv;
|
||||
}
|
||||
|
||||
function _drawCalendarEvents(events) {
|
||||
var daysView = $("daysView");
|
||||
var subdivs = daysView.childNodesWithTag("div");
|
||||
var days = subdivs[1].childNodesWithTag("div");
|
||||
for (var i = 0; i < events.length; i++) {
|
||||
var parentDiv = days[i].childNodesWithTag("div")[0];
|
||||
for (var j = 0; j < events[i].length; j++) {
|
||||
var eventRep = events[i][j];
|
||||
var eventDiv = newEventDIV(eventRep);
|
||||
parentDiv.appendChild(eventDiv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function newEventDIV(eventRep) {
|
||||
// cname, calendar, starts, lasts,
|
||||
// startHour, endHour, title) {
|
||||
var eventDiv = document.createElement("div");
|
||||
var event = calendarEvents[eventRep.cname];
|
||||
if (!event.siblings)
|
||||
event.siblings = [];
|
||||
eventDiv.event = event;
|
||||
eventDiv.cname = event[0];
|
||||
eventDiv.calendar = event[1];
|
||||
|
||||
$(eventDiv).addClassName("event");
|
||||
// $(eventDiv).addClassName(eventClass(cname));
|
||||
$(eventDiv).addClassName("starts" + eventRep.start);
|
||||
$(eventDiv).addClassName("lasts" + eventRep.length);
|
||||
for (var i = 1; i < 5; i++) {
|
||||
var shadowDiv = document.createElement("div");
|
||||
eventDiv.appendChild(shadowDiv);
|
||||
$(shadowDiv).addClassName("shadow");
|
||||
$(shadowDiv).addClassName("shadow" + i);
|
||||
}
|
||||
var innerDiv = document.createElement("div");
|
||||
eventDiv.appendChild(innerDiv);
|
||||
$(innerDiv).addClassName("eventInside");
|
||||
$(innerDiv).addClassName("calendarFolder" + event[1]);
|
||||
|
||||
var gradientDiv = document.createElement("div");
|
||||
innerDiv.appendChild(gradientDiv);
|
||||
$(gradientDiv).addClassName("gradient");
|
||||
var gradientImg = document.createElement("img");
|
||||
gradientDiv.appendChild(gradientImg);
|
||||
gradientImg.src = ResourcesURL + "/event-gradient.png";
|
||||
|
||||
var textDiv = document.createElement("div");
|
||||
innerDiv.appendChild(textDiv);
|
||||
$(textDiv).addClassName("text");
|
||||
// if (startHour) {
|
||||
// var headerSpan = document.createElement("span");
|
||||
// textDiv.appendChild(headerSpan);
|
||||
// $(headerSpan).addClassName("eventHeader");
|
||||
// headerSpan.appendChild(document.createTextNode(startHour + " - "
|
||||
// + endHour));
|
||||
// textDiv.appendChild(document.createElement("br"));
|
||||
// }
|
||||
textDiv.appendChild(document.createTextNode(event[3]));
|
||||
|
||||
var pc = 100 / eventRep.siblings;
|
||||
eventDiv.style.width = pc + "%";
|
||||
var left = eventRep.position * pc;
|
||||
eventDiv.style.left = left + "%";
|
||||
|
||||
eventDiv.observe("mousedown", listRowMouseDownHandler);
|
||||
eventDiv.observe("click", onCalendarSelectEvent);
|
||||
eventDiv.observe("dblclick", editDoubleClickedEvent);
|
||||
|
||||
event.siblings.push(eventDiv);
|
||||
|
||||
return eventDiv;
|
||||
}
|
||||
|
||||
function _drawMonthCalendarEvents(events) {
|
||||
var daysView = $("monthDaysView");
|
||||
var days = daysView.childNodesWithTag("div");
|
||||
for (var i = 0; i < days.length; i++) {
|
||||
var parentDiv = days[i];
|
||||
for (var j = 0; j < events[i].length; j++) {
|
||||
var eventRep = events[i][j];
|
||||
var eventDiv = newMonthEventDIV(eventRep);
|
||||
parentDiv.appendChild(eventDiv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function newMonthEventDIV(eventRep) {
|
||||
// cname, calendar, starts, lasts,
|
||||
// startHour, endHour, title) {
|
||||
var eventDiv = document.createElement("div");
|
||||
var event = calendarEvents[eventRep.cname];
|
||||
if (!event.siblings)
|
||||
event.siblings = [];
|
||||
eventDiv.event = event;
|
||||
eventDiv.cname = event[0];
|
||||
eventDiv.calendar = event[1];
|
||||
|
||||
$(eventDiv).addClassName("event");
|
||||
for (var i = 1; i < 5; i++) {
|
||||
var shadowDiv = document.createElement("div");
|
||||
eventDiv.appendChild(shadowDiv);
|
||||
$(shadowDiv).addClassName("shadow");
|
||||
$(shadowDiv).addClassName("shadow" + i);
|
||||
}
|
||||
var innerDiv = document.createElement("div");
|
||||
eventDiv.appendChild(innerDiv);
|
||||
$(innerDiv).addClassName("eventInside");
|
||||
$(innerDiv).addClassName("calendarFolder" + event[1]);
|
||||
|
||||
var gradientDiv = document.createElement("div");
|
||||
innerDiv.appendChild(gradientDiv);
|
||||
$(gradientDiv).addClassName("gradient");
|
||||
var gradientImg = document.createElement("img");
|
||||
gradientDiv.appendChild(gradientImg);
|
||||
gradientImg.src = ResourcesURL + "/event-gradient.png";
|
||||
|
||||
var textDiv = document.createElement("div");
|
||||
innerDiv.appendChild(textDiv);
|
||||
$(textDiv).addClassName("textw");
|
||||
|
||||
var eventText;
|
||||
if (event[7])
|
||||
eventText = event[3];
|
||||
else
|
||||
eventText = eventRep.starthour + " - " + event[3];
|
||||
textDiv.appendChild(document.createTextNode(eventText));
|
||||
|
||||
eventDiv.observe("mousedown", listRowMouseDownHandler);
|
||||
eventDiv.observe("click", onCalendarSelectEvent);
|
||||
eventDiv.observe("dblclick", editDoubleClickedEvent);
|
||||
|
||||
event.siblings.push(eventDiv);
|
||||
|
||||
return eventDiv;
|
||||
}
|
||||
|
||||
|
@ -1021,7 +957,7 @@ function calendarDisplayCallback(http) {
|
|||
contentView = $("calendarContent");
|
||||
else
|
||||
contentView = $("daysView");
|
||||
|
||||
|
||||
refreshCalendarEvents(http.callbackData.scrollEvent);
|
||||
|
||||
var days = document.getElementsByClassName("day", contentView);
|
||||
|
@ -1270,22 +1206,30 @@ function onYearMenuItemClick(event) {
|
|||
changeDateSelectorDisplay(year + month + "01", true);
|
||||
}
|
||||
|
||||
function selectCalendarEvent(div) {
|
||||
function selectCalendarEvent(cname) {
|
||||
// Select event in calendar view
|
||||
if (selectedCalendarCell)
|
||||
for (var i = 0; i < selectedCalendarCell.length; i++)
|
||||
selectedCalendarCell[i].deselect();
|
||||
|
||||
for (var i = 0; i < div.siblings.length; i++)
|
||||
div.siblings[i].selectElement();
|
||||
|
||||
selectedCalendarCell = div.siblings;
|
||||
if (calendarEvents) {
|
||||
var event = calendarEvents[cname];
|
||||
// if (event) {
|
||||
// if (event[12])
|
||||
// log("recurrence; date=" + event[4]);
|
||||
// }
|
||||
if (event && event.siblings) {
|
||||
for (var i = 0; i < event.siblings.length; i++)
|
||||
event.siblings[i].selectElement();
|
||||
selectedCalendarCell = event.siblings;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onCalendarSelectEvent() {
|
||||
var list = $("eventsList");
|
||||
|
||||
selectCalendarEvent(this);
|
||||
selectCalendarEvent(this.cname);
|
||||
|
||||
// Select event in events list
|
||||
$(list.tBodies[0]).deselectAll();
|
||||
|
@ -1298,11 +1242,7 @@ function onCalendarSelectEvent() {
|
|||
}
|
||||
|
||||
function onCalendarSelectDay(event) {
|
||||
var day;
|
||||
if (currentView == "multicolumndayview")
|
||||
day = this.getAttribute("day");
|
||||
else
|
||||
day = this.getAttribute("day");
|
||||
var day = this.getAttribute("day");
|
||||
var needRefresh = (listFilter == 'view_selectedday'
|
||||
&& day != currentDay);
|
||||
|
||||
|
@ -1322,22 +1262,23 @@ function onCalendarSelectDay(event) {
|
|||
}
|
||||
|
||||
function changeWeekCalendarDisplayOfSelectedDay(node) {
|
||||
var days = document.getElementsByClassName("day", node.parentNode);
|
||||
var daysView = $("daysView");
|
||||
var daysDiv = daysView.childNodesWithTag("div");
|
||||
var days = daysDiv[1].childNodesWithTag("div");
|
||||
var headerDiv = $("calendarHeader").childNodesWithTag("div")[1];
|
||||
var headerDays = document.getElementsByClassName("day", headerDiv);
|
||||
var headerDays = $(headerDiv).childNodesWithTag("div");
|
||||
|
||||
// log ("days: " + days.length + "; headerDays: " + headerDays.length);
|
||||
for (var i = 0; i < days.length; i++)
|
||||
if (days[i] != node) {
|
||||
// log("unselect day : " + i);
|
||||
headerDays[i].removeClassName("selectedDay");
|
||||
days[i].removeClassName("selectedDay");
|
||||
}
|
||||
else {
|
||||
// log("selected day : " + i);
|
||||
for (var i = 0; i < days.length; i++) {
|
||||
if (days[i] == node
|
||||
|| headerDays[i] == node) {
|
||||
headerDays[i].addClassName("selectedDay");
|
||||
days[i].addClassName("selectedDay");
|
||||
}
|
||||
else {
|
||||
headerDays[i].removeClassName("selectedDay");
|
||||
days[i].removeClassName("selectedDay");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function findMonthCalendarSelectedCell(daysContainer) {
|
||||
|
@ -1400,7 +1341,7 @@ function updateTaskStatus(event) {
|
|||
}
|
||||
|
||||
function updateCalendarStatus(event) {
|
||||
var list = new Array();
|
||||
var list = [];
|
||||
var newStatus = (this.checked ? 1 : 0);
|
||||
|
||||
if (isSafari() && !isSafari3()) {
|
||||
|
@ -1525,12 +1466,12 @@ function onCalendarsMenuPrepareVisibility() {
|
|||
function getMenus() {
|
||||
var menus = {};
|
||||
|
||||
var dateMenu = new Array();
|
||||
var dateMenu = [];
|
||||
for (var i = 0; i < 12; i++)
|
||||
dateMenu.push(onMonthMenuItemClick);
|
||||
menus["monthListMenu"] = dateMenu;
|
||||
|
||||
dateMenu = new Array();
|
||||
dateMenu = [];
|
||||
for (var i = 0; i < 11; i++)
|
||||
dateMenu.push(onYearMenuItemClick);
|
||||
menus["yearListMenu"] = dateMenu;
|
||||
|
@ -1830,7 +1771,7 @@ function initDateSelectorEvents() {
|
|||
arrow.observe("click", onDateSelectorGotoMonth);
|
||||
arrow = $("leftArrow");
|
||||
arrow.observe("click", onDateSelectorGotoMonth);
|
||||
|
||||
|
||||
var menuButton = $("monthLabel");
|
||||
menuButton.observe("click", popupMonthMenu);
|
||||
menuButton = $("yearLabel");
|
||||
|
|
Loading…
Reference in New Issue