Skip to content

Commit

Permalink
Expose all email addresses in autocompletion
Browse files Browse the repository at this point in the history
This change is immediately applicable to LDAP-based system address
books. However, personal SQL-based address books must have their quick
tables recreated. To do so, one must use sogo-tool to backup and restore
the user's data.

Resolves #3443, #3526
  • Loading branch information
cgx committed May 25, 2016
1 parent 6dc80e1 commit fd4b094
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 28 deletions.
3 changes: 3 additions & 0 deletions 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
Expand Down
71 changes: 48 additions & 23 deletions SoObjects/Contacts/NGVCard+SOGo.m
Expand Up @@ -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 ) )
Expand All @@ -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 $
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand All @@ -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: @""];
Expand Down Expand Up @@ -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];
Expand All @@ -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;
Expand All @@ -377,7 +377,7 @@ - (NSString *) _simpleValueForType: (NSString *) aType

if (!aTypeToExclude)
break;

if (![ce hasAttribute: @"type" havingValue: aTypeToExclude])
break;

Expand Down Expand Up @@ -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 &&
Expand Down Expand Up @@ -640,7 +640,7 @@ - (NSMutableDictionary *) asLDIFRecord
}
}
}

[self _setValue: @"title" to: [self title] inLDIFRecord: ldifRecord];
[self _setupOrgFieldsInLDIFRecord: ldifRecord];

Expand Down Expand Up @@ -683,7 +683,7 @@ - (NSString *) workCompany
{
CardElement *org;
NSString *company;

org = [self org];
company = [org flattenedValueAtIndex: 0 forKey: @""];
if ([company length] == 0)
Expand All @@ -696,7 +696,7 @@ - (NSString *) fullName
{
CardElement *n;
NSString *fn, *firstName, *lastName, *org;

fn = [self fn];
if ([fn length] == 0)
{
Expand All @@ -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;
Expand All @@ -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];
}
Expand Down Expand Up @@ -771,7 +794,7 @@ - (NSString *) _phoneOfType: (NSString *) aType

if (!aTypeToExclude)
break;

if (![ce hasAttribute: @"type" havingValue: aTypeToExclude])
break;

Expand Down Expand Up @@ -824,7 +847,7 @@ - (NSCalendarDate *) birthday
andShortTimeString: nil
inTimeZone: [NSTimeZone timeZoneWithName: @"GMT"]];
}

return date;
}

Expand All @@ -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"];
Expand Down
18 changes: 16 additions & 2 deletions SoObjects/Contacts/SOGoContactGCSFolder.m
Expand Up @@ -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
{
Expand Down
2 changes: 1 addition & 1 deletion UI/Templates/MailerUI/UIxMailEditor.wox
Expand Up @@ -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">
<md-item-template>
Expand Down
21 changes: 21 additions & 0 deletions UI/WebServerResources/js/Contacts/Card.service.js
Expand Up @@ -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
Expand Down
16 changes: 14 additions & 2 deletions UI/WebServerResources/js/Mailer/MessageEditorController.js
Expand Up @@ -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) {
Expand Down

0 comments on commit fd4b094

Please sign in to comment.