Due to recent improvements (Jinja -> Qweb, safe rendering) rendering API
supports several ways of giving options to the rendering process. Those
have mainly two usage
* ``preserve_comments`` : keep comments in rendered HTML, used notably
in mass mailing or digest to keep browser-specific comments;
* ``post_process`` : perform a post processing on rendered HTML, used notably
to process local links and add tracking to shortened links;
All those are now given directly inside an optional ``options`` parameter
given to ``_render_field`` and its sub-method ``_render_template``.
They can also be defined as field level, using ``render_options`` field
parameter. Some fields are updated
* composer mixin body (which impacts all inheriting models, notably
mail composer, survey and elearning invite wizards as well as appraisal
and appraisal feedback): post processing is now always done by default.
It was already done manually in calls that can be simplified;
* mail template body_html: post processing is now always done by default. It
was already done manually in calls that can be simplified;
* mailing body_html and preview are now post processed by default. It was
already the case in testing wizard. Preview is updated to avoid post
processing of links, as it was before. Remaining use case is the sending
which uses the mail composer, therefore was already post processed;
Finally some 'compute_lang' are explicitly added in _render_field calls in
order to be explicit on what we want, instead of being unsure.
Task-2710804 (Mail: Clean MailThread API)
Prepares Task-2088884 (Mail: Use editable computed stored fields in composer)
Part-of: odoo/odoo#106072
96 lines
4.1 KiB
Python
96 lines
4.1 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from odoo import api, fields, models, tools, _
|
|
|
|
|
|
class MailComposerMixin(models.AbstractModel):
|
|
""" Mixin used to edit and render some fields used when sending emails or
|
|
notifications based on a mail template.
|
|
|
|
Main current purpose is to hide details related to subject and body computation
|
|
and rendering based on a mail.template. It also give the base tools to control
|
|
who is allowed to edit body, notably when dealing with templating language
|
|
like inline_template or qweb.
|
|
|
|
It is meant to evolve in a near future with upcoming support of qweb and fine
|
|
grain control of rendering access.
|
|
"""
|
|
_name = 'mail.composer.mixin'
|
|
_inherit = 'mail.render.mixin'
|
|
_description = 'Mail Composer Mixin'
|
|
|
|
# Content
|
|
subject = fields.Char('Subject', compute='_compute_subject', readonly=False, store=True)
|
|
body = fields.Html(
|
|
'Contents', compute='_compute_body', readonly=False, store=True,
|
|
render_engine='qweb', render_options={'post_process': True}, sanitize=False)
|
|
template_id = fields.Many2one('mail.template', 'Mail Template', domain="[('model', '=', render_model)]")
|
|
# Access
|
|
is_mail_template_editor = fields.Boolean('Is Editor', compute='_compute_is_mail_template_editor')
|
|
can_edit_body = fields.Boolean('Can Edit Body', compute='_compute_can_edit_body')
|
|
|
|
@api.depends('template_id')
|
|
def _compute_subject(self):
|
|
for composer_mixin in self:
|
|
if composer_mixin.template_id:
|
|
composer_mixin.subject = composer_mixin.template_id.subject
|
|
elif not composer_mixin.subject:
|
|
composer_mixin.subject = False
|
|
|
|
@api.depends('template_id')
|
|
def _compute_body(self):
|
|
for composer_mixin in self:
|
|
if composer_mixin.template_id:
|
|
composer_mixin.body = composer_mixin.template_id.body_html
|
|
elif not composer_mixin.body:
|
|
composer_mixin.body = False
|
|
|
|
@api.depends_context('uid')
|
|
def _compute_is_mail_template_editor(self):
|
|
is_mail_template_editor = self.env.is_admin() or self.env.user.has_group('mail.group_mail_template_editor')
|
|
for record in self:
|
|
record.is_mail_template_editor = is_mail_template_editor
|
|
|
|
@api.depends('template_id', 'is_mail_template_editor')
|
|
def _compute_can_edit_body(self):
|
|
for record in self:
|
|
record.can_edit_body = (
|
|
record.is_mail_template_editor
|
|
or not record.template_id
|
|
)
|
|
|
|
def _render_field(self, field, *args, **kwargs):
|
|
"""Render the given field on the given records.
|
|
This method bypass the rights when needed to
|
|
be able to render the template values in mass mode.
|
|
"""
|
|
if field not in self._fields:
|
|
raise ValueError(_("The field %s does not exist on the model %s", field, self._name))
|
|
|
|
composer_value = self[field]
|
|
|
|
if (
|
|
not self.template_id
|
|
or self.is_mail_template_editor
|
|
):
|
|
# Do not need to bypass the verification
|
|
return super(MailComposerMixin, self)._render_field(field, *args, **kwargs)
|
|
|
|
template_field = 'body_html' if field == 'body' else field
|
|
assert template_field in self.template_id._fields
|
|
template_value = self.template_id[template_field]
|
|
|
|
if field == 'body':
|
|
sanitized_template_value = tools.html_sanitize(template_value)
|
|
if not self.can_edit_body or composer_value in (sanitized_template_value, template_value):
|
|
# Take the previous body which we can trust without HTML editor reformatting
|
|
self.body = self.template_id.body_html
|
|
return super(MailComposerMixin, self.sudo())._render_field(field, *args, **kwargs)
|
|
|
|
elif composer_value == template_value:
|
|
# The value is the same as the mail template so we trust it
|
|
return super(MailComposerMixin, self.sudo())._render_field(field, *args, **kwargs)
|
|
|
|
return super(MailComposerMixin, self)._render_field(field, *args, **kwargs)
|