summaryrefslogtreecommitdiff
path: root/addons/web_editor/static/src/js
diff options
context:
space:
mode:
authorSamuel Degueldre <sad@odoo.com>2020-10-22 10:42:54 +0000
committerqsm-odoo <qsm@odoo.com>2020-11-02 17:03:56 +0000
commitd649232e49a8bca55ba8684a605fd34068138cf6 (patch)
treecab8a0328c5dd3bbff38647e9a7326efa17c7b99 /addons/web_editor/static/src/js
parent0a23a2bb65f6e59e4db545e6736c754c55463b15 (diff)
[FIX] web_editor: DOM is not cleaned before saving custom snippets
Previously, when saving a custom snippet, the outerHTML of the snippet was naively read directly and saved as a new custom snippet. Unfortunately this completely bypasses all cleanup mechanisms that we have before saving, such as stopping the public widgets, or creating attachments for cropped or optimized images. This would result in weird bugs, where public widgets would appear twice when dropping a custom snippet containing one, as well as the creating a new attachment for any image that was optimized or cropped before saving the custom snippet every time it was dropped in the page again. Unfortunately there is no good mechanism for an option to ask the editor to clean the DOM without actually saving it, as a temporary measure, the snippet-save option will instead save the whole page (which will clean up the DOM) and save the custom snippet after the save, before refreshing the page and reopening the editor, not unlike some theme options. task-2341612 closes odoo/odoo#61202 X-original-commit: 2fa955267a3f81495be82c4214abd8befcf1fc95 Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
Diffstat (limited to 'addons/web_editor/static/src/js')
-rw-r--r--addons/web_editor/static/src/js/editor/snippets.editor.js6
-rw-r--r--addons/web_editor/static/src/js/editor/snippets.options.js54
2 files changed, 47 insertions, 13 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 ea9b0a8e64f..c8ac1b23cf1 100644
--- a/addons/web_editor/static/src/js/editor/snippets.editor.js
+++ b/addons/web_editor/static/src/js/editor/snippets.editor.js
@@ -2399,6 +2399,12 @@ var SnippetsMenu = Widget.extend({
});
},
/**
+ * UNUSED: used to be called when saving a custom snippet. We now save and
+ * reload the page when saving a custom snippet so that all the DOM cleanup
+ * mechanisms are run before saving. Kept for compatibility.
+ *
+ * TODO: remove in master / find a way to clean the DOM without save+reload
+ *
* @private
*/
_onReloadSnippetTemplate: async function (ev) {
diff --git a/addons/web_editor/static/src/js/editor/snippets.options.js b/addons/web_editor/static/src/js/editor/snippets.options.js
index 652a05571cd..d2935b8ccac 100644
--- a/addons/web_editor/static/src/js/editor/snippets.options.js
+++ b/addons/web_editor/static/src/js/editor/snippets.options.js
@@ -4,6 +4,7 @@ odoo.define('web_editor.snippets.options', function (require) {
var core = require('web.core');
const {ColorpickerWidget} = require('web.Colorpicker');
const Dialog = require('web.Dialog');
+const rpc = require('web.rpc');
const time = require('web.time');
var Widget = require('web.Widget');
var ColorPaletteWidget = require('web_editor.ColorPalette').ColorPaletteWidget;
@@ -4601,27 +4602,54 @@ registry.SnippetSave = SnippetOptionWidget.extend({
classes: 'btn-primary',
close: true,
click: async () => {
- const snippetName = dialog.el.querySelector('.o_we_snippet_name_input').value;
- const targetCopyEl = this.$target[0].cloneNode(true);
- delete targetCopyEl.dataset.name;
+ const save = await new Promise(resolve => {
+ Dialog.confirm(this, _t("To save a snippet, we need to save all your previous modifications and reload the page."), {
+ buttons: [
+ {
+ text: _t("Save and Reload"),
+ classes: 'btn-primary',
+ close: true,
+ click: () => resolve(true),
+ }, {
+ text: _t("Cancel"),
+ close: true,
+ click: () => resolve(false),
+ }
+ ]
+ });
+ });
+ if (!save) {
+ return;
+ }
const snippetKey = this.$target[0].dataset.snippet;
let thumbnailURL;
this.trigger_up('snippet_thumbnail_url_request', {
key: snippetKey,
onSuccess: url => thumbnailURL = url,
});
- await this._rpc({
- model: 'ir.ui.view',
- method: 'save_snippet',
- kwargs: {
- 'name': snippetName,
- 'arch': targetCopyEl.outerHTML,
- 'template_key': this.options.snippets,
- 'snippet_key': snippetKey,
- 'thumbnail_url': thumbnailURL,
+ this.trigger_up('request_save', {
+ reloadEditor: true,
+ onSuccess: async () => {
+ const snippetName = dialog.el.querySelector('.o_we_snippet_name_input').value;
+ const targetCopyEl = this.$target[0].cloneNode(true);
+ delete targetCopyEl.dataset.name;
+ // By the time onSuccess is called after request_save, the
+ // current widget has been destroyed and is orphaned, so this._rpc
+ // will not work as it can't trigger_up. For this reason, we need
+ // to bypass the service provider and use the global RPC directly
+ await rpc.query({
+ model: 'ir.ui.view',
+ method: 'save_snippet',
+ kwargs: {
+ 'name': snippetName,
+ 'arch': targetCopyEl.outerHTML,
+ 'template_key': this.options.snippets,
+ 'snippet_key': snippetKey,
+ 'thumbnail_url': thumbnailURL,
+ },
+ });
},
});
- this.trigger_up('reload_snippet_template');
},
}, {
text: _t("Discard"),