[IMP] email.template: review/adapt form to 7.0-style + continue refactoring polishing
bzr revid: odo@openerp.com-20120901010907-703t6vx6n99tnyzq
This commit is contained in:
parent
761864c11c
commit
9d16f324e9
|
@ -29,7 +29,7 @@ from osv import fields
|
||||||
import tools
|
import tools
|
||||||
from tools.translate import _
|
from tools.translate import _
|
||||||
from tools.html_sanitize import html_sanitize
|
from tools.html_sanitize import html_sanitize
|
||||||
from tools import html2plaintext, append_content_to_html
|
from tools import append_content_to_html
|
||||||
from urllib import quote as quote
|
from urllib import quote as quote
|
||||||
_logger = logging.getLogger(__name__)
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -42,7 +42,6 @@ class email_template(osv.osv):
|
||||||
"Templates for sending email"
|
"Templates for sending email"
|
||||||
_name = "email.template"
|
_name = "email.template"
|
||||||
_description = 'Email Templates'
|
_description = 'Email Templates'
|
||||||
_rec_name = 'name' # override mail.message's behavior
|
|
||||||
|
|
||||||
def render_template(self, cr, uid, template, model, res_id, context=None):
|
def render_template(self, cr, uid, template, model, res_id, context=None):
|
||||||
"""Render the given template text, replace mako expressions ``${expr}``
|
"""Render the given template text, replace mako expressions ``${expr}``
|
||||||
|
@ -102,55 +101,44 @@ class email_template(osv.osv):
|
||||||
mod_name = self.pool.get('ir.model').browse(cr, uid, model_id, context).model
|
mod_name = self.pool.get('ir.model').browse(cr, uid, model_id, context).model
|
||||||
return {'value':{'model': mod_name}}
|
return {'value':{'model': mod_name}}
|
||||||
|
|
||||||
def name_get(self, cr, uid, ids, context=None):
|
|
||||||
""" Override name_get of mail.message: return directly the template
|
|
||||||
name, and not the generated name from mail.message.common."""
|
|
||||||
return [(record.id, record.name) for record in self.browse(cr, uid, ids, context=context)]
|
|
||||||
|
|
||||||
_columns = {
|
_columns = {
|
||||||
'name': fields.char('Name', size=250),
|
'name': fields.char('Name'),
|
||||||
'model_id': fields.many2one('ir.model', 'Related document model'),
|
'model_id': fields.many2one('ir.model', 'Applies to', help="The kind of document with with this template can be used"),
|
||||||
'model': fields.related('model_id', 'model', type='char', string='Related Document Model',
|
'model': fields.related('model_id', 'model', type='char', string='Related Document Model',
|
||||||
size=128, select=True, store=True, readonly=True),
|
size=128, select=True, store=True, readonly=True),
|
||||||
'lang': fields.char('Language Selection', size=250,
|
'lang': fields.char('Language',
|
||||||
help="Optional translation language (ISO code) to select when sending out an email. "
|
help="Optional translation language (ISO code) to select when sending out an email. "
|
||||||
"If not set, the english version will be used. "
|
"If not set, the english version will be used. "
|
||||||
"This should usually be a placeholder expression "
|
"This should usually be a placeholder expression "
|
||||||
"that provides the appropriate language code, e.g. "
|
"that provides the appropriate language code, e.g. "
|
||||||
"${object.partner_id.lang.code}."),
|
"${object.partner_id.lang.code}.",
|
||||||
|
placeholder="${object.partner_id.lang.code}"),
|
||||||
'user_signature': fields.boolean('Add Signature',
|
'user_signature': fields.boolean('Add Signature',
|
||||||
help="If checked, the user's signature will be appended to the text version "
|
help="If checked, the user's signature will be appended to the text version "
|
||||||
"of the message"),
|
"of the message"),
|
||||||
'report_name': fields.char('Report Filename', size=200, translate=True,
|
|
||||||
help="Name to use for the generated report file (may contain placeholders)\n"
|
|
||||||
"The extension can be omitted and will then come from the report type."),
|
|
||||||
'report_template':fields.many2one('ir.actions.report.xml', 'Optional report to print and attach'),
|
|
||||||
'ref_ir_act_window':fields.many2one('ir.actions.act_window', 'Sidebar action', readonly=True,
|
|
||||||
help="Sidebar action to make this template available on records "
|
|
||||||
"of the related document model"),
|
|
||||||
'ref_ir_value':fields.many2one('ir.values', 'Sidebar Button', readonly=True,
|
|
||||||
help="Sidebar button to open the sidebar action"),
|
|
||||||
'track_campaign_item': fields.boolean('Resource Tracking',
|
|
||||||
help="Enable this is you wish to include a special tracking marker "
|
|
||||||
"in outgoing emails so you can identify replies and link "
|
|
||||||
"them back to the corresponding resource record. "
|
|
||||||
"This is useful for CRM leads for example"),
|
|
||||||
# we need a separate m2m table to avoid ID collisions with the original mail.message entries
|
|
||||||
'attachment_ids': fields.many2many('ir.attachment', 'email_template_attachment_rel', 'email_template_id',
|
|
||||||
'attachment_id', 'Files to attach',
|
|
||||||
help="You may attach files to this template, to be added to all "
|
|
||||||
"emails created from this template"),
|
|
||||||
'auto_delete': fields.boolean('Auto Delete', help="Permanently delete this email after sending it, to save space"),
|
|
||||||
# Overridden mail.message.common fields to make tooltips more appropriate:
|
|
||||||
'subject': fields.char('Subject', translate=True, help="Subject (placeholders may be used here)",),
|
'subject': fields.char('Subject', translate=True, help="Subject (placeholders may be used here)",),
|
||||||
'email_from': fields.char('From', size=128, help="Sender address (placeholders may be used here)"),
|
'email_from': fields.char('From', help="Sender address (placeholders may be used here)"),
|
||||||
'email_to': fields.char('To', size=256, help="Comma-separated recipient addresses (placeholders may be used here)"),
|
'email_to': fields.char('To', help="Comma-separated recipient addresses (placeholders may be used here)"),
|
||||||
'email_cc': fields.char('Cc', size=256, help="Carbon copy recipients (placeholders may be used here)"),
|
'email_cc': fields.char('Cc', help="Carbon copy recipients (placeholders may be used here)"),
|
||||||
'reply_to': fields.char('Reply-To', size=250, help="Preferred response address (placeholders may be used here)"),
|
'reply_to': fields.char('Reply-To', help="Preferred response address (placeholders may be used here)"),
|
||||||
'mail_server_id': fields.many2one('ir.mail_server', 'Outgoing Mail Server', readonly=False,
|
'mail_server_id': fields.many2one('ir.mail_server', 'Outgoing Mail Server', readonly=False,
|
||||||
help="Optional preferred server for outgoing mails. If not set, the highest "
|
help="Optional preferred server for outgoing mails. If not set, the highest "
|
||||||
"priority one will be used."),
|
"priority one will be used."),
|
||||||
'body_html': fields.text('Rich-text Contents', translate=True, help="Rich-text/HTML version of the message (placeholders may be used here)"),
|
'body_html': fields.text('Body', translate=True, help="Rich-text/HTML version of the message (placeholders may be used here)"),
|
||||||
|
'report_name': fields.char('Report Filename', translate=True,
|
||||||
|
help="Name to use for the generated report file (may contain placeholders)\n"
|
||||||
|
"The extension can be omitted and will then come from the report type."),
|
||||||
|
'report_template': fields.many2one('ir.actions.report.xml', 'Optional report to print and attach'),
|
||||||
|
'ref_ir_act_window': fields.many2one('ir.actions.act_window', 'Sidebar action', readonly=True,
|
||||||
|
help="Sidebar action to make this template available on records "
|
||||||
|
"of the related document model"),
|
||||||
|
'ref_ir_value': fields.many2one('ir.values', 'Sidebar Button', readonly=True,
|
||||||
|
help="Sidebar button to open the sidebar action"),
|
||||||
|
'attachment_ids': fields.many2many('ir.attachment', 'email_template_attachment_rel', 'email_template_id',
|
||||||
|
'attachment_id', 'Attachments',
|
||||||
|
help="You may attach files to this template, to be added to all "
|
||||||
|
"emails created from this template"),
|
||||||
|
'auto_delete': fields.boolean('Auto Delete', help="Permanently delete this email after sending it, to save space"),
|
||||||
|
|
||||||
# Fake fields used to implement the placeholder assistant
|
# Fake fields used to implement the placeholder assistant
|
||||||
'model_object_field': fields.many2one('ir.model.fields', string="Field",
|
'model_object_field': fields.many2one('ir.model.fields', string="Field",
|
||||||
|
@ -164,12 +152,8 @@ class email_template(osv.osv):
|
||||||
help="When a relationship field is selected as first field, "
|
help="When a relationship field is selected as first field, "
|
||||||
"this field lets you select the target field within the "
|
"this field lets you select the target field within the "
|
||||||
"destination document model (sub-model)."),
|
"destination document model (sub-model)."),
|
||||||
'null_value': fields.char('Null value', help="Optional value to use if the target field is empty", size=128),
|
'null_value': fields.char('Default Value', help="Optional value to use if the target field is empty"),
|
||||||
'copyvalue': fields.char('Expression', size=256, help="Final placeholder expression, to be copy-pasted in the desired template field."),
|
'copyvalue': fields.char('Placeholder Expression', help="Final placeholder expression, to be copy-pasted in the desired template field."),
|
||||||
}
|
|
||||||
|
|
||||||
_defaults = {
|
|
||||||
'track_campaign_item': True
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def create_action(self, cr, uid, ids, context=None):
|
def create_action(self, cr, uid, ids, context=None):
|
||||||
|
@ -214,7 +198,7 @@ class email_template(osv.osv):
|
||||||
if template.ref_ir_value:
|
if template.ref_ir_value:
|
||||||
ir_values_obj = self.pool.get('ir.values')
|
ir_values_obj = self.pool.get('ir.values')
|
||||||
ir_values_obj.unlink(cr, uid, template.ref_ir_value.id, context)
|
ir_values_obj.unlink(cr, uid, template.ref_ir_value.id, context)
|
||||||
except:
|
except Exception:
|
||||||
raise osv.except_osv(_("Warning"), _("Deletion of the action record failed."))
|
raise osv.except_osv(_("Warning"), _("Deletion of the action record failed."))
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
|
@ -1,94 +1,67 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<openerp>
|
<openerp>
|
||||||
<data>
|
<data>
|
||||||
|
|
||||||
<record model="ir.ui.view" id="email_template_form">
|
<record model="ir.ui.view" id="email_template_form">
|
||||||
<field name="name">email.template.form</field>
|
<field name="name">email.template.form</field>
|
||||||
<field name="model">email.template</field>
|
<field name="model">email.template</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<form string="Templates" version="7.0">
|
<form string="Templates" version="7.0">
|
||||||
<sheet>
|
<sheet>
|
||||||
<group col="4">
|
<div class="oe_title">
|
||||||
<field name="name" required="1"/>
|
<label for="name" class="oe_edit_only"/><h1><field name="name" required="1"/></h1>
|
||||||
<field name="model_id" required="1" on_change="onchange_model_id(model_id)"/>
|
<h3><label for="model_id"/><field name="model_id" required="1" on_change="onchange_model_id(model_id)" class="oe_inline"/></h3>
|
||||||
<field name="model" invisible="1"/>
|
<field name="model" invisible="1"/>
|
||||||
</group>
|
</div>
|
||||||
<notebook>
|
<div class="oe_right oe_button_box" name="buttons">
|
||||||
<page string="Email Details">
|
<field name="ref_ir_act_window" invisible="1"/>
|
||||||
<group>
|
<button name="create_action" string="Add context action" type="object"
|
||||||
<field name="email_from" required="1"/>
|
attrs="{'invisible':[('ref_ir_act_window','!=',False)]}"
|
||||||
<field name="email_to" required="1"/>
|
help="Display an option on related documents to open a composition wizard with this template"/>
|
||||||
<field name="email_cc"/>
|
<button name="unlink_action" string="Remove context action" type="object"
|
||||||
<field name="reply_to"/>
|
attrs="{'invisible':[('ref_ir_act_window','=',False)]}"
|
||||||
<field name="subject" required="1"/>
|
help="Remove the contextual action to use this template on related documents"/>
|
||||||
<notebook colspan="4">
|
<button name="%(wizard_email_template_preview)d" string="Preview"
|
||||||
<page string="Body (HTML)">
|
type="action" target="new"
|
||||||
<field name="body_html" colspan="4" width="250" height="250" nolabel="1"/>
|
context="{'template_id':active_id}"/>
|
||||||
<label string="Note: This is Raw HTML." colspan="4"/>
|
</div>
|
||||||
</page>
|
<notebook>
|
||||||
</notebook>
|
<page string="Email Details">
|
||||||
<field name="user_signature"/>
|
<group>
|
||||||
<notebook colspan="4">
|
<group string="Addressing">
|
||||||
<page string="Dynamic Values Builder">
|
<field name="email_from" required="1"/>
|
||||||
<group>
|
<field name="email_to" required="1"/>
|
||||||
<field name="model_object_field"
|
<field name="email_cc"/>
|
||||||
domain="[('model_id','=',model_id),('ttype','!=','one2many'),('ttype','!=','many2many')]"
|
<field name="reply_to"/>
|
||||||
on_change="onchange_sub_model_object_value_field(model_object_field)"/>
|
<field name="user_signature"/>
|
||||||
<field name="sub_object" readonly="1"/>
|
</group>
|
||||||
<field name="sub_model_object_field"
|
<group string="Dynamic Value Builder" class="oe_edit_only">
|
||||||
domain="[('model_id','=',sub_object),('ttype','!=','one2many'),('ttype','!=','many2many')]"
|
<field name="model_object_field" domain="[('model_id','=',model_id),('ttype','!=','one2many'),('ttype','!=','many2many')]" on_change="onchange_sub_model_object_value_field(model_object_field)"/>
|
||||||
attrs="{'readonly':[('sub_object','=',False)],'required':[('sub_object','!=',False)]}"
|
<field name="sub_object" readonly="1"/>
|
||||||
on_change="onchange_sub_model_object_value_field(model_object_field,sub_model_object_field)"/>
|
<field name="sub_model_object_field" domain="[('model_id','=',sub_object),('ttype','!=','one2many'),('ttype','!=','many2many')]" attrs="{'readonly':[('sub_object','=',False)],'required':[('sub_object','!=',False)]}" on_change="onchange_sub_model_object_value_field(model_object_field,sub_model_object_field)"/>
|
||||||
<field name="null_value" on_change="onchange_sub_model_object_value_field(model_object_field,sub_model_object_field,null_value)"/>
|
<field name="null_value" on_change="onchange_sub_model_object_value_field(model_object_field,sub_model_object_field,null_value)"/>
|
||||||
<field name="copyvalue"/>
|
<field name="copyvalue"/>
|
||||||
|
</group>
|
||||||
|
<group string="Contents" colspan="2">
|
||||||
|
<field name="subject" required="1"/>
|
||||||
|
<field name="body_html" width="250" height="450" nolabel="1" colspan="2" placeholder="Email contents (in raw HTML format)"/>
|
||||||
</group>
|
</group>
|
||||||
</page>
|
|
||||||
</notebook>
|
|
||||||
<button name="%(wizard_email_template_preview)d" string="Preview Template"
|
|
||||||
type="action" colspan="4" target="new" icon="gtk-zoom-fit" context="{'template_id':active_id}"/>
|
|
||||||
</group>
|
|
||||||
</page>
|
|
||||||
<page string="Advanced">
|
|
||||||
<group colspan="2" col="2">
|
|
||||||
<group colspan="2" col="2">
|
|
||||||
<separator string="Sidebar Button" colspan="2"/>
|
|
||||||
<button name="create_action" string="Add sidebar button" type="object" icon="gtk-execute"
|
|
||||||
colspan="2" attrs="{'invisible':[('ref_ir_act_window','!=',False)]}"
|
|
||||||
help="Display a button in the sidebar of related documents to open a composition wizard with this template"
|
|
||||||
/>
|
|
||||||
<field name="ref_ir_act_window" attrs="{'invisible':[('ref_ir_act_window','=',False)]}"/>
|
|
||||||
<field name="ref_ir_value" attrs="{'invisible':[('ref_ir_act_window','=',False)]}"/>
|
|
||||||
<button name="unlink_action" string="Remove sidebar button" type="object" icon="gtk-delete"
|
|
||||||
colspan="2" attrs="{'invisible':[('ref_ir_act_window','=',False)]}"
|
|
||||||
help="Remove the sidebar button currently displayed on related documents"
|
|
||||||
/>
|
|
||||||
</group>
|
</group>
|
||||||
<group colspan="2" col="2">
|
</page>
|
||||||
<separator string="Advanced Options" colspan="2"/>
|
<page string="Advanced">
|
||||||
<field name="mail_server_id"/>
|
<group>
|
||||||
<field name="track_campaign_item"/>
|
|
||||||
<field name="auto_delete"/>
|
|
||||||
<field name="lang"/>
|
<field name="lang"/>
|
||||||
|
<field name="mail_server_id"/>
|
||||||
|
<field name="auto_delete"/>
|
||||||
|
<field name="report_template" domain="[('model','=',model)]"/>
|
||||||
|
<field name="report_name" class="oe_inline"
|
||||||
|
attrs="{'invisible':[('report_template','=',False)]}"/>
|
||||||
|
<field name="attachment_ids">
|
||||||
|
<tree><field name="name"/></tree>
|
||||||
|
</field>
|
||||||
</group>
|
</group>
|
||||||
</group>
|
</page>
|
||||||
<group colspan="2" col="2">
|
</notebook>
|
||||||
<separator string="Attachments" colspan="2"/>
|
</sheet>
|
||||||
<notebook colspan="2">
|
|
||||||
<page string="Attach Report">
|
|
||||||
<group>
|
|
||||||
<field name="report_template" colspan="4"
|
|
||||||
domain="[('model','=',model)]"/>
|
|
||||||
<field name="report_name" colspan="4" />
|
|
||||||
</group>
|
|
||||||
</page>
|
|
||||||
<page string="Attach existing files">
|
|
||||||
<field name="attachment_ids" colspan="4" nolabel="1" height="350"/>
|
|
||||||
</page>
|
|
||||||
</notebook>
|
|
||||||
</group>
|
|
||||||
</page>
|
|
||||||
</notebook>
|
|
||||||
</sheet>
|
|
||||||
</form>
|
</form>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
@ -98,9 +71,9 @@
|
||||||
<field name="model">email.template</field>
|
<field name="model">email.template</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<tree string="Templates">
|
<tree string="Templates">
|
||||||
<field name="model_id"/>
|
|
||||||
<field name="mail_server_id" invisible="1"/>
|
<field name="mail_server_id" invisible="1"/>
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
|
<field name="model_id"/>
|
||||||
<field name="subject"/>
|
<field name="subject"/>
|
||||||
<field name="email_from"/>
|
<field name="email_from"/>
|
||||||
<field name="email_to"/>
|
<field name="email_to"/>
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||||
access_email_template,email.template,model_email_template,,1,0,0,0
|
access_email_template,email.template,model_email_template,,1,1,1,0
|
||||||
access_email_template_system,email.template system,model_email_template,base.group_system,1,1,1,1
|
access_email_template_system,email.template system,model_email_template,base.group_system,1,1,1,1
|
||||||
access_email_template_manager,email.template,model_email_template,,1,1,1,1
|
|
||||||
access_email_template_preview_system,email.template.preview system,model_email_template_preview,base.group_system,1,1,1,1
|
|
||||||
|
|
|
|
@ -65,29 +65,19 @@ class email_template_preview(osv.osv_memory):
|
||||||
return result
|
return result
|
||||||
|
|
||||||
_columns = {
|
_columns = {
|
||||||
'res_id':fields.selection(_get_records, 'Sample Document'),
|
'res_id': fields.selection(_get_records, 'Sample Document'),
|
||||||
}
|
}
|
||||||
|
|
||||||
def on_change_res_id(self, cr, uid, ids, res_id, context=None):
|
def on_change_res_id(self, cr, uid, ids, res_id, context=None):
|
||||||
if not res_id:
|
if not res_id: return {}
|
||||||
return {}
|
|
||||||
vals = {}
|
vals = {}
|
||||||
email_template = self.pool.get('email.template')
|
email_template = self.pool.get('email.template')
|
||||||
template_id = context and context.get('template_id')
|
template_id = context and context.get('template_id')
|
||||||
|
template = email_template.browse(cr, uid, template_id, context=context)
|
||||||
# FIXME ODO: replace everything below with a call to template.generate_email
|
vals['name'] = template.name
|
||||||
template = email_template.get_email_template(cr, uid, template_id=template_id, record_id=res_id, context=context)
|
mail_values = email_template.generate_email(cr, uid, template_id, res_id, context=context)
|
||||||
model = template.model
|
for k in ('email_from','email_to','email_cc','reply_to','subject','body_html'):
|
||||||
vals['email_to'] = self.render_template(cr, uid, template.email_to, model, res_id, context)
|
vals[k] = mail_values[k]
|
||||||
vals['email_cc'] = self.render_template(cr, uid, template.email_cc, model, res_id, context)
|
|
||||||
vals['reply_to'] = self.render_template(cr, uid, template.reply_to, model, res_id, context)
|
|
||||||
vals['subject'] = self.render_template(cr, uid, template.subject, model, res_id, context)
|
|
||||||
description = self.render_template(cr, uid, template.body_html, model, res_id, context) or ''
|
|
||||||
if template.user_signature:
|
|
||||||
signature = self.pool.get('res.users').browse(cr, uid, uid, context).signature
|
|
||||||
description += '\n' + signature
|
|
||||||
vals['body_html'] = description
|
|
||||||
vals['report_name'] = self.render_template(cr, uid, template.report_name, model, res_id, context)
|
|
||||||
return {'value': vals}
|
return {'value': vals}
|
||||||
|
|
||||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||||
|
|
|
@ -7,15 +7,20 @@
|
||||||
<field name="model">email_template.preview</field>
|
<field name="model">email_template.preview</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<form string="Email Preview" version="7.0">
|
<form string="Email Preview" version="7.0">
|
||||||
<group>
|
<div>
|
||||||
|
<h2>Preview of <field name="name" readonly="1" class="oe_inline"/></h2>
|
||||||
<field name="model_id" invisible="1"/>
|
<field name="model_id" invisible="1"/>
|
||||||
<field name="res_id" on_change="on_change_res_id(res_id, context)"/>
|
<h3>Using sample document
|
||||||
<field name="email_to" readonly="1"/>
|
<field name="res_id" on_change="on_change_res_id(res_id, context)" class="oe_inline"/>
|
||||||
<field name="email_cc" readonly="1" attrs="{'invisible': [('email_cc','=',False)]}"/>
|
</h3>
|
||||||
<field name="reply_to" readonly="1" attrs="{'invisible': [('reply_to','=',False)]}"/>
|
</div>
|
||||||
<field name="subject" readonly="1"/>
|
<group>
|
||||||
<field name="body_html" nolabel="1" colspan="4" height="350" width="350" readonly="1" widget="html"/>
|
<field name="email_from" readonly="1"/>
|
||||||
<field name="report_name" colspan="4" readonly="1"/>
|
<field name="email_to" readonly="1"/>
|
||||||
|
<field name="email_cc" readonly="1" attrs="{'invisible':[('email_cc','=',False)]}"/>
|
||||||
|
<field name="reply_to" readonly="1" attrs="{'invisible':[('reply_to','=',False)]}"/>
|
||||||
|
<field name="subject" readonly="1"/>
|
||||||
|
<field name="body_html" widget="html" readonly="1"/>
|
||||||
</group>
|
</group>
|
||||||
</form>
|
</form>
|
||||||
</field>
|
</field>
|
||||||
|
|
Loading…
Reference in New Issue