diff --git a/addons/mail/models/mail_channel.py b/addons/mail/models/mail_channel.py index bdc0f8b2160..fe33a2da77a 100644 --- a/addons/mail/models/mail_channel.py +++ b/addons/mail/models/mail_channel.py @@ -579,6 +579,10 @@ class Channel(models.Model): .channel_partner_ids .filtered(lambda p: p.id != self.env.user.partner_id.id) .read(['id', 'name', 'im_status'])) + for direct_partner in info['direct_partner']: + users = self.env['res.partner'].browse(direct_partner['id']).user_ids + if users: + direct_partner['out_of_office_message'] = users[0].out_of_office_message # add last message preview (only used in mobile) if self._context.get('isMobile', False): diff --git a/addons/mail/static/src/js/models/threads/dm_chat.js b/addons/mail/static/src/js/models/threads/dm_chat.js index 4967a1e9963..21fb72e91ae 100644 --- a/addons/mail/static/src/js/models/threads/dm_chat.js +++ b/addons/mail/static/src/js/models/threads/dm_chat.js @@ -1,7 +1,9 @@ odoo.define('mail.model.DMChat', function (require) { "use strict"; +var core = require('web.core'); var TwoUserChannel = require('mail.model.TwoUserChannel'); +var _t = core._t; /** * Any piece of code in JS that make use of DMs must ideally interact with @@ -18,6 +20,7 @@ var DMChat = TwoUserChannel.extend({ * @param {integer} params.data.direct_partner[0].id * @param {string} params.data.direct_partner[0].im_status * @param {string} params.data.direct_partner[0].name + * @param {string} [params.data.direct_partner[0].out_of_office_message=''] */ init: function (params) { this._super.apply(this, arguments); @@ -50,6 +53,17 @@ var DMChat = TwoUserChannel.extend({ getDirectPartnerID: function () { return this._directPartnerID; }, + /** + * Get the out of office message of the thread + * + * @returns {string} + */ + getOutOfOfficeMessage: function () { + if (this._outOfOfficeMessage === '') { + return undefined; + } + return this._outOfOfficeMessage; + }, /** * @override */ diff --git a/addons/mail/static/src/js/thread_windows/abstract_thread_window.js b/addons/mail/static/src/js/thread_windows/abstract_thread_window.js index 3e4e2e16325..da958c1c5f1 100644 --- a/addons/mail/static/src/js/thread_windows/abstract_thread_window.js +++ b/addons/mail/static/src/js/thread_windows/abstract_thread_window.js @@ -147,6 +147,22 @@ var AbstractThreadWindow = Widget.extend({ } return this._thread; }, + /** + * Get out of office user text + * + * @returns {string|undefined} + */ + getOutOfOfficeMessage: function () { + if ( + !( + this.hasThread() && + this._thread.getType() === 'dm_chat' + ) + ) { + return undefined; + } + return this._thread.getOutOfOfficeMessage(); + }, /** * Get the status of the thread, such as the im status of a DM chat * ('online', 'offline', etc.). If this window has no thread, returns diff --git a/addons/mail/static/src/scss/abstract_thread_window.scss b/addons/mail/static/src/scss/abstract_thread_window.scss index b148afa111f..62b0c42d033 100644 --- a/addons/mail/static/src/scss/abstract_thread_window.scss +++ b/addons/mail/static/src/scss/abstract_thread_window.scss @@ -79,6 +79,11 @@ $o-mail-thread-window-zindex: $zindex-modal + 1 !default; } + .o_out_of_office { + background-color: #9dd0e8; + padding:8px; + } + .o_mail_thread { flex: 1 1 100%; overflow: auto; diff --git a/addons/mail/static/src/scss/discuss.scss b/addons/mail/static/src/scss/discuss.scss index 570dc2dedd6..711180d3544 100644 --- a/addons/mail/static/src/scss/discuss.scss +++ b/addons/mail/static/src/scss/discuss.scss @@ -252,6 +252,11 @@ &.o_user_idle { color: theme-color('warning'); } + &.fa-stack { + width: 1em; + height: 1em; + line-height: 1em; + } } diff --git a/addons/mail/static/src/scss/thread.scss b/addons/mail/static/src/scss/thread.scss index 7c867896150..84a826922ff 100644 --- a/addons/mail/static/src/scss/thread.scss +++ b/addons/mail/static/src/scss/thread.scss @@ -68,6 +68,19 @@ margin-top: 2px; text-align: center; font-size: smaller; + .o_thread_message_sidebar_image { + position: relative; + height: $o-mail-thread-avatar-size; + + .o_updatable_im_status { + width: $o-mail-thread-avatar-size; + } + .o_mail_user_status { + position: absolute; + bottom: 0; + right: 0; + } + } @include media-breakpoint-down(sm) { margin-top: 4px; diff --git a/addons/mail/static/src/xml/thread_window.xml b/addons/mail/static/src/xml/thread_window.xml index 4164bc0abc9..4d175fcf2b8 100644 --- a/addons/mail/static/src/xml/thread_window.xml +++ b/addons/mail/static/src/xml/thread_window.xml @@ -6,6 +6,9 @@ --> +
+
+
To: diff --git a/addons/mail/static/tests/thread_window/basic_thread_window_tests.js b/addons/mail/static/tests/thread_window/basic_thread_window_tests.js index 3fc942b506f..5a0bc62f880 100644 --- a/addons/mail/static/tests/thread_window/basic_thread_window_tests.js +++ b/addons/mail/static/tests/thread_window/basic_thread_window_tests.js @@ -632,6 +632,69 @@ QUnit.test('do not auto-focus chat window on receiving new message from new DM', parent.destroy(); }); +QUnit.test('out-of-office status in thread window', function (assert) { + assert.expect(1); + this.data = { + 'mail.message': { + fields: {}, + records: [], + }, + initMessaging: { + channel_slots: { + channel_channel: [{ + id: 1, + name: "DM", + channel_type: "chat", + message_unread_counter: 0, + direct_partner: [{ id: 666, name: 'DemoUser1', im_status: 'online', out_of_office_message: 'Please don\'t disturb'}], + }], + }, + }, + }; + var parent = this.createParent({ + data: this.data, + services: this.services, + }); + // detach channel 1, so that it opens corresponding thread window. + parent.call('mail_service', 'getChannel', 1).detach(); + + var $threadWindow = $('.o_thread_window'); + assert.containsOnce($threadWindow, '.o_out_of_office_text'); + + parent.destroy(); +}); + +QUnit.test('no out-of-office status in thread window', function (assert) { + assert.expect(1); + this.data = { + 'mail.message': { + fields: {}, + records: [], + }, + initMessaging: { + channel_slots: { + channel_channel: [{ + id: 1, + name: "DM", + channel_type: "chat", + message_unread_counter: 0, + direct_partner: [{ id: 666, name: 'DemoUser1', im_status: 'online'}], + }], + }, + }, + }; + var parent = this.createParent({ + data: this.data, + services: this.services, + }); + // detach channel 1, so that it opens corresponding thread window. + parent.call('mail_service', 'getChannel', 1).detach(); + + var $threadWindow = $('.o_thread_window'); + assert.containsNone($threadWindow, '.o_out_of_office_text'); + parent.destroy(); +}); + }); }); }); diff --git a/addons/test_mail/tests/test_mail_channel.py b/addons/test_mail/tests/test_mail_channel.py index 79ab747fed5..c95f562332d 100644 --- a/addons/test_mail/tests/test_mail_channel.py +++ b/addons/test_mail/tests/test_mail_channel.py @@ -196,6 +196,19 @@ class TestChannelFeatures(common.BaseFunctionalTest, common.MockEmails): email['email_to'][0], [formataddr((self.user_employee.name, self.user_employee.email)), formataddr((self.test_partner.name, self.test_partner.email))]) + @mute_logger('odoo.addons.mail.models.mail_mail') + def test_channel_out_of_office(self): + self.user_employee.out_of_office_message = 'Out' + test_chat = self.env['mail.channel'].with_context(common.BaseFunctionalTest._test_context).create({ + 'channel_partner_ids': [(4, self.user_employee.partner_id.id), (4, self.user_admin.partner_id.id)], + 'public': 'private', + 'channel_type': 'chat', + 'email_send': False, + 'name': 'test' + }) + infos = test_chat.sudo(self.user_admin).channel_info() + self.assertEqual(infos[0]['direct_partner'][0]['out_of_office_message'], 'Out') + @tagged('moderation') class TestChannelModeration(common.Moderation):