From 205fad17a3c3607a6bd36973a8048fa4e8a8ed6b Mon Sep 17 00:00:00 2001 From: Benoit Socias Date: Wed, 2 Aug 2023 08:18:23 +0000 Subject: [PATCH] [IMP] web_editor, website: add drop-zone locking and exclusion Since [1] form fields cannot be moved outside of their form and since [2] table of contents cannot be nested within another table of content. Those were implemented with specific references to website classes within web_editor. This commit introduces declarative mechanisms for both situations: - `data-drop-lock-within`: prevents dropping outside the closest parent that matches the specified selector. - `data-drop-exclude-ancestor`: disallows dropping within a parent that matches the specified selector. [1]: https://github.com/odoo/odoo/commit/638d0e875dcb05191fe833d2f889235891dfb46a [2]: https://github.com/odoo/odoo/commit/55339cd6a7b7916184893c0fe27b5483683a047a task-3131384 closes odoo/odoo#130477 Signed-off-by: Guillaume Dieleman (gdi) --- .../static/src/js/editor/snippets.editor.js | 74 +++++++++++-------- .../views/snippets/s_table_of_content.xml | 2 +- .../website/views/snippets/s_website_form.xml | 3 +- 3 files changed, 46 insertions(+), 33 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 b56b16bb044..8d6a3857218 100644 --- a/addons/web_editor/static/src/js/editor/snippets.editor.js +++ b/addons/web_editor/static/src/js/editor/snippets.editor.js @@ -693,6 +693,8 @@ var SnippetEditor = Widget.extend({ this.styles = {}; this.selectorSiblings = []; this.selectorChildren = []; + this.selectorLockWithin = new Set(); + const selectorExcludeAncestor = new Set(); var $element = this.$target.parent(); while ($element.length) { @@ -740,6 +742,12 @@ var SnippetEditor = Widget.extend({ if (val['drop-in']) { this.selectorChildren.push(val['drop-in']); } + if (val['drop-lock-within']) { + this.selectorLockWithin.add(val['drop-lock-within']); + } + if (val['drop-exclude-ancestor']) { + selectorExcludeAncestor.add(val['drop-exclude-ancestor']); + } var optionName = val.option; var option = new (options.registry[optionName] || options.Class)( @@ -774,6 +782,13 @@ var SnippetEditor = Widget.extend({ return option.appendTo(document.createDocumentFragment()); }); + if (selectorExcludeAncestor.size) { + // Prevents dropping an element into another one. + // (E.g. ToC inside another ToC) + const excludedAncestorSelector = [...selectorExcludeAncestor].join(", "); + this.excludeAncestors = (i, el) => !el.closest(excludedAncestorSelector); + } + this.isTargetMovable = (this.selectorSiblings.length > 0 || this.selectorChildren.length > 0); this.$el.find('[data-bs-toggle="dropdown"]').dropdown(); @@ -1006,40 +1021,34 @@ var SnippetEditor = Widget.extend({ width: self.$target.width(), height: self.$target.height() }; - const closestFormEl = this.$target[0].closest('form'); - self.$target.after(' -
+
diff --git a/addons/website/views/snippets/s_website_form.xml b/addons/website/views/snippets/s_website_form.xml index 90dce371183..1e6120b99a1 100644 --- a/addons/website/views/snippets/s_website_form.xml +++ b/addons/website/views/snippets/s_website_form.xml @@ -74,7 +74,8 @@
+ data-exclude=".s_website_form_dnone" data-drop-near=".s_website_form_field" + data-drop-lock-within="form"> Custom field Text