[FIX] mass_mailing: hide menu on mobile

closes odoo/odoo#114543

Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
This commit is contained in:
Renaud Thiry
2023-03-08 16:26:16 +01:00
parent 7c533fce5c
commit beb02b5c8e
7 changed files with 218 additions and 29 deletions
@@ -46,10 +46,11 @@ export class MassMailingHtmlField extends HtmlField {
return {
...super.wysiwygOptions,
onIframeUpdated: () => this.onIframeUpdated(),
foldSnippets: device.isMobile,
snippets: 'mass_mailing.email_designer_snippets',
resizable: false,
defaultDataForLinkTools: { isNewWindow: true },
toolbarTemplate: 'mass_mailing.web_editor_toolbar',
toolbarTemplate: device.isMobile ? 'web_editor.toolbar' : 'mass_mailing.web_editor_toolbar',
...this.props.wysiwygOptions,
};
}
@@ -226,11 +227,6 @@ export class MassMailingHtmlField extends HtmlField {
// Overide `d-flex` class which style is `!important`
$snippetsSideBar.find(`.o_we_website_top_actions > *:not(${selectorToKeep})`).attr('style', 'display: none!important');
if (device.isMobile) {
$snippetsSideBar.hide();
this.wysiwyg.$iframe.attr('style', 'padding-left: 0px !important');
}
if (!odoo.debug) {
$snippetsSideBar.find('.o_codeview_btn').hide();
}
@@ -269,7 +265,11 @@ export class MassMailingHtmlField extends HtmlField {
if (!this._themeParams) {
// Initialize theme parameters.
this._themeClassNames = "";
this._themeParams = _.map($themes, (theme) => {
const displayableThemes =
device.isMobile ?
_.filter($themes, theme => !$(theme).data("hideFromMobile")) :
$themes;
this._themeParams = _.map(displayableThemes, (theme) => {
const $theme = $(theme);
const name = $theme.data("name");
const classname = "o_" + name + "_theme";
@@ -335,6 +335,8 @@ export class MassMailingHtmlField extends HtmlField {
const editableAreaIsEmpty = value === "" || value === blankEditable;
if (editableAreaIsEmpty) {
// unfold to prevent toolbar from going over the menu
this.wysiwyg.snippetsMenu.setFolded(false);
$themeSelectorNew.appendTo(this.wysiwyg.$iframeBody);
}
@@ -350,6 +352,9 @@ export class MassMailingHtmlField extends HtmlField {
this.wysiwyg.$iframeBody.closest('body').removeClass("o_force_mail_theme_choice");
$themeSelectorNew.remove();
if (device.isMobile) {
this.wysiwyg.snippetsMenu.setFolded(true);
}
this._switchImages(themeParams, $snippets);
@@ -375,6 +380,8 @@ export class MassMailingHtmlField extends HtmlField {
selection.removeAllRanges();
selection.addRange(range);
}
// mark selection done for tour testing
$editable.addClass('theme_selection_done');
}, 0);
});
@@ -51,3 +51,144 @@ registry.category("web_tour.tours").add('mass_mailing_snippets_menu_tabs', {
},
...stepUtils.discardForm(),
]});
registry.category("web_tour.tours").add('mass_mailing_snippets_menu_toolbar_new_mailing_mobile', {
test: true,
url: '/web',
steps: [
stepUtils.showAppsMenuItem(), {
content: "Select the 'Email Marketing' app.",
trigger: '.o_app[data-menu-xmlid="mass_mailing.mass_mailing_menu_root"]',
},
{
content: "Click on the create button to create a new mailing.",
trigger: 'button.o_list_button_add',
mobile: true,
},
{
content: "Check templates available in theme selector",
trigger: 'iframe .o_mail_theme_selector_new',
run: function () {
if (this.$anchor[0].querySelector('#empty')) {
console.error('The empty template should not be visible on mobile.');
}
},
mobile: true,
},
{
content: "Make sure the toolbar isn't floating",
trigger: 'iframe',
run: function () {
const iframeDocument = this.$anchor[0].contentDocument;
if (iframeDocument.querySelector('#toolbar.oe-floating')) {
console.error('There should not be a floating toolbar in the iframe');
}
},
mobile: true,
},
{
content: "Click on the 'Start From Scratch' template.",
trigger: 'iframe #default',
mobile: true,
},
{
content: "Select an editable element",
trigger: 'iframe .s_text_block',
mobile: true,
},
{
content: "Make sure the snippets menu is hidden",
trigger: 'iframe',
run: function () {
const iframeDocument = this.$anchor[0].contentDocument;
if (!iframeDocument.querySelector('#oe_snippets.d-none')) {
console.error('The snippet menu should be hidden');
}
},
mobile: true,
},
{
content: "Make sure the toolbar is there",
trigger: 'iframe #toolbar.oe-floating',
run: () => null, // it's a check
mobile: true,
},
...stepUtils.discardForm().map(command => ({...command, mobile: true})),
]
});
registry.category("web_tour.tours").add('mass_mailing_snippets_menu_toolbar', {
test: true,
url: '/web',
steps: [
stepUtils.showAppsMenuItem(), {
content: "Select the 'Email Marketing' app.",
trigger: '.o_app[data-menu-xmlid="mass_mailing.mass_mailing_menu_root"]',
},
{
content: "Click on the create button to create a new mailing.",
trigger: 'button.o_list_button_add',
},
{
content: "Wait for the theme selector to load.",
trigger: 'iframe .o_mail_theme_selector_new',
},
{
content: "Make sure there does not exist a floating toolbar",
trigger: 'iframe',
run: function () {
const iframeDocument = this.$anchor[0].contentDocument;
if (iframeDocument.querySelector('#toolbar.oe-floating')) {
console.error('There should not be a floating toolbar in the iframe');
}
},
},
{
content: "Make sure the empty template is an option on non-mobile devices.",
trigger: 'iframe #empty',
run: () => null,
},
{
content: "Click on the default 'welcome' template.",
trigger: 'iframe #default',
},
{ // necessary to wait for the cursor to be placed in the first p
// and to avoid leaving the page before the selection is added
content: "Wait for template selection event to be over.",
trigger: 'iframe .o_editable.theme_selection_done',
},
{
content: "Make sure the snippets menu is not hidden",
trigger: 'iframe #oe_snippets:not(.d-none)',
run: () => null,
},
{
content: "Wait for .s_text_block to be populated",
trigger: 'iframe .s_text_block p',
run: () => null,
},
{
content: "Click and select p block inside the editor",
trigger: 'iframe',
run: function () {
const iframeWindow = this.$anchor[0].contentWindow;
const iframeDocument = iframeWindow.document;
const p = iframeDocument.querySelector('.s_text_block p');
p.click();
const selection = iframeWindow.getSelection();
const range = iframeDocument.createRange();
range.selectNodeContents(p);
selection.removeAllRanges();
selection.addRange(range);
},
},
{
content: "Make sure the toolbar is there",
trigger: 'iframe #oe_snippets .o_we_customize_panel #toolbar',
run: () => null,
},
...stepUtils.discardForm(),
],
});
@@ -1,10 +1,13 @@
.o_mass_mailing_iframe body {
// padding for snippets only if editor has snippets (not on mobile)
// (not reactive as hiding the menu itself isn't reactive)
.o_mass_mailing_iframe body.editor_has_snippets {
padding-right: $o-we-sidebar-width !important;
#web_editor-top-edit .note-popover .popover {
right: $o-we-sidebar-width !important;
}
}
.o_mass_mailing_iframe body {
.modal:not(.o_technical_modal) {
top: 0 !important;
// set z-index so customize options visible on dialog.
@@ -27,3 +27,9 @@ class TestUi(HttpCaseWithUserDemo):
def test_02_mass_mailing_snippets_menu_tabs(self):
self.start_tour("/web", 'mass_mailing_snippets_menu_tabs', login="demo")
def test_03_mass_mailing_snippets_toolbar_mobile_hide(self):
self.start_tour("/web", 'mass_mailing_snippets_menu_toolbar_new_mailing_mobile', login="demo")
def test_04_mass_mailing_snippets_menu_hide(self):
self.start_tour("/web", 'mass_mailing_snippets_menu_toolbar', login="demo")
@@ -34,7 +34,8 @@
<div data-name="empty"
title="Start From Scratch"
data-img="/mass_mailing/static/src/img/theme_imgs/empty_thumb"
data-images-info='{"logo": {"format": "png"}}'>
data-images-info='{"logo": {"format": "png"}}'
data-hide-from-mobile="true">
<t t-call="mass_mailing.theme_empty_template"/>
</div>
<div data-name="default"
@@ -1827,9 +1827,12 @@ var SnippetsMenu = Widget.extend({
this.$el = this.window.$(this.$el);
this.$el.data('snippetMenu', this);
this.folded = !!this.options.foldSnippets;
this.customizePanel = document.createElement('div');
this.customizePanel.classList.add('o_we_customize_panel', 'd-none');
this._addToolbar();
// adds toolbar if not folded
this.setFolded(this.folded);
this._checkEditorToolbarVisibilityCallback = this._checkEditorToolbarVisibility.bind(this);
$(this.options.wysiwyg.odooEditor.document.body).on('click', this._checkEditorToolbarVisibilityCallback);
@@ -2118,6 +2121,17 @@ var SnippetsMenu = Widget.extend({
cacheSnippetTemplate[this.options.snippets] = this._defLoadSnippets;
return this._defLoadSnippets;
},
/**
* Visually hide or display this snippet menu
* @param {boolean} foldState
*/
setFolded: function (foldState = true) {
this.el.classList.toggle('d-none', foldState);
this.el.ownerDocument.body.classList.toggle('editor_has_snippets', !foldState);
this.folded = !!foldState;
// "add" toolbar to set it inside the snippet menu/in the body
this._addToolbar();
},
/**
* Get the editable area.
*
@@ -2901,7 +2915,7 @@ var SnippetsMenu = Widget.extend({
this._disableUndroppableSnippets();
this.$el.addClass('o_loaded');
$(this.el.ownerDocument.body).addClass('editor_has_snippets');
$(this.el.ownerDocument.body).toggleClass('editor_has_snippets', !this.folded);
},
/**
* Eases patching the XML definition for snippets and options in stable
@@ -3364,7 +3378,10 @@ var SnippetsMenu = Widget.extend({
this._currentTab = tab || this.tabs.BLOCKS;
this._$toolbarContainer[0].remove();
if (this._$toolbarContainer) {
this._$toolbarContainer[0].remove();
}
this._$toolbarContainer = null;
if (content) {
while (this.customizePanel.firstChild) {
this.customizePanel.removeChild(this.customizePanel.firstChild);
@@ -4107,6 +4124,10 @@ var SnippetsMenu = Widget.extend({
this._filterSnippets('');
},
_addToolbar(toolbarMode = "text") {
if (this.folded) {
this._addToolbarToOriginalPosition();
return;
}
let titleText = _t("Inline Text");
switch (toolbarMode) {
case "image":
@@ -4121,26 +4142,35 @@ var SnippetsMenu = Widget.extend({
}
this.options.wysiwyg.toolbar.el.classList.remove('oe-floating');
if (!this._$toolbarContainer) {
// Create toolbar custom container.
this._$toolbarContainer = $('<WE-CUSTOMIZEBLOCK-OPTIONS id="o_we_editor_toolbar_container"/>');
const $title = $("<we-title><span>" + titleText + "</span></we-title>");
this._$toolbarContainer.append($title);
this._$toolbarContainer.append(this.options.wysiwyg.toolbar.$el);
$(this.customizePanel).append(this._$toolbarContainer);
// Create toolbar custom container.
this._$toolbarContainer = $('<WE-CUSTOMIZEBLOCK-OPTIONS id="o_we_editor_toolbar_container"/>');
const $title = $("<we-title><span>" + titleText + "</span></we-title>");
this._$toolbarContainer.append($title);
this._$toolbarContainer.append(this.options.wysiwyg.toolbar.$el);
$(this.customizePanel).append(this._$toolbarContainer);
// Create table-options custom container.
const $customizeTableBlock = $(QWeb.render('web_editor.toolbar.table-options'));
this.options.wysiwyg.odooEditor.bindExecCommand($customizeTableBlock[0]);
$(this.customizePanel).append($customizeTableBlock);
this._$removeFormatButton = this._$removeFormatButton || this.options.wysiwyg.toolbar.$el.find('#removeFormat');
$title.append(this._$removeFormatButton);
// Create table-options custom container.
const $customizeTableBlock = $(QWeb.render('web_editor.toolbar.table-options'));
this.options.wysiwyg.odooEditor.bindExecCommand($customizeTableBlock[0]);
$(this.customizePanel).append($customizeTableBlock);
this._$removeFormatButton = this.options.wysiwyg.toolbar.$el.find('#removeFormat');
$title.append(this._$removeFormatButton);
this._$toolbarContainer.append(this.options.wysiwyg.toolbar.$el);
}
this._checkEditorToolbarVisibility();
},
_addToolbarToOriginalPosition: function () {
const toolbar = this.options.wysiwyg.toolbar.el;
toolbar.classList.add('oe-floating');
if (this.options.wysiwyg.odooEditor.isMobile) {
const editorEditable = this.options.wysiwyg.odooEditor.editable;
editorEditable.before(toolbar);
} else if (this.options.autohideToolbar) {
document.body.appendChild(toolbar);
}
},
/**
* Update editor UI visibility based on the current range.
*/
@@ -224,6 +224,7 @@ const Wysiwyg = Widget.extend({
collaborationClientAvatarUrl: `${browser.location.origin}/web/image?model=res.users&field=avatar_128&id=${this.getSession().uid}`,
renderingClasses: ['o_dirty', 'o_transform_removal', 'oe_edited_link', 'o_menu_loading'],
dropImageAsAttachment: options.dropImageAsAttachment,
foldSnippets: !!options.foldSnippets,
}, editorCollaborationOptions));
this.odooEditor.addEventListener('contentChanged', function () {