[IMP] website_sale_autocomplete: don't search if less than 5 char

In case of error (wrong whitelisted ip e.g.), the error was not visible.
Now we log it in odoo-log.

Add arbitrary limit of 5 char before to make api call
(limit: 'Rue X', 'Street', ...)

Hide suggested dropdown if less than 5 chars or no results (in case of
error, results are empty and so dropdown not with class 'show')

task-2806842 (partially)

closes odoo/odoo#95773

X-original-commit: 387d19208fc97259c5786c5098c02ccc248c53ae
Signed-off-by: Jérémy Kersten <jke@odoo.com>
This commit is contained in:
Jeremy Kersten
2022-07-12 06:20:57 +02:00
parent 3fe33487e1
commit 8a18d7a20f
5 changed files with 57 additions and 30 deletions
@@ -6,6 +6,10 @@ from odoo import http
from odoo.http import request
from odoo.tools import html2plaintext
import logging
_logger = logging.getLogger(__name__)
FIELDS_MAPPING = {
'country': ['country'],
'street_number': ['number'],
@@ -63,6 +67,12 @@ class AutoCompleteController(http.Controller):
return guessed_house_number
def _perform_place_search(self, partial_address, api_key=None, session_id=None, language_code=None, country_code=None):
if len(partial_address) <= 5:
return {
'results': [],
'session_id': session_id
}
params = {
'key': api_key,
'fields': 'formatted_address,name',
@@ -79,11 +89,16 @@ class AutoCompleteController(http.Controller):
try:
results = requests.get(f'{GOOGLE_PLACES_ENDPOINT}/autocomplete/json', params=params, timeout=TIMEOUT).json()
except (TimeoutError, ValueError):
except (TimeoutError, ValueError) as e:
_logger.error(e)
return {
'results': [],
'session_id': session_id
}
if results.get('error_message'):
_logger.error(results['error_message'])
results = results.get('predictions', [])
# Convert google specific format to standard format.
@@ -109,9 +124,13 @@ class AutoCompleteController(http.Controller):
try:
results = requests.get(f'{GOOGLE_PLACES_ENDPOINT}/details/json', params=params, timeout=TIMEOUT).json()
except (TimeoutError, ValueError):
except (TimeoutError, ValueError) as e:
_logger.error(e)
return {'address': None}
if results.get('error_message'):
_logger.error(results['error_message'])
try:
html_address = results['result']['adr_address']
results = results['result']['address_components'] # Get rid of useless extra data
@@ -9,3 +9,6 @@ class Website(models.Model):
google_places_api_key = fields.Char(
string='Google Places API Key',
groups="base.group_system")
def has_google_places_api_key(self):
return bool(self.sudo().google_places_api_key)
@@ -20,7 +20,7 @@ publicWidget.registry.AddressForm = publicWidget.Widget.extend({
this.countrySelect = document.querySelector('select[name="country_id"]');
this.stateSelect = document.querySelector('select[name="state_id"]');
this.dp = new DropPrevious();
this.sessionId = this._generateUUID()
this.sessionId = this._generateUUID();
this._onChangeStreet = debounce(this._onChangeStreet, 200);
this._super.apply(this, arguments);
@@ -38,30 +38,36 @@ publicWidget.registry.AddressForm = publicWidget.Widget.extend({
});
},
_onChangeStreet: async function(ev) {
this.dp.add(
this._rpc({
route: '/autocomplete/address',
params: {
partial_address: ev.currentTarget.value,
session_id: this.sessionId || null
_hideAutocomplete: function (inputContainer) {
const dropdown = inputContainer.querySelector('.dropdown-menu');
if (dropdown) {
dropdown.remove();
}
},
_onChangeStreet: async function (ev) {
const inputContainer = ev.currentTarget.parentNode;
if (ev.currentTarget.value.length >= 5) {
this.dp.add(
this._rpc({
route: '/autocomplete/address',
params: {
partial_address: ev.currentTarget.value,
session_id: this.sessionId || null
}
})).then((response) => {
this._hideAutocomplete(inputContainer);
inputContainer.appendChild($(QWeb.render("website_sale_autocomplete.AutocompleteDropDown", {
results: response.results
}))[0]);
if (response.session_id) {
this.sessionId = response.session_id;
}
}
})).then((response) => {
if (response.results) {
const inputContainer = ev.currentTarget.parentNode;
const dropdown = inputContainer.querySelector('.dropdown-menu');
if (dropdown) {
dropdown.remove();
}
inputContainer.appendChild($(QWeb.render("website_sale_autocomplete.AutocompleteDropDown", {
results: response.results
}))[0]);
}
if (response.session_id) {
this.sessionId = response.session_id;
}
}
);
);
} else {
this._hideAutocomplete(inputContainer);
}
},
_onClickAutocompleteResult: async function(ev) {
@@ -2,14 +2,13 @@
<templates>
<t t-name="website_sale_autocomplete.AutocompleteDropDown">
<div t-attf-class="dropdown-menu w-100 #{results ? 'show' : ''}">
<div t-attf-class="dropdown-menu w-100 #{results.length ? 'show' : ''}">
<a class="dropdown-item js_autocomplete_result"
t-foreach="results" t-as="result"
t-att-data-google-place-id="result['google_place_id']">
<t t-out="result['formatted_address']"/>
</a>
<img class="p-2" src="/website_sale_autocomplete/static/src/img/powered_by_google_on_white.png" alt="Powered by Google"/>
<img class="pull-right pr-1" src="/website_sale_autocomplete/static/src/img/powered_by_google_on_white.png" alt="Powered by Google"/>
</div>
</t>
</templates>
@@ -4,7 +4,7 @@
<template id="website_sale_address_with_autocomplete" inherit_id="website_sale.address">
<xpath expr="//input[@name='street']" position="attributes">
<attribute name="t-att-data-autocomplete-enabled">
1 if website.sudo().google_places_api_key else 0
1 if website.has_google_places_api_key() else 0
</attribute>
</xpath>
</template>