diff --git a/NEWS b/NEWS index ee5dbeb034..2c06ee4191 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,9 @@ 3.1.1 (2016-MM-DD) ------------------ +Enhancements + - [web] expose all email addresses in autocompletion of message editor (#3443) + Bug fixes - [web] fixed creation of chip on blur (sgTransformOnBlur directive) - [web] fixed composition of new messages from Contacts module diff --git a/SoObjects/Contacts/NGVCard+SOGo.m b/SoObjects/Contacts/NGVCard+SOGo.m index 3053aa60f3..ea4d2cb1fc 100644 --- a/SoObjects/Contacts/NGVCard+SOGo.m +++ b/SoObjects/Contacts/NGVCard+SOGo.m @@ -45,7 +45,7 @@ SUP person STRUCTURAL MAY ( title $ x121Address $ registeredAddress $ destinationIndicator $ preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $ - telephoneNumber $ internationaliSDNNumber $ + telephoneNumber $ internationaliSDNNumber $ facsimileTelephoneNumber $ street $ postOfficeBox $ postalCode $ postalAddress $ physicalDeliveryOfficeName $ ou $ st $ l ) ) @@ -64,10 +64,10 @@ userSMIMECertificate $ userPKCS12 ) ) -objectclass ( 1.3.6.1.4.1.13769.9.1 NAME 'mozillaAbPersonAlpha' - SUP top AUXILIARY +objectclass ( 1.3.6.1.4.1.13769.9.1 NAME 'mozillaAbPersonAlpha' + SUP top AUXILIARY MUST ( cn ) - MAY( c $ + MAY( c $ description $ displayName $ facsimileTelephoneNumber $ @@ -257,7 +257,7 @@ - (void) updateFromLDIFRecord: (NSDictionary *) ldifRecord given: [ldifRecord objectForKey: @"givenname"] additional: nil prefixes: nil suffixes: nil]; [self setNickname: [ldifRecord objectForKey: @"mozillanickname"]]; - [self setTitle: [ldifRecord objectForKey: @"title"]]; + [self setTitle: [ldifRecord objectForKey: @"title"]]; fn = [ldifRecord objectForKey: @"displayname"]; if (!fn) @@ -294,7 +294,7 @@ - (void) updateFromLDIFRecord: (NSDictionary *) ldifRecord ou = [ldifRecord objectForKey: @"ou"]; if ([ou isKindOfClass: [NSArray class]]) - units = [NSArray arrayWithArray: ou]; + units = [NSArray arrayWithArray: (NSArray *)ou]; else if (ou) units = [NSArray arrayWithObject: ou]; else @@ -308,7 +308,7 @@ - (void) updateFromLDIFRecord: (NSDictionary *) ldifRecord setSingleValue: [ldifRecord objectForKey: @"mozillahomeurl"] forKey: @""]; [[self elementWithTag: @"url" ofType: @"work"] setSingleValue: [ldifRecord objectForKey: @"mozillaworkurl"] forKey: @""]; - + [[self uniqueChildWithTag: @"x-aim"] setSingleValue: [ldifRecord objectForKey: @"nsaimid"] forKey: @""]; @@ -343,7 +343,7 @@ - (void) updateFromLDIFRecord: (NSDictionary *) ldifRecord o = [ldifRecord objectForKey: @"vcardcategories"]; - // We can either have an array (from SOGo's web gui) or a + // We can either have an array (from SOGo's web gui) or a // string (from a LDIF import) as the value here. if ([o isKindOfClass: [NSArray class]]) [self setCategories: o]; @@ -356,7 +356,7 @@ - (void) updateFromLDIFRecord: (NSDictionary *) ldifRecord /* VCARD -> LDIF */ - (NSString *) _simpleValueForType: (NSString *) aType inArray: (NSArray *) anArray - excluding: (NSString *) aTypeToExclude + excluding: (NSString *) aTypeToExclude { NSArray *elements; NSString *value; @@ -377,7 +377,7 @@ - (NSString *) _simpleValueForType: (NSString *) aType if (!aTypeToExclude) break; - + if (![ce hasAttribute: @"type" havingValue: aTypeToExclude]) break; @@ -609,8 +609,8 @@ - (NSMutableDictionary *) asLDIFRecord to: [self _simpleValueForType: @"home" inArray: elements excluding: nil] inLDIFRecord: ldifRecord]; - - // If we don't have a "work" or "home" URL but we still have + + // If we don't have a "work" or "home" URL but we still have // an URL field present, let's add it to the "home" value if ([[ldifRecord objectForKey: @"mozillaworkurl"] length] == 0 && [[ldifRecord objectForKey: @"mozillahomeurl"] length] == 0 && @@ -640,7 +640,7 @@ - (NSMutableDictionary *) asLDIFRecord } } } - + [self _setValue: @"title" to: [self title] inLDIFRecord: ldifRecord]; [self _setupOrgFieldsInLDIFRecord: ldifRecord]; @@ -683,7 +683,7 @@ - (NSString *) workCompany { CardElement *org; NSString *company; - + org = [self org]; company = [org flattenedValueAtIndex: 0 forKey: @""]; if ([company length] == 0) @@ -696,7 +696,7 @@ - (NSString *) fullName { CardElement *n; NSString *fn, *firstName, *lastName, *org; - + fn = [self fn]; if ([fn length] == 0) { @@ -723,6 +723,29 @@ - (NSString *) fullName return fn; } +- (NSArray *) emails +{ + NSArray *elements; + NSMutableArray *emails; + NSString *email; + int i; + + emails = [NSMutableArray array]; + elements = [self childrenWithTag: @"email"]; + + for (i = [elements count]-1; i >= 0; i--) + { + email = [[elements objectAtIndex: i] flattenedValuesForKey: @""]; + if ([email caseInsensitiveCompare: [self preferredEMail]] == NSOrderedSame) + // First element of array is the preferred email address + [emails insertObject: email atIndex: 0]; + else + [emails addObject: email]; + } + + return emails; +} + - (NSArray *) secondaryEmails { NSMutableArray *emails; @@ -735,11 +758,11 @@ - (NSArray *) secondaryEmails [emails removeObjectsInArray: [self childrenWithTag: @"email" andAttribute: @"type" havingValue: @"pref"]]; - + for (i = [emails count]-1; i >= 0; i--) { email = [[emails objectAtIndex: i] flattenedValuesForKey: @""]; - + if ([email caseInsensitiveCompare: [self preferredEMail]] == NSOrderedSame) [emails removeObjectAtIndex: i]; } @@ -771,7 +794,7 @@ - (NSString *) _phoneOfType: (NSString *) aType if (!aTypeToExclude) break; - + if (![ce hasAttribute: @"type" havingValue: aTypeToExclude]) break; @@ -824,7 +847,7 @@ - (NSCalendarDate *) birthday andShortTimeString: nil inTimeZone: [NSTimeZone timeZoneWithName: @"GMT"]]; } - + return date; } @@ -849,10 +872,12 @@ - (NSMutableDictionary *) quickRecordFromContent: (NSString *) theContent value = [self preferredTel]; if (value) [fields setObject: value forKey: @"c_telephonenumber"]; - value = [self preferredEMail]; - if (![value isNotNull]) - value = @""; - [fields setObject: value forKey: @"c_mail"]; + v = [self emails]; + if ([v count] > 0) + [fields setObject: [v componentsJoinedByString: @","] + forKey: @"c_mail"]; + else + [fields setObject: [NSNull null] forKey: @"c_mail"]; element = [self org]; [fields setObject: [element flattenedValueAtIndex: 0 forKey: @""] forKey: @"c_o"]; diff --git a/SoObjects/Contacts/SOGoContactGCSFolder.m b/SoObjects/Contacts/SOGoContactGCSFolder.m index bed89682f4..1cd2720f7f 100644 --- a/SoObjects/Contacts/SOGoContactGCSFolder.m +++ b/SoObjects/Contacts/SOGoContactGCSFolder.m @@ -264,9 +264,23 @@ - (void) fixupContactRecord: (NSMutableDictionary *) contactRecord data = [contactRecord objectForKey: @"c_mail"]; if ([data length]) { + NSArray *values; NSDictionary *email; - email = [NSDictionary dictionaryWithObjectsAndKeys: @"pref", @"type", data, @"value", nil]; - [contactRecord setObject: [NSArray arrayWithObject: email] forKey: @"emails"]; + NSMutableArray *emails; + NSString *type, *value; + int i, max; + + values = [data componentsSeparatedByString: @","]; + max = [values count]; + emails = [NSMutableArray arrayWithCapacity: max]; + for (i = 0; i < max; i++) + { + type = (i == 0)? @"pref" : @"home"; + value = [values objectAtIndex: i]; + email = [NSDictionary dictionaryWithObjectsAndKeys: type, @"type", value, @"value", nil]; + [emails addObject: email]; + } + [contactRecord setObject: emails forKey: @"emails"]; } else { diff --git a/UI/Templates/MailerUI/UIxMailEditor.wox b/UI/Templates/MailerUI/UIxMailEditor.wox index 468e628d70..1d340c86df 100644 --- a/UI/Templates/MailerUI/UIxMailEditor.wox +++ b/UI/Templates/MailerUI/UIxMailEditor.wox @@ -64,7 +64,7 @@ md-selected-item="editor.autocomplete.to.selected" md-items="user in editor.contactFilter(editor.autocomplete.to.searchText)" md-min-length="3" - md-delay="300" + md-delay="150" md-no-cache="true" label:placeholder="Add a recipient"> diff --git a/UI/WebServerResources/js/Contacts/Card.service.js b/UI/WebServerResources/js/Contacts/Card.service.js index cdfcbd665c..5390a839fd 100644 --- a/UI/WebServerResources/js/Contacts/Card.service.js +++ b/UI/WebServerResources/js/Contacts/Card.service.js @@ -424,6 +424,27 @@ return this.refs.length - 1; }; + /** + * @function explode + * @memberof Card.prototype + * @desc Create a new Card associated to each email address of this card. + * @return an array of Card instances + */ + Card.prototype.explode = function() { + var _this = this, cards = [], data; + + if (this.emails.length > 1) { + data = this.$omit(); + _.forEach(this.emails, function(email) { + var card = new Card(angular.extend({}, data, {emails: [email]})); + cards.push(card); + }); + return cards; + } + else + return [this]; + }; + /** * @function $reset * @memberof Card.prototype diff --git a/UI/WebServerResources/js/Mailer/MessageEditorController.js b/UI/WebServerResources/js/Mailer/MessageEditorController.js index 69a8227d53..2605536388 100644 --- a/UI/WebServerResources/js/Mailer/MessageEditorController.js +++ b/UI/WebServerResources/js/Mailer/MessageEditorController.js @@ -197,8 +197,20 @@ } function contactFilter($query) { - AddressBook.$filterAll($query); - return AddressBook.$cards; + return AddressBook.$filterAll($query).then(function(cards) { + // Divide the matching cards by email addresses so the user can select + // the recipient address of her choice + var explodedCards = []; + _.forEach(_.invokeMap(cards, 'explode'), function(manyCards) { + _.forEach(manyCards, function(card) { + explodedCards.push(card); + }); + }); + // Remove duplicates + return _.uniqBy(explodedCards, function(card) { + return card.$$fullname + ' ' + card.$$email; + }); + }); } function addRecipient(contact, field) {