diff options
| author | Sébastien Theys <seb@odoo.com> | 2020-09-02 12:21:07 +0000 |
|---|---|---|
| committer | Sébastien Theys <seb@odoo.com> | 2020-09-03 09:33:38 +0000 |
| commit | 781bf9ec2eb5606d76ba3afa61cf06b5c3ac85fc (patch) | |
| tree | 63e4553759b13830bf82a915a74353c02b081464 /addons/mail/static/src | |
| parent | 45ba62817d8a82129a2bae44cae9e3757529bdce (diff) | |
[FIX] mail: add open chat when clicking on author im status icon
task-2329538
closes odoo/odoo#57006
X-original-commit: bfb8d99baaadedb2d0492b6f378b13b3330d496a
Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
Signed-off-by: Sébastien Theys (seb) <seb@odoo.com>
Diffstat (limited to 'addons/mail/static/src')
8 files changed, 164 insertions, 4 deletions
diff --git a/addons/mail/static/src/components/chat_window/chat_window.js b/addons/mail/static/src/components/chat_window/chat_window.js index 7f9b53d2670..43353c6086f 100644 --- a/addons/mail/static/src/components/chat_window/chat_window.js +++ b/addons/mail/static/src/components/chat_window/chat_window.js @@ -226,6 +226,9 @@ class ChatWindow extends Component { if (isEventHandled(ev, 'Message.authorOpenProfile')) { return; } + if (isEventHandled(ev, 'PartnerImStatusIcon.openChat')) { + return; + } this.chatWindow.focus(); } diff --git a/addons/mail/static/src/components/message/message.js b/addons/mail/static/src/components/message/message.js index 499c462efe9..e63d35332ea 100644 --- a/addons/mail/static/src/components/message/message.js +++ b/addons/mail/static/src/components/message/message.js @@ -166,8 +166,9 @@ class Message extends Component { return false; } if ( - this.message.originThread && - this.message.originThread.correspondent === this.message.author + this.threadView && + this.threadView.thread && + this.threadView.thread.correspondent === this.message.author ) { return false; } diff --git a/addons/mail/static/src/components/message/message.xml b/addons/mail/static/src/components/message/message.xml index b0a41947c88..d739cb1769f 100644 --- a/addons/mail/static/src/components/message/message.xml +++ b/addons/mail/static/src/components/message/message.xml @@ -27,6 +27,7 @@ 'o-message-selected': props.isSelected, 'o_Message_partnerImStatusIcon-mobile': env.messaging.device.isMobile, }" + hasOpenChat="hasAuthorOpenChat" partnerLocalId="message.author.localId" /> </t> diff --git a/addons/mail/static/src/components/message/message_tests.js b/addons/mail/static/src/components/message/message_tests.js index 3d7bf1da396..df964458fea 100644 --- a/addons/mail/static/src/components/message/message_tests.js +++ b/addons/mail/static/src/components/message/message_tests.js @@ -9,6 +9,7 @@ const { afterNextRender, beforeEach, createRootComponent, + nextAnimationFrame, start, } = require('mail/static/src/utils/test_utils.js'); @@ -829,6 +830,129 @@ QUnit.test('data-oe-id & data-oe-model link redirection on click', async functio ); }); +QUnit.test('chat with author should be opened after clicking on his avatar', async function (assert) { + assert.expect(4); + + this.data['res.partner'].records.push({ id: 10 }); + this.data['res.users'].records.push({ partner_id: 10 }); + await this.start({ + hasChatWindow: true, + }); + const message = this.env.models['mail.message'].create({ + author: [['insert', { id: 10 }]], + id: 10, + }); + await this.createMessageComponent(message); + assert.containsOnce( + document.body, + '.o_Message_authorAvatar', + "message should have the author avatar" + ); + assert.hasClass( + document.querySelector('.o_Message_authorAvatar'), + 'o_redirect', + "author avatar should have the redirect style" + ); + + await afterNextRender(() => + document.querySelector('.o_Message_authorAvatar').click() + ); + assert.containsOnce( + document.body, + '.o_ChatWindow_thread', + "chat window with thread should be opened after clicking on author avatar" + ); + assert.strictEqual( + document.querySelector('.o_ChatWindow_thread').dataset.correspondentId, + message.author.id.toString(), + "chat with author should be opened after clicking on his avatar" + ); +}); + +QUnit.test('chat with author should be opened after clicking on his im status icon', async function (assert) { + assert.expect(4); + + this.data['res.partner'].records.push({ id: 10 }); + this.data['res.users'].records.push({ partner_id: 10 }); + await this.start({ + hasChatWindow: true, + }); + const message = this.env.models['mail.message'].create({ + author: [['insert', { id: 10, im_status: 'online' }]], + id: 10, + }); + await this.createMessageComponent(message); + assert.containsOnce( + document.body, + '.o_Message_partnerImStatusIcon', + "message should have the author im status icon" + ); + assert.hasClass( + document.querySelector('.o_Message_partnerImStatusIcon'), + 'o-has-open-chat', + "author im status icon should have the open chat style" + ); + + await afterNextRender(() => + document.querySelector('.o_Message_partnerImStatusIcon').click() + ); + assert.containsOnce( + document.body, + '.o_ChatWindow_thread', + "chat window with thread should be opened after clicking on author im status icon" + ); + assert.strictEqual( + document.querySelector('.o_ChatWindow_thread').dataset.correspondentId, + message.author.id.toString(), + "chat with author should be opened after clicking on his im status icon" + ); +}); + +QUnit.test('open chat with author on avatar click should be disabled when currently chatting with the author', async function (assert) { + assert.expect(3); + + this.data['mail.channel'].records.push({ + channel_type: 'chat', + members: [this.data.currentPartnerId, 10], + public: 'private', + }); + this.data['res.partner'].records.push({ id: 10 }); + this.data['res.users'].records.push({ partner_id: 10 }); + await this.start({ + hasChatWindow: true, + }); + const correspondent = this.env.models['mail.partner'].insert({ id: 10 }); + const message = this.env.models['mail.message'].create({ + author: [['link', correspondent]], + id: 10, + }); + const thread = await correspondent.getChat(); + const threadView = this.env.models['mail.thread_view'].create({ + thread: [['link', thread]], + }); + await this.createMessageComponent(message, { + threadViewLocalId: threadView.localId, + }); + assert.containsOnce( + document.body, + '.o_Message_authorAvatar', + "message should have the author avatar" + ); + assert.doesNotHaveClass( + document.querySelector('.o_Message_authorAvatar'), + 'o_redirect', + "author avatar should not have the redirect style" + ); + + document.querySelector('.o_Message_authorAvatar').click(); + await nextAnimationFrame(); + assert.containsNone( + document.body, + '.o_ChatWindow', + "should have no thread opened after clicking on author avatar when currently chatting with the author" + ); +}); + }); }); }); diff --git a/addons/mail/static/src/components/partner_im_status_icon/partner_im_status_icon.js b/addons/mail/static/src/components/partner_im_status_icon/partner_im_status_icon.js index 7150c2914a9..2a9af18f79a 100644 --- a/addons/mail/static/src/components/partner_im_status_icon/partner_im_status_icon.js +++ b/addons/mail/static/src/components/partner_im_status_icon/partner_im_status_icon.js @@ -2,6 +2,7 @@ odoo.define('mail/static/src/components/partner_im_status_icon/partner_im_status 'use strict'; const useStore = require('mail/static/src/component_hooks/use_store/use_store.js'); +const { markEventHandled } = require('mail/static/src/utils/utils.js'); const { Component } = owl; @@ -34,15 +35,37 @@ class PartnerImStatusIcon extends Component { return this.env.models['mail.partner'].get(this.props.partnerLocalId); } + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + + /** + * @private + * @param {MouseEvent} ev + */ + _onClick(ev) { + if (!this.props.hasOpenChat) { + return; + } + markEventHandled(ev, 'PartnerImStatusIcon.openChat'); + this.partner.openChat(); + } + } Object.assign(PartnerImStatusIcon, { defaultProps: { - hasBackground: true + hasBackground: true, + hasOpenChat: false, }, props: { partnerLocalId: String, hasBackground: Boolean, + /** + * Determines whether a click on `this` should open a chat with + * `this.partner`. + */ + hasOpenChat: Boolean, }, template: 'mail.PartnerImStatusIcon', }); diff --git a/addons/mail/static/src/components/partner_im_status_icon/partner_im_status_icon.scss b/addons/mail/static/src/components/partner_im_status_icon/partner_im_status_icon.scss index d5791c2f0c6..608c281aa0a 100644 --- a/addons/mail/static/src/components/partner_im_status_icon/partner_im_status_icon.scss +++ b/addons/mail/static/src/components/partner_im_status_icon/partner_im_status_icon.scss @@ -25,6 +25,12 @@ // Style // ------------------------------------------------------------------ +.o_PartnerImStatusIcon { + &.o-has-open-chat { + cursor: pointer; + } +} + .o_PartnerImStatusIcon_innerBackground { color: white; } diff --git a/addons/mail/static/src/components/partner_im_status_icon/partner_im_status_icon.xml b/addons/mail/static/src/components/partner_im_status_icon/partner_im_status_icon.xml index 23879cc6b39..ca20a547f2b 100644 --- a/addons/mail/static/src/components/partner_im_status_icon/partner_im_status_icon.xml +++ b/addons/mail/static/src/components/partner_im_status_icon/partner_im_status_icon.xml @@ -7,9 +7,11 @@ 'o-away': partner and partner.im_status === 'away', 'o-background': !props.hasBackground, 'o-bot': partner and env.messaging.partnerRoot === partner, + 'o-has-open-chat': props.hasOpenChat, 'o-offline': partner and partner.im_status === 'offline', 'o-online': partner and partner.im_status === 'online', }" + t-on-click="_onClick" t-att-data-partner-local-id="partner ? partner.localId : undefined" > <t t-if="partner" name="rootCondition"> diff --git a/addons/mail/static/src/components/thread_view/thread_view.xml b/addons/mail/static/src/components/thread_view/thread_view.xml index eead567fa1e..12352f67fe5 100644 --- a/addons/mail/static/src/components/thread_view/thread_view.xml +++ b/addons/mail/static/src/components/thread_view/thread_view.xml @@ -2,7 +2,7 @@ <templates xml:space="preserve"> <t t-name="mail.ThreadView" owl="1"> - <div class="o_ThreadView" t-att-data-thread-local-id="threadView and threadView.thread and threadView.thread.localId"> + <div class="o_ThreadView" t-att-data-correspondent-id="threadView and threadView.thread and threadView.thread.correspondent and threadView.thread.correspondent.id" t-att-data-thread-local-id="threadView and threadView.thread and threadView.thread.localId"> <t t-if="threadView"> <t t-if="threadView.isShowingLoading" name="loadingCondition"> <div class="o_ThreadView_loading"> |
