Please make sure you backup your file, before change as below:
If you can wait, this feature is out of the box V11.
frappe-bench/apps/frappe/frappe/email/__init__.py
Replace method get_contact_list with below
@frappe.whitelist()
def get_contact_list(txt):
"""Returns contacts (from autosuggest)"""
txt = txt.replace('%', '')
def get_users():
return filter(None, frappe.db.sql('select email as value, concat(first_name, " ", last_name) as description from tabUser where email like %s',
('%' + txt + '%'), as_dict = True))
try:
out = filter(None, frappe.db.sql("""select distinct email_id as value, concat(first_name, " ", last_name) as description from `tabContact`
where email_id like %(txt)s or concat(first_name, " ", last_name) like %(txt)s order by
if (locate( %(_txt)s, concat(first_name, " ", last_name)), locate( %(_txt)s, concat(first_name, " ", last_name)), 99999),
if (locate( %(_txt)s, email_id), locate( %(_txt)s, email_id), 99999)""",
{'txt': "%%%s%%" % frappe.db.escape(txt),
'_txt': txt.replace("%", "")
}, as_dict = True)
)
if not out:
out = get_users()
except Exception as e:
if e.args[0]==1146:
# no Contact, use User
out = get_users()
else:
raise
return out
frappe-bench/apps/frappe/frappe/public/js/frappe/views/communication.js
replace function setup_awesomplete_for_input with below:
setup_awesomplete_for_input: function(input) {
function split(val) {
return val.split( /,\s*/ );
}
function extractLast(term) {
return split(term).pop();
}
var awesomplete = new Awesomplete(input, {
minChars: 0,
maxItems: 99,
autoFirst: true,
data: function(item) {
if(!(item instanceof Object)) {
var d = {"value": item};
item = d;
}
return {
label: item.label || item.value,
value: item.value
};
},
item: function(item) {
var d = this.get_item(item.value);
if(!d) {
d = item;
}
if (!d.label) {
d.label = d.value;
}
var _label = d.label;
var html = "<strong>" + _label + "</strong>";
if(d.description && d.value!==d.description) {
html += '<br><span class="small">' + __(d.description) + '</span>';
}
return $('<li></li>')
.data('item.autocomplete', d)
.prop('aria-selected', 'false')
.html('<a><p>' + html + '</p></a>')
.get(0);
},
sort: () => {
return 0;
},
list: [],
filter: function(text, input) { return true },
replace: function(text) {
var before = this.input.value.match(/^.+,\s*|/)[0];
this.input.value = before + text + ", ";
}
});
var delay_timer;
var $input = $(input);
$input.on("input", function(e) {
clearTimeout(delay_timer);
delay_timer = setTimeout(function() {
var term = e.target.value;
frappe.call({
method:'frappe.email.get_contact_list',
args: {
'txt': extractLast(term) || '%'
},
quiet: true,
callback: function(r) {
awesomplete.list = r.message || [];
}
});
},250);
});
}
Then run command:
bench clear-cache
bench build
bench restart