From ab900bb62a6c6fecc6940e2ef04c2ccf4986372c Mon Sep 17 00:00:00 2001 From: Martin Geubelle Date: Thu, 16 Nov 2017 13:52:40 +0100 Subject: [PATCH] [FIX] mail: keep model informed of new messages Do not forward-port this after 11.0 After sending a message, if one switched in edit mode in the form view, the created message disappeared. This is because the model is not aware of messages (they are created through their own routes, message are not handled as other one2many fields with commands) and the widget was reset with a new datapoint instance when switching in edit mode. In this rev. we keep the model informed of the new messages by directly writing the message ids in the datapoint. Note that the includes on FormController and BasicModel are one in the form_renderer.js file to fix this issue in existing database without adding files. Another revision will be done in master to add the correct files. opw-781353 --- addons/mail/static/src/js/form_renderer.js | 49 +++++++++++++ addons/mail/static/src/js/thread_field.js | 4 ++ addons/mail/static/tests/chatter_tests.js | 80 ++++++++++++++++++++++ 3 files changed, 133 insertions(+) diff --git a/addons/mail/static/src/js/form_renderer.js b/addons/mail/static/src/js/form_renderer.js index 520827d7695..9d9532e2171 100644 --- a/addons/mail/static/src/js/form_renderer.js +++ b/addons/mail/static/src/js/form_renderer.js @@ -1,7 +1,9 @@ odoo.define('mail.form_renderer', function (require) { "use strict"; +var BasicModel = require('web.BasicModel'); var Chatter = require('mail.Chatter'); +var FormController = require('web.FormController'); var FormRenderer = require('web.FormRenderer'); /** @@ -88,4 +90,51 @@ FormRenderer.include({ }, }); +/** + * Include the FormController and BasicModel to update the datapoint on the + * model when a message is posted. + */ +FormController.include({ + custom_events: _.extend({}, FormController.prototype.custom_events, { + new_message: '_onNewMessage', + }), + + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + + /** + * @private + * @param {OdooEvent} event + * @param {string} event.data.id datapointID + * @param {integer[]} event.data.msgIDs list of message ids + */ + _onNewMessage: function (event) { + this.model.updateMessageIDs(event.data.id, event.data.msgIDs); + }, +}); + +BasicModel.include({ + + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- + + /** + * Update the message ids on a datapoint. + * + * Note that we directly update the res_ids on the datapoint as the message + * has already been posted ; this change can't be handled 'normally' with + * x2m commands because the change won't be saved as a normal field. + * + * @param {string} id + * @param {integer[]} msgIDs + */ + updateMessageIDs: function (id, msgIDs) { + var element = this.localData[id]; + element.res_ids = msgIDs; + element.count = msgIDs.length; + }, +}); + }); diff --git a/addons/mail/static/src/js/thread_field.js b/addons/mail/static/src/js/thread_field.js index 0d7635cae8b..75e379e6ea1 100644 --- a/addons/mail/static/src/js/thread_field.js +++ b/addons/mail/static/src/js/thread_field.js @@ -107,6 +107,10 @@ var ThreadField = AbstractField.extend(chat_mixin, { _onNewMessage: function (message) { if (message.model === this.model && message.res_id === this.res_id) { this.msgIDs.unshift(message.id); + this.trigger_up('new_message', { + id: this.value.id, + msgIDs: this.msgIDs, + }); this._fetchAndRenderThread(this.msgIDs); } }, diff --git a/addons/mail/static/tests/chatter_tests.js b/addons/mail/static/tests/chatter_tests.js index c650f8c10c9..409b729fc78 100644 --- a/addons/mail/static/tests/chatter_tests.js +++ b/addons/mail/static/tests/chatter_tests.js @@ -494,6 +494,86 @@ QUnit.test('chatter: post, receive and star messages', function (assert) { }); }); + +QUnit.test('chatter: post a message and switch in edit mode', function (assert) { + assert.expect(5); + + var messages = []; + var bus = new Bus(); + var form = createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '
' + + '' + + '' + + '' + + '
' + + '' + + '
' + + '
', + res_id: 2, + session: {}, + mockRPC: function (route, args) { + if (route === "/web/dataset/call_kw/partner/message_get_suggested_recipients") { + return $.when({2: []}); + } + return this._super(route, args); + }, + intercepts: { + get_messages: function (event) { + event.stopPropagation(); + var requested_msgs = _.filter(messages, function (msg) { + return _.contains(event.data.options.ids, msg.id); + }); + event.data.callback($.when(requested_msgs)); + }, + post_message: function (event) { + event.stopPropagation(); + messages.push({ + attachment_ids: [], + author_id: ["42", "Me"], + body: event.data.message.content, + date: moment(), // now + displayed_author: "Me", + id: 42, + is_note: event.data.message.subtype === 'mail.mt_note', + is_starred: false, + model: 'partner', + res_id: 2, + }); + bus.trigger('new_message', { + id: 42, + model: event.data.options.model, + res_id: event.data.options.res_id, + }); + }, + get_bus: function (event) { + event.stopPropagation(); + event.data.callback(bus); + }, + }, + }); + + assert.strictEqual(form.$('.o_thread_message').length, 0, "thread should not contain messages"); + + // send a message + form.$('.o_chatter_button_new_message').click(); + form.$('.oe_chatter .o_composer_text_field:first()').val("My first message"); + form.$('.oe_chatter .o_composer_button_send').click(); + assert.strictEqual(form.$('.o_thread_message').length, 1, "thread should contain a message"); + assert.ok(form.$('.o_thread_message:first() .o_thread_message_core').text().indexOf('My first message') >= 0, + "the message's body should be correct"); + + // switch in edit mode + form.$buttons.find('.o_form_button_edit').click(); + assert.strictEqual(form.$('.o_thread_message').length, 1, "thread should contain a message"); + assert.ok(form.$('.o_thread_message:first() .o_thread_message_core').text().indexOf('My first message') >= 0, + "the message's body should be correct"); + + form.destroy(); +}); + QUnit.test('form activity widget: schedule next activity', function (assert) { assert.expect(5); this.data.partner.records[0].activity_ids = [1];