Monotone-Parent: 52de90085e2d18ded0d0c315e7148e1c72feb785
Monotone-Revision: 99d14630f5294d40da6680a39d69b6f1b7853938 Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2008-07-17T21:12:43 Monotone-Branch: ca.inverse.sogomaint-2.0.2
parent
e1beed1ba0
commit
bdc02c26ab
45
ChangeLog
45
ChangeLog
|
@ -1,3 +1,48 @@
|
|||
2008-07-17 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
|
||||
* UI/Scheduler/UIxCalListingActions.m ([UIxCalListingActions
|
||||
-eventsBlocksAction]): event blocks now that the "c_recurrence_id"
|
||||
virtual field into account.
|
||||
|
||||
* UI/Common/UIxObjectActions.m ([UIxObjectActions -deleteAction]):
|
||||
new action method, moved from UIxContactView so that it is
|
||||
generalized to all SOGoObjects.
|
||||
|
||||
* SoObjects/Appointments/SOGoCalendarComponent.m
|
||||
([SOGoCalendarComponent -init]): we now save the calendar to avoid
|
||||
multiple parsing and instantiation of children components.
|
||||
([SOGoCalendarComponent -toOneRelationshipKeys]): declare
|
||||
components as children.
|
||||
([SOGoCalendarComponent
|
||||
-lookupName:lookupNameinContext:localContextacquire:acquire]):
|
||||
handle the search for components and their occurences.
|
||||
([SOGoCalendarComponent -saveComponent:newObject]): added code to
|
||||
update recurrence ids whenever the user saves a new version of the
|
||||
master component.
|
||||
|
||||
* SoObjects/Appointments/SOGoAppointmentObject.m ([SOGoAppointmentObject -occurence:occ])
|
||||
([SOGoAppointmentObject -newOccurenceWithID:recID])
|
||||
([SOGoAppointmentObject -prepareDeleteOccurence:occurence]): new
|
||||
methods to handle occurences.
|
||||
|
||||
* SoObjects/Appointments/SOGoAppointmentFolder.m
|
||||
([SOGoAppointmentFolder -fixupCycleRecord:_recordcycleRange:_r]):
|
||||
declare a new "c_recurrence_id" field, that will be overwritten
|
||||
with further exception occurences.
|
||||
|
||||
* UI/Scheduler/UIxOccurenceDialog.[hm]: new dialog asking whether
|
||||
to edit/delete all occurences of a recurrent event or only the one
|
||||
selected.
|
||||
|
||||
* SoObjects/Appointments/SOGoComponentOccurence.[hm]: super class
|
||||
of new classes belows.
|
||||
|
||||
* SoObjects/Appointments/SOGoAppointmentOccurence.[hm]: new class
|
||||
module that handle occurences within events.
|
||||
|
||||
* SoObjects/Appointments/SOGoTaskOccurence.[hm]: new class
|
||||
module that handle occurences within todos.
|
||||
|
||||
2008-07-16 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
|
||||
* UI/Scheduler/UIxCalListingActions.m ([UIxCalListingActions
|
||||
|
|
1
NEWS
1
NEWS
|
@ -14,6 +14,7 @@ address book in the Address Book module
|
|||
- fixed various bugs occuring with Firefox 3
|
||||
- fixed bug where selecting the current day cell would not select the header day cell and vice-versa in the daily and weekly views
|
||||
- the events are now computed in the server code again, in order to speedup the drawing of events as well as to fix the bug where events would be shifted back or forth of one day, depending on how their start time would be compared to UTC time
|
||||
- implemented the handling of exceptional occurences of recurrent events
|
||||
|
||||
0.9.0-20080520 (1.0 rc6)
|
||||
------------------------
|
||||
|
|
|
@ -20,6 +20,9 @@ Appointments_OBJC_FILES = \
|
|||
SOGoCalendarComponent.m \
|
||||
SOGoAppointmentObject.m \
|
||||
SOGoTaskObject.m \
|
||||
SOGoComponentOccurence.m \
|
||||
SOGoAppointmentOccurence.m \
|
||||
SOGoTaskOccurence.m \
|
||||
SOGoAppointmentFolder.m \
|
||||
SOGoAppointmentFolders.m \
|
||||
SOGoFreeBusyObject.m \
|
||||
|
|
|
@ -618,6 +618,7 @@ static Class sogoAppointmentFolderKlass = Nil;
|
|||
cycleRange: (NGCalendarDateRange *) _r
|
||||
{
|
||||
NSMutableDictionary *md;
|
||||
NSNumber *dateSecs;
|
||||
id tmp;
|
||||
|
||||
md = [[_record mutableCopy] autorelease];
|
||||
|
@ -627,7 +628,9 @@ static Class sogoAppointmentFolderKlass = Nil;
|
|||
tmp = [_r startDate];
|
||||
[tmp setTimeZone: timeZone];
|
||||
[md setObject:tmp forKey:@"startDate"];
|
||||
[md setObject: [NSNumber numberWithInt: [tmp timeIntervalSince1970]] forKey: @"c_startdate"];
|
||||
dateSecs = [NSNumber numberWithInt: [tmp timeIntervalSince1970]];
|
||||
[md setObject: dateSecs forKey: @"c_startdate"];
|
||||
[md setObject: dateSecs forKey: @"c_recurrence_id"];
|
||||
tmp = [_r endDate];
|
||||
[tmp setTimeZone: timeZone];
|
||||
[md setObject:tmp forKey:@"endDate"];
|
||||
|
@ -682,11 +685,11 @@ static Class sogoAppointmentFolderKlass = Nil;
|
|||
{
|
||||
NSCalendarDate *startDate, *recurrenceId;
|
||||
NSMutableDictionary *newRecord;
|
||||
NSDictionary *oldRecord;
|
||||
NGCalendarDateRange *newRecordRange;
|
||||
int recordIndex;
|
||||
|
||||
newRecord = nil;
|
||||
|
||||
recurrenceId = [component recurrenceId];
|
||||
if ([dateRange containsDate: recurrenceId])
|
||||
{
|
||||
|
@ -698,6 +701,11 @@ static Class sogoAppointmentFolderKlass = Nil;
|
|||
if ([dateRange containsDate: startDate])
|
||||
{
|
||||
newRecord = [self fixupRecord: [component quickRecord]];
|
||||
[newRecord setObject: [NSNumber numberWithInt: 1]
|
||||
forKey: @"c_iscycle"];
|
||||
oldRecord = [ma objectAtIndex: recordIndex];
|
||||
[newRecord setObject: [oldRecord objectForKey: @"c_recurrence_id"]
|
||||
forKey: @"c_recurrence_id"];
|
||||
[ma replaceObjectAtIndex: recordIndex withObject: newRecord];
|
||||
}
|
||||
else
|
||||
|
@ -754,6 +762,7 @@ static Class sogoAppointmentFolderKlass = Nil;
|
|||
intoArray: (NSMutableArray *) _ma
|
||||
{
|
||||
NSMutableDictionary *row, *fixedRow;
|
||||
NSMutableArray *recordArray;
|
||||
NSDictionary *cycleinfo;
|
||||
NSCalendarDate *startDate, *endDate;
|
||||
NGCalendarDateRange *fir, *rRange;
|
||||
|
@ -761,6 +770,8 @@ static Class sogoAppointmentFolderKlass = Nil;
|
|||
unsigned i, count;
|
||||
NSString *content;
|
||||
|
||||
recordArray = [NSMutableArray array];
|
||||
|
||||
content = [_row objectForKey: @"c_cycleinfo"];
|
||||
if (![content isNotNull])
|
||||
{
|
||||
|
@ -800,12 +811,14 @@ static Class sogoAppointmentFolderKlass = Nil;
|
|||
rRange = [ranges objectAtIndex: i];
|
||||
fixedRow = [self fixupCycleRecord: row cycleRange: rRange];
|
||||
if (fixedRow)
|
||||
[_ma addObject:fixedRow];
|
||||
[recordArray addObject: fixedRow];
|
||||
}
|
||||
|
||||
[self _appendCycleExceptionsFromRow: row
|
||||
forRange: _r
|
||||
toArray: _ma];
|
||||
toArray: recordArray];
|
||||
|
||||
[_ma addObjectsFromArray: recordArray];
|
||||
}
|
||||
|
||||
- (NSArray *) fixupCyclicRecords: (NSArray *) _records
|
||||
|
|
|
@ -44,11 +44,12 @@
|
|||
#import <SoObjects/SOGo/SOGoWebDAVValue.h>
|
||||
#import <SoObjects/SOGo/WORequest+SOGo.h>
|
||||
|
||||
#import "NSArray+Appointments.h"
|
||||
#import "SOGoAppointmentFolder.h"
|
||||
#import "iCalEventChanges+SOGo.h"
|
||||
#import "iCalEntityObject+SOGo.h"
|
||||
#import "iCalPerson+SOGo.h"
|
||||
#import "NSArray+Appointments.h"
|
||||
#import "SOGoAppointmentFolder.h"
|
||||
#import "SOGoAppointmentOccurence.h"
|
||||
|
||||
#import "SOGoAppointmentObject.h"
|
||||
|
||||
|
@ -129,6 +130,35 @@
|
|||
return @"vevent";
|
||||
}
|
||||
|
||||
- (SOGoComponentOccurence *) occurence: (iCalRepeatableEntityObject *) occ
|
||||
{
|
||||
return [SOGoAppointmentOccurence occurenceWithComponent: occ
|
||||
withMasterComponent: [self component: NO
|
||||
secure: NO]
|
||||
inContainer: self];
|
||||
}
|
||||
|
||||
- (iCalRepeatableEntityObject *) newOccurenceWithID: (NSString *) recID
|
||||
{
|
||||
iCalEvent *newOccurence;
|
||||
NSCalendarDate *date;
|
||||
unsigned int interval;
|
||||
|
||||
newOccurence = (iCalEvent *) [super newOccurenceWithID: recID];
|
||||
date = [newOccurence recurrenceId];
|
||||
interval = [[newOccurence endDate]
|
||||
timeIntervalSinceDate: [newOccurence startDate]];
|
||||
[newOccurence setStartDate: date];
|
||||
[newOccurence setEndDate: [date addYear: 0
|
||||
month: 0
|
||||
day: 0
|
||||
hour: 0
|
||||
minute: 0
|
||||
second: interval]];
|
||||
|
||||
return newOccurence;
|
||||
}
|
||||
|
||||
- (SOGoAppointmentObject *) _lookupEvent: (NSString *) eventUID
|
||||
forUID: (NSString *) uid
|
||||
{
|
||||
|
@ -195,6 +225,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
#warning what about occurences?
|
||||
- (void) _handleRemovedUsers: (NSArray *) attendees
|
||||
{
|
||||
NSEnumerator *enumerator;
|
||||
|
@ -573,7 +604,7 @@
|
|||
return ex;
|
||||
}
|
||||
|
||||
- (void) prepareDelete
|
||||
- (void) prepareDeleteOccurence: (iCalEvent *) occurence
|
||||
{
|
||||
iCalEvent *event;
|
||||
SOGoUser *currentUser;
|
||||
|
@ -583,23 +614,32 @@
|
|||
{
|
||||
currentUser = [context activeUser];
|
||||
event = [self component: NO secure: NO];
|
||||
if (!occurence)
|
||||
occurence = event;
|
||||
if ([event userIsOrganizer: currentUser])
|
||||
{
|
||||
attendees = [event attendeesWithoutUser: currentUser];
|
||||
attendees = [occurence attendeesWithoutUser: currentUser];
|
||||
if (![attendees count] && event != occurence)
|
||||
attendees = [event attendeesWithoutUser: currentUser];
|
||||
if ([attendees count])
|
||||
{
|
||||
[self _handleRemovedUsers: attendees];
|
||||
[self sendEMailUsingTemplateNamed: @"Deletion"
|
||||
forOldObject: nil
|
||||
andNewObject: [event itipEntryWithMethod: @"cancel"]
|
||||
andNewObject: [occurence itipEntryWithMethod: @"cancel"]
|
||||
toAttendees: attendees];
|
||||
}
|
||||
}
|
||||
else if ([event userIsParticipant: currentUser])
|
||||
else if ([occurence userIsParticipant: currentUser])
|
||||
[self changeParticipationStatus: @"DECLINED"];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) prepareDelete
|
||||
{
|
||||
[self prepareDeleteOccurence: nil];
|
||||
}
|
||||
|
||||
/* message type */
|
||||
|
||||
- (NSString *) outlookMessageClass
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
/* SOGoAppointmentOccurence.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.
|
||||
*/
|
||||
|
||||
#ifndef SOGOAPPOINTMENTOCCURENCE_H
|
||||
#define SOGOAPPOINTMENTOCCURENCE_H
|
||||
|
||||
#import "SOGoComponentOccurence.h"
|
||||
|
||||
@interface SOGoAppointmentOccurence : SOGoComponentOccurence
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SOGOAPPOINTMENTOCCURENCE_H */
|
|
@ -0,0 +1,27 @@
|
|||
/* SOGoAppointmentOccurence.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 "SOGoAppointmentOccurence.h"
|
||||
|
||||
@implementation SOGoAppointmentOccurence
|
||||
|
||||
@end
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
#import <SOGo/SOGoContentObject.h>
|
||||
|
||||
#import "SOGoComponentOccurence.h"
|
||||
|
||||
@class NSArray;
|
||||
@class NSString;
|
||||
|
||||
|
@ -33,8 +35,14 @@
|
|||
@class iCalRepeatableEntityObject;
|
||||
|
||||
@class SOGoUser;
|
||||
@class SOGoComponentOccurence;
|
||||
|
||||
@interface SOGoCalendarComponent : SOGoContentObject
|
||||
@interface SOGoCalendarComponent : SOGoContentObject <SOGoComponentOccurence>
|
||||
{
|
||||
iCalCalendar *fullCalendar;
|
||||
iCalCalendar *safeCalendar;
|
||||
iCalCalendar *originalCalendar;
|
||||
}
|
||||
|
||||
- (NSString *) componentTag;
|
||||
|
||||
|
@ -66,6 +74,11 @@
|
|||
- (iCalPerson *) iCalPersonWithUID: (NSString *) uid;
|
||||
- (NSArray *) getUIDsForICalPersons: (NSArray *) iCalPersons;
|
||||
|
||||
/* recurrences */
|
||||
- (SOGoComponentOccurence *)
|
||||
occurence: (iCalRepeatableEntityObject *) component;
|
||||
- (iCalRepeatableEntityObject *) newOccurenceWithID: (NSString *) recID;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SOGOCALENDARCOMPONENT_H */
|
||||
|
|
|
@ -53,7 +53,9 @@
|
|||
#import "SOGoAptMailNotification.h"
|
||||
#import "iCalEntityObject+SOGo.h"
|
||||
#import "iCalPerson+SOGo.h"
|
||||
#import "iCalRepeatableEntityObject+SOGo.h"
|
||||
#import "SOGoCalendarComponent.h"
|
||||
#import "SOGoComponentOccurence.h"
|
||||
|
||||
static BOOL sendEMailNotifications = NO;
|
||||
|
||||
|
@ -74,6 +76,26 @@ static BOOL sendEMailNotifications = NO;
|
|||
}
|
||||
}
|
||||
|
||||
- (id) init
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
fullCalendar = nil;
|
||||
safeCalendar = nil;
|
||||
originalCalendar = nil;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[fullCalendar release];
|
||||
[safeCalendar release];
|
||||
[originalCalendar release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (NSString *) davContentType
|
||||
{
|
||||
return @"text/calendar";
|
||||
|
@ -146,6 +168,150 @@ static BOOL sendEMailNotifications = NO;
|
|||
return iCalString;
|
||||
}
|
||||
|
||||
static inline BOOL
|
||||
_occurenceHasID (iCalRepeatableEntityObject *occurence, NSString *recID)
|
||||
{
|
||||
unsigned int seconds, recSeconds;
|
||||
|
||||
seconds = [recID intValue];
|
||||
recSeconds = [[occurence recurrenceId] timeIntervalSince1970];
|
||||
|
||||
return (seconds == recSeconds);
|
||||
}
|
||||
|
||||
- (iCalRepeatableEntityObject *) lookupOccurence: (NSString *) recID
|
||||
{
|
||||
iCalRepeatableEntityObject *component, *occurence, *currentOccurence;
|
||||
NSArray *occurences;
|
||||
unsigned int count, max;
|
||||
|
||||
occurence = nil;
|
||||
|
||||
component = [self component: NO secure: NO];
|
||||
if ([component hasRecurrenceRules])
|
||||
{
|
||||
occurences = [[self calendar: NO secure: NO] allObjects];
|
||||
max = [occurences count];
|
||||
count = 1;
|
||||
while (!occurence && count < max)
|
||||
{
|
||||
currentOccurence = [occurences objectAtIndex: count];
|
||||
if (_occurenceHasID (currentOccurence, recID))
|
||||
occurence = currentOccurence;
|
||||
else
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return occurence;
|
||||
}
|
||||
|
||||
- (SOGoComponentOccurence *) occurence: (iCalRepeatableEntityObject *) component
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (iCalRepeatableEntityObject *) newOccurenceWithID: (NSString *) recID
|
||||
{
|
||||
iCalRepeatableEntityObject *masterOccurence, *newOccurence;
|
||||
iCalCalendar *calendar;
|
||||
NSCalendarDate *recDate;
|
||||
|
||||
recDate = [NSCalendarDate dateWithTimeIntervalSince1970: [recID intValue]];
|
||||
masterOccurence = [self component: NO secure: NO];
|
||||
if ([masterOccurence doesOccurOnDate: recDate])
|
||||
{
|
||||
newOccurence = [masterOccurence mutableCopy];
|
||||
[newOccurence autorelease];
|
||||
[newOccurence removeAllRecurrenceRules];
|
||||
[newOccurence removeAllExceptionRules];
|
||||
[newOccurence removeAllExceptionDates];
|
||||
[newOccurence setOrganizer: nil];
|
||||
[newOccurence setRecurrenceId: recDate];
|
||||
|
||||
calendar = [newOccurence parent];
|
||||
[calendar addChild: newOccurence];
|
||||
}
|
||||
else
|
||||
newOccurence = nil;
|
||||
|
||||
return newOccurence;
|
||||
}
|
||||
|
||||
- (BOOL) isFolderish
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (id) toManyRelationshipKeys
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (id) toOneRelationshipKeys
|
||||
{
|
||||
NSMutableArray *keys;
|
||||
NSArray *occurences;
|
||||
NSCalendarDate *recID;
|
||||
unsigned int count, max, seconds;
|
||||
|
||||
keys = [NSMutableArray array];
|
||||
[keys addObject: @"master"];
|
||||
occurences = [[self calendar: NO secure: NO] allObjects];
|
||||
max = [occurences count];
|
||||
for (count = 1; count < max; count++)
|
||||
{
|
||||
recID = [[occurences objectAtIndex: count] recurrenceId];
|
||||
if (recID)
|
||||
{
|
||||
seconds = [recID timeIntervalSince1970];
|
||||
[keys addObject: [NSString stringWithFormat: @"occurence%d",
|
||||
seconds]];
|
||||
}
|
||||
}
|
||||
|
||||
return keys;
|
||||
}
|
||||
|
||||
- (id) lookupName: (NSString *) lookupName
|
||||
inContext: (id) localContext
|
||||
acquire: (BOOL) acquire
|
||||
{
|
||||
id obj;
|
||||
iCalRepeatableEntityObject *occurence;
|
||||
NSString *recID;
|
||||
BOOL isNewOccurence;
|
||||
|
||||
obj = [super lookupName: lookupName
|
||||
inContext: localContext
|
||||
acquire: acquire];
|
||||
if (!obj)
|
||||
{
|
||||
if ([lookupName isEqualToString: @"master"])
|
||||
obj = [self occurence: [self component: NO secure: NO]];
|
||||
else if ([lookupName hasPrefix: @"occurence"])
|
||||
{
|
||||
recID = [lookupName substringFromIndex: 9];
|
||||
occurence = [self lookupOccurence: recID];
|
||||
if (!occurence)
|
||||
{
|
||||
occurence = [self newOccurenceWithID: recID];
|
||||
isNewOccurence = YES;
|
||||
}
|
||||
if (occurence)
|
||||
{
|
||||
obj = [self occurence: occurence];
|
||||
if (isNewOccurence)
|
||||
[obj setIsNew: isNewOccurence];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
- (NSString *) contentAsString
|
||||
{
|
||||
NSString *secureContent;
|
||||
|
@ -166,34 +332,45 @@ static BOOL sendEMailNotifications = NO;
|
|||
- (iCalCalendar *) calendar: (BOOL) create secure: (BOOL) secure
|
||||
{
|
||||
NSString *componentTag;
|
||||
CardGroup *newComponent;
|
||||
iCalCalendar *calendar;
|
||||
iCalRepeatableEntityObject *newComponent;
|
||||
iCalCalendar **calendar;
|
||||
NSString *iCalString;
|
||||
|
||||
if (secure)
|
||||
iCalString = [self secureContentAsString];
|
||||
calendar = &safeCalendar;
|
||||
else
|
||||
iCalString = content;
|
||||
calendar = &fullCalendar;
|
||||
|
||||
if ([iCalString length] > 0)
|
||||
calendar = [iCalCalendar parseSingleFromSource: iCalString];
|
||||
else
|
||||
if (!*calendar)
|
||||
{
|
||||
if (create)
|
||||
if (secure)
|
||||
iCalString = [self secureContentAsString];
|
||||
else
|
||||
iCalString = content;
|
||||
|
||||
if ([iCalString length] > 0)
|
||||
{
|
||||
calendar = [iCalCalendar groupWithTag: @"vcalendar"];
|
||||
[calendar setVersion: @"2.0"];
|
||||
[calendar setProdID: @"-//Inverse groupe conseil//SOGo 0.9//EN"];
|
||||
componentTag = [[self componentTag] uppercaseString];
|
||||
newComponent = [[calendar classForTag: componentTag]
|
||||
groupWithTag: componentTag];
|
||||
[calendar addChild: newComponent];
|
||||
ASSIGN (*calendar, [iCalCalendar parseSingleFromSource: iCalString]);
|
||||
if (!secure)
|
||||
originalCalendar = [*calendar copy];
|
||||
}
|
||||
else
|
||||
calendar = nil;
|
||||
{
|
||||
if (create)
|
||||
{
|
||||
ASSIGN (*calendar, [iCalCalendar groupWithTag: @"vcalendar"]);
|
||||
[*calendar setVersion: @"2.0"];
|
||||
[*calendar setProdID: @"-//Inverse groupe conseil//SOGo 0.9//EN"];
|
||||
componentTag = [[self componentTag] uppercaseString];
|
||||
newComponent = [[*calendar classForTag: componentTag]
|
||||
groupWithTag: componentTag];
|
||||
[newComponent setUid: [self globallyUniqueObjectId]];
|
||||
[*calendar addChild: newComponent];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return calendar;
|
||||
return *calendar;
|
||||
}
|
||||
|
||||
- (id) component: (BOOL) create secure: (BOOL) secure
|
||||
|
@ -202,10 +379,36 @@ static BOOL sendEMailNotifications = NO;
|
|||
firstChildWithTag: [self componentTag]];
|
||||
}
|
||||
|
||||
- (void) _updateRecurrenceIDs
|
||||
{
|
||||
iCalRepeatableEntityObject *master, *oldMaster, *currentComponent;
|
||||
int deltaSecs;
|
||||
NSArray *components;
|
||||
unsigned int count, max;
|
||||
NSCalendarDate *recID;
|
||||
|
||||
master = [self component: NO secure: NO];
|
||||
oldMaster = (iCalRepeatableEntityObject *)
|
||||
[originalCalendar firstChildWithTag: [self componentTag]];
|
||||
deltaSecs = [[master startDate]
|
||||
timeIntervalSinceDate: [oldMaster startDate]];
|
||||
components = [fullCalendar allObjects];
|
||||
max = [components count];
|
||||
for (count = 1; count < max; count++)
|
||||
{
|
||||
currentComponent = [components objectAtIndex: count];
|
||||
recID = [[currentComponent recurrenceId] addTimeInterval: deltaSecs];
|
||||
[currentComponent setRecurrenceId: recID];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) saveComponent: (iCalRepeatableEntityObject *) newObject
|
||||
{
|
||||
NSString *newiCalString;
|
||||
|
||||
if (!isNew
|
||||
&& [newObject isRecurrent])
|
||||
[self _updateRecurrenceIDs];
|
||||
newiCalString = [[newObject parent] versitString];
|
||||
|
||||
[self saveContentString: newiCalString];
|
||||
|
@ -633,4 +836,11 @@ static BOOL sendEMailNotifications = NO;
|
|||
return roles;
|
||||
}
|
||||
|
||||
/* SOGoComponentOccurence protocol */
|
||||
|
||||
- (iCalRepeatableEntityObject *) occurence
|
||||
{
|
||||
return [self component: YES secure: NO];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/* SOGoComponentOccurence.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.
|
||||
*/
|
||||
|
||||
#ifndef SOGOCOMPONENTOCCURENCE_H
|
||||
#define SOGOCOMPONENTOCCURENCE_H
|
||||
|
||||
#import <SOGo/SOGoObject.h>
|
||||
|
||||
@class iCalRepeatableEntityObject;
|
||||
@class SOGoCalendarComponent;
|
||||
|
||||
@protocol SOGoComponentOccurence
|
||||
|
||||
- (iCalRepeatableEntityObject *) occurence;
|
||||
- (BOOL) isNew;
|
||||
- (id) delete;
|
||||
|
||||
@end
|
||||
|
||||
@interface SOGoComponentOccurence : SOGoObject <SOGoComponentOccurence>
|
||||
{
|
||||
iCalRepeatableEntityObject *component;
|
||||
iCalRepeatableEntityObject *master;
|
||||
BOOL isNew;
|
||||
}
|
||||
|
||||
+ (id) occurenceWithComponent: (iCalRepeatableEntityObject *) newComponent
|
||||
withMasterComponent: (iCalRepeatableEntityObject *) newMaster
|
||||
inContainer: (SOGoCalendarComponent *) newContainer;
|
||||
|
||||
- (void) setComponent: (iCalRepeatableEntityObject *) newComponent;
|
||||
- (void) setMasterComponent: (iCalRepeatableEntityObject *) newMaster;
|
||||
- (void) setIsNew: (BOOL) newIsNew;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SOGOCOMPONENTOCCURENCE_H */
|
|
@ -0,0 +1,163 @@
|
|||
/* SOGoComponentOccurence.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/NSArray.h>
|
||||
#import <Foundation/NSString.h>
|
||||
|
||||
#import <NGCards/iCalCalendar.h>
|
||||
#import <NGCards/iCalRepeatableEntityObject.h>
|
||||
|
||||
#import "SOGoComponentOccurence.h"
|
||||
|
||||
#import "SOGoCalendarComponent.h"
|
||||
@interface SOGoCalendarComponent (OccurenceExtensions)
|
||||
|
||||
- (void) prepareDeleteOccurence: (iCalRepeatableEntityObject *) component;
|
||||
|
||||
@end
|
||||
|
||||
@implementation SOGoComponentOccurence
|
||||
|
||||
+ (id) occurenceWithComponent: (iCalRepeatableEntityObject *) newComponent
|
||||
withMasterComponent: (iCalRepeatableEntityObject *) newMaster
|
||||
inContainer: (SOGoCalendarComponent *) newContainer
|
||||
{
|
||||
SOGoComponentOccurence *occurence;
|
||||
unsigned int seconds;
|
||||
NSString *newName;
|
||||
|
||||
if (newComponent == newMaster)
|
||||
newName = @"master";
|
||||
else
|
||||
{
|
||||
seconds = [[newComponent recurrenceId] timeIntervalSince1970];
|
||||
newName = [NSString stringWithFormat: @"occurence%d", seconds];
|
||||
};
|
||||
occurence = [self objectWithName: newName inContainer: newContainer];
|
||||
[occurence setComponent: newComponent];
|
||||
[occurence setMasterComponent: newMaster];
|
||||
|
||||
return occurence;
|
||||
}
|
||||
|
||||
- (id) init
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
component = nil;
|
||||
master = nil;
|
||||
isNew = NO;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) setIsNew: (BOOL) newIsNew
|
||||
{
|
||||
isNew = newIsNew;
|
||||
}
|
||||
|
||||
- (BOOL) isNew
|
||||
{
|
||||
return isNew;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[component release];
|
||||
[master release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
/* SOGoObject overrides */
|
||||
|
||||
- (BOOL) isFolderish
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (NSString *) contentAsString
|
||||
{
|
||||
return [component versitString];
|
||||
}
|
||||
|
||||
- (NSString *) davContentLength
|
||||
{
|
||||
unsigned int length;
|
||||
|
||||
length = [[self contentAsString]
|
||||
lengthOfBytesUsingEncoding: NSUTF8StringEncoding];
|
||||
|
||||
return [NSString stringWithFormat: @"%u", length];
|
||||
}
|
||||
|
||||
/* /SOGoObject overrides */
|
||||
|
||||
- (void) setComponent: (iCalRepeatableEntityObject *) newComponent
|
||||
{
|
||||
ASSIGN (component, newComponent);
|
||||
}
|
||||
|
||||
- (void) setMasterComponent: (iCalRepeatableEntityObject *) newMaster
|
||||
{
|
||||
ASSIGN (master, newMaster);
|
||||
}
|
||||
|
||||
- (NSArray *) aclsForUser: (NSString *) uid
|
||||
{
|
||||
return [container aclsForUser: uid];
|
||||
}
|
||||
|
||||
/* SOGoComponentOccurence protocol */
|
||||
|
||||
- (iCalRepeatableEntityObject *) occurence
|
||||
{
|
||||
return component;
|
||||
}
|
||||
|
||||
- (id) delete
|
||||
{
|
||||
NSException *error;
|
||||
iCalCalendar *parent;
|
||||
|
||||
if (component == master)
|
||||
error = [container delete];
|
||||
else
|
||||
{
|
||||
if ([container respondsToSelector: @selector (prepareDeleteOccurence:)])
|
||||
[container prepareDeleteOccurence: component];
|
||||
[master addToExceptionDates: [component startDate]];
|
||||
parent = [component parent];
|
||||
[[parent children] removeObject: component];
|
||||
[container saveComponent: master];
|
||||
error = nil;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
- (void) saveComponent: (id) newEvent
|
||||
{
|
||||
[container saveComponent: newEvent];
|
||||
}
|
||||
|
||||
@end
|
|
@ -35,6 +35,7 @@
|
|||
#import "NSArray+Appointments.h"
|
||||
#import "SOGoAptMailNotification.h"
|
||||
#import "SOGoAppointmentFolder.h"
|
||||
#import "SOGoTaskOccurence.h"
|
||||
|
||||
#import "SOGoTaskObject.h"
|
||||
|
||||
|
@ -45,6 +46,14 @@
|
|||
return @"vtodo";
|
||||
}
|
||||
|
||||
- (SOGoComponentOccurence *) occurence: (iCalRepeatableEntityObject *) occ
|
||||
{
|
||||
return [SOGoTaskOccurence occurenceWithComponent: occ
|
||||
withMasterComponent: [self component: NO
|
||||
secure: NO]
|
||||
inContainer: self];
|
||||
}
|
||||
|
||||
/* message type */
|
||||
|
||||
- (NSString *) outlookMessageClass
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
/* SOGoTaskOccurence.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.
|
||||
*/
|
||||
|
||||
#ifndef SOGOTASKOCCURENCE_H
|
||||
#define SOGOTASKOCCURENCE_H
|
||||
|
||||
#import "SOGoComponentOccurence.h"
|
||||
|
||||
@interface SOGoTaskOccurence : SOGoComponentOccurence
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SOGOTASKOCCURENCE_H */
|
|
@ -0,0 +1,27 @@
|
|||
/* SOGoTaskOccurence.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 "SOGoTaskOccurence.h"
|
||||
|
||||
@implementation SOGoTaskOccurence
|
||||
|
||||
@end
|
|
@ -25,6 +25,7 @@
|
|||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSValue.h>
|
||||
|
||||
#import <NGExtensions/NGCalendarDateRange.h>
|
||||
#import <NGExtensions/NSNull+misc.h>
|
||||
#import <NGExtensions/NSObject+Logs.h>
|
||||
|
||||
|
@ -192,4 +193,15 @@
|
|||
return row;
|
||||
}
|
||||
|
||||
- (NGCalendarDateRange *) firstOccurenceRange
|
||||
{
|
||||
return [NGCalendarDateRange calendarDateRangeWithStartDate: [self startDate]
|
||||
endDate: [self endDate]];
|
||||
}
|
||||
|
||||
- (unsigned int) occurenceInterval
|
||||
{
|
||||
return [[self endDate] timeIntervalSinceDate: [self startDate]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -29,5 +29,6 @@
|
|||
@interface iCalRepeatableEntityObject (SOGoExtensions)
|
||||
|
||||
- (NSString *) cycleInfo;
|
||||
- (BOOL) doesOccurOnDate: (NSCalendarDate *) occurenceDate;
|
||||
|
||||
@end
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
#import <Foundation/NSString.h>
|
||||
|
||||
#import <NGCards/iCalRecurrenceRule.h>
|
||||
#import <NGCards/iCalRecurrenceCalculator.h>
|
||||
#import <NGExtensions/NGCalendarDateRange.h>
|
||||
|
||||
#import "iCalRepeatableEntityObject+SOGo.h"
|
||||
|
||||
|
@ -86,4 +88,42 @@
|
|||
return value;
|
||||
}
|
||||
|
||||
- (NGCalendarDateRange *) firstOccurenceRange
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (unsigned int) occurenceInterval
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (BOOL) doesOccurOnDate: (NSCalendarDate *) occurenceDate
|
||||
{
|
||||
NSArray *ranges;
|
||||
NGCalendarDateRange *checkRange;
|
||||
NSCalendarDate *endDate;
|
||||
BOOL doesOccur;
|
||||
|
||||
doesOccur = [self isRecurrent];
|
||||
if (doesOccur)
|
||||
{
|
||||
endDate = [occurenceDate addTimeInterval: [self occurenceInterval]];
|
||||
checkRange = [NGCalendarDateRange calendarDateRangeWithStartDate: occurenceDate
|
||||
endDate: endDate];
|
||||
ranges = [iCalRecurrenceCalculator recurrenceRangesWithinCalendarDateRange: checkRange
|
||||
firstInstanceCalendarDateRange: [self firstOccurenceRange]
|
||||
recurrenceRules: [self recurrenceRules]
|
||||
exceptionRules: [self exceptionRules]
|
||||
exceptionDates: [self exceptionDates]];
|
||||
doesOccur = [ranges dateRangeArrayContainsDate: occurenceDate];
|
||||
}
|
||||
|
||||
return doesOccur;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSValue.h>
|
||||
|
||||
#import <NGExtensions/NGCalendarDateRange.h>
|
||||
#import <NGExtensions/NSNull+misc.h>
|
||||
#import <NGExtensions/NSObject+Logs.h>
|
||||
|
||||
|
@ -169,4 +170,15 @@
|
|||
return row;
|
||||
}
|
||||
|
||||
- (NGCalendarDateRange *) firstOccurenceRange
|
||||
{
|
||||
return [NGCalendarDateRange calendarDateRangeWithStartDate: [self startDate]
|
||||
endDate: [self due]];
|
||||
}
|
||||
|
||||
- (unsigned int) occurenceInterval
|
||||
{
|
||||
return [[self due] timeIntervalSinceDate: [self startDate]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -52,6 +52,26 @@
|
|||
SOGoTaskObject = {
|
||||
superclass = "SOGoCalendarComponent";
|
||||
};
|
||||
SOGoComponentOccurence = {
|
||||
superclass = "SOGoObject";
|
||||
protectedBy = "Access Object";
|
||||
defaultRoles = {
|
||||
"ViewAllComponent" = ( "Owner", "Organizer", "Participant", "ComponentModifier", "ComponentResponder", "ComponentViewer" );
|
||||
"ViewDAndT" = ( "Organizer", "Participant", "ComponentDAndTViewer" );
|
||||
"ModifyComponent" = ( "Owner", "Organizer", "ComponentModifier" );
|
||||
"RespondToComponent" = ( "Participant", "ComponentModifier", "ComponentResponder" );
|
||||
"Access Object" = ( "Owner", "Organizer", "Participant", "ComponentModifier", "ComponentResponder", "ComponentViewer", "ComponentDAndTViewer" );
|
||||
"Change Images and Files" = ( "Owner", "Organizer", "ComponentModifier" );
|
||||
"Access Contents Information" = ( "Owner", "Organizer", "Participant", "ComponentModifier", "ComponentResponder", "ComponentViewer", "ComponentDAndTViewer" );
|
||||
"WebDAV Access" = ( "Owner", "Organizer", "Participant", "ComponentModifier", "ComponentResponder", "ComponentViewer", "ComponentDAndTViewer" );
|
||||
};
|
||||
};
|
||||
SOGoAppointmentOccurence = {
|
||||
superclass = "SOGoComponentOccurence";
|
||||
};
|
||||
SOGoTaskOccurence = {
|
||||
superclass = "SOGoComponentOccurence";
|
||||
};
|
||||
SOGoFreeBusyObject = {
|
||||
superclass = "SOGoContentObject";
|
||||
protectedBy = "Access Contents Information";
|
||||
|
|
|
@ -692,8 +692,7 @@ NSString *SOGoWeekStartFirstFullWeek = @"FirstFullWeek";
|
|||
NSArray *sogoRoles;
|
||||
NSString *rqMethod;
|
||||
|
||||
rolesForObject = [NSMutableArray new];
|
||||
[rolesForObject autorelease];
|
||||
rolesForObject = [NSMutableArray array];
|
||||
|
||||
sogoRoles = [super rolesForObject: object inContext: context];
|
||||
if (sogoRoles)
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
#import <SoObjects/SOGo/SOGoObject.h>
|
||||
#import <SoObjects/SOGo/SOGoPermissions.h>
|
||||
|
||||
#import "WODirectAction+SOGo.h"
|
||||
|
||||
#import "UIxObjectActions.h"
|
||||
|
||||
@implementation UIxObjectActions
|
||||
|
@ -71,4 +73,15 @@
|
|||
return response;
|
||||
}
|
||||
|
||||
- (WOResponse *) deleteAction
|
||||
{
|
||||
WOResponse *response;
|
||||
|
||||
response = (WOResponse *) [[self clientObject] delete];
|
||||
if (!response)
|
||||
response = [self responseWithStatus: 204];
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -40,6 +40,11 @@
|
|||
actionClass = "UIxObjectActions";
|
||||
actionName = "removeUserFromAcls";
|
||||
};
|
||||
delete = {
|
||||
protectedBy = "Delete Objects";
|
||||
actionClass = "UIxObjectActions";
|
||||
actionName = "delete";
|
||||
};
|
||||
acls = {
|
||||
protectedBy = "ReadAcls";
|
||||
pageName = "UIxAclEditor";
|
||||
|
|
|
@ -34,8 +34,6 @@
|
|||
CardElement *workAdr;
|
||||
}
|
||||
|
||||
- (BOOL)isDeletableClientObject;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* UIXCONTACTVIEW_H */
|
||||
|
|
|
@ -516,32 +516,4 @@
|
|||
return self;
|
||||
}
|
||||
|
||||
- (BOOL) isDeletableClientObject
|
||||
{
|
||||
return [[self clientObject] respondsToSelector: @selector(delete)];
|
||||
}
|
||||
|
||||
- (id) deleteAction
|
||||
{
|
||||
NSException *ex;
|
||||
|
||||
if (![self isDeletableClientObject])
|
||||
/* return 400 == Bad Request */
|
||||
return [NSException exceptionWithHTTPStatus: 400
|
||||
reason:@"method cannot be invoked on "
|
||||
@"the specified object"];
|
||||
|
||||
ex = [[self clientObject] delete];
|
||||
if (ex)
|
||||
{
|
||||
// TODO: improve error handling
|
||||
[self debugWithFormat: @"failed to delete: %@", ex];
|
||||
|
||||
return ex;
|
||||
}
|
||||
|
||||
return [self responseWithStatus: 200
|
||||
andString: [[self clientObject] nameInContainer]];
|
||||
}
|
||||
|
||||
@end /* UIxContactView */
|
||||
|
|
|
@ -41,35 +41,26 @@
|
|||
id currentAddress;
|
||||
}
|
||||
|
||||
- (BOOL)isDeletableClientObject;
|
||||
|
||||
@end
|
||||
|
||||
@implementation UIxMailView
|
||||
|
||||
static NSString *mailETag = nil;
|
||||
|
||||
+ (int)version {
|
||||
return [super version] + 0 /* v2 */;
|
||||
}
|
||||
|
||||
+ (void)initialize {
|
||||
+ (void) initialize
|
||||
{
|
||||
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
|
||||
|
||||
NSAssert2([super version] == 2,
|
||||
@"invalid superclass (%@) version %i !",
|
||||
NSStringFromClass([self superclass]), [super version]);
|
||||
|
||||
if ([ud boolForKey:@"SOGoDontUseETagsForMailViewer"]) {
|
||||
if ([ud boolForKey:@"SOGoDontUseETagsForMailViewer"])
|
||||
NSLog(@"Note: usage of constant etag for mailer viewer is disabled.");
|
||||
}
|
||||
else {
|
||||
mailETag = [[NSString alloc] initWithFormat:@"\"imap4url_%d_%d_%03d\"",
|
||||
UIX_MAILER_MAJOR_VERSION,
|
||||
UIX_MAILER_MINOR_VERSION,
|
||||
UIX_MAILER_SUBMINOR_VERSION];
|
||||
NSLog(@"Note: using constant etag for mail viewer: '%@'", mailETag);
|
||||
}
|
||||
else
|
||||
{
|
||||
mailETag = [[NSString alloc] initWithFormat:@"\"imap4url_%d_%d_%03d\"",
|
||||
UIX_MAILER_MAJOR_VERSION,
|
||||
UIX_MAILER_MINOR_VERSION,
|
||||
UIX_MAILER_SUBMINOR_VERSION];
|
||||
NSLog(@"Note: using constant etag for mail viewer: '%@'", mailETag);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
|
@ -193,11 +184,6 @@ static NSString *mailETag = nil;
|
|||
return self;
|
||||
}
|
||||
|
||||
- (BOOL) isDeletableClientObject
|
||||
{
|
||||
return [[self clientObject] respondsToSelector: @selector (delete)];
|
||||
}
|
||||
|
||||
- (BOOL) isInlineViewer
|
||||
{
|
||||
return NO;
|
||||
|
|
|
@ -33,7 +33,8 @@
|
|||
};
|
||||
SOGoContentObject = {
|
||||
superclass = "SOGoObject";
|
||||
defaultAccess = "Access Contents Information";
|
||||
defaultAccess = "allow";
|
||||
/* defaultAccess = "Access Contents Information"; */
|
||||
protectedBy = "Access Object";
|
||||
defaultRoles = {
|
||||
"Access Contents Information" = ( "Owner", "ObjectViewer", "ObjectEditor" );
|
||||
|
|
|
@ -107,7 +107,7 @@
|
|||
- (WOResponse *) redirectToLocation: (NSString *) newLocation;
|
||||
|
||||
/* Debugging */
|
||||
- (BOOL)isUIxDebugEnabled;
|
||||
- (BOOL) isUIxDebugEnabled;
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -456,6 +456,10 @@ vtodo_class2 = "(Vertrouwelijke taak)";
|
|||
|
||||
"Please select an event or a task." = "Selecteer een afspraak of een taak.";
|
||||
|
||||
"editRepeatingItem" = "Het item dat u bewerkt is een herhalend item. Wilt u alle items of enkel dit item bewerken?";
|
||||
"button_thisOccurrenceOnly" = "Enkel dit item";
|
||||
"button_allOccurrences" = "Alle herhalingen";
|
||||
|
||||
/* Properties dialog */
|
||||
"Name:" = "Naam:";
|
||||
"Color:" = "Kleur:";
|
||||
|
|
|
@ -473,6 +473,10 @@ vtodo_class2 = "(Confidential task)";
|
|||
|
||||
"Please select an event or a task." = "Please select an event or a task.";
|
||||
|
||||
"editRepeatingItem" = "The item you are editing is a repeating item. Do you want to edit all occurences of it or only this single instance?";
|
||||
"button_thisOccurrenceOnly" = "This occurence only";
|
||||
"button_allOccurrences" = "All occurences";
|
||||
|
||||
/* Properties dialog */
|
||||
"Name:" = "Name:";
|
||||
"Color:" = "Color:";
|
||||
|
|
|
@ -470,6 +470,10 @@ vtodo_class2 = "(Tâche confidentielle)";
|
|||
|
||||
"Please select an event or a task." = "Veuillez sélectionner un événement ou une tâche.";
|
||||
|
||||
"editRepeatingItem" = "L'élément que vous éditez est récurrent. Voulez-vous modifier toutes ses occurrences ou seulement celle-ci ?";
|
||||
"button_thisOccurrenceOnly" = "Cette occurence seulement";
|
||||
"button_allOccurrences" = "Toutes les occurences";
|
||||
|
||||
/* Properties dialog */
|
||||
"Name:" = "Nom :";
|
||||
"Color:" = "Couleur :";
|
||||
|
|
|
@ -43,7 +43,8 @@ SchedulerUI_OBJC_FILES = \
|
|||
UIxCalParticipationStatusView.m \
|
||||
UIxCalMonthOverview.m \
|
||||
UIxCalMonthViewOld.m \
|
||||
UIxRecurrenceEditor.m
|
||||
UIxRecurrenceEditor.m \
|
||||
UIxOccurenceDialog.m
|
||||
# UIxAppointmentProposal.m
|
||||
# UIxTaskProposal.m
|
||||
|
||||
|
|
|
@ -457,6 +457,10 @@ vtodo_class2 = "(Confidential task)";
|
|||
|
||||
"Please select an event or a task." = "Bitte wählen Sie einen Termin oder eine Aufgabe aus!";
|
||||
|
||||
"editRepeatingItem" = "Der Eintrag, den Sie bearbeiten, ist ein wiederkehrender Eintrag. Wollen Sie alle seine Ereignisse bearbeiten oder nur diese einzelne Instanz?";
|
||||
"button_thisOccurrenceOnly" = "Nur dieses Ereignis";
|
||||
"button_allOccurrences" = "Alle Ereignisse";
|
||||
|
||||
/* Properties dialog */
|
||||
"Name:" = "Name:";
|
||||
"Color:" = "Farbe:";
|
||||
|
|
|
@ -471,6 +471,10 @@ vtodo_class2 = "(Attività confidenziale)";
|
|||
"From" = "Da";
|
||||
"To" = "A";
|
||||
|
||||
"editRepeatingItem" = "L'elemento che si sta modificando è un elemento ripetuto. Si vogliono modificare tutte le sue occorrenze o solo questa?";
|
||||
"button_thisOccurrenceOnly" = "Solamente questa occorrenza";
|
||||
"button_allOccurrences" = "Tutte le occorrenze";
|
||||
|
||||
/* Properties dialog */
|
||||
"Name:" = "Nome:";
|
||||
"Color:" = "Colore:";
|
||||
|
|
|
@ -477,6 +477,10 @@ vtodo_class2 = "(Tarea confidencial)";
|
|||
"Please select an event or a task."
|
||||
= "Seleccione un evento o tarea, por favor";
|
||||
|
||||
"editRepeatingItem" = "El elemento que está editando es un elemento repetitivo. ¿Quiere editar todas sus ocurrencias o sólo la que ha señalado?";
|
||||
"button_thisOccurrenceOnly" = "Sólo esta ocurrencia";
|
||||
"button_allOccurrences" = "Todas las ocurrencias";
|
||||
|
||||
/* Properties dialog */
|
||||
"Name:" = "Nombre:";
|
||||
"Color:" = "Color:";
|
||||
|
|
|
@ -38,6 +38,8 @@
|
|||
#import <SoObjects/Appointments/SOGoAppointmentFolder.h>
|
||||
#import <SoObjects/Appointments/SOGoAppointmentObject.h>
|
||||
|
||||
#import <SoObjects/Appointments/SOGoComponentOccurence.h>
|
||||
|
||||
#import "UIxComponentEditor.h"
|
||||
#import "UIxAppointmentEditor.h"
|
||||
|
||||
|
@ -71,7 +73,7 @@
|
|||
{
|
||||
if (!event)
|
||||
{
|
||||
event = (iCalEvent *) [[self clientObject] component: YES secure: YES];
|
||||
event = (iCalEvent *) [[self clientObject] occurence];
|
||||
[event retain];
|
||||
}
|
||||
|
||||
|
@ -165,9 +167,12 @@
|
|||
NSCalendarDate *startDate, *endDate;
|
||||
NSString *duration;
|
||||
unsigned int minutes;
|
||||
SOGoObject <SOGoComponentOccurence> *co;
|
||||
|
||||
[self event];
|
||||
if ([[self clientObject] isNew])
|
||||
co = [self clientObject];
|
||||
if ([co isNew]
|
||||
&& [co isKindOfClass: [SOGoCalendarComponent class]])
|
||||
{
|
||||
startDate = [self newStartDate];
|
||||
duration = [self queryParameterForKey:@"dur"];
|
||||
|
@ -231,7 +236,7 @@
|
|||
|
||||
actionName = [[request requestHandlerPath] lastPathComponent];
|
||||
|
||||
return ([[self clientObject] isKindOfClass: [SOGoAppointmentObject class]]
|
||||
return ([[self clientObject] conformsToProtocol: @protocol (SOGoComponentOccurence)]
|
||||
&& [actionName hasPrefix: @"save"]);
|
||||
}
|
||||
|
||||
|
|
|
@ -65,7 +65,8 @@ static NSArray *tasksFields = nil;
|
|||
@"c_status", @"c_title", @"c_startdate",
|
||||
@"c_enddate", @"c_location", @"c_isallday",
|
||||
@"c_classification", @"c_partmails",
|
||||
@"c_partstates", @"c_owner", @"c_iscycle", nil];
|
||||
@"c_partstates", @"c_owner", @"c_iscycle",
|
||||
@"c_recurrence_id", nil];
|
||||
[eventsFields retain];
|
||||
}
|
||||
if (!tasksFields)
|
||||
|
@ -404,7 +405,7 @@ _feedBlockWithMonthBasedData(NSMutableDictionary *block, unsigned int start,
|
|||
end: (unsigned int) end
|
||||
cname: (NSString *) cName
|
||||
onDay: (unsigned int) dayStart
|
||||
recurrence: (BOOL) recurrence
|
||||
recurrenceTime: (unsigned int) recurrenceTime
|
||||
userState: (iCalPersonPartStat) userState
|
||||
{
|
||||
NSMutableDictionary *block;
|
||||
|
@ -416,8 +417,9 @@ _feedBlockWithMonthBasedData(NSMutableDictionary *block, unsigned int start,
|
|||
else
|
||||
_feedBlockWithMonthBasedData (block, start, userTimeZone, dateFormatter);
|
||||
[block setObject: cName forKey: @"cname"];
|
||||
if (recurrence)
|
||||
[block setObject: @"1" forKey: @"recurrence"];
|
||||
if (recurrenceTime)
|
||||
[block setObject: [NSNumber numberWithInt: recurrenceTime]
|
||||
forKey: @"recurrenceTime"];
|
||||
if (userState != iCalPersonPartStatOther)
|
||||
[block setObject: [NSNumber numberWithInt: userState]
|
||||
forKey: @"userState"];
|
||||
|
@ -463,11 +465,10 @@ _userStateInEvent (NSArray *event)
|
|||
withEvent: (NSArray *) event
|
||||
{
|
||||
unsigned int currentDayStart, startSecs, endsSecs, currentStart, eventStart,
|
||||
eventEnd, offset;
|
||||
eventEnd, offset, recurrenceTime;
|
||||
NSMutableArray *currentDay;
|
||||
NSMutableDictionary *eventBlock;
|
||||
NSString *eventCName;
|
||||
BOOL recurrence;
|
||||
iCalPersonPartStat userState;
|
||||
|
||||
startSecs = (unsigned int) [startDate timeIntervalSince1970];
|
||||
|
@ -475,7 +476,10 @@ _userStateInEvent (NSArray *event)
|
|||
eventStart = [[event objectAtIndex: 4] unsignedIntValue];
|
||||
eventEnd = [[event objectAtIndex: 5] unsignedIntValue];
|
||||
|
||||
recurrence = [[event objectAtIndex: 12] boolValue];
|
||||
if ([[event objectAtIndex: 12] boolValue])
|
||||
recurrenceTime = [[event objectAtIndex: 13] unsignedIntValue];
|
||||
else
|
||||
recurrenceTime = 0;
|
||||
|
||||
currentStart = eventStart;
|
||||
if (currentStart < startSecs)
|
||||
|
@ -500,7 +504,7 @@ _userStateInEvent (NSArray *event)
|
|||
end: currentDayStart + dayLength - 1
|
||||
cname: eventCName
|
||||
onDay: currentDayStart
|
||||
recurrence: recurrence
|
||||
recurrenceTime: recurrenceTime
|
||||
userState: userState];
|
||||
[currentDay addObject: eventBlock];
|
||||
currentDayStart += dayLength;
|
||||
|
@ -512,7 +516,7 @@ _userStateInEvent (NSArray *event)
|
|||
end: eventEnd
|
||||
cname: eventCName
|
||||
onDay: currentDayStart
|
||||
recurrence: recurrence
|
||||
recurrenceTime: recurrenceTime
|
||||
userState: userState];
|
||||
[currentDay addObject: eventBlock];
|
||||
}
|
||||
|
|
|
@ -399,6 +399,11 @@ iRANGE(2);
|
|||
|
||||
/* accessors */
|
||||
|
||||
- (BOOL) isChildOccurence
|
||||
{
|
||||
return [[self clientObject] isKindOfClass: [SOGoComponentOccurence class]];
|
||||
}
|
||||
|
||||
- (void) setItem: (id) _item
|
||||
{
|
||||
ASSIGN (item, _item);
|
||||
|
@ -418,7 +423,7 @@ iRANGE(2);
|
|||
{
|
||||
NSString *tag;
|
||||
|
||||
tag = [[self clientObject] componentTag];
|
||||
tag = [[component tag] lowercaseString];
|
||||
|
||||
return [self labelForKey: [NSString stringWithFormat: @"%@_%@", item, tag]];
|
||||
}
|
||||
|
@ -456,7 +461,7 @@ iRANGE(2);
|
|||
- (BOOL) canBeOrganizer
|
||||
{
|
||||
NSString *owner;
|
||||
SOGoCalendarComponent *co;
|
||||
SOGoObject <SOGoComponentOccurence> *co;
|
||||
SOGoUser *currentUser;
|
||||
BOOL hasOrganizer;
|
||||
SoSecurityManager *sm;
|
||||
|
@ -801,7 +806,7 @@ iRANGE(2);
|
|||
SOGoAppointmentFolders *parentFolder;
|
||||
|
||||
fDisplayName = [item displayName];
|
||||
folder = [[self clientObject] container];
|
||||
folder = [self componentCalendar];
|
||||
parentFolder = [folder container];
|
||||
if ([fDisplayName isEqualToString: [parentFolder defaultFolderName]])
|
||||
fDisplayName = [self labelForKey: fDisplayName];
|
||||
|
@ -823,7 +828,9 @@ iRANGE(2);
|
|||
SOGoAppointmentFolder *calendar;
|
||||
|
||||
calendar = [[self clientObject] container];
|
||||
|
||||
if ([calendar isKindOfClass: [SOGoCalendarComponent class]])
|
||||
calendar = [calendar container];
|
||||
|
||||
return calendar;
|
||||
}
|
||||
|
||||
|
@ -1125,8 +1132,8 @@ RANGE(2);
|
|||
|
||||
- (BOOL) isWriteableClientObject
|
||||
{
|
||||
return [[self clientObject]
|
||||
respondsToSelector: @selector(saveContentString:)];
|
||||
return [[self clientObject]
|
||||
respondsToSelector: @selector(saveContentString:)];
|
||||
}
|
||||
|
||||
/* access */
|
||||
|
@ -1485,54 +1492,56 @@ RANGE(2);
|
|||
clientObject = [self clientObject];
|
||||
if ([clientObject isNew])
|
||||
{
|
||||
[component setUid: [clientObject nameInContainer]];
|
||||
[component setCreated: now];
|
||||
[component setTimeStampAsDate: now];
|
||||
}
|
||||
[component setPriority: priority];
|
||||
[component setLastModified: now];
|
||||
|
||||
// We remove any repeat rules
|
||||
if (!repeat && [component hasRecurrenceRules])
|
||||
[component removeAllRecurrenceRules];
|
||||
else if ([repeat caseInsensitiveCompare: @"-"] != NSOrderedSame)
|
||||
if (![self isChildOccurence])
|
||||
{
|
||||
rule = [iCalRecurrenceRule new];
|
||||
// We remove any repeat rules
|
||||
if (!repeat && [component hasRecurrenceRules])
|
||||
[component removeAllRecurrenceRules];
|
||||
else if ([repeat caseInsensitiveCompare: @"-"] != NSOrderedSame)
|
||||
{
|
||||
rule = [iCalRecurrenceRule new];
|
||||
|
||||
[rule setInterval: @"1"];
|
||||
|
||||
if ([repeat caseInsensitiveCompare: @"BI-WEEKLY"] == NSOrderedSame)
|
||||
{
|
||||
[rule setFrequency: iCalRecurrenceFrequenceWeekly];
|
||||
[rule setInterval: @"2"];
|
||||
}
|
||||
else if ([repeat caseInsensitiveCompare: @"EVERY WEEKDAY"] == NSOrderedSame)
|
||||
{
|
||||
[rule setByDayMask: (iCalWeekDayMonday
|
||||
|iCalWeekDayTuesday
|
||||
|iCalWeekDayWednesday
|
||||
|iCalWeekDayThursday
|
||||
|iCalWeekDayFriday)];
|
||||
[rule setFrequency: iCalRecurrenceFrequenceDaily];
|
||||
}
|
||||
else if ([repeat caseInsensitiveCompare: @"MONTHLY"] == NSOrderedSame
|
||||
|| [repeat caseInsensitiveCompare: @"DAILY"] == NSOrderedSame
|
||||
|| [repeat caseInsensitiveCompare: @"WEEKLY"] == NSOrderedSame
|
||||
|| [repeat caseInsensitiveCompare: @"YEARLY"] == NSOrderedSame)
|
||||
{
|
||||
[rule setInterval: @"1"];
|
||||
[rule setFrequency:
|
||||
(iCalRecurrenceFrequency) [rule valueForFrequency: repeat]];
|
||||
}
|
||||
else
|
||||
{
|
||||
// We have a CUSTOM recurrence. Let's decode what kind of custome recurrence
|
||||
// we have and set that.
|
||||
[self _handleCustomRRule: rule];
|
||||
}
|
||||
|
||||
[component setRecurrenceRules: [NSArray arrayWithObject: rule]];
|
||||
[rule release];
|
||||
if ([repeat caseInsensitiveCompare: @"BI-WEEKLY"] == NSOrderedSame)
|
||||
{
|
||||
[rule setFrequency: iCalRecurrenceFrequenceWeekly];
|
||||
[rule setInterval: @"2"];
|
||||
}
|
||||
else if ([repeat caseInsensitiveCompare: @"EVERY WEEKDAY"] == NSOrderedSame)
|
||||
{
|
||||
[rule setByDayMask: (iCalWeekDayMonday
|
||||
|iCalWeekDayTuesday
|
||||
|iCalWeekDayWednesday
|
||||
|iCalWeekDayThursday
|
||||
|iCalWeekDayFriday)];
|
||||
[rule setFrequency: iCalRecurrenceFrequenceDaily];
|
||||
}
|
||||
else if ([repeat caseInsensitiveCompare: @"MONTHLY"] == NSOrderedSame
|
||||
|| [repeat caseInsensitiveCompare: @"DAILY"] == NSOrderedSame
|
||||
|| [repeat caseInsensitiveCompare: @"WEEKLY"] == NSOrderedSame
|
||||
|| [repeat caseInsensitiveCompare: @"YEARLY"] == NSOrderedSame)
|
||||
{
|
||||
[rule setInterval: @"1"];
|
||||
[rule setFrequency:
|
||||
(iCalRecurrenceFrequency) [rule valueForFrequency: repeat]];
|
||||
}
|
||||
else
|
||||
{
|
||||
// We have a CUSTOM recurrence. Let's decode what kind of custome recurrence
|
||||
// we have and set that.
|
||||
[self _handleCustomRRule: rule];
|
||||
}
|
||||
|
||||
[component setRecurrenceRules: [NSArray arrayWithObject: rule]];
|
||||
[rule release];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/* UIxOccurenceDialog.h - this file is part of SOGo
|
||||
*
|
||||
* Copyright (C) 2008 Inverse inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef UIXRECURRENCEEDITOR_H
|
||||
#define UIXRECURRENCEEDITOR_H
|
||||
|
||||
#import <SOGoUI/UIxComponent.h>
|
||||
|
||||
@class NSString;
|
||||
|
||||
@interface UIxOccurenceDialog : UIxComponent
|
||||
{
|
||||
NSString *action;
|
||||
}
|
||||
|
||||
- (NSString *) action;
|
||||
|
||||
- (NSString *) calendarFolder;
|
||||
- (NSString *) componentName;
|
||||
- (NSString *) recurrenceName;
|
||||
|
||||
- (id <WOActionResults>) defaultAction;
|
||||
- (id <WOActionResults>) confirmDeletionAction;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* UIXRECURRENCEEDITOR_H */
|
|
@ -0,0 +1,90 @@
|
|||
/* UIxOccurenceDialog.m - this file is part of SOGo
|
||||
*
|
||||
* Copyright (C) 2008 Inverse inc.
|
||||
*
|
||||
* 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/NSArray.h>
|
||||
#import <Foundation/NSString.h>
|
||||
|
||||
#import <Common/UIxPageFrame.h>
|
||||
|
||||
#import <SoObjects/Appointments/SOGoCalendarComponent.h>
|
||||
|
||||
#import "UIxOccurenceDialog.h"
|
||||
|
||||
@implementation UIxOccurenceDialog
|
||||
|
||||
- (id) init
|
||||
{
|
||||
if ((self = [super init]))
|
||||
action = nil;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[action release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (NSString *) action
|
||||
{
|
||||
return action;
|
||||
}
|
||||
|
||||
- (NSString *) calendarFolder
|
||||
{
|
||||
SOGoCalendarComponent *component;
|
||||
|
||||
component = [[self clientObject] container];
|
||||
|
||||
return [[component container] nameInContainer];
|
||||
}
|
||||
|
||||
- (NSString *) componentName
|
||||
{
|
||||
SOGoCalendarComponent *component;
|
||||
|
||||
component = [[self clientObject] container];
|
||||
|
||||
return [component nameInContainer];
|
||||
}
|
||||
|
||||
- (NSString *) recurrenceName
|
||||
{
|
||||
return [[self clientObject] nameInContainer];
|
||||
}
|
||||
|
||||
- (id <WOActionResults>) defaultAction
|
||||
{
|
||||
ASSIGN (action, @"edit");
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id <WOActionResults>) confirmDeletionAction
|
||||
{
|
||||
ASSIGN (action, @"delete");
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
|
@ -335,7 +335,7 @@
|
|||
|
||||
actionName = [[request requestHandlerPath] lastPathComponent];
|
||||
|
||||
return ([[self clientObject] isKindOfClass: [SOGoTaskObject class]]
|
||||
return ([[self clientObject] conformsToProtocol: @protocol (SOGoComponentOccurence)]
|
||||
&& [actionName hasPrefix: @"save"]);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,239 +2,293 @@
|
|||
requires = ( MAIN, MainUI, CommonUI, Appointments, Contacts, ContactsUI );
|
||||
|
||||
publicResources = (
|
||||
previous_week.gif,
|
||||
next_week.gif,
|
||||
icon_view_overview.gif,
|
||||
icon_view_overview_inactive.gif,
|
||||
icon_view_chart.gif,
|
||||
icon_view_chart_inactive.gif,
|
||||
icon_view_list.gif,
|
||||
icon_view_list_inactive.gif,
|
||||
icon_view_columns.gif,
|
||||
icon_view_columns_inactive.gif,
|
||||
icon_popupcalendar.gif,
|
||||
first.gif,
|
||||
previous.gif,
|
||||
next.gif,
|
||||
last.gif,
|
||||
skycalendar.html,
|
||||
skycalendar.js,
|
||||
green_corner.gif,
|
||||
invisible_space_2.gif,
|
||||
cycles.plist,
|
||||
);
|
||||
previous_week.gif,
|
||||
next_week.gif,
|
||||
icon_view_overview.gif,
|
||||
icon_view_overview_inactive.gif,
|
||||
icon_view_chart.gif,
|
||||
icon_view_chart_inactive.gif,
|
||||
icon_view_list.gif,
|
||||
icon_view_list_inactive.gif,
|
||||
icon_view_columns.gif,
|
||||
icon_view_columns_inactive.gif,
|
||||
icon_popupcalendar.gif,
|
||||
first.gif,
|
||||
previous.gif,
|
||||
next.gif,
|
||||
last.gif,
|
||||
skycalendar.html,
|
||||
skycalendar.js,
|
||||
green_corner.gif,
|
||||
invisible_space_2.gif,
|
||||
cycles.plist,
|
||||
);
|
||||
|
||||
factories = {
|
||||
};
|
||||
|
||||
categories = {
|
||||
SOGoAppointmentFolders = {
|
||||
slots = {
|
||||
toolbar = {
|
||||
protectedBy = "View";
|
||||
value = "SOGoAppointmentFolders.toolbar";
|
||||
};
|
||||
SOGoAppointmentFolders = {
|
||||
slots = {
|
||||
toolbar = {
|
||||
protectedBy = "View";
|
||||
value = "SOGoAppointmentFolders.toolbar";
|
||||
};
|
||||
methods = {
|
||||
view = {
|
||||
protectedBy = "View";
|
||||
pageName = "UIxCalMainView";
|
||||
};
|
||||
saveDragHandleState = {
|
||||
protectedBy = "View";
|
||||
pageName = "UIxCalMainView";
|
||||
actionName = "saveDragHandleState";
|
||||
};
|
||||
dateselector = {
|
||||
protectedBy = "View";
|
||||
pageName = "UIxCalDateSelector";
|
||||
};
|
||||
calendarslist = {
|
||||
protectedBy = "View";
|
||||
pageName = "UIxCalendarSelector";
|
||||
actionName = "calendarsList";
|
||||
};
|
||||
eventslist = {
|
||||
protectedBy = "View";
|
||||
actionClass = "UIxCalListingActions";
|
||||
actionName = "eventsList";
|
||||
};
|
||||
eventsblocks = {
|
||||
protectedBy = "View";
|
||||
actionClass = "UIxCalListingActions";
|
||||
actionName = "eventsBlocks";
|
||||
};
|
||||
taskslist = {
|
||||
protectedBy = "View";
|
||||
actionClass = "UIxCalListingActions";
|
||||
actionName = "tasksList";
|
||||
};
|
||||
dayview = {
|
||||
protectedBy = "View";
|
||||
pageName = "UIxCalDayView";
|
||||
};
|
||||
multicolumndayview = {
|
||||
protectedBy = "View";
|
||||
pageName = "UIxCalMulticolumnDayView";
|
||||
};
|
||||
weekview = {
|
||||
protectedBy = "View";
|
||||
pageName = "UIxCalWeekView";
|
||||
};
|
||||
monthview = {
|
||||
protectedBy = "View";
|
||||
pageName = "UIxCalMonthView";
|
||||
};
|
||||
show = {
|
||||
protectedBy = "View";
|
||||
pageName = "UIxCalView";
|
||||
actionName = "redirectForUIDs";
|
||||
};
|
||||
// proposal = {
|
||||
// protectedBy = "View";
|
||||
// pageName = "UIxAppointmentProposal";
|
||||
// };
|
||||
// proposalSearch = {
|
||||
// protectedBy = "View";
|
||||
// pageName = "UIxAppointmentProposal";
|
||||
// actionName = "proposalSearch";
|
||||
// };
|
||||
userRights = {
|
||||
protectedBy = "ReadAcls";
|
||||
pageName = "UIxCalUserRightsEditor";
|
||||
};
|
||||
saveUserRights = {
|
||||
protectedBy = "Change Permissions";
|
||||
pageName = "UIxCalUserRightsEditor";
|
||||
actionName = "saveUserRights";
|
||||
};
|
||||
editAttendees = {
|
||||
protectedBy = "View";
|
||||
pageName = "UIxAttendeesEditor";
|
||||
};
|
||||
editRecurrence = {
|
||||
protectedBy = "View";
|
||||
pageName = "UIxRecurrenceEditor";
|
||||
};
|
||||
colorPicker = {
|
||||
protectedBy = "View";
|
||||
pageName = "UIxColorPicker";
|
||||
};
|
||||
};
|
||||
methods = {
|
||||
view = {
|
||||
protectedBy = "View";
|
||||
pageName = "UIxCalMainView";
|
||||
};
|
||||
};
|
||||
saveDragHandleState = {
|
||||
protectedBy = "View";
|
||||
pageName = "UIxCalMainView";
|
||||
actionName = "saveDragHandleState";
|
||||
};
|
||||
dateselector = {
|
||||
protectedBy = "View";
|
||||
pageName = "UIxCalDateSelector";
|
||||
};
|
||||
calendarslist = {
|
||||
protectedBy = "View";
|
||||
pageName = "UIxCalendarSelector";
|
||||
actionName = "calendarsList";
|
||||
};
|
||||
eventslist = {
|
||||
protectedBy = "View";
|
||||
actionClass = "UIxCalListingActions";
|
||||
actionName = "eventsList";
|
||||
};
|
||||
eventsblocks = {
|
||||
protectedBy = "View";
|
||||
actionClass = "UIxCalListingActions";
|
||||
actionName = "eventsBlocks";
|
||||
};
|
||||
taskslist = {
|
||||
protectedBy = "View";
|
||||
actionClass = "UIxCalListingActions";
|
||||
actionName = "tasksList";
|
||||
};
|
||||
dayview = {
|
||||
protectedBy = "View";
|
||||
pageName = "UIxCalDayView";
|
||||
};
|
||||
multicolumndayview = {
|
||||
protectedBy = "View";
|
||||
pageName = "UIxCalMulticolumnDayView";
|
||||
};
|
||||
weekview = {
|
||||
protectedBy = "View";
|
||||
pageName = "UIxCalWeekView";
|
||||
};
|
||||
monthview = {
|
||||
protectedBy = "View";
|
||||
pageName = "UIxCalMonthView";
|
||||
};
|
||||
show = {
|
||||
protectedBy = "View";
|
||||
pageName = "UIxCalView";
|
||||
actionName = "redirectForUIDs";
|
||||
};
|
||||
// proposal = {
|
||||
// protectedBy = "View";
|
||||
// pageName = "UIxAppointmentProposal";
|
||||
// };
|
||||
// proposalSearch = {
|
||||
// protectedBy = "View";
|
||||
// pageName = "UIxAppointmentProposal";
|
||||
// actionName = "proposalSearch";
|
||||
// };
|
||||
userRights = {
|
||||
protectedBy = "ReadAcls";
|
||||
pageName = "UIxCalUserRightsEditor";
|
||||
};
|
||||
saveUserRights = {
|
||||
protectedBy = "Change Permissions";
|
||||
pageName = "UIxCalUserRightsEditor";
|
||||
actionName = "saveUserRights";
|
||||
};
|
||||
editAttendees = {
|
||||
protectedBy = "View";
|
||||
pageName = "UIxAttendeesEditor";
|
||||
};
|
||||
editRecurrence = {
|
||||
protectedBy = "View";
|
||||
pageName = "UIxRecurrenceEditor";
|
||||
};
|
||||
colorPicker = {
|
||||
protectedBy = "View";
|
||||
pageName = "UIxColorPicker";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
SOGoAppointmentFolder = {
|
||||
methods = {
|
||||
properties = {
|
||||
protectedBy = "Access Contents Information";
|
||||
pageName = "UIxCalendarProperties";
|
||||
};
|
||||
saveProperties = {
|
||||
protectedBy = "Access Contents Information";
|
||||
pageName = "UIxCalendarProperties";
|
||||
actionName = "saveProperties";
|
||||
};
|
||||
show = {
|
||||
protectedBy = "View";
|
||||
pageName = "UIxCalView";
|
||||
actionName = "redirectForUIDs";
|
||||
};
|
||||
userRights = {
|
||||
protectedBy = "ReadAcls";
|
||||
pageName = "UIxCalUserRightsEditor";
|
||||
};
|
||||
saveUserRights = {
|
||||
protectedBy = "Change Permissions";
|
||||
pageName = "UIxCalUserRightsEditor";
|
||||
actionName = "saveUserRights";
|
||||
};
|
||||
newevent = {
|
||||
protectedBy = "Add Documents, Images, and Files";
|
||||
pageName = "UIxAppointmentEditor";
|
||||
actionName = "new";
|
||||
};
|
||||
newtask = {
|
||||
protectedBy = "Add Documents, Images, and Files";
|
||||
pageName = "UIxTaskEditor";
|
||||
actionName = "new";
|
||||
};
|
||||
SOGoAppointmentFolder = {
|
||||
methods = {
|
||||
properties = {
|
||||
protectedBy = "Access Contents Information";
|
||||
pageName = "UIxCalendarProperties";
|
||||
};
|
||||
};
|
||||
saveProperties = {
|
||||
protectedBy = "Access Contents Information";
|
||||
pageName = "UIxCalendarProperties";
|
||||
actionName = "saveProperties";
|
||||
};
|
||||
show = {
|
||||
protectedBy = "View";
|
||||
pageName = "UIxCalView";
|
||||
actionName = "redirectForUIDs";
|
||||
};
|
||||
userRights = {
|
||||
protectedBy = "ReadAcls";
|
||||
pageName = "UIxCalUserRightsEditor";
|
||||
};
|
||||
saveUserRights = {
|
||||
protectedBy = "Change Permissions";
|
||||
pageName = "UIxCalUserRightsEditor";
|
||||
actionName = "saveUserRights";
|
||||
};
|
||||
newevent = {
|
||||
protectedBy = "Add Documents, Images, and Files";
|
||||
pageName = "UIxAppointmentEditor";
|
||||
actionName = "new";
|
||||
};
|
||||
newtask = {
|
||||
protectedBy = "Add Documents, Images, and Files";
|
||||
pageName = "UIxTaskEditor";
|
||||
actionName = "new";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
SOGoCalendarComponent = {
|
||||
};
|
||||
SOGoCalendarComponent = {
|
||||
};
|
||||
|
||||
SOGoAppointmentObject = {
|
||||
slots = {
|
||||
toolbar = {
|
||||
protectedBy = "View";
|
||||
value = "SOGoAppointmentObject.toolbar";
|
||||
};
|
||||
SOGoAppointmentObject = {
|
||||
slots = {
|
||||
toolbar = {
|
||||
protectedBy = "View";
|
||||
value = "SOGoAppointmentObject.toolbar";
|
||||
};
|
||||
methods = {
|
||||
edit = {
|
||||
protectedBy = "ViewAllComponent";
|
||||
pageName = "UIxAppointmentEditor";
|
||||
};
|
||||
editAsAppointment = {
|
||||
protectedBy = "ViewAllComponent";
|
||||
pageName = "UIxAppointmentEditor";
|
||||
};
|
||||
save = {
|
||||
protectedBy = "ModifyComponent";
|
||||
pageName = "UIxAppointmentEditor";
|
||||
actionName = "save";
|
||||
};
|
||||
saveAsAppointment = {
|
||||
protectedBy = "ModifyComponent";
|
||||
pageName = "UIxAppointmentEditor";
|
||||
actionName = "save";
|
||||
};
|
||||
accept = {
|
||||
protectedBy = "RespondToComponent";
|
||||
pageName = "UIxAppointmentEditor";
|
||||
actionName = "accept";
|
||||
};
|
||||
decline = {
|
||||
protectedBy = "RespondToComponent";
|
||||
pageName = "UIxAppointmentEditor";
|
||||
actionName = "decline";
|
||||
};
|
||||
};
|
||||
methods = {
|
||||
edit = {
|
||||
protectedBy = "ViewAllComponent";
|
||||
pageName = "UIxAppointmentEditor";
|
||||
};
|
||||
};
|
||||
editAsAppointment = {
|
||||
protectedBy = "ViewAllComponent";
|
||||
pageName = "UIxAppointmentEditor";
|
||||
};
|
||||
save = {
|
||||
protectedBy = "ModifyComponent";
|
||||
pageName = "UIxAppointmentEditor";
|
||||
actionName = "save";
|
||||
};
|
||||
saveAsAppointment = {
|
||||
protectedBy = "ModifyComponent";
|
||||
pageName = "UIxAppointmentEditor";
|
||||
actionName = "save";
|
||||
};
|
||||
accept = {
|
||||
protectedBy = "RespondToComponent";
|
||||
pageName = "UIxAppointmentEditor";
|
||||
actionName = "accept";
|
||||
};
|
||||
decline = {
|
||||
protectedBy = "RespondToComponent";
|
||||
pageName = "UIxAppointmentEditor";
|
||||
actionName = "decline";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
SOGoTaskObject = {
|
||||
slots = {
|
||||
toolbar = {
|
||||
protectedBy = "View";
|
||||
value = "SOGoAppointmentObject.toolbar";
|
||||
};
|
||||
SOGoTaskObject = {
|
||||
slots = {
|
||||
toolbar = {
|
||||
protectedBy = "View";
|
||||
value = "SOGoAppointmentObject.toolbar";
|
||||
};
|
||||
methods = {
|
||||
edit = {
|
||||
protectedBy = "ViewAllComponent";
|
||||
pageName = "UIxTaskEditor";
|
||||
};
|
||||
editAsTask = {
|
||||
protectedBy = "ViewAllComponent";
|
||||
pageName = "UIxTaskEditor";
|
||||
};
|
||||
save = {
|
||||
protectedBy = "ModifyComponent";
|
||||
pageName = "UIxTaskEditor";
|
||||
actionName = "save";
|
||||
};
|
||||
saveAsTask = {
|
||||
protectedBy = "ModifyComponent";
|
||||
pageName = "UIxTaskEditor";
|
||||
actionName = "save";
|
||||
};
|
||||
changeStatus = {
|
||||
protectedBy = "ModifyComponent";
|
||||
pageName = "UIxTaskEditor";
|
||||
actionName = "changeStatus";
|
||||
};
|
||||
};
|
||||
methods = {
|
||||
edit = {
|
||||
protectedBy = "ViewAllComponent";
|
||||
pageName = "UIxTaskEditor";
|
||||
};
|
||||
};
|
||||
editAsTask = {
|
||||
protectedBy = "ViewAllComponent";
|
||||
pageName = "UIxTaskEditor";
|
||||
};
|
||||
save = {
|
||||
protectedBy = "ModifyComponent";
|
||||
pageName = "UIxTaskEditor";
|
||||
actionName = "save";
|
||||
};
|
||||
saveAsTask = {
|
||||
protectedBy = "ModifyComponent";
|
||||
pageName = "UIxTaskEditor";
|
||||
actionName = "save";
|
||||
};
|
||||
changeStatus = {
|
||||
protectedBy = "ModifyComponent";
|
||||
pageName = "UIxTaskEditor";
|
||||
actionName = "changeStatus";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
SOGoComponentOccurence = {
|
||||
methods = {
|
||||
confirmEditing = {
|
||||
protectedBy = "ModifyComponent";
|
||||
pageName = "UIxOccurenceDialog";
|
||||
};
|
||||
confirmDeletion = {
|
||||
protectedBy = "ModifyComponent";
|
||||
pageName = "UIxOccurenceDialog";
|
||||
actionName = "confirmDeletion";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
SOGoAppointmentOccurence = {
|
||||
slots = {
|
||||
toolbar = {
|
||||
protectedBy = "View";
|
||||
value = "SOGoAppointmentObject.toolbar";
|
||||
};
|
||||
};
|
||||
methods = {
|
||||
edit = {
|
||||
protectedBy = "ViewAllComponent";
|
||||
pageName = "UIxAppointmentEditor";
|
||||
};
|
||||
save = {
|
||||
protectedBy = "ModifyComponent";
|
||||
pageName = "UIxAppointmentEditor";
|
||||
actionName = "save";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
SOGoTaskOccurence = {
|
||||
slots = {
|
||||
toolbar = {
|
||||
protectedBy = "View";
|
||||
value = "SOGoTaskObject.toolbar";
|
||||
};
|
||||
};
|
||||
methods = {
|
||||
edit = {
|
||||
protectedBy = "ViewAllComponent";
|
||||
pageName = "UIxTaskEditor";
|
||||
};
|
||||
save = {
|
||||
protectedBy = "ModifyComponent";
|
||||
pageName = "UIxTaskEditor";
|
||||
actionName = "save";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
string="itemCategoryText" selection="category"
|
||||
/><var:string label:value="Calendar:" />
|
||||
<var:popup const:id="calendarList"
|
||||
var:disabled="isChildOccurence"
|
||||
list="calendarList" item="item"
|
||||
string="calendarDisplayName"
|
||||
var:selection="componentCalendar"
|
||||
|
@ -75,6 +76,7 @@
|
|||
<label><var:string label:value="Repeat:" />
|
||||
<span class="content"><var:popup list="repeatList" item="item"
|
||||
label:noSelectionString="repeat_NEVER"
|
||||
var:disabled="isChildOccurence"
|
||||
const:disabledValue="-"
|
||||
const:name="repeatList"
|
||||
const:id="repeatList"
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
<?xml version='1.0' standalone='yes'?>
|
||||
<!DOCTYPE var:component>
|
||||
<var:component
|
||||
xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:var="http://www.skyrix.com/od/binding"
|
||||
xmlns:const="http://www.skyrix.com/od/constant"
|
||||
xmlns:uix="OGo:uix"
|
||||
xmlns:rsrc="OGo:url"
|
||||
xmlns:label="OGo:label"
|
||||
className="UIxPageFrame"
|
||||
const:popup="YES"
|
||||
title="name"
|
||||
const:toolbar="none">
|
||||
<script type="text/javascript">
|
||||
var calendarFolder = '<var:string value="calendarFolder"/>';
|
||||
var componentName = '<var:string value="componentName"/>';
|
||||
var recurrenceName = '<var:string value="recurrenceName"/>';
|
||||
var action = '<var:string value="action"/>';
|
||||
</script>
|
||||
<div id="message">
|
||||
<var:string label:value="editRepeatingItem"/>
|
||||
</div>
|
||||
<div id="windowButtons">
|
||||
<div id="leftButtons">
|
||||
<input type="button" id="thisButton" const:class="button" label:value="button_thisOccurrenceOnly"/>
|
||||
</div>
|
||||
<div id="rightButtons">
|
||||
<input type="submit" id="cancelButton" const:class="button" label:value="Cancel"/>
|
||||
<input type="button" id="allButton" const:class="button" label:value="button_allOccurrences"/>
|
||||
</div>
|
||||
</div>
|
||||
</var:component>
|
|
@ -71,9 +71,14 @@ function onMenuNewTaskClick(event) {
|
|||
newEvent(this, "task");
|
||||
}
|
||||
|
||||
function _editEventId(id, calendar) {
|
||||
var urlstr = ApplicationBaseURL + calendar + "/" + id + "/edit";
|
||||
function _editEventId(id, calendar, recurrence) {
|
||||
var targetname = "SOGo_edit_" + id;
|
||||
var urlstr = ApplicationBaseURL + calendar + "/" + id;
|
||||
if (recurrence) {
|
||||
urlstr += "/" + recurrence;
|
||||
targetname += recurrence;
|
||||
}
|
||||
urlstr += "/edit";
|
||||
var win = window.open(urlstr, "_blank",
|
||||
"width=490,height=470,resizable=0");
|
||||
if (win)
|
||||
|
@ -115,50 +120,60 @@ function _batchDeleteEvents() {
|
|||
function deleteEvent() {
|
||||
if (listOfSelection) {
|
||||
var nodes = listOfSelection.getSelectedRows();
|
||||
|
||||
if (nodes.length > 0) {
|
||||
var label = "";
|
||||
if (listOfSelection == $("tasksList"))
|
||||
label = labels["taskDeleteConfirmation"];
|
||||
else
|
||||
label = labels["eventDeleteConfirmation"];
|
||||
|
||||
if (confirm(label)) {
|
||||
if (document.deleteEventAjaxRequest) {
|
||||
|
||||
if (nodes.length == 1
|
||||
&& nodes[0].recurrenceTime) {
|
||||
_editRecurrenceDialog(nodes[0], "confirmDeletion");
|
||||
}
|
||||
else {
|
||||
if (confirm(label)) {
|
||||
if (document.deleteEventAjaxRequest) {
|
||||
document.deleteEventAjaxRequest.aborted = true;
|
||||
document.deleteEventAjaxRequest.abort();
|
||||
}
|
||||
var sortedNodes = [];
|
||||
var calendars = [];
|
||||
|
||||
for (var i = 0; i < nodes.length; i++) {
|
||||
var calendar = nodes[i].calendar;
|
||||
if (!sortedNodes[calendar]) {
|
||||
sortedNodes[calendar] = [];
|
||||
calendars.push(calendar);
|
||||
}
|
||||
sortedNodes[calendar].push(nodes[i].cname);
|
||||
}
|
||||
for (var i = 0; i < calendars.length; i++) {
|
||||
calendarsOfEventsToDelete.push(calendars[i]);
|
||||
eventsToDelete.push(sortedNodes[calendars[i]]);
|
||||
}
|
||||
_batchDeleteEvents();
|
||||
}
|
||||
var sortedNodes = [];
|
||||
var calendars = [];
|
||||
|
||||
for (var i = 0; i < nodes.length; i++) {
|
||||
var calendar = nodes[i].calendar;
|
||||
if (!sortedNodes[calendar]) {
|
||||
sortedNodes[calendar] = [];
|
||||
calendars.push(calendar);
|
||||
}
|
||||
sortedNodes[calendar].push(nodes[i].cname);
|
||||
}
|
||||
for (var i = 0; i < calendars.length; i++) {
|
||||
calendarsOfEventsToDelete.push(calendars[i]);
|
||||
eventsToDelete.push(sortedNodes[calendars[i]]);
|
||||
}
|
||||
_batchDeleteEvents();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
window.alert(labels["Please select an event or a task."]);
|
||||
}
|
||||
}
|
||||
else if (selectedCalendarCell) {
|
||||
var label = labels["eventDeleteConfirmation"];
|
||||
if (confirm(label)) {
|
||||
if (document.deleteEventAjaxRequest) {
|
||||
document.deleteEventAjaxRequest.aborted = true;
|
||||
document.deleteEventAjaxRequest.abort();
|
||||
if (selectedCalendarCell[0].recurrenceTime) {
|
||||
_editRecurrenceDialog(selectedCalendarCell[0], "confirmDeletion");
|
||||
}
|
||||
else {
|
||||
var label = labels["eventDeleteConfirmation"];
|
||||
if (confirm(label)) {
|
||||
if (document.deleteEventAjaxRequest) {
|
||||
document.deleteEventAjaxRequest.aborted = true;
|
||||
document.deleteEventAjaxRequest.abort();
|
||||
}
|
||||
eventsToDelete.push([selectedCalendarCell[0].cname]);
|
||||
calendarsOfEventsToDelete.push(selectedCalendarCell[0].calendar);
|
||||
_batchDeleteEvents();
|
||||
}
|
||||
eventsToDelete.push([selectedCalendarCell[0].cname]);
|
||||
calendarsOfEventsToDelete.push(selectedCalendarCell[0].calendar);
|
||||
_batchDeleteEvents();
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -268,13 +283,97 @@ function deleteEventsFromViews(events) {
|
|||
}
|
||||
}
|
||||
|
||||
function _editRecurrenceDialog(eventDiv, method) {
|
||||
var targetname = "SOGo_edit_" + eventDiv.cname + eventDiv.recurrenceTime;
|
||||
var urlstr = (ApplicationBaseURL + eventDiv.calendar + "/" + eventDiv.cname
|
||||
+ "/occurence" + eventDiv.recurrenceTime + "/" + method);
|
||||
var win = window.open(urlstr, "_blank",
|
||||
"width=490,height=70,resizable=0");
|
||||
if (win)
|
||||
win.focus();
|
||||
}
|
||||
|
||||
function editDoubleClickedEvent(event) {
|
||||
_editEventId(this.cname, this.calendar);
|
||||
if (this.recurrenceTime)
|
||||
_editRecurrenceDialog(this, "confirmEditing");
|
||||
else
|
||||
_editEventId(this.cname, this.calendar);
|
||||
|
||||
preventDefault(event);
|
||||
event.cancelBubble = true;
|
||||
}
|
||||
|
||||
function performEventEdition(folder, event, recurrence) {
|
||||
_editEventId(event, folder, recurrence);
|
||||
}
|
||||
|
||||
function performEventDeletion(folder, event, recurrence) {
|
||||
if (calendarEvents) {
|
||||
var eventEntry = calendarEvents[event];
|
||||
if (eventEntry) {
|
||||
var urlstr = ApplicationBaseURL + folder + "/" + event;
|
||||
var nodes;
|
||||
if (recurrence) {
|
||||
urlstr += "/" + recurrence;
|
||||
var occurenceTime = recurrence.substring(9);
|
||||
nodes = [];
|
||||
for (var i = 0; i < eventEntry.siblings.length; i++) {
|
||||
if (eventEntry.siblings[i].recurrenceTime
|
||||
&& eventEntry.siblings[i].recurrenceTime == occurenceTime)
|
||||
nodes.push(eventEntry.siblings[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
nodes = eventEntry.siblings;
|
||||
urlstr += "/delete";
|
||||
document.deleteEventAjaxRequest = triggerAjaxRequest(urlstr,
|
||||
performDeleteEventCallback,
|
||||
{ nodes: nodes,
|
||||
recurrence: recurrence });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function performDeleteEventCallback(http) {
|
||||
if (http.readyState == 4) {
|
||||
if (isHttpStatus204(http.status)) {
|
||||
var nodes = http.callbackData.nodes;
|
||||
var recurrenceTime = 0;
|
||||
if (http.callbackData.recurrence)
|
||||
recurrenceTime = http.callbackData.recurrence.substring(9);
|
||||
var cName = nodes[0].cname;
|
||||
var eventEntry = calendarEvents[cName];
|
||||
var node = nodes.pop();
|
||||
while (node) {
|
||||
node.parentNode.removeChild(node);
|
||||
node = nodes.pop();
|
||||
}
|
||||
if (recurrenceTime) {
|
||||
var row = $(cName + "-" + recurrenceTime);
|
||||
if (row)
|
||||
row.parentNode.removeChild(row);
|
||||
}
|
||||
else {
|
||||
delete calendarEvents[cName];
|
||||
var tables = [ "eventsList", "tasksList" ];
|
||||
for (var i = 0; i < 2; i++) {
|
||||
var table = $(tables[i]);
|
||||
if (table.tBodies)
|
||||
rows = table.tBodies[0].rows;
|
||||
else
|
||||
rows = $(table).childNodesWithTag("li");
|
||||
for (var j = rows.length; j > 0; j--) {
|
||||
var row = $(rows[j - 1]);
|
||||
var id = row.getAttribute("id");
|
||||
if (id.indexOf(cName) == 0)
|
||||
row.parentNode.removeChild(row);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onSelectAll() {
|
||||
var list = $("eventsList");
|
||||
list.selectRowsMatchingClass("eventRow");
|
||||
|
@ -370,10 +469,15 @@ function eventsListCallback(http) {
|
|||
var row = document.createElement("tr");
|
||||
table.tBodies[0].appendChild(row);
|
||||
$(row).addClassName("eventRow");
|
||||
row.setAttribute("id", escape(data[i][0]));
|
||||
var rTime = data[i][13];
|
||||
var id = escape(data[i][0]);
|
||||
if (rTime)
|
||||
id += "-" + escape(rTime);
|
||||
row.setAttribute("id", id);
|
||||
row.cname = escape(data[i][0]);
|
||||
row.calendar = data[i][1];
|
||||
|
||||
if (rTime)
|
||||
row.recurrenceTime = escape(rTime);
|
||||
var startDate = new Date();
|
||||
startDate.setTime(data[i][4] * 1000);
|
||||
row.day = startDate.getDayString();
|
||||
|
@ -391,12 +495,12 @@ function eventsListCallback(http) {
|
|||
td = $(document.createElement("td"));
|
||||
row.appendChild(td);
|
||||
td.observe("mousedown", listRowMouseDownHandler, true);
|
||||
td.appendChild(document.createTextNode(data[i][13]));
|
||||
td.appendChild(document.createTextNode(data[i][14]));
|
||||
|
||||
td = $(document.createElement("td"));
|
||||
row.appendChild(td);
|
||||
td.observe("mousedown", listRowMouseDownHandler, true);
|
||||
td.appendChild(document.createTextNode(data[i][14]));
|
||||
td.appendChild(document.createTextNode(data[i][15]));
|
||||
|
||||
td = $(document.createElement("td"));
|
||||
row.appendChild(td);
|
||||
|
@ -761,16 +865,17 @@ function _drawCalendarAllDaysEvents(events) {
|
|||
}
|
||||
}
|
||||
|
||||
function newAllDayEventDIV(eventRep) {
|
||||
function newBaseEventDIV(eventRep, event, eventText) {
|
||||
// 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];
|
||||
if (eventRep.recurrenceTime)
|
||||
eventDiv.recurrenceTime = eventRep.recurrenceTime;
|
||||
|
||||
eventDiv.addClassName("event");
|
||||
if (eventRep.userState && userStates[eventRep.userState])
|
||||
|
@ -787,69 +892,6 @@ function newAllDayEventDIV(eventRep) {
|
|||
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");
|
||||
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");
|
||||
if (eventRep.userState && userStates[eventRep.userState])
|
||||
eventDiv.addClassName(userStates[eventRep.userState]);
|
||||
|
||||
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");
|
||||
|
@ -860,20 +902,7 @@ function newEventDIV(eventRep) {
|
|||
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 + "%";
|
||||
textDiv.appendChild(document.createTextNode(eventText));
|
||||
|
||||
eventDiv.observe("mousedown", listRowMouseDownHandler);
|
||||
eventDiv.observe("click", onCalendarSelectEvent);
|
||||
|
@ -884,6 +913,43 @@ function newEventDIV(eventRep) {
|
|||
return eventDiv;
|
||||
}
|
||||
|
||||
function newAllDayEventDIV(eventRep) {
|
||||
// cname, calendar, starts, lasts,
|
||||
// startHour, endHour, title) {
|
||||
var event = calendarEvents[eventRep.cname];
|
||||
var eventDiv = newBaseEventDIV(eventRep, event, event[3]);
|
||||
|
||||
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) {
|
||||
var event = calendarEvents[eventRep.cname];
|
||||
var eventDiv = newBaseEventDIV(eventRep, event, event[3]);
|
||||
|
||||
var pc = 100 / eventRep.siblings;
|
||||
eventDiv.style.width = pc + "%";
|
||||
var left = eventRep.position * pc;
|
||||
eventDiv.style.left = left + "%";
|
||||
eventDiv.addClassName("starts" + eventRep.start);
|
||||
eventDiv.addClassName("lasts" + eventRep.length);
|
||||
|
||||
return eventDiv;
|
||||
}
|
||||
|
||||
function _drawMonthCalendarEvents(events) {
|
||||
var daysView = $("monthDaysView");
|
||||
var days = daysView.childNodesWithTag("div");
|
||||
|
@ -898,56 +964,14 @@ function _drawMonthCalendarEvents(events) {
|
|||
}
|
||||
|
||||
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");
|
||||
if (eventRep.userState && userStates[eventRep.userState]) {
|
||||
eventDiv.addClassName(userStates[eventRep.userState]);
|
||||
log (eventDiv.getAttribute("class"));
|
||||
}
|
||||
|
||||
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);
|
||||
var eventDiv = newBaseEventDIV(eventRep, event, eventText);
|
||||
|
||||
return eventDiv;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
DIV#message, DIV#windowButtons
|
||||
{ margin: 10px; }
|
||||
|
||||
DIV#windowButtons INPUT
|
||||
{ text-align: center; }
|
||||
|
||||
DIV#leftButtons
|
||||
{ float: left;
|
||||
width: 200px;
|
||||
text-align: left; }
|
||||
|
||||
DIV#rightButtons
|
||||
{ text-align: right; }
|
|
@ -0,0 +1,40 @@
|
|||
function onCancelButtonClick(event) {
|
||||
window.close();
|
||||
}
|
||||
|
||||
function onThisButtonClick(event) {
|
||||
if (action == 'edit')
|
||||
window.opener.performEventEdition(calendarFolder, componentName,
|
||||
recurrenceName);
|
||||
else if (action == 'delete')
|
||||
window.opener.performEventDeletion(calendarFolder, componentName,
|
||||
recurrenceName);
|
||||
else
|
||||
window.alert("Invalid action: " + action);
|
||||
|
||||
window.close();
|
||||
}
|
||||
|
||||
function onAllButtonClick(event) {
|
||||
if (action == 'edit')
|
||||
window.opener.performEventEdition(calendarFolder, componentName);
|
||||
else if (action == 'delete')
|
||||
window.opener.performEventDeletion(calendarFolder, componentName);
|
||||
else
|
||||
window.alert("Invalid action: " + action);
|
||||
|
||||
window.close();
|
||||
}
|
||||
|
||||
function onOccurenceDialogLoad() {
|
||||
var thisButton = $("thisButton");
|
||||
thisButton.observe("click", onThisButtonClick);
|
||||
|
||||
var allButton = $("allButton");
|
||||
allButton.observe("click", onAllButtonClick);
|
||||
|
||||
var cancelButton = $("cancelButton");
|
||||
cancelButton.observe("click", onCancelButtonClick);
|
||||
}
|
||||
|
||||
FastInit.addOnLoad(onOccurenceDialogLoad);
|
Loading…
Reference in New Issue