diff --git a/addons/mass_mailing/static/src/js/snippets.editor.js b/addons/mass_mailing/static/src/js/snippets.editor.js
index 9bf8b202fac..20ef9a44584 100644
--- a/addons/mass_mailing/static/src/js/snippets.editor.js
+++ b/addons/mass_mailing/static/src/js/snippets.editor.js
@@ -1,15 +1,25 @@
odoo.define('mass_mailing.snippets.editor', function (require) {
'use strict';
+const {_lt} = require('web.core');
const snippetsEditor = require('web_editor.snippet.editor');
const MassMailingSnippetsMenu = snippetsEditor.SnippetsMenu.extend({
+ events: _.extend({}, snippetsEditor.SnippetsMenu.prototype.events, {
+ 'click .o_we_customize_design_btn': '_onDesignTabClick',
+ }),
custom_events: _.extend({}, snippetsEditor.SnippetsMenu.prototype.custom_events, {
drop_zone_over: '_onDropZoneOver',
drop_zone_out: '_onDropZoneOut',
drop_zone_start: '_onDropZoneStart',
drop_zone_stop: '_onDropZoneStop',
}),
+ tabs: _.extend({}, snippetsEditor.SnippetsMenu.prototype.tabs, {
+ DESIGN: 'design',
+ }),
+ optionsTabStructure: [
+ ['design-options', _lt("Design Options")],
+ ],
//--------------------------------------------------------------------------
// Public
@@ -38,6 +48,13 @@ const MassMailingSnippetsMenu = snippetsEditor.SnippetsMenu.extend({
$dropzone.attr('data-editor-sub-message', $hookParent.attr('data-editor-sub-message'));
return $dropzone;
},
+ /**
+ * @override
+ */
+ _updateRightPanelContent: function ({content, tab}) {
+ this._super(...arguments);
+ this.$('.o_we_customize_design_btn').toggleClass('active', tab === this.tabs.DESIGN);
+ },
//--------------------------------------------------------------------------
// Handler
@@ -88,6 +105,62 @@ const MassMailingSnippetsMenu = snippetsEditor.SnippetsMenu.extend({
$oEditable.attr('contenteditable', false);
}
},
+ /**
+ * @private
+ */
+ async _onDesignTabClick() {
+ // Note: nothing async here but start the loading effect asap
+ let releaseLoader;
+ try {
+ const promise = new Promise(resolve => releaseLoader = resolve);
+ this._execWithLoadingEffect(() => promise, false, 0);
+ // loader is added to the DOM synchronously
+ await new Promise(resolve => requestAnimationFrame(() => requestAnimationFrame(resolve)));
+ // ensure loader is rendered: first call asks for the (already done) DOM update,
+ // second call happens only after rendering the first "updates"
+
+ if (!this.topFakeOptionEl) {
+ let el;
+ for (const [elementName, title] of this.optionsTabStructure) {
+ const newEl = document.createElement(elementName);
+ newEl.dataset.name = title;
+ if (el) {
+ el.appendChild(newEl);
+ } else {
+ this.topFakeOptionEl = newEl;
+ }
+ el = newEl;
+ }
+ this.bottomFakeOptionEl = el;
+ this.el.appendChild(this.topFakeOptionEl);
+ }
+
+ // Need all of this in that order so that:
+ // - the element is visible and can be enabled and the onFocus method is
+ // called each time.
+ // - the element is hidden afterwards so it does not take space in the
+ // DOM, same as the overlay which may make a scrollbar appear.
+ this.topFakeOptionEl.classList.remove('d-none');
+ const editorPromise = this._activateSnippet($(this.bottomFakeOptionEl));
+ releaseLoader(); // because _activateSnippet uses the same mutex as the loader
+ releaseLoader = undefined;
+ const editor = await editorPromise;
+ this.topFakeOptionEl.classList.add('d-none');
+ editor.toggleOverlay(false);
+
+ this._updateRightPanelContent({
+ tab: this.tabs.DESIGN,
+ });
+ } catch (e) {
+ // Normally the loading effect is removed in case of error during the action but here
+ // the actual activity is happening outside of the action, the effect must therefore
+ // be cleared in case of error as well
+ if (releaseLoader) {
+ releaseLoader();
+ }
+ throw e;
+ }
+ },
});
return MassMailingSnippetsMenu;
diff --git a/addons/mass_mailing/views/snippets_themes.xml b/addons/mass_mailing/views/snippets_themes.xml
index 2605f92de0d..44c29a8b82e 100644
--- a/addons/mass_mailing/views/snippets_themes.xml
+++ b/addons/mass_mailing/views/snippets_themes.xml
@@ -13,7 +13,9 @@
-
+
@@ -532,5 +534,9 @@
data-img="/mass_mailing/static/src/img/snippets_options/align_stretch.svg"/>
+
+
+