diff --git a/addons/web_editor/static/src/js/editor/snippets.options.js b/addons/web_editor/static/src/js/editor/snippets.options.js index d3fd4442efc..deb72ac4f99 100644 --- a/addons/web_editor/static/src/js/editor/snippets.options.js +++ b/addons/web_editor/static/src/js/editor/snippets.options.js @@ -4438,8 +4438,10 @@ const SnippetOptionWidget = Widget.extend({ return; } + this.__willReload = requiresReload; // Call widget option methods and update $target await this._select(previewMode, widget); + this.__willReload = false; // If it is not preview mode, the user selected the option for good // (so record the action) diff --git a/addons/website/static/src/js/editor/snippets.options.js b/addons/website/static/src/js/editor/snippets.options.js index d8f8b0246e3..c4261a0e735 100644 --- a/addons/website/static/src/js/editor/snippets.options.js +++ b/addons/website/static/src/js/editor/snippets.options.js @@ -656,6 +656,7 @@ options.userValueWidgetsRegistry['we-gpspicker'] = GPSPicker; options.Class.include({ custom_events: Object.assign({}, options.Class.prototype.custom_events || {}, { 'google_fonts_custo_request': '_onGoogleFontsCustoRequest', + 'request_save': '_onSaveRequest', }), specialCheckAndReloadMethodsNames: ['customizeWebsiteViews', 'customizeWebsiteVariable', 'customizeWebsiteColor'], @@ -1029,6 +1030,22 @@ options.Class.include({ reloadEditor: true, }); }, + /** + * This handler prevents reloading the page twice with a `request_save` + * event when a widget is already going to handle reloading the page. + * + * @param {OdooEvent} ev + */ + _onSaveRequest(ev) { + // If a widget requires a reload, any subsequent request to save is + // useless, as the reload will save the page anyway. It can cause + // a race condition where the wysiwyg attempts to reload the page twice, + // so ignore the request. + if (this.__willReload) { + ev.stopPropagation(); + return; + } + } }); function _getLastPreFilterLayerElement($el) { diff --git a/addons/website_sale/static/src/js/website_sale.editor.js b/addons/website_sale/static/src/js/website_sale.editor.js index 28d64feed79..88f35a5fa56 100644 --- a/addons/website_sale/static/src/js/website_sale.editor.js +++ b/addons/website_sale/static/src/js/website_sale.editor.js @@ -51,14 +51,14 @@ options.registry.WebsiteSaleGridLayout = options.Class.extend({ */ setPpr: function (previewMode, widgetValue, params) { this.ppr = parseInt(widgetValue); - this.rpc('/shop/config/website', { 'shop_ppr': this.ppr }); + return this.rpc('/shop/config/website', { 'shop_ppr': this.ppr }); }, /** * @see this.selectClass for params */ setDefaultSort: function (previewMode, widgetValue, params) { this.default_sort = widgetValue; - this.rpc('/shop/config/website', { 'shop_default_sort': this.default_sort }); + return this.rpc('/shop/config/website', { 'shop_default_sort': this.default_sort }); }, //-------------------------------------------------------------------------- @@ -488,7 +488,9 @@ options.registry.WebsiteSaleProductPage = options.Class.extend({ }, _updateWebsiteConfig(params) { - this.rpc('/shop/config/website', params).then(() => this.trigger_up('request_save', {reload: true, optionSelector: this.data.selector})); + // TODO: Remove the request_save in master, it's already done by the + // data-page-options set to true in the template. + return this.rpc('/shop/config/website', params).then(() => this.trigger_up('request_save', {reload: true, optionSelector: this.data.selector})); }, _getZoomOptionData() { @@ -504,11 +506,11 @@ options.registry.WebsiteSaleProductPage = options.Class.extend({ const zoomOption = this._getZoomOptionData(); const updateWidth = this._updateWebsiteConfig.bind(this, { product_page_image_width: widgetValue }); if (!zoomOption || widgetValue !== "100_pc") { - updateWidth(); + await updateWidth(); } else { const defaultZoomOption = "website_sale.product_picture_magnify_click"; await this._customizeWebsiteData(defaultZoomOption, { possibleValues: zoomOption._methodsParams.optionsPossibleValues["customizeWebsiteViews"] }, true); - updateWidth(); + await updateWidth(); } }, @@ -519,7 +521,7 @@ options.registry.WebsiteSaleProductPage = options.Class.extend({ const zoomOption = this._getZoomOptionData(); const updateLayout = this._updateWebsiteConfig.bind(this, { product_page_image_layout: widgetValue }); if (!zoomOption) { - updateLayout(); + await updateLayout(); } else { const imageWidthOption = this.productDetailMain.dataset.image_width; let defaultZoomOption = widgetValue === "grid" ? "website_sale.product_picture_magnify_click" : "website_sale.product_picture_magnify_hover"; @@ -527,7 +529,7 @@ options.registry.WebsiteSaleProductPage = options.Class.extend({ defaultZoomOption = "website_sale.product_picture_magnify_click"; } await this._customizeWebsiteData(defaultZoomOption, { possibleValues: zoomOption._methodsParams.optionsPossibleValues["customizeWebsiteViews"] }, true); - updateLayout(); + await updateLayout(); } }, @@ -672,17 +674,21 @@ options.registry.WebsiteSaleProductPage = options.Class.extend({ 2: 'medium', 3: 'big', }[widgetValue]; - this.rpc('/shop/config/website', { + this.productPageGrid.dataset.image_spacing = spacing; + // TODO: Remove the request_save in master, it's already done by the + // data-page-options set to true in the template. + return this.rpc('/shop/config/website', { 'product_page_image_spacing': spacing, }).then(() => this.trigger_up('request_save', {reload: true, optionSelector: this.data.selector})); - this.productPageGrid.dataset.image_spacing = spacing; }, setColumns(previewMode, widgetValue, params) { - this.rpc('/shop/config/website', { + this.productPageGrid.dataset.grid_columns = widgetValue; + // TODO: Remove the request_save in master, it's already done by the + // data-page-options set to true in the template. + return this.rpc('/shop/config/website', { 'product_page_grid_columns': widgetValue, }).then(() => this.trigger_up('request_save', {reload: true, optionSelector: this.data.selector})); - this.productPageGrid.dataset.grid_columns = widgetValue; }, /**