2005-07-15 Helge Hess <helge.hess@opengroupware.org>
+ * v0.9.11
+
+ * added UIxMailPartICalAction for calendar part related link actions
+ (no actions implemented yet)
+
+ * UIxMailPartViewer.m: added preferred extensions for iCalendar and
+ vCard mime types, moved in -pathToAttachment from
+ UIxMailPartLinkViewer (returns a nice download-link), added
+ -pathToAttachmentObject method (returns a plain link to the part
+ SoObject)
+
+ * UIxMailPartLinkViewer.m: moved -pathToAttachment method to baseclass
+
* UIxMailPartICalViewer.m: added method to retrieve the authorative
event (DB before mail), added a method to return an organizer display
name (with appropriate fallbacks) (v0.9.10)
-2005-07-15 Helge Hess <helge.hess@opengroupware.org>
-
* UIxMailPartICalViewer.m: rewrote not to use SOGoAppointment and to
use iCalCalendar instead (v0.9.9)
-2005-07-15 Helge Hess <helge.hess@opengroupware.org>
-
* UIxMailSizeFormatter.m, UIxMailPartMixedViewer.m,
UIxMailPartICalViewer.m, UIxMailPartAlternativeViewer.m,
UIxMailPartViewer.m: fixed gcc 4.0 warnings (v0.9.8)
UIxMailPartMessageViewer.m \
UIxMailPartICalViewer.m \
UIxMailPartHTMLViewer.m \
+ \
+ UIxMailPartICalAction.m \
MailPartViewers_RESOURCE_FILES += \
Version \
--- /dev/null
+/*
+ Copyright (C) 2005 SKYRIX Software AG
+
+ This file is part of OpenGroupware.org.
+
+ 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
+ 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
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 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
+ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+*/
+
+#include <NGObjWeb/WODirectAction.h>
+
+@interface UIxMailPartICalAction : WODirectAction
+@end
+
+#include "common.h"
+
+@implementation UIxMailPartICalAction
+
+- (id)redirectToViewerWithError:(NSString *)_error {
+ WOResponse *r;
+ NSString *viewURL;
+ 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];
+ [r setStatus:302 /* moved */];
+ [r setHeader:viewURL forKey:@"location"];
+ return r;
+}
+
+- (id)changePartStatusAction:(NSString *)_newStatus {
+ [self logWithFormat:@"TODO: should %@: %@", _newStatus, [self clientObject]];
+ return [self redirectToViewerWithError:
+ [_newStatus stringByAppendingString:@" not implemented!"]];
+}
+
+- (id)markAcceptedAction {
+ return [self changePartStatusAction:@"ACCEPTED"];
+}
+- (id)markDeclinedAction {
+ return [self changePartStatusAction:@"DECLINED"];
+}
+- (id)markTentativeAction {
+ return [self changePartStatusAction:@"TENTATIVE"];
+}
+
+@end /* UIxMailPartICalAction */
return @"[todo: no organizer set, use 'from']";
}
+/* 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 */
@implementation UIxMailPartLinkViewer
-/* URLs */
-
-- (NSString *)pathToAttachment {
- NSString *url, *n, *pext;
-
- pext = [self preferredPathExtension];
-
- /* path to mail controller object */
-
- url = [[self clientObject] baseURLInContext:[self context]];
- if (![url hasSuffix:@"/"]) url = [url stringByAppendingString:@"/"];
-
- /* mail relative path to body-part */
-
- if ([(n = [[self partPath] componentsJoinedByString:@"/"]) isNotNull]) {
- /* eg this was nil for a draft containing an HTML message */
- url = [url stringByAppendingString:n];
- }
-
- if ([pext isNotNull] && [pext length] > 0) {
- /* attach extension */
- url = [url stringByAppendingString:@"."];
- url = [url stringByAppendingString:pext];
- }
-
- /*
- If we have an attachment name, we attach it, this is properly handled by
- SOGoMailBodyPart.
- */
-
- n = [self filenameForDisplay];
- if ([n isNotNull] && [n length] > 0) {
- url = [url stringByAppendingString:@"/"];
- if (isdigit([n characterAtIndex:0]))
- url = [url stringByAppendingString:@"fn-"];
- url = [url stringByAppendingString:[n stringByEscapingURL]];
-
- // TODO: should we check for a proper extension?
- }
-
- return url;
-}
@end /* UIxMailPartLinkViewer */
- (void)resetPathCaches;
- (void)resetBodyInfoCaches;
+/* part URLs */
+
+- (NSString *)pathToAttachmentObject; /* link to SoObject */
+- (NSString *)pathToAttachment; /* download link */
+
@end
#endif /* __Mailer_UIxMailPartViewer_H__ */
if ([_st isEqualToString:@"png"]) return @"png";
}
else if ([_mt isEqualToString:@"text"]) {
- if ([_st isEqualToString:@"plain"]) return @"txt";
- if ([_st isEqualToString:@"xml"]) return @"xml";
+ if ([_st isEqualToString:@"plain"]) return @"txt";
+ if ([_st isEqualToString:@"xml"]) return @"xml";
+ if ([_st isEqualToString:@"calendar"]) return @"ics";
+ if ([_st isEqualToString:@"x-vcard"]) return @"vcf";
}
else if ([_mt isEqualToString:@"message"]) {
if ([_st isEqualToString:@"rfc822"]) return @"mail";
if ((s = [self filename]) != nil)
return s;
-
+
s = [[self partPath] componentsJoinedByString:@"-"];
- return [@"untitled-" stringByAppendingString:s];
+ return ([s length] > 0)
+ ? [@"untitled-" stringByAppendingString:s]
+ : @"untitled";
}
- (NSFormatter *)sizeFormatter {
return [UIxMailSizeFormatter sharedMailSizeFormatter];
}
+/* URL generation */
+
+- (NSString *)pathToAttachmentObject {
+ /* this points to the SoObject representing the part, no modifications */
+ NSString *url, *n, *pext;
+
+ /* path to mail controller object */
+
+ url = [[self clientObject] baseURLInContext:[self context]];
+ if (![url hasSuffix:@"/"]) url = [url stringByAppendingString:@"/"];
+
+ /* mail relative path to body-part */
+
+ if ([(n = [[self partPath] componentsJoinedByString:@"/"]) isNotNull]) {
+ /* eg this was nil for a draft containing an HTML message */
+ url = [url stringByAppendingString:n];
+ }
+
+ /* we currently NEED the extension for SoObject lookup (should be fixed) */
+
+ pext = [self preferredPathExtension];
+ if ([pext isNotNull] && [pext length] > 0) {
+ /* attach extension */
+ if ([url hasSuffix:@"/"]) {
+ /* this happens if the part is the root-content of the mail */
+ url = [url substringToIndex:([url length] - 1)];
+ }
+ url = [url stringByAppendingString:@"."];
+ url = [url stringByAppendingString:pext];
+ }
+
+ return url;
+}
+
+- (NSString *)pathToAttachment {
+ /* this generates a more beautiful 'download' URL for a part */
+ NSString *url, *fn;
+
+ fn = [self filename];
+
+ if (![fn isNotNull] || ([fn length] == 0))
+ fn = nil;
+
+ /* get basic URL */
+
+ url = [self pathToAttachmentObject];
+
+ /*
+ If we have an attachment name, we attach it, this is properly handled by
+ SOGoMailBodyPart.
+ */
+
+ if (fn != nil) {
+ if (![url hasSuffix:@"/"]) url = [url stringByAppendingString:@"/"];
+ if (isdigit([fn characterAtIndex:0]))
+ url = [url stringByAppendingString:@"fn-"];
+ url = [url stringByAppendingString:[fn stringByEscapingURL]];
+
+ // TODO: should we check for a proper extension?
+ }
+
+ return url;
+}
+
@end /* UIxMailPartViewer */
# version file
-SUBMINOR_VERSION:=10
+SUBMINOR_VERSION:=11
# v0.9.0 requires libNGiCal v4.5.53
# v0.9.1 requires libNGMime v4.5.213
};
categories = {
+ SOGoCalendarMailBodyPart = {
+ methods = {
+ accept = {
+ protectedBy = "View";
+ actionClass = "UIxMailPartICalAction";
+ actionName = "markAccepted";
+ };
+ decline = {
+ protectedBy = "View";
+ actionClass = "UIxMailPartICalAction";
+ actionName = "markDeclined";
+ };
+ tentative = {
+ protectedBy = "View";
+ actionClass = "UIxMailPartICalAction";
+ actionName = "markTentative";
+ };
+ };
+ };
};
}
(<var:string label:value="you are an attendee"/>)
</var:if>
</legend>
+
+ <p>
+ <a var:href="acceptLink" >accept</a> |
+ <a var:href="declineLink" >decline</a> |
+ <a var:href="tentativeLink">tentative</a>
+ </p>
+
+ <var:if condition="isEventStoredInCalendar" const:negate="1">
+ <!--
+ TODO: check whether the user is a participant or organizer, otherwise
+ he won't see the event!
+ -->
+ <p>
+ The event is not in your primary calendar:
+ <a var:href="addToCalendarLink">add to calendar</a>.
+ </p>
+ </var:if>
+ <!-- TODO: show _parent link to jump to the calendar entry -->
<var:if condition="inCalendar.method" const:value="REQUEST">
<!-- sent to attendees to propose or update a meeting -->
<var:if condition="isLoggedInUserAnAttendee">
<p>
- Organizer <var:string value="organizerDisplayName" />
+ Organizer
+ <a var:href="inEvent.organizer.email"
+ ><var:string value="organizerDisplayName" /></a>
invites you to participate in a meeting.
</p>
<!-- TODO: buttons: accept/decline/tentatively -->
<var:if condition="isLoggedInUserAnAttendee" const:negate="1">
<p>
- Organizer <var:string value="organizerDisplayName" />
+ Organizer
+ <a var:href="inEvent.organizer.email"
+ ><var:string value="organizerDisplayName" /></a>
is proposing a meeting to the attendees. You receive this
mail as a notification, you are not scheduled as a participant.
</p>
<var:if condition="inCalendar.method" const:value="REPLY">
<!-- sent to organizer to update the status of the participant -->
<p>
- iMIP 'DELETE' requests are not yet supported by SOGo.
+ iMIP 'REPLY' requests are not yet supported by SOGo.
</p>
</var:if>
<var:if condition="inCalendar.method" const:value="PUBLISH">
<!-- none-scheduling event sent to someone for adding to the calendar -->
</var:if>
-
- TODO: Storage:
- <var:if condition="isEventStoredInCalendar">
- <var:string label:value="The event is in your calendar." />
- <!-- var:string value="storedEventObject" / -->
-
- <!-- todo: show core info + differences -->
- </var:if>
- <var:if condition="isEventStoredInCalendar" const:negate="1">
- <var:string label:value="The event is not in your calendar." />
-
- <!-- TODO: show "add to calendar" toolbar button -->
- </var:if>
- <br />
-
+
<var:if condition="isLoggedInUserTheOrganizer">
<!--
Possible Status: