From 28f0db302a2087372ab5690ddf8dff4fe74d3702 Mon Sep 17 00:00:00 2001 From: qsm-odoo Date: Wed, 21 Sep 2022 13:00:42 +0000 Subject: [PATCH] [FIX] web_editor, website: fix saving multiple contents at once Since [1], as part of the new translation system made with [2], saving multiple elements in a website page was only saving the first one. E.g. - Enter edit mode of your homepage - Add something in the main area of the page - Add something in the footer - Save => Only the main area is saved, not the footer. This was actually the same in translate mode... only translation of the first edited area could be saved. At least, with the bug fixed version of [1] comes the small advantage of not saving multiple times the same field (except for view parts). E.g.: an event's dates are displayed multiple times in different formats -> in 15.0, 3 RPC were made by date changed, now only one is made. [1]: https://github.com/odoo/odoo/commit/1b473cf0db4d85c2b523ac87fbab533bce5f3e21 [2]: https://github.com/odoo/odoo/commit/4e82c45abdb0b420edead2bd1d0ba9ff4bb4a224 closes odoo/odoo#100762 X-original-commit: c834d151afed0ca633ffb6bcba2f45b544689e74 Signed-off-by: Romain Derie (rde) --- .../static/src/js/wysiwyg/wysiwyg.js | 42 ++++++++++++++----- .../static/tests/tours/multi_edition.js | 36 ++++++++++++++++ addons/website/tests/test_ui.py | 3 ++ 3 files changed, 71 insertions(+), 10 deletions(-) create mode 100644 addons/website/static/tests/tours/multi_edition.js diff --git a/addons/web_editor/static/src/js/wysiwyg/wysiwyg.js b/addons/web_editor/static/src/js/wysiwyg/wysiwyg.js index 74dfd68141a..8080389feb5 100644 --- a/addons/web_editor/static/src/js/wysiwyg/wysiwyg.js +++ b/addons/web_editor/static/src/js/wysiwyg/wysiwyg.js @@ -2159,10 +2159,36 @@ const Wysiwyg = Widget.extend({ $('.o_editable') .removeClass('o_editable o_is_inline_editable o_editable_date_field_linked o_editable_date_field_format_changed'); - const defs = _.map(_.groupBy($allBlocks.toArray(), - function($obj) { - return $obj.dataset['oe-model'] + $obj.dataset['oe-field'] + $obj.dataset['oe-id'] - }), (els) => { + const saveElementFuncName = this.options.enableTranslation + ? '_saveTranslationElement' + : '_saveElement'; + + // Group elements to save if possible. + const groupedElements = _.groupBy($allBlocks.toArray(), el => { + const model = el.dataset.oeModel; + const field = el.dataset.oeField; + + // There are elements which have no linked model as something + // special is to be done "to save them" (potential override to + // `_saveElement` which is expected to be called for each unique + // dirty element). In that case, do not group those elements. + if (!model) { + return _.uniqueId('special-element-to-save-'); + } + + // Do not group elements which are parts of views, unless we are + // in translate mode. + if (!this.options.enableTranslation + && (model === 'ir.ui.view' && field === 'arch')) { + return _.uniqueId('view-part-to-save-'); + } + + // Otherwise, group elements which are from the same field of the + // same record (`_saveElement` will only consider the first one and + // `_saveTranslationElement` can handle the set if it makes sense). + return `${model}::${el.dataset.oeId}::${field}`; + }); + const proms = Object.values(groupedElements).map(els => { const $els = $(els); $els.find('[class]').filter(function () { @@ -2173,11 +2199,7 @@ const Wysiwyg = Widget.extend({ // TODO: Add a queue with concurrency limit in webclient return this.saving_mutex.exec(() => { - let saveElement = '_saveElement'; - if (this.options.enableTranslation) { - saveElement = '_saveTranslationElement'; - } - return this[saveElement]($els, context || this.options.context) + return this[saveElementFuncName]($els, context || this.options.context) .then(function () { $els.removeClass('o_dirty'); }).guardedCatch(function (response) { @@ -2198,7 +2220,7 @@ const Wysiwyg = Widget.extend({ }); }); }); - return Promise.all(defs).then(function () { + return Promise.all(proms).then(function () { window.onbeforeunload = null; }).guardedCatch((failed) => { // If there were errors, re-enable edition diff --git a/addons/website/static/tests/tours/multi_edition.js b/addons/website/static/tests/tours/multi_edition.js new file mode 100644 index 00000000000..bfa5472e4a8 --- /dev/null +++ b/addons/website/static/tests/tours/multi_edition.js @@ -0,0 +1,36 @@ +/** @odoo-module **/ + +import wTourUtils from 'website.tour_utils'; + +wTourUtils.registerWebsitePreviewTour('website_multi_edition', { + test: true, + url: '/', + edition: true, +}, [ + { + content: 'Check the current page has not the elements that will be added', + trigger: 'iframe body:not(:has(.s_text_image)):not(:has(.s_hr))', + run: () => null, + }, + // Edit the main element of the page + wTourUtils.dragNDrop({ + id: 's_text_image', + name: 'Text - Image', + }), + // Edit another part in the page, like the footer + wTourUtils.dragNDrop({ + id: 's_hr', + name: 'Separator', + }), + ...wTourUtils.clickOnSave(), + { + content: 'Check that the main element of the page was properly saved', + trigger: 'iframe main .s_text_image', + run: () => null, + }, + { + content: 'Check that the footer was properly saved', + trigger: 'iframe footer .s_hr', + run: () => null, + }, +]); diff --git a/addons/website/tests/test_ui.py b/addons/website/tests/test_ui.py index 3e2d7c918e1..d30ed22e38a 100644 --- a/addons/website/tests/test_ui.py +++ b/addons/website/tests/test_ui.py @@ -314,3 +314,6 @@ class TestUi(odoo.tests.HttpCase): def test_22_website_gray_color_palette(self): self.start_tour('/web', 'website_gray_color_palette', login='admin') + + def test_23_website_multi_edition(self): + self.start_tour('/@?enable_editor=1', 'website_multi_edition', login='admin')