From 458cb9b55a01b5922a2e91ba4a8b3f32d657fb68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Theys?= Date: Tue, 12 Jul 2022 13:57:28 +0000 Subject: [PATCH] [IMP] mail: display guest in channel member list Part of task-2664860 closes odoo/odoo#95859 Signed-off-by: Louis Wicket (wil) --- addons/mail/models/mail_channel.py | 30 ++++++++---- .../channel_member/channel_member.xml | 6 +-- addons/mail/static/src/models/channel.js | 4 +- .../mail/static/src/models/channel_member.js | 46 +++++++++++++------ .../static/src/models/channel_member_view.js | 8 ++-- addons/mail/static/src/models/partner.js | 4 -- addons/mail/static/src/models/persona.js | 6 ++- .../src/models/persona_im_status_icon_view.js | 2 +- .../mail/static/tests/helpers/mock_server.js | 36 ++++++++++++--- .../components/channel_member_list_tests.js | 14 ++---- 10 files changed, 103 insertions(+), 53 deletions(-) diff --git a/addons/mail/models/mail_channel.py b/addons/mail/models/mail_channel.py index 3682e8101a9..2de8c6b718d 100644 --- a/addons/mail/models/mail_channel.py +++ b/addons/mail/models/mail_channel.py @@ -1176,15 +1176,29 @@ class Channel(models.Model): count = self.env['mail.channel.partner'].search_count( domain=[('channel_id', '=', self.id)], ) - return { - 'channelMembers': [('insert', [{ + members_data = [] + for member in channel_partners: + if member.partner_id: + persona = { + 'partner': [('insert-and-replace', { + 'id': member.partner_id.id, + 'name': member.partner_id.name, + 'im_status': member.partner_id.im_status, + })], + } + if member.guest_id: + persona = { + 'guest': [('insert-and-replace', { + 'id': member.guest_id.id, + 'name': member.guest_id.name, + })], + } + members_data.append({ 'id': member.id, - 'partner': [('insert', { - 'id': member.partner_id.id, - 'name': member.partner_id.name, - 'im_status': member.partner_id.im_status, - })] if member.partner_id else [('clear',)], - } for member in channel_partners])], + 'persona': [('insert-and-replace', persona)], + }) + return { + 'channelMembers': [('insert', members_data)], 'memberCount': count, } diff --git a/addons/mail/static/src/components/channel_member/channel_member.xml b/addons/mail/static/src/components/channel_member/channel_member.xml index b6a8537df5b..da6be6d4e55 100644 --- a/addons/mail/static/src/components/channel_member/channel_member.xml +++ b/addons/mail/static/src/components/channel_member/channel_member.xml @@ -2,9 +2,9 @@ -
+
- Avatar + Avatar
- +
diff --git a/addons/mail/static/src/models/channel.js b/addons/mail/static/src/models/channel.js index 3e5d9e6dad6..198ed402af1 100644 --- a/addons/mail/static/src/models/channel.js +++ b/addons/mail/static/src/models/channel.js @@ -52,8 +52,8 @@ registerModel({ */ _sortMembers() { return [ - ['truthy-first', 'name'], - ['case-insensitive-asc', 'name'], + ['truthy-first', 'persona.name'], + ['case-insensitive-asc', 'persona.name'], ]; }, }, diff --git a/addons/mail/static/src/models/channel_member.js b/addons/mail/static/src/models/channel_member.js index 59fd64de270..63f79e0ee91 100644 --- a/addons/mail/static/src/models/channel_member.js +++ b/addons/mail/static/src/models/channel_member.js @@ -8,32 +8,50 @@ registerModel({ name: 'ChannelMember', identifyingFields: ['id'], recordMethods: { + /** + * @private + * @returns {string|FieldCommand} + */ + _computeAvatarUrl() { + if (this.persona.partner) { + return `/mail/channel/${this.channel.id}/partner/${this.persona.partner.id}/avatar_128`; + } + if (this.persona.guest) { + return `/mail/channel/${this.channel.id}/guest/${this.persona.guest.id}/avatar_128?unique=${this.persona.guest.name}`; + } + return clear(); + }, /** * @private * @returns {FieldCommand} */ _computeChannelAsOfflineMember() { - return this.partner && !this.partner.isOnline ? replace(this.channel) : clear(); + if (this.persona.partner) { + return !this.persona.partner.isOnline ? replace(this.channel) : clear(); + } + if (this.persona.guest) { + return replace(this.channel); + } + return clear(); }, /** * @private * @returns {FieldCommand} */ _computeChannelAsOnlineMember() { - return this.partner && this.partner.isOnline ? replace(this.channel) : clear(); - }, - /** - * @private - * @returns {string} - */ - _computeName() { - if (!this.partner) { - return; + if (this.persona.partner) { + return this.persona.partner.isOnline ? replace(this.channel) : clear(); } - return this.partner.nameOrDisplayName; + if (this.persona.guest) { + return clear(); + } + return clear(); }, }, fields: { + avatarUrl: attr({ + compute: '_computeAvatarUrl', + }), channel: one('Channel', { inverse: 'channelMembers', readonly: true, @@ -55,12 +73,10 @@ registerModel({ readonly: true, required: true, }), - name: attr({ - compute: '_computeName', - }), - partner: one('Partner', { + persona: one('Persona', { inverse: 'channelMembers', readonly: true, + required: true, }), }, }); diff --git a/addons/mail/static/src/models/channel_member_view.js b/addons/mail/static/src/models/channel_member_view.js index 1c1415a0b44..0232229cefc 100644 --- a/addons/mail/static/src/models/channel_member_view.js +++ b/addons/mail/static/src/models/channel_member_view.js @@ -15,17 +15,17 @@ registerModel({ * @param {MouseEvent} ev */ onClickMember(ev) { - if (isEventHandled(ev, 'PersonaImStatusIcon.Click') || !this.channelMember.partner) { + if (isEventHandled(ev, 'PersonaImStatusIcon.Click') || !this.channelMember.persona.partner) { return; } - this.channelMember.partner.openChat(); + this.channelMember.persona.partner.openChat(); }, /** * @private * @returns {Boolean} */ _computeHasOpenChat() { - return this.channelMember.partner ? true : false; + return this.channelMember.persona.partner ? true : false; }, /** * @private @@ -39,7 +39,7 @@ registerModel({ * @returns {FieldCommand} */ _computePersonaImStatusIconView() { - return this.channelMember.partner && this.channelMember.partner.isImStatusSet ? insertAndReplace() : clear(); + return this.channelMember.persona.partner && this.channelMember.persona.partner.isImStatusSet ? insertAndReplace() : clear(); }, }, fields: { diff --git a/addons/mail/static/src/models/partner.js b/addons/mail/static/src/models/partner.js index 042676fb878..44cd5fedb9c 100644 --- a/addons/mail/static/src/models/partner.js +++ b/addons/mail/static/src/models/partner.js @@ -383,10 +383,6 @@ registerModel({ inverse: 'partner', isCausal: true, }), - channelMembers: many('ChannelMember', { - inverse: 'partner', - isCausal: true, - }), country: one('Country'), /** * Deprecated. diff --git a/addons/mail/static/src/models/persona.js b/addons/mail/static/src/models/persona.js index d4b4f32c8af..2e644b120b3 100644 --- a/addons/mail/static/src/models/persona.js +++ b/addons/mail/static/src/models/persona.js @@ -1,7 +1,7 @@ /** @odoo-module **/ import { registerModel } from '@mail/model/model_core'; -import { attr, one } from '@mail/model/model_field'; +import { attr, many, one } from '@mail/model/model_field'; import { clear } from '@mail/model/model_field_command'; registerModel({ @@ -36,6 +36,10 @@ registerModel({ }, }, fields: { + channelMembers: many('ChannelMember', { + inverse: 'persona', + isCausal: true, + }), guest: one('Guest', { inverse: 'persona', readonly: true, diff --git a/addons/mail/static/src/models/persona_im_status_icon_view.js b/addons/mail/static/src/models/persona_im_status_icon_view.js index df513addf1a..b4a6fe169d5 100644 --- a/addons/mail/static/src/models/persona_im_status_icon_view.js +++ b/addons/mail/static/src/models/persona_im_status_icon_view.js @@ -25,7 +25,7 @@ registerModel({ return replace(this.channelInvitationFormSelectablePartnerViewOwner.partner.persona); } if (this.channelMemberViewOwner) { - return replace(this.channelMemberViewOwner.channelMember.partner.persona); + return replace(this.channelMemberViewOwner.channelMember.persona); } if (this.composerSuggestionViewOwner) { return replace(this.composerSuggestionViewOwner.suggestable.partner.persona); diff --git a/addons/mail/static/tests/helpers/mock_server.js b/addons/mail/static/tests/helpers/mock_server.js index 2b78f9c1235..326f31da8ac 100644 --- a/addons/mail/static/tests/helpers/mock_server.js +++ b/addons/mail/static/tests/helpers/mock_server.js @@ -1329,17 +1329,41 @@ patch(MockServer.prototype, 'mail', { const memberCount = this.pyEnv['mail.channel.partner'].searchCount([ ['channel_id', 'in', channel_ids], ]); - return { - channelMembers: [['insert', channelPartners.map(channelPartner => { + const membersData = []; + for (const channelPartner of channelPartners) { + let persona; + if (channelPartner.partner_id) { const [partner] = this.pyEnv['res.partner'].searchRead( [['id', '=', channelPartner.partner_id[0]]], { fields: ['id', 'name', 'im_status'] } ); - return { - id: channelPartner.id, - partner: [['insert', partner]], + persona = { + 'partner': [['insert-and-replace', { + 'id': partner.id, + 'name': partner.name, + 'im_status': partner.im_status, + }]], }; - })]], + } + if (channelPartner.guest_id) { + const [guest] = this.pyEnv['mail.guest'].searchRead( + [['id', '=', channelPartner.guest_id[0]]], + { fields: ['id', 'name'] } + ); + persona = { + 'guest': [['insert-and-replace', { + 'id': guest.id, + 'name': guest.name, + }]], + }; + } + membersData.push({ + 'id': channelPartner.id, + 'persona': [['insert-and-replace', persona]], + }); + } + return { + channelMembers: [['insert', membersData]], memberCount, }; }, diff --git a/addons/mail/static/tests/qunit_suite_tests/components/channel_member_list_tests.js b/addons/mail/static/tests/qunit_suite_tests/components/channel_member_list_tests.js index 167f1017092..e858776e0dc 100644 --- a/addons/mail/static/tests/qunit_suite_tests/components/channel_member_list_tests.js +++ b/addons/mail/static/tests/qunit_suite_tests/components/channel_member_list_tests.js @@ -79,7 +79,7 @@ QUnit.test('should have correct members in member list', async function (assert) channel_type: 'group', public: 'private', }); - const { click, messaging, openDiscuss } = await start({ + const { click, openDiscuss } = await start({ discuss: { context: { active_id: `mail.channel_${mailChannelId1}`, @@ -96,16 +96,12 @@ QUnit.test('should have correct members in member list', async function (assert) ); assert.containsOnce( document.body, - `.o_ChannelMember[data-partner-local-id="${ - messaging.models['Partner'].findFromIdentifyingData({ id: pyEnv.currentPartnerId }).localId - }"]`, + `.o_ChannelMember[data-partner-id="${pyEnv.currentPartnerId}"]`, "should have current partner in member list (current partner is a member)", ); assert.containsOnce( document.body, - `.o_ChannelMember[data-partner-local-id="${ - messaging.models['Partner'].findFromIdentifyingData({ id: resPartnerId1 }).localId - }"]`, + `.o_ChannelMember[data-partner-id="${resPartnerId1}"]`, "should have 'Demo' in member list ('Demo' is a member)", ); }); @@ -215,7 +211,7 @@ QUnit.test('chat with member should be opened after clicking on channel member', channel_type: 'group', public: 'private', }); - const { click, messaging, openDiscuss } = await start({ + const { click, openDiscuss } = await start({ discuss: { context: { active_id: `mail.channel_${mailChannelId1}`, @@ -225,7 +221,7 @@ QUnit.test('chat with member should be opened after clicking on channel member', await openDiscuss(); await click('.o_ThreadViewTopbar_showMemberListButton'); - await click(`.o_ChannelMember[data-partner-local-id="${messaging.models['Partner'].findFromIdentifyingData({ id: resPartnerId1 }).localId}"]`); + await click(`.o_ChannelMember[data-partner-id="${resPartnerId1}"]`); assert.containsOnce( document.body, `.o_ThreadView[data-correspondent-id="${resPartnerId1}"]`,