Files
odoo_source/addons/mail/models/mail_composer_mixin.py
T
Nicolas Bayet 4813f42997 [IMP] mail,*: replace jinja with qweb
Jinja as a templating engine was problematic in differents respect:
- introduce external dependency to Odoo (less controll)
- add another templating mechanism in the stack
- specific feature in qweb cannot be reused
- difficulty in rendering easily editable templates
- more knowledge required with no betterment

By replacing jinja with qweb we can now build tools to edit a qweb
that will work with the previously jinja encoded document
(essentially `mail.template` records).

There is a catch however. Some email fields (eg. email_to) used jinja
syntax for rendering dynamic variables (ie. ${object.something} and
${object.something_that_should_not_be_escaped | safe}).

We still want user to use dynamic variables for some char fields (eg.
subject, from, to, ...). We made a new rendering engine called
"inline_template" that will render an expression enclosed by `{{` and
`}}`.

To be able to edit the templates from the backend interface, a
plugin to the Odoo editor has been made for seamlessly edit the
document.

This qweb plugin includes:
- make dynamic variables (eg. `<t t-out="variable"/>`) not editable
  (for preventing the user to shoot himself in the foot)
- group and hide related logical branching (ie. t-if, t-elif, and t-else)
  in order to see only one at once
- a floating select input to switch visibility of a particular logical
  branching

Task-27033

X-original-commit: odoo/odoo@68182baff4
Part-of: odoo/odoo#77377
2021-09-28 23:42:54 +00:00

94 lines
4.0 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', render_engine='qweb', store=True, readonly=False, 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)