From: wolfgang Date: Fri, 27 Jul 2007 20:07:06 +0000 (+0000) Subject: git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1127 d1b88da0-ebda-0310... X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ddfde35f210f69ef6ba1b92dbd0ba990a8476698;p=scalable-opengroupware.org git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1127 d1b88da0-ebda-0310-925b-ed51d893ca5b --- diff --git a/ChangeLog b/ChangeLog index 9f2d6069..08cf853e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,28 @@ 2007-07-27 Wolfgang Sourdeau + * UI/MailerUI/UIxMailForwardAction.m ([UIxMailForwardAction + -forwardAction]): adapted to the new saveAttachment:withMetadata: + method (see below). + + * UI/MailerUI/UIxMailEditor.m ([UIxMailEditor -saveAction]): added + code to save the attached filenames with the filename returned by + the web server as well as their mime types. + + * UI/MailPartViewers/UIxMailPartMessageViewer.m ([UIxMailPartMessageViewer -fromAddresses]) + ([UIxMailPartMessageViewer -toAddresses]) + ([UIxMailPartMessageViewer -ccAddresses]): new methods returning + the corresponding fields separated with a ", " (if needed). + + * SoObjects/Mailer/SOGoDraftObject.m ([SOGoDraftObject + -saveAttachment:_attachwithMetadata:metadata]): new method + replacing -saveAttachment:withName: and which takes a dictionary + as parameter with the filename and the mime type of the + attachment. + The mimetype is then saved in a hidden text file. + ([SOGoDraftObject -contentTypeForAttachmentWithName:]): if exists, + take the mime type from the hidden text file related to the + attachment. + * SoObjects/Contacts/SOGoContactGCSFolder.m () ([SOGoContactGCSFolder -lookupContactsWithFilter:filtersortBy:sortKeyordering:sortOrdering]): diff --git a/SoObjects/Mailer/SOGoDraftObject.h b/SoObjects/Mailer/SOGoDraftObject.h index b3b635da..1292c508 100644 --- a/SoObjects/Mailer/SOGoDraftObject.h +++ b/SoObjects/Mailer/SOGoDraftObject.h @@ -55,7 +55,8 @@ - (NSArray *)fetchAttachmentNames; - (BOOL)isValidAttachmentName:(NSString *)_name; -- (NSException *)saveAttachment:(NSData *)_attach withName:(NSString *)_name; +- (NSException *) saveAttachment: (NSData *)_attach + withMetadata: (NSDictionary *) metadata; - (NSException *)deleteAttachmentWithName:(NSString *)_name; /* NGMime representations */ diff --git a/SoObjects/Mailer/SOGoDraftObject.m b/SoObjects/Mailer/SOGoDraftObject.m index 8bd8ab98..999e1f32 100644 --- a/SoObjects/Mailer/SOGoDraftObject.m +++ b/SoObjects/Mailer/SOGoDraftObject.m @@ -257,8 +257,10 @@ static BOOL showTextAttachmentsInline = NO; reason:@"Invalid attachment name!"]; } -- (NSException *)saveAttachment:(NSData *)_attach withName:(NSString *)_name { - NSString *p; +- (NSException *) saveAttachment: (NSData *) _attach + withMetadata: (NSDictionary *) metadata +{ + NSString *p, *name, *mimeType; if (![_attach isNotNull]) { return [NSException exceptionWithHTTPStatus:400 /* Bad Request */ @@ -269,14 +271,29 @@ static BOOL showTextAttachmentsInline = NO; return [NSException exceptionWithHTTPStatus:500 /* Server Error */ reason:@"Could not create folder for draft!"]; } - if (![self isValidAttachmentName:_name]) - return [self invalidAttachmentNameError:_name]; + name = [metadata objectForKey: @"filename"]; + if (![self isValidAttachmentName: name]) + return [self invalidAttachmentNameError: name]; - p = [self pathToAttachmentWithName:_name]; - if (![_attach writeToFile:p atomically:YES]) { - return [NSException exceptionWithHTTPStatus:500 /* Server Error */ - reason:@"Could not write attachment to draft!"]; - } + p = [self pathToAttachmentWithName: name]; + if (![_attach writeToFile: p atomically: YES]) + { + return [NSException exceptionWithHTTPStatus:500 /* Server Error */ + reason:@"Could not write attachment to draft!"]; + } + + mimeType = [metadata objectForKey: @"mime-type"]; + if ([mimeType length] > 0) + { + p = [self pathToAttachmentWithName: + [NSString stringWithFormat: @".%@.mime", name]]; + if (![[mimeType dataUsingEncoding: NSUTF8StringEncoding] + writeToFile: p atomically: YES]) + { + return [NSException exceptionWithHTTPStatus:500 /* Server Error */ + reason:@"Could not write attachment to draft!"]; + } + } return nil; /* everything OK */ } @@ -383,14 +400,28 @@ static BOOL showTextAttachmentsInline = NO; } - (NSString *)contentTypeForAttachmentWithName:(NSString *)_name { - NSString *s; + NSString *s, *p; + NSData *mimeData; - s = [self mimeTypeForExtension:[_name pathExtension]]; - if ([_name length] > 0) - s = [s stringByAppendingFormat:@"; name=\"%@\"", _name]; + p = [self pathToAttachmentWithName: + [NSString stringWithFormat: @".%@.mime", _name]]; + mimeData = [NSData dataWithContentsOfFile: p]; + if (mimeData) + { + s = [[NSString alloc] initWithData: mimeData + encoding: NSUTF8StringEncoding]; + [s autorelease]; + } + else + { + s = [self mimeTypeForExtension:[_name pathExtension]]; + if ([_name length] > 0) + s = [s stringByAppendingFormat:@"; name=\"%@\"", _name]; + } return s; } + - (NSString *)contentDispositionForAttachmentWithName:(NSString *)_name { NSString *type; NSString *cdtype; diff --git a/UI/MailPartViewers/UIxMailPartMessageViewer.m b/UI/MailPartViewers/UIxMailPartMessageViewer.m index 4f05c58f..3a18cb76 100644 --- a/UI/MailPartViewers/UIxMailPartMessageViewer.m +++ b/UI/MailPartViewers/UIxMailPartMessageViewer.m @@ -10,40 +10,46 @@ 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 + 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 + 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 "UIxMailPartViewer.h" +#import +#import + +#import +#import "UIxMailRenderingContext.h" + +#import "UIxMailPartViewer.h" /* UIxMailPartMessageViewer - Show message/rfc822 mail parts. Note that the IMAP4 server already returns a - proper body structure of the message. - - Relevant body-info keys: - to/sender/from/cc/bcc/in-reply-to/reply-to - array of addr-dicts - type/subtype - message/RFC822 - size - subject - parameterList - dict (eg 'name') - messageId - date - encoding - 7BIT - bodyLines - 83 - bodyId - (empty string?) - description - (empty string?, content-description?) - - body - a body structure? - - Addr-Dict: - hostName / mailboxName / personalName / sourceRoute + Show message/rfc822 mail parts. Note that the IMAP4 server already returns a + proper body structure of the message. + + Relevant body-info keys: + to/sender/from/cc/bcc/in-reply-to/reply-to - array of addr-dicts + type/subtype - message/RFC822 + size + subject + parameterList - dict (eg 'name') + messageId + date + encoding - 7BIT + bodyLines - 83 + bodyId - (empty string?) + description - (empty string?, content-description?) + + body - a body structure? + + Addr-Dict: + hostName / mailboxName / personalName / sourceRoute */ @class NGImap4Envelope; @@ -51,103 +57,126 @@ @interface UIxMailPartMessageViewer : UIxMailPartViewer { NGImap4Envelope *envelope; - id currentAddress; } @end -#include -#include "UIxMailRenderingContext.h" -#include -#include -#include "common.h" - @implementation UIxMailPartMessageViewer -- (void)dealloc { - [self->currentAddress release]; - [self->envelope release]; +- (void) dealloc +{ + [envelope release]; [super dealloc]; } /* cache maintenance */ -- (void)resetBodyInfoCaches { +- (void) resetBodyInfoCaches +{ [super resetBodyInfoCaches]; - [self->envelope release]; self->envelope = nil; - [self->currentAddress release]; self->currentAddress = nil; -} - -/* notifications */ - -- (void)sleep { - [self->currentAddress release]; self->currentAddress = nil; - [super sleep]; -} - -/* accessors */ - -- (void)setCurrentAddress:(id)_addr { - ASSIGN(self->currentAddress, _addr); -} -- (id)currentAddress { - return self->currentAddress; + [envelope release]; envelope = nil; } /* nested body structure */ -- (id)contentInfo { +- (id) contentInfo +{ return [[self bodyInfo] valueForKey:@"body"]; } -- (id)contentPartPath { +- (id) contentPartPath +{ /* Path processing is a bit weird in the context of message/rfc822. If we have a multipart, the multipart itself has no own identifier! Instead the children of the multipart are directly mapped into the message namespace. - + If the message has just a plain content, ids seems to be as expected (that is, its just a "1"). */ - NSArray *pp; + NSArray *pp; NSString *mt; - + mt = [[[self contentInfo] valueForKey:@"type"] lowercaseString]; if ([mt isEqualToString:@"multipart"]) return [self partPath]; - + pp = [self partPath]; - return [pp count] > 0 - ? [pp arrayByAddingObject:@"1"] - : [NSArray arrayWithObject:@"1"]; + return (([pp count] > 0) + ? [pp arrayByAddingObject: @"1"] + : [NSArray arrayWithObject: @"1"]); } -- (id)contentViewerComponent { - id info; - - info = [self contentInfo]; - return [[[self context] mailRenderingContext] viewerForBodyInfo:info]; +- (id) contentViewerComponent +{ + UIxMailRenderingContext *mailContext; + + mailContext = [[self context] mailRenderingContext]; + + return [mailContext viewerForBodyInfo: [self contentInfo]]; } /* generating envelope */ -- (NGImap4Envelope *)envelope { - if (self->envelope == nil) { - self->envelope = [[NGImap4Envelope alloc] initWithBodyStructureInfo: - [self bodyInfo]]; - } - return self->envelope; +- (NGImap4Envelope *) envelope +{ + if (!envelope) + envelope = [[NGImap4Envelope alloc] initWithBodyStructureInfo: + [self bodyInfo]]; + + return envelope; +} + +- (NSString *) formattedComponents: (NSArray *) components +{ + NSMutableArray *formattedComponents; + unsigned int count, max; + NSString *component; + + max = [components count]; + formattedComponents = [NSMutableArray arrayWithCapacity: max]; + for (count = 0; count < max; count++) + { + component = [[components objectAtIndex: count] email]; + [formattedComponents addObject: component]; + } + + return [formattedComponents componentsJoinedByString: @", "]; +} + +- (NSString *) fromAddresses +{ + NSArray *from; + + from = [[self envelope] from]; + + return [self formattedComponents: from]; +} + +- (NSString *) toAddresses +{ + NSArray *to; + + to = [[self envelope] to]; + + return [self formattedComponents: to]; +} + +- (NSString *) ccAddresses +{ + NSArray *cc; + + cc = [[self envelope] cc]; + + return [self formattedComponents: cc]; } /* links to recipients */ -- (NSString *)linkToEnvelopeAddress:(NGImap4EnvelopeAddress *)_address { +- (NSString *) linkToEnvelopeAddress: (NGImap4EnvelopeAddress *) _address +{ // TODO: make some web-link, eg open a new compose panel? return [@"mailto:" stringByAppendingString:[_address baseEMail]]; } -- (NSString *)currentAddressLink { - return [self linkToEnvelopeAddress:[self currentAddress]]; -} - @end /* UIxMailPartMessageViewer */ diff --git a/UI/MailerUI/Toolbars/SOGoDraftObject.toolbar b/UI/MailerUI/Toolbars/SOGoDraftObject.toolbar index d8bba1f0..6355b0a0 100644 --- a/UI/MailerUI/Toolbars/SOGoDraftObject.toolbar +++ b/UI/MailerUI/Toolbars/SOGoDraftObject.toolbar @@ -2,7 +2,7 @@ ( /* first group */ { link = "#"; isSafe = NO; - onclick = "clickedEditorSend(this);return false;"; + onclick = "return clickedEditorSend(this);"; image = "tb-compose-send-flat-24x24.png"; cssClass = "tbicon_send"; label = "Send"; }, @@ -13,13 +13,13 @@ label = "Contacts"; }, { link = "#"; isSafe = NO; - onclick = "clickedEditorAttach(this)"; + onclick = "return clickedEditorAttach(this)"; image = "tb-compose-attach-flat-24x24.png"; cssClass = "tbicon_attach"; label = "Attach"; }, { link = "#"; isSafe = NO; - onclick = "clickedEditorSave(this);return false;"; + onclick = "return clickedEditorSave(this);"; image = "tb-mail-file-flat-24x24.png"; cssClass = "tbicon_save"; label = "Save"; }, diff --git a/UI/MailerUI/UIxMailEditor.m b/UI/MailerUI/UIxMailEditor.m index 6b530be2..ffae1214 100644 --- a/UI/MailerUI/UIxMailEditor.m +++ b/UI/MailerUI/UIxMailEditor.m @@ -25,14 +25,17 @@ #import #import -#import -#import #import #import #import #import #import #import +#import +#import +#import +#import +#import #import #import @@ -77,12 +80,13 @@ static BOOL useLocationBasedSentFolder = NO; static NSDictionary *internetMailHeaders = nil; static NSArray *infoKeys = nil; -+ (void)initialize { ++ (void) initialize +{ NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; infoKeys = [[NSArray alloc] initWithObjects: @"subject", @"text", @"to", @"cc", @"bcc", - @"from", @"replyTo", + @"from", @"replyTo", nil]; keepMailTmpFile = [ud boolForKey:@"SOGoMailEditorKeepTmpFile"]; @@ -95,18 +99,18 @@ static NSArray *infoKeys = nil; /* Internet mail settings */ showInternetMarker = [ud boolForKey:@"SOGoShowInternetMarker"]; - if (!showInternetMarker) { + if (!showInternetMarker) NSLog(@"Note: visual Internet marker on mail editor disabled " @"(SOGoShowInternetMarker)"); - } internetMailHeaders = [[ud dictionaryForKey:@"SOGoInternetMailHeaders"] copy]; - NSLog(@"Note: specified %d headers for mails send via the Internet.", + NSLog (@"Note: specified %d headers for mails send via the Internet.", [internetMailHeaders count]); } -- (void)dealloc { +- (void) dealloc +{ [sentFolder release]; [fromEMails release]; [from release]; @@ -123,68 +127,94 @@ static NSArray *infoKeys = nil; /* accessors */ -- (void)setFrom:(NSString *)_value { +- (void) setFrom: (NSString *) _value +{ ASSIGNCOPY(from, _value); } -- (NSString *)from { + +- (NSString *) from +{ if (![from isNotEmpty]) return [[[self context] activeUser] primaryEmail]; + return from; } -- (void)setReplyTo:(NSString *)_ignore { +- (void) setReplyTo: (NSString *) _ignore +{ } -- (NSString *)replyTo { + +- (NSString *) replyTo +{ /* we are here for future extensibility */ return @""; } -- (void)setSubject:(NSString *)_value { +- (void) setSubject: (NSString *) _value +{ ASSIGNCOPY(subject, _value); } -- (NSString *)subject { + +- (NSString *) subject +{ return subject ? subject : @""; } -- (void)setText:(NSString *)_value { +- (void) setText: (NSString *) _value +{ ASSIGNCOPY(text, _value); } -- (NSString *)text { + +- (NSString *) text +{ return [text isNotNull] ? text : @""; } -- (void)setTo:(NSArray *)_value { +- (void) setTo: (NSArray *)_value +{ ASSIGNCOPY(to, _value); } -- (NSArray *)to { + +- (NSArray *) to +{ return [to isNotNull] ? to : [NSArray array]; } -- (void)setCc:(NSArray *)_value { +- (void) setCc: (NSArray *) _value +{ ASSIGNCOPY(cc, _value); } -- (NSArray *)cc { + +- (NSArray *) cc +{ return [cc isNotNull] ? cc : [NSArray array]; } -- (void)setBcc:(NSArray *)_value { +- (void) setBcc: (NSArray *) _value +{ ASSIGNCOPY(bcc, _value); } -- (NSArray *)bcc { + +- (NSArray *) bcc +{ return [bcc isNotNull] ? bcc : [NSArray array]; } -- (BOOL)hasOneOrMoreRecipients { +- (BOOL) hasOneOrMoreRecipients +{ if ([[self to] count] > 0) return YES; if ([[self cc] count] > 0) return YES; if ([[self bcc] count] > 0) return YES; return NO; } -- (void)setAttachmentName:(NSString *)_attachmentName { +- (void) setAttachmentName: (NSString *) _attachmentName +{ ASSIGN(attachmentName, _attachmentName); } -- (NSString *)attachmentName { + +- (NSString *) attachmentName +{ return attachmentName; } @@ -403,23 +433,96 @@ static NSArray *infoKeys = nil; /* actions */ -- (BOOL)_saveFormInfo { +- (NSDictionary *) _scanAttachmentFilenamesInRequest: (id) httpBody +{ + NSMutableDictionary *filenames; + NSDictionary *attachment; + NSArray *parts; + unsigned int count, max; + NGMimeBodyPart *part; + NGMimeContentDispositionHeaderField *header; + NSString *mimeType; + + parts = [httpBody parts]; + max = [parts count]; + filenames = [NSMutableDictionary dictionaryWithCapacity: max]; + + for (count = 0; count < max; count++) + { + part = [parts objectAtIndex: count]; + header = [part headerForKey: @"content-disposition"]; + mimeType = [[part headerForKey: @"content-type"] stringValue]; + attachment = [NSDictionary dictionaryWithObjectsAndKeys: + [header filename], @"filename", + mimeType, @"mime-type", nil]; + [filenames setObject: attachment + forKey: [header name]]; + } + + return filenames; +} + +- (BOOL) _saveAttachments +{ + WORequest *request; + NSEnumerator *allKeys; + NSString *key; + BOOL success; + NSDictionary *filenames; + id httpBody; + SOGoDraftObject *co; + + success = YES; + request = [context request]; + + httpBody = [[request httpRequest] body]; + filenames = [self _scanAttachmentFilenamesInRequest: httpBody]; + + co = [self clientObject]; + allKeys = [[request formValueKeys] objectEnumerator]; + key = [allKeys nextObject]; + while (key && success) + { + if ([key hasPrefix: @"attachment"]) + success + = (![co saveAttachment: (NSData *) [request formValueForKey: key] + withMetadata: [filenames objectForKey: key]]); + key = [allKeys nextObject]; + } + + return success; +} + +- (BOOL) _saveFormInfo +{ NSDictionary *info; - - if ((info = [self storeInfo]) != nil) { - NSException *error; - - if ((error = [[self clientObject] storeInfo:info]) != nil) { - [self errorWithFormat:@"failed to store draft: %@", error]; - // TODO: improve error handling - return NO; + NSException *error; + BOOL success; + + success = YES; + + if ([self _saveAttachments]) + { + info = [self storeInfo]; + if (info) + { + error = [[self clientObject] storeInfo:info]; + if (error) + { + [self errorWithFormat:@"failed to store draft: %@", error]; + // TODO: improve error handling + success = NO; + } + } } - } + else + success = NO; // TODO: wrap content - return YES; + return success; } + - (id)failedToSaveFormResponse { // TODO: improve error handling return [NSException exceptionWithHTTPStatus:500 /* server error */ @@ -443,23 +546,8 @@ static NSArray *infoKeys = nil; return [[self attachmentNames] count] > 0 ? YES : NO; } -- (NSString *)initialLeftsideStyle { - if ([self hasAttachments]) - return @"width: 67%"; - return @"width: 100%"; -} - -- (NSString *)initialRightsideStyle { - if ([self hasAttachments]) - return @"display: block"; - return @"display: none"; -} - -- (id)defaultAction { - return [self redirectToLocation:@"edit"]; -} - -- (id)editAction { +- (id) defaultAction +{ #if 0 [self logWithFormat:@"edit action, load content from: %@", [self clientObject]]; diff --git a/UI/MailerUI/UIxMailForwardAction.m b/UI/MailerUI/UIxMailForwardAction.m index 29daff75..ba59391e 100644 --- a/UI/MailerUI/UIxMailForwardAction.m +++ b/UI/MailerUI/UIxMailForwardAction.m @@ -93,11 +93,17 @@ nil]; if ((error = [newDraft storeInfo:info]) != nil) return error; - + /* attach message */ // TODO: use subject for filename? - error = [newDraft saveAttachment:content withName:@"forward.mail"]; +// error = [newDraft saveAttachment:content withName:@"forward.mail"]; + attachment = [NSDictionary dictionaryWithObjectsAndKeys: + @"forward.mail", @"filename", + @"message/rfc822", @"mime-type", + nil]; + error = [newDraft saveAttachment: content + withMetadata: attachment]; if (error != nil) return error; diff --git a/UI/Templates/MailPartViewers/UIxMailPartMessageViewer.wox b/UI/Templates/MailPartViewers/UIxMailPartMessageViewer.wox index e42ccbfd..49011477 100644 --- a/UI/Templates/MailPartViewers/UIxMailPartMessageViewer.wox +++ b/UI/Templates/MailPartViewers/UIxMailPartMessageViewer.wox @@ -1,80 +1,40 @@ +
+ xmlns:var="http://www.skyrix.com/od/binding" + xmlns:label="OGo:label" + class="linked_attachment_frame">
- - - - - - - - - - - - - - - - - - - - - - - - - - -
: - - -
: - - - - - -
: - -
: - - - - - -
: - - - - -
-
-
- -
- -
- - +
+ : +
+ : +
+ : +
+
+ : +
+ + : + + +
+
+ +
+ +
+ + + -->
diff --git a/UI/Templates/MailerUI/UIxMailEditor.wox b/UI/Templates/MailerUI/UIxMailEditor.wox index 709379cf..af0ff5b2 100644 --- a/UI/Templates/MailerUI/UIxMailEditor.wox +++ b/UI/Templates/MailerUI/UIxMailEditor.wox @@ -9,16 +9,27 @@ className="UIxPageFrame" title="panelTitle" const:popup="YES"> -
+ + +
-
-
-
-
+
    + +
: - - - Attach ... - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - -
File:
File:
File:
- - -
-
- -
-
- -
-
- - - - - - - - - - - - -
- Attachments - - -
- delete -
-
-
-
-
- -
- - - diff --git a/UI/WebServerResources/MailerUI.css b/UI/WebServerResources/MailerUI.css index 98d15c6b..4d19b7ef 100644 --- a/UI/WebServerResources/MailerUI.css +++ b/UI/WebServerResources/MailerUI.css @@ -174,7 +174,7 @@ DIV#folderTreeContent padding-left: 6px; } -table.titletable +TABLE.titletable { height: 24px; vertical-align: middle; @@ -182,7 +182,7 @@ table.titletable padding-left: 6px; } -table.titletable td.titlecell SELECT +TABLE.titletable td.titlecell SELECT { display: -moz-popup; border-top: 1px solid #fff; @@ -268,7 +268,7 @@ IMG.mailerReadIcon */ } -div.mailer_readicon +DIV.mailer_readicon { /* TODO: use Thunderbird icon */ background-image: url(icon_read.gif); @@ -276,7 +276,7 @@ div.mailer_readicon background-position: 0px 4px; } -div.mailer_readicon a +DIV.mailer_readicon a { width: 17px; height: 17px; @@ -284,7 +284,7 @@ div.mailer_readicon a display: block; } -div.mailerUnreadIcon +DIV.mailerUnreadIcon { /* TODO: use Thunderbird icon */ background-image: url(icon_unread.gif); @@ -292,7 +292,7 @@ div.mailerUnreadIcon background-position: 0px 4px; } -div.mailer_unreadicon a +DIV.mailer_unreadicon a { width: 17px; height: 17px; @@ -302,36 +302,30 @@ div.mailer_unreadicon a /* fields (key/value UI), eg used in mail viewer */ -table.mailer_fieldtable +TABLE.mailer_fieldtable { top: 0px; left: 0px; padding-top: .5em; overflow-y: auto; overflow-x: hidden; - height: 6.5em; + height: 7.5em; border-bottom: 1px solid #808080; background: #d4d0c8; } -div.mailer_mailcontent +DIV.mailer_mailcontent { background-color: #fff; position: absolute; padding: .5em; - margin-top: .5em; - top: 10em; + top: 7.5em; overflow: auto; left: 0px; right: 0px; bottom: 0px; } -DIV#messageContent div.mailer_mailcontent -{ - top: 6em; -} - td.mailer_fieldname { white-space: nowrap; @@ -419,24 +413,13 @@ td.attachment_uplabel /* attachment link viewer */ -div.linked_attachment_frame -{ - background-color: #dcdad5; - padding: 4px; -} +DIV.linked_attachment_frame +{ border: 0px; } -div.linked_attachment_body -{ - padding: 4px; - border-width: 1px; - border-style: solid; - border-top-color: white; - border-left-color: white; - border-bottom-color: #808080; - border-right-color: #808080; -} +DIV.linked_attachment_body +{ border: 0px; } -div.linked_attachment_meta +DIV.linked_attachment_meta { color: #444444; font-style: italic; @@ -444,12 +427,27 @@ div.linked_attachment_meta padding: 2px; } -table.linked_attachment_meta +TABLE.linked_attachment_meta { color: #444444; font-style: italic; } +DIV.bodyFields +{ + background: #efefef; + font-family: serif; + margin: 0.5em; +} + +DIV.bodyFields SPAN.fieldName +{ font-weight: bold; } + +DIV.bodyAdditionalFields +{ + background: #d4d0c8; +} + DIV[datatype~="additional"] > A.node > SPAN.nodeName { color: #777; font-style: italic; } diff --git a/UI/WebServerResources/MailerUI.js b/UI/WebServerResources/MailerUI.js index 434753d4..1793aa30 100644 --- a/UI/WebServerResources/MailerUI.js +++ b/UI/WebServerResources/MailerUI.js @@ -51,62 +51,6 @@ function clearSearch(sender) { return true; } -/* mail editor */ - -function validateEditorInput(sender) { - var errortext = ""; - var field; - - field = document.pageform.subject; - if (field.value == "") - errortext = errortext + labels.error_missingsubject + "\n"; - - if (!UIxRecipientSelectorHasRecipients()) - errortext = errortext + labels.error_missingrecipients + "\n"; - - if (errortext.length > 0) { - alert(labels.error_validationfailed.decodeEntities() + ":\n" - + errortext.decodeEntities()); - return false; - } - return true; -} - -function clickedEditorSend(sender) { - if (!validateEditorInput(sender)) - return false; - - document.pageform.action = "send"; - document.pageform.submit(); - // if everything is ok, close the window - return true; -} - -function clickedEditorAttach(sender) { - var urlstr; - - urlstr = "viewAttachments"; - window.open(urlstr, "SOGo_attach", - "width=320,height=320,resizable=1,scrollbars=1,toolbar=0," + - "location=0,directories=0,status=0,menubar=0,copyhistory=0"); - return false; /* stop following the link */ -} - -function clickedEditorSave(sender) { - document.pageform.action = "save"; - document.pageform.submit(); - refreshOpener(); - return true; -} - -function clickedEditorDelete(sender) { - document.pageform.action = "delete"; - document.pageform.submit(); - refreshOpener(); - window.close(); - return true; -} - function openAddressbook(sender) { var urlstr; @@ -833,7 +777,9 @@ function onMenuViewMessageSource(event) { if (rows.length > 0) { var url = (ApplicationBaseURL + currentMailbox + "/" + rows[0].substr(4) + "/viewsource"); - window.open(url); + window.open(url, "", + "width=680,height=520,resizable=1,scrollbars=1,toolbar=0," + + "location=0,directories=0,status=0,menubar=0,copyhistory=0"); } preventDefault(event); diff --git a/UI/WebServerResources/SchedulerUI.js b/UI/WebServerResources/SchedulerUI.js index 860d0e57..b4fe4f2f 100644 --- a/UI/WebServerResources/SchedulerUI.js +++ b/UI/WebServerResources/SchedulerUI.js @@ -657,8 +657,8 @@ function drawCalendarEvent(eventData, sd, ed) { if (!lasts) lasts = 1; - var eventDiv = newEventDIV(eventData[0], eventData[1], starts, lasts, - null, null, title); + var eventDiv = newEventDIV(eventData[0], eventData[1], starts, lasts, + null, null, title); siblings.push(eventDiv); eventDiv.siblings = siblings; var dayString = days[i].getDayString(); diff --git a/UI/WebServerResources/UIxMailEditor.css b/UI/WebServerResources/UIxMailEditor.css index 201b11d1..a21531e7 100644 --- a/UI/WebServerResources/UIxMailEditor.css +++ b/UI/WebServerResources/UIxMailEditor.css @@ -43,14 +43,13 @@ DIV#subjectRow INPUT width: 38em; padding-left: .5em; } -div#compose_internetmarker { - padding: 8px; +div#compose_internetmarker +{ padding: 8px; text-align: center; background-color: white; border-color: red; border-width: 2px; - border-style: solid; -} + border-style: solid; } div#headerArea { border-top: 1px solid #fff; @@ -66,11 +65,16 @@ div#attachmentsArea padding-left: 5px; border-left: 1px solid #888; } +input.currentAttachment +{ position: absolute; + top: 1em; + right: 1em; } + +input.attachment +{ display: none; } + div#compose_attachments_list -{ - width: 100%; - height: 10em; - background-color: #ffffff; +{ background-color: #ffffff; margin-left: 0px; padding: 2px; border-bottom: 1px solid #fff; @@ -78,8 +82,32 @@ div#compose_attachments_list border-top: 2px solid #222; border-left: 2px solid #222; -moz-border-top-colors: #9c9a94 #000 transparent; + -moz-border-left-colors: #9c9a94 #000 transparent; } + +UL#attachments +{ cursor: default; + margin: 0px; + padding: 0px; + width: 100%; + height: 10em; + border-bottom: 1px solid #fff; + border-right: 1px solid #fff; + border-top: 2px solid #222; + border-left: 2px solid #222; + background-color: #fff; + -moz-border-top-colors: #9c9a94 #000 transparent; -moz-border-left-colors: #9c9a94 #000 transparent; -} + list-style-type: none; + list-style-image: none; + overflow: auto; + overflow-x: hidden; } + +UL#attachments LI +{ white-space: nowrap; + padding-bottom: 1px; } + +UL#attachments LI IMG +{ vertical-align: bottom; } DIV.pageContent TEXTAREA { position: absolute; @@ -87,4 +115,3 @@ DIV.pageContent TEXTAREA right: 0em; bottom: 0em; top: 17em; } - diff --git a/UI/WebServerResources/UIxMailEditor.js b/UI/WebServerResources/UIxMailEditor.js index 839d8991..ac33fa91 100644 --- a/UI/WebServerResources/UIxMailEditor.js +++ b/UI/WebServerResources/UIxMailEditor.js @@ -120,3 +120,150 @@ function updateInlineAttachmentList(sender, attachments) { else div.style.display = ""; } +/* mail editor */ + +function validateEditorInput(sender) { + var errortext = ""; + var field; + + field = document.pageform.subject; + if (field.value == "") + errortext = errortext + labels.error_missingsubject + "\n"; + + if (!UIxRecipientSelectorHasRecipients()) + errortext = errortext + labels.error_missingrecipients + "\n"; + + if (errortext.length > 0) { + alert(labels.error_validationfailed.decodeEntities() + ":\n" + + errortext.decodeEntities()); + return false; + } + return true; +} + +function clickedEditorSend(sender) { + if (!validateEditorInput(sender)) + return false; + + document.pageform.action = "send"; + document.pageform.submit(); + + window.alert("cocou"); + + return false; +} + +function clickedEditorAttach(sender) { + var area = $("attachmentsArea"); + + area.setStyle({ display: "block" }); + + var inputs = area.getElementsByTagName("input"); + var attachmentName = "attachment" + inputs.length; + var newAttachment = createElement("input", attachmentName, + "currentAttachment", null, + { type: "file", + name: attachmentName }, + area); + Event.observe(newAttachment, "change", + onAttachmentChange.bindAsEventListener(newAttachment)); + + return false; +} + +function onAddAttachment() { + var area = $("attachmentsArea"); + var inputs = area.getElementsByTagName("input"); + var attachmentName = "attachment" + inputs.length; + var newAttachment = createElement("input", attachmentName, + "currentAttachment", null, + { type: "file", + name: attachmentName }, + area); + Event.observe(newAttachment, "change", + onAttachmentChange.bindAsEventListener(newAttachment)); +} + +function onAttachmentChange(event) { + if (this.value == "") + this.parentNode.removeChild(this); + else { + this.addClassName("attachment"); + this.removeClassName("currentAttachment"); + var list = $("attachments"); + createAttachment(this, list); + } +} + +function createAttachment(node, list) { + var attachment = createElement("li", null, null, { node: node }, null, list); + createElement("img", null, null, { src: ResourcesURL + "/attachment.gif" }, + null, attachment); + Event.observe(attachment, "click", onRowClick); + + var filename = node.value; + var separator; + if (navigator.appVersion.indexOf("Windows") > -1) + separator = "\\"; + else + separator = "/"; + var fileArray = filename.split(separator); + var attachmentName = document.createTextNode(fileArray[fileArray.length-1]); + attachment.appendChild(attachmentName); +} + +function clickedEditorSave(sender) { + document.pageform.action = "save"; + document.pageform.submit(); + refreshOpener(); + + return false; +} + +function clickedEditorDelete(sender) { + document.pageform.action = "delete"; + document.pageform.submit(); + refreshOpener(); + window.close(); + + return false; +} + +function initMailEditor() { + var list = $("attachments"); + $(list).attachMenu("attachmentsMenu"); + var elements = list.childNodesWithTag("li"); + for (var i = 0; i < elements.length; i++) + Event.observe(elements[i], "click", + onRowClick.bindAsEventListener(elements[i])); +} + +function getMenus() { + return { "attachmentsMenu": new Array(null, onRemoveAttachments, + onSelectAllAttachments, + "-", + onAddAttachment, null) }; +} + +function onRemoveAttachments() { + var list = $("attachments"); + var nodes = list.getSelectedNodes(); + for (var i = nodes.length-1; i > -1; i--) { + var input = $(nodes[i]).node; + if (input) { + input.parentNode.removeChild(input); + list.removeChild(nodes[i]); + } + else + window.alert("Server attachments not handled"); + } +} + +function onSelectAllAttachments() { + var list = $("attachments"); + var nodes = list.childNodesWithTag("li"); + for (var i = 0; i < nodes.length; i++) + nodes[i].select(); +} + +window.addEventListener("load", initMailEditor, false); diff --git a/UI/WebServerResources/UIxMailEditorAttach.js b/UI/WebServerResources/UIxMailEditorAttach.js deleted file mode 100644 index 8fbca8c1..00000000 --- a/UI/WebServerResources/UIxMailEditorAttach.js +++ /dev/null @@ -1,41 +0,0 @@ -/* - 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. -*/ - -function updateAttachmentListInEditorWindow(sender) { - var attachments; - - attachments = this.getAttachmentNames(); - window.opener.updateInlineAttachmentList(this, attachments); -} - -function getAttachmentNames() { - var e, s, names; - - e = document.getElementById('attachmentList'); - s = e.innerHTML; - /* remove trailing delimiter */ - s = s.substr(0, s.length - 1); - if (s == '') return null; - - /* probably no OS allows '/' in a file name */ - names = s.split('/'); - return names; -} diff --git a/UI/WebServerResources/generic.js b/UI/WebServerResources/generic.js index d469df7d..18845795 100644 --- a/UI/WebServerResources/generic.js +++ b/UI/WebServerResources/generic.js @@ -121,7 +121,7 @@ function createElement(tagName, id, classes, attributes, htmlAttributes, newElement[i] = attributes[i]; if (htmlAttributes) for (var i in htmlAttributes) - newElement.setAttribute(i, attributes[i]); + newElement.setAttribute(i, htmlAttributes[i]); if (parentNode) parentNode.appendChild(newElement);