[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:
@@ -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 () {
|
||||
|
||||
Reference in New Issue
Block a user