Compare commits
1 Commits
12.0-mig-m
...
12.0-remov
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3f06231c22 |
@@ -1,19 +0,0 @@
|
|||||||
# Mail Usability
|
|
||||||
|
|
||||||
Take back the control on your email
|
|
||||||
|
|
||||||
## Feature
|
|
||||||
|
|
||||||
- do not follow automatically a object when sending an email
|
|
||||||
- better email preview, allow to select between the whole database object and not only the last 10
|
|
||||||
- use a light template version for notification without link (link should be explicit)
|
|
||||||
- add some additional style in the white list when santizing html field (see tools.py)
|
|
||||||
- make the email template by default not 'auto_delete'
|
|
||||||
|
|
||||||
## TIPS
|
|
||||||
|
|
||||||
Never, never tick the 'auto_delete' on mail template because it fucking hard to debug
|
|
||||||
and understand what have been sent (we should create a module with a crontask, that drop them latter)
|
|
||||||
|
|
||||||
If the template of mail do not look like the same when saving it in odoo, maybe the sanitize style have drop some balise
|
|
||||||
please run odoo with "LOG_STYLE_SANITIZE=True odoo" to understand what have been drop, magic warning logger will tell you everthing
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
from . import models
|
|
||||||
from . import wizard
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
# Copyright 2020 Akretion France (http://www.akretion.com)
|
|
||||||
# @author Benoît Guillot <benoit.guillot@akretion.com>
|
|
||||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
|
||||||
|
|
||||||
{
|
|
||||||
'name': 'Mail Usability',
|
|
||||||
'version': '12.0.1.0.0',
|
|
||||||
'category': 'Base',
|
|
||||||
'license': 'AGPL-3',
|
|
||||||
'summary': 'Usability improvements on mails',
|
|
||||||
'description': """
|
|
||||||
Mail Usability
|
|
||||||
==============
|
|
||||||
|
|
||||||
Small usability improvements on mails:
|
|
||||||
|
|
||||||
* remove link in mail footer
|
|
||||||
|
|
||||||
* remove 'sent by' in notification footer
|
|
||||||
|
|
||||||
* add a new entry *All Messages Except Notifications* to the field *Receive Inbox Notifications by Email* of partners (becomes the default value)
|
|
||||||
""",
|
|
||||||
'author': 'Akretion',
|
|
||||||
'website': 'http://www.akretion.com',
|
|
||||||
'depends': ['mail'],
|
|
||||||
'data': [
|
|
||||||
'views/mail_view.xml',
|
|
||||||
'data/mail_data.xml',
|
|
||||||
'wizard/email_template_preview_view.xml',
|
|
||||||
],
|
|
||||||
'installable': True,
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<odoo noupdate="1">
|
|
||||||
|
|
||||||
<!--Default Notification Email template -->
|
|
||||||
<record id="mail_template_notification" model="mail.template">
|
|
||||||
<field name="name">Notification Email</field>
|
|
||||||
<field name="subject">${object.subject}</field>
|
|
||||||
<field name="model_id" ref="mail.model_mail_message"/>
|
|
||||||
<field name="auto_delete" eval="True"/>
|
|
||||||
<field name="body_html">${object.body | safe}</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<template id="message_notification_email_usability">
|
|
||||||
<div t-raw="message.body"/>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
|
|
||||||
</odoo>
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
from . import mail
|
|
||||||
from . import tools
|
|
||||||
from . import mail_template
|
|
||||||
from . import mail_message
|
|
||||||
from . import res_partner
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
# Copyright 2016-2017 Akretion France (http://www.akretion.com)
|
|
||||||
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
|
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
|
||||||
|
|
||||||
|
|
||||||
from odoo import models, api
|
|
||||||
import logging
|
|
||||||
_logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class MailThread(models.AbstractModel):
|
|
||||||
_inherit = 'mail.thread'
|
|
||||||
|
|
||||||
def _active_message_auto_subscribe_notify(self):
|
|
||||||
_logger.debug('Skip automatic subscribe notification')
|
|
||||||
return False
|
|
||||||
|
|
||||||
def _message_auto_subscribe_notify(self, partner_ids, template):
|
|
||||||
if self._active_message_auto_subscribe_notify():
|
|
||||||
return super(MailThread, self)._message_auto_subscribe_notify(
|
|
||||||
partner_ids, template)
|
|
||||||
else:
|
|
||||||
return True
|
|
||||||
|
|
||||||
@api.multi
|
|
||||||
@api.returns('self', lambda value: value.id)
|
|
||||||
def message_post(self, body='', subject=None, message_type='notification',
|
|
||||||
subtype=None, parent_id=False, attachments=None,
|
|
||||||
content_subtype='html', **kwargs):
|
|
||||||
if not 'mail_create_nosubscribe' in self._context:
|
|
||||||
# Do not implicitly follow an object by just sending a message
|
|
||||||
self = self.with_context(mail_create_nosubscribe=True)
|
|
||||||
return super(MailThread, self).message_post(
|
|
||||||
body=body, subject=subject, message_type=message_type,
|
|
||||||
subtype=subtype, parent_id=parent_id, attachments=attachments,
|
|
||||||
content_subtype=content_subtype, **kwargs)
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
# Copyright 2019 Akretion France (http://www.akretion.com)
|
|
||||||
# @author Sébastien BEAU <sebastien.beau@akretion.com>
|
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
|
||||||
|
|
||||||
from odoo import models
|
|
||||||
|
|
||||||
|
|
||||||
class MailMessage(models.Model):
|
|
||||||
_inherit = 'mail.message'
|
|
||||||
|
|
||||||
@property
|
|
||||||
def record_id(self):
|
|
||||||
# we do not use a reference field here as mail message
|
|
||||||
# are used everywhere and many model are not yet loaded
|
|
||||||
# so odoo raise exception
|
|
||||||
if self:
|
|
||||||
self.ensure_one()
|
|
||||||
return self.env[self.model].browse(self.res_id)
|
|
||||||
return None
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
# Copyright 2018 Akretion France (http://www.akretion.com)
|
|
||||||
# @author Sébastien BEAU <sebastien.beau@akretion.com>
|
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
|
||||||
|
|
||||||
from openerp import fields, models
|
|
||||||
|
|
||||||
|
|
||||||
class MailTemplate(models.Model):
|
|
||||||
_inherit = 'mail.template'
|
|
||||||
|
|
||||||
auto_delete = fields.Boolean(default=False)
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
# Copyright 2016-2019 Akretion France (http://www.akretion.com)
|
|
||||||
# @author Sébastien BEAU <sebastien.beau@akretion.com>
|
|
||||||
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
|
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
|
||||||
|
|
||||||
from odoo import models, fields, api
|
|
||||||
|
|
||||||
|
|
||||||
class ResPartner(models.Model):
|
|
||||||
_inherit = 'res.partner'
|
|
||||||
|
|
||||||
opt_out = fields.Boolean(track_visibility='onchange')
|
|
||||||
|
|
||||||
@api.model
|
|
||||||
def _notify(self, message, rdata, record, force_send=False,
|
|
||||||
send_after_commit=True, model_description=False,
|
|
||||||
mail_auto_delete=True):
|
|
||||||
# use an empty layout for notification by default
|
|
||||||
if not message.layout:
|
|
||||||
message.layout = 'mail_usability.message_notification_email_usability'
|
|
||||||
# Never auto delete notification email
|
|
||||||
# fucking to hard to debug when message have been delete
|
|
||||||
mail_auto_delete = False
|
|
||||||
return super(ResPartner, self)._notify(
|
|
||||||
message=message, rdata=rdata, record=record,
|
|
||||||
force_send=force_send, send_after_commit=send_after_commit,
|
|
||||||
model_description=model_description, mail_auto_delete=mail_auto_delete)
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
# Copyright 2018 Akretion France (http://www.akretion.com)
|
|
||||||
# @author Sébastien BEAU <sebastien.beau@akretion.com>
|
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
|
||||||
|
|
||||||
from odoo.tools.mail import _Cleaner
|
|
||||||
import os
|
|
||||||
import logging
|
|
||||||
_logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
_Cleaner._style_whitelist += [
|
|
||||||
'word-wrap',
|
|
||||||
'display'
|
|
||||||
'border-top',
|
|
||||||
'border-bottom',
|
|
||||||
'border-left',
|
|
||||||
'border-right',
|
|
||||||
'text-transform',
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
if os.getenv('LOG_STYLE_SANITIZE'):
|
|
||||||
# Monkey patch the parse style method to debug
|
|
||||||
# the missing style
|
|
||||||
def parse_style(self, el):
|
|
||||||
attributes = el.attrib
|
|
||||||
styling = attributes.get('style')
|
|
||||||
if styling:
|
|
||||||
valid_styles = {}
|
|
||||||
styles = self._style_re.findall(styling)
|
|
||||||
for style in styles:
|
|
||||||
if style[0].lower() in self._style_whitelist:
|
|
||||||
valid_styles[style[0].lower()] = style[1]
|
|
||||||
# START HACK
|
|
||||||
else:
|
|
||||||
_logger.warning('Remove style %s %s', *style)
|
|
||||||
# END HACK
|
|
||||||
if valid_styles:
|
|
||||||
el.attrib['style'] = '; '.join(
|
|
||||||
'%s:%s' % (key, val)
|
|
||||||
for (key, val) in valid_styles.iteritems())
|
|
||||||
else:
|
|
||||||
del el.attrib['style']
|
|
||||||
_Cleaner.parse_style = parse_style
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 9.5 KiB |
@@ -1,16 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<odoo>
|
|
||||||
|
|
||||||
<record id="view_mail_tree" model="ir.ui.view">
|
|
||||||
<field name="model">mail.mail</field>
|
|
||||||
<field name="inherit_id" ref="mail.view_mail_tree"/>
|
|
||||||
<field name="arch" type="xml">
|
|
||||||
<field name="email_from" position="replace"/>
|
|
||||||
<field name="date" position="after">
|
|
||||||
<field name="email_from"/>
|
|
||||||
<field name="email_to"/>
|
|
||||||
</field>
|
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
</odoo>
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
from . import email_template_preview
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
# Copyright 2019 Akretion France (http://www.akretion.com)
|
|
||||||
# @author Sébastien BEAU <sebastien.beau@akretion.com>
|
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
|
||||||
|
|
||||||
from openerp import api, fields, models
|
|
||||||
|
|
||||||
|
|
||||||
class TemplatePreview(models.TransientModel):
|
|
||||||
_inherit = "email_template.preview"
|
|
||||||
|
|
||||||
res_id = fields.Integer(compute='_compute_res_id')
|
|
||||||
object_id = fields.Reference(selection='_reference_models')
|
|
||||||
|
|
||||||
@api.model
|
|
||||||
def default_get(self, fields):
|
|
||||||
result = super(TemplatePreview, self).default_get(fields)
|
|
||||||
if result.get('model_id'):
|
|
||||||
model = self.env['ir.model'].browse(result['model_id'])
|
|
||||||
result['object_id'] = model.model
|
|
||||||
return result
|
|
||||||
|
|
||||||
def _reference_models(self):
|
|
||||||
result = self.default_get(['model_id'])
|
|
||||||
if result.get('model_id'):
|
|
||||||
model = self.env['ir.model'].browse(result['model_id'])
|
|
||||||
return [(model.model, model.name)]
|
|
||||||
else:
|
|
||||||
ir_models = self.env['ir.model'].search([('state', '!=', 'manual')])
|
|
||||||
return [(ir_model.model, ir_model.name)
|
|
||||||
for ir_model in ir_models
|
|
||||||
if not ir_model.model.startswith('ir.')]
|
|
||||||
|
|
||||||
@api.depends('object_id')
|
|
||||||
def _compute_res_id(self):
|
|
||||||
for record in self:
|
|
||||||
if self.object_id:
|
|
||||||
record.res_id = self.object_id.id
|
|
||||||
|
|
||||||
def send(self):
|
|
||||||
template = self.env['mail.template'].browse(
|
|
||||||
self._context['template_id'])
|
|
||||||
template.send_mail(
|
|
||||||
self.res_id, force_send=True, raise_exception=True)
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<odoo>
|
|
||||||
|
|
||||||
<record id="email_template_preview_form" model="ir.ui.view">
|
|
||||||
<field name="model">email_template.preview</field>
|
|
||||||
<field name="inherit_id" ref="mail.email_template_preview_form"/>
|
|
||||||
<field name="arch" type="xml">
|
|
||||||
<field name="res_id" position="attributes">
|
|
||||||
<attribute name="invisible">True</attribute>
|
|
||||||
</field>
|
|
||||||
<field name="res_id" position="after">
|
|
||||||
<field name="object_id"/>
|
|
||||||
</field>
|
|
||||||
<footer position="inside">
|
|
||||||
<button
|
|
||||||
string="Send"
|
|
||||||
name="send"
|
|
||||||
class="btn-primary"
|
|
||||||
type='object'/>
|
|
||||||
</footer>
|
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
</odoo>
|
|
||||||
@@ -16,11 +16,6 @@
|
|||||||
<field name="standard_price" class="oe_inline" position="after">
|
<field name="standard_price" class="oe_inline" position="after">
|
||||||
<button name="show_product_price_history" class="oe_inline oe_link" type="object" string="Show History" context="{'active_id': active_id}"/>
|
<button name="show_product_price_history" class="oe_inline oe_link" type="object" string="Show History" context="{'active_id': active_id}"/>
|
||||||
</field>
|
</field>
|
||||||
<!-- Don't make it too big, othesize computers with small resolutions
|
|
||||||
will see the product name + image under the block of buttons -->
|
|
||||||
<div class="oe_title" position="attributes">
|
|
||||||
<attribute name="style">width: 650px;</attribute>
|
|
||||||
</div>
|
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user