[FIX] mail, im_livechat: allow to reopen closed chat in discuss
task-2346862 closes odoo/odoo#60859 X-original-commit: 063aa1deccdd6b53d1ab7de68921c95ecf60581c Signed-off-by: Sébastien Theys (seb) <seb@odoo.com>
This commit is contained in:
committed by
Sébastien Theys
parent
6f8d9ab39b
commit
454ecb46c9
@@ -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();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -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})
|
||||
|
||||
|
||||
@@ -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"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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);
|
||||
|
||||
@@ -341,7 +341,6 @@ function factory(dependencies) {
|
||||
return channels;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Performs the `channel_seen` RPC on `mail.channel`.
|
||||
*
|
||||
@@ -361,6 +360,25 @@ function factory(dependencies) {
|
||||
}, { shadow: true });
|
||||
}
|
||||
|
||||
/**
|
||||
* 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`.
|
||||
*
|
||||
@@ -452,6 +470,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`.
|
||||
*
|
||||
@@ -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],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -700,6 +731,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.
|
||||
*/
|
||||
@@ -867,6 +906,14 @@ function factory(dependencies) {
|
||||
await this.async(() => currentPartnerFollower.remove());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
@@ -921,7 +968,7 @@ function factory(dependencies) {
|
||||
*/
|
||||
unsubscribe() {
|
||||
this.env.messaging.chatWindowManager.closeThread(this);
|
||||
this.update({ isPendingPinned: false });
|
||||
this.unpin();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
@@ -1296,6 +1343,19 @@ function factory(dependencies) {
|
||||
this._currentPartnerLastNotifiedIsTyping = isTyping;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
//----------------------------------------------------------------------
|
||||
@@ -1701,6 +1733,16 @@ function factory(dependencies) {
|
||||
compute: '_computeNeedactionMessages',
|
||||
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.
|
||||
|
||||
@@ -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],
|
||||
|
||||
Reference in New Issue
Block a user