summaryrefslogtreecommitdiff
path: root/addons
diff options
context:
space:
mode:
authorXavier Dubuc <xdu@odoo.com>2020-10-27 15:18:57 +0000
committerSébastien Theys <seb@odoo.com>2020-10-27 15:18:57 +0000
commit063aa1deccdd6b53d1ab7de68921c95ecf60581c (patch)
tree51b65c2c75706e02fd27a242836862e7f372ec3e /addons
parent4e660dfdf40a36eed7123bcea2452874238fddd8 (diff)
[FIX] mail, im_livechat: allow to reopen closed chat in discuss
task-2346862 closes odoo/odoo#60080 Signed-off-by: Sébastien Theys (seb) <seb@odoo.com>
Diffstat (limited to 'addons')
-rw-r--r--addons/im_livechat/static/src/models/messaging_initializer/messaging_initializer.js2
-rw-r--r--addons/mail/models/mail_channel.py14
-rw-r--r--addons/mail/static/src/components/discuss/tests/discuss_pinned_tests.js2
-rw-r--r--addons/mail/static/src/models/messaging_initializer/messaging_initializer.js2
-rw-r--r--addons/mail/static/src/models/messaging_notification_handler/messaging_notification_handler.js2
-rw-r--r--addons/mail/static/src/models/thread/thread.js132
-rw-r--r--addons/mail/static/src/models/user/user.js4
7 files changed, 104 insertions, 54 deletions
diff --git a/addons/im_livechat/static/src/models/messaging_initializer/messaging_initializer.js b/addons/im_livechat/static/src/models/messaging_initializer/messaging_initializer.js
index 6a98302e668..634fbb5dbfe 100644
--- a/addons/im_livechat/static/src/models/messaging_initializer/messaging_initializer.js
+++ b/addons/im_livechat/static/src/models/messaging_initializer/messaging_initializer.js
@@ -26,7 +26,7 @@ registerInstancePatchModel('mail.messaging_initializer', 'im_livechat/static/src
// flux specific: channels received at init have to be
// considered pinned. task-2284357
if (!channel.isPinned) {
- channel.update({ isPendingPinned: true });
+ channel.pin();
}
}
},
diff --git a/addons/mail/models/mail_channel.py b/addons/mail/models/mail_channel.py
index a3f6f5154db..74e1eac1332 100644
--- a/addons/mail/models/mail_channel.py
+++ b/addons/mail/models/mail_channel.py
@@ -264,8 +264,15 @@ class Channel(models.Model):
return values
def _subscribe_users(self):
+ to_create = []
for mail_channel in self:
- mail_channel.write({'channel_partner_ids': [(4, pid) for pid in mail_channel.mapped('group_ids').mapped('users').mapped('partner_id').ids]})
+ partners_to_add = mail_channel.group_ids.users.partner_id - mail_channel.channel_partner_ids
+ to_create += [{
+ 'channel_id': mail_channel.id,
+ 'partner_id': partner.id,
+ } for partner in partners_to_add]
+
+ self.env['mail.channel.partner'].create(to_create)
def action_follow(self):
self.ensure_one()
@@ -672,6 +679,7 @@ class Channel(models.Model):
# pin up the channel for the current partner
if pin:
self.env['mail.channel.partner'].search([('partner_id', '=', self.env.user.partner_id.id), ('channel_id', '=', channel.id)]).write({'is_pinned': True})
+ channel._broadcast(self.env.user.partner_id.ids)
else:
# create a new one
channel = self.create({
@@ -681,7 +689,6 @@ class Channel(models.Model):
'email_send': False,
'name': ', '.join(self.env['res.partner'].sudo().browse(partners_to).mapped('name')),
})
- # broadcast the channel header to the other partner (not me)
channel._broadcast(partners_to)
return channel.channel_info()[0]
@@ -735,8 +742,7 @@ class Channel(models.Model):
self.ensure_one()
channel_partners = self.env['mail.channel.partner'].search(
[('partner_id', '=', self.env.user.partner_id.id), ('channel_id', '=', self.id)])
- if not pinned:
- self.env['bus.bus'].sendone((self._cr.dbname, 'res.partner', self.env.user.partner_id.id), self.channel_info('unsubscribe')[0])
+ self.env['bus.bus'].sendone((self._cr.dbname, 'res.partner', self.env.user.partner_id.id), self.channel_info('unsubscribe' if not pinned else False)[0])
if channel_partners:
channel_partners.write({'is_pinned': pinned})
diff --git a/addons/mail/static/src/components/discuss/tests/discuss_pinned_tests.js b/addons/mail/static/src/components/discuss/tests/discuss_pinned_tests.js
index a373b25cd49..108e7a28d1d 100644
--- a/addons/mail/static/src/components/discuss/tests/discuss_pinned_tests.js
+++ b/addons/mail/static/src/components/discuss/tests/discuss_pinned_tests.js
@@ -93,7 +93,7 @@ QUnit.test('sidebar: pinned channel 3: open pinned channel and unpin it', async
assert.deepEqual(args.args[0], [20],
"The right id is sent to the server to remove"
);
- assert.strictEqual(args.args[1], 'leave',
+ assert.strictEqual(args.kwargs.command, 'leave',
"The right command is sent to the server"
);
}
diff --git a/addons/mail/static/src/models/messaging_initializer/messaging_initializer.js b/addons/mail/static/src/models/messaging_initializer/messaging_initializer.js
index 13da76dbb38..da2f51757be 100644
--- a/addons/mail/static/src/models/messaging_initializer/messaging_initializer.js
+++ b/addons/mail/static/src/models/messaging_initializer/messaging_initializer.js
@@ -169,7 +169,7 @@ function factory(dependencies) {
// flux specific: channels received at init have to be
// considered pinned. task-2284357
if (!channel.isPinned) {
- channel.update({ isPendingPinned: true });
+ channel.pin();
}
}
}
diff --git a/addons/mail/static/src/models/messaging_notification_handler/messaging_notification_handler.js b/addons/mail/static/src/models/messaging_notification_handler/messaging_notification_handler.js
index 783b43e4f20..affa3c05a30 100644
--- a/addons/mail/static/src/models/messaging_notification_handler/messaging_notification_handler.js
+++ b/addons/mail/static/src/models/messaging_notification_handler/messaging_notification_handler.js
@@ -205,7 +205,7 @@ function factory(dependencies) {
))[0];
}
if (!channel.isPinned) {
- channel.update({ isPendingPinned: true });
+ channel.pin();
}
const message = this.env.models['mail.message'].insert(convertedData);
diff --git a/addons/mail/static/src/models/thread/thread.js b/addons/mail/static/src/models/thread/thread.js
index cd1ee77b1ce..4de44f8b3ec 100644
--- a/addons/mail/static/src/models/thread/thread.js
+++ b/addons/mail/static/src/models/thread/thread.js
@@ -341,7 +341,6 @@ function factory(dependencies) {
return channels;
}
-
/**
* Performs the `channel_seen` RPC on `mail.channel`.
*
@@ -362,6 +361,25 @@ function factory(dependencies) {
}
/**
+ * Performs the `channel_pin` RPC on `mail.channel`.
+ *
+ * @static
+ * @param {Object} param0
+ * @param {boolean} [param0.pinned=false]
+ * @param {string} param0.uuid
+ */
+ static async performRpcChannelPin({ pinned = false, uuid }) {
+ return this.env.services.rpc({
+ model: 'mail.channel',
+ method: 'channel_pin',
+ kwargs: {
+ uuid,
+ pinned,
+ },
+ }, { shadow: true });
+ }
+
+ /**
* Performs the `channel_create` RPC on `mail.channel`.
*
* @static
@@ -453,6 +471,25 @@ function factory(dependencies) {
}
/**
+ * Performs the `execute_command` RPC on `mail.channel`.
+ *
+ * @static
+ * @param {Object} param0
+ * @param {string} param0.command the command to execute
+ * @param {integer[]} param0.ids list of id of channels
+ */
+ static async performRpcExecuteCommand({ command, ids }) {
+ return this.env.services.rpc({
+ model: 'mail.channel',
+ method: 'execute_command',
+ args: [ids],
+ kwargs: {
+ command,
+ }
+ });
+ }
+
+ /**
* Performs RPC on the route `/mail/get_suggested_recipients`.
*
* @static
@@ -633,23 +670,17 @@ function factory(dependencies) {
*
* Only makes sense if isPendingPinned is set to the desired value.
*/
- notifyPinStateToServer() {
- // method is called from _updateAfter so it cannot be async
+ async notifyPinStateToServer() {
if (this.isPendingPinned) {
- this.env.services.rpc({
- model: 'mail.channel',
- method: 'channel_pin',
- kwargs: {
- uuid: this.uuid,
- pinned: true,
- },
- }, { shadow: true });
+ await this.env.models['mail.thread'].performRpcChannelPin({
+ pinned: true,
+ uuid: this.uuid,
+ });
} else {
- this.env.services.rpc({
- model: 'mail.channel',
- method: 'execute_command',
- args: [[this.id], 'leave']
- }, { shadow: true });
+ await this.env.models['mail.thread'].performRpcExecuteCommand({
+ command: 'leave',
+ ids: [this.id],
+ });
}
}
@@ -701,6 +732,14 @@ function factory(dependencies) {
}
/**
+ * Pin this thread and notify server of the change.
+ */
+ async pin() {
+ this.update({ isPendingPinned: true });
+ await this.notifyPinStateToServer();
+ }
+
+ /**
* Open a dialog to add channels as followers.
*/
promptAddChannelFollower() {
@@ -868,6 +907,14 @@ function factory(dependencies) {
}
/**
+ * Unpin this thread and notify server of the change.
+ */
+ async unpin() {
+ this.update({ isPendingPinned: false });
+ await this.notifyPinStateToServer();
+ }
+
+ /**
* Called when current partner has explicitly stopped inserting some
* input in composer. Useful to notify current partner has currently
* stopped typing something in the composer of this thread to all other
@@ -921,7 +968,7 @@ function factory(dependencies) {
*/
unsubscribe() {
this.env.messaging.chatWindowManager.closeThread(this);
- this.update({ isPendingPinned: false });
+ this.unpin();
}
//----------------------------------------------------------------------
@@ -1297,6 +1344,19 @@ function factory(dependencies) {
}
/**
+ * Handles change of pinned state coming from the server. Useful to
+ * clear pending state once server acknowledged the change.
+ *
+ * @private
+ * @see isPendingPinned
+ */
+ _onIsServerPinnedChanged() {
+ if (this.isServerPinned === this.isPendingPinned) {
+ this.update({ isPendingPinned: clear() });
+ }
+ }
+
+ /**
* Handles change of fold state coming from the server. Useful to
* synchronize corresponding chat window.
*
@@ -1350,34 +1410,6 @@ function factory(dependencies) {
});
}
- /**
- * @override
- */
- _updateAfter(previous) {
- if (this.model !== 'mail.channel') {
- // pin state only makes sense on channels
- return;
- }
- if (
- this.isPendingPinned !== undefined &&
- previous.isPendingPinned !== this.isPendingPinned
- ) {
- this.notifyPinStateToServer();
- }
- if (this.isServerPinned === this.isPendingPinned) {
- this.update({ isPendingPinned: clear() });
- }
- }
-
- /**
- * @override
- */
- _updateBefore() {
- return {
- isPendingPinned: this.isPendingPinned,
- };
- }
-
//----------------------------------------------------------------------
// Handlers
//----------------------------------------------------------------------
@@ -1702,6 +1734,16 @@ function factory(dependencies) {
dependencies: ['messages'],
}),
/**
+ * Not a real field, used to trigger `_onIsServerPinnedChanged` when one of
+ * the dependencies changes.
+ */
+ onIsServerPinnedChanged: attr({
+ compute: '_onIsServerPinnedChanged',
+ dependencies: [
+ 'isServerPinned',
+ ],
+ }),
+ /**
* Not a real field, used to trigger `_onServerFoldStateChanged` when one of
* the dependencies changes.
*/
diff --git a/addons/mail/static/src/models/user/user.js b/addons/mail/static/src/models/user/user.js
index 2decc8efd92..172b8c5b780 100644
--- a/addons/mail/static/src/models/user/user.js
+++ b/addons/mail/static/src/models/user/user.js
@@ -113,7 +113,9 @@ function factory(dependencies) {
thread.model === 'mail.channel' &&
thread.public === 'private'
);
- if (!chat) {
+ if (!chat ||!chat.isPinned) {
+ // if chat is not pinned then it has to be pinned client-side
+ // and server-side, which is a side effect of following rpc
chat = await this.async(() =>
this.env.models['mail.thread'].performRpcCreateChat({
partnerIds: [this.partner.id],