[REF] mail: move imp of service.insert() to Model.insert()
In preparation to clean code of models, e.g. by simplifying model insertion and reducing side-effects in record insertion. This commit moves the implementation of the `insert()` in discuss services to the models, and drop support of the service methods `insert()`. The only way to insert a model is through the store entry, e.g. `store.Thread.insert()`. closes odoo/odoo#133509 Related: odoo/enterprise#46499 Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
/** @odoo-module */
|
||||
|
||||
import { Activity } from "@mail/core/web/activity_model";
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
|
||||
patch(Activity, {
|
||||
insert(data) {
|
||||
const activity = super.insert(...arguments);
|
||||
const { calendar_event_id: calendarEventId } = data;
|
||||
if (calendarEventId) {
|
||||
activity["calendar_event_id"] = calendarEventId;
|
||||
}
|
||||
return activity;
|
||||
},
|
||||
});
|
||||
@@ -4,15 +4,6 @@ import { ActivityService } from "@mail/core/web/activity_service";
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
|
||||
patch(ActivityService.prototype, {
|
||||
insert(data) {
|
||||
const activity = super.insert(...arguments);
|
||||
const { calendar_event_id: calendarEventId } = data;
|
||||
if (calendarEventId) {
|
||||
activity["calendar_event_id"] = calendarEventId;
|
||||
}
|
||||
return activity;
|
||||
},
|
||||
|
||||
async rescheduleMeeting(activityId) {
|
||||
const action = await this.orm.call("mail.activity", "action_create_calendar_event", [
|
||||
[activityId],
|
||||
|
||||
@@ -2,9 +2,34 @@
|
||||
|
||||
import { DEFAULT_AVATAR } from "@mail/core/common/persona_service";
|
||||
import { Thread } from "@mail/core/common/thread_model";
|
||||
import { assignDefined, createLocalId } from "@mail/utils/common/misc";
|
||||
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
|
||||
patch(Thread, {
|
||||
insert(data) {
|
||||
const isUnknown = !(createLocalId(data.model, data.id) in this.records);
|
||||
const thread = super.insert(data);
|
||||
if (thread.type === "livechat") {
|
||||
if (data?.channel) {
|
||||
assignDefined(thread, data.channel, ["anonymous_name"]);
|
||||
}
|
||||
if (data?.operator_pid) {
|
||||
thread.operator = this.store.Persona.insert({
|
||||
type: "partner",
|
||||
id: data.operator_pid[0],
|
||||
displayName: data.operator_pid[1],
|
||||
});
|
||||
}
|
||||
if (isUnknown) {
|
||||
this.store.discuss.livechat.threads.push(thread.localId);
|
||||
this.env.services["mail.thread"].sortChannels();
|
||||
}
|
||||
}
|
||||
return thread;
|
||||
},
|
||||
});
|
||||
|
||||
patch(Thread.prototype, {
|
||||
get isChannel() {
|
||||
return this.type === "livechat" || super.isChannel;
|
||||
|
||||
@@ -2,32 +2,10 @@
|
||||
|
||||
import { ThreadService } from "@mail/core/common/thread_service";
|
||||
import { removeFromArray } from "@mail/utils/common/arrays";
|
||||
import { assignDefined, createLocalId } from "@mail/utils/common/misc";
|
||||
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
|
||||
patch(ThreadService.prototype, {
|
||||
insert(data) {
|
||||
const isUnknown = !(createLocalId(data.model, data.id) in this.store.Thread.records);
|
||||
const thread = super.insert(data);
|
||||
if (thread.type === "livechat") {
|
||||
if (data?.channel) {
|
||||
assignDefined(thread, data.channel, ["anonymous_name"]);
|
||||
}
|
||||
if (data?.operator_pid) {
|
||||
thread.operator = this.store.Persona.insert({
|
||||
type: "partner",
|
||||
id: data.operator_pid[0],
|
||||
displayName: data.operator_pid[1],
|
||||
});
|
||||
}
|
||||
if (isUnknown) {
|
||||
this.store.discuss.livechat.threads.push(thread.localId);
|
||||
this.sortChannels();
|
||||
}
|
||||
}
|
||||
return thread;
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
* @param {import("@mail/core/common/thread_model").Thread} thread
|
||||
|
||||
@@ -1,10 +1,22 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { ChatbotStep } from "@im_livechat/embed/chatbot/chatbot_step_model";
|
||||
|
||||
import { Message } from "@mail/core/common/message_model";
|
||||
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
import { session } from "@web/session";
|
||||
|
||||
patch(Message, {
|
||||
insert(data) {
|
||||
const message = super.insert(data);
|
||||
if (data.chatbotStep) {
|
||||
message.chatbotStep = new ChatbotStep(data.chatbotStep);
|
||||
}
|
||||
return message;
|
||||
},
|
||||
});
|
||||
|
||||
patch(Message.prototype, {
|
||||
get isSelfAuthored() {
|
||||
if (this.originThread.type !== "livechat") {
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { ChatbotStep } from "@im_livechat/embed/chatbot/chatbot_step_model";
|
||||
|
||||
import { MessageService } from "@mail/core/common/message_service";
|
||||
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
|
||||
patch(MessageService.prototype, {
|
||||
insert(data) {
|
||||
const message = super.insert(data);
|
||||
if (data.chatbotStep) {
|
||||
message.chatbotStep = new ChatbotStep(data.chatbotStep);
|
||||
}
|
||||
return message;
|
||||
},
|
||||
});
|
||||
@@ -1,9 +1,63 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { Thread } from "@mail/core/common/thread_model";
|
||||
import { createLocalId, onChange } from "@mail/utils/common/misc";
|
||||
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
import { session } from "@web/session";
|
||||
import { SESSION_STATE } from "./livechat_service";
|
||||
|
||||
patch(Thread, {
|
||||
insert(data) {
|
||||
const isUnknown = !(createLocalId(data.model, data.id) in this.records);
|
||||
const thread = super.insert(...arguments);
|
||||
const livechatService = this.env.services["im_livechat.livechat"];
|
||||
const chatbotService = this.env.services["im_livechat.chatbot"];
|
||||
const messageService = this.env.services["mail.message"];
|
||||
if (thread.type === "livechat" && isUnknown) {
|
||||
if (livechatService.displayWelcomeMessage && !chatbotService.isChatbotThread(thread)) {
|
||||
livechatService.welcomeMessage = this.store.Message.insert({
|
||||
id: messageService.getNextTemporaryId(),
|
||||
body: livechatService.options.default_message,
|
||||
res_id: thread.id,
|
||||
model: thread.model,
|
||||
author: thread.operator,
|
||||
});
|
||||
}
|
||||
if (chatbotService.isChatbotThread(thread)) {
|
||||
chatbotService.typingMessage = this.store.Message.insert({
|
||||
id: messageService.getNextTemporaryId(),
|
||||
res_id: thread.id,
|
||||
model: thread.model,
|
||||
author: thread.operator,
|
||||
});
|
||||
}
|
||||
onChange(thread, "state", () => {
|
||||
if (![SESSION_STATE.CLOSED, SESSION_STATE.NONE].includes(livechatService.state)) {
|
||||
livechatService.updateSession({
|
||||
state: thread.state,
|
||||
});
|
||||
}
|
||||
});
|
||||
onChange(thread, "seen_message_id", () => {
|
||||
if (![SESSION_STATE.CLOSED, SESSION_STATE.NONE].includes(livechatService.state)) {
|
||||
livechatService.updateSession({
|
||||
seen_message_id: thread.seen_message_id,
|
||||
});
|
||||
}
|
||||
});
|
||||
onChange(thread, "message_unread_counter", () => {
|
||||
if (![SESSION_STATE.CLOSED, SESSION_STATE.NONE].includes(livechatService.state)) {
|
||||
livechatService.updateSession({
|
||||
channel: thread.channel,
|
||||
});
|
||||
}
|
||||
});
|
||||
this.store.livechatThread = thread;
|
||||
}
|
||||
return thread;
|
||||
},
|
||||
});
|
||||
|
||||
patch(Thread.prototype, {
|
||||
chatbotScriptId: null,
|
||||
|
||||
@@ -4,7 +4,6 @@ import { SESSION_STATE } from "@im_livechat/embed/core/livechat_service";
|
||||
|
||||
import { ThreadService, threadService } from "@mail/core/common/thread_service";
|
||||
import { prettifyMessageContent } from "@mail/utils/common/format";
|
||||
import { createLocalId, onChange } from "@mail/utils/common/misc";
|
||||
|
||||
import { markup } from "@odoo/owl";
|
||||
|
||||
@@ -110,56 +109,6 @@ patch(ThreadService.prototype, {
|
||||
}
|
||||
},
|
||||
|
||||
insert(data) {
|
||||
const isUnknown = !(createLocalId(data.model, data.id) in this.store.Thread.records);
|
||||
const thread = super.insert(...arguments);
|
||||
if (thread.type === "livechat" && isUnknown) {
|
||||
if (
|
||||
this.livechatService.displayWelcomeMessage &&
|
||||
!this.chatbotService.isChatbotThread(thread)
|
||||
) {
|
||||
this.livechatService.welcomeMessage = this.store.Message.insert({
|
||||
id: this.messageService.getNextTemporaryId(),
|
||||
body: this.livechatService.options.default_message,
|
||||
res_id: thread.id,
|
||||
model: thread.model,
|
||||
author: thread.operator,
|
||||
});
|
||||
}
|
||||
if (this.chatbotService.isChatbotThread(thread)) {
|
||||
this.chatbotService.typingMessage = this.store.Message.insert({
|
||||
id: this.messageService.getNextTemporaryId(),
|
||||
res_id: thread.id,
|
||||
model: thread.model,
|
||||
author: thread.operator,
|
||||
});
|
||||
}
|
||||
onChange(thread, "state", () => {
|
||||
if (
|
||||
![SESSION_STATE.CLOSED, SESSION_STATE.NONE].includes(this.livechatService.state)
|
||||
) {
|
||||
this.livechatService.updateSession({ state: thread.state });
|
||||
}
|
||||
});
|
||||
onChange(thread, "seen_message_id", () => {
|
||||
if (
|
||||
![SESSION_STATE.CLOSED, SESSION_STATE.NONE].includes(this.livechatService.state)
|
||||
) {
|
||||
this.livechatService.updateSession({ seen_message_id: thread.seen_message_id });
|
||||
}
|
||||
});
|
||||
onChange(thread, "message_unread_counter", () => {
|
||||
if (
|
||||
![SESSION_STATE.CLOSED, SESSION_STATE.NONE].includes(this.livechatService.state)
|
||||
) {
|
||||
this.livechatService.updateSession({ channel: thread.channel });
|
||||
}
|
||||
});
|
||||
this.store.livechatThread = thread;
|
||||
}
|
||||
return thread;
|
||||
},
|
||||
|
||||
async update(thread, data) {
|
||||
super.update(...arguments);
|
||||
if (data.operator_pid) {
|
||||
|
||||
@@ -1,12 +1,33 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { Record } from "@mail/core/common/record";
|
||||
import { Record, modelRegistry } from "@mail/core/common/record";
|
||||
import { assignDefined } from "@mail/utils/common/misc";
|
||||
|
||||
import { deserializeDateTime } from "@web/core/l10n/dates";
|
||||
import { url } from "@web/core/utils/urls";
|
||||
|
||||
export class Attachment extends Record {
|
||||
/** @type {Object.<number, Attachment>} */
|
||||
static records = {};
|
||||
|
||||
/**
|
||||
* @param {Object} data
|
||||
* @returns {Attachment}
|
||||
*/
|
||||
static insert(data) {
|
||||
if (!("id" in data)) {
|
||||
throw new Error("Cannot insert attachment: id is missing in data");
|
||||
}
|
||||
let attachment = this.records[data.id];
|
||||
if (!attachment) {
|
||||
this.records[data.id] = new Attachment();
|
||||
attachment = this.records[data.id];
|
||||
Object.assign(attachment, { _store: this.store, id: data.id });
|
||||
}
|
||||
this.env.services["mail.attachment"].update(attachment, data);
|
||||
return attachment;
|
||||
}
|
||||
|
||||
/** @type {import("@mail/core/common/store_service").Store} */
|
||||
_store;
|
||||
accessToken;
|
||||
@@ -151,3 +172,5 @@ export class Attachment extends Record {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
modelRegistry.add(Attachment.name, Attachment);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { Attachment } from "@mail/core/common/attachment_model";
|
||||
import { removeFromArrayWithPredicate } from "@mail/utils/common/arrays";
|
||||
import { assignDefined, createLocalId } from "@mail/utils/common/misc";
|
||||
|
||||
@@ -21,20 +20,6 @@ export class AttachmentService {
|
||||
this.rpc = services["rpc"];
|
||||
}
|
||||
|
||||
insert(data) {
|
||||
if (!("id" in data)) {
|
||||
throw new Error("Cannot insert attachment: id is missing in data");
|
||||
}
|
||||
let attachment = this.store.Attachment.records[data.id];
|
||||
if (!attachment) {
|
||||
this.store.Attachment.records[data.id] = new Attachment();
|
||||
attachment = this.store.Attachment.records[data.id];
|
||||
Object.assign(attachment, { _store: this.store, id: data.id });
|
||||
}
|
||||
this.update(attachment, data);
|
||||
return attachment;
|
||||
}
|
||||
|
||||
update(attachment, data) {
|
||||
assignDefined(attachment, data, [
|
||||
"checksum",
|
||||
|
||||
@@ -1,8 +1,28 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { Record } from "@mail/core/common/record";
|
||||
import { Record, modelRegistry } from "@mail/core/common/record";
|
||||
|
||||
export class CannedResponse extends Record {
|
||||
/** @type {Object.<number, CannedResponse>} */
|
||||
static records = {};
|
||||
/**
|
||||
* @param {Object} data
|
||||
* @returns {CannedResponse}
|
||||
*/
|
||||
static insert(data) {
|
||||
let cannedResponse = this.records[data.id];
|
||||
if (!cannedResponse) {
|
||||
this.records[data.id] = new CannedResponse();
|
||||
cannedResponse = this.records[data.id];
|
||||
}
|
||||
Object.assign(cannedResponse, {
|
||||
id: data.id,
|
||||
name: data.source,
|
||||
substitution: data.substitution,
|
||||
});
|
||||
return cannedResponse;
|
||||
}
|
||||
|
||||
/** @type {number} */
|
||||
id;
|
||||
/** @type {string} */
|
||||
@@ -10,3 +30,5 @@ export class CannedResponse extends Record {
|
||||
/** @type {string} */
|
||||
substitution;
|
||||
}
|
||||
|
||||
modelRegistry.add(CannedResponse.name, CannedResponse);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { Record } from "@mail/core/common/record";
|
||||
import { Record, modelRegistry } from "@mail/core/common/record";
|
||||
import { createLocalId } from "@mail/utils/common/misc";
|
||||
|
||||
/**
|
||||
@@ -11,6 +11,24 @@ import { createLocalId } from "@mail/utils/common/misc";
|
||||
* @property {number} threadId
|
||||
*/
|
||||
export class ChannelMember extends Record {
|
||||
/** @type {Object.<number, ChannelMember>} */
|
||||
static records = {};
|
||||
/**
|
||||
* @param {Object|Array} data
|
||||
* @returns {ChannelMember}
|
||||
*/
|
||||
static insert(data) {
|
||||
const memberData = Array.isArray(data) ? data[1] : data;
|
||||
let member = this.records[memberData.id];
|
||||
if (!member) {
|
||||
this.records[memberData.id] = new ChannelMember();
|
||||
member = this.records[memberData.id];
|
||||
member._store = this.store;
|
||||
}
|
||||
this.env.services["discuss.channel.member"].update(member, data);
|
||||
return member;
|
||||
}
|
||||
|
||||
/** @type {number} */
|
||||
id;
|
||||
personaLocalId;
|
||||
@@ -42,3 +60,5 @@ export class ChannelMember extends Record {
|
||||
return this.persona.lang_name;
|
||||
}
|
||||
}
|
||||
|
||||
modelRegistry.add(ChannelMember.name, ChannelMember);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { ChannelMember } from "@mail/core/common/channel_member_model";
|
||||
import { removeFromArray } from "@mail/utils/common/arrays";
|
||||
|
||||
import { registry } from "@web/core/registry";
|
||||
@@ -15,22 +14,6 @@ export class ChannelMemberService {
|
||||
this.store = services["mail.store"];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object|Array} data
|
||||
* @returns {ChannelMember}
|
||||
*/
|
||||
insert(data) {
|
||||
const memberData = Array.isArray(data) ? data[1] : data;
|
||||
let member = this.store.ChannelMember.records[memberData.id];
|
||||
if (!member) {
|
||||
this.store.ChannelMember.records[memberData.id] = new ChannelMember();
|
||||
member = this.store.ChannelMember.records[memberData.id];
|
||||
member._store = this.store;
|
||||
}
|
||||
this.update(member, data);
|
||||
return member;
|
||||
}
|
||||
|
||||
update(member, data) {
|
||||
const [command, memberData] = Array.isArray(data) ? data : ["insert", data];
|
||||
member.id = memberData.id;
|
||||
|
||||
@@ -1,12 +1,52 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { Record } from "@mail/core/common/record";
|
||||
import { Record, modelRegistry } from "@mail/core/common/record";
|
||||
import { assignDefined } from "@mail/utils/common/misc";
|
||||
|
||||
import { _t } from "@web/core/l10n/translation";
|
||||
|
||||
/** @typedef {{ thread?: import("@mail/core/common/thread_model").Thread, folded?: boolean, replaceNewMessageChatWindow?: boolean }} ChatWindowData */
|
||||
|
||||
export class ChatWindow extends Record {
|
||||
/** @type {ChatWindow[]} */
|
||||
static records = [];
|
||||
/**
|
||||
* @param {ChatWindowData} [data]
|
||||
* @returns {ChatWindow}
|
||||
*/
|
||||
static insert(data = {}) {
|
||||
const chatWindow = this.records.find((c) => c.threadLocalId === data.thread?.localId);
|
||||
if (!chatWindow) {
|
||||
const chatWindow = new ChatWindow(this.store, data);
|
||||
assignDefined(chatWindow, data);
|
||||
let index;
|
||||
const visible = this.env.services["mail.chat_window"].visible;
|
||||
const maxVisible = this.env.services["mail.chat_window"].maxVisible;
|
||||
if (!data.replaceNewMessageChatWindow) {
|
||||
if (maxVisible <= this.records.length) {
|
||||
const swaped = visible[visible.length - 1];
|
||||
index = visible.length - 1;
|
||||
this.env.services["mail.chat_window"].hide(swaped);
|
||||
} else {
|
||||
index = this.records.length;
|
||||
}
|
||||
} else {
|
||||
const newMessageChatWindowIndex = this.records.findIndex((cw) => !cw.thread);
|
||||
index =
|
||||
newMessageChatWindowIndex !== -1
|
||||
? newMessageChatWindowIndex
|
||||
: this.records.length;
|
||||
}
|
||||
this.records.splice(index, data.replaceNewMessageChatWindow ? 1 : 0, chatWindow);
|
||||
return this.records[index]; // return reactive version
|
||||
}
|
||||
if (chatWindow.hidden) {
|
||||
this.env.services["mail.chat_window"].makeVisible(chatWindow);
|
||||
}
|
||||
assignDefined(chatWindow, data);
|
||||
return chatWindow;
|
||||
}
|
||||
|
||||
/** @type {import("@mail/core/common/store_service").Store} */
|
||||
_store;
|
||||
|
||||
@@ -45,3 +85,5 @@ export class ChatWindow extends Record {
|
||||
return !this.folded && !this.hidden;
|
||||
}
|
||||
}
|
||||
|
||||
modelRegistry.add(ChatWindow.name, ChatWindow);
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { ChatWindow } from "@mail/core/common/chat_window_model";
|
||||
import { assignDefined } from "@mail/utils/common/misc";
|
||||
|
||||
import { browser } from "@web/core/browser/browser";
|
||||
import { registry } from "@web/core/registry";
|
||||
|
||||
@@ -82,49 +79,6 @@ export class ChatWindowService {
|
||||
return maxAmountWithoutHidden;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ChatWindowData} [data]
|
||||
* @returns {ChatWindow}
|
||||
*/
|
||||
insert(data = {}) {
|
||||
const chatWindow = this.store.ChatWindow.records.find(
|
||||
(c) => c.threadLocalId === data.thread?.localId
|
||||
);
|
||||
if (!chatWindow) {
|
||||
const chatWindow = new ChatWindow(this.store, data);
|
||||
assignDefined(chatWindow, data);
|
||||
let index;
|
||||
if (!data.replaceNewMessageChatWindow) {
|
||||
if (this.maxVisible <= this.store.ChatWindow.records.length) {
|
||||
const swaped = this.visible[this.visible.length - 1];
|
||||
index = this.visible.length - 1;
|
||||
this.hide(swaped);
|
||||
} else {
|
||||
index = this.store.ChatWindow.records.length;
|
||||
}
|
||||
} else {
|
||||
const newMessageChatWindowIndex = this.store.ChatWindow.records.findIndex(
|
||||
(chatWindow) => !chatWindow.thread
|
||||
);
|
||||
index =
|
||||
newMessageChatWindowIndex !== -1
|
||||
? newMessageChatWindowIndex
|
||||
: this.store.ChatWindow.records.length;
|
||||
}
|
||||
this.store.ChatWindow.records.splice(
|
||||
index,
|
||||
data.replaceNewMessageChatWindow ? 1 : 0,
|
||||
chatWindow
|
||||
);
|
||||
return this.store.ChatWindow.records[index]; // return reactive version
|
||||
}
|
||||
if (chatWindow.hidden) {
|
||||
this.makeVisible(chatWindow);
|
||||
}
|
||||
assignDefined(chatWindow, data);
|
||||
return chatWindow;
|
||||
}
|
||||
|
||||
focus(chatWindow) {
|
||||
chatWindow.autofocus++;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { Record } from "@mail/core/common/record";
|
||||
import { Record, modelRegistry } from "@mail/core/common/record";
|
||||
|
||||
/**
|
||||
* @typedef Data
|
||||
@@ -11,6 +11,28 @@ import { Record } from "@mail/core/common/record";
|
||||
*/
|
||||
|
||||
export class Follower extends Record {
|
||||
/** @type {Object.<number, Follower>} */
|
||||
static records = {};
|
||||
/**
|
||||
* @param {Data} data
|
||||
* @returns {Follower}
|
||||
*/
|
||||
static insert(data) {
|
||||
let follower = this.records[data.id];
|
||||
if (!follower) {
|
||||
this.records[data.id] = new Follower();
|
||||
follower = this.records[data.id];
|
||||
}
|
||||
Object.assign(follower, {
|
||||
followedThread: data.followedThread,
|
||||
id: data.id,
|
||||
isActive: data.is_active,
|
||||
partner: this.store.Persona.insert({ ...data.partner, type: "partner" }),
|
||||
_store: this.store,
|
||||
});
|
||||
return follower;
|
||||
}
|
||||
|
||||
/** @type {import("@mail/core/common/thread_model").Thread} */
|
||||
followedThread;
|
||||
/** @type {number} */
|
||||
@@ -32,3 +54,5 @@ export class Follower extends Record {
|
||||
: hasWriteAccess;
|
||||
}
|
||||
}
|
||||
|
||||
modelRegistry.add(Follower.name, Follower);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { Record } from "@mail/core/common/record";
|
||||
import { Record, modelRegistry } from "@mail/core/common/record";
|
||||
import { htmlToTextContentInline } from "@mail/utils/common/format";
|
||||
import { createLocalId } from "@mail/utils/common/misc";
|
||||
|
||||
@@ -14,6 +14,33 @@ import { url } from "@web/core/utils/urls";
|
||||
const { DateTime } = luxon;
|
||||
|
||||
export class Message extends Record {
|
||||
/** @type {Object.<number, Message>} */
|
||||
static records = {};
|
||||
/**
|
||||
* @param {Object} data
|
||||
* @returns {Message}
|
||||
*/
|
||||
static insert(data) {
|
||||
let message;
|
||||
if (data.res_id) {
|
||||
this.store.Thread.insert({
|
||||
model: data.model,
|
||||
id: data.res_id,
|
||||
});
|
||||
}
|
||||
if (data.id in this.records) {
|
||||
message = this.records[data.id];
|
||||
} else {
|
||||
message = new Message();
|
||||
message._store = this.store;
|
||||
this.records[data.id] = message;
|
||||
message = this.records[data.id];
|
||||
}
|
||||
this.env.services["mail.message"].update(message, data);
|
||||
// return reactive version
|
||||
return message;
|
||||
}
|
||||
|
||||
/** @type {Object[]} */
|
||||
attachments = [];
|
||||
/** @type {import("@mail/core/common/persona_model").Persona} */
|
||||
@@ -243,3 +270,5 @@ export class Message extends Record {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
modelRegistry.add(Message.name, Message);
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { LinkPreview } from "@mail/core/common/link_preview_model";
|
||||
import { Message } from "@mail/core/common/message_model";
|
||||
import { MessageReactions } from "@mail/core/common/message_reactions_model";
|
||||
import { NotificationGroup } from "@mail/core/common/notification_group_model";
|
||||
import { Notification } from "@mail/core/common/notification_model";
|
||||
import { removeFromArrayWithPredicate, replaceArrayWithCompare } from "@mail/utils/common/arrays";
|
||||
import { convertBrToLineBreak, prettifyMessageContent } from "@mail/utils/common/format";
|
||||
import { assignDefined, createLocalId } from "@mail/utils/common/misc";
|
||||
@@ -207,31 +204,6 @@ export class MessageService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} data
|
||||
* @returns {Message}
|
||||
*/
|
||||
insert(data) {
|
||||
let message;
|
||||
if (data.res_id) {
|
||||
this.store.Thread.insert({
|
||||
model: data.model,
|
||||
id: data.res_id,
|
||||
});
|
||||
}
|
||||
if (data.id in this.store.Message.records) {
|
||||
message = this.store.Message.records[data.id];
|
||||
} else {
|
||||
message = new Message();
|
||||
message._store = this.store;
|
||||
this.store.Message.records[data.id] = message;
|
||||
message = this.store.Message.records[data.id];
|
||||
}
|
||||
this.update(message, data);
|
||||
// return reactive version
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("@mail/core/common/message_model").Message} message
|
||||
* @param {Object} data
|
||||
@@ -426,20 +398,6 @@ export class MessageService {
|
||||
return reaction;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} data
|
||||
* @returns {Notification}
|
||||
*/
|
||||
insertNotification(data) {
|
||||
let notification = this.store.Notification.records[data.id];
|
||||
if (!notification) {
|
||||
this.store.Notification.records[data.id] = new Notification(this.store, data);
|
||||
notification = this.store.Notification.records[data.id];
|
||||
}
|
||||
this.updateNotification(notification, data);
|
||||
return notification;
|
||||
}
|
||||
|
||||
updateNotification(notification, data) {
|
||||
Object.assign(notification, {
|
||||
messageId: data.messageId,
|
||||
@@ -470,26 +428,6 @@ export class MessageService {
|
||||
});
|
||||
}
|
||||
|
||||
insertNotificationGroups(data) {
|
||||
let group = this.store.NotificationGroup.records.find((group) => {
|
||||
return (
|
||||
group.resModel === data.resModel &&
|
||||
group.type === data.type &&
|
||||
(group.resModel !== "discuss.channel" || group.resIds.has(data.resId))
|
||||
);
|
||||
});
|
||||
if (!group) {
|
||||
group = new NotificationGroup(this.store);
|
||||
}
|
||||
this.updateNotificationGroup(group, data);
|
||||
if (group.notifications.length === 0) {
|
||||
removeFromArrayWithPredicate(this.store.NotificationGroup.records, (gr) =>
|
||||
gr.eq(group)
|
||||
);
|
||||
}
|
||||
return group;
|
||||
}
|
||||
|
||||
updateNotificationGroup(group, data) {
|
||||
Object.assign(group, {
|
||||
modelName: data.modelName ?? group.modelName,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { CannedResponse } from "@mail/core/common/canned_response_model";
|
||||
import { cleanTerm } from "@mail/utils/common/format";
|
||||
|
||||
import { reactive } from "@odoo/owl";
|
||||
@@ -157,20 +156,6 @@ export class Messaging {
|
||||
res_id: id,
|
||||
});
|
||||
}
|
||||
|
||||
insertCannedResponse(data) {
|
||||
let cannedResponse = this.store.CannedResponse.records[data.id];
|
||||
if (!cannedResponse) {
|
||||
this.store.CannedResponse.records[data.id] = new CannedResponse();
|
||||
cannedResponse = this.store.CannedResponse.records[data.id];
|
||||
}
|
||||
Object.assign(cannedResponse, {
|
||||
id: data.id,
|
||||
name: data.source,
|
||||
substitution: data.substitution,
|
||||
});
|
||||
return cannedResponse;
|
||||
}
|
||||
}
|
||||
|
||||
export const messagingService = {
|
||||
|
||||
@@ -1,11 +1,36 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { Record } from "@mail/core/common/record";
|
||||
import { Record, modelRegistry } from "@mail/core/common/record";
|
||||
import { removeFromArrayWithPredicate } from "@mail/utils/common/arrays";
|
||||
|
||||
import { _t } from "@web/core/l10n/translation";
|
||||
|
||||
let nextId = 1;
|
||||
export class NotificationGroup extends Record {
|
||||
/** @type {NotificationGroup[]} */
|
||||
static records = [];
|
||||
/**
|
||||
* @param {Object} data
|
||||
* @returns {NotificationGroup}
|
||||
*/
|
||||
static insert(data) {
|
||||
let group = this.records.find((group) => {
|
||||
return (
|
||||
group.resModel === data.resModel &&
|
||||
group.type === data.type &&
|
||||
(group.resModel !== "discuss.channel" || group.resIds.has(data.resId))
|
||||
);
|
||||
});
|
||||
if (!group) {
|
||||
group = new NotificationGroup(this.store);
|
||||
}
|
||||
this.env.services["mail.message"].updateNotificationGroup(group, data);
|
||||
if (group.notifications.length === 0) {
|
||||
removeFromArrayWithPredicate(this.records, (gr) => gr.eq(group));
|
||||
}
|
||||
return group;
|
||||
}
|
||||
|
||||
/** @type {import("@mail/core/common/notification_model").Notification[]} */
|
||||
notifications = [];
|
||||
/** @type {string} */
|
||||
@@ -46,3 +71,5 @@ export class NotificationGroup extends Record {
|
||||
return this.lastMessage?.datetime;
|
||||
}
|
||||
}
|
||||
|
||||
modelRegistry.add(NotificationGroup.name, NotificationGroup);
|
||||
|
||||
@@ -1,10 +1,26 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { Record } from "@mail/core/common/record";
|
||||
import { Record, modelRegistry } from "@mail/core/common/record";
|
||||
|
||||
import { _t } from "@web/core/l10n/translation";
|
||||
|
||||
export class Notification extends Record {
|
||||
/** @type {Object.<number, Notification>} */
|
||||
static records = {};
|
||||
/**
|
||||
* @param {Object} data
|
||||
* @returns {Notification}
|
||||
*/
|
||||
static insert(data) {
|
||||
let notification = this.records[data.id];
|
||||
if (!notification) {
|
||||
this.records[data.id] = new Notification(this.store, data);
|
||||
notification = this.records[data.id];
|
||||
}
|
||||
this.env.services["mail.message"].updateNotification(notification, data);
|
||||
return notification;
|
||||
}
|
||||
|
||||
/** @type {number} */
|
||||
id;
|
||||
/** @type {number} */
|
||||
@@ -79,3 +95,5 @@ export class Notification extends Record {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
modelRegistry.add(Notification.name, Notification);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { Record } from "@mail/core/common/record";
|
||||
import { Record, modelRegistry } from "@mail/core/common/record";
|
||||
import { createLocalId } from "@mail/utils/common/misc";
|
||||
|
||||
/**
|
||||
* @typedef {'offline' | 'bot' | 'online' | 'away' | 'im_partner' | undefined} ImStatus
|
||||
@@ -13,6 +14,26 @@ import { Record } from "@mail/core/common/record";
|
||||
*/
|
||||
|
||||
export class Persona extends Record {
|
||||
/** @type {Object.<number, Persona>} */
|
||||
static records = {};
|
||||
/**
|
||||
* @param {Data} data
|
||||
* @returns {Persona}
|
||||
*/
|
||||
static insert(data) {
|
||||
const localId = createLocalId(data.type, data.id);
|
||||
let persona = this.records[localId];
|
||||
if (!persona) {
|
||||
persona = new Persona();
|
||||
persona._store = this.store;
|
||||
persona.localId = localId;
|
||||
this.records[localId] = persona;
|
||||
}
|
||||
this.env.services["mail.persona"].update(persona, data);
|
||||
// return reactive version
|
||||
return this.records[localId];
|
||||
}
|
||||
|
||||
/** @type {string} */
|
||||
localId;
|
||||
/** @type {number} */
|
||||
@@ -45,3 +66,5 @@ export class Persona extends Record {
|
||||
return this.email.substring(0, this.email.lastIndexOf("@"));
|
||||
}
|
||||
}
|
||||
|
||||
modelRegistry.add(Persona.name, Persona);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { Persona } from "@mail/core/common/persona_model";
|
||||
import { assignDefined, createLocalId, nullifyClearCommands } from "@mail/utils/common/misc";
|
||||
import { assignDefined, nullifyClearCommands } from "@mail/utils/common/misc";
|
||||
|
||||
import { registry } from "@web/core/registry";
|
||||
import { useSequential } from "@mail/utils/common/hooks";
|
||||
@@ -39,24 +38,6 @@ export class PersonaService {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("@mail/core/common/persona_model").Data} data
|
||||
* @returns {import("@mail/core/common/persona_model").Persona}
|
||||
*/
|
||||
insert(data) {
|
||||
const localId = createLocalId(data.type, data.id);
|
||||
let persona = this.store.Persona.records[localId];
|
||||
if (!persona) {
|
||||
persona = new Persona();
|
||||
persona._store = this.store;
|
||||
persona.localId = localId;
|
||||
this.store.Persona.records[localId] = persona;
|
||||
}
|
||||
this.update(persona, data);
|
||||
// return reactive version
|
||||
return this.store.Persona.records[localId];
|
||||
}
|
||||
|
||||
update(persona, data) {
|
||||
nullifyClearCommands(data);
|
||||
assignDefined(persona, { ...data });
|
||||
@@ -96,13 +77,13 @@ export class PersonaService {
|
||||
}
|
||||
);
|
||||
for (const { id, is_company } of partnerData) {
|
||||
this.insert({ id, is_company, type: "partner" });
|
||||
this.store.Persona.insert({ id, is_company, type: "partner" });
|
||||
ongoing.delete(id);
|
||||
this._sQueue.todo.delete(id);
|
||||
}
|
||||
for (const id of ongoing) {
|
||||
// no is_company found => assumes persona is not a company
|
||||
this.insert({ id, is_company: false, type: "partner" });
|
||||
this.store.Persona.insert({ id, is_company: false, type: "partner" });
|
||||
this._sQueue.todo.delete(id);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,8 +1,19 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { toRaw } from "@odoo/owl";
|
||||
import { registry } from "@web/core/registry";
|
||||
|
||||
export const modelRegistry = registry.category("discuss.model");
|
||||
|
||||
export class Record {
|
||||
static records = {};
|
||||
|
||||
/**
|
||||
* @param {Object} data
|
||||
* @returns {Record}
|
||||
*/
|
||||
static insert(data) {}
|
||||
|
||||
/** @param {Record} record */
|
||||
eq(record) {
|
||||
return toRaw(this) === toRaw(record);
|
||||
@@ -23,3 +34,5 @@ export class Record {
|
||||
return !this.in(list);
|
||||
}
|
||||
}
|
||||
|
||||
modelRegistry.add(Record.name, Record);
|
||||
|
||||
@@ -7,119 +7,33 @@ import { reactive } from "@odoo/owl";
|
||||
import { _t } from "@web/core/l10n/translation";
|
||||
import { registry } from "@web/core/registry";
|
||||
import { debounce } from "@web/core/utils/timing";
|
||||
import { modelRegistry } from "./record";
|
||||
|
||||
export class Store {
|
||||
Activity = {
|
||||
/** @type {Object.<number, import("@mail/core/web/activity_model").Activity>} */
|
||||
records: {},
|
||||
/**
|
||||
* @param {import("@mail/core/web/activity_model").Data} data
|
||||
* @param {Object} [param1]
|
||||
* @param {boolean} param1.broadcast
|
||||
* @returns {import("@mail/core/web/activity_model").Activity}
|
||||
*/
|
||||
insert: (data, { broadcast = true } = {}) =>
|
||||
this.env.services["mail.activity"].insert(data, { broadcast }),
|
||||
};
|
||||
Attachment = {
|
||||
/** @type {Object.<number, import("@mail/core/common/attachment_model").Attachment>} */
|
||||
records: {},
|
||||
/**
|
||||
* @param {Object} data
|
||||
* @returns {import("@mail/core/common/attachment_model").Attachment}
|
||||
*/
|
||||
insert: (data) => this.env.services["mail.attachment"].insert(data),
|
||||
};
|
||||
CannedResponse = {
|
||||
/** @type {Object.<number, import("@mail/core/common/canned_response_model").CannedResponse>} */
|
||||
records: {},
|
||||
/**
|
||||
* @param {Object} data
|
||||
* @returns {import("@mail/core/common/canned_response_model").CannedResponse}
|
||||
*/
|
||||
insert: (data) => this.env.services["mail.messaging"].insertCannedResponse(data),
|
||||
};
|
||||
ChannelMember = {
|
||||
/** @type {Object.<number, import("@mail/core/common/channel_member_model").ChannelMember>} */
|
||||
records: {},
|
||||
/**
|
||||
* @param {Object|Array} data
|
||||
* @returns {import("@mail/core/common/channel_member_model").ChannelMember}
|
||||
*/
|
||||
insert: (data) => this.env.services["discuss.channel.member"].insert(data),
|
||||
};
|
||||
ChatWindow = {
|
||||
/** @type {import("@mail/core/common/chat_window_model").ChatWindow[]} */
|
||||
records: [],
|
||||
/**
|
||||
* @param {ChatWindowData} [data]
|
||||
* @returns {import("@mail/core/common/chat_window_model").ChatWindow}
|
||||
*/
|
||||
insert: (data = {}) => this.env.services["mail.chat_window"].insert(data),
|
||||
};
|
||||
Follower = {
|
||||
/** @type {Object.<number, import("@mail/core/common/follower_model").Follower>} */
|
||||
records: {},
|
||||
/**
|
||||
* @param {import("@mail/core/common/follower_model").Data} data
|
||||
* @returns {import("@mail/core/common/follower_model").Follower}
|
||||
*/
|
||||
insert: (data) => this.env.services["mail.thread"].insertFollower(data),
|
||||
};
|
||||
Message = {
|
||||
/** @type {Object.<number, import("@mail/core/common/message_model").Message>} */
|
||||
records: {},
|
||||
/**
|
||||
* @param {Object} data
|
||||
* @returns {import("@mail/core/common/message_model").Message}
|
||||
*/
|
||||
insert: (data) => this.env.services["mail.message"].insert(data),
|
||||
};
|
||||
Notification = {
|
||||
/** @type {Object.<number, import("@mail/core/common/notification_model").Notification>} */
|
||||
records: {},
|
||||
/**
|
||||
* @param {Object} data
|
||||
* @returns {import("@mail/core/common/notification_model").Notification}
|
||||
*/
|
||||
insert: (data) => this.env.services["mail.message"].insertNotification(data),
|
||||
};
|
||||
NotificationGroup = {
|
||||
/** @type {import("@mail/core/common/notification_group_model").NotificationGroup[]} */
|
||||
records: [],
|
||||
/**
|
||||
* @param {Object} data
|
||||
* @returns {import("@mail/core/common/notification_group_model").NotificationGroup}
|
||||
*/
|
||||
insert: (data) => this.env.services["mail.message"].insertNotificationGroups(data),
|
||||
};
|
||||
Persona = {
|
||||
/** @type {Object.<number, import("@mail/core/common/persona_model").Persona>} */
|
||||
records: {},
|
||||
/**
|
||||
* @param {import("@mail/core/common/persona_model").Data} data
|
||||
* @returns {import("@mail/core/common/persona_model").Persona}
|
||||
*/
|
||||
insert: (data) => this.env.services["mail.persona"].insert(data),
|
||||
};
|
||||
RtcSession = {
|
||||
/** @type {Object.<number, import("@mail/discuss/call/common/rtc_session_model").RtcSession>} */
|
||||
records: {},
|
||||
/**
|
||||
* @param {Object} data
|
||||
* @returns {number, import("@mail/discuss/call/common/rtc_session_model").RtcSession}
|
||||
*/
|
||||
insert: (data) => this.env.services["discuss.rtc"].insertSession(data),
|
||||
};
|
||||
Thread = {
|
||||
/** @type {Object.<string, import("@mail/core/common/thread_model").Thread>} */
|
||||
records: {},
|
||||
/**
|
||||
* @param {Object} data
|
||||
* @returns {import("@mail/core/common/thread_model").Thread}
|
||||
*/
|
||||
insert: (data) => this.env.services["mail.thread"].insert(data),
|
||||
};
|
||||
/** @type {typeof import("@mail/core/web/activity_model").Activity} */
|
||||
Activity;
|
||||
/** @type {typeof import("@mail/core/common/attachment_model").Attachment} */
|
||||
Attachment;
|
||||
/** @type {typeof import("@mail/core/common/canned_response_model").CannedResponse} */
|
||||
CannedResponse;
|
||||
/** @type {typeof import("@mail/core/common/channel_member_model").ChannelMember} */
|
||||
ChannelMember;
|
||||
/** @type {typeof import("@mail/core/common/chat_window_model").ChatWindow} */
|
||||
ChatWindow;
|
||||
/** @type {typeof import("@mail/core/common/follower_model").Follower} */
|
||||
Follower;
|
||||
/** @type {typeof import("@mail/core/common/message_model").Message} */
|
||||
Message;
|
||||
/** @type {typeof import("@mail/core/common/notification_model").Notification} */
|
||||
Notification;
|
||||
/** @type {typeof import("@mail/core/common/notification_group_model").NotificationGroup} */
|
||||
NotificationGroup;
|
||||
/** @type {typeof import("@mail/core/common/persona_model").Persona} */
|
||||
Persona;
|
||||
/** @type {typeof import("@mail/discuss/call/common/rtc_session_model").RtcSession} */
|
||||
RtcSession;
|
||||
/** @type {typeof import("@mail/core/common/thread_model").Thread} */
|
||||
Thread;
|
||||
|
||||
/**
|
||||
* @param {import("@web/env").OdooEnv} env
|
||||
@@ -257,6 +171,19 @@ export const storeService = {
|
||||
*/
|
||||
start(env, services) {
|
||||
const res = reactive(new Store(env, services));
|
||||
for (const [name, Model] of modelRegistry.getEntries()) {
|
||||
if (res[name]) {
|
||||
throw new Error(
|
||||
`There must be no duplicated Model Names (duplicate found: ${name})`
|
||||
);
|
||||
}
|
||||
// classes cannot be made reactive because they are functions and they are not supported.
|
||||
// work-around: make an object whose prototype is the class, so that static props become
|
||||
// instance props.
|
||||
const entry = Object.assign(Object.create(Model), { env, store: res });
|
||||
entry.records = JSON.parse(JSON.stringify(Model.records));
|
||||
res[name] = entry;
|
||||
}
|
||||
onChange(res.Thread, "records", () => res.updateBusSubscription());
|
||||
services.ui.bus.addEventListener("resize", () => {
|
||||
if (!services.ui.isSmall) {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { Record } from "@mail/core/common/record";
|
||||
import { Record, modelRegistry } from "@mail/core/common/record";
|
||||
import { ScrollPosition } from "@mail/core/common/scroll_position_model";
|
||||
import { createLocalId } from "@mail/utils/common/misc";
|
||||
import { createLocalId, onChange } from "@mail/utils/common/misc";
|
||||
|
||||
import { deserializeDateTime } from "@web/core/l10n/dates";
|
||||
import { _t } from "@web/core/l10n/translation";
|
||||
@@ -22,6 +22,44 @@ import { Deferred } from "@web/core/utils/concurrency";
|
||||
*/
|
||||
|
||||
export class Thread extends Record {
|
||||
/** @type {Object.<string, Thread>} */
|
||||
static records = {};
|
||||
/**
|
||||
* @param {Object} data
|
||||
* @returns {Thread}
|
||||
*/
|
||||
static insert(data) {
|
||||
if (!("id" in data)) {
|
||||
throw new Error("Cannot insert thread: id is missing in data");
|
||||
}
|
||||
if (!("model" in data)) {
|
||||
throw new Error("Cannot insert thread: model is missing in data");
|
||||
}
|
||||
const localId = createLocalId(data.model, data.id);
|
||||
if (localId in this.records) {
|
||||
const thread = this.records[localId];
|
||||
this.env.services["mail.thread"].update(thread, data);
|
||||
return thread;
|
||||
}
|
||||
const thread = new Thread(this.store, data);
|
||||
onChange(thread, "message_unread_counter", () => {
|
||||
if (thread.channel) {
|
||||
thread.channel.message_unread_counter = thread.message_unread_counter;
|
||||
}
|
||||
});
|
||||
onChange(thread, "isLoaded", () => thread.isLoadedDeferred.resolve());
|
||||
onChange(thread, "channelMembers", () => this.store.updateBusSubscription());
|
||||
onChange(thread, "is_pinned", () => {
|
||||
if (!thread.is_pinned && this.store.discuss.threadLocalId === thread.localId) {
|
||||
this.store.discuss.threadLocalId = null;
|
||||
}
|
||||
});
|
||||
this.env.services["mail.thread"].update(thread, data);
|
||||
this.env.services["mail.thread"].insertComposer({ thread });
|
||||
// return reactive version.
|
||||
return this.records[thread.localId];
|
||||
}
|
||||
|
||||
/** @type {number} */
|
||||
id;
|
||||
/** @type {string} */
|
||||
@@ -461,3 +499,5 @@ export class Thread extends Record {
|
||||
return this._store.Message.records[Math.max(...previousMessages.map((m) => m.id))];
|
||||
}
|
||||
}
|
||||
|
||||
modelRegistry.add(Thread.name, Thread);
|
||||
|
||||
@@ -3,19 +3,13 @@
|
||||
import { Composer } from "@mail/core/common/composer_model";
|
||||
import { loadEmoji } from "@web/core/emoji_picker/emoji_picker";
|
||||
import { DEFAULT_AVATAR } from "@mail/core/common/persona_service";
|
||||
import { Thread } from "@mail/core/common/thread_model";
|
||||
import {
|
||||
removeFromArray,
|
||||
removeFromArrayWithPredicate,
|
||||
replaceArrayWithCompare,
|
||||
} from "@mail/utils/common/arrays";
|
||||
import { prettifyMessageContent } from "@mail/utils/common/format";
|
||||
import {
|
||||
assignDefined,
|
||||
createLocalId,
|
||||
onChange,
|
||||
nullifyClearCommands,
|
||||
} from "@mail/utils/common/misc";
|
||||
import { assignDefined, createLocalId, nullifyClearCommands } from "@mail/utils/common/misc";
|
||||
|
||||
import { markup } from "@odoo/owl";
|
||||
|
||||
@@ -803,42 +797,6 @@ export class ThreadService {
|
||||
this.env.bus.trigger("mail.thread/onUpdate", { thread, data });
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} data
|
||||
* @returns {Thread}
|
||||
*/
|
||||
insert(data) {
|
||||
if (!("id" in data)) {
|
||||
throw new Error("Cannot insert thread: id is missing in data");
|
||||
}
|
||||
if (!("model" in data)) {
|
||||
throw new Error("Cannot insert thread: model is missing in data");
|
||||
}
|
||||
const localId = createLocalId(data.model, data.id);
|
||||
if (localId in this.store.Thread.records) {
|
||||
const thread = this.store.Thread.records[localId];
|
||||
this.update(thread, data);
|
||||
return thread;
|
||||
}
|
||||
const thread = new Thread(this.store, data);
|
||||
onChange(thread, "message_unread_counter", () => {
|
||||
if (thread.channel) {
|
||||
thread.channel.message_unread_counter = thread.message_unread_counter;
|
||||
}
|
||||
});
|
||||
onChange(thread, "isLoaded", () => thread.isLoadedDeferred.resolve());
|
||||
onChange(thread, "channelMembers", () => this.store.updateBusSubscription());
|
||||
onChange(thread, "is_pinned", () => {
|
||||
if (!thread.is_pinned && this.store.discuss.threadLocalId === thread.localId) {
|
||||
this.store.discuss.threadLocalId = null;
|
||||
}
|
||||
});
|
||||
this.update(thread, data);
|
||||
this.insertComposer({ thread });
|
||||
// return reactive version.
|
||||
return this.store.Thread.records[thread.localId];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} data
|
||||
* @returns {Composer}
|
||||
|
||||
@@ -31,7 +31,6 @@ export class ActivityListPopover extends Component {
|
||||
setup() {
|
||||
this.orm = useService("orm");
|
||||
this.user = useService("user");
|
||||
this.activity = useService("mail.activity");
|
||||
this.store = useState(useService("mail.store"));
|
||||
this.updateFromProps(this.props);
|
||||
onWillUpdateProps((props) => this.updateFromProps(props));
|
||||
@@ -84,7 +83,7 @@ export class ActivityListPopover extends Component {
|
||||
}
|
||||
);
|
||||
for (const activityData of activitiesData) {
|
||||
this.activity.insert(activityData);
|
||||
this.store.Activity.insert(activityData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { Record } from "@mail/core/common/record";
|
||||
import { Record, modelRegistry } from "@mail/core/common/record";
|
||||
import { assignDefined } from "@mail/utils/common/misc";
|
||||
|
||||
/**
|
||||
* @typedef Data
|
||||
@@ -33,6 +34,30 @@ import { Record } from "@mail/core/common/record";
|
||||
*/
|
||||
|
||||
export class Activity extends Record {
|
||||
/** @type {Object.<number, Activity>} */
|
||||
static records = {};
|
||||
|
||||
/**
|
||||
* @param {Data} data
|
||||
* @param {Object} [param1]
|
||||
* @param {boolean} param1.broadcast
|
||||
* @returns {Activity}
|
||||
*/
|
||||
static insert(data, { broadcast = true } = {}) {
|
||||
const activity = this.records[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.env.services["mail.activity"].broadcastChannel?.postMessage({
|
||||
type: "insert",
|
||||
payload: this.env.services["mail.activity"]._serialize(activity),
|
||||
});
|
||||
}
|
||||
return activity;
|
||||
}
|
||||
|
||||
/** @type {string} */
|
||||
activity_category;
|
||||
/** @type {[number, string]} */
|
||||
@@ -105,3 +130,5 @@ export class Activity extends Record {
|
||||
return store.Activity.records[id];
|
||||
}
|
||||
}
|
||||
|
||||
modelRegistry.add(Activity.name, Activity);
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { Activity } from "@mail/core/web/activity_model";
|
||||
import { assignDefined } from "@mail/utils/common/misc";
|
||||
|
||||
import { _t } from "@web/core/l10n/translation";
|
||||
import { registry } from "@web/core/registry";
|
||||
import { browser } from "@web/core/browser/browser";
|
||||
@@ -80,27 +77,6 @@ export class ActivityService {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("@mail/core/web/activity_model").Data} data
|
||||
* @param {Object} [param1]
|
||||
* @param {boolean} param1.broadcast
|
||||
* @returns {import("@mail/core/web/activity_model").Activity}
|
||||
*/
|
||||
insert(data, { broadcast = true } = {}) {
|
||||
const activity = this.store.Activity.records[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, { broadcast = true } = {}) {
|
||||
delete this.store.Activity.records[activity.id];
|
||||
if (broadcast) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { Follower } from "@mail/core/common/follower_model";
|
||||
import { ThreadService, threadService } from "@mail/core/common/thread_service";
|
||||
import { parseEmail } from "@mail/js/utils";
|
||||
import { createLocalId } from "@mail/utils/common/misc";
|
||||
@@ -44,7 +43,7 @@ patch(ThreadService.prototype, {
|
||||
if ("attachments" in result) {
|
||||
result["attachments"] = result["attachments"].map((attachment) => ({
|
||||
...attachment,
|
||||
originThread: this.insert(attachment.originThread[0][1]),
|
||||
originThread: this.store.Thread.insert(attachment.originThread[0][1]),
|
||||
}));
|
||||
}
|
||||
thread.canPostOnReadonly = result.canPostOnReadonly;
|
||||
@@ -111,7 +110,7 @@ patch(ThreadService.prototype, {
|
||||
// to force a reload
|
||||
this.store.Thread.records[localId].status = "new";
|
||||
}
|
||||
const thread = this.insert({
|
||||
const thread = this.store.Thread.insert({
|
||||
id: resId,
|
||||
model: resModel,
|
||||
type: "chatter",
|
||||
@@ -132,25 +131,6 @@ patch(ThreadService.prototype, {
|
||||
}
|
||||
return thread;
|
||||
},
|
||||
/**
|
||||
* @param {import("@mail/core/common/follower_model").Data} data
|
||||
* @returns {import("@mail/core/common/follower_model").Follower}
|
||||
*/
|
||||
insertFollower(data) {
|
||||
let follower = this.store.Follower.records[data.id];
|
||||
if (!follower) {
|
||||
this.store.Follower.records[data.id] = new Follower();
|
||||
follower = this.store.Follower.records[data.id];
|
||||
}
|
||||
Object.assign(follower, {
|
||||
followedThread: data.followedThread,
|
||||
id: data.id,
|
||||
isActive: data.is_active,
|
||||
partner: this.store.Persona.insert({ ...data.partner, type: "partner" }),
|
||||
_store: this.store,
|
||||
});
|
||||
return follower;
|
||||
},
|
||||
/**
|
||||
* @param {import("@mail/core/common/thread_model").Thread} thread
|
||||
* @param {import("@mail/core/web/suggested_recipient").SuggestedRecipient[]} dataList
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
import { BlurManager } from "@mail/discuss/call/common/blur_manager";
|
||||
import { monitorAudio } from "@mail/discuss/call/common/media_monitoring";
|
||||
import { RtcSession } from "@mail/discuss/call/common/rtc_session_model";
|
||||
import { removeFromArray } from "@mail/utils/common/arrays";
|
||||
import { closeStream, createLocalId, onChange } from "@mail/utils/common/misc";
|
||||
|
||||
@@ -1397,38 +1396,6 @@ export class Rtc {
|
||||
await this.refreshAudioStatus();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} data
|
||||
* @returns {RtcSession}
|
||||
*/
|
||||
insertSession(data) {
|
||||
let session;
|
||||
if (this.store.RtcSession.records[data.id]) {
|
||||
session = this.store.RtcSession.records[data.id];
|
||||
} else {
|
||||
session = new RtcSession();
|
||||
session._store = this.store;
|
||||
}
|
||||
const { channelMember, ...remainingData } = data;
|
||||
for (const key in remainingData) {
|
||||
session[key] = remainingData[key];
|
||||
}
|
||||
if (channelMember?.channel) {
|
||||
session.channelId = channelMember.channel.id;
|
||||
}
|
||||
if (channelMember) {
|
||||
const channelMemberRecord = this.store.ChannelMember.insert(channelMember);
|
||||
channelMemberRecord.rtcSessionId = session.id;
|
||||
session.channelMemberId = channelMemberRecord.id;
|
||||
if (channelMemberRecord.thread) {
|
||||
channelMemberRecord.thread.rtcSessions[session.id] = session;
|
||||
}
|
||||
}
|
||||
this.store.RtcSession.records[session.id] = session;
|
||||
// return reactive version
|
||||
return this.store.RtcSession.records[session.id];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("@mail/discuss/call/common/rtc_session_model").id} id
|
||||
*/
|
||||
|
||||
@@ -1,9 +1,43 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { Record } from "@mail/core/common/record";
|
||||
import { Record, modelRegistry } from "@mail/core/common/record";
|
||||
import { createLocalId } from "@mail/utils/common/misc";
|
||||
|
||||
export class RtcSession extends Record {
|
||||
/** @type {Object.<number, RtcSession>} */
|
||||
static records = {};
|
||||
/**
|
||||
* @param {Object} data
|
||||
* @returns {number, RtcSession}
|
||||
*/
|
||||
static insert(data) {
|
||||
let session;
|
||||
if (this.records[data.id]) {
|
||||
session = this.records[data.id];
|
||||
} else {
|
||||
session = new RtcSession();
|
||||
session._store = this.store;
|
||||
}
|
||||
const { channelMember, ...remainingData } = data;
|
||||
for (const key in remainingData) {
|
||||
session[key] = remainingData[key];
|
||||
}
|
||||
if (channelMember?.channel) {
|
||||
session.channelId = channelMember.channel.id;
|
||||
}
|
||||
if (channelMember) {
|
||||
const channelMemberRecord = this.store.ChannelMember.insert(channelMember);
|
||||
channelMemberRecord.rtcSessionId = session.id;
|
||||
session.channelMemberId = channelMemberRecord.id;
|
||||
if (channelMemberRecord.thread) {
|
||||
channelMemberRecord.thread.rtcSessions[session.id] = session;
|
||||
}
|
||||
}
|
||||
this.records[session.id] = session;
|
||||
// return reactive version
|
||||
return this.records[session.id];
|
||||
}
|
||||
|
||||
// Server data
|
||||
channelId;
|
||||
channelMemberId;
|
||||
@@ -141,3 +175,5 @@ export class RtcSession extends Record {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
modelRegistry.add(RtcSession.name, RtcSession);
|
||||
|
||||
@@ -39,7 +39,6 @@ export function isDragSourceExternalFile(dataTransfer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {Object} target
|
||||
* @param {string} key
|
||||
|
||||
@@ -7,7 +7,7 @@ QUnit.module("attachment model test", {});
|
||||
QUnit.test("Attachment model properties", async (assert) => {
|
||||
const { env } = await start();
|
||||
|
||||
const attachment = env.services["mail.attachment"].insert({
|
||||
const attachment = env.services["mail.store"].Attachment.insert({
|
||||
filename: "test.txt",
|
||||
id: 750,
|
||||
mimetype: "text/plain",
|
||||
|
||||
Reference in New Issue
Block a user