From 75c1a00143778a4c5b43a928a7d57c79728af2e3 Mon Sep 17 00:00:00 2001
From: "Louis (loco)" <loco@odoo.com>
Date: Tue, 9 May 2023 15:11:10 +0000
Subject: [PATCH] [FIX] web_editor, *: reorder invisible elements panel at
 snippet move

*website

Steps to reproduce the bug:
- Add a Cover and a Picture snippet on the website.
- Change their visibility to "Conditionally".
- Change the order of the two snippets on the page either with the drag
and drop tool or with the "move up" or "move down" option.
=> Their order on the "Invisible Elements" panel has not been updated.

The problem is fixed by calling `_updateInvisibleDOM()` at the end of
`moveSnippet()` and `_onSnippetDragAndDropStop()`. Note that before this
commit, all the snippets with a conditional visibility were hidden at
the call of `_onSnippetDragAndDropStop()`. This is due to the call of
`cleanForSave()` from `_destroyEditors()`. `_onSnippetDragAndDropStop()`
has been adapted in order to, as for the "move" option, do not change
the visibility of those elements.

task-3203914

closes odoo/odoo#113549

Signed-off-by: Dieleman Guillaume (gdi) <gdi@odoo.com>
---
 .../static/src/js/editor/snippets.editor.js   | 27 +++++++++
 .../static/src/js/editor/snippets.options.js  |  3 +
 .../tests/tours/conditional_visibility.js     | 60 +++++++++++++++++--
 addons/website/tests/test_ui.py               |  1 +
 4 files changed, 86 insertions(+), 5 deletions(-)

diff --git a/addons/web_editor/static/src/js/editor/snippets.editor.js b/addons/web_editor/static/src/js/editor/snippets.editor.js
index c73994f28951..20ea753b0a51 100644
--- a/addons/web_editor/static/src/js/editor/snippets.editor.js
+++ b/addons/web_editor/static/src/js/editor/snippets.editor.js
@@ -1261,6 +1261,7 @@ var SnippetsMenu = Widget.extend({
         'request_editable': '_onRequestEditable',
         'disable_loading_effect': '_onDisableLoadingEffect',
         'enable_loading_effect': '_onEnableLoadingEffect',
+        "update_invisible_dom": "_onUpdateInvisibleDom",
     },
     // enum of the SnippetsMenu's tabs.
     tabs: {
@@ -3187,6 +3188,14 @@ var SnippetsMenu = Widget.extend({
      */
     _onSnippetDragAndDropStop: async function (ev) {
         this.snippetEditorDragging = false;
+        const visibleConditionalEls = [];
+        for (const snippetEditor of this.snippetEditors) {
+            const targetEl = snippetEditor.$target[0];
+            if (targetEl.dataset["visibility"] === "conditional" &&
+                !targetEl.classList.contains("o_conditional_hidden")) {
+                visibleConditionalEls.push(targetEl);
+            }
+        }
         const modalEl = ev.data.$snippet[0].closest('.modal');
         const carouselItemEl = ev.data.$snippet[0].closest('.carousel-item');
         // If the snippet is in a modal, destroy editors only in that modal.
@@ -3196,6 +3205,16 @@ var SnippetsMenu = Widget.extend({
         // first slide.
         await this._destroyEditors(carouselItemEl ? $(carouselItemEl) : modalEl ? $(modalEl) : null);
         await this._activateSnippet(ev.data.$snippet);
+        // Because of _destroyEditors(), all the snippets with a conditional
+        // visibility are hidden. Show the ones that were visible before the
+        // drag and drop.
+        for (const visibleConditionalEl of visibleConditionalEls) {
+            visibleConditionalEl.classList.remove("o_conditional_hidden");
+            delete visibleConditionalEl.dataset["invisible"];
+        }
+        // Update the "Invisible Elements" panel as the order of invisible
+        // snippets could have changed on the page.
+        await this._updateInvisibleDOM();
     },
     /**
      * Returns the droppable snippet from which a dropped snippet originates.
@@ -3619,6 +3638,14 @@ var SnippetsMenu = Widget.extend({
     _onSnippetSearchResetClick: function () {
         this._filterSnippets('');
     },
+    /**
+     * Called when a child editor asks to update the "Invisible Elements" panel.
+     *
+     * @private
+     */
+    async _onUpdateInvisibleDom() {
+        await this._updateInvisibleDOM();
+    },
     _addToolbar(toolbarMode = "text") {
         let titleText = _t("Inline Text");
         switch (toolbarMode) {
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 6b164ebb85a8..f87dbf81e4d5 100644
--- a/addons/web_editor/static/src/js/editor/snippets.options.js
+++ b/addons/web_editor/static/src/js/editor/snippets.options.js
@@ -4846,6 +4846,9 @@ registry.SnippetMove = SnippetOptionWidget.extend({
                 });
             }
         }
+        // Update the "Invisible Elements" panel as the order of invisible
+        // snippets could have changed on the page.
+        this.trigger_up("update_invisible_dom");
     },
 });
 
diff --git a/addons/website/static/tests/tours/conditional_visibility.js b/addons/website/static/tests/tours/conditional_visibility.js
index da7f2fa552a2..2530e5a60bd5 100644
--- a/addons/website/static/tests/tours/conditional_visibility.js
+++ b/addons/website/static/tests/tours/conditional_visibility.js
@@ -29,6 +29,18 @@ function checkEyeIcon(snippetName, visible) {
             run: () => {}, // it is a check
         };
 }
+function checkEyesIconAfterSave(footerIsHidden = true) {
+    const eyeIconChecks = [
+        checkEyeIcon("Header", false),
+        checkEyeIcon("Text - Image", true),
+        checkEyeIcon("Popup", false),
+        checkEyeIcon("Banner", true),
+    ];
+    if (footerIsHidden) {
+        eyeIconChecks.push(checkEyeIcon("Footer", false));
+    }
+    return eyeIconChecks;
+}
 tour.register('conditional_visibility_1', {
     test: true,
     url: '/',
@@ -141,9 +153,47 @@ checkEyeIcon("Header", false),
 checkEyeIcon("Banner", false),
 ...wTourUtils.clickOnSave(),
 ...wTourUtils.clickOnEditAndWaitEditMode(),
-checkEyeIcon("Header", false),
-checkEyeIcon("Text - Image", true),
-checkEyeIcon("Popup", false),
-checkEyeIcon("Banner", true),
-checkEyeIcon("Footer", false),
+...checkEyesIconAfterSave(),
+]);
+
+tour.register("conditional_visibility_4", {
+    test: true,
+    url: "/",
+},
+[
+...wTourUtils.clickOnEditAndWaitEditMode(),
+// Click on the "Text-Image" snippet.
+wTourUtils.clickOnSnippet(snippets[0]),
+{
+    content: "Click on the 'move down' option",
+    trigger: "we-button.o_we_user_value_widget.fa-angle-down",
+},
+...checkEyesIconAfterSave(),
+{
+    content: "Check the order on the 'Invisible Elements' panel",
+    trigger: ".o_we_invisible_el_panel div:nth-child(3):contains('Banner')",
+    run: () => {}, // it is a check
+},
+{
+    content: "Toggle the visibility of the Footer",
+    trigger: ".o_we_invisible_el_panel .o_we_invisible_entry:contains('Footer')",
+},
+{
+    content: "Check that the footer is visible",
+    trigger: "body.editor_enable #wrapwrap footer",
+    run: () => {}, // it is a check
+},
+// Click on the "Banner" snippet.
+wTourUtils.clickOnSnippet(snippets[1]),
+{
+    content: "Drag the 'Banner' snippet to the end of the page",
+    trigger: ".o_overlay_move_options .ui-draggable-handle",
+    run: "drag_and_drop #wrapwrap footer",
+},
+...checkEyesIconAfterSave(false),
+{
+    content: "Check the order on the 'Invisible Elements' panel",
+    trigger: ".o_we_invisible_el_panel div:nth-child(3):contains('Text - Image')",
+    run: () => {}, // it is a check
+},
 ]);
diff --git a/addons/website/tests/test_ui.py b/addons/website/tests/test_ui.py
index fb0086cba951..02b39083a804 100644
--- a/addons/website/tests/test_ui.py
+++ b/addons/website/tests/test_ui.py
@@ -219,6 +219,7 @@ class TestUi(odoo.tests.HttpCase):
         self.start_tour('/', 'conditional_visibility_1', login='admin')
         self.start_tour('/', 'conditional_visibility_2', login='admin')
         self.start_tour('/', 'conditional_visibility_3', login='admin')
+        self.start_tour('/', 'conditional_visibility_4', login='admin')
 
     def test_11_website_snippet_background_edition(self):
         self.env['ir.attachment'].create({
-- 
GitLab