mirror of https://github.com/OCA/social.git
Merge cd0331e886
into 4f9f322b53
commit
e6b20daffd
|
@ -31,6 +31,10 @@ Mail Message Reply
|
||||||
This addon allow to reply on messages from odoo directly. It is useful
|
This addon allow to reply on messages from odoo directly. It is useful
|
||||||
when replying to a message from a customer.
|
when replying to a message from a customer.
|
||||||
|
|
||||||
|
Additionally, it is possible to separate the reply body from the mail
|
||||||
|
body. This separation is only for the composer and the sent mail will
|
||||||
|
contain both parts.
|
||||||
|
|
||||||
**Table of contents**
|
**Table of contents**
|
||||||
|
|
||||||
.. contents::
|
.. contents::
|
||||||
|
@ -42,6 +46,12 @@ Usage
|
||||||
On the messages from threads, a reply button is shown. Once it has been
|
On the messages from threads, a reply button is shown. Once it has been
|
||||||
pressed, a composer with the reply is shown.
|
pressed, a composer with the reply is shown.
|
||||||
|
|
||||||
|
To activate the separation of the reply body add the system parameter
|
||||||
|
"mail_quoted_reply.separate_reply_body". After opening a composer with
|
||||||
|
the reply button the reply body will be shown below the mail body as
|
||||||
|
readonly. To write into the reply body uncheck "Reply Readonly". For
|
||||||
|
longer replies this can take some time.
|
||||||
|
|
||||||
Bug Tracker
|
Bug Tracker
|
||||||
===========
|
===========
|
||||||
|
|
||||||
|
@ -63,13 +73,13 @@ Authors
|
||||||
Contributors
|
Contributors
|
||||||
------------
|
------------
|
||||||
|
|
||||||
- Enric Tobella
|
- Enric Tobella
|
||||||
- Lois Rilo <lois.rilo@forgeflow.com>
|
- Lois Rilo <lois.rilo@forgeflow.com>
|
||||||
- Giuseppe Borruso <gborruso@dinamicheaziendali.it>
|
- Giuseppe Borruso <gborruso@dinamicheaziendali.it>
|
||||||
- Laurence Labusch <lala@labiso.de>
|
- Laurence Labusch <lala@labiso.de>
|
||||||
- Dani Forga
|
- Dani Forga
|
||||||
- Tris Doan <tridm@trobz.com>
|
- Tris Doan <tridm@trobz.com>
|
||||||
- Akim Juillerat <akim.juillerat@camptocamp.com>
|
- Akim Juillerat <akim.juillerat@camptocamp.com>
|
||||||
|
|
||||||
Other credits
|
Other credits
|
||||||
-------------
|
-------------
|
||||||
|
|
|
@ -10,7 +10,9 @@
|
||||||
"author": "Creu Blanca,Odoo Community Association (OCA)",
|
"author": "Creu Blanca,Odoo Community Association (OCA)",
|
||||||
"website": "https://github.com/OCA/social",
|
"website": "https://github.com/OCA/social",
|
||||||
"depends": ["mail"],
|
"depends": ["mail"],
|
||||||
"data": [],
|
"data": [
|
||||||
|
"views/mail_compose_message_views.xml",
|
||||||
|
],
|
||||||
"assets": {
|
"assets": {
|
||||||
"web.assets_backend": [
|
"web.assets_backend": [
|
||||||
"/mail_quoted_reply/static/src/*.js",
|
"/mail_quoted_reply/static/src/*.js",
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
from markupsafe import Markup
|
from markupsafe import Markup
|
||||||
|
|
||||||
from odoo import api, models, tools
|
from odoo import api, fields, models, tools
|
||||||
|
|
||||||
|
|
||||||
class MailComposeMessage(models.TransientModel):
|
class MailComposeMessage(models.TransientModel):
|
||||||
_inherit = "mail.compose.message"
|
_inherit = "mail.compose.message"
|
||||||
|
|
||||||
|
is_reply_readonly = fields.Boolean(default=True, string="Reply Readonly")
|
||||||
|
reply_body = fields.Html(default="", string="Reply body")
|
||||||
|
is_separate_body = fields.Boolean(compute="_compute_is_separate_body")
|
||||||
|
|
||||||
@api.depends("composition_mode", "model", "res_domain", "res_ids", "template_id")
|
@api.depends("composition_mode", "model", "res_domain", "res_ids", "template_id")
|
||||||
@api.depends_context("is_quoted_reply")
|
@api.depends_context("is_quoted_reply")
|
||||||
def _compute_body(self):
|
def _compute_body(self):
|
||||||
|
@ -13,10 +17,13 @@ class MailComposeMessage(models.TransientModel):
|
||||||
for composer in self:
|
for composer in self:
|
||||||
context = composer._context
|
context = composer._context
|
||||||
if context.get("is_quoted_reply"):
|
if context.get("is_quoted_reply"):
|
||||||
if composer.body:
|
if self.is_separate_body:
|
||||||
composer.body += Markup(context["quote_body"])
|
self.reply_body = context["quote_body"]
|
||||||
else:
|
else:
|
||||||
composer.body = Markup(context["quote_body"])
|
if self.body:
|
||||||
|
self.body += Markup(context["quote_body"])
|
||||||
|
else:
|
||||||
|
self.body = Markup(context["quote_body"])
|
||||||
return res
|
return res
|
||||||
|
|
||||||
@api.depends(
|
@api.depends(
|
||||||
|
@ -36,3 +43,29 @@ class MailComposeMessage(models.TransientModel):
|
||||||
if subj:
|
if subj:
|
||||||
composer.subject = tools.ustr(subj)
|
composer.subject = tools.ustr(subj)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
@api.onchange("is_reply_readonly")
|
||||||
|
def _onchange_is_reply_readonly(self):
|
||||||
|
if self.reply_body:
|
||||||
|
self.reply_body = Markup(self.reply_body)
|
||||||
|
|
||||||
|
@api.depends("reply_body")
|
||||||
|
def _compute_is_separate_body(self):
|
||||||
|
if self._context.get("is_quoted_reply", False):
|
||||||
|
parameter_string = (
|
||||||
|
self.env["ir.config_parameter"]
|
||||||
|
.sudo()
|
||||||
|
.get_param("mail_quoted_reply.separate_reply_body", "")
|
||||||
|
)
|
||||||
|
self.is_separate_body = parameter_string.lower() not in ["", "false", "0"]
|
||||||
|
else:
|
||||||
|
self.is_separate_body = False
|
||||||
|
|
||||||
|
def _prepare_mail_values(self, res_ids):
|
||||||
|
results = super()._prepare_mail_values(res_ids)
|
||||||
|
if self.is_separate_body and self.reply_body:
|
||||||
|
for res_id in res_ids:
|
||||||
|
values = results.get(res_id)
|
||||||
|
reply_body = Markup(self.reply_body)
|
||||||
|
values.update({"body": values.get("body") + reply_body})
|
||||||
|
return results
|
||||||
|
|
|
@ -1,2 +1,6 @@
|
||||||
This addon allow to reply on messages from odoo directly. It is useful
|
This addon allow to reply on messages from odoo directly. It is useful
|
||||||
when replying to a message from a customer.
|
when replying to a message from a customer.
|
||||||
|
|
||||||
|
Additionally, it is possible to separate the reply body from the mail
|
||||||
|
body. This separation is only for the composer and the sent mail will
|
||||||
|
contain both parts.
|
||||||
|
|
|
@ -1,2 +1,6 @@
|
||||||
On the messages from threads, a reply button is shown. Once it has been
|
On the messages from threads, a reply button is shown. Once it has been
|
||||||
pressed, a composer with the reply is shown.
|
pressed, a composer with the reply is shown.
|
||||||
|
|
||||||
|
To activate the separation of the reply body add the system parameter "mail_quoted_reply.separate_reply_body".
|
||||||
|
After opening a composer with the reply button the reply body will be shown below the mail body as readonly.
|
||||||
|
To write into the reply body uncheck "Reply Readonly". For longer replies this can take some time.
|
||||||
|
|
|
@ -372,6 +372,9 @@ ul.auto-toc {
|
||||||
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/social/tree/17.0/mail_quoted_reply"><img alt="OCA/social" src="https://img.shields.io/badge/github-OCA%2Fsocial-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/social-17-0/social-17-0-mail_quoted_reply"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/social&target_branch=17.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
|
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/social/tree/17.0/mail_quoted_reply"><img alt="OCA/social" src="https://img.shields.io/badge/github-OCA%2Fsocial-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/social-17-0/social-17-0-mail_quoted_reply"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/social&target_branch=17.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
|
||||||
<p>This addon allow to reply on messages from odoo directly. It is useful
|
<p>This addon allow to reply on messages from odoo directly. It is useful
|
||||||
when replying to a message from a customer.</p>
|
when replying to a message from a customer.</p>
|
||||||
|
<p>Additionally, it is possible to separate the reply body from the mail
|
||||||
|
body. This separation is only for the composer and the sent mail will
|
||||||
|
contain both parts.</p>
|
||||||
<p><strong>Table of contents</strong></p>
|
<p><strong>Table of contents</strong></p>
|
||||||
<div class="contents local topic" id="contents">
|
<div class="contents local topic" id="contents">
|
||||||
<ul class="simple">
|
<ul class="simple">
|
||||||
|
@ -390,6 +393,11 @@ when replying to a message from a customer.</p>
|
||||||
<h1><a class="toc-backref" href="#toc-entry-1">Usage</a></h1>
|
<h1><a class="toc-backref" href="#toc-entry-1">Usage</a></h1>
|
||||||
<p>On the messages from threads, a reply button is shown. Once it has been
|
<p>On the messages from threads, a reply button is shown. Once it has been
|
||||||
pressed, a composer with the reply is shown.</p>
|
pressed, a composer with the reply is shown.</p>
|
||||||
|
<p>To activate the separation of the reply body add the system parameter
|
||||||
|
“mail_quoted_reply.separate_reply_body”. After opening a composer with
|
||||||
|
the reply button the reply body will be shown below the mail body as
|
||||||
|
readonly. To write into the reply body uncheck “Reply Readonly”. For
|
||||||
|
longer replies this can take some time.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="bug-tracker">
|
<div class="section" id="bug-tracker">
|
||||||
<h1><a class="toc-backref" href="#toc-entry-2">Bug Tracker</a></h1>
|
<h1><a class="toc-backref" href="#toc-entry-2">Bug Tracker</a></h1>
|
||||||
|
|
|
@ -44,3 +44,32 @@ class TestMessageReply(TransactionCase):
|
||||||
)
|
)
|
||||||
self.assertTrue(new_message)
|
self.assertTrue(new_message)
|
||||||
self.assertEqual(1, len(new_message))
|
self.assertEqual(1, len(new_message))
|
||||||
|
|
||||||
|
def test_reply_separate_body(self):
|
||||||
|
self.env["ir.config_parameter"].sudo().create(
|
||||||
|
{
|
||||||
|
"key": "mail_quoted_reply.separate_reply_body",
|
||||||
|
"value": "True",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
partner = self.env["res.partner"].create({"name": "demo partner"})
|
||||||
|
message = partner.message_post(
|
||||||
|
body="demo message",
|
||||||
|
message_type="email",
|
||||||
|
partner_ids=self.env.ref("base.partner_demo").ids,
|
||||||
|
)
|
||||||
|
partner.invalidate_recordset()
|
||||||
|
action = message.reply_message()
|
||||||
|
wizard = (
|
||||||
|
self.env[action["res_model"]].with_context(**action["context"]).create({})
|
||||||
|
)
|
||||||
|
wizard._compute_body()
|
||||||
|
self.assertTrue("<p>demo message</p>" in wizard.reply_body)
|
||||||
|
wizard.action_send_mail()
|
||||||
|
new_message = partner.message_ids.filtered(
|
||||||
|
lambda r: r.message_type != "notification" and r != message
|
||||||
|
)
|
||||||
|
self.assertTrue(new_message)
|
||||||
|
self.assertEqual(1, len(new_message))
|
||||||
|
new_message = new_message[0]
|
||||||
|
self.assertTrue("<p>demo message</p>" in new_message.body)
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<odoo>
|
||||||
|
<record id="mail_quoted_reply_composer_view_form" model="ir.ui.view">
|
||||||
|
<field name="model">mail.compose.message</field>
|
||||||
|
<field name="inherit_id" ref="mail.email_compose_message_wizard_form" />
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//field[@name='body']" position="after">
|
||||||
|
<field name="is_separate_body" invisible="1" />
|
||||||
|
<field
|
||||||
|
name="reply_body"
|
||||||
|
readonly="is_reply_readonly"
|
||||||
|
invisible="not is_separate_body"
|
||||||
|
force_save="1"
|
||||||
|
/>
|
||||||
|
<label for="is_reply_readonly" invisible="not is_separate_body" />
|
||||||
|
<field
|
||||||
|
name="is_reply_readonly"
|
||||||
|
widget="boolean_toggle"
|
||||||
|
invisible="not is_separate_body"
|
||||||
|
/>
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
</odoo>
|
Loading…
Reference in New Issue