From 416500f6e3e17ecda5ee1ece1a1d274e5870eaab Mon Sep 17 00:00:00 2001 From: Samuel Degueldre Date: Mon, 10 Feb 2020 10:13:24 +0000 Subject: [PATCH] [IMP] web_editor, website: add callback to editor clone and remove We recently transitioned to async option methods, this allows us to have better control on the order of execution in the edition workflow, and among other things, keep the editor's UI in sync with the current state of the DOM. However, some snippet options (such as the number of columns option) need to remove or clone portions of the DOM, and as such, trigger the onClone or onRemove methods of the snippets contained in that portion if applicable. Because these methods are defined on other options, we first need to make sure all the snippetEditors for this portion are created, which is asynchronous. This commit adds support for an onSuccess callback to the 'clone_snippet' and 'remove_snippet' event handlers, such that options can choose to be notified when the work has been done, allowing them to wait for it before proceeding. This commit also adapts the layout_column snippet option to make use of that new feature, and remove code that was used as a workaround before, ie: precomputing the expected number of columns after the clone/remove, and using that number to adjust the width of the columns and update the UI. We can now just wait for the clone/remove, and use the real number of columns currently in the DOM. closes odoo/odoo#45343 X-original-commit: c159d58ce9cfca4a44f159b18eb10d1138977e23 Signed-off-by: Quentin Smetz (qsm) --- .../static/src/js/editor/snippets.editor.js | 43 +++++++++++-------- .../static/src/js/editor/snippets.options.js | 31 +++++++------ 2 files changed, 40 insertions(+), 34 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 b840301654e..9d11a7ac4c7 100644 --- a/addons/web_editor/static/src/js/editor/snippets.editor.js +++ b/addons/web_editor/static/src/js/editor/snippets.editor.js @@ -386,7 +386,7 @@ var SnippetEditor = Widget.extend({ * @private * @param {boolean} recordUndo */ - clone: function (recordUndo) { + clone: async function (recordUndo) { this.trigger_up('snippet_will_be_cloned', {$target: this.$target}); var $clone = this.$target.clone(false); @@ -396,15 +396,18 @@ var SnippetEditor = Widget.extend({ } this.$target.after($clone); - this.trigger_up('call_for_each_child_snippet', { - $snippet: $clone, - callback: function (editor, $snippet) { - for (var i in editor.styles) { - editor.styles[i].onClone({ - isCurrent: ($snippet.is($clone)), - }); - } - }, + await new Promise(resolve => { + this.trigger_up('call_for_each_child_snippet', { + $snippet: $clone, + callback: function (editor, $snippet) { + for (var i in editor.styles) { + editor.styles[i].onClone({ + isCurrent: ($snippet.is($clone)), + }); + } + resolve(); + }, + }); }); this.trigger_up('snippet_cloned', {$target: $clone, $origin: this.$target}); @@ -1925,11 +1928,13 @@ var SnippetsMenu = Widget.extend({ * @private * @param {OdooEvent} ev */ - _onCloneSnippet: function (ev) { + _onCloneSnippet: async function (ev) { ev.stopPropagation(); - this._createSnippetEditor(ev.data.$snippet).then(editor => { - editor.clone(); - }); + const editor = await this._createSnippetEditor(ev.data.$snippet); + await editor.clone(); + if (ev.data.onSuccess) { + ev.data.onSuccess(); + } }, /** * Called when a child editor asks to deactivate the current snippet @@ -2103,11 +2108,13 @@ var SnippetsMenu = Widget.extend({ * @private * @param {OdooEvent} ev */ - _onRemoveSnippet: function (ev) { + _onRemoveSnippet: async function (ev) { ev.stopPropagation(); - this._createSnippetEditor(ev.data.$snippet).then(function (editor) { - editor.removeSnippet(); - }); + const editor = await this._createSnippetEditor(ev.data.$snippet); + await editor.removeSnippet(); + if (ev.data.onSuccess) { + ev.data.onSuccess(); + } }, /** * Saving will destroy all editors since they need to clean their DOM. diff --git a/addons/website/static/src/js/editor/snippets.options.js b/addons/website/static/src/js/editor/snippets.options.js index 1d0e1e39e6c..1094906fe61 100644 --- a/addons/website/static/src/js/editor/snippets.options.js +++ b/addons/website/static/src/js/editor/snippets.options.js @@ -1027,9 +1027,9 @@ options.registry.layout_column = options.Class.extend({ * * @see this.selectClass for parameters */ - selectCount: function (previewMode, widgetValue, params) { + selectCount: async function (previewMode, widgetValue, params) { const nbColumns = parseInt(widgetValue); - this._updateColumnCount(nbColumns - this.$target.children().length); + await this._updateColumnCount(nbColumns - this.$target.children().length); }, //-------------------------------------------------------------------------- @@ -1041,7 +1041,7 @@ options.registry.layout_column = options.Class.extend({ */ _computeWidgetState: function (methodName, params) { if (methodName === 'selectCount') { - return '' + (this.colsLength || this.$target.children().length); + return '' + this.$target.children().length; } return this._super(...arguments); }, @@ -1052,38 +1052,40 @@ options.registry.layout_column = options.Class.extend({ * @private * @param {integer} count - positif to add, negative to remove */ - _updateColumnCount: function (count) { + _updateColumnCount: async function (count) { if (!count) { return; } this.trigger_up('request_history_undo_record', {$target: this.$target}); - var colsLength = this.$target.children().length + count; if (count > 0) { var $lastColumn = this.$target.children().last(); for (var i = 0; i < count; i++) { - this.trigger_up('clone_snippet', {$snippet: $lastColumn}); + await new Promise(resolve => { + this.trigger_up('clone_snippet', {$snippet: $lastColumn, onSuccess: resolve}); + }); } } else { var self = this; - _.each(this.$target.children().slice(count), function (el) { - self.trigger_up('remove_snippet', {$snippet: $(el)}); - }); + for (const el of this.$target.children().slice(count)) { + await new Promise(resolve => { + self.trigger_up('remove_snippet', {$snippet: $(el), onSuccess: resolve}); + }); + } } - this._resizeColumns(colsLength); + this._resizeColumns(); this.trigger_up('cover_update'); }, /** * Resizes the columns so that they are kept on one row. * * @private - * @param {number} [colsLength] (default to the actual number of columns) */ - _resizeColumns: function (colsLength) { + _resizeColumns: function () { var $columns = this.$target.children(); - colsLength = colsLength || $columns.length; + const colsLength = $columns.length; var colSize = Math.floor(12 / colsLength) || 1; var colOffset = Math.floor((12 - colSize * colsLength) / 2); var colClass = 'col-lg-' + colSize; @@ -1095,9 +1097,6 @@ options.registry.layout_column = options.Class.extend({ if (colOffset) { $columns.first().addClass('offset-lg-' + colOffset); } - // TODO: remove in master. This is used to keep the UI in sync, but - // won't be needed once option methods are properly asynchronous. - this.colsLength = colsLength; }, });