[FIX] web_editor, website: prevent drop elements next to editable media

In the past, it was possible to drop elements in non-editable areas.
Commit [1] fixed the issue but then commit [2] added a solution to be
able to edit a media element that is in a `o_not_editable` environment.
Unfortunately, the solution makes it possible to drop elements next to
the `o_editable_media` elements ignoring the editable context (ignoring
the first fix).

Steps to reproduce the issue:
- Enter website edit mode
- Drop a Team block in a page
- Click on the Team block

=> The user is able to drop a "Text highlight" block next to the team
member pictures.

This commit
- reverts the commit [1] because in the meantime, the commit [3] fixed
the issue.
- fixes the Team block issue.
- fixes the filterFunc for the drop-in.
- adds a test to ensure the issue doesn't come back.

[1]: https://github.com/odoo/odoo/commit/67924648676b37898aedd86bc32868299aee542c
[2]: https://github.com/odoo/odoo/commit/580f1b77ce0b96b7efbf83a0ccdf6979bbf0e904
[3]: https://github.com/odoo/odoo/commit/ae7452f18dbd6ed56dbf883ae8495382b336aa78

opw-3536227

closes odoo/odoo#144806

X-original-commit: 9b4c2498b8fa2bc0aca604b6256e6c805b9b4c10
Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
Signed-off-by: Guillaume Dieleman (gdi) <gdi@odoo.com>
This commit is contained in:
Guillaume-gdi
2023-12-05 19:53:33 +00:00
parent f051402776
commit fc6630a2d7
3 changed files with 60 additions and 5 deletions
@@ -2423,7 +2423,7 @@ var SnippetsMenu = Widget.extend({
$selectorSiblings = $(unique(($selectorSiblings || $()).add($selectorChildren.children()).get()));
}
var noDropZonesSelector = '[data-invisible="1"], .o_we_no_overlay, :not(:visible), :not(:o_editable)';
var noDropZonesSelector = '[data-invisible="1"], .o_we_no_overlay, :not(:visible)';
if ($selectorSiblings) {
$selectorSiblings.not(`.oe_drop_zone, .oe_drop_clone, ${noDropZonesSelector}`).each(function () {
var data;
@@ -2835,6 +2835,13 @@ var SnippetsMenu = Widget.extend({
_computeSelectorFunctions: function (selector, exclude, target, noCheck, isChildren, excludeParent) {
var self = this;
// TODO in master: FOR_DROP should be a param of the function.
const forDropID = 'FOR_DROP';
const forDrop = exclude && exclude.startsWith(forDropID);
if (forDrop) {
exclude = exclude.substring(forDropID.length);
}
// The `:not(.o_editable_media)` part is handled outside of the selector
// (see filterFunc).
// Note: the `:not([contenteditable="true"])` part was there for that
@@ -2856,10 +2863,19 @@ var SnippetsMenu = Widget.extend({
// When noCheck is true, we only check the exclude.
return true;
}
// `o_editable_media` bypasses the `o_not_editable` class.
if (this.classList.contains('o_editable_media')) {
// `o_editable_media` bypasses the `o_not_editable` class except for
// drag & drop.
if (!forDrop && this.classList.contains('o_editable_media')) {
return weUtils.shouldEditableMediaBeEditable(this);
}
if (forDrop && !isChildren) {
// it's a drop-in.
return !$(this)
.is('.o_not_editable :not([contenteditable="true"]), .o_not_editable');
}
if (isChildren) {
return !$(this).is('.o_not_editable *');
}
return !$(this)
.is('.o_not_editable:not(.s_social_media) :not([contenteditable="true"])');
};
@@ -2956,8 +2972,8 @@ var SnippetsMenu = Widget.extend({
'base_target': target,
'selector': self._computeSelectorFunctions(selector, exclude, target, noCheck),
'$el': $style,
'drop-near': $style.data('drop-near') && self._computeSelectorFunctions($style.data('drop-near'), '', false, noCheck, true, excludeParent),
'drop-in': $style.data('drop-in') && self._computeSelectorFunctions($style.data('drop-in'), '', false, noCheck),
'drop-near': $style.data('drop-near') && self._computeSelectorFunctions($style.data('drop-near'), 'FOR_DROP', false, noCheck, true, excludeParent),
'drop-in': $style.data('drop-in') && self._computeSelectorFunctions($style.data('drop-in'), 'FOR_DROP', false, noCheck),
'drop-exclude-ancestor': this.dataset.dropExcludeAncestor,
'drop-lock-within': this.dataset.dropLockWithin,
'data': Object.assign({string: $style.attr('string')}, $style.data()),
@@ -0,0 +1,36 @@
/** @odoo-module **/
import wTourUtils from '@website/js/tours/tour_utils';
wTourUtils.registerWebsitePreviewTour("test_drag_and_drop_on_non_editable", {
test: true,
url: "/",
edition: true,
}, () => [
wTourUtils.dragNDrop({
id: "s_company_team",
name: "Team",
}),
{
content: "Click on an editable media in non editable env.",
trigger: "iframe .s_company_team .o_not_editable > .o_editable_media",
},
{
content: "Verify that the Replace options is in the editor.",
trigger: "we-button[data-replace-media]",
isCheck: true,
},
wTourUtils.goBackToBlocks(),
Object.assign(wTourUtils.dragNDrop({
id: "s_text_highlight",
name: "Text Highlight",
}), {
content: "Drag and drop the Text Highlight building block next to the Team block media.",
run: "drag_and_drop_native iframe .s_company_team .o_not_editable > .o_editable_media",
}),
{
content: "Verify that the Text Highlight building block isn't in a non editable element.",
trigger: "iframe .s_company_team :not(.o_not_editable) > .s_text_highlight",
isCheck: true,
},
]);
+3
View File
@@ -95,3 +95,6 @@ class TestSnippets(HttpCase):
website.cookies_bar = True
self.start_tour(self.env['website'].get_client_action_url('/'), 'snippet_popup_and_scrollbar', login='admin')
self.start_tour(self.env['website'].get_client_action_url('/'), 'snippet_popup_and_animations', login='admin')
def test_drag_and_drop_on_non_editable(self):
self.start_tour(self.env['website'].get_client_action_url('/'), 'test_drag_and_drop_on_non_editable', login='admin')