From c986422a3d4037b5429a7e8e64b5388d5a726b94 Mon Sep 17 00:00:00 2001 From: Francis Lachapelle Date: Fri, 11 Feb 2022 09:45:54 -0500 Subject: [PATCH] feat(mail(web)): Templates folder for pre-defined drafts To create a template, the user needs to: - define a mailbox as the Templates folder; - move a draft to this special folder. Fixes #4320 Fixes #5363 --- SoObjects/Mailer/GNUmakefile | 1 + SoObjects/Mailer/SOGoMailAccount.h | 4 +++ SoObjects/Mailer/SOGoMailAccount.m | 33 +++++++++++++++++++ SoObjects/Mailer/SOGoMailBaseObject.h | 1 + SoObjects/Mailer/SOGoMailBaseObject.m | 5 +++ SoObjects/Mailer/SOGoMailFolder.m | 4 +++ SoObjects/Mailer/SOGoTemplatesFolder.h | 32 ++++++++++++++++++ SoObjects/Mailer/SOGoTemplatesFolder.m | 31 +++++++++++++++++ SoObjects/SOGo/SOGoDefaults.plist | 1 + SoObjects/SOGo/SOGoUser.m | 2 ++ SoObjects/SOGo/SOGoUserDefaults.h | 3 ++ SoObjects/SOGo/SOGoUserDefaults.m | 11 +++++++ UI/MailerUI/English.lproj/Localizable.strings | 7 ++++ UI/MailerUI/UIxMailActions.m | 30 +++++++++++++++++ UI/MailerUI/UIxMailView.m | 7 ++++ UI/MailerUI/product.plist | 10 ++++++ UI/Templates/MailerUI/UIxMailEditor.wox | 4 ++- UI/Templates/MailerUI/UIxMailMainFrame.wox | 5 +++ UI/Templates/MailerUI/UIxMailViewTemplate.wox | 15 +++++++-- UI/WebServerResources/js/Common/utils.js | 6 ++-- .../js/Mailer/Mailbox.service.js | 4 +++ .../js/Mailer/Message.service.js | 12 ++++++- .../js/Mailer/MessageController.js | 6 ++++ .../js/Mailer/MessageEditorController.js | 3 +- .../js/Mailer/sgMessageListItem.directive.js | 2 +- 25 files changed, 230 insertions(+), 9 deletions(-) create mode 100644 SoObjects/Mailer/SOGoTemplatesFolder.h create mode 100644 SoObjects/Mailer/SOGoTemplatesFolder.m diff --git a/SoObjects/Mailer/GNUmakefile b/SoObjects/Mailer/GNUmakefile index 7b713f54d..411bbc2bb 100644 --- a/SoObjects/Mailer/GNUmakefile +++ b/SoObjects/Mailer/GNUmakefile @@ -24,6 +24,7 @@ Mailer_OBJC_FILES += \ SOGoDraftsFolder.m \ SOGoTrashFolder.m \ SOGoJunkFolder.m \ + SOGoTemplatesFolder.m \ \ SOGoMailBodyPart.m \ SOGoHTMLMailBodyPart.m \ diff --git a/SoObjects/Mailer/SOGoMailAccount.h b/SoObjects/Mailer/SOGoMailAccount.h index 58f80cf45..dc90471ca 100644 --- a/SoObjects/Mailer/SOGoMailAccount.h +++ b/SoObjects/Mailer/SOGoMailAccount.h @@ -44,6 +44,7 @@ @class SOGoSentFolder; @class SOGoTrashFolder; @class SOGoJunkFolder; +@class SOGoTemplatesFolder; typedef enum { undefined = -1, @@ -63,6 +64,7 @@ typedef enum { SOGoSentFolder *sentFolder; SOGoTrashFolder *trashFolder; SOGoJunkFolder *junkFolder; + SOGoTemplatesFolder *templatesFolder; SOGoIMAPAclStyle imapAclStyle; NSMutableArray *identities; NSString *otherUsersFolderName; @@ -117,12 +119,14 @@ typedef enum { - (NSString *) otherUsersFolderNameInContext: (id)_ctx; - (NSString *) sharedFoldersNameInContext: (id)_ctx; - (NSString *) junkFolderNameInContext: (id)_ctx; +- (NSString *) templatesFolderNameInContext: (id)_ctx; - (SOGoMailFolder *) inboxFolderInContext: (id)_ctx; - (SOGoDraftsFolder *) draftsFolderInContext: (id)_ctx; - (SOGoSentFolder *) sentFolderInContext: (id)_ctx; - (SOGoTrashFolder *) trashFolderInContext: (id)_ctx; - (SOGoJunkFolder *) junkFolderInContext: (id)_ctx; +- (SOGoTemplatesFolder *) templatesFolderInContext: (id)_ctx; /* namespaces */ diff --git a/SoObjects/Mailer/SOGoMailAccount.m b/SoObjects/Mailer/SOGoMailAccount.m index a474e1a64..7c16c3831 100644 --- a/SoObjects/Mailer/SOGoMailAccount.m +++ b/SoObjects/Mailer/SOGoMailAccount.m @@ -48,6 +48,7 @@ #import "SOGoSentFolder.h" #import "SOGoTrashFolder.h" #import "SOGoJunkFolder.h" +#import "SOGoTemplatesFolder.h" #import "SOGoUser+Mailer.h" #import "SOGoMailAccount.h" @@ -70,6 +71,7 @@ static NSString *inboxFolderName = @"INBOX"; sentFolder = nil; trashFolder = nil; junkFolder = nil; + templatesFolder = nil; imapAclStyle = undefined; identities = nil; otherUsersFolderName = nil; @@ -88,6 +90,7 @@ static NSString *inboxFolderName = @"INBOX"; [sentFolder release]; [trashFolder release]; [junkFolder release]; + [templatesFolder release]; [identities release]; [otherUsersFolderName release]; [sharedFoldersName release]; @@ -100,6 +103,11 @@ static NSString *inboxFolderName = @"INBOX"; return NO; } +- (BOOL) isInTemplatesFolder +{ + return NO; +} + - (void) _appendNamespace: (NSArray *) namespace toFolders: (NSMutableArray *) folders { @@ -406,6 +414,7 @@ static NSString *inboxFolderName = @"INBOX"; [self sentFolderNameInContext: context], [self trashFolderNameInContext: context], [self junkFolderNameInContext: context], + [self templatesFolderNameInContext: context], nil] stringsWithFormat: @"/%@"]; folders = [[self imap4Connection] allFoldersForURL: [self imap4URL] onlySubscribedFolders: subscribedOnly]; @@ -479,6 +488,9 @@ static NSString *inboxFolderName = @"INBOX"; else if ([flags containsObject: [self junkFolderNameInContext: context]] || [folderName isEqualToString: [self junkFolderNameInContext: context]]) folderType = @"junk"; + else if ([flags containsObject: [self templatesFolderNameInContext: context]] || + [folderName isEqualToString: [self templatesFolderNameInContext: context]]) + folderType = @"templates"; else if ([folderName isEqualToString: otherUsersFolderName]) folderType = @"otherUsers"; else if ([folderName isEqualToString: sharedFoldersName]) @@ -1012,6 +1024,9 @@ static NSString *inboxFolderName = @"INBOX"; else if ([folderName isEqualToString: [self junkFolderNameInContext: _ctx]]) klazz = [SOGoJunkFolder class]; + else if ([folderName + isEqualToString: [self templatesFolderNameInContext: _ctx]]) + klazz = [SOGoTemplatesFolder class]; else klazz = [SOGoMailFolder class]; @@ -1081,6 +1096,11 @@ static NSString *inboxFolderName = @"INBOX"; return [self _userFolderNameWithPurpose: @"Junk"]; } +- (NSString *) templatesFolderNameInContext: (id)_ctx +{ + return [self _userFolderNameWithPurpose: @"Templates"]; +} + - (NSString *) otherUsersFolderNameInContext: (id)_ctx { return otherUsersFolderName; @@ -1192,6 +1212,19 @@ static NSString *inboxFolderName = @"INBOX"; return junkFolder; } +- (SOGoTemplatesFolder *) templatesFolderInContext: (id) _ctx +{ + if (!templatesFolder) + { + templatesFolder + = [self folderWithTraversal: [self templatesFolderNameInContext: _ctx] + andClassName: @"SOGoTemplatesFolder"]; + [templatesFolder retain]; + } + + return templatesFolder; +} + /* account delegation */ - (NSArray *) delegates { diff --git a/SoObjects/Mailer/SOGoMailBaseObject.h b/SoObjects/Mailer/SOGoMailBaseObject.h index 97d06690d..43306d76a 100644 --- a/SoObjects/Mailer/SOGoMailBaseObject.h +++ b/SoObjects/Mailer/SOGoMailBaseObject.h @@ -62,6 +62,7 @@ - (SOGoMailAccount *) mailAccountFolder; - (SOGoMailAccounts *) mailAccountsFolder; - (BOOL) isInDraftsFolder; +- (BOOL) isInTemplatesFolder; /* IMAP4 */ diff --git a/SoObjects/Mailer/SOGoMailBaseObject.m b/SoObjects/Mailer/SOGoMailBaseObject.m index 9d415c67a..b59b94a86 100644 --- a/SoObjects/Mailer/SOGoMailBaseObject.m +++ b/SoObjects/Mailer/SOGoMailBaseObject.m @@ -121,6 +121,11 @@ return [container isInDraftsFolder]; } +- (BOOL) isInTemplatesFolder +{ + return [container isInTemplatesFolder]; +} + /* IMAP4 */ - (NGImap4ConnectionManager *) mailManager diff --git a/SoObjects/Mailer/SOGoMailFolder.m b/SoObjects/Mailer/SOGoMailFolder.m index 997407c36..3cc47114d 100644 --- a/SoObjects/Mailer/SOGoMailFolder.m +++ b/SoObjects/Mailer/SOGoMailFolder.m @@ -1144,6 +1144,10 @@ static NSInteger _compareFetchResultsByUID (id entry1, id entry2, NSArray *uids) isEqualToString: [mailAccount junkFolderNameInContext: _ctx]]) className = @"SOGoJunkFolder"; + else if ([fullFolderName + isEqualToString: + [mailAccount templatesFolderNameInContext: _ctx]]) + className = @"SOGoTemplatesFolder"; /* else if ([folderName isEqualToString: [mailAccount sieveFolderNameInContext: _ctx]]) obj = [self lookupFiltersFolder: _key inContext: _ctx]; */ diff --git a/SoObjects/Mailer/SOGoTemplatesFolder.h b/SoObjects/Mailer/SOGoTemplatesFolder.h new file mode 100644 index 000000000..9bcb61187 --- /dev/null +++ b/SoObjects/Mailer/SOGoTemplatesFolder.h @@ -0,0 +1,32 @@ +/* + Copyright (C) 2022 Inverse inc. + + This file is part of SOGo. + + SOGo 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. + + SOGo 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. +*/ + +#ifndef __Mailer_SOGoTemplatesFolder_H__ +#define __Mailer_SOGoTemplatesFolder_H__ + +#import "SOGoDraftsFolder.h" + +@class SOGoDraftsFolder; + +@interface SOGoTemplatesFolder : SOGoDraftsFolder +@end + +#endif /* __Mailer_SOGoTemplatesFolder_H__ */ diff --git a/SoObjects/Mailer/SOGoTemplatesFolder.m b/SoObjects/Mailer/SOGoTemplatesFolder.m new file mode 100644 index 000000000..b732a7d35 --- /dev/null +++ b/SoObjects/Mailer/SOGoTemplatesFolder.m @@ -0,0 +1,31 @@ +/* + Copyright (C) 2022 Inverse inc. + + This file is part of SOGo. + + SOGo 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. + + SOGo 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. +*/ + +#import "SOGoTemplatesFolder.h" + +@implementation SOGoTemplatesFolder + +- (BOOL) isInTemplatesFolder +{ + return YES; +} + +@end /* SOGoTemplatesFolder */ diff --git a/SoObjects/SOGo/SOGoDefaults.plist b/SoObjects/SOGo/SOGoDefaults.plist index a158ad5c7..9ba853590 100644 --- a/SoObjects/SOGo/SOGoDefaults.plist +++ b/SoObjects/SOGo/SOGoDefaults.plist @@ -115,6 +115,7 @@ SOGoDraftsFolderName = "Drafts"; SOGoTrashFolderName = "Trash"; SOGoJunkFolderName = "Junk"; + SOGoTemplatesFolderName = "Templates"; SOGoMailComposeMessageType = "html"; SOGoMailComposeFontSize = "0"; SOGoMailDisplayRemoteInlineImages = "never"; diff --git a/SoObjects/SOGo/SOGoUser.m b/SoObjects/SOGo/SOGoUser.m index 7edbce1f7..1255ec231 100644 --- a/SoObjects/SOGo/SOGoUser.m +++ b/SoObjects/SOGo/SOGoUser.m @@ -923,6 +923,8 @@ forKey: @"Trash"]; [mailboxes setObject: [_defaults junkFolderName] forKey: @"Junk"]; + [mailboxes setObject: [_defaults templatesFolderName] + forKey: @"Templates"]; [mailAccount setObject: mailboxes forKey: @"specialMailboxes"]; [mailboxes release]; diff --git a/SoObjects/SOGo/SOGoUserDefaults.h b/SoObjects/SOGo/SOGoUserDefaults.h index 12f3ee33a..106b2660a 100644 --- a/SoObjects/SOGo/SOGoUserDefaults.h +++ b/SoObjects/SOGo/SOGoUserDefaults.h @@ -111,6 +111,9 @@ extern NSString *SOGoWeekStartFirstFullWeek; - (void) setJunkFolderName: (NSString *) newValue; - (NSString *) junkFolderName; +- (void) setTemplatesFolderName: (NSString *) newValue; +- (NSString *) templatesFolderName; + - (void) setFirstDayOfWeek: (int) newValue; - (int) firstDayOfWeek; diff --git a/SoObjects/SOGo/SOGoUserDefaults.m b/SoObjects/SOGo/SOGoUserDefaults.m index 5e2f021db..ae9fab4ba 100644 --- a/SoObjects/SOGo/SOGoUserDefaults.m +++ b/SoObjects/SOGo/SOGoUserDefaults.m @@ -492,6 +492,17 @@ NSString *SOGoWeekStartFirstFullWeek = @"FirstFullWeek"; stringByEncodingImap4FolderName]; } +- (void) setTemplatesFolderName: (NSString *) newValue +{ + [self setObject: newValue forKey: @"SOGoTemplatesFolderName"]; +} + +- (NSString *) templatesFolderName +{ + return [[self stringForKey: @"SOGoTemplatesFolderName"] + stringByEncodingImap4FolderName]; +} + - (void) setFirstDayOfWeek: (int) newValue { [self setInteger: newValue forKey: @"SOGoFirstDayOfWeek"]; diff --git a/UI/MailerUI/English.lproj/Localizable.strings b/UI/MailerUI/English.lproj/Localizable.strings index 7ebedc694..9edf491f9 100644 --- a/UI/MailerUI/English.lproj/Localizable.strings +++ b/UI/MailerUI/English.lproj/Localizable.strings @@ -187,6 +187,7 @@ "InboxFolderName" = "Inbox"; "DraftsFolderName" = "Drafts"; "JunkFolderName" = "Junk"; +"TemplatesFolderName" = "Templates"; "SieveFolderName" = "Filters"; "Folders" = "Folders"; /* title line */ @@ -432,6 +433,9 @@ "Set as Sent" = "Set as Sent"; "Set as Trash" = "Set as Trash"; +/* Set the folder as the one holding the Templates */ +"Set as Templates" = "Set as Templates"; + /* Set the folder as the one holding Junk mails */ "Set as Junk" = "Set as Junk"; @@ -454,6 +458,9 @@ "Your email has been sent" = "Your email has been sent"; "Folder compacted" = "Folder compacted"; +"New draft" = "New draft"; +"Create new draft with this template" = "Create new draft with this template"; + /* Advanced search */ "Enter Subject" = "Enter Subject"; "Enter From" = "Enter From"; diff --git a/UI/MailerUI/UIxMailActions.m b/UI/MailerUI/UIxMailActions.m index 69a27d9cf..5333ffd0f 100644 --- a/UI/MailerUI/UIxMailActions.m +++ b/UI/MailerUI/UIxMailActions.m @@ -118,6 +118,36 @@ andString: [data jsonRepresentation]]; } +- (WOResponse *) composeAction +{ + SOGoMailAccount *account; + SOGoMailObject *co; + SOGoDraftsFolder *drafts; + SOGoDraftObject *newMail; + NSString *accountName, *mailboxName, *messageName; + NSDictionary *data; + + co = [self clientObject]; + account = [co mailAccountFolder]; + drafts = [account draftsFolderInContext: context]; + newMail = [drafts newDraft]; + [newMail fetchMailForEditing: co]; + [newMail storeInfo]; + + accountName = [account nameInContainer]; + mailboxName = [drafts absoluteImap4Name]; + mailboxName = [mailboxName substringWithRange: NSMakeRange(1, [mailboxName length] -2)]; + messageName = [newMail nameInContainer]; + + data = [NSDictionary dictionaryWithObjectsAndKeys: + accountName, @"accountId", + mailboxName, @"mailboxPath", + messageName, @"draftId", nil]; + + return [self responseWithStatus: 201 + andString: [data jsonRepresentation]]; +} + - (WOResponse *) viewPlainAction { BOOL htmlContent; diff --git a/UI/MailerUI/UIxMailView.m b/UI/MailerUI/UIxMailView.m index e7be2fe13..fe373a2d8 100644 --- a/UI/MailerUI/UIxMailView.m +++ b/UI/MailerUI/UIxMailView.m @@ -68,6 +68,7 @@ } - (BOOL) mailIsDraft; +- (BOOL) mailIsTemplate; - (NSNumber *) shouldAskReceipt; - (NSString *) formattedDate; - (NSString *) _matchingIdentityEMailOrDefault: (BOOL) useDefault; @@ -340,6 +341,7 @@ static NSString *mailETag = nil; data = [NSMutableDictionary dictionaryWithObjectsAndKeys: [self shouldAskReceipt], @"shouldAskReceipt", [NSNumber numberWithBool: [self mailIsDraft]], @"isDraft", + [NSNumber numberWithBool: [self mailIsTemplate]], @"isTemplate", renderedPart, @"parts", nil]; if ([self formattedDate]) @@ -803,6 +805,11 @@ static NSString *mailETag = nil; return [[self clientObject] isInDraftsFolder]; } +- (BOOL) mailIsTemplate +{ + return [[self clientObject] isInTemplatesFolder]; +} + - (id) redirectToParentFolder { id url; diff --git a/UI/MailerUI/product.plist b/UI/MailerUI/product.plist index d7700d7c8..5f55a4f59 100644 --- a/UI/MailerUI/product.plist +++ b/UI/MailerUI/product.plist @@ -119,6 +119,11 @@ actionClass = "UIxMailFolderActions"; actionName = "setAsJunkFolder"; }; + setAsTemplatesFolder = { + protectedBy = "View"; + actionClass = "UIxMailFolderActions"; + actionName = "setAsTemplatesFolder"; + }; markMessagesAsJunk = { protectedBy = "View"; actionClass = "UIxMailFolderActions"; @@ -237,6 +242,11 @@ actionClass = "UIxMailActions"; actionName = "edit"; }; + compose = { + protectedBy = "View"; + actionClass = "UIxMailActions"; + actionName = "compose"; + }; reply = { protectedBy = "View"; actionClass = "UIxMailActions"; diff --git a/UI/Templates/MailerUI/UIxMailEditor.wox b/UI/Templates/MailerUI/UIxMailEditor.wox index ce4a0a99c..67d0b00f4 100644 --- a/UI/Templates/MailerUI/UIxMailEditor.wox +++ b/UI/Templates/MailerUI/UIxMailEditor.wox @@ -60,7 +60,9 @@
This field is required
- send diff --git a/UI/Templates/MailerUI/UIxMailMainFrame.wox b/UI/Templates/MailerUI/UIxMailMainFrame.wox index 0435b2585..18d09a1f2 100644 --- a/UI/Templates/MailerUI/UIxMailMainFrame.wox +++ b/UI/Templates/MailerUI/UIxMailMainFrame.wox @@ -274,6 +274,11 @@ + + + + + diff --git a/UI/Templates/MailerUI/UIxMailViewTemplate.wox b/UI/Templates/MailerUI/UIxMailViewTemplate.wox index dfe824ab9..a36ad4c90 100644 --- a/UI/Templates/MailerUI/UIxMailViewTemplate.wox +++ b/UI/Templates/MailerUI/UIxMailViewTemplate.wox @@ -155,7 +155,7 @@
-
+
@@ -255,9 +255,20 @@
+ +
+ + + drafts +

+
+
+ + ng-show="viewer.message.signed">
diff --git a/UI/WebServerResources/js/Common/utils.js b/UI/WebServerResources/js/Common/utils.js index 70ade85d3..7c6ccfbc8 100644 --- a/UI/WebServerResources/js/Common/utils.js +++ b/UI/WebServerResources/js/Common/utils.js @@ -134,8 +134,10 @@ String.prototype.formatted = function() { return newString; }; -String.prototype.isValidEmail = function() { - var emailRE = /^([\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*[\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)$/i; +String.prototype.isValidEmail = function(strict) { + var emailRE = strict ? + /^([\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*[\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)$/i : /([\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*[\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)/i; + return emailRE.test(this); }; diff --git a/UI/WebServerResources/js/Mailer/Mailbox.service.js b/UI/WebServerResources/js/Mailer/Mailbox.service.js index 00ca6b536..d1db3f583 100644 --- a/UI/WebServerResources/js/Mailer/Mailbox.service.js +++ b/UI/WebServerResources/js/Mailer/Mailbox.service.js @@ -203,6 +203,10 @@ this.$displayName = l('JunkFolderName'); this.$icon = 'thumb_down'; } + else if (this.type == 'templates') { + this.$displayName = l('TemplatesFolderName'); + this.$icon = 'mail_outline'; + } else if (this.type == 'additional') { this.$icon = 'folder'; } diff --git a/UI/WebServerResources/js/Mailer/Message.service.js b/UI/WebServerResources/js/Mailer/Message.service.js index b202b5054..717a29622 100644 --- a/UI/WebServerResources/js/Mailer/Message.service.js +++ b/UI/WebServerResources/js/Mailer/Message.service.js @@ -776,10 +776,20 @@ return this.$newDraft('forward'); }; + /** + * @function $compose + * @memberof Message.prototype + * @desc Prepare a new Message object as a new draft from a copy of this message. + * @returns a promise of the HTTP operations + */ + Message.prototype.$compose = function() { + return this.$newDraft('compose'); + }; + /** * @function $newDraft * @memberof Message.prototype - * @desc Prepare a new Message object as a reply or a forward of the current message and associated + * @desc Prepare a new Message object as a reply, a forward or a copy of the current message and associated * to the draft mailbox. * @see {@link Account.$newMessage} * @see {@link Message.$editableContent} diff --git a/UI/WebServerResources/js/Mailer/MessageController.js b/UI/WebServerResources/js/Mailer/MessageController.js index bf41f4fb4..975060e3b 100644 --- a/UI/WebServerResources/js/Mailer/MessageController.js +++ b/UI/WebServerResources/js/Mailer/MessageController.js @@ -479,6 +479,12 @@ } }; + this.compose = function($event) { + if (!this._showMailEditorInPopup('compose')) { + _showMailEditor($event, this.message.$compose()); + } + }; + this.openInPopup = function(action) { var url = [sgSettings.baseURL(), 'UIxMailPopupView#!/Mail', diff --git a/UI/WebServerResources/js/Mailer/MessageEditorController.js b/UI/WebServerResources/js/Mailer/MessageEditorController.js index 5f3d5ae19..a71b9fafb 100644 --- a/UI/WebServerResources/js/Mailer/MessageEditorController.js +++ b/UI/WebServerResources/js/Mailer/MessageEditorController.js @@ -304,7 +304,6 @@ this.addRecipient = function (contact, field) { var recipients, recipient, list, i, address; - var emailRE = /([\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*[\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)/i; recipients = this.message.editable[field]; @@ -319,7 +318,7 @@ contact.charCodeAt(i) == 32 || // space contact.charCodeAt(i) == 44 || // , contact.charCodeAt(i) == 59) && // ; - emailRE.test(address) && + address.isValidEmail() && recipients.indexOf(address) < 0) { recipients.push(address); address = ''; diff --git a/UI/WebServerResources/js/Mailer/sgMessageListItem.directive.js b/UI/WebServerResources/js/Mailer/sgMessageListItem.directive.js index e51c1b5c2..31c515d63 100644 --- a/UI/WebServerResources/js/Mailer/sgMessageListItem.directive.js +++ b/UI/WebServerResources/js/Mailer/sgMessageListItem.directive.js @@ -33,7 +33,7 @@ // this.service = Message; this.MailboxService = Mailbox; - if (Mailbox.selectedFolder.type == 'draft') + if (Mailbox.selectedFolder.type == 'draft' || Mailbox.selectedFolder.type == 'templates') watchedAttrs.push('subject'); $scope.$watch(