diff --git a/addons/mail/static/src/components/message/message.xml b/addons/mail/static/src/components/message/message.xml index 02a0c49e20c..d248c422550 100644 --- a/addons/mail/static/src/components/message/message.xml +++ b/addons/mail/static/src/components/message/message.xml @@ -156,7 +156,7 @@
- +

diff --git a/addons/mail/static/src/components/message/message_tests.js b/addons/mail/static/src/components/message/message_tests.js index 8e2669a8698..7f10771ce0d 100644 --- a/addons/mail/static/src/components/message/message_tests.js +++ b/addons/mail/static/src/components/message/message_tests.js @@ -108,7 +108,8 @@ QUnit.test('basic rendering', async function (assert) { 1, "message should display the content" ); - assert.strictEqual(messageEl.querySelector(`:scope .o_Message_content`).innerHTML, + assert.strictEqual( + messageEl.querySelector(`:scope .o_Message_content`).innerHTML, "

Test

", "message should display the correct content" ); @@ -738,6 +739,50 @@ QUnit.test('prevent attachment delete on non-authored message', async function ( ); }); +QUnit.test('subtype description should be displayed if it is different than body', async function (assert) { + assert.expect(2); + + await this.start(); + const message = this.env.models['mail.message'].create({ + body: "

Hello

", + id: 100, + subtype_description: 'Bonjour', + }); + await this.createMessageComponent(message); + assert.containsOnce( + document.body, + '.o_Message_content', + "message should have content" + ); + assert.strictEqual( + document.querySelector(`.o_Message_content`).textContent, + "HelloBonjour", + "message content should display both body and subtype description when they are different" + ); +}); + +QUnit.test('subtype description should not be displayed if it is similar to body', async function (assert) { + assert.expect(2); + + await this.start(); + const message = this.env.models['mail.message'].create({ + body: "

Hello

", + id: 100, + subtype_description: 'hello', + }); + await this.createMessageComponent(message); + assert.containsOnce( + document.body, + '.o_Message_content', + "message should have content" + ); + assert.strictEqual( + document.querySelector(`.o_Message_content`).textContent, + "Hello", + "message content should display only body when subtype description is similar" + ); +}); + }); }); }); diff --git a/addons/mail/static/src/models/message/message.js b/addons/mail/static/src/models/message/message.js index e982df36667..c92714fb3e8 100644 --- a/addons/mail/static/src/models/message/message.js +++ b/addons/mail/static/src/models/message/message.js @@ -4,7 +4,7 @@ odoo.define('mail/static/src/models/message/message.js', function (require) { const emojis = require('mail.emojis'); const { registerNewModel } = require('mail/static/src/model/model_core.js'); const { attr, many2many, many2one, one2many } = require('mail/static/src/model/model_field.js'); -const { addLink, parseAndTransform } = require('mail.utils'); +const { addLink, htmlToTextContentInline, parseAndTransform } = require('mail.utils'); const { str_to_datetime } = require('web.time'); @@ -349,6 +349,18 @@ function factory(dependencies) { ); } + /** + * @private + * @returns {boolean} + */ + _computeIsBodyEqualSubtypeDescription() { + if (!this.body || !this.subtype_description) { + return false; + } + const inlineBody = htmlToTextContentInline(this.body); + return inlineBody.toLowerCase() === this.subtype_description.toLowerCase(); + } + /** * @private * @returns {boolean} @@ -480,6 +492,34 @@ function factory(dependencies) { 'messagingCurrentPartner', ], }), + /** + * States whether `body` and `subtype_description` contain similar + * values. + * + * This is necessary to avoid displaying both of them together when they + * contain duplicate information. This will especially happen with + * messages that are posted automatically at the creation of a record + * (messages that serve as tracking messages). They do have hard-coded + * "record created" body while being assigned a subtype with a + * description that states the same information. + * + * Fixing newer messages is possible by not assigning them a duplicate + * body content, but the check here is still necessary to handle + * existing messages. + * + * Limitations: + * - A translated subtype description might not match a non-translatable + * body created by a user with a different language. + * - Their content might be mostly but not exactly the same. + */ + isBodyEqualSubtypeDescription: attr({ + compute: '_computeIsBodyEqualSubtypeDescription', + default: false, + dependencies: [ + 'body', + 'subtype_description', + ], + }), isModeratedByCurrentPartner: attr({ compute: '_computeIsModeratedByCurrentPartner', default: false,