Monotone-Parent: a164259525f718f804b625a9f09b4c3b3c9e83f8

Monotone-Revision: 11f4bdac420d36e45b12ca5d1d393ec34f43c609

Monotone-Author: wsourdeau@inverse.ca
Monotone-Date: 2007-11-10T00:02:30
Monotone-Branch: ca.inverse.sogo
This commit is contained in:
Wolfgang Sourdeau 2007-11-10 00:02:30 +00:00
parent aebac17d01
commit 1eda040e84
13 changed files with 563 additions and 416 deletions

View file

@ -1,5 +1,21 @@
2007-11-09 Wolfgang Sourdeau <wsourdeau@inverse.ca> 2007-11-09 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* UI/MailPartViewers/UIxMailPartICalViewer.m
([UIxMailPartICalViewer -acceptLink])
([UIxMailPartICalViewer -declineLink])
([UIxMailPartICalViewer -tentativeLink]): removed useless methods.
* UI/MailPartViewers/UIxMailPartICalAction.m ([UIxMailPartICalAction -addToCalendarAction])
([UIxMailPartICalAction -deleteFromCalendarAction]): new stub
methods.
* SoObjects/Mailer/SOGoMailObject.m ([SOGoMailObject
-lookupImap4BodyPartKey:]): make use of the new method below.
* SoObjects/Mailer/SOGoMailBodyPart.m ([SOGoMailBodyPart
+bodyPartClassForMimeType:mimeTypeinContext:_ctx]): new method
that returns an appropriate Class depending on a given mime type.
* UI/SOGoUI/UIxComponent.m ([UIxComponent -canCreateOrModify]): * UI/SOGoUI/UIxComponent.m ([UIxComponent -canCreateOrModify]):
new boolean accessor that determines whether someone can create new boolean accessor that determines whether someone can create
(i.e. modify a new entry) or modify an existing entry. (i.e. modify a new entry) or modify an existing entry.

View file

@ -62,6 +62,8 @@
+ (Class) bodyPartClassForKey: (NSString *) _key + (Class) bodyPartClassForKey: (NSString *) _key
inContext: (id) _ctx; inContext: (id) _ctx;
+ (Class) bodyPartClassForMimeType: (NSString *) mimeType
inContext: (id) _ctx;
@end @end

View file

@ -34,6 +34,8 @@
#import <NGExtensions/NGBase64Coding.h> #import <NGExtensions/NGBase64Coding.h>
#import <NGImap4/NGImap4Connection.h> #import <NGImap4/NGImap4Connection.h>
#import <SoObjects/SOGo/NSDictionary+Utilities.h>
#import "SOGoMailObject.h" #import "SOGoMailObject.h"
#import "SOGoMailManager.h" #import "SOGoMailManager.h"
@ -305,7 +307,9 @@ static BOOL debugOn = NO;
/* factory */ /* factory */
+ (Class)bodyPartClassForKey:(NSString *)_key inContext:(id)_ctx { + (Class) bodyPartClassForKey: (NSString *) _key
inContext: (id) _ctx
{
NSString *pe; NSString *pe;
pe = [_key pathExtension]; pe = [_key pathExtension];
@ -335,6 +339,36 @@ static BOOL debugOn = NO;
return self; return self;
} }
+ (Class) bodyPartClassForMimeType: (NSString *) mimeType
inContext: (id) _ctx
{
NSString *classString;
Class klazz;
if ([mimeType isEqualToString: @"image/gif"]
|| [mimeType isEqualToString: @"image/png"]
|| [mimeType isEqualToString: @"image/jpg"])
classString = @"SOGoImageMailBodyPart";
else if ([mimeType isEqualToString: @"text/calendar"])
classString = @"SOGoCalendarMailBodyPart";
else if ([mimeType isEqualToString: @"text/x-vcard"])
classString = @"SOGoVCardMailBodyPart";
else if ([mimeType isEqualToString: @"message/rfc822"])
classString = @"SOGoMessageMailBodyPart";
else
{
NSLog (@"unhandled mime type: '%@'", mimeType);
classString = nil;
}
if (classString)
klazz = NSClassFromString (classString);
else
klazz = Nil;
return klazz;
}
/* etag support */ /* etag support */
- (id)davEntityTag { - (id)davEntityTag {

View file

@ -735,8 +735,22 @@ static BOOL debugSoParts = NO;
{ {
// TODO: we might want to check for existence prior controller creation // TODO: we might want to check for existence prior controller creation
Class clazz; Class clazz;
NSArray *parts;
int part;
NSDictionary *partDesc;
NSString *mimeType;
clazz = [SOGoMailBodyPart bodyPartClassForKey:_key inContext:_ctx]; parts = [[self bodyStructure] objectForKey: @"parts"];
part = [_key intValue] - 1;
if (part > -1 && part < [parts count])
{
partDesc = [parts objectAtIndex: part];
mimeType = [[partDesc keysWithFormat: @"%{type}/%{subtype}"] lowercaseString];
clazz = [SOGoMailBodyPart bodyPartClassForMimeType: mimeType
inContext: _ctx];
}
else
clazz = Nil;
return [clazz objectWithName:_key inContainer: self]; return [clazz objectWithName:_key inContainer: self];
} }

View file

@ -17,15 +17,17 @@ Organizer = "Organisateur";
Time = "Time"; Time = "Time";
Attendees = "Attendees"; Attendees = "Attendees";
request_info = "invites you to participate in a meeting."; request_info = "invites you to participate in a meeting.";
do_add_to_cal = "add to calendar"; "Add to calendar" = "Add to calendar";
do_del_from_cal = "delete from calendar"; "Delete from calendar" = "Delete from calendar";
do_accept = "accept"; Accept = "Accept";
do_decline = "decline"; Decline = "Decline";
do_tentative = "tentative"; Tentative = "Tentative";
do_update_status = "update status in calendar"; "Update status in calendar" = "Update status in calendar";
reply_info_no_attendee = "You received a reply to a scheduling event but the sender of the reply is not a participant."; reply_info_no_attendee = "You received a reply to a scheduling event but the sender of the reply is not a participant.";
reply_info = "This is a reply to an event invitation done by you."; reply_info = "This is a reply to an event invitation done by you.";
"to" = "to";
"Untitled" = "Untitled"; "Untitled" = "Untitled";
"Size" = "Size"; "Size" = "Size";

View file

@ -17,15 +17,17 @@ Organizer = "Organisateur";
Time = "Date"; Time = "Date";
Attendees = "Invités"; Attendees = "Invités";
request_info = "vous invite à une réunion."; request_info = "vous invite à une réunion.";
do_add_to_cal = "ajouter à l'agenda"; "Add to calendar" = "Ajouter à l'agenda";
do_del_from_cal = "effacer de l'agenda"; "Delete from calendar" = "Effacer de l'agenda";
do_accept = "accepter"; Accept = "Accepter";
do_decline = "decliner"; Decline = "Decliner";
do_tentative = "tentative"; Tentative = "Tentative";
do_update_status = "mettre l'agenda à jour"; "Update status in calendar" = "Mettre l'agenda à jour";
reply_info_no_attendee = "Vous avez reçu une réponse à un événement mais l'expéditeur n'est pas un invité."; reply_info_no_attendee = "Vous avez reçu une réponse à un événement mais l'expéditeur n'est pas un invité.";
reply_info = "Ceci est une réponse à un événement que vous avez organisé."; reply_info = "Ceci est une réponse à un événement que vous avez organisé.";
"to" = "à";
"Untitled" = "Sans titre"; "Untitled" = "Sans titre";
"Size" = "Taille"; "Size" = "Taille";

View file

@ -17,15 +17,17 @@ Organizer = "Organisateur";
Time = "Time"; Time = "Time";
Attendees = "Attendees"; Attendees = "Attendees";
request_info = "invites you to participate in a meeting."; request_info = "invites you to participate in a meeting.";
do_add_to_cal = "add to calendar"; "Add to calendar" = "Add to calendar";
do_del_from_cal = "delete from calendar"; "Delete from calendar" = "Delete from calendar";
do_accept = "accept"; Accept = "Accept";
do_decline = "decline"; Decline = "Decline";
do_tentative = "tentative"; Tentative = "Tentative";
do_update_status = "update status in calendar"; "Update status in calendar" = "Update status in calendar";
reply_info_no_attendee = "You received a reply to a scheduling event but the sender of the reply is not a participant."; reply_info_no_attendee = "You received a reply to a scheduling event but the sender of the reply is not a participant.";
reply_info = "This is a reply to an event invitation done by you."; reply_info = "This is a reply to an event invitation done by you.";
"to" = "to";
"Untitled" = "Untitled"; "Untitled" = "Untitled";
"Size" = "Size"; "Size" = "Size";

View file

@ -1,76 +1,63 @@
/* /* UIxMailPartICalAction.m - this file is part of SOGo
Copyright (C) 2005 SKYRIX Software AG *
* Copyright (C) 2007 Inverse groupe conseil
This file is part of OpenGroupware.org. *
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
OGo is free software; you can redistribute it and/or modify it under *
the terms of the GNU Lesser General Public License as published by the * This file is free software; you can redistribute it and/or modify
Free Software Foundation; either version 2, or (at your option) any * it under the terms of the GNU General Public License as published by
later version. * the Free Software Foundation; either version 2, or (at your option)
* any later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY *
WARRANTY; without even the implied warranty of MERCHANTABILITY or * This file is distributed in the hope that it will be useful,
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * but WITHOUT ANY WARRANTY; without even the implied warranty of
License for more details. * 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 Lesser General Public *
License along with OGo; see the file COPYING. If not, write to the * You should have received a copy of the GNU General Public License
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA * along with this program; see the file COPYING. If not, write to
02111-1307, USA. * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/ */
#import <NGObjWeb/SoObject.h> #import <Foundation/NSString.h>
#import <NGObjWeb/WOContext.h>
#import <NGObjWeb/WOResponse.h>
#import <NGObjWeb/WODirectAction.h> #import <NGObjWeb/WODirectAction.h>
#import <NGExtensions/NSNull+misc.h>
#import <NGExtensions/NSString+misc.h> #import <UI/Common/WODirectAction+SOGo.h>
@interface UIxMailPartICalAction : WODirectAction @interface UIxMailPartICalAction : WODirectAction
@end @end
@implementation UIxMailPartICalAction @implementation UIxMailPartICalAction
- (id)redirectToViewerWithError:(NSString *)_error { - (WOResponse *) _changePartStatusAction: (NSString *) _newStatus
WOResponse *r; {
NSString *viewURL; return [self responseWithStatus: 404];
id mail;
mail = [[self clientObject] valueForKey:@"mailObject"];
[self logWithFormat:@"MAIL: %@", mail];
viewURL = [mail baseURLInContext:[self context]];
[self logWithFormat:@" url: %@", viewURL];
viewURL = [viewURL stringByAppendingString:
[viewURL hasSuffix:@"/"] ? @"view" : @"/view"];
if ([_error isNotNull] && [_error length] > 0) {
viewURL = [viewURL stringByAppendingString:@"?error="];
viewURL = [viewURL stringByAppendingString:
[_error stringByEscapingURL]];
} }
r = [[self context] response]; - (WOResponse *) markAcceptedAction
[r setStatus:302 /* moved */]; {
[r setHeader:viewURL forKey:@"location"]; return [self _changePartStatusAction: @"ACCEPTED"];
return r;
} }
- (id)changePartStatusAction:(NSString *)_newStatus { - (WOResponse *) markDeclinedAction
[self logWithFormat:@"TODO: should %@: %@", _newStatus, [self clientObject]]; {
return [self redirectToViewerWithError: return [self _changePartStatusAction: @"DECLINED"];
[_newStatus stringByAppendingString:@" not implemented!"]];
} }
- (id)markAcceptedAction { - (WOResponse *) markTentativeAction
return [self changePartStatusAction:@"ACCEPTED"]; {
return [self _changePartStatusAction: @"TENTATIVE"];
} }
- (id)markDeclinedAction {
return [self changePartStatusAction:@"DECLINED"]; - (WOResponse *) addToCalendarAction
{
return [self responseWithStatus: 404];
} }
- (id)markTentativeAction {
return [self changePartStatusAction:@"TENTATIVE"]; - (WOResponse *) deleteFromCalendarAction
{
return [self responseWithStatus: 404];
} }
@end /* UIxMailPartICalAction */ @end /* UIxMailPartICalAction */

View file

@ -46,34 +46,37 @@
@implementation UIxMailPartICalViewer @implementation UIxMailPartICalViewer
- (void)dealloc { - (void) dealloc
[self->storedEventObject release]; {
[self->storedEvent release]; [storedEventObject release];
[self->attendee release]; [storedEvent release];
[self->item release]; [attendee release];
[self->inCalendar release]; [item release];
[self->inEvent release]; [inCalendar release];
[self->dateFormatter release]; [inEvent release];
[dateFormatter release];
[super dealloc]; [super dealloc];
} }
/* maintain caches */ /* maintain caches */
- (void)resetPathCaches { - (void) resetPathCaches
{
[super resetPathCaches]; [super resetPathCaches];
[self->inEvent release]; self->inEvent = nil; [inEvent release]; inEvent = nil;
[self->inCalendar release]; self->inCalendar = nil; [inCalendar release]; inCalendar = nil;
[self->storedEventObject release]; self->storedEventObject = nil; [storedEventObject release]; storedEventObject = nil;
[self->storedEvent release]; self->storedEvent = nil; [storedEvent release]; storedEvent = nil;
/* not strictly path-related, but useless without it anyway: */ /* not strictly path-related, but useless without it anyway: */
[self->attendee release]; self->attendee = nil; [attendee release]; attendee = nil;
[self->item release]; self->item = nil; [item release]; item = nil;
} }
/* raw content handling */ /* raw content handling */
- (NSStringEncoding)fallbackStringEncoding { - (NSStringEncoding) fallbackStringEncoding
{
/* /*
iCalendar invitations sent by Outlook 2002 have the annoying bug that the iCalendar invitations sent by Outlook 2002 have the annoying bug that the
mail states an UTF-8 content encoding but the actual iCalendar content is mail states an UTF-8 content encoding but the actual iCalendar content is
@ -102,52 +105,66 @@
return inCalendar; return inCalendar;
} }
- (BOOL)couldParseCalendar { - (BOOL) couldParseCalendar
{
return [[self inCalendar] isNotNull]; return [[self inCalendar] isNotNull];
} }
- (iCalEvent *)inEvent { - (iCalEvent *) inEvent
{
NSArray *events; NSArray *events;
if (self->inEvent != nil) if (inEvent)
return [self->inEvent isNotNull] ? self->inEvent : nil; return [inEvent isNotNull] ? inEvent : nil;
events = [[self inCalendar] events]; events = [[self inCalendar] events];
if ([events count] > 0) { if ([events count] > 0) {
self->inEvent = [[events objectAtIndex:0] retain]; inEvent = [[events objectAtIndex:0] retain];
return self->inEvent; return inEvent;
} }
else { else {
self->inEvent = [[NSNull null] retain]; inEvent = [[NSNull null] retain];
return nil; return nil;
} }
} }
/* formatters */ /* formatters */
- (SOGoDateFormatter *)dateFormatter { - (SOGoDateFormatter *) dateFormatter
if (self->dateFormatter == nil) { {
if (dateFormatter == nil) {
dateFormatter = [[context activeUser] dateFormatterInContext: context]; dateFormatter = [[context activeUser] dateFormatterInContext: context];
[dateFormatter retain]; [dateFormatter retain];
} }
return self->dateFormatter; return dateFormatter;
} }
/* below is copied from UIxAppointmentView, can we avoid that? */ /* below is copied from UIxAppointmentView, can we avoid that? */
- (void)setAttendee:(id)_attendee { - (void) setAttendee: (id) _attendee
ASSIGN(self->attendee, _attendee); {
ASSIGN(attendee, _attendee);
} }
- (id)attendee {
return self->attendee; - (id) attendee
{
return attendee;
} }
- (NSString *) _personForDisplay: (iCalPerson *) person - (NSString *) _personForDisplay: (iCalPerson *) person
{ {
return [NSString stringWithFormat: @"%@ <%@>", NSString *fn, *email, *result;
[person cnWithoutQuotes],
[person rfc822Email]]; fn = [person cnWithoutQuotes];
email = [person rfc822Email];
if ([fn length])
result = [NSString stringWithFormat: @"%@ <%@>",
fn, email];
else
result = email;
return result;
} }
- (NSString *) attendeeForDisplay - (NSString *) attendeeForDisplay
@ -155,11 +172,14 @@
return [self _personForDisplay: attendee]; return [self _personForDisplay: attendee];
} }
- (void)setItem:(id)_item { - (void) setItem: (id) _item
ASSIGN(self->item, _item); {
ASSIGN(item, _item);
} }
- (id)item {
return self->item; - (id) item
{
return item;
} }
- (NSCalendarDate *) startTime - (NSCalendarDate *) startTime
@ -186,10 +206,13 @@
return date; return date;
} }
- (BOOL)isEndDateOnSameDay { - (BOOL) isEndDateOnSameDay
{
return [[self startTime] isDateOnSameDay:[self endTime]]; return [[self startTime] isDateOnSameDay:[self endTime]];
} }
- (NSTimeInterval)duration {
- (NSTimeInterval) duration
{
return [[self endTime] timeIntervalSinceDate:[self startTime]]; return [[self endTime] timeIntervalSinceDate:[self startTime]];
} }
@ -209,12 +232,13 @@
return [folder lookupName: @"personal" inContext: context acquire: NO]; return [folder lookupName: @"personal" inContext: context acquire: NO];
} }
- (id)storedEventObject { - (id) storedEventObject
{
/* lookup object in the users Calendar */ /* lookup object in the users Calendar */
id calendar; id calendar;
if (self->storedEventObject != nil) if (storedEventObject)
return [self->storedEventObject isNotNull] ? self->storedEventObject : nil; return [storedEventObject isNotNull] ? storedEventObject : nil;
calendar = [self calendarFolder]; calendar = [self calendarFolder];
if ([calendar isKindOfClass:[NSException class]]) { if ([calendar isKindOfClass:[NSException class]]) {
@ -224,7 +248,7 @@
NSString *filename; NSString *filename;
filename = [calendar resourceNameForEventUID:[[self inEvent] uid]]; filename = [calendar resourceNameForEventUID:[[self inEvent] uid]];
if (filename != nil) { if (filename) {
// TODO: When we get an exception, this might be an auth issue meaning // TODO: When we get an exception, this might be an auth issue meaning
// that the UID indeed exists but that the user has no access to // that the UID indeed exists but that the user has no access to
// the object. // the object.
@ -233,21 +257,23 @@
tmp = [calendar lookupName:filename inContext:[self context] acquire:NO]; tmp = [calendar lookupName:filename inContext:[self context] acquire:NO];
if ([tmp isNotNull] && ![tmp isKindOfClass:[NSException class]]) if ([tmp isNotNull] && ![tmp isKindOfClass:[NSException class]])
self->storedEventObject = [tmp retain]; storedEventObject = [tmp retain];
} }
} }
if (self->storedEventObject == nil) if (storedEventObject == nil)
self->storedEventObject = [[NSNull null] retain]; storedEventObject = [[NSNull null] retain];
return self->storedEventObject; return storedEventObject;
} }
- (BOOL)isEventStoredInCalendar { - (BOOL) isEventStoredInCalendar
{
return [[self storedEventObject] isNotNull]; return [[self storedEventObject] isNotNull];
} }
- (iCalEvent *)storedEvent { - (iCalEvent *) storedEvent
{
return (iCalEvent *) [(SOGoAppointmentObject *)[self storedEventObject] component: NO]; return (iCalEvent *) [(SOGoAppointmentObject *)[self storedEventObject] component: NO];
} }
@ -262,14 +288,16 @@
return [identity objectForKey: @"email"]; return [identity objectForKey: @"email"];
} }
- (iCalEvent *)authorativeEvent { - (iCalEvent *) authorativeEvent
{
/* DB is considered master, when in DB, ignore mail organizer */ /* DB is considered master, when in DB, ignore mail organizer */
return [self isEventStoredInCalendar] return [self isEventStoredInCalendar]
? [self storedEvent] ? [self storedEvent]
: [self inEvent]; : [self inEvent];
} }
- (BOOL)isLoggedInUserTheOrganizer { - (BOOL) isLoggedInUserTheOrganizer
{
NSString *loginEMail; NSString *loginEMail;
if ((loginEMail = [self loggedInUserEMail]) == nil) { if ((loginEMail = [self loggedInUserEMail]) == nil) {
@ -280,7 +308,8 @@
return [[self authorativeEvent] isOrganizer:loginEMail]; return [[self authorativeEvent] isOrganizer:loginEMail];
} }
- (BOOL)isLoggedInUserAnAttendee { - (BOOL) isLoggedInUserAnAttendee
{
NSString *loginEMail; NSString *loginEMail;
if ((loginEMail = [self loggedInUserEMail]) == nil) { if ((loginEMail = [self loggedInUserEMail]) == nil) {
@ -309,7 +338,8 @@
/* replies */ /* replies */
- (NGImap4EnvelopeAddress *)replySenderAddress { - (NGImap4EnvelopeAddress *) replySenderAddress
{
/* /*
The iMIP reply is the sender of the mail, the 'attendees' are NOT set to The iMIP reply is the sender of the mail, the 'attendees' are NOT set to
the actual attendees. BUT the attendee field contains the reply-status! the actual attendees. BUT the attendee field contains the reply-status!
@ -321,14 +351,18 @@
return [tmp objectAtIndex:0]; return [tmp objectAtIndex:0];
} }
- (NSString *)replySenderEMail { - (NSString *) replySenderEMail
{
return [[self replySenderAddress] email]; return [[self replySenderAddress] email];
} }
- (NSString *)replySenderBaseEMail {
- (NSString *) replySenderBaseEMail
{
return [[self replySenderAddress] baseEMail]; return [[self replySenderAddress] baseEMail];
} }
- (iCalPerson *)inReplyAttendee { - (iCalPerson *) inReplyAttendee
{
NSArray *attendees; NSArray *attendees;
attendees = [[self inEvent] attendees]; attendees = [[self inEvent] attendees];
@ -339,7 +373,9 @@
return [attendees objectAtIndex:0]; return [attendees objectAtIndex:0];
} }
- (iCalPerson *)storedReplyAttendee {
- (iCalPerson *) storedReplyAttendee
{
/* /*
TODO: since an attendee can have multiple email addresses, maybe we TODO: since an attendee can have multiple email addresses, maybe we
should translate the email to an internal uid and then retrieve should translate the email to an internal uid and then retrieve
@ -350,28 +386,22 @@
iCalEvent *e; iCalEvent *e;
iCalPerson *p; iCalPerson *p;
if ((e = [self storedEvent]) == nil) p = nil;
return nil;
if ((p = [e findParticipantWithEmail:[self replySenderBaseEMail]])) e = [self storedEvent];
return p; if (e)
if ((p = [e findParticipantWithEmail:[self replySenderEMail]])) {
return p; p = [e findParticipantWithEmail: [self replySenderBaseEMail]];
return nil; if (!p)
p = [e findParticipantWithEmail:[self replySenderEMail]];
} }
- (BOOL)isReplySenderAnAttendee {
return p;
}
- (BOOL) isReplySenderAnAttendee
{
return [[self storedReplyAttendee] isNotNull]; return [[self storedReplyAttendee] isNotNull];
} }
/* action URLs */
- (id)acceptLink {
return [[self pathToAttachmentObject] stringByAppendingString:@"/accept"];
}
- (id)declineLink {
return [[self pathToAttachmentObject] stringByAppendingString:@"/decline"];
}
- (id)tentativeLink {
return [[self pathToAttachmentObject] stringByAppendingString:@"/tentative"];
}
@end /* UIxMailPartICalViewer */ @end /* UIxMailPartICalViewer */

View file

@ -25,6 +25,16 @@
actionClass = "UIxMailPartICalAction"; actionClass = "UIxMailPartICalAction";
actionName = "markTentative"; actionName = "markTentative";
}; };
addToCalendar = {
protectedBy = "View";
actionClass = "UIxMailPartICalAction";
actionName = "addToCalendar";
};
deleteFromCalendar = {
protectedBy = "View";
actionClass = "UIxMailPartICalAction";
actionName = "deleteFromCalendar";
};
}; };
}; };
}; };

View file

@ -1,4 +1,5 @@
<?xml version="1.0" standalone="yes"?> <?xml version="1.0" standalone="yes"?>
<!DOCTYPE div>
<div xmlns="http://www.w3.org/1999/xhtml" <div xmlns="http://www.w3.org/1999/xhtml"
xmlns:var="http://www.skyrix.com/od/binding" xmlns:var="http://www.skyrix.com/od/binding"
xmlns:label="OGo:label" xmlns:label="OGo:label"
@ -32,16 +33,21 @@
</var:if> </var:if>
</legend> </legend>
<var:if condition="inCalendar.method" const:value="REQUEST">
<!-- var:if condition="inCalendar.method" const:value="REQUEST" -->
<!-- sent to attendees to propose or update a meeting --> <!-- sent to attendees to propose or update a meeting -->
<var:if condition="isLoggedInUserAnAttendee"> <var:if condition="isLoggedInUserAnAttendee">
<p class="uix_ical_toolbar"> <p class="uix_ical_toolbar" id="iCalendarToolbar">
<a var:href="acceptLink" label:string="do_accept"/> | <input id="iCalendarAttachment" type="hidden"
<a var:href="declineLink" label:string="do_decline"/> | var:value="pathToAttachmentObject"/>
<a var:href="tentativeLink" label:string="do_tentative"/> <input id="iCalendarAccept" class="button"
<var:if condition="isEventStoredInCalendar" const:negate="1"> type="button" label:value="Accept"/>
| <a var:href="addToCalendarLink" label:string="do_add_to_cal" /> <input id="iCalendarDecline" class="button"
type="button" label:value="Decline"/>
<input id="iCalendarTentative" class="button"
type="button" label:value="Tentative"/>
<var:if condition="isEventStoredInCalendar" const:negate="YES">
| <input id="iCalendarAddToCalendar" class="button"
type="button" label:value="Add to calendar"/>
</var:if> </var:if>
</p> </p>
@ -53,7 +59,7 @@
</p> </p>
</var:if> </var:if>
<var:if condition="isLoggedInUserAnAttendee" const:negate="1"> <var:if condition="isLoggedInUserAnAttendee" const:negate="YES">
<p> <p>
<var:string label:value="Organizer" /> <var:string label:value="Organizer" />
<a var:href="inEvent.organizer.email" <a var:href="inEvent.organizer.email"
@ -61,7 +67,7 @@
<var:string label:value="request_info_no_attendee" /> <var:string label:value="request_info_no_attendee" />
</p> </p>
</var:if> </var:if>
<!-- var:if --> </var:if>
<var:if condition="inCalendar.method" const:value="REPLY"> <var:if condition="inCalendar.method" const:value="REPLY">
@ -90,13 +96,13 @@
</var:if> </var:if>
</var:if> </var:if>
<var:if condition="inCalendar.method" const:value="CANCEL"> <var:if condition="inCalendar.method" const:value="CANCEL">
<!-- sent to attendees to notify of the attendee being removed or the <!-- sent to attendees to notify of the attendee being removed or the
event being deleted --> event being deleted -->
<var:if condition="isEventStoredInCalendar"> <var:if condition="isEventStoredInCalendar">
<p class="uix_ical_toolbar"> <p class="uix_ical_toolbar">
<a var:href="delFromCalendarLink" label:string="do_del_from_cal"/> <input id="iCalendarDeleteFromCalendar" class="button"
type="button" label:value="Delete from calendar"/>
</p> </p>
</var:if> </var:if>
@ -148,7 +154,6 @@
<br /> <br />
</var:if> </var:if>
<div class="linked_attachment_meta" style="background-color: white;"> <div class="linked_attachment_meta" style="background-color: white;">
<table border="0" class="linked_attachment_meta"> <table border="0" class="linked_attachment_meta">
<tr> <tr>

View file

@ -9,7 +9,7 @@ if (typeof textMailAccounts != 'undefined') {
mailAccounts = new Array(); mailAccounts = new Array();
} }
var currentMessages = new Array(); var currentMessages = {};
var maxCachedMessages = 20; var maxCachedMessages = 20;
var cachedMessages = new Array(); var cachedMessages = new Array();
var currentMailbox = null; var currentMailbox = null;
@ -743,13 +743,56 @@ function configureLinksInMessage() {
if (editDraftButton) if (editDraftButton)
Event.observe(editDraftButton, "click", Event.observe(editDraftButton, "click",
onMessageEditDraft.bindAsEventListener(editDraftButton)); onMessageEditDraft.bindAsEventListener(editDraftButton));
configureiCalLinksInMessage();
}
function configureiCalLinksInMessage() {
var buttons = { "iCalendarAccept": "accept",
"iCalendarDecline": "decline",
"iCalendarTentative": "tentative",
"iCalendarAddToCalendar": "addToCalendar",
"iCalendarDeleteFromCalendar": "deleteFromCalendar" };
for (var key in buttons) {
var button = $(key);
if (button) {
button.action = buttons[key];
Event.observe(button, "click",
onICalendarButtonClick.bindAsEventListener(button));
}
}
}
function onICalendarButtonClick(event) {
var link = $("iCalendarAttachment").value;
if (link) {
var urlstr = link + "/" + this.action;
triggerAjaxRequest(urlstr, ICalendarButtonCallback,
currentMailbox + "/"
+ currentMessages[currentMailbox]);
window.alert(urlstr);
}
}
function ICalendarButtonCallback(http) {
if (http.readyState == 4)
if (isHttpStatus204(http.status)) {
var oldMsg = http.callbackData;
var msg = currentMailbox + "/" + currentMessages[currentMailbox];
if (oldMsg == msg) {
deleteCachedMessage(oldMsg);
loadMessage(currentMessages[currentMailbox]);
}
}
} }
function resizeMailContent() { function resizeMailContent() {
var headerTable = document.getElementsByClassName('mailer_fieldtable')[0]; var headerTable = document.getElementsByClassName('mailer_fieldtable')[0];
var contentDiv = document.getElementsByClassName('mailer_mailcontent')[0]; var contentDiv = document.getElementsByClassName('mailer_mailcontent')[0];
contentDiv.setStyle({ 'top': (Element.getHeight(headerTable) + headerTable.offsetTop) + 'px' }); contentDiv.setStyle({ 'top':
(Element.getHeight(headerTable) + headerTable.offsetTop) + 'px' });
} }
function onMessageContentMenu(event) { function onMessageContentMenu(event) {