[FIX] website: restore google map UI for special google map snippet

Since [1], the google map UI to search for locations thanks to the
google map API was not working anymore. Indeed, the lib was loaded
inside the iframe (as it should) but not outside of it, preventing to
use the `google` object in the related editor panel widget. The
autocomplete UI style was also broken as the CSS is not available
outside the iframe.

As a fix, the code outside the iframe now use the `google` object from
inside the iframe (no problem seems to come out of it) and the style is
restored via custom CSS (custom CSS already existed and was already
changing most default style anyway).

As a reminder, this snippet is only available in debug mode or if your
google map key is setup, which we do not allow to enter anymore via
standard flow since 16.0 (15.3).

[1]: https://github.com/odoo/odoo/commit/31cc10b91dc7762e23b4bde9b945be0c4ce3fe3b

closes odoo/odoo#106103

X-original-commit: 7d60d0ae4ea195edc4a12e57bf1c3b7c661bcf82
Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
This commit is contained in:
qsm-odoo
2022-11-21 21:18:58 +01:00
parent 2b640b2c2a
commit 7f610369bc
2 changed files with 61 additions and 14 deletions
@@ -1,4 +1,3 @@
/* globals google*/
odoo.define('website.editor.snippets.options', function (require) {
'use strict';
@@ -316,6 +315,11 @@ const GPSPicker = InputUserValueWidget.extend({
init() {
this._super(...arguments);
this._gmapCacheGPSToPlace = {};
// The google API will be loaded inside the website iframe. Let's try
// not having to load it in the backend too and just using the iframe
// google object instead.
this.contentWindow = this.$target[0].ownerDocument.defaultView;
},
/**
* @override
@@ -354,8 +358,23 @@ const GPSPicker = InputUserValueWidget.extend({
return;
}
this._gmapAutocomplete = new google.maps.places.Autocomplete(this.inputEl, {types: ['geocode']});
google.maps.event.addListener(this._gmapAutocomplete, 'place_changed', this._onPlaceChanged.bind(this));
this._gmapAutocomplete = new this.contentWindow.google.maps.places.Autocomplete(this.inputEl, {types: ['geocode']});
this.contentWindow.google.maps.event.addListener(this._gmapAutocomplete, 'place_changed', this._onPlaceChanged.bind(this));
},
/**
* @override
*/
destroy() {
this._super(...arguments);
// Without this, the google library injects elements inside the backend
// DOM but do not remove them once the editor is left. Notice that
// this is also done when the widget is destroyed for another reason
// than leaving the editor, but if the google API needs that container
// again afterwards, it will simply recreate it.
for (const el of document.body.querySelectorAll('.pac-container')) {
el.remove();
}
},
//--------------------------------------------------------------------------
@@ -400,9 +419,9 @@ const GPSPicker = InputUserValueWidget.extend({
}
const p = gps.substring(1).slice(0, -1).split(',');
const location = new google.maps.LatLng(p[0] || 0, p[1] || 0);
const location = new this.contentWindow.google.maps.LatLng(p[0] || 0, p[1] || 0);
return new Promise(resolve => {
const service = new google.maps.places.PlacesService(document.createElement('div'));
const service = new this.contentWindow.google.maps.places.PlacesService(document.createElement('div'));
service.nearbySearch({
// Do a 'nearbySearch' followed by 'getDetails' to avoid using
// GMap Geocoder which the user may not have enabled... but
@@ -411,13 +430,16 @@ const GPSPicker = InputUserValueWidget.extend({
location: location,
radius: 1,
}, (results, status) => {
const GMAP_CRITICAL_ERRORS = [google.maps.places.PlacesServiceStatus.REQUEST_DENIED, google.maps.places.PlacesServiceStatus.UNKNOWN_ERROR];
if (status === google.maps.places.PlacesServiceStatus.OK) {
const GMAP_CRITICAL_ERRORS = [
this.contentWindow.google.maps.places.PlacesServiceStatus.REQUEST_DENIED,
this.contentWindow.google.maps.places.PlacesServiceStatus.UNKNOWN_ERROR
];
if (status === this.contentWindow.google.maps.places.PlacesServiceStatus.OK) {
service.getDetails({
placeId: results[0].place_id,
fields: ['geometry', 'formatted_address'],
}, (place, status) => {
if (status === google.maps.places.PlacesServiceStatus.OK) {
if (status === this.contentWindow.google.maps.places.PlacesServiceStatus.OK) {
this._gmapCacheGPSToPlace[gps] = place;
resolve(place);
} else if (GMAP_CRITICAL_ERRORS.includes(status)) {
@@ -231,29 +231,54 @@ $i: 1;
border-bottom: none !important;
}
.pac-container { // google map autosuggestion
.pac-container { // google map autosuggestion (note: their CSS lib is not used)
z-index: $zindex-modal-backdrop; // > $o-we-zindex
width: $o-we-sidebar-width !important;
width: ceil($o-we-sidebar-width * 0.9) !important;
font-size: $o-we-sidebar-font-size;
margin-left: -$o-we-sidebar-width/2;
border: $o-we-sidebar-content-field-border-width solid $o-we-sidebar-content-field-dropdown-border-color;
border-top: none;
border-radius: $o-we-item-border-radius;
overflow: hidden;
background-color: $o-we-sidebar-content-field-dropdown-bg;
box-shadow: $o-we-sidebar-content-field-dropdown-shadow;
margin-top: $o-we-sidebar-content-field-dropdown-spacing;
transform: translate(41px);
&:after {
display: none;
}
.pac-item {
@include o-text-overflow(block);
line-height: $o-we-sidebar-content-field-dropdown-item-height;
color: $o-we-sidebar-content-field-clickable-color;
padding: 0 1em 0 (2 * $o-we-sidebar-content-field-control-item-spacing + $o-we-sidebar-content-field-control-item-size);
border-top: $o-we-sidebar-content-field-border-width solid lighten($o-we-sidebar-content-field-dropdown-border-color, 15%);
border-radius: $o-we-sidebar-content-field-border-radius;
background-color: $o-we-sidebar-content-field-clickable-bg;
color: $o-we-sidebar-content-field-clickable-color;
&:hover {
font-size: $o-we-sidebar-font-size;
&:hover, &:focus, &.pac-item-selected {
background-color: $o-we-sidebar-content-field-dropdown-item-bg-hover;
cursor: pointer;
}
}
.pac-item-query {
color: $o-we-sidebar-content-field-clickable-color;
.pac-icon-marker {
position: absolute;
margin-left: -1em;
&::after {
content: '\f041';
font-family: FontAwesome;
}
}
.pac-item-query {
margin-right: 0.4em;
color: inherit;
}
}
}