From 418159b716ebca97b1029a6cf86bcb2364212683 Mon Sep 17 00:00:00 2001 From: "Louis Wicket (wil)" Date: Tue, 21 Mar 2023 13:58:31 +0000 Subject: [PATCH] [IMP] mail: sync activities data between tabs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-2714099. closes odoo/odoo#115986 Related: odoo/enterprise#38537 Signed-off-by: Alexandre Kühn (aku) --- .../src/activity/activity_service_patch.js | 2 +- .../activity/activity_markasdone_popover.js | 9 +-- .../src/web/activity/activity_service.js | 61 ++++++++++++++++++- 3 files changed, 62 insertions(+), 10 deletions(-) diff --git a/addons/calendar/static/src/activity/activity_service_patch.js b/addons/calendar/static/src/activity/activity_service_patch.js index d4c1f38740f..5bb8178ce77 100644 --- a/addons/calendar/static/src/activity/activity_service_patch.js +++ b/addons/calendar/static/src/activity/activity_service_patch.js @@ -5,7 +5,7 @@ import { patch } from "@web/core/utils/patch"; patch(ActivityService.prototype, "calendar/activity_service", { insert(data) { - const activity = this._super(data); + const activity = this._super(...arguments); const { calendar_event_id: calendarEventId } = data; if (calendarEventId) { activity["calendar_event_id"] = calendarEventId; diff --git a/addons/mail/static/src/web/activity/activity_markasdone_popover.js b/addons/mail/static/src/web/activity/activity_markasdone_popover.js index 105556c7352..b40a8d4e544 100644 --- a/addons/mail/static/src/web/activity/activity_markasdone_popover.js +++ b/addons/mail/static/src/web/activity/activity_markasdone_popover.js @@ -50,13 +50,8 @@ export class ActivityMarkAsDone extends Component { if (this.props.close) { this.props.close(); } - const action = await this.env.services.orm.call( - "mail.activity", - "action_feedback_schedule_next", - [[this.props.activity.id]], - { - feedback: this.props.activity.feedback, - } + const action = await this.env.services["mail.activity"].markAsDoneAndScheduleNext( + this.props.activity ); this.threadService.fetchNewMessages(thread); if (this.props.reload) { diff --git a/addons/mail/static/src/web/activity/activity_service.js b/addons/mail/static/src/web/activity/activity_service.js index 70d78d96e9c..b11380f7f1e 100644 --- a/addons/mail/static/src/web/activity/activity_service.js +++ b/addons/mail/static/src/web/activity/activity_service.js @@ -7,6 +7,9 @@ import { registry } from "@web/core/registry"; export class ActivityService { constructor(env, services) { + // useful for synchronizing activity data between multiple tabs + this.broadcastChannel = new BroadcastChannel("mail.activity.channel"); + this.broadcastChannel.onmessage = this._onBroadcastChannelMessage.bind(this); this.env = env; /** @type {import("@mail/core/store_service").Store} */ this.store = services["mail.store"]; @@ -22,6 +25,24 @@ export class ActivityService { attachment_ids: attachmentIds, feedback: activity.feedback, }); + this.broadcastChannel.postMessage({ + type: "reload chatter", + payload: { resId: activity.res_id, resModel: activity.res_model }, + }); + } + + async markAsDoneAndScheduleNext(activity) { + const action = await this.env.services.orm.call( + "mail.activity", + "action_feedback_schedule_next", + [[activity.id]], + { feedback: activity.feedback } + ); + this.broadcastChannel.postMessage({ + type: "reload chatter", + payload: { resId: activity.res_id, resModel: activity.res_model }, + }); + return action; } async schedule(resModel, resId, activityId = false, defaultActivityTypeId = undefined) { @@ -51,19 +72,55 @@ export class ActivityService { /** * @param {import("./activity_model").Data} data + * @param {Object} [param1] + * @param {boolean} param1.broadcast * @returns {import("./activity_model").Activity} */ - insert(data) { + insert(data, { broadcast = true } = {}) { const activity = this.store.activities[data.id] ?? new Activity(this.store, data.id); if (data.request_partner_id) { data.request_partner_id = data.request_partner_id[0]; } assignDefined(activity, data); + if (broadcast) { + this.broadcastChannel.postMessage({ + type: "insert", + payload: this._serialize(activity), + }); + } return activity; } - delete(activity) { + delete(activity, { broadcast = true } = {}) { delete this.store.activities[activity.id]; + if (broadcast) { + this.broadcastChannel.postMessage({ type: "delete", payload: { id: activity.id } }); + } + } + + _onBroadcastChannelMessage({ data }) { + switch (data.type) { + case "insert": + this.insert(data.payload, { broadcast: false }); + break; + case "delete": + this.delete(data.payload, { broadcast: false }); + break; + case "reload chatter": { + const thread = this.env.services["mail.thread"].getThread( + data.payload.resModel, + data.payload.resId + ); + this.env.services["mail.thread"].fetchNewMessages(thread); + break; + } + } + } + + _serialize(activity) { + const data = { ...activity }; + delete data._store; + return JSON.parse(JSON.stringify(data)); } }