Bug 1037114 - Implement contacts list filtering on Name, Last Name and Mail. r=mikedeboer

This commit is contained in:
Paolo Amadini
2014-10-03 19:04:13 +01:00
parent 2a76119ae1
commit d2092e21fc
3 changed files with 117 additions and 71 deletions

View File

@@ -17,6 +17,29 @@ loop.contacts = (function(_, mozL10n) {
// Number of contacts to add to the list at the same time.
const CONTACTS_CHUNK_SIZE = 100;
// At least this number of contacts should be present for the filter to appear.
const MIN_CONTACTS_FOR_FILTERING = 7;
let getContactNames = function(contact) {
// The model currently does not enforce a name to be present, but we're
// going to assume it is awaiting more advanced validation of required fields
// by the model. (See bug 1069918)
// NOTE: this method of finding a firstname and lastname is not i18n-proof.
let names = contact.name[0].split(" ");
return {
firstName: names.shift(),
lastName: names.join(" ")
};
};
let getPreferredEmail = function(contact) {
// A contact may not contain email addresses, but only a phone number.
if (!contact.email || contact.email.length == 0) {
return { value: "" };
}
return contact.email.find(e => e.pref) || contact.email[0];
};
const ContactDropdown = React.createClass({displayName: 'ContactDropdown',
propTypes: {
handleAction: React.PropTypes.func.isRequired,
@@ -137,7 +160,7 @@ loop.contacts = (function(_, mozL10n) {
return (
currContact.name[0] !== nextContact.name[0] ||
currContact.blocked !== nextContact.blocked ||
this.getPreferredEmail(currContact).value !== this.getPreferredEmail(nextContact).value
getPreferredEmail(currContact).value !== getPreferredEmail(nextContact).value
);
},
@@ -147,34 +170,6 @@ loop.contacts = (function(_, mozL10n) {
}
},
getContactNames: function() {
// The model currently does not enforce a name to be present, but we're
// going to assume it is awaiting more advanced validation of required fields
// by the model. (See bug 1069918)
// NOTE: this method of finding a firstname and lastname is not i18n-proof.
let names = this.props.contact.name[0].split(" ");
return {
firstName: names.shift(),
lastName: names.join(" ")
};
},
getPreferredEmail: function(contact = this.props.contact) {
let email;
// A contact may not contain email addresses, but only a phone number instead.
if (contact.email) {
email = contact.email[0];
contact.email.some(function(address) {
if (address.pref) {
email = address;
return true;
}
return false;
});
}
return email || { value: "" };
},
canEdit: function() {
// We cannot modify imported contacts. For the moment, the check for
// determining whether the contact is imported is based on its category.
@@ -182,8 +177,8 @@ loop.contacts = (function(_, mozL10n) {
},
render: function() {
let names = this.getContactNames();
let email = this.getPreferredEmail();
let names = getContactNames(this.props.contact);
let email = getPreferredEmail(this.props.contact);
let cx = React.addons.classSet;
let contactCSSClass = cx({
contact: true,
@@ -218,10 +213,13 @@ loop.contacts = (function(_, mozL10n) {
});
const ContactsList = React.createClass({displayName: 'ContactsList',
mixins: [React.addons.LinkedStateMixin],
getInitialState: function() {
return {
contacts: {},
importBusy: false
importBusy: false,
filter: "",
};
},
@@ -344,6 +342,24 @@ loop.contacts = (function(_, mozL10n) {
return contact.blocked ? "blocked" : "available";
});
let showFilter = Object.getOwnPropertyNames(this.state.contacts).length >=
MIN_CONTACTS_FOR_FILTERING;
if (showFilter) {
let filter = this.state.filter.trim().toLocaleLowerCase();
if (filter) {
let filterFn = contact => {
return contact.name[0].toLocaleLowerCase().contains(filter) ||
getPreferredEmail(contact).value.toLocaleLowerCase().contains(filter);
};
if (shownContacts.available) {
shownContacts.available = shownContacts.available.filter(filterFn);
}
if (shownContacts.blocked) {
shownContacts.blocked = shownContacts.blocked.filter(filterFn);
}
}
}
// TODO: bug 1076767 - add a spinner whilst importing contacts.
return (
React.DOM.div(null,
@@ -356,13 +372,18 @@ loop.contacts = (function(_, mozL10n) {
onClick: this.handleImportButtonClick}),
Button({caption: mozL10n.get("new_contact_button"),
onClick: this.handleAddContactButtonClick})
)
),
showFilter ?
React.DOM.input({className: "contact-filter",
placeholder: mozL10n.get("contacts_search_placesholder"),
valueLink: this.linkState("filter")})
: null
),
React.DOM.ul({className: "contact-list"},
shownContacts.available ?
shownContacts.available.sort(this.sortContacts).map(viewForItem) :
null,
shownContacts.blocked ?
shownContacts.blocked && shownContacts.blocked.length > 0 ?
React.DOM.div({className: "contact-separator"}, mozL10n.get("contacts_blocked_contacts")) :
null,
shownContacts.blocked ?