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 ff7526ea4e1fe2793a4be2ea8ec73a6c0f93262b..b0298cfc989022fde9b08763122b06101b4c79c8 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 0000000000000000000000000000000000000000..4234101179079553c5e38d357b04ef48dbd22607 --- /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 a4b5bb380596a64859f5ebd379ca83259a772609..ad650f7a258d572581cd5ad0e476edac8b2f6b8c 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')