From ff209a8b36fca38e3eff210554d649959d9d3db9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Theys?= Date: Tue, 22 Sep 2020 16:30:09 +0000 Subject: [PATCH] [FIX] mail: allow to open record thread in chat window MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit task-2171885 closes odoo/odoo#58324 X-original-commit: af6e68c2c5bd819402af0126c87f375e096c8d0d Signed-off-by: Alexandre Kühn (aku) Signed-off-by: Sébastien Theys (seb) --- ...ification_list_notification_group_tests.js | 44 +++---- .../thread_needaction_preview.js | 1 + .../thread_needaction_preview_tests.js | 117 ++++++++++++++++++ .../mail/static/src/models/thread/thread.js | 16 ++- 4 files changed, 143 insertions(+), 35 deletions(-) diff --git a/addons/mail/static/src/components/notification_list/notification_list_notification_group_tests.js b/addons/mail/static/src/components/notification_list/notification_list_notification_group_tests.js index aa1d36593ad..223ce3637b0 100644 --- a/addons/mail/static/src/components/notification_list/notification_list_notification_group_tests.js +++ b/addons/mail/static/src/components/notification_list/notification_list_notification_group_tests.js @@ -171,7 +171,7 @@ QUnit.test('mark as read', async function (assert) { QUnit.test('grouped notifications by document', async function (assert) { // If some failures linked to a document refers to a same document, a single // notification should group all those failures. - assert.expect(9); + assert.expect(5); this.data['mail.message'].records.push( // first message that is expected to have a failure @@ -205,31 +205,7 @@ QUnit.test('grouped notifications by document', async function (assert) { notification_type: 'email', // expected failure type for email message } ); - const bus = new Bus(); - bus.on('do-action', null, payload => { - assert.step('do_action'); - assert.strictEqual( - payload.action.type, - 'ir.actions.act_window', - "action should have the type act_window" - ); - assert.strictEqual( - payload.action.res_model, - 'res.partner', - "action should have the group model as res_model" - ); - assert.strictEqual( - JSON.stringify(payload.action.views), - JSON.stringify([[false, 'form']]), - "action should have form view" - ); - assert.strictEqual( - payload.action.res_id, - 31, - "action should have the group res_id as res_id" - ); - }); - await this.start({ env: { bus } }); + await this.start({ hasChatWindow: true }); await this.createNotificationListComponent(); assert.containsOnce( @@ -247,11 +223,19 @@ QUnit.test('grouped notifications by document', async function (assert) { "(2)", "should have 2 notifications in the group" ); + assert.containsNone( + document.body, + '.o_ChatWindow', + "should have no chat window initially" + ); - document.querySelector('.o_NotificationGroup').click(); - assert.verifySteps( - ['do_action'], - "should do an action to display the related record" + await afterNextRender(() => + document.querySelector('.o_NotificationGroup').click() + ); + assert.containsOnce( + document.body, + '.o_ChatWindow', + "should have opened the thread in a chat window after clicking on it" ); }); diff --git a/addons/mail/static/src/components/thread_needaction_preview/thread_needaction_preview.js b/addons/mail/static/src/components/thread_needaction_preview/thread_needaction_preview.js index 24486cfc93c..2b6bede0909 100644 --- a/addons/mail/static/src/components/thread_needaction_preview/thread_needaction_preview.js +++ b/addons/mail/static/src/components/thread_needaction_preview/thread_needaction_preview.js @@ -105,6 +105,7 @@ class ThreadNeedactionPreview extends Component { // handled in `_onClickMarkAsRead` return; } + this.thread.markNeedactionMessagesAsRead(); this.thread.open(); if (!this.env.messaging.device.isMobile) { this.env.messaging.messagingMenu.close(); diff --git a/addons/mail/static/src/components/thread_needaction_preview/thread_needaction_preview_tests.js b/addons/mail/static/src/components/thread_needaction_preview/thread_needaction_preview_tests.js index 7f16eb68fb3..5c59a8f3d50 100644 --- a/addons/mail/static/src/components/thread_needaction_preview/thread_needaction_preview_tests.js +++ b/addons/mail/static/src/components/thread_needaction_preview/thread_needaction_preview_tests.js @@ -13,6 +13,8 @@ const { start, } = require('mail/static/src/utils/test_utils.js'); +const Bus = require('web.Bus'); + QUnit.module('mail', {}, function () { QUnit.module('components', {}, function () { QUnit.module('thread_needaction_preview', {}, function () { @@ -84,6 +86,121 @@ QUnit.test('mark as read', async function (assert) { ); }); +QUnit.test('click on preview should mark as read and open the thread', async function (assert) { + assert.expect(5); + + await this.start({ + hasChatWindow: true, + async mockRPC(route, args) { + if (route.includes('set_message_done')) { + assert.step('set_message_done'); + } + return this._super(...arguments); + }, + }); + const thread = this.env.models['mail.thread'].create({ + id: 11, + model: 'mail.channel', + }); + this.env.models['mail.message'].create({ + id: 21, + isNeedaction: true, + originThread: [['link', thread]], + }); + await this.createThreadNeedactionPreviewComponent({ + threadLocalId: thread.localId, + }); + assert.containsOnce( + document.body, + '.o_ThreadNeedactionPreview', + "should have a preview initially" + ); + assert.containsNone( + document.body, + '.o_ChatWindow', + "should have no chat window initially" + ); + + await afterNextRender(() => + document.querySelector('.o_ThreadNeedactionPreview').click() + ); + assert.verifySteps( + ['set_message_done'], + "should have marked the message as read on clicking on the preview" + ); + assert.containsOnce( + document.body, + '.o_ChatWindow', + "should have opened the thread on clicking on the preview" + ); +}); + +QUnit.test('click on expand from chat window should close the chat window and open the form view', async function (assert) { + assert.expect(8); + + const bus = new Bus(); + bus.on('do-action', null, payload => { + assert.step('do_action'); + assert.strictEqual( + payload.action.res_id, + 11, + "should redirect to the id of the thread" + ); + assert.strictEqual( + payload.action.res_model, + 'res.partner', + "should redirect to the model of the thread" + ); + }); + await this.start({ + env: { bus }, + hasChatWindow: true, + }); + const thread = this.env.models['mail.thread'].create({ + id: 11, + model: 'res.partner', + }); + this.env.models['mail.message'].create({ + id: 21, + isNeedaction: true, + originThread: [['link', thread]], + }); + await this.createThreadNeedactionPreviewComponent({ + threadLocalId: thread.localId, + }); + assert.containsOnce( + document.body, + '.o_ThreadNeedactionPreview', + "should have a preview initially" + ); + await afterNextRender(() => + document.querySelector('.o_ThreadNeedactionPreview').click() + ); + assert.containsOnce( + document.body, + '.o_ChatWindow', + "should have opened the thread on clicking on the preview" + ); + assert.containsOnce( + document.body, + '.o_ChatWindowHeader_commandExpand', + "should have an expand button" + ); + + await afterNextRender(() => + document.querySelector('.o_ChatWindowHeader_commandExpand').click() + ); + assert.containsNone( + document.body, + '.o_ChatWindow', + "should have closed the chat window on clicking expand" + ); + assert.verifySteps( + ['do_action'], + "should have done an action to open the form view" + ); +}); + }); }); }); diff --git a/addons/mail/static/src/models/thread/thread.js b/addons/mail/static/src/models/thread/thread.js index a1818376233..bed46a7f41b 100644 --- a/addons/mail/static/src/models/thread/thread.js +++ b/addons/mail/static/src/models/thread/thread.js @@ -631,16 +631,22 @@ function factory(dependencies) { * @param {boolean} [param0.expanded=false] */ async open({ expanded = false } = {}) { + const discuss = this.env.messaging.discuss; // check if thread must be opened in form view if (!['mail.box', 'mail.channel'].includes(this.model)) { - return this.env.messaging.openDocument({ - id: this.id, - model: this.model, - }); + if (expanded || discuss.isOpen) { + // Close chat window because having the same thread opened + // both in chat window and as main document does not look + // good. + this.env.messaging.chatWindowManager.closeThread(this); + return this.env.messaging.openDocument({ + id: this.id, + model: this.model, + }); + } } // check if thread must be opened in discuss const device = this.env.messaging.device; - const discuss = this.env.messaging.discuss; if ( (!device.isMobile && (discuss.isOpen || expanded)) || this.model === 'mail.box'