[FIX] website: never show an empty popup

When using the "ConditionalVisibility/DeviceVisibility" option for
blocks that are inside a popup, you can end up with an empty popup.
This was has been a limitation of those options for a while, but there
is a real use case for hiding a popup under certain circumstances.

Adapting the options to work on popup was complex enough that it does
not seem suitable for a stable version.

But a simple solution that tries to break as little as possible existing
code could be a huge benefit.

This commit makes it so that if the all children of the .oe_structure
are currently being hidden by ConditionalVisibility selectors or by
DeviceVisibility classes, the popup will not be shown to the visitor.

It will still show if content is being hidden by other means, either
with customizations, or if the content is dynamically generated (like in
the case of a Dynamic Snippet).

This change is done starting saas-16.3 as this is the version the OPW
was opened with, and since this is still a significant change, it will
limit the impacted versions.

opw-3734501
task-3128349

closes odoo/odoo#158303

X-original-commit: 3f5e3c4d49d4c0f67b548d22846e27c5ff8c73f1
Signed-off-by: Romain Derie (rde) <rde@odoo.com>
Signed-off-by: Arthur Detroux (ard) <ard@odoo.com>
This commit is contained in:
Arthur Detroux (ard)
2024-03-27 14:09:48 +00:00
parent 5286ef499d
commit 2bcc2d82ab
@@ -3,7 +3,7 @@
import publicWidget from "@web/legacy/js/public/public_widget";
import { cookie } from "@web/core/browser/cookie";
import {throttleForAnimation} from "@web/core/utils/timing";
import { utils as uiUtils } from "@web/core/ui/ui_service";
import { utils as uiUtils, SIZES } from "@web/core/ui/ui_service";
import {setUtmsHtmlDataset} from '@website/js/content/inject_dom';
// TODO In master, export this class too or merge it with PopupWidget
@@ -94,7 +94,21 @@ const PopupWidget = publicWidget.Widget.extend({
this._showPopupOnClick();
} else {
this._popupAlreadyShown = !!cookie.get(this.$el.attr('id'));
if (!this._popupAlreadyShown) {
// Check if every child element of the popup is conditionally hidden,
// and if so, never show an empty popup.
// config.device.isMobile is true if the device is <= SM, but the device
// visibility option uses < LG to hide on mobile. So compute it here.
const isMobile = uiUtils.getSize() < SIZES.LG;
const emptyPopup = [
...this.$el[0].querySelectorAll(".oe_structure > *:not(.s_popup_close)")
].every((el) => {
const visibilitySelectors = el.dataset.visibilitySelectors;
const deviceInvisible = isMobile
? el.classList.contains("o_snippet_mobile_invisible")
: el.classList.contains("o_snippet_desktop_invisible");
return (visibilitySelectors && el.matches(visibilitySelectors)) || deviceInvisible;
});
if (!this._popupAlreadyShown && !emptyPopup) {
this._bindPopup();
}
}