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. +

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