From 2eb70a471a8c6d9a814a74b8e641fdabc8100f83 Mon Sep 17 00:00:00 2001
From: "Nasreddin Boulif (bon)" <bon@odoo.com>
Date: Mon, 13 Dec 2021 14:18:09 +0000
Subject: [PATCH] [FIX] website: allow to remove shadow on all cards

Steps to reproduce:

  - Install `website_hr_recruiment` module
  - Go to `your_website.com/jobs`
  - Activate Edit mode and add a "3 Columns" block
  - Select one of the columns and set the shadow to `None`

Issue:

  Shadow is not removed, and by default the "outset" mode is selected.

Cause:

  When we check the state of the shadow with `css('box-shadow')`, it
  will always be set because a custom css 'box-shadow' is set by the
  module website_hr_recruitment on card element, and therefore the value
  will always be either 'inset' or 'outset'.

Solution:

  If widget value is set to '', replace `box-shadow` style to 'none'
  (only if needed) so it will override the style from css file.

opw-2701512

Part-of: odoo/odoo#81038
Co-authored-by: qsm-odoo <qsm@odoo.com>
---
 .../web_editor/static/src/js/common/utils.js  | 20 ++++++++++++++++++
 .../static/src/js/editor/snippets.options.js  |  2 +-
 .../static/src/js/editor/snippets.options.js  | 21 ++++++++++++-------
 3 files changed, 34 insertions(+), 9 deletions(-)

diff --git a/addons/web_editor/static/src/js/common/utils.js b/addons/web_editor/static/src/js/common/utils.js
index 1cd103181ed8..187211b58239 100644
--- a/addons/web_editor/static/src/js/common/utils.js
+++ b/addons/web_editor/static/src/js/common/utils.js
@@ -156,6 +156,26 @@ function _areCssValuesEqual(value1, value2, cssProp, $target) {
         return true;
     }
 
+    // In case the values are meant as box-shadow, this is difficult to compare.
+    // In this case we use the kinda hacky and probably inneficient but probably
+    // easiest way: applying the value as box-shadow of two fakes elements and
+    // compare their computed value.
+    if (cssProp === 'box-shadow') {
+        const temp1El = document.createElement('div');
+        temp1El.style.boxShadow = value1;
+        document.body.appendChild(temp1El);
+        value1 = getComputedStyle(temp1El).boxShadow;
+        document.body.removeChild(temp1El);
+
+        const temp2El = document.createElement('div');
+        temp2El.style.boxShadow = value2;
+        document.body.appendChild(temp2El);
+        value2 = getComputedStyle(temp2El).boxShadow;
+        document.body.removeChild(temp2El);
+
+        return value1 === value2;
+    }
+
     // Convert the second value in the unit of the first one and compare
     // floating values
     const data = _getNumericAndUnit(value1);
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 fa5ab60622bd..f39af3f9f5c7 100644
--- a/addons/web_editor/static/src/js/editor/snippets.options.js
+++ b/addons/web_editor/static/src/js/editor/snippets.options.js
@@ -2170,7 +2170,7 @@ const SnippetOptionWidget = Widget.extend({
         hasUserValue = applyCSS.call(this, cssProps[0], values.join(' '), styles) || hasUserValue;
 
         function applyCSS(cssProp, cssValue, styles) {
-            if (!weUtils.areCssValuesEqual(styles[cssProp], cssValue)) {
+            if (!weUtils.areCssValuesEqual(styles[cssProp], cssValue, cssProp, this.$target[0])) {
                 this.$target[0].style.setProperty(cssProp, cssValue, 'important');
                 return true;
             }
diff --git a/addons/website/static/src/js/editor/snippets.options.js b/addons/website/static/src/js/editor/snippets.options.js
index 1d7982ac6429..5afc2a4a33c0 100644
--- a/addons/website/static/src/js/editor/snippets.options.js
+++ b/addons/website/static/src/js/editor/snippets.options.js
@@ -2174,14 +2174,19 @@ options.registry.Box = options.Class.extend({
     /**
      * @see this.selectClass for parameters
      */
-    setShadow(previewMode, widgetValue, params) {
+    async setShadow(previewMode, widgetValue, params) {
+        // Add/remove the shadow class
         this.$target.toggleClass(params.shadowClass, !!widgetValue);
-        const defaultShadow = this._getDefaultShadow(widgetValue, params.shadowClass);
-        this.$target[0].style.setProperty('box-shadow', defaultShadow, 'important');
-        if (widgetValue === 'outset') {
-            // In this case, the shadowClass is enough
-            this.$target[0].style.setProperty('box-shadow', '');
-        }
+
+        // Get the shadow value that is supposed to be set according to the
+        // shadow mode. Try to apply it via the selectStyle method so that it is
+        // either ignored because the shadow class had its effect or forced (to
+        // the shadow value or none) if toggling the class is not enough (e.g.
+        // if the item has a default shadow coming from CSS rules, removing the
+        // shadow class won't be enough to remove the shadow but in most other
+        // cases it will).
+        const defaultShadow = this._getDefaultShadow(widgetValue, params.shadowClass) || 'none';
+        await this.selectStyle(previewMode, defaultShadow, Object.assign({cssProperty: 'box-shadow'}, params));
     },
 
     //--------------------------------------------------------------------------
@@ -2231,7 +2236,7 @@ options.registry.Box = options.Class.extend({
             }
         }
         el.remove();
-        return '';
+        return ''; // TODO in master this should be changed to 'none'
     }
 });
 
-- 
GitLab