From fa233f804249ddad5cb242594d1369a92fcc08a2 Mon Sep 17 00:00:00 2001 From: Benoit Socias <bso@odoo.com> Date: Wed, 18 Jan 2023 08:16:23 +0000 Subject: [PATCH] [FIX] website: not move images twice within image wall Since [1] the "Images Add/Remove All" buttons are on top of the background options in order to appear as the first option for the "Image Wall" snippet. This makes the JS related to the handling of the options of that snippet created twice: once for the buttons above and once for the options below. Because of this, events are registered by both instances and they both get notified on option update. Therefore, when an image is moved, it is moved twice instead of once. This commit differentiates both instances, and makes the one that handles the "Add" and "Remove All" buttons be the only one that works on the images. In stable the differentiation is done with conditional statements. In master the instances should be of distinct classes. [1]: https://github.com/odoo/odoo/commit/b6494fcf284edcddaa36b5fcfd407a6d7186fbd7 task-2990053 closes odoo/odoo#110242 Signed-off-by: Guillaume-gdi <gdi@odoo.com> --- .../src/snippets/s_image_gallery/options.js | 29 +++++++++--- .../static/tests/tours/snippet_images_wall.js | 44 +++++++++++++++++++ addons/website/tests/test_snippets.py | 3 ++ 3 files changed, 71 insertions(+), 5 deletions(-) create mode 100644 addons/website/static/tests/tours/snippet_images_wall.js diff --git a/addons/website/static/src/snippets/s_image_gallery/options.js b/addons/website/static/src/snippets/s_image_gallery/options.js index ff7526ea4e1f..b0298cfc9890 100644 --- a/addons/website/static/src/snippets/s_image_gallery/options.js +++ b/addons/website/static/src/snippets/s_image_gallery/options.js @@ -16,6 +16,18 @@ options.registry.gallery = options.Class.extend({ */ start: function () { var self = this; + // TODO In master: define distinct classes. + // Differentiate both instances of this class: we want to avoid + // registering the same event listener twice. + this.hasAddImages = this.el.querySelector("we-button[data-add-images]"); + + if (!this.hasAddImages) { + const containerEl = this.$target[0].querySelector(":scope > .container, :scope > .container-fluid, :scope > .o_container_small"); + if (containerEl.querySelector(":scope > *:not(div)")) { + self.mode(null, self.getMode()); + } + return this._super.apply(this, arguments); + } // Make sure image previews are updated if images are changed this.$target.on('image_changed.gallery', 'img', function (ev) { @@ -43,11 +55,6 @@ options.registry.gallery = options.Class.extend({ } }); - const $container = this.$('> .container, > .container-fluid, > .o_container_small'); - if ($container.find('> *:not(div)').length) { - self.mode(null, self.getMode()); - } - return this._super.apply(this, arguments); }, /** @@ -302,12 +309,24 @@ options.registry.gallery = options.Class.extend({ */ notify: function (name, data) { this._super(...arguments); + // TODO Remove in master. + if (!this.hasAddImages) { + // In stable, the widget is instanciated twice. We do not want + // operations, especially moves, to be performed twice. + // We therefore ignore the requests from one of the instances. + return; + } if (name === 'image_removed') { data.$image.remove(); // Force the removal of the image before reset this.mode('reset', this.getMode()); } else if (name === 'image_index_request') { var imgs = this._getImages(); var position = _.indexOf(imgs, data.$image[0]); + if (position === 0 && data.position === "prev") { + data.position = "last"; + } else if (position === imgs.length - 1 && data.position === "next") { + data.position = "first"; + } imgs.splice(position, 1); switch (data.position) { case 'first': diff --git a/addons/website/static/tests/tours/snippet_images_wall.js b/addons/website/static/tests/tours/snippet_images_wall.js new file mode 100644 index 000000000000..423410117907 --- /dev/null +++ b/addons/website/static/tests/tours/snippet_images_wall.js @@ -0,0 +1,44 @@ +/** @odoo-module **/ + +import tour from "web_tour.tour"; +import wTourUtils from "website.tour_utils"; + +tour.register("snippet_images_wall", { + test: true, + url: "/", +}, [ + ...wTourUtils.clickOnEditAndWaitEditMode(), + wTourUtils.dragNDrop({ + id: "s_images_wall", + name: "Images Wall", +}), wTourUtils.clickOnSnippet({ + id: "s_image_gallery", + name: "Images Wall", +}), { + // Prefixing selectors with #wrap to avoid matching droppable block. + content: "Click on third image", + trigger: "#wrap .s_image_gallery img[data-index='2']", +}, { + content: "Click on move to previous", + trigger: ".snippet-option-gallery_img we-button[data-position='prev']", +}, { + content: "Click on move to first", + extra_trigger: "#wrap .s_image_gallery .o_masonry_col:nth-child(2):has(img[data-index='1'][data-original-src*='sign'])", + trigger: ".snippet-option-gallery_img we-button[data-position='first']", +}, { + content: "Click on move to previous", + extra_trigger: "#wrap .s_image_gallery .o_masonry_col:nth-child(1):has(img[data-index='0'][data-original-src*='sign'])", + trigger: ".snippet-option-gallery_img we-button[data-position='prev']", +}, { + content: "Click on move to next", + extra_trigger: "#wrap .s_image_gallery .o_masonry_col:nth-child(3):has(img[data-index='5'][data-original-src*='sign'])", + trigger: ".snippet-option-gallery_img we-button[data-position='next']", +}, { + content: "Click on move to last", + extra_trigger: "#wrap .s_image_gallery .o_masonry_col:nth-child(1):has(img[data-index='0'][data-original-src*='sign'])", + trigger: ".snippet-option-gallery_img we-button[data-position='last']", +}, { + content: "Check layout", + trigger: "#wrap .s_image_gallery .o_masonry_col:nth-child(3):has(img[data-index='5'][data-original-src*='sign'])", + run: () => {}, // This is a check. +}]); diff --git a/addons/website/tests/test_snippets.py b/addons/website/tests/test_snippets.py index a4b5bb380596..ad650f7a258d 100644 --- a/addons/website/tests/test_snippets.py +++ b/addons/website/tests/test_snippets.py @@ -53,3 +53,6 @@ class TestSnippets(odoo.tests.HttpCase): 'url': base + '/web/image/website.s_banner_default_image.jpg', }) self.start_tour("/", "snippet_image_gallery", login='admin') + + def test_07_snippet_images_wall(self): + self.start_tour('/', 'snippet_images_wall', login='admin') -- GitLab