From d5b839f71339eaa705c0ae41c8dfd6a378a2be92 Mon Sep 17 00:00:00 2001 From: Bastien PIERRE Date: Wed, 4 Oct 2023 10:02:23 +0200 Subject: [PATCH] [IMP] web_editor: Wysiwyg: Allow to save given editable Before this commit, the save operation of wysiwyg was applied on the current editable. After this commit, the save operation of wysiwyg can be used on a given element. This advantage of this change is that saving can now be triggered on a copy of the original editable element, or on any document in memory. This makes the use case of the report editor easier to handle. That is, when the save fails, we need to go back to the state of the editor before the save: that is WITH the changes of the user, but not cleaned by the wysiwyg yet. task-id-3457404 Part-of: odoo/odoo#135265 --- .../static/src/js/wysiwyg/wysiwyg.js | 33 ++++++++++++------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/addons/web_editor/static/src/js/wysiwyg/wysiwyg.js b/addons/web_editor/static/src/js/wysiwyg/wysiwyg.js index 36005e37fb3..2675f006a3e 100644 --- a/addons/web_editor/static/src/js/wysiwyg/wysiwyg.js +++ b/addons/web_editor/static/src/js/wysiwyg/wysiwyg.js @@ -997,18 +997,25 @@ export class Wysiwyg extends Component { this.odooEditor.historyReset(); } /** - * Saves the content. + * Saves the content or the given editable. * * @param {boolean} [reload=true] + * @param {Object} [editable=false] Specific editable to save * @returns {Promise} */ - async saveContent(reload = true) { + async saveContent(reload = true, editable = false) { this.savingContent = true; - await this.cleanForSave(); + if (!editable) { + await this.cleanForSave(); + const editables = "getContentEditableAreas" in this.options ? this.options.getContentEditableAreas(this.odooEditor) : []; + await this.savePendingImages(editables.length ? $(editables) : this.$editable); + await this._saveViewBlocks(); + } else { + await this.cleanForSave(editable); + await this.savePendingImages(editable); + await this._saveViewBlocks(false, editable); + } - const editables = "getContentEditableAreas" in this.options ? this.options.getContentEditableAreas(this.odooEditor) : []; - await this.savePendingImages(editables.length ? $(editables) : this.$editable); - await this._saveViewBlocks(); this.savingContent = false; window.removeEventListener('beforeunload', this._onBeforeUnload); @@ -1130,10 +1137,10 @@ export class Wysiwyg extends Component { closestElement(...args) { return closestElement(...args); } - async cleanForSave() { + async cleanForSave(editable = this.odooEditor.editable) { if (this.odooEditor) { - this.odooEditor.cleanForSave(); - this._attachHistoryIds(); + this.odooEditor.cleanForSave(editable); + this._attachHistoryIds(editable); } if (this.snippetsMenu) { @@ -2522,18 +2529,20 @@ export class Wysiwyg extends Component { } /** - * Searches all the dirty element on the page and saves them one by one. If + * Searches all the dirty element on the page or given element and saves them one by one. If * one cannot be saved, this notifies it to the user and restarts rte * edition. * * @param {Object} [context] - the context to use for saving rpc, default to * the editor context found on the page + * @param {Object} [element] - Specific given element to save * @return {Promise} rejected if the save cannot be done */ - _saveViewBlocks(context) { + _saveViewBlocks(context, element = false) { // TODO should be review to probably not search in the whole body, // iframe or not. - const $ = getJqueryFromDocument(this.$editable[0].ownerDocument); + // If the element is given, then search within not from the document. + const $ = element ? getJqueryFromDocument(element) : getJqueryFromDocument(this.$editable[0].ownerDocument); const $allBlocks = $((this.options || {}).savableSelector).filter('.o_dirty'); const $dirty = $('.o_dirty');