Something went wrong on our end
-
oury.balde authored
Only required for mustache/handlebars template engines.
oury.balde authoredOnly required for mustache/handlebars template engines.
redner_template.py 8.08 KiB
import logging
import re
from odoo import _, api, fields, models
from odoo.exceptions import ValidationError
from .redner import Redner
logger = logging.getLogger(__name__)
PREFIX = "tmpl_"
expression_pattern = re.compile(
r"""
(?P<open_bracket>\{\{) # Match opening brackets {{
(?P<content>.*) # Match anything
(?P<close_bracket>\}\}) # Match closing brackets }}
""",
re.VERBOSE,
)
# Match every words which starts with PREFIX
variable_pattern = re.compile(r"(?P<variable>%s[\w]+)" % PREFIX, re.VERBOSE)
def get_redner_tmpl_keys(data) -> list: # noqa
"""Retrieve every substitution template variables, should be prefixed by
``tmpl_``.
Args:
data(string): xml body i.e::
<mjml><mj-body>{{tmpl_replace_me}}</mj-body></mjml>
Returns:
list: of keywords
"""
if not data:
return []
return list(
set(
[
v.group("variable")
for e in expression_pattern.finditer(data)
for v in variable_pattern.finditer(e.group("content"))
]
)
)
class RednerTemplate(models.Model):
_name = "redner.template"
_description = "Redner Template"
name = fields.Char(
string="Name",
required=True,
help="This is a name of template mjml redner",
)
body = fields.Text(
string="Template remote Id",
translate=True,
help="Code for the mjml redner template must be added here",
)
slug = fields.Char(string="Slug")
active = fields.Boolean(
string="Active",
default=True,
help=(
"If unchecked, it will allow you to hide the "
"template without removing it."
),
)
is_mjml = fields.Boolean(
string="Is MJML",
default=True,
help="set to false if your template doesn't contain MJML",
)
detected_keywords = fields.Text(
string="Keywords", readonly=True, compute="_compute_keywords"
)
language = fields.Selection(
string=_("Language"),
selection=[
("mustache", "mustache"),
("handlebar", "handlebar"),
("od+mustache", "od"),
],
default="mustache",
required=True,
help="templating language",
)
redner_id = fields.Char(string="Redner ID", readonly=True)
produces = fields.Selection(
selection=[
("text/mjml", "MJML"),
("text/html", "HTML"),
("application/vnd.oasis.opendocument.text", "OpenDocument Text"),
],
string="Produces",
default="text/mjml",
)
locale_id = fields.Many2one(
comodel_name="res.lang",
string="Locale",
help="Optional translation language (ISO code).",
)
template_data = fields.Binary("Libreoffice Template")
_redner = None
@property
def redner(self):
"""Try to avoid Redner instance to be over created"""
if self._redner is None:
# Bypass security rules when reading these configuration params. By
# default, only some administrators have access to that model.
config_model = self.env["ir.config_parameter"].sudo()
self._redner = Redner(
config_model.get_param("redner.api_key"),
config_model.get_param("redner.server_url"),
config_model.get_param("redner.account"),
)
return self._redner
@api.model
def create(self, vals):
"""Overwrite create to create redner template"""
# Prepare template params according to the selected language.
# Use template data field if the selected language is "od";
# otherwise the body field is used.
if vals.get("language") == "od+mustache":
body = (
vals.get("template_data")
)
body_format = "base64"
else:
body = (
vals.get("body")
)
body_format = "text"
# We depend on the API for consistency here
# So raised error should not result with a created template
vals["redner_id"] = self.redner.templates.account_template_add(
vals.get("language"),
body,
vals.get("name"),
produces=vals.get("produces"),
body_format=body_format,
version=fields.Date.to_string(fields.Datetime.now()),
)
return super(RednerTemplate, self).create(vals)
def write(self, vals):
"""Overwrite write to update redner template"""
# Similar to the "send_to_rednerd_server" method; not worth factoring
# out.
# We depend on the API for consistency here
# So raised error should not result with an updated template
if "name" in vals:
self.ensure_one()
redner_id = self.redner_id
vals["redner_id"] = vals["name"]
ret = super(RednerTemplate, self).write(vals)
for record in self:
try:
body, body_format = (
(record.template_data.decode("utf8"), "base64")
if record.language == "od+mustache"
else (record.body, "text")
)
if "name" not in vals:
redner_id = record.redner_id
record.redner.templates.account_template_update(
redner_id,
vals.get("language", record.language),
body,
name=vals.get("name", ""),
produces=vals.get("produces", record.produces),
version=record.write_date,
)
except Exception as e:
logger.error("Failed to update redner template :%s" % e)
raise ValidationError(
_("Failed to update render template, %s" % e)
)
return ret
def unlink(self):
"""Overwrite unlink to delete redner template"""
# We do NOT depend on the API for consistency here
# So raised error should not result block template deletion
try:
self.redner.templates.account_template_delete(self.redner_id)
except Exception:
pass
return super(RednerTemplate, self).unlink()
def copy(self, default=None):
self.ensure_one()
default = dict(default or {}, name=_("%s (copy)") % self.name)
return super(RednerTemplate, self).copy(default)
@api.depends("body")
def _compute_keywords(self):
for record in self:
record.detected_keywords = get_redner_tmpl_keys(record.body)
@api.model
def get_keywords(self):
"""Return mjml redner keywords"""
return get_redner_tmpl_keys(self.body)
def send_to_rednerd_server(self):
"""Send templates to the rednerd server. Useful when you have
existing templates you want to register onto a new rednerd server (or
with a new user).
"""
for record in self:
# Similar to the "write" method override; not worth factoring out.
templates = record.redner.templates
body, body_format = (
(record.template_data.decode("utf8"), "base64")
if record.language == "od+mustache"
else (record.body, "text")
)
try:
templates.account_template_update(
record.redner_id,
record.language,
body,
record.name,
produces=record.produces,
body_format=body_format,
version=fields.Date.to_string(record.write_date),
)
except ValidationError:
record.redner_id = templates.account_template_add(
record.language,
body,
record.name,
produces=record.produces,
body_format=body_format,
version=fields.Date.to_string(fields.Datetime.now()),
)