From 171eea3fae81ad4f147e5092bbd0b7c2ae0c8184 Mon Sep 17 00:00:00 2001 From: nounoubensebia Date: Wed, 31 Mar 2021 12:46:13 +0000 Subject: [PATCH] [IMP] mass_mailing[_sms], tools: make mass mailing form focus on body Make the email body take the entire space to avoid having some wasted space, this will also make the user have more focus when designing an email. Revamp the settings notebook page in order to give more clarity to the user, and move some fields from the main form have been moved to this section to have more space in the bottom for the email body. In the mailing form, when the mailing is sent or is being sent, set fields which are no longer useful for the user to change to readonly mode. Add a wizard that enables the user to schedule a mailing, the schedule field is still kept in the form for the user to be able to change the date when the mailing is in the queue (if they want to send it sooner). Display an action helper-style content when the email is empty, because, currently, the user is left with a big white screen when the email has no content which is not desirable. Update the html_empty function to take into account style attributes to better match the editor's void content. Hide A/B testing fields from SMS mailing form view as these are not supported for SMS marketing. Task-2469409 closes odoo/odoo#68882 Ent-pr: https://github.com/odoo/odoo/pull/68882 Related: odoo/enterprise#18391 Signed-off-by: Thibault Delavallee (tde) --- addons/mass_mailing/__manifest__.py | 1 + addons/mass_mailing/models/mailing.py | 30 +++++- .../mass_mailing/security/ir.model.access.csv | 1 + .../static/src/css/basic_theme_readonly.css | 7 ++ .../static/src/js/mass_mailing_widget.js | 7 ++ .../static/src/scss/mass_mailing.scss | 34 +++++++ .../static/src/scss/mass_mailing.ui.scss | 14 +++ addons/mass_mailing/tests/__init__.py | 1 + .../tests/test_mailing_internals.py | 23 +++++ .../test_mailing_mailing_schedule_date.py | 33 +++++++ .../views/mailing_mailing_views.xml | 94 +++++++++++-------- addons/mass_mailing/wizard/__init__.py | 1 + .../wizard/mailing_mailing_schedule_date.py | 16 ++++ .../mailing_mailing_schedule_date_views.xml | 28 ++++++ .../views/mailing_mailing_views.xml | 27 ++++-- odoo/addons/base/tests/test_mail.py | 6 +- odoo/tools/mail.py | 8 +- 17 files changed, 273 insertions(+), 58 deletions(-) create mode 100644 addons/mass_mailing/tests/test_mailing_mailing_schedule_date.py create mode 100644 addons/mass_mailing/wizard/mailing_mailing_schedule_date.py create mode 100644 addons/mass_mailing/wizard/mailing_mailing_schedule_date_views.xml diff --git a/addons/mass_mailing/__manifest__.py b/addons/mass_mailing/__manifest__.py index 51f1bd6f86d..1c2b0c86af8 100644 --- a/addons/mass_mailing/__manifest__.py +++ b/addons/mass_mailing/__manifest__.py @@ -30,6 +30,7 @@ 'wizard/mailing_contact_to_list_views.xml', 'wizard/mailing_list_merge_views.xml', 'wizard/mailing_mailing_test_views.xml', + 'wizard/mailing_mailing_schedule_date_views.xml', 'views/mailing_mailing_views_menus.xml', 'views/mailing_trace_views.xml', 'views/link_tracker_views.xml', diff --git a/addons/mass_mailing/models/mailing.py b/addons/mass_mailing/models/mailing.py index 82abae99248..7646a0b0e12 100644 --- a/addons/mass_mailing/models/mailing.py +++ b/addons/mass_mailing/models/mailing.py @@ -88,14 +88,18 @@ class MassMailing(models.Model): sent_date = fields.Datetime(string='Sent Date', copy=False) schedule_type = fields.Selection([('now', 'Send now'), ('scheduled', 'Send on')], string='Schedule', - default='now', required=True, readonly=True, states={'draft': [('readonly', False)]}) - schedule_date = fields.Datetime(string='Scheduled for', tracking=True, readonly=True, states={'draft': [('readonly', False)]}, - compute='_compute_schedule_date', store=True, copy=True) + default='now', required=True, readonly=True, + states={'draft': [('readonly', False)], 'in_queue': [('readonly', False)]}) + schedule_date = fields.Datetime(string='Scheduled for', tracking=True, readonly=True, + states={'draft': [('readonly', False)], 'in_queue': [('readonly', False)]}, + compute='_compute_schedule_date', store=True, copy=True) calendar_date = fields.Datetime('Calendar Date', compute='_compute_calendar_date', store=True, copy=False, help="Technical field for the calendar view.") # don't translate 'body_arch', the translations are only on 'body_html' body_arch = fields.Html(string='Body', translate=False) body_html = fields.Html(string='Body converted to be sent by mail', sanitize_attributes=False) + is_body_empty = fields.Boolean(compute="_compute_is_body_empty", + help='Technical field used to determine if the mail body is empty') attachment_ids = fields.Many2many('ir.attachment', 'mass_mailing_ir_attachments_rel', 'mass_mailing_id', 'attachment_id', string='Attachments') keep_archives = fields.Boolean(string='Keep Archives') @@ -132,6 +136,9 @@ class MassMailing(models.Model): mailing_domain = fields.Char( string='Domain', compute='_compute_mailing_domain', readonly=False, store=True) + mail_server_available = fields.Boolean( + compute='_compute_mail_server_available', + help="Technical field used to know if the user has activated the outgoing mail server option in the settings") mail_server_id = fields.Many2one('ir.mail_server', string='Mail Server', default=_get_default_mail_server_id, help="Use a specific mail server in priority. Otherwise Odoo relies on the first outgoing mail server available (based on their sequencing) as it does for normal mails.") @@ -290,6 +297,14 @@ class MassMailing(models.Model): else: mailing.calendar_date = False + @api.depends('body_html') + def _compute_is_body_empty(self): + for mailing in self: + mailing.is_body_empty = tools.is_html_empty(mailing.body_html) + + def _compute_mail_server_available(self): + self.mail_server_available = self.env['ir.config_parameter'].sudo().get_param('mass_mailing.outgoing_mail_server') + # ------------------------------------------------------ # ORM # ------------------------------------------------------ @@ -353,10 +368,17 @@ class MassMailing(models.Model): } def action_launch(self): + self.write({'schedule_type': 'now'}) return self.action_put_in_queue() def action_schedule(self): - return self.action_put_in_queue() + self.ensure_one() + if self.schedule_date: + return self.action_put_in_queue() + else: + action = self.env["ir.actions.actions"]._for_xml_id("mass_mailing.mailing_mailing_schedule_date_action") + action['context'] = dict(self.env.context, default_mass_mailing_id=self.id) + return action def action_put_in_queue(self): self.write({'state': 'in_queue'}) diff --git a/addons/mass_mailing/security/ir.model.access.csv b/addons/mass_mailing/security/ir.model.access.csv index 58cf8054186..07d0dce33ad 100644 --- a/addons/mass_mailing/security/ir.model.access.csv +++ b/addons/mass_mailing/security/ir.model.access.csv @@ -18,3 +18,4 @@ access_link_tracker_mailing,access.link.tracker.mailing,link_tracker.model_link_ access_mailing_list_merge,access.mailing.list.merge,model_mailing_list_merge,mass_mailing.group_mass_mailing_user,1,1,1,0 access_mailing_mailing_test,access.mailing.mailing.test,model_mailing_mailing_test,mass_mailing.group_mass_mailing_user,1,1,1,0 access_mailing_contact_to_list,access.mailing.contact.to.list,model_mailing_contact_to_list,mass_mailing.group_mass_mailing_user,1,1,1,1 +access_mailing_schedule_date,access.mailing.schedule.date,model_mailing_mailing_schedule_date,mass_mailing.group_mass_mailing_user,1,1,1,1 diff --git a/addons/mass_mailing/static/src/css/basic_theme_readonly.css b/addons/mass_mailing/static/src/css/basic_theme_readonly.css index 340eec95a68..09337cbfdf8 100644 --- a/addons/mass_mailing/static/src/css/basic_theme_readonly.css +++ b/addons/mass_mailing/static/src/css/basic_theme_readonly.css @@ -5,3 +5,10 @@ #wrapwrap .o_layout.o_basic_theme { font-family: -apple-system, "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; } + +/* +Make sure that the mail body takes all available space + */ +body.o_readonly.o_in_iframe { + margin: 0; +} diff --git a/addons/mass_mailing/static/src/js/mass_mailing_widget.js b/addons/mass_mailing/static/src/js/mass_mailing_widget.js index 98c05789da5..4e279014fb4 100644 --- a/addons/mass_mailing/static/src/js/mass_mailing_widget.js +++ b/addons/mass_mailing/static/src/js/mass_mailing_widget.js @@ -347,6 +347,11 @@ var MassMailingFieldHtml = FieldHtml.extend({ this._super(); this.wysiwyg.odooEditor.observerFlush(); this.wysiwyg.odooEditor.resetHistory(); + //this will make the editor take all the bottom space + this.wysiwyg.$iframe.css({ + 'min-height': '100vh', + width: '100%' + }); }, /** * @private @@ -442,6 +447,8 @@ var MassMailingFieldHtml = FieldHtml.extend({ $themeSelectorNew.appendTo(this.wysiwyg.$iframeBody); } + this.wysiwyg.$iframeBody.addClass("o_mass_mailing_iframe") + /** * Add proposition to install enterprise themes if not installed. */ diff --git a/addons/mass_mailing/static/src/scss/mass_mailing.scss b/addons/mass_mailing/static/src/scss/mass_mailing.scss index 129c1e0e90b..a035f5bd08c 100644 --- a/addons/mass_mailing/static/src/scss/mass_mailing.scss +++ b/addons/mass_mailing/static/src/scss/mass_mailing.scss @@ -1,3 +1,19 @@ +.o_form_view .o_form_sheet .o_notebook .tab-content .tab-pane .o_mail_body { + // cancel the padding of the form_sheet + margin-top: -$o-sheet-cancel-hpadding; + margin-left: -$o-sheet-cancel-hpadding; + margin-right: -$o-sheet-cancel-hpadding; + margin-bottom: -40px; +} + +@include media-breakpoint-between(lg, xl, $o-extra-grid-breakpoints) { + .o_form_view .o_form_sheet .o_notebook .tab-content .tab-pane .o_mail_body { + // cancel the padding of the form_sheet when breakpoints are reached + margin-left: -$o-sheet-cancel-hpadding*2; + margin-right: -$o-sheet-cancel-hpadding*2; + } +} + .o_kanban_view { .oe_kanban_mass_mailing { .o_title { @@ -22,6 +38,24 @@ } } } + +.o_form_view .o_group.o_inner_group.o_mass_mailing_mailing_group { + //used to gain extra space in form + display: block; +} + +.o_mass_mailing_mailing_form { + .alert:not(.o_invisible_modifier) + .clearfix.position-relative.o_form_sheet { + //hides extra space between form and alert messages + margin-top: -12px; + } +} + +.o_form_view.o_xxl_form_view.o_mass_mailing_mailing_form { + // This will hide the chatter scroll bar + height: initial; +} + .o_form_view { // This will display the emoji widget in the right position after a text field with sms option. .o_sms_container ~ .o_mail_add_emoji{ diff --git a/addons/mass_mailing/static/src/scss/mass_mailing.ui.scss b/addons/mass_mailing/static/src/scss/mass_mailing.ui.scss index cf9391f2722..e3bd9010f02 100644 --- a/addons/mass_mailing/static/src/scss/mass_mailing.ui.scss +++ b/addons/mass_mailing/static/src/scss/mass_mailing.ui.scss @@ -268,3 +268,17 @@ body.editor_enable.o_basic_theme.o_in_iframe { :root { font-size: 14px; } + + +.o_mass_mailing_iframe { + //this will display the email body without padding + .note-editable { + padding: 0; + } + + //this will display the editor wrapper and the snippets at the same level + .iframe-editor-wrapper { + margin-top: -2px; + } + +} diff --git a/addons/mass_mailing/tests/__init__.py b/addons/mass_mailing/tests/__init__.py index ddc9e161eec..520838f6f8d 100644 --- a/addons/mass_mailing/tests/__init__.py +++ b/addons/mass_mailing/tests/__init__.py @@ -5,3 +5,4 @@ from . import common from . import test_mailing_internals from . import test_mailing_list from . import test_mailing_controllers +from . import test_mailing_mailing_schedule_date diff --git a/addons/mass_mailing/tests/test_mailing_internals.py b/addons/mass_mailing/tests/test_mailing_internals.py index c220fd4e675..2d762f5dfcd 100644 --- a/addons/mass_mailing/tests/test_mailing_internals.py +++ b/addons/mass_mailing/tests/test_mailing_internals.py @@ -370,3 +370,26 @@ Email: test@odoo.com""", link_info, link_params=link_params, ) + +class TestMailingScheduleDateWizard(MassMailCommon): + + @mute_logger('odoo.addons.mail.models.mail_mail') + @users('user_marketing') + def test_mailing_schedule_date(self): + mailing = self.env['mailing.mailing'].create({ + 'name': 'mailing', + 'subject': 'some subject' + }) + # create a schedule date wizard + wizard_form = Form( + self.env['mailing.mailing.schedule.date'].with_context(default_mass_mailing_id=mailing.id)) + + # set a schedule date + wizard_form.schedule_date = datetime(2021, 4, 30, 9, 0) + wizard = wizard_form.save() + wizard.action_schedule_date() + + # assert that the schedule_date and schedule_type fields are correct and that the mailing is put in queue + self.assertEqual(mailing.schedule_date, datetime(2021, 4, 30, 9, 0)) + self.assertEqual(mailing.schedule_type, 'scheduled') + self.assertEqual(mailing.state, 'in_queue') diff --git a/addons/mass_mailing/tests/test_mailing_mailing_schedule_date.py b/addons/mass_mailing/tests/test_mailing_mailing_schedule_date.py new file mode 100644 index 00000000000..815cdb24a69 --- /dev/null +++ b/addons/mass_mailing/tests/test_mailing_mailing_schedule_date.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from datetime import datetime + +from odoo.addons.mass_mailing.tests.common import MassMailCommon +from odoo.tests import users, Form +from odoo.tools import mute_logger + + +class TestMailingScheduleDateWizard(MassMailCommon): + + @mute_logger('odoo.addons.mail.models.mail_mail') + @users('user_marketing') + def test_mailing_schedule_date(self): + mailing = self.env['mailing.mailing'].create({ + 'name': 'mailing', + 'subject': 'some subject', + 'mailing_model_id': self.env['ir.model']._get('res.partner').id, + }) + # create a schedule date wizard + wizard_form = Form( + self.env['mailing.mailing.schedule.date'].with_context(default_mass_mailing_id=mailing.id)) + + # set a schedule date + wizard_form.schedule_date = datetime(2021, 4, 30, 9, 0) + wizard = wizard_form.save() + wizard.action_schedule_date() + + # assert that the schedule_date and schedule_type fields are correct and that the mailing is put in queue + self.assertEqual(mailing.schedule_date, datetime(2021, 4, 30, 9, 0)) + self.assertEqual(mailing.schedule_type, 'scheduled') + self.assertEqual(mailing.state, 'in_queue') diff --git a/addons/mass_mailing/views/mailing_mailing_views.xml b/addons/mass_mailing/views/mailing_mailing_views.xml index 1a6043ee520..2692f0cfe77 100644 --- a/addons/mass_mailing/views/mailing_mailing_views.xml +++ b/addons/mass_mailing/views/mailing_mailing_views.xml @@ -54,13 +54,13 @@ mailing.mailing.form mailing.mailing -
+
- - + - - - +
+ + +
+ +
+
+

+ No template picked yet. +

+

+ Start editing your mailing to design something awesome. +

+
+
- - - + + + - + + - -