From d5a031a9a3769256e04b5933d598561ff46af253 Mon Sep 17 00:00:00 2001 From: Nicolas Bayet Date: Tue, 26 Oct 2021 08:37:44 +0000 Subject: [PATCH] [FIX] web_editor, website: only save dirty element Before this commit, when inserting a new snippet or moving a snippet that was already in the page would temporarily create hooks (`we-hook`) in the page. The insertion of thoses hooks would trigger mutation in the dirty observer (observer defined in edit.js) and mark all oe_structure for which a hook was temporarily inserted. Thus, creating unnecessary views in the backend. Now, the code skip the mutations of the drag and drop hooks. Task-2567752 closes odoo/odoo#79394 X-original-commit: 1b80fe9b56acea09a6784691561df65fe6349f50 Signed-off-by: David Monjoie (dmo) Signed-off-by: Antoine Guenet --- .../static/lib/odoo-editor/src/OdooEditor.js | 5 ++ .../static/src/js/editor/snippets.editor.js | 9 ++++ addons/website/static/src/js/menu/edit.js | 46 +++++++++++++------ 3 files changed, 45 insertions(+), 15 deletions(-) diff --git a/addons/web_editor/static/lib/odoo-editor/src/OdooEditor.js b/addons/web_editor/static/lib/odoo-editor/src/OdooEditor.js index 4dff1d95348..73306c70d22 100644 --- a/addons/web_editor/static/lib/odoo-editor/src/OdooEditor.js +++ b/addons/web_editor/static/lib/odoo-editor/src/OdooEditor.js @@ -424,6 +424,7 @@ export class OdooEditor extends EventTarget { clearTimeout(this.observerTimeout); this.observer.disconnect(); this.observerFlush(); + this.dispatchEvent(new Event('observerUnactive')); } } observerFlush() { @@ -454,6 +455,7 @@ export class OdooEditor extends EventTarget { characterData: true, characterDataOldValue: true, }); + this.dispatchEvent(new Event('observerActive')); } observerApply(records) { @@ -552,6 +554,9 @@ export class OdooEditor extends EventTarget { if (record.type === 'attributes') { // Skip the attributes change on the dom. if (record.target === this.editable) continue; + if (record.attributeName === 'contenteditable') { + continue; + } attributeCache.set(record.target, attributeCache.get(record.target) || {}); if ( 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 18e62245151..59ffb83d28e 100644 --- a/addons/web_editor/static/src/js/editor/snippets.editor.js +++ b/addons/web_editor/static/src/js/editor/snippets.editor.js @@ -834,6 +834,7 @@ var SnippetEditor = Widget.extend({ * @private */ _onDragAndDropStart: function () { + this.wysiwyg.odooEditor.observerUnactive('dragAndDropMoveSnippet'); this.trigger_up('drag_and_drop_start'); this.options.wysiwyg.odooEditor.automaticStepUnactive(); var self = this; @@ -947,6 +948,7 @@ var SnippetEditor = Widget.extend({ this.$body.removeClass('move-important'); $clone.remove(); + this.wysiwyg.odooEditor.observerActive('dragAndDropMoveSnippet'); if (this.dropped) { if (prev) { this.$target.insertAfter(prev); @@ -2319,6 +2321,7 @@ var SnippetsMenu = Widget.extend({ start: function () { self.options.wysiwyg.odooEditor.automaticStepUnactive(); self.$el.find('.oe_snippet_thumbnail').addClass('o_we_already_dragging'); + self.options.wysiwyg.odooEditor.observerUnactive('dragAndDropCreateSnippet'); dropped = false; $snippet = $(this); @@ -2421,6 +2424,7 @@ var SnippetsMenu = Widget.extend({ } self.getEditableArea().find('.oe_drop_zone').droppable('destroy').remove(); + self.options.wysiwyg.odooEditor.observerActive('dragAndDropCreateSnippet'); if (dropped) { var prev = $toInsert.first()[0].previousSibling; @@ -2439,7 +2443,12 @@ var SnippetsMenu = Widget.extend({ } var $target = $toInsert; + + + self.options.wysiwyg.odooEditor.observerUnactive('dragAndDropCreateSnippet'); await self._scrollToSnippet($target, self.$scrollable); + self.options.wysiwyg.odooEditor.observerActive('dragAndDropCreateSnippet'); + _.defer(async function () { // Free the mutex now to allow following operations diff --git a/addons/website/static/src/js/menu/edit.js b/addons/website/static/src/js/menu/edit.js index e9c6af74dcc..d79c6150b1d 100644 --- a/addons/website/static/src/js/menu/edit.js +++ b/addons/website/static/src/js/menu/edit.js @@ -103,7 +103,10 @@ var EditPageMenu = websiteNavbarData.WebsiteNavbarActionWidget.extend({ if (this._saving) { return false; } - this.observer.disconnect(); + if (this.observer) { + this.observer.disconnect(); + this.observer = undefined; + } var self = this; this._saving = true; this.trigger_up('edition_will_stopped'); @@ -279,11 +282,7 @@ var EditPageMenu = websiteNavbarData.WebsiteNavbarActionWidget.extend({ // 1. Make sure every .o_not_editable is not editable. // 2. Observe changes to mark dirty structures and fields. - this.observer = new MutationObserver(records => { - this.wysiwyg.odooEditor.observerUnactive(); - $('#wrap').find('.o_not_editable[contenteditable!=false]').attr('contenteditable', false); - this.wysiwyg.odooEditor.observerActive(); - + const processRecords = (records) => { records = this.wysiwyg.odooEditor.filterMutationRecords(records); // Skip the step for this stack because if the editor undo the first // step that has a dirty element, the following code would have @@ -303,15 +302,29 @@ var EditPageMenu = websiteNavbarData.WebsiteNavbarActionWidget.extend({ } }); } - }); + }; + this.observer = new MutationObserver(processRecords); + const observe = () => { + if (this.observer) { + this.observer.observe(document.body, { + childList: true, + subtree: true, + attributes: true, + attributeOldValue: true, + characterData: true, + }); + } + } + observe(); + + this.wysiwyg.odooEditor.addEventListener('observerUnactive', () => { + if (this.observer) { + processRecords(this.observer.takeRecords()); + this.observer.disconnect(); + } + }) + this.wysiwyg.odooEditor.addEventListener('observerActive', observe) - this.observer.observe(document.body, { - childList: true, - subtree: true, - attributes: true, - attributeOldValue: true, - characterData: true, - }); $('body').addClass('editor_started'); }, @@ -451,7 +464,10 @@ var EditPageMenu = websiteNavbarData.WebsiteNavbarActionWidget.extend({ this.trigger_up('widgets_stop_request', { $target: this._targetForEdition(), }); - this.observer.disconnect(); + if (this.observer) { + this.observer.disconnect(); + this.observer = undefined; + } }, /** * Called when edition was stopped. Notifies the