Monotone-Parent: 1d8390cb8afe22fe543231383205ab7e41337609

Monotone-Revision: f633654a120834c13835a3ef41a1418e31efffe3

Monotone-Author: wsourdeau@inverse.ca
Monotone-Date: 2008-07-16T21:48:54
Monotone-Branch: ca.inverse.sogo
maint-2.0.2
Wolfgang Sourdeau 2008-07-16 21:48:54 +00:00
parent f2527bfde3
commit f0d7546b8b
8 changed files with 259 additions and 182 deletions

View File

@ -1,3 +1,14 @@
2008-07-16 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* UI/Scheduler/UIxCalListingActions.m ([UIxCalListingActions
-eventsBlocksAction]): take user participation status into account
again.
* SoObjects/Appointments/iCalEntityObject+SOGo.m
([iCalEntityObject
-quickRecordDateAsNumber:_datewithOffset:offsetforAllDay:allDay]):
enhanced method to do the special computations for all day events.
2008-07-15 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* UI/Scheduler/NSDictionary+Scheduler.m: new category module that

View File

@ -46,7 +46,9 @@ NSNumber *iCalDistantFutureNumber;
- (NSMutableDictionary *) quickRecord;
- (int) priorityNumber;
- (NSNumber *) quickRecordDateAsNumber: (NSCalendarDate *) _date;
- (NSNumber *) quickRecordDateAsNumber: (NSCalendarDate *) _date
withOffset: (int) offset
forAllDay: (BOOL) allDay;
@end

View File

@ -24,10 +24,14 @@
#import <Foundation/NSEnumerator.h>
#import <Foundation/NSString.h>
#import <Foundation/NSValue.h>
#import <Foundation/NSTimeZone.h>
#import <NGCards/iCalCalendar.h>
#import <NGCards/iCalPerson.h>
#import <NGObjWeb/WOApplication.h>
#import <NGObjWeb/WOContext+SoObjects.h>
#import <SoObjects/SOGo/NSArray+Utilities.h>
#import <SoObjects/SOGo/SOGoUser.h>
@ -35,8 +39,31 @@
#import "iCalEntityObject+SOGo.h"
static int utcOffset = -1;
@implementation iCalEntityObject (SOGoExtensions)
static inline int
_computeAllDayOffset()
{
NSTimeZone *tz;
SOGoUser *user;
WOApplication *application;
int offset;
if (utcOffset == -1)
{
tz = [[NSCalendarDate date] timeZone];
utcOffset = [tz secondsFromGMT];
}
application = [WOApplication application];
user = [[application context] activeUser];
offset = utcOffset - [[user timeZone] secondsFromGMT];
return offset;
}
+ (void) initializeSOGoExtensions;
{
if (!iCalDistantFuture)
@ -140,10 +167,24 @@
}
- (NSNumber *) quickRecordDateAsNumber: (NSCalendarDate *) _date
withOffset: (int) offset
forAllDay: (BOOL) allDay
{
return ((_date == iCalDistantFuture)
? iCalDistantFutureNumber
: [NSNumber numberWithUnsignedInt: [_date timeIntervalSince1970]]);
unsigned int seconds;
NSNumber *dateNumber;
if (_date == iCalDistantFuture)
dateNumber = iCalDistantFutureNumber;
else
{
seconds = [_date timeIntervalSince1970] + offset;
if (allDay)
seconds += _computeAllDayOffset ();
dateNumber = [NSNumber numberWithUnsignedInt: seconds];
}
return dateNumber;
}
- (NSMutableDictionary *) quickRecord

View File

@ -52,7 +52,7 @@
NSCalendarDate *startDate, *endDate;
NSArray *attendees;
NSString *uid, *title, *location, *status;
NSNumber *sequence, *dateNumber;
NSNumber *sequence;
id organizer;
id participants, partmails;
NSMutableString *partstates;
@ -61,7 +61,7 @@
iCalAccessClass accessClass;
/* extract values */
startDate = [self startDate];
endDate = [self endDate];
uid = [self uid];
@ -108,56 +108,56 @@
if ([sequence isNotNull]) [row setObject: sequence forKey: @"c_sequence"];
if ([startDate isNotNull])
[row setObject: [self quickRecordDateAsNumber: startDate]
forKey: @"c_startdate"];
if ([endDate isNotNull])
{
if (endDate == iCalDistantFuture)
dateNumber = iCalDistantFutureNumber;
else
{
if (isAllDay)
i = 1;
else
i = 0;
dateNumber
= [NSNumber numberWithUnsignedInt:
[endDate timeIntervalSince1970] - i];
}
[row setObject: dateNumber forKey: @"c_enddate"];
if (isAllDay)
NSLog (@"start date...");
[row setObject: [self quickRecordDateAsNumber: startDate
withOffset: 0 forAllDay: isAllDay]
forKey: @"c_startdate"];
}
if ([endDate isNotNull])
[row setObject: [self quickRecordDateAsNumber: endDate
withOffset: ((isAllDay) ? -1 : 0)
forAllDay: isAllDay]
forKey: @"c_enddate"];
if ([self isRecurrent]) {
NSCalendarDate *date;
date = [self lastPossibleRecurrenceStartDate];
if (!date) {
/* this could also be *nil*, but in the end it makes the fetchspecs
more complex - thus we set it to a "reasonable" distant future */
date = iCalDistantFuture;
if ([self isRecurrent])
{
NSCalendarDate *date;
date = [self lastPossibleRecurrenceStartDate];
if (!date)
{
/* this could also be *nil*, but in the end it makes the fetchspecs
more complex - thus we set it to a "reasonable" distant future */
date = iCalDistantFuture;
}
[row setObject: [self quickRecordDateAsNumber: date
withOffset: 0 forAllDay: NO]
forKey: @"c_cycleenddate"];
[row setObject: [self cycleInfo] forKey: @"c_cycleinfo"];
}
[row setObject:[self quickRecordDateAsNumber:date] forKey: @"c_cycleenddate"];
[row setObject:[self cycleInfo] forKey: @"c_cycleinfo"];
}
if ([participants length] > 0)
[row setObject: participants forKey: @"c_participants"];
if ([partmails length] > 0)
[row setObject: partmails forKey: @"c_partmails"];
if ([status isNotNull]) {
int code = 1;
if ([status isNotNull])
{
int code = 1;
if ([status isEqualToString: @"TENTATIVE"])
code = 2;
else if ([status isEqualToString: @"CANCELLED"])
code = 0;
[row setObject:[NSNumber numberWithInt:code] forKey: @"c_status"];
}
else {
/* confirmed by default */
[row setObject: [NSNumber numberWithInt:1] forKey: @"c_status"];
}
if ([status isEqualToString: @"TENTATIVE"])
code = 2;
else if ([status isEqualToString: @"CANCELLED"])
code = 0;
[row setObject:[NSNumber numberWithInt:code] forKey: @"c_status"];
}
else
{
/* confirmed by default */
[row setObject: [NSNumber numberWithInt:1] forKey: @"c_status"];
}
[row setObject: [NSNumber numberWithUnsignedInt: accessClass]
forKey: @"c_classification"];

View File

@ -95,23 +95,23 @@
if ([sequence isNotNull]) [row setObject: sequence forKey: @"c_sequence"];
if ([startDate isNotNull])
date = [self quickRecordDateAsNumber: startDate];
date = [self quickRecordDateAsNumber: startDate
withOffset: 0 forAllDay: NO];
else
date = [NSNull null];
[row setObject: date forKey: @"c_startdate"];
if ([dueDate isNotNull])
date = [self quickRecordDateAsNumber: dueDate];
if ([dueDate isNotNull])
date = [self quickRecordDateAsNumber: dueDate
withOffset: 0 forAllDay: NO];
else
date = [NSNull null];
[row setObject: date forKey: @"c_enddate"];
if ([self isRecurrent])
{
[row setObject: [self quickRecordDateAsNumber: iCalDistantFuture]
forKey: @"c_cycleenddate"];
[row setObject: [self cycleInfo]
forKey: @"c_cycleinfo"];
[row setObject: iCalDistantFutureNumber forKey: @"c_cycleenddate"];
[row setObject: [self cycleInfo] forKey: @"c_cycleinfo"];
}
if ([participants length] > 0)
@ -119,46 +119,50 @@
if ([partmails length] > 0)
[row setObject:partmails forKey: @"c_partmails"];
if ([status isNotNull]) {
code = 0; /* NEEDS-ACTION */
if ([status isEqualToString: @"COMPLETED"])
code = 1;
else if ([status isEqualToString: @"IN-PROCESS"])
code = 2;
else if ([status isEqualToString: @"CANCELLED"])
code = 3;
[row setObject: [NSNumber numberWithInt: code] forKey: @"c_status"];
}
else {
/* confirmed by default */
[row setObject:[NSNumber numberWithInt:1] forKey: @"c_status"];
}
if ([status isNotNull])
{
code = 0; /* NEEDS-ACTION */
if ([status isEqualToString: @"COMPLETED"])
code = 1;
else if ([status isEqualToString: @"IN-PROCESS"])
code = 2;
else if ([status isEqualToString: @"CANCELLED"])
code = 3;
[row setObject: [NSNumber numberWithInt: code] forKey: @"c_status"];
}
else
{
/* confirmed by default */
[row setObject:[NSNumber numberWithInt:1] forKey: @"c_status"];
}
[row setObject: [NSNumber numberWithUnsignedInt: accessClass]
forKey: @"c_classification"];
organizer = [self organizer];
if (organizer) {
NSString *email;
if (organizer)
{
NSString *email;
email = [organizer valueForKey: @"rfc822Email"];
if (email)
[row setObject:email forKey: @"c_orgmail"];
}
email = [organizer valueForKey: @"rfc822Email"];
if (email)
[row setObject:email forKey: @"c_orgmail"];
}
/* construct partstates */
count = [attendees count];
partstates = [[NSMutableString alloc] initWithCapacity:count * 2];
for ( i = 0; i < count; i++) {
iCalPerson *p;
iCalPersonPartStat stat;
for (i = 0; i < count; i++)
{
iCalPerson *p;
iCalPersonPartStat stat;
p = [attendees objectAtIndex:i];
stat = [p participationStatus];
if(i != 0)
[partstates appendString: @"\n"];
[partstates appendFormat: @"%d", stat];
}
p = [attendees objectAtIndex:i];
stat = [p participationStatus];
if(i != 0)
[partstates appendString: @"\n"];
[partstates appendFormat: @"%d", stat];
}
[row setObject:partstates forKey: @"c_partstates"];
[partstates release];

View File

@ -323,13 +323,12 @@ static NSArray *tasksFields = nil;
- (WOResponse *) eventsListAction
{
NSArray *oldEvent, *participants, *states;
NSArray *oldEvent;
NSEnumerator *events;
NSMutableArray *newEvents, *newEvent;
unsigned int interval, i;
unsigned int interval;
BOOL isAllDay;
NSString *sort, *ascending, *participant, *state;
SOGoUser *user;
NSString *sort, *ascending;
[self _setupContext];
@ -346,40 +345,6 @@ static NSArray *tasksFields = nil;
interval = [[oldEvent objectAtIndex: 5] intValue];
[newEvent addObject: [self _formattedDateForSeconds: interval
forAllDay: isAllDay]];
participants = nil;
state = nil;
if ([[oldEvent objectAtIndex: 9] length] > 0 &&
[[oldEvent objectAtIndex: 10] length] > 0)
{
participants = [[oldEvent objectAtIndex: 9] componentsSeparatedByString: @"\n"];
states = [[oldEvent objectAtIndex: 10] componentsSeparatedByString: @"\n"];
for (i = 0; i < [participants count]; i++)
{
user = [SOGoUser userWithLogin: [oldEvent objectAtIndex: 11] roles: nil];
participant = [participants objectAtIndex: i];
if ([user hasEmail: participant]) {
switch ([[states objectAtIndex: i] intValue]) {
case iCalPersonPartStatNeedsAction:
state = @"needs-action";
break;
case iCalPersonPartStatAccepted:
state = @"accepted";
break;
case iCalPersonPartStatDeclined:
state = @"declined";
break;
}
[newEvent replaceObjectAtIndex: 9 withObject: state];
break;
}
}
}
if (participants == nil || i == [participants count])
[newEvent replaceObjectAtIndex: 9 withObject: @""];
[newEvent removeObjectAtIndex: 11];
[newEvent removeObjectAtIndex: 10];
[newEvents addObject: newEvent];
}
@ -440,6 +405,7 @@ _feedBlockWithMonthBasedData(NSMutableDictionary *block, unsigned int start,
cname: (NSString *) cName
onDay: (unsigned int) dayStart
recurrence: (BOOL) recurrence
userState: (iCalPersonPartStat) userState
{
NSMutableDictionary *block;
@ -452,10 +418,47 @@ _feedBlockWithMonthBasedData(NSMutableDictionary *block, unsigned int start,
[block setObject: cName forKey: @"cname"];
if (recurrence)
[block setObject: @"1" forKey: @"recurrence"];
if (userState != iCalPersonPartStatOther)
[block setObject: [NSNumber numberWithInt: userState]
forKey: @"userState"];
return block;
}
static inline iCalPersonPartStat
_userStateInEvent (NSArray *event)
{
unsigned int count, max;
iCalPersonPartStat state;
NSString *partList, *stateList;
NSArray *participants, *states;
SOGoUser *user;
participants = nil;
state = iCalPersonPartStatOther;
partList = [event objectAtIndex: 9];
stateList = [event objectAtIndex: 10];
if ([partList length] && [stateList length])
{
participants = [partList componentsSeparatedByString: @"\n"];
states = [stateList componentsSeparatedByString: @"\n"];
count = 0;
max = [participants count];
while (state == iCalPersonPartStatOther && count < max)
{
user = [SOGoUser userWithLogin: [event objectAtIndex: 11]
roles: nil];
if ([user hasEmail: [participants objectAtIndex: count]])
state = [[states objectAtIndex: count] intValue];
else
count++;
}
}
return state;
}
- (void) _fillBlocks: (NSArray *) blocks
withEvent: (NSArray *) event
{
@ -465,6 +468,7 @@ _feedBlockWithMonthBasedData(NSMutableDictionary *block, unsigned int start,
NSMutableDictionary *eventBlock;
NSString *eventCName;
BOOL recurrence;
iCalPersonPartStat userState;
startSecs = (unsigned int) [startDate timeIntervalSince1970];
endsSecs = (unsigned int) [endDate timeIntervalSince1970];
@ -489,13 +493,15 @@ _feedBlockWithMonthBasedData(NSMutableDictionary *block, unsigned int start,
eventEnd = endsSecs;
eventCName = [event objectAtIndex: 0];
while (currentStart + dayLength < eventEnd)
userState = _userStateInEvent (event);
while (currentDayStart + dayLength < eventEnd)
{
eventBlock = [self _eventBlockWithStart: currentStart
end: currentDayStart + 86399
end: currentDayStart + dayLength - 1
cname: eventCName
onDay: currentDayStart
recurrence: recurrence];
recurrence: recurrence
userState: userState];
[currentDay addObject: eventBlock];
currentDayStart += dayLength;
currentStart = currentDayStart;
@ -506,7 +512,8 @@ _feedBlockWithMonthBasedData(NSMutableDictionary *block, unsigned int start,
end: eventEnd
cname: eventCName
onDay: currentDayStart
recurrence: recurrence];
recurrence: recurrence
userState: userState];
[currentDay addObject: eventBlock];
}

View File

@ -906,22 +906,22 @@ DIV.event DIV.text
DIV.event.needs-action DIV.text
{ background-image: url("needs-action.png");
background-repeat: no-repeat;
background-position: 98% 95%; }
background-position: top right; }
DIV.event.accepted DIV.text
{ background-image: url("accepted.png");
background-repeat: no-repeat;
background-position: 98% 95%; }
background-position: top right; }
DIV.event.declined DIV.text
{ background-image: url("declined.png");
background-repeat: no-repeat;
background-position: 98% 95%; }
background-position: top right; }
DIV.event.tentative DIV.text
{ background-image: url("tentative.png");
background-repeat: no-repeat;
background-position: 98% 95%; }
background-position: top right; }
DIV#daysView DIV[class~="event"].starts0
{ top: 0.000000%; }

View File

@ -23,6 +23,8 @@ var usersRightsWindowWidth = 502;
var eventsBlocks;
var calendarEvents = null;
var userStates = [ "needs-action", "accepted", "declined", "tentative" ];
function newEvent(sender, type) {
var day = $(sender).readAttribute("day");
if (!day)
@ -389,12 +391,12 @@ function eventsListCallback(http) {
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][13]));
td = $(document.createElement("td"));
row.appendChild(td);
td.observe("mousedown", listRowMouseDownHandler, true);
td.appendChild(document.createTextNode(data[i][12]));
td.appendChild(document.createTextNode(data[i][14]));
td = $(document.createElement("td"));
row.appendChild(td);
@ -762,7 +764,7 @@ function _drawCalendarAllDaysEvents(events) {
function newAllDayEventDIV(eventRep) {
// cname, calendar, starts, lasts,
// startHour, endHour, title) {
var eventDiv = document.createElement("div");
var eventDiv = $(document.createElement("div"));
var event = calendarEvents[eventRep.cname];
if (!event.siblings)
event.siblings = [];
@ -770,28 +772,31 @@ function newAllDayEventDIV(eventRep) {
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]);
eventDiv.addClassName("event");
if (eventRep.userState && userStates[eventRep.userState])
eventDiv.addClassName(userStates[eventRep.userState]);
var gradientDiv = document.createElement("div");
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");
gradientDiv.addClassName("gradient");
var gradientImg = document.createElement("img");
gradientDiv.appendChild(gradientImg);
gradientImg.src = ResourcesURL + "/event-gradient.png";
var textDiv = document.createElement("div");
var textDiv = $(document.createElement("div"));
innerDiv.appendChild(textDiv);
$(textDiv).addClassName("text");
textDiv.addClassName("text");
textDiv.appendChild(document.createTextNode(event[3]));
eventDiv.observe("mousedown", listRowMouseDownHandler);
@ -820,7 +825,7 @@ function _drawCalendarEvents(events) {
function newEventDIV(eventRep) {
// cname, calendar, starts, lasts,
// startHour, endHour, title) {
var eventDiv = document.createElement("div");
var eventDiv = $(document.createElement("div"));
var event = calendarEvents[eventRep.cname];
if (!event.siblings)
event.siblings = [];
@ -828,31 +833,33 @@ function newEventDIV(eventRep) {
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]);
eventDiv.addClassName("event");
if (eventRep.userState && userStates[eventRep.userState])
eventDiv.addClassName(userStates[eventRep.userState]);
var gradientDiv = document.createElement("div");
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.addClassName("gradient");
var gradientImg = $(document.createElement("img"));
gradientDiv.appendChild(gradientImg);
gradientImg.src = ResourcesURL + "/event-gradient.png";
var textDiv = document.createElement("div");
var textDiv = $(document.createElement("div"));
innerDiv.appendChild(textDiv);
$(textDiv).addClassName("text");
textDiv.addClassName("text");
// if (startHour) {
// var headerSpan = document.createElement("span");
// textDiv.appendChild(headerSpan);
@ -893,7 +900,7 @@ function _drawMonthCalendarEvents(events) {
function newMonthEventDIV(eventRep) {
// cname, calendar, starts, lasts,
// startHour, endHour, title) {
var eventDiv = document.createElement("div");
var eventDiv = $(document.createElement("div"));
var event = calendarEvents[eventRep.cname];
if (!event.siblings)
event.siblings = [];
@ -901,28 +908,33 @@ function newMonthEventDIV(eventRep) {
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);
eventDiv.addClassName("event");
if (eventRep.userState && userStates[eventRep.userState]) {
eventDiv.addClassName(userStates[eventRep.userState]);
log (eventDiv.getAttribute("class"));
}
var innerDiv = document.createElement("div");
eventDiv.appendChild(innerDiv);
$(innerDiv).addClassName("eventInside");
$(innerDiv).addClassName("calendarFolder" + event[1]);
var gradientDiv = document.createElement("div");
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");
gradientDiv.addClassName("gradient");
var gradientImg = document.createElement("img");
gradientDiv.appendChild(gradientImg);
gradientImg.src = ResourcesURL + "/event-gradient.png";
var textDiv = document.createElement("div");
var textDiv = $(document.createElement("div"));
innerDiv.appendChild(textDiv);
$(textDiv).addClassName("textw");
textDiv.addClassName("textw");
var eventText;
if (event[7])
@ -1265,8 +1277,8 @@ function changeWeekCalendarDisplayOfSelectedDay(node) {
var daysView = $("daysView");
var daysDiv = daysView.childNodesWithTag("div");
var days = daysDiv[1].childNodesWithTag("div");
var headerDiv = $("calendarHeader").childNodesWithTag("div")[1];
var headerDays = $(headerDiv).childNodesWithTag("div");
var headerDiv = $($("calendarHeader").childNodesWithTag("div")[1]);
var headerDays = headerDiv.childNodesWithTag("div");
for (var i = 0; i < days.length; i++) {
if (days[i] == node