[FIX] web_editor: prevent inner snippets to toggle the grid mode

In [1], conditions have been made in order to allow/forbid each snippet
to toggle the grid mode. However, a case has been forgotten: when a
snippet that cannot toggle the grid mode is dropped inside a snippet
that can toggle it (so it is an inner snippet). Indeed, if we drag one
of the inner snippet columns, we can see that the grid mode is toggled,
where it should not be the case.

This issue comes from the check looking if the grid layout option is
in the right panel. Indeed, even though such a snippet does not have
it, if it is dropped inside a snippet that can toggle the grid mode,
then the option is well present in the right panel (= the outer snippet
one).

This commit fixes this issue by improving the check: now, dragging a
column can toggle the grid mode only if the container having the option
is the same as the one of the column. This commit also improves the
siblings/children filtering (to only have the relevant dropzones) in
order to take this case into account and to be more robust to
customizations.

Steps to reproduce:
- drop a Text-Image snippet
- drop a Form snippet inside one of the columns
- drag a form field
=> the grid mode is toggled.

[1]: https://github.com/odoo/odoo/commit/84d684d8bdf43d3db11defd8174dee44775085c2

opw-3100399
opw-3139938

closes odoo/odoo#110888

X-original-commit: 34b534f75dbf3e4c475ca8cc40c8fafde5dbea5d
Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
Co-authored-by: qsm-odoo <qsm@odoo.com>
This commit is contained in:
Soukéina Bojabza
2023-01-24 23:21:49 +01:00
committed by qsm-odoo
co-authored by qsm-odoo
parent 839d74d174
commit 1fdcfab6ee
@@ -984,7 +984,14 @@ var SnippetEditor = Widget.extend({
this.trigger_up('user_value_widget_request', {
name: 'grid_mode',
allowParentOption: true,
onSuccess: () => hasGridLayoutOption = true,
onSuccess: (widget) => {
// The grid option is considered as present only if the
// container element having it is the same as the container of
// the column we are dragging.
if (widget.$target[0] === rowEl.parentElement) {
hasGridLayoutOption = true;
}
},
});
const allowGridMode = hasGridLayoutOption || rowEl.classList.contains('o_grid_mode');
@@ -1043,7 +1050,7 @@ var SnippetEditor = Widget.extend({
this.trigger_up('deactivate_snippet', {$snippet: self.$target});
}
const isPopup = this.$target[0].closest('div.s_popup');
const openModalEl = this.$target[0].closest('.modal');
this.dropped = false;
this._dropSiblings = {
@@ -1087,35 +1094,48 @@ var SnippetEditor = Widget.extend({
// definitions in master but we should find a better to define those and
// such cases.
if (this.$target[0].classList.contains('s_website_form_field')) {
$selectorSiblings = $selectorSiblings.filter(
(i, el) => closestFormEl === el.closest('form')
);
const filterFunc = (i, el) => el.closest('form') === closestFormEl;
if ($selectorSiblings) {
$selectorSiblings = $selectorSiblings.filter(filterFunc);
}
if ($selectorChildren) {
$selectorChildren = $selectorChildren.filter(filterFunc);
}
}
// Remove the siblings/children outside the open popup.
if (openModalEl) {
const filterFunc = (i, el) => el.closest('.modal') === openModalEl;
if ($selectorSiblings) {
$selectorSiblings = $selectorSiblings.filter(filterFunc);
}
if ($selectorChildren) {
$selectorChildren = $selectorChildren.filter(filterFunc);
}
}
const canBeSanitizedUnless = this._canBeSanitizedUnless(this.$target[0]);
// Remove the siblings that belong to a snippet in grid mode
// and put the identified grid mode snippets in their own "selector".
// Remove the siblings/children that would add a dropzone as direct
// child of a grid area and make a dedicated set out of the identified
// grid areas.
const selectorGrids = new Set();
if (rowEl.classList.contains('row')) {
if ($selectorSiblings) {
// Looping backwards because elements are removed, so the
// indexes are not lost.
for (let i = $selectorSiblings.length - 1; i >= 0; i--) {
if (isPopup && !$selectorSiblings[i].closest('div.s_popup')) {
// Removing the siblings that are outside the popup if
// the grid item is in a popup.
$selectorSiblings.splice(i, 1);
} else {
const gridSnippet = $selectorSiblings[i].closest('div.o_grid_mode');
if (gridSnippet) {
$selectorSiblings.splice(i, 1);
selectorGrids.add(gridSnippet);
}
}
const filterOutSelectorGrids = ($selectorItems, getDropzoneParent) => {
if (!$selectorItems) {
return;
}
// Looping backwards because elements are removed, so the
// indexes are not lost.
for (let i = $selectorItems.length - 1; i >= 0; i--) {
const el = getDropzoneParent($selectorItems[i]);
if (el.classList.contains('o_grid_mode')) {
$selectorItems.splice(i, 1);
selectorGrids.add(el);
}
}
}
};
filterOutSelectorGrids($selectorSiblings, el => el.parentElement);
filterOutSelectorGrids($selectorChildren, el => el);
this.trigger_up('activate_snippet', {$snippet: this.$target.parent()});
this.trigger_up('activate_insertion_zones', {