[IMP] mail: send channel update to the client

Before this PR, channel update were not sent via bus notifications.

Part of task-2821415

closes odoo/odoo#136623

Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
This commit is contained in:
Didier (did)
2023-10-04 19:40:14 +00:00
parent 2129dcb288
commit f29a09d7d3
5 changed files with 93 additions and 35 deletions
+17 -17
View File
@@ -273,11 +273,25 @@ class Channel(models.Model):
failing_channels = self.sudo().filtered(lambda channel: channel.channel_type != vals.get('channel_type'))
if failing_channels:
raise UserError(_('Cannot change the channel type of: %(channel_names)s', channel_names=', '.join(failing_channels.mapped('name'))))
notifications = []
for channel in self:
current_val = channel.read(vals.keys())[0]
diff = {}
for key in vals.keys():
if current_val.get(key) != vals.get(key) and key != "image_128":
diff[key] = vals[key]
if diff:
notifications.append([channel, "mail.record/insert", {
"Thread": {
"id": current_val["id"],
"model": "discuss.channel",
**diff
}
}])
result = super().write(vals)
if vals.get('group_ids'):
self._subscribe_users_automatically()
if 'image_128' in vals:
notifications = []
for channel in self:
notifications.append([channel, 'mail.record/insert', {
'Channel': {
@@ -285,7 +299,7 @@ class Channel(models.Model):
'id': channel.id,
}
}])
self.env['bus.bus']._sendmany(notifications)
self.env['bus.bus']._sendmany(notifications)
return result
def init(self):
@@ -1001,7 +1015,7 @@ class Channel(models.Model):
'foldStateCount': state_count,
'id': session_state.channel_id.id,
'model': 'discuss.channel',
'serverFoldState': state,
'fold_state': state,
}
})
@@ -1112,24 +1126,10 @@ class Channel(models.Model):
def channel_rename(self, name):
self.ensure_one()
self.write({'name': name})
self.env['bus.bus']._sendone(self, 'mail.record/insert', {
'Thread': {
'id': self.id,
'model': 'discuss.channel',
'name': name,
}
})
def channel_change_description(self, description):
self.ensure_one()
self.write({'description': description})
self.env['bus.bus']._sendone(self, 'mail.record/insert', {
'Thread': {
'id': self.id,
'description': description,
'model': 'discuss.channel',
}
})
def channel_join(self):
""" Shortcut to add the current user as member of self channels.
@@ -87,10 +87,10 @@ export class DiscussCoreWeb {
if (payload.Thread) {
const data = payload.Thread;
const thread = this.store.Thread.get(data);
if (data.serverFoldState && thread && data.foldStateCount > thread.foldStateCount) {
if (data.fold_state && thread && data.foldStateCount > thread.foldStateCount) {
thread.foldStateCount = data.foldStateCount;
if (data.serverFoldState !== thread.state) {
thread.state = data.serverFoldState;
if (data.fold_state !== thread.state) {
thread.state = data.fold_state;
if (thread.state === "closed") {
const chatWindow = this.store.discuss.chatWindows.find((chatWindow) =>
chatWindow.thread?.eq(thread)
@@ -7,6 +7,7 @@ import { start } from "@mail/../tests/helpers/test_utils";
import { getOrigin } from "@web/core/utils/urls";
import { click, contains, insertText } from "@web/../tests/utils";
import { triggerHotkey } from "@web/../tests/helpers/utils";
QUnit.module("discuss sidebar");
@@ -1158,3 +1159,21 @@ QUnit.test("Unpinning channel closes its chat window", async () => {
await openFormView("discuss.channel");
await contains(".o-mail-ChatWindow", { count: 0, text: "Sales" });
});
QUnit.test("Update channel data via bus notification", async () => {
const pyEnv = await startServer();
const channelId = pyEnv["discuss.channel"].create({
name: "Sales",
channel_member_ids: [Command.create({ partner_id: pyEnv.currentPartnerId })],
channel_type: "channel",
create_uid: pyEnv.currentUserId,
});
const tab1 = await start({ asTab: true });
const tab2 = await start({ asTab: true });
tab1.openDiscuss(channelId);
tab2.openDiscuss(channelId);
await contains(".o-mail-DiscussSidebarChannel", { text: "Sales", target: tab1.target });
await insertText(".o-mail-Discuss-threadName", "test", { target: tab1.target });
await triggerHotkey("Enter");
await contains(".o-mail-DiscussSidebarChannel", { text: "Salestest", target: tab2.target });
});
@@ -10,6 +10,40 @@ import { Command } from "@mail/../tests/helpers/command";
const { DateTime } = luxon;
patch(MockServer.prototype, {
/**
* @override
*/
mockWrite(model, args) {
const notifications = [];
if (model == "discuss.channel") {
const vals = args[1];
const [channel] = this.getRecords(model, [["id", "=", args[0][0]]]);
if (channel) {
const diff = {};
for (const key in vals) {
if (channel[key] != vals[key] && key !== "image_128") {
diff[key] = vals[key];
}
}
notifications.push([
channel,
"mail.record/insert",
{
Thread: {
id: channel.id,
model: "discuss.channel",
...diff,
},
},
]);
}
}
const mockWriteResult = super.mockWrite(...arguments);
if (notifications.length) {
this.pyEnv["bus.bus"]._sendmany(notifications);
}
return mockWriteResult;
},
async _performRPC(route, args) {
if (args.model === "discuss.channel" && args.method === "execute_command_help") {
return this._mockDiscussChannelExecuteCommandHelp(args.args[0], args.model);
@@ -488,7 +522,7 @@ patch(MockServer.prototype, {
foldStateCount: state_count,
id: channel.id,
model: "discuss.channel",
serverFoldState: foldState,
fold_state: foldState,
},
});
}
@@ -777,24 +811,10 @@ patch(MockServer.prototype, {
_mockDiscussChannelChannelRename(ids, name) {
const channel = this.getRecords("discuss.channel", [["id", "in", ids]])[0];
this.pyEnv["discuss.channel"].write([channel.id], { name });
this.pyEnv["bus.bus"]._sendone(channel, "mail.record/insert", {
Thread: {
id: channel.id,
model: "discuss.channel",
name: name,
},
});
},
_mockDiscussChannelChannelChangeDescription(ids, description) {
const channel = this.getRecords("discuss.channel", [["id", "in", ids]])[0];
this.pyEnv["discuss.channel"].write([channel.id], { description });
this.pyEnv["bus.bus"]._sendone(channel, "mail.record/insert", {
Thread: {
id: channel.id,
model: "discuss.channel",
description: description,
},
});
},
/**
* Simulates `channel_set_custom_name` on `discuss.channel`.
@@ -504,6 +504,25 @@ class TestChannelInternals(MailCommon):
test_channel.image_128 = base64.b64encode(("<svg/>").encode())
self.assertEqual(test_channel.avatar_128, test_channel.image_128)
def test_channel_write_should_send_notification(self):
channel = self.env['discuss.channel'].create({"name": "test", "description": "test"})
# do the operation once before the assert to grab the value to expect
with self.assertBus(
[(self.cr.dbname, 'discuss.channel', channel.id)],
[{
"type": "mail.record/insert",
"payload": {
'Thread': {
"id": channel.id,
"model": "discuss.channel",
"name": "test test",
}
},
}]
):
channel.name = "test test"
channel.description = "test"
def test_channel_write_should_send_notification_if_image_128_changed(self):
channel = self.env['discuss.channel'].create({'name': '', 'uuid': 'test-uuid'})
# do the operation once before the assert to grab the value to expect