[IMP] mail: sync activities data between tabs

Task-2714099.

closes odoo/odoo#115986

Related: odoo/enterprise#38537
Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
This commit is contained in:
Louis Wicket (wil)
2023-03-31 17:02:30 +02:00
parent 0e9498a345
commit 418159b716
3 changed files with 62 additions and 10 deletions
@@ -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;
@@ -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) {
@@ -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));
}
}