From 34d775e8739c03359d948a62b29bcd0c41ffd9f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Theys?= Date: Thu, 18 Aug 2022 16:18:12 +0000 Subject: [PATCH] [IMP] mail, *: remove explicit usage of insert-and-replace MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * = calendar, im_livechat, rating, snailmail, test_discuss_full, test_mail, website_livechat Distinction between "replace" and "insert-and-replace" can be guessed based on the type of the provided data. task-2957295 closes odoo/odoo#98404 Related: odoo/enterprise#30580 Signed-off-by: Alexandre Kühn (aku) --- addons/calendar/models/res_users.py | 2 +- .../static/tests/helpers/mock_server.js | 2 +- .../src/legacy/public_livechat_chatbot.js | 8 +- .../im_livechat/static/src/models/discuss.js | 3 +- .../static/src/models/livechat_button_view.js | 12 +- .../im_livechat/static/src/models/message.js | 5 +- .../static/src/models/public_livechat.js | 6 +- .../src/models/public_livechat_global.js | 16 +- .../src/models/public_livechat_window.js | 3 +- .../im_livechat/static/src/models/thread.js | 21 +- addons/im_livechat/static/src/public/main.js | 3 +- addons/im_livechat/tests/test_message.py | 10 +- addons/mail/controllers/discuss.py | 6 +- addons/mail/models/mail_channel.py | 8 +- addons/mail/models/mail_channel_member.py | 12 +- .../mail/models/mail_channel_rtc_session.py | 2 +- addons/mail/models/mail_message.py | 28 +- addons/mail/models/mail_thread.py | 2 +- addons/mail/models/mail_tracking_value.py | 10 +- addons/mail/models/res_users_settings.py | 2 +- .../mail/models/res_users_settings_volumes.py | 12 +- .../discuss_container/discuss_container.js | 5 +- addons/mail/static/src/model/model_core.js | 2 +- addons/mail/static/src/model/model_field.js | 16 +- .../static/src/model/model_field_command.js | 15 - addons/mail/static/src/model/model_manager.js | 3 +- .../static/src/models/activity_box_view.js | 5 +- .../mail/static/src/models/activity_group.js | 5 +- .../static/src/models/activity_menu_view.js | 7 +- .../mail/static/src/models/activity_view.js | 23 +- .../static/src/models/attachment_box_view.js | 6 +- .../mail/static/src/models/attachment_card.js | 5 +- .../static/src/models/attachment_image.js | 6 +- .../mail/static/src/models/attachment_list.js | 14 +- .../static/src/models/attachment_viewer.js | 14 +- .../src/models/call_action_list_view.js | 4 +- .../mail/static/src/models/call_main_view.js | 15 +- .../static/src/models/call_main_view_tile.js | 3 +- .../src/models/call_participant_card.js | 4 +- .../static/src/models/call_sidebar_view.js | 3 +- .../src/models/call_sidebar_view_tile.js | 3 +- addons/mail/static/src/models/call_view.js | 6 +- .../mail/static/src/models/canned_response.js | 3 +- addons/mail/static/src/models/channel.js | 5 +- .../mail/static/src/models/channel_command.js | 3 +- .../src/models/channel_invitation_form.js | 8 +- ...invitation_form_selectable_partner_view.js | 4 +- .../channel_member_list_category_view.js | 6 +- .../src/models/channel_member_list_view.js | 6 +- .../static/src/models/channel_member_view.js | 6 +- addons/mail/static/src/models/chat_window.js | 16 +- .../static/src/models/chat_window_manager.js | 6 +- addons/mail/static/src/models/chatter.js | 37 +-- .../composer_suggested_recipient_list_view.js | 14 +- .../models/composer_suggestion_list_view.js | 13 +- ...iew_extra_composer_suggestion_view_item.js | 3 +- ...view_main_composer_suggestion_view_item.js | 3 +- .../src/models/composer_suggestion_view.js | 4 +- .../mail/static/src/models/composer_view.js | 18 +- .../src/models/delete_message_confirm_view.js | 4 +- addons/mail/static/src/models/dialog.js | 12 +- addons/mail/static/src/models/discuss.js | 16 +- .../static/src/models/discuss_public_view.js | 10 +- .../src/models/discuss_sidebar_category.js | 8 +- addons/mail/static/src/models/discuss_view.js | 10 +- .../src/models/emoji_category_bar_view.js | 13 +- .../mail/static/src/models/emoji_grid_view.js | 8 +- .../static/src/models/emoji_picker_view.js | 5 +- .../mail/static/src/models/emoji_registry.js | 24 +- addons/mail/static/src/models/follower.js | 6 +- .../src/models/follower_list_menu_view.js | 5 +- .../src/models/follower_subtype_list.js | 4 +- addons/mail/static/src/models/guest.js | 3 +- addons/mail/static/src/models/mailbox.js | 6 +- addons/mail/static/src/models/message.js | 8 +- .../static/src/models/message_action_list.js | 6 +- .../static/src/models/message_list_view.js | 4 +- .../message_list_view_message_view_item.js | 3 +- .../src/models/message_seen_indicator_view.js | 6 +- addons/mail/static/src/models/message_view.js | 45 +-- addons/mail/static/src/models/messaging.js | 40 +-- .../mail/static/src/models/messaging_menu.js | 8 +- .../models/messaging_notification_handler.js | 8 +- addons/mail/static/src/models/notification.js | 6 +- .../src/models/notification_list_view.js | 108 +++---- .../src/models/notification_request_view.js | 4 +- ...ther_member_long_typing_in_thread_timer.js | 3 +- addons/mail/static/src/models/partner.js | 6 +- addons/mail/static/src/models/popover_view.js | 10 +- addons/mail/static/src/models/record.js | 3 +- addons/mail/static/src/models/rtc.js | 6 +- addons/mail/static/src/models/rtc_session.js | 9 +- .../mail/static/src/models/sound_effects.js | 25 +- addons/mail/static/src/models/thread.js | 79 ++--- .../models/thread_needaction_preview_view.js | 6 +- .../static/src/models/thread_preview_view.js | 6 +- addons/mail/static/src/models/thread_view.js | 12 +- .../static/src/models/thread_view_topbar.js | 4 +- .../mail/static/src/models/thread_viewer.js | 4 +- addons/mail/static/src/models/throttle.js | 9 +- addons/mail/static/src/models/timer.js | 52 ++-- addons/mail/static/src/models/user_setting.js | 4 +- addons/mail/static/src/models/welcome_view.js | 4 +- .../mail/static/tests/helpers/mock_server.js | 32 +-- .../static/tests/helpers/webclient_setup.js | 3 +- .../mail/static/tests/models/test_models.js | 7 +- .../model_field_commands/clear_tests.js | 14 +- .../insert_and_replace_tests.js | 27 +- .../model_field_commands/insert_tests.js | 14 +- .../model_field_commands/link_tests.js | 6 +- .../model_field_commands/replace_tests.js | 11 +- .../model_field_commands/unlink_all_tests.js | 8 +- .../model_field_commands/unlink_tests.js | 8 +- .../qunit_suite_tests/models/clock_tests.js | 9 +- .../qunit_suite_tests/models/message_tests.js | 6 +- .../qunit_suite_tests/models/thread_tests.js | 10 +- .../qunit_suite_tests/utils/throttle_tests.js | 9 +- .../qunit_suite_tests/utils/timer_tests.js | 19 +- addons/mail/tests/test_rtc.py | 269 +++++++++--------- addons/rating/models/mail_message.py | 4 +- .../static/tests/helpers/mock_server.js | 4 +- addons/snailmail/static/src/models/dialog.js | 4 +- .../static/src/models/message_view.js | 9 +- .../tests/test_performance.py | 58 ++-- addons/test_mail/tests/test_message_track.py | 14 +- addons/test_mail/tests/test_performance.py | 4 +- .../website_livechat_chatbot_test_script.js | 8 +- .../static/src/models/livechat_button_view.js | 4 +- 128 files changed, 796 insertions(+), 879 deletions(-) diff --git a/addons/calendar/models/res_users.py b/addons/calendar/models/res_users.py index 019aaede6dc..fb4fc39ccff 100644 --- a/addons/calendar/models/res_users.py +++ b/addons/calendar/models/res_users.py @@ -49,7 +49,7 @@ class Users(models.Model): 'name': meeting_label, 'model': 'calendar.event', 'icon': modules.module.get_module_icon(self.env['calendar.event']._original_module), - 'meetings': [('insert-and-replace', meetings_lines)], + 'meetings': meetings_lines, } res.insert(0, meetings_systray) diff --git a/addons/calendar/static/tests/helpers/mock_server.js b/addons/calendar/static/tests/helpers/mock_server.js index d85833a862f..0f04b39fd4b 100644 --- a/addons/calendar/static/tests/helpers/mock_server.js +++ b/addons/calendar/static/tests/helpers/mock_server.js @@ -82,7 +82,7 @@ patch(MockServer.prototype, 'calendar', { if (meetingsLines.length) { activities.unshift({ id: 'calendar.event', // for simplicity - meetings: [['insert-and-replace', meetingsLines]], + meetings: meetingsLines, model: 'calendar.event', name: 'Today\'s Meetings', type: 'meeting', diff --git a/addons/im_livechat/static/src/legacy/public_livechat_chatbot.js b/addons/im_livechat/static/src/legacy/public_livechat_chatbot.js index 18a93920ec4..907beb3ff96 100644 --- a/addons/im_livechat/static/src/legacy/public_livechat_chatbot.js +++ b/addons/im_livechat/static/src/legacy/public_livechat_chatbot.js @@ -6,7 +6,7 @@ import time from 'web.time'; import utils from 'web.utils'; import LivechatButton from '@im_livechat/legacy/widgets/livechat_button'; -import { increment, insertAndReplace } from '@mail/model/model_field_command'; +import { increment } from '@mail/model/model_field_command'; const _t = core._t; @@ -299,7 +299,7 @@ const _t = core._t; this._chatbotAddMessage(nextStep.chatbot_posted_message); } - this.messaging.publicLivechatGlobal.chatbot.update({ currentStep: insertAndReplace({ data: nextStep.chatbot_step }) }); + this.messaging.publicLivechatGlobal.chatbot.update({ currentStep: { data: nextStep.chatbot_step } }); this._chatbotProcessStep(); } else { @@ -412,12 +412,12 @@ const _t = core._t; */ _sendWelcomeChatbotMessage(stepIndex, welcomeMessageDelay) { const chatbotStep = this.messaging.publicLivechatGlobal.chatbot.welcomeSteps[stepIndex]; - this.messaging.publicLivechatGlobal.chatbot.update({ currentStep: insertAndReplace({ data: chatbotStep }) }); + this.messaging.publicLivechatGlobal.chatbot.update({ currentStep: { data: chatbotStep } }); if (chatbotStep.chatbot_step_message) { this.messaging.publicLivechatGlobal.livechatButtonView.addMessage({ id: '_welcome_' + stepIndex, - is_discussion: true, // important for css style -> we only want white background for chatbot + is_discussion: true, // important for css style -> we only want white background for chatbot author_id: ( this.messaging.publicLivechatGlobal.publicLivechat.operator ? [ diff --git a/addons/im_livechat/static/src/models/discuss.js b/addons/im_livechat/static/src/models/discuss.js index 16511b245a9..10d73b531c9 100644 --- a/addons/im_livechat/static/src/models/discuss.js +++ b/addons/im_livechat/static/src/models/discuss.js @@ -2,7 +2,6 @@ import { addFields, patchRecordMethods } from '@mail/model/model_core'; import { one } from '@mail/model/model_field'; -import { insertAndReplace } from '@mail/model/model_field_command'; // ensure that the model definition is loaded before the patch import '@mail/models/discuss'; @@ -23,7 +22,7 @@ addFields('Discuss', { * Discuss sidebar category for `livechat` channel threads. */ categoryLivechat: one('DiscussSidebarCategory', { - default: insertAndReplace(), + default: {}, inverse: 'discussAsLivechat', isCausal: true, }), diff --git a/addons/im_livechat/static/src/models/livechat_button_view.js b/addons/im_livechat/static/src/models/livechat_button_view.js index d19d63dc3b9..dce7fc82158 100644 --- a/addons/im_livechat/static/src/models/livechat_button_view.js +++ b/addons/im_livechat/static/src/models/livechat_button_view.js @@ -4,7 +4,7 @@ import PublicLivechatMessage from '@im_livechat/legacy/models/public_livechat_me import { registerModel } from '@mail/model/model_core'; import { attr, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; import { qweb } from 'web.core'; import { get_cookie, set_cookie, unaccent } from 'web.utils'; @@ -55,7 +55,7 @@ registerModel({ }, askFeedback() { this.chatWindow.legacyChatWindow.$('.o_thread_composer input').prop('disabled', true); - this.messaging.publicLivechatGlobal.update({ feedbackView: insertAndReplace() }); + this.messaging.publicLivechatGlobal.update({ feedbackView: {} }); /** * When we enter the "ask feedback" process of the chat, we hide some elements that become * unnecessary and irrelevant (restart / end messages, any text field values, ...). @@ -164,7 +164,7 @@ registerModel({ } const chatbotState = localStorage.getItem(this.messaging.publicLivechatGlobal.chatbotSessionCookieKey); if (chatbotState) { - this.messaging.publicLivechatGlobal.chatbot.update({ currentStep: insertAndReplace({ data: this.messaging.publicLivechatGlobal.localStorageChatbotState._chatbotCurrentStep }) }); + this.messaging.publicLivechatGlobal.chatbot.update({ currentStep: { data: this.messaging.publicLivechatGlobal.localStorageChatbotState._chatbotCurrentStep } }); } }, closeChat() { @@ -191,7 +191,7 @@ registerModel({ } }, async openChatWindow() { - this.update({ chatWindow: insertAndReplace() }); + this.update({ chatWindow: {} }); await this.chatWindow.legacyChatWindow.appendTo($('body')); const cssProps = { bottom: 0 }; cssProps[this.messaging.locale.textDirection === 'rtl' ? 'left' : 'right'] = 0; @@ -412,14 +412,14 @@ registerModel({ } } else { this.messaging.publicLivechatGlobal.update({ - publicLivechat: insertAndReplace({ data: livechatData }), + publicLivechat: { data: livechatData }, }); return this.openChatWindow().then(() => { if (!this.messaging.publicLivechatGlobal.history) { this.widget._sendWelcomeMessage(); } this.widget._renderMessages(); - this.messaging.publicLivechatGlobal.update({ notificationHandler: insertAndReplace() }); + this.messaging.publicLivechatGlobal.update({ notificationHandler: {} }); set_cookie('im_livechat_session', unaccent(JSON.stringify(this.messaging.publicLivechatGlobal.publicLivechat.legacyPublicLivechat.toData()), true), 60 * 60); set_cookie('im_livechat_auto_popup', JSON.stringify(false), 60 * 60); diff --git a/addons/im_livechat/static/src/models/message.js b/addons/im_livechat/static/src/models/message.js index d9e8ef40043..1ae56b51fe9 100644 --- a/addons/im_livechat/static/src/models/message.js +++ b/addons/im_livechat/static/src/models/message.js @@ -1,7 +1,6 @@ /** @odoo-module **/ import { patchModelMethods, patchRecordMethods } from '@mail/model/model_core'; -import { insertAndReplace } from '@mail/model/model_field_command'; // ensure the model definition is loaded before the patch import '@mail/models/message'; @@ -15,10 +14,10 @@ patchModelMethods('Message', { if (data.author_id[2]) { // flux specific for livechat, a 3rd param is livechat_username // and means 2nd param (display_name) should be ignored - data2.author = insertAndReplace({ + data2.author = { id: data.author_id[0], livechat_username: data.author_id[2], - }); + }; } } return data2; diff --git a/addons/im_livechat/static/src/models/public_livechat.js b/addons/im_livechat/static/src/models/public_livechat.js index bf993ef098b..e1dd7481e3f 100644 --- a/addons/im_livechat/static/src/models/public_livechat.js +++ b/addons/im_livechat/static/src/models/public_livechat.js @@ -4,7 +4,7 @@ import PublicLivechat from '@im_livechat/legacy/models/public_livechat'; import { registerModel } from '@mail/model/model_core'; import { attr, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; registerModel({ name: 'PublicLivechat', @@ -56,10 +56,10 @@ registerModel({ if (!this.data.operator_pid[0]) { return clear(); } - return insertAndReplace({ + return { id: this.data.operator_pid[0], name: this.data.operator_pid[1], - }); + }; }, /** * @private diff --git a/addons/im_livechat/static/src/models/public_livechat_global.js b/addons/im_livechat/static/src/models/public_livechat_global.js index 1315b7fd442..a7bf73712ce 100644 --- a/addons/im_livechat/static/src/models/public_livechat_global.js +++ b/addons/im_livechat/static/src/models/public_livechat_global.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, many, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; import { qweb } from 'web.core'; @@ -54,16 +54,16 @@ registerModel({ */ _computeChatbot() { if (this.isTestChatbot) { - return insertAndReplace({ data: this.testChatbotData.chatbot }); + return { data: this.testChatbotData.chatbot }; } if (this.chatbotState === 'init') { - return insertAndReplace({ data: this.rule.chatbot }); + return { data: this.rule.chatbot }; } if (this.chatbotState === 'welcome') { - return insertAndReplace({ data: this.livechatInit.rule.chatbot }); + return { data: this.livechatInit.rule.chatbot }; } if (this.chatbotState === 'restore_session' && this.localStorageChatbotState) { - return insertAndReplace({ data: this.localStorageChatbotState._chatbot }); + return { data: this.localStorageChatbotState._chatbot }; } return clear(); }, @@ -106,7 +106,7 @@ registerModel({ */ _computeLivechatButtonView() { if (this.isAvailable && this.isAvailableForMe && this.hasLoadedQWebTemplate && this.env.services.public_livechat_service) { - return insertAndReplace(); + return {}; } return clear(); }, @@ -193,9 +193,9 @@ registerModel({ // -> initialize necessary state if (this.rule.chatbot_welcome_steps && this.rule.chatbot_welcome_steps.length !== 0) { this.chatbot.update({ - currentStep: insertAndReplace({ + currentStep: { data: this.chatbot.lastWelcomeStep, - }), + }, }); } } else if (this.chatbotState === 'welcome') { diff --git a/addons/im_livechat/static/src/models/public_livechat_window.js b/addons/im_livechat/static/src/models/public_livechat_window.js index 4a9bbbf2399..67387d9dea0 100644 --- a/addons/im_livechat/static/src/models/public_livechat_window.js +++ b/addons/im_livechat/static/src/models/public_livechat_window.js @@ -4,7 +4,6 @@ import PublicLivechatWindow from '@im_livechat/legacy/widgets/public_livechat_wi import { registerModel } from '@mail/model/model_core'; import { attr, one } from '@mail/model/model_field'; -import { insertAndReplace } from '@mail/model/model_field_command'; registerModel({ name: 'PublicLivechatWindow', @@ -46,7 +45,7 @@ registerModel({ inverse: 'chatWindow', }), publicLivechatView: one('PublicLivechatView', { - default: insertAndReplace(), + default: {}, inverse: 'publicLivechatWindowOwner', isCausal: true, }), diff --git a/addons/im_livechat/static/src/models/thread.js b/addons/im_livechat/static/src/models/thread.js index 264ee5f271a..8dd2ef9a99a 100644 --- a/addons/im_livechat/static/src/models/thread.js +++ b/addons/im_livechat/static/src/models/thread.js @@ -2,7 +2,7 @@ import { addFields, addRecordMethods, patchModelMethods, patchRecordMethods } from '@mail/model/model_core'; import { one } from '@mail/model/model_field'; -import { clear, insert, link, unlink } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; // ensure that the model definition is loaded before the patch import '@mail/models/thread'; @@ -57,19 +57,18 @@ patchModelMethods('Thread', { * of polluting the database, it is therefore acceptable and * easier to handle one temporary partner per channel. */ - data2.members.push(unlink(this.messaging.publicPartners)); - const partner = this.messaging.models['Partner'].insert( - Object.assign( - this.messaging.models['Partner'].convertData(data.livechat_visitor), - { id: this.messaging.models['Partner'].getNextPublicId() } - ) + const publicPartnerIds = this.messaging.publicPartners.map(partner => partner.id); + data2.members = data2.members.filter(partnerData => !publicPartnerIds.includes(partnerData.id)); + const partnerData = Object.assign( + this.messaging.models['Partner'].convertData(data.livechat_visitor), + { id: this.messaging.models['Partner'].getNextPublicId() } ); - data2.members.push(link(partner)); - data2.correspondent = partner; + data2.members.push(partnerData); + data2.correspondent = partnerData; } else { const partnerData = this.messaging.models['Partner'].convertData(data.livechat_visitor); - data2.members.push(insert(partnerData)); - data2.correspondent = insert(partnerData); + data2.members.push(partnerData); + data2.correspondent = partnerData; } } return data2; diff --git a/addons/im_livechat/static/src/public/main.js b/addons/im_livechat/static/src/public/main.js index 2e7f9f371a0..eb9ac3f0866 100644 --- a/addons/im_livechat/static/src/public/main.js +++ b/addons/im_livechat/static/src/public/main.js @@ -3,7 +3,6 @@ import { publicLivechatService } from '@im_livechat/services/public_livechat_service'; import { isAvailable, options, serverUrl } from 'im_livechat.loaderData'; -import { insertAndReplace } from '@mail/model/model_field_command'; import { messagingService } from '@mail/services/messaging_service'; import { makeMessagingToLegacyEnv } from '@mail/utils/make_messaging_to_legacy_env'; @@ -12,7 +11,7 @@ import { registry } from '@web/core/registry'; const messagingValuesService = { start() { return { - publicLivechatGlobal: insertAndReplace({ isAvailable, options, serverUrl }), + publicLivechatGlobal: { isAvailable, options, serverUrl }, }; } }; diff --git a/addons/im_livechat/tests/test_message.py b/addons/im_livechat/tests/test_message.py index a2771ea7f10..d0ccaf36884 100644 --- a/addons/im_livechat/tests/test_message.py +++ b/addons/im_livechat/tests/test_message.py @@ -43,7 +43,7 @@ class TestImLivechatMessage(TransactionCase): rating_id=record_rating.id, ) self.assertEqual(message.message_format(), [{ - 'attachment_ids': [('insert-and-replace', [])], + 'attachment_ids': [], 'author_id': (self.users[1].partner_id.id, "test1"), 'body': message.body, 'date': message.date, @@ -53,16 +53,16 @@ class TestImLivechatMessage(TransactionCase): 'is_note': True, 'is_notification': False, 'message_type': 'notification', - 'messageReactionGroups': [('insert-and-replace', [])], + 'messageReactionGroups': [], 'model': 'mail.channel', 'module_icon': '/mail/static/description/icon.png', 'needaction_partner_ids': [], 'notifications': [], - 'rating': [('insert-and-replace', { + 'rating': { 'id': record_rating.id, 'ratingImageUrl': record_rating.rating_image_url, 'ratingText': record_rating.rating_text, - })], + }, 'recipients': [], 'record_name': "test1 Ernest Employee", 'res_id': channel_livechat_1.id, @@ -71,5 +71,5 @@ class TestImLivechatMessage(TransactionCase): 'subject': False, 'subtype_description': False, 'subtype_id': (self.env.ref('mail.mt_note').id, 'Note'), - 'trackingValues': [('insert-and-replace', [])], + 'trackingValues': [], }]) diff --git a/addons/mail/controllers/discuss.py b/addons/mail/controllers/discuss.py index 94fbd5c8f90..7a748fea508 100644 --- a/addons/mail/controllers/discuss.py +++ b/addons/mail/controllers/discuss.py @@ -245,7 +245,7 @@ class DiscussController(http.Controller): return { 'id': message_sudo.id, 'body': message_sudo.body, - 'attachments': [('insert-and-replace', message_sudo.attachment_ids._attachment_format())], + 'attachments': message_sudo.attachment_ids._attachment_format(), } @http.route('/mail/attachment/upload', methods=['POST'], type='http', auth='public') @@ -334,7 +334,7 @@ class DiscussController(http.Controller): 'content': content, 'count': len(reactions), 'guests': guests, - 'message': [('insert-and-replace', {'id', message_sudo.id})], + 'message': {'id', message_sudo.id}, 'partners': partners, })], } @@ -362,7 +362,7 @@ class DiscussController(http.Controller): 'content': content, 'count': len(reactions), 'guests': guests, - 'message': [('insert-and-replace', {'id': message_sudo.id})], + 'message': {'id': message_sudo.id}, 'partners': partners, })], } diff --git a/addons/mail/models/mail_channel.py b/addons/mail/models/mail_channel.py index fdc36950901..7e934126a83 100644 --- a/addons/mail/models/mail_channel.py +++ b/addons/mail/models/mail_channel.py @@ -634,7 +634,7 @@ class Channel(models.Model): self.env['bus.bus']._sendone(self, 'mail.message/insert', { 'id': message.id, 'body': message.body, - 'attachments': [('insert-and-replace', message.attachment_ids._attachment_format())], + 'attachments': message.attachment_ids._attachment_format(), }) return super()._message_update_content_after_hook(message=message) @@ -653,7 +653,7 @@ class Channel(models.Model): 'content': content, 'count': len(reactions), 'guests': guests, - 'message': [('insert-and-replace', {'id': message.id})], + 'message': {'id': message.id}, 'partners': partners, })], }) @@ -674,7 +674,7 @@ class Channel(models.Model): 'content': content, 'count': len(reactions), 'guests': guests, - 'message': [('insert-and-replace', {'id': message.id})], + 'message': {'id': message.id}, 'partners': partners, })], }) @@ -823,7 +823,7 @@ class Channel(models.Model): 'rtcSessions': [('insert', rtc_sessions_by_channel.get(channel, []))], }) - info['channel'] = [('insert-and-replace', channel_data)] + info['channel'] = channel_data channel_infos.append(info) return channel_infos diff --git a/addons/mail/models/mail_channel_member.py b/addons/mail/models/mail_channel_member.py index ebb14e563b6..51be36caa57 100644 --- a/addons/mail/models/mail_channel_member.py +++ b/addons/mail/models/mail_channel_member.py @@ -125,24 +125,24 @@ class ChannelMember(models.Model): for member in self: if member.partner_id: persona = { - 'partner': [('insert-and-replace', { + 'partner': { 'id': member.partner_id.id, 'name': member.partner_id.name, 'im_status': member.partner_id.im_status, - })], + }, } if member.guest_id: persona = { - 'guest': [('insert-and-replace', { + 'guest': { 'id': member.guest_id.id, 'name': member.guest_id.name, 'im_status': member.guest_id.im_status, - })], + }, } members_formatted_data.append({ 'id': member.id, - 'channel': [('insert-and-replace', {'id': member.channel_id.id})], - 'persona': [('insert-and-replace', persona)], + 'channel': {'id': member.channel_id.id}, + 'persona': persona, }) return members_formatted_data diff --git a/addons/mail/models/mail_channel_rtc_session.py b/addons/mail/models/mail_channel_rtc_session.py index 08692111871..e84a2229e01 100644 --- a/addons/mail/models/mail_channel_rtc_session.py +++ b/addons/mail/models/mail_channel_rtc_session.py @@ -99,7 +99,7 @@ class MailRtcSession(models.Model): self.ensure_one() vals = { 'id': self.id, - 'channelMember': [('insert-and-replace', self.channel_member_id.mail_channel_member_format()[0])], + 'channelMember': self.channel_member_id.mail_channel_member_format()[0], } if complete_info: vals.update({ diff --git a/addons/mail/models/mail_message.py b/addons/mail/models/mail_message.py index cd4b51e9bb5..5f86648fcf7 100644 --- a/addons/mail/models/mail_message.py +++ b/addons/mail/models/mail_message.py @@ -869,20 +869,20 @@ class Message(models.Model): reactions_per_content = defaultdict(lambda: self.env['mail.message.reaction']) for reaction in message_sudo.reaction_ids: reactions_per_content[reaction.content] |= reaction - reaction_groups = [('insert-and-replace', [{ + reaction_groups = [{ 'content': content, 'count': len(reactions), - 'guests': [('insert-and-replace', [{'id': guest.id, 'name': guest.name} for guest in reactions.guest_id])], - 'message': [('insert-and-replace', {'id': message_sudo.id})], - 'partners': [('insert-and-replace', [{'id': partner.id, 'name': partner.name} for partner in reactions.partner_id])], - } for content, reactions in reactions_per_content.items()])] + 'guests': [{'id': guest.id, 'name': guest.name} for guest in reactions.guest_id], + 'message': {'id': message_sudo.id}, + 'partners': [{'id': partner.id, 'name': partner.name} for partner in reactions.partner_id], + } for content, reactions in reactions_per_content.items()] if format_reply and message_sudo.model == 'mail.channel' and message_sudo.parent_id: vals['parentMessage'] = message_sudo.parent_id.message_format(format_reply=False)[0] allowed_tracking_ids = message_sudo.tracking_value_ids.filtered(lambda tracking: not tracking.field_groups or self.env.is_superuser() or self.user_has_groups(tracking.field_groups)) vals.update({ 'notifications': message_sudo.notification_ids._filtered_for_web_client()._notification_format(), - 'attachment_ids': [('insert-and-replace', message_sudo.attachment_ids._attachment_format())] if not legacy else message_sudo.attachment_ids._attachment_format(legacy=True), - 'trackingValues': [('insert-and-replace', allowed_tracking_ids._tracking_value_format())], + 'attachment_ids': message_sudo.attachment_ids._attachment_format() if not legacy else message_sudo.attachment_ids._attachment_format(legacy=True), + 'trackingValues': allowed_tracking_ids._tracking_value_format(), 'messageReactionGroups': reaction_groups, 'record_name': record_name, }) @@ -913,30 +913,30 @@ class Message(models.Model): 'body': HTML content of the message 'model': u'res.partner', 'record_name': u'Agrolait', - 'attachment_ids': [('insert-and-replace', [ + 'attachment_ids': [ { 'file_type_icon': u'webimage', 'id': 45, 'name': u'sample.png', 'filename': u'sample.png' } - ])], + ], 'needaction_partner_ids': [], # list of partner ids 'res_id': 7, - 'trackingValues': [('insert-and-replace', + 'trackingValues': [ { 'changedField': "Customer", 'id': 2965, - 'newValue': [('insert-and-replace', { + 'newValue': { 'currencyId': "", 'fieldType': 'char', 'value': "Axelor", - })], - 'oldValue': [('insert-and-replace', { + ], + 'oldValue': { 'currencyId': "", 'fieldType': 'char', 'value': "", - })], + ], } ], 'author_id': (3, u'Administrator'), diff --git a/addons/mail/models/mail_thread.py b/addons/mail/models/mail_thread.py index 49cd4487ed7..95fbd065409 100644 --- a/addons/mail/models/mail_thread.py +++ b/addons/mail/models/mail_thread.py @@ -3164,7 +3164,7 @@ class MailThread(models.AbstractModel): res['activities'] = self.activity_ids.activity_format() if 'attachments' in request_list: res['attachments'] = self._get_mail_thread_data_attachments()._attachment_format() - res['mainAttachment'] = [('insert-and-replace', {'id': self.message_main_attachment_id.id})] if self.message_main_attachment_id else [('clear',)] + res['mainAttachment'] = {'id': self.message_main_attachment_id.id} if self.message_main_attachment_id else [('clear',)] if 'followers' in request_list: res['followers'] = [{ 'id': follower.id, diff --git a/addons/mail/models/mail_tracking_value.py b/addons/mail/models/mail_tracking_value.py index adc3f64407c..d6665f4a48c 100644 --- a/addons/mail/models/mail_tracking_value.py +++ b/addons/mail/models/mail_tracking_value.py @@ -92,14 +92,16 @@ class MailTracking(models.Model): tracking_values = [{ 'changedField': tracking.field_desc, 'id': tracking.id, - 'newValue': [('insert-and-replace', { + 'newValue': { 'currencyId': tracking.currency_id.id, 'fieldType': tracking.field_type, - 'value': tracking._get_new_display_value()[0]})], - 'oldValue': [('insert-and-replace', { + 'value': tracking._get_new_display_value()[0], + }, + 'oldValue': { 'currencyId': tracking.currency_id.id, 'fieldType': tracking.field_type, - 'value': tracking._get_old_display_value()[0]})], + 'value': tracking._get_old_display_value()[0], + }, } for tracking in self] return tracking_values diff --git a/addons/mail/models/res_users_settings.py b/addons/mail/models/res_users_settings.py index f76a49d0c20..1e2550fea8c 100644 --- a/addons/mail/models/res_users_settings.py +++ b/addons/mail/models/res_users_settings.py @@ -35,7 +35,7 @@ class ResUsersSettings(models.Model): fields_to_format = [name for name, field in self._fields.items() if name == 'id' or not field.automatic] res = self._read_format(fnames=fields_to_format)[0] if 'user_id' in fields_to_format: - res['user_id'] = [('insert-and-replace', {'id': self.user_id.id})] + res['user_id'] = {'id': self.user_id.id} if 'volume_settings_ids' in fields_to_format: volume_settings = self.volume_settings_ids._discuss_users_settings_volume_format() res['volume_settings_ids'] = [('insert', volume_settings)] diff --git a/addons/mail/models/res_users_settings_volumes.py b/addons/mail/models/res_users_settings_volumes.py index 66a5afc3ff4..1ec304522ab 100644 --- a/addons/mail/models/res_users_settings_volumes.py +++ b/addons/mail/models/res_users_settings_volumes.py @@ -26,15 +26,15 @@ class ResUsersSettingsVolumes(models.Model): return [{ 'id': volume_setting.id, 'volume': volume_setting.volume, - 'guest_id': [('insert-and-replace', { + 'guest_id': { 'id': volume_setting.guest_id.id, 'name': volume_setting.guest_id.name, - })] if volume_setting.guest_id else [('clear',)], - 'partner_id': [('insert-and-replace', { + } if volume_setting.guest_id else [('clear',)], + 'partner_id': { 'id': volume_setting.partner_id.id, 'name': volume_setting.partner_id.name, - })] if volume_setting.partner_id else [('clear',)], - 'user_setting_id': [('insert-and-replace', { + } if volume_setting.partner_id else [('clear',)], + 'user_setting_id': { 'id': volume_setting.user_setting_id.id, - })], + }, } for volume_setting in self] diff --git a/addons/mail/static/src/components/discuss_container/discuss_container.js b/addons/mail/static/src/components/discuss_container/discuss_container.js index bd506cbaa15..d05c9b7d6c8 100644 --- a/addons/mail/static/src/components/discuss_container/discuss_container.js +++ b/addons/mail/static/src/components/discuss_container/discuss_container.js @@ -3,7 +3,6 @@ import { useModels } from '@mail/component_hooks/use_models'; // ensure component is registered before-hand import '@mail/components/discuss/discuss'; -import { insertAndReplace } from '@mail/model/model_field_command'; import { getMessagingComponent } from "@mail/utils/messaging_component"; const { Component, onWillDestroy } = owl; @@ -25,9 +24,9 @@ export class DiscussContainer extends Component { 'mail.box_inbox'; this.discuss = this.messaging.discuss; this.discuss.update({ - discussView: insertAndReplace({ + discussView: { actionId: action.id, - }), + }, initActiveId, }); // Wait for messaging to be initialized to make sure the system diff --git a/addons/mail/static/src/model/model_core.js b/addons/mail/static/src/model/model_core.js index 5e80c0d3351..bd925c7551a 100644 --- a/addons/mail/static/src/model/model_core.js +++ b/addons/mail/static/src/model/model_core.js @@ -10,7 +10,7 @@ */ export const registry = new Map(); - +export const IS_RECORD = Symbol("Record"); /** * Concats `contextMessage` at the beginning of any error raising when calling diff --git a/addons/mail/static/src/model/model_field.js b/addons/mail/static/src/model/model_field.js index 4bcc179d9ca..097a666792c 100644 --- a/addons/mail/static/src/model/model_field.js +++ b/addons/mail/static/src/model/model_field.js @@ -1,6 +1,7 @@ /** @odoo-module **/ import { clear, FieldCommand, link, unlink, unlinkAll } from '@mail/model/model_field_command'; +import { IS_RECORD } from '@mail/model/model_core'; /** * Class whose instances represent field on a model. @@ -261,9 +262,20 @@ export class ModelField { } else if (newVal instanceof Array && newVal[0] instanceof FieldCommand) { return newVal; } else if (this.fieldType === 'relation') { - if (newVal instanceof Array && newVal[0] && ['clear', 'insert', 'insert-and-replace', 'insert-and-unlink', 'link', 'replace', 'unlink', 'unlink-all'].includes(newVal[0][0])) { + if (newVal instanceof Array && newVal[0] instanceof Array && ['clear', 'insert', 'insert-and-replace', 'insert-and-unlink', 'link', 'replace', 'unlink', 'unlink-all'].includes(newVal[0][0])) { + // newVal: [['insert', ...], ...] return newVal.map(([name, value]) => new FieldCommand(name, value)); + } else if (newVal instanceof Array && newVal[0] && !newVal[0][IS_RECORD]) { + // newVal: [data, ...] + return [new FieldCommand('insert-and-replace', newVal)]; + } else if (newVal instanceof Array && newVal[0]) { + // newVal: [record, ...] + return [new FieldCommand('replace', newVal)]; + } else if (!newVal[IS_RECORD]) { + // newVal: data + return [new FieldCommand('insert-and-replace', newVal)]; } else { + // newVal: record return [new FieldCommand('replace', newVal)]; } } else { @@ -846,7 +858,7 @@ export class ModelField { if (!record) { throw Error(`record is undefined. Did you try to link() or insert() empty value? Considering clear() instead.`); } - if (!record.modelManager) { + if (!record[IS_RECORD]) { throw Error(`${record} is not a record. Did you try to use link() instead of insert() with data?`); } const otherModel = record.modelManager.models[this.to]; diff --git a/addons/mail/static/src/model/model_field_command.js b/addons/mail/static/src/model/model_field_command.js index 3d4b62278b4..6922f7bd128 100644 --- a/addons/mail/static/src/model/model_field_command.js +++ b/addons/mail/static/src/model/model_field_command.js @@ -93,20 +93,6 @@ function insert(data) { return new FieldCommand('insert', data); } -/** - * Returns a insert-and-replace command to give to the model manager at create/update. - * `insertAndReplace` command can be used for relation fields. - * - Create new record(s) from data if the record(s) do not exist; - * - or update the record(s) if they can be found from identifying data; - * - and then replace the record(s) for a relation field. - * - * @param {Object|Object[]} [data={}] - data object or data objects array to insert and replace record(s). - * @returns {FieldCommand} - */ -function insertAndReplace(data = {}) { - return new FieldCommand('insert-and-replace', data); -} - /** * Returns a insert-and-unlink command to give to the model manager at create/update. * `insertAndUnlink` command can be used for relation fields. @@ -179,7 +165,6 @@ export { decrement, increment, insert, - insertAndReplace, link, set, unlink, diff --git a/addons/mail/static/src/model/model_manager.js b/addons/mail/static/src/model/model_manager.js index 13486e846e4..a65a1380a6d 100644 --- a/addons/mail/static/src/model/model_manager.js +++ b/addons/mail/static/src/model/model_manager.js @@ -1,6 +1,6 @@ /** @odoo-module **/ -import { registry } from '@mail/model/model_core'; +import { IS_RECORD, registry } from '@mail/model/model_core'; import { ModelField } from '@mail/model/model_field'; import { ModelIndexAnd } from '@mail/model/model_index_and'; import { ModelIndexXor } from '@mail/model/model_index_xor'; @@ -642,6 +642,7 @@ export class ModelManager { __listeners: [], // Field values of record. __values: {}, + [IS_RECORD]: true, }); const record = owl.markRaw(!this.isDebug ? nonProxyRecord : new Proxy(nonProxyRecord, { get: function getFromProxy(record, prop) { diff --git a/addons/mail/static/src/models/activity_box_view.js b/addons/mail/static/src/models/activity_box_view.js index 1d9e78797a8..7dccf103050 100644 --- a/addons/mail/static/src/models/activity_box_view.js +++ b/addons/mail/static/src/models/activity_box_view.js @@ -2,7 +2,6 @@ import { registerModel } from '@mail/model/model_core'; import { attr, many, one } from '@mail/model/model_field'; -import { insertAndReplace } from '@mail/model/model_field_command'; registerModel({ name: 'ActivityBoxView', @@ -19,9 +18,9 @@ registerModel({ * @returns {FieldCommand} */ _computeActivityViews() { - return insertAndReplace(this.chatter.thread.activities.map(activity => { + return this.chatter.thread.activities.map(activity => { return { activity }; - })); + }); }, }, fields: { diff --git a/addons/mail/static/src/models/activity_group.js b/addons/mail/static/src/models/activity_group.js index 9d9f3799de6..69ff6a06f3d 100644 --- a/addons/mail/static/src/models/activity_group.js +++ b/addons/mail/static/src/models/activity_group.js @@ -2,7 +2,6 @@ import { registerModel } from '@mail/model/model_core'; import { attr, many, one } from '@mail/model/model_field'; -import { insertAndReplace } from '@mail/model/model_field_command'; import { OnChange } from '@mail/model/model_onchange'; registerModel({ @@ -12,12 +11,12 @@ registerModel({ return { actions: data.actions, domain: data.domain, - irModel: insertAndReplace({ + irModel: { iconUrl: data.icon, id: data.id, model: data.model, name: data.name, - }), + }, overdue_count: data.overdue_count, planned_count: data.planned_count, today_count: data.today_count, diff --git a/addons/mail/static/src/models/activity_menu_view.js b/addons/mail/static/src/models/activity_menu_view.js index 0a139cfd58d..b9818871838 100644 --- a/addons/mail/static/src/models/activity_menu_view.js +++ b/addons/mail/static/src/models/activity_menu_view.js @@ -2,7 +2,6 @@ import { registerModel } from '@mail/model/model_core'; import { attr, many } from '@mail/model/model_field'; -import { insertAndReplace } from '@mail/model/model_field_command'; import session from 'web.session'; @@ -29,7 +28,7 @@ registerModel({ kwargs: { context: session.user_context }, }); this.update({ - activityGroups: insertAndReplace(data.map(vals => this.messaging.models['ActivityGroup'].convertData(vals))), + activityGroups: data.map(vals => this.messaging.models['ActivityGroup'].convertData(vals)), extraCount: 0, }); }, @@ -68,11 +67,11 @@ registerModel({ * @returns {FieldCommand} */ _computeActivityGroupViews() { - return insertAndReplace(this.activityGroups.map(activityGroup => { + return this.activityGroups.map(activityGroup => { return { activityGroup, }; - })); + }); }, /** * @private diff --git a/addons/mail/static/src/models/activity_view.js b/addons/mail/static/src/models/activity_view.js index 43b290776c1..8f02d8aa616 100644 --- a/addons/mail/static/src/models/activity_view.js +++ b/addons/mail/static/src/models/activity_view.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, many, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; import { auto_str_to_date, getLangDateFormat, getLangDatetimeFormat } from 'web.time'; import { sprintf } from '@web/core/utils/strings'; @@ -57,7 +57,7 @@ registerModel({ } }, onClickMarkDoneButton() { - this.update({ markDonePopoverView: this.markDonePopoverView ? clear() : insertAndReplace() }); + this.update({ markDonePopoverView: this.markDonePopoverView ? clear() : {} }); }, /** * Handles the click on the upload document button. This open the file @@ -108,7 +108,7 @@ registerModel({ * @returns {FieldCommand} */ _computeFileUploader() { - return this.activity.category === 'upload_file' ? insertAndReplace() : clear(); + return this.activity.category === 'upload_file' ? {} : clear(); }, /** * @private @@ -139,14 +139,7 @@ registerModel({ * @returns {FieldCommand} */ _computeMailTemplateViews() { - if (this.activity.mailTemplates.length === 0) { - return clear(); - } - return insertAndReplace( - this.activity.mailTemplates.map( - mailTemplate => ({ mailTemplate }) - ), - ); + return this.activity.mailTemplates.map(mailTemplate => ({ mailTemplate })); }, /** * @private @@ -188,11 +181,11 @@ registerModel({ compute: '_computeAssignedUserText', }), clockWatcher: one('ClockWatcher', { - default: insertAndReplace({ - clock: insertAndReplace({ + default: { + clock: { frequency: 60 * 1000, - }), - }), + }, + }, inverse: 'activityViewOwner', isCausal: true, }), diff --git a/addons/mail/static/src/models/attachment_box_view.js b/addons/mail/static/src/models/attachment_box_view.js index 33825025fad..b79805fdc32 100644 --- a/addons/mail/static/src/models/attachment_box_view.js +++ b/addons/mail/static/src/models/attachment_box_view.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; registerModel({ name: 'AttachmentBoxView', @@ -19,7 +19,7 @@ registerModel({ */ _computeAttachmentList() { return (this.chatter.thread && this.chatter.thread.allAttachments.length > 0) - ? insertAndReplace() + ? {} : clear(); }, }, @@ -42,7 +42,7 @@ registerModel({ */ component: attr(), fileUploader: one('FileUploader', { - default: insertAndReplace(), + default: {}, inverse: 'attachmentBoxView', isCausal: true, readonly: true, diff --git a/addons/mail/static/src/models/attachment_card.js b/addons/mail/static/src/models/attachment_card.js index a06a6a9fb63..5e6ce65311c 100644 --- a/addons/mail/static/src/models/attachment_card.js +++ b/addons/mail/static/src/models/attachment_card.js @@ -2,7 +2,6 @@ import { registerModel } from '@mail/model/model_core'; import { attr, one } from '@mail/model/model_field'; -import { insertAndReplace } from '@mail/model/model_field_command'; registerModel({ name: 'AttachmentCard', @@ -15,7 +14,7 @@ registerModel({ return; } this.attachmentList.update({ - attachmentListViewDialog: insertAndReplace(), + attachmentListViewDialog: {}, selectedAttachment: this.attachment, }); }, @@ -32,7 +31,7 @@ registerModel({ if (this.attachmentList.composerViewOwner) { this.attachment.remove(); } else { - this.update({ attachmentDeleteConfirmDialog: insertAndReplace() }); + this.update({ attachmentDeleteConfirmDialog: {} }); } }, /** diff --git a/addons/mail/static/src/models/attachment_image.js b/addons/mail/static/src/models/attachment_image.js index 7dc6ab1c849..f69cb01c3b8 100644 --- a/addons/mail/static/src/models/attachment_image.js +++ b/addons/mail/static/src/models/attachment_image.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; import { isEventHandled, markEventHandled } from '@mail/utils/utils'; registerModel({ @@ -36,7 +36,7 @@ registerModel({ return; } this.attachmentList.update({ - attachmentListViewDialog: insertAndReplace(), + attachmentListViewDialog: {}, selectedAttachment: this.attachment, }); }, @@ -53,7 +53,7 @@ registerModel({ if (this.attachmentList.composerViewOwner) { this.attachment.remove(); } else { - this.update({ attachmentDeleteConfirmDialog: insertAndReplace() }); + this.update({ attachmentDeleteConfirmDialog: {} }); } }, /** diff --git a/addons/mail/static/src/models/attachment_list.js b/addons/mail/static/src/models/attachment_list.js index cf6c71d9e54..873d9b9960d 100644 --- a/addons/mail/static/src/models/attachment_list.js +++ b/addons/mail/static/src/models/attachment_list.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, many, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; registerModel({ name: 'AttachmentList', @@ -25,18 +25,10 @@ registerModel({ this.update({ selectedAttachment: this.attachments[prevIndex] }); }, _computeAttachmentImages() { - return insertAndReplace(this.imageAttachments.map(attachment => { - return { - attachment, - }; - })); + return this.imageAttachments.map(attachment => ({ attachment })); }, _computeAttachmentCards() { - return insertAndReplace(this.nonImageAttachments.map(attachment => { - return { - attachment, - }; - })); + return this.nonImageAttachments.map(attachment => ({ attachment })); }, /** * @returns {FieldCommand} diff --git a/addons/mail/static/src/models/attachment_viewer.js b/addons/mail/static/src/models/attachment_viewer.js index 0fc71ff51e2..80e032e39b0 100644 --- a/addons/mail/static/src/models/attachment_viewer.js +++ b/addons/mail/static/src/models/attachment_viewer.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, many, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; registerModel({ name: 'AttachmentViewer', @@ -184,9 +184,9 @@ registerModel({ */ _computeAttachmentViewerViewable() { if (this.attachmentList) { - return insertAndReplace({ + return { attachmentOwner: this.attachmentList.selectedAttachment, - }); + }; } return clear(); }, @@ -195,11 +195,9 @@ registerModel({ */ _computeAttachmentViewerViewables() { if (this.attachmentList) { - return insertAndReplace( - this.attachmentList.viewableAttachments.map((attachment) => { - return { attachmentOwner: attachment }; - }) - ); + return this.attachmentList.viewableAttachments.map(attachment => { + return { attachmentOwner: attachment }; + }); } return clear(); }, diff --git a/addons/mail/static/src/models/call_action_list_view.js b/addons/mail/static/src/models/call_action_list_view.js index c97c6f23f60..e87b2238f7a 100644 --- a/addons/mail/static/src/models/call_action_list_view.js +++ b/addons/mail/static/src/models/call_action_list_view.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; registerModel({ name: 'CallActionListView', @@ -175,7 +175,7 @@ registerModel({ compute: '_computeMicrophoneButtonTitle', }), callOptionMenu: one('CallOptionMenu', { - default: insertAndReplace(), + default: {}, inverse: 'callActionListView', isCausal: true, }), diff --git a/addons/mail/static/src/models/call_main_view.js b/addons/mail/static/src/models/call_main_view.js index 3fbe5d7bc22..815e7dbd667 100644 --- a/addons/mail/static/src/models/call_main_view.js +++ b/addons/mail/static/src/models/call_main_view.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, many, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; import { isEventHandled, markEventHandled } from '@mail/utils/utils'; @@ -109,7 +109,10 @@ registerModel({ }); }, onShowOverlayTimeout() { - this.update({ showOverlay: false }); + this.update({ + showOverlay: false, + showOverlayTimer: clear(), + }); }, //---------------------------------------------------------------------- @@ -135,9 +138,9 @@ registerModel({ */ _computeMainTiles() { if (this.callView.activeRtcSession) { - return insertAndReplace([{ channelMember: this.callView.activeRtcSession.channelMember }]); + return [{ channelMember: this.callView.activeRtcSession.channelMember }]; } - return insertAndReplace(this.callView.filteredChannelMembers.map(channelMember => ({ channelMember }))); + return this.callView.filteredChannelMembers.map(channelMember => ({ channelMember })); }, /** * Shows the overlay (buttons) for a set a mount of time. @@ -147,7 +150,7 @@ registerModel({ _showOverlay() { this.update({ showOverlay: true, - showOverlayTimer: [clear(), insertAndReplace()], + showOverlayTimer: { doReset: this.showOverlayTimer ? true : undefined }, }); }, }, @@ -156,7 +159,7 @@ registerModel({ * The model for the controller (buttons). */ callActionListView: one('CallActionListView', { - default: insertAndReplace(), + default: {}, inverse: 'callMainView', isCausal: true, readonly: true, diff --git a/addons/mail/static/src/models/call_main_view_tile.js b/addons/mail/static/src/models/call_main_view_tile.js index 3c379253bd7..7f5702525f8 100644 --- a/addons/mail/static/src/models/call_main_view_tile.js +++ b/addons/mail/static/src/models/call_main_view_tile.js @@ -1,7 +1,6 @@ /** @odoo-module **/ import { registerModel } from '@mail/model/model_core'; -import { insertAndReplace } from '@mail/model/model_field_command'; import { one } from '@mail/model/model_field'; registerModel({ @@ -15,7 +14,7 @@ registerModel({ identifying: true, }), participantCard: one('CallParticipantCard', { - default: insertAndReplace(), + default: {}, inverse: 'mainViewTileOwner', isCausal: true, }), diff --git a/addons/mail/static/src/models/call_participant_card.js b/addons/mail/static/src/models/call_participant_card.js index 2de8ca31b65..cd168b942be 100644 --- a/addons/mail/static/src/models/call_participant_card.js +++ b/addons/mail/static/src/models/call_participant_card.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; import { isEventHandled, markEventHandled } from '@mail/utils/utils'; import { sprintf } from '@web/core/utils/strings'; @@ -145,7 +145,7 @@ registerModel({ */ _computeCallParticipantVideoView() { if (this.rtcSession && this.rtcSession.videoStream) { - return insertAndReplace(); + return {}; } return clear(); }, diff --git a/addons/mail/static/src/models/call_sidebar_view.js b/addons/mail/static/src/models/call_sidebar_view.js index d5aafaf7165..29195caf299 100644 --- a/addons/mail/static/src/models/call_sidebar_view.js +++ b/addons/mail/static/src/models/call_sidebar_view.js @@ -2,7 +2,6 @@ import { registerModel } from '@mail/model/model_core'; import { many, one } from '@mail/model/model_field'; -import { insertAndReplace } from '@mail/model/model_field_command'; registerModel({ name: 'CallSidebarView', @@ -12,7 +11,7 @@ registerModel({ * @returns {FieldCommand} */ _computeSidebarTiles() { - return insertAndReplace(this.callView.filteredChannelMembers.map(channelMember => ({ channelMember }))); + return this.callView.filteredChannelMembers.map(channelMember => ({ channelMember })); }, }, fields: { diff --git a/addons/mail/static/src/models/call_sidebar_view_tile.js b/addons/mail/static/src/models/call_sidebar_view_tile.js index 3bbf1ddcb36..89cfcf444dd 100644 --- a/addons/mail/static/src/models/call_sidebar_view_tile.js +++ b/addons/mail/static/src/models/call_sidebar_view_tile.js @@ -1,7 +1,6 @@ /** @odoo-module **/ import { registerModel } from '@mail/model/model_core'; -import { insertAndReplace } from '@mail/model/model_field_command'; import { one } from '@mail/model/model_field'; registerModel({ @@ -15,7 +14,7 @@ registerModel({ identifying: true, }), participantCard: one('CallParticipantCard', { - default: insertAndReplace(), + default: {}, inverse: 'sidebarViewTileOwner', isCausal: true, }), diff --git a/addons/mail/static/src/models/call_view.js b/addons/mail/static/src/models/call_view.js index 5c5eee61e36..1d69a95ba55 100644 --- a/addons/mail/static/src/models/call_view.js +++ b/addons/mail/static/src/models/call_view.js @@ -5,7 +5,7 @@ import { browser } from "@web/core/browser/browser"; import { registerModel } from '@mail/model/model_core'; import { attr, many, one } from '@mail/model/model_field'; import { OnChange } from '@mail/model/model_onchange'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; registerModel({ name: 'CallView', @@ -80,7 +80,7 @@ registerModel({ */ _computeCallSideBarView() { if (this.activeRtcSession && this.isSidebarOpen && !this.threadView.compact) { - return insertAndReplace(); + return {}; } return clear(); }, @@ -163,7 +163,7 @@ registerModel({ compute: '_computeAspectRatio', }), callMainView: one('CallMainView', { - default: insertAndReplace(), + default: {}, inverse: 'callView', isCausal: true, readonly: true, diff --git a/addons/mail/static/src/models/canned_response.js b/addons/mail/static/src/models/canned_response.js index 0b4b0ab9ba2..884e7070e29 100644 --- a/addons/mail/static/src/models/canned_response.js +++ b/addons/mail/static/src/models/canned_response.js @@ -2,7 +2,6 @@ import { registerModel } from '@mail/model/model_core'; import { attr, one } from '@mail/model/model_field'; -import { insertAndReplace } from '@mail/model/model_field_command'; import { cleanSearchTerm } from '@mail/utils/utils'; registerModel({ @@ -82,7 +81,7 @@ registerModel({ */ substitution: attr(), suggestable: one('ComposerSuggestable', { - default: insertAndReplace(), + default: {}, inverse: 'cannedResponse', isCausal: true, readonly: true, diff --git a/addons/mail/static/src/models/channel.js b/addons/mail/static/src/models/channel.js index 804fd48d257..39f3ead3e8c 100644 --- a/addons/mail/static/src/models/channel.js +++ b/addons/mail/static/src/models/channel.js @@ -2,7 +2,6 @@ import { registerModel } from '@mail/model/model_core'; import { attr, one, many } from '@mail/model/model_field'; -import { insertAndReplace } from '@mail/model/model_field_command'; registerModel({ name: 'Channel', @@ -44,10 +43,10 @@ registerModel({ * @returns {FieldCommand} */ _computeThread() { - return insertAndReplace({ + return { id: this.id, model: 'mail.channel', - }); + }; }, /** * @private diff --git a/addons/mail/static/src/models/channel_command.js b/addons/mail/static/src/models/channel_command.js index 1d3a9481736..2090049a2dd 100644 --- a/addons/mail/static/src/models/channel_command.js +++ b/addons/mail/static/src/models/channel_command.js @@ -2,7 +2,6 @@ import { registerModel } from '@mail/model/model_core'; import { attr, one } from '@mail/model/model_field'; -import { insertAndReplace } from '@mail/model/model_field_command'; import { cleanSearchTerm } from '@mail/utils/utils'; registerModel({ @@ -130,7 +129,7 @@ registerModel({ identifying: true, }), suggestable: one('ComposerSuggestable', { - default: insertAndReplace(), + default: {}, inverse: 'channelCommand', isCausal: true, readonly: true, diff --git a/addons/mail/static/src/models/channel_invitation_form.js b/addons/mail/static/src/models/channel_invitation_form.js index 2a4c9d0a458..af5ff572c67 100644 --- a/addons/mail/static/src/models/channel_invitation_form.js +++ b/addons/mail/static/src/models/channel_invitation_form.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, many, one } from '@mail/model/model_field'; -import { clear, insertAndReplace, link, unlink } from '@mail/model/model_field_command'; +import { clear, link, unlink } from '@mail/model/model_field_command'; import { cleanSearchTerm } from '@mail/utils/utils'; import { sprintf } from '@web/core/utils/strings'; @@ -147,7 +147,7 @@ registerModel({ } this.update({ searchResultCount: count, - selectablePartners: insertAndReplace(partnersData.map(partnerData => this.messaging.models['Partner'].convertData(partnerData))), + selectablePartners: partnersData.map(partnerData => this.messaging.models['Partner'].convertData(partnerData)), }); } finally { if (this.exists()) { @@ -201,7 +201,7 @@ registerModel({ if (this.selectablePartners.length === 0) { return clear(); } - return insertAndReplace(this.selectablePartners.map(partner => ({ partner }))); + return this.selectablePartners.map(partner => ({ partner })); }, /** * @private @@ -211,7 +211,7 @@ registerModel({ if (this.selectedPartners.length === 0) { return clear(); } - return insertAndReplace(this.selectedPartners.map(partner => ({ partner }))); + return this.selectedPartners.map(partner => ({ partner })); }, /** * @private diff --git a/addons/mail/static/src/models/channel_invitation_form_selectable_partner_view.js b/addons/mail/static/src/models/channel_invitation_form_selectable_partner_view.js index c23a683cdfe..558e3e4a662 100644 --- a/addons/mail/static/src/models/channel_invitation_form_selectable_partner_view.js +++ b/addons/mail/static/src/models/channel_invitation_form_selectable_partner_view.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; registerModel({ name: 'ChannelInvitationFormSelectablePartnerView', @@ -12,7 +12,7 @@ registerModel({ * @returns {FieldCommand} */ _computePersonaImStatusIconView() { - return this.partner.isImStatusSet ? insertAndReplace() : clear(); + return this.partner.isImStatusSet ? {} : clear(); }, }, fields: { diff --git a/addons/mail/static/src/models/channel_member_list_category_view.js b/addons/mail/static/src/models/channel_member_list_category_view.js index 74dd688cbb5..2a256c3d53e 100644 --- a/addons/mail/static/src/models/channel_member_list_category_view.js +++ b/addons/mail/static/src/models/channel_member_list_category_view.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, many, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; import { sprintf } from '@web/core/utils/strings'; @@ -30,9 +30,7 @@ registerModel({ if (this.members.length === 0) { return clear(); } - return insertAndReplace( - this.members.map(channelMember => ({ channelMember })), - ); + return this.members.map(channelMember => ({ channelMember })); }, /** * @private diff --git a/addons/mail/static/src/models/channel_member_list_view.js b/addons/mail/static/src/models/channel_member_list_view.js index a542730c41a..ad929a29e4e 100644 --- a/addons/mail/static/src/models/channel_member_list_view.js +++ b/addons/mail/static/src/models/channel_member_list_view.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; registerModel({ name: 'ChannelMemberListView', @@ -38,7 +38,7 @@ registerModel({ */ _computeOfflineCategoryView() { if (this.channel && this.channel.orderedOfflineMembers.length > 0) { - return insertAndReplace(); + return {}; } return clear(); }, @@ -48,7 +48,7 @@ registerModel({ */ _computeOnlineCategoryView() { if (this.channel && this.channel.orderedOnlineMembers.length > 0) { - return insertAndReplace(); + return {}; } return clear(); }, diff --git a/addons/mail/static/src/models/channel_member_view.js b/addons/mail/static/src/models/channel_member_view.js index fe17cdf4bfa..fbdabc5ea1e 100644 --- a/addons/mail/static/src/models/channel_member_view.js +++ b/addons/mail/static/src/models/channel_member_view.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; import { isEventHandled } from '@mail/utils/utils'; registerModel({ @@ -39,9 +39,9 @@ registerModel({ */ _computePersonaImStatusIconView() { if (this.channelMember.persona.guest && this.channelMember.persona.guest.im_status) { - return insertAndReplace(); + return {}; } - return this.channelMember.persona.partner && this.channelMember.persona.partner.isImStatusSet ? insertAndReplace() : clear(); + return this.channelMember.persona.partner && this.channelMember.persona.partner.isImStatusSet ? {} : clear(); }, }, fields: { diff --git a/addons/mail/static/src/models/chat_window.js b/addons/mail/static/src/models/chat_window.js index 0b11ea4f159..ca3a6b5a0cc 100644 --- a/addons/mail/static/src/models/chat_window.js +++ b/addons/mail/static/src/models/chat_window.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; import { isEventHandled, markEventHandled } from '@mail/utils/utils'; registerModel({ @@ -231,9 +231,9 @@ registerModel({ onClickShowInviteForm(ev) { markEventHandled(ev, 'ChatWindow.onClickCommand'); this.update({ - channelInvitationForm: insertAndReplace({ + channelInvitationForm: { doFocusOnSearchInput: true, - }), + }, isMemberListOpened: false, }); if (!this.messaging.isCurrentUserGuest) { @@ -348,7 +348,7 @@ registerModel({ */ _computeChannelMemberListView() { if (this.thread && this.thread.hasMemberListFeature && this.isMemberListOpened) { - return insertAndReplace(); + return {}; } return clear(); }, @@ -463,7 +463,7 @@ registerModel({ */ _computeNewMessageAutocompleteInputView() { if (this.hasNewMessageForm) { - return insertAndReplace(); + return {}; } return clear(); }, @@ -479,11 +479,11 @@ registerModel({ * @returns {ThreadViewer} */ _computeThreadViewer() { - return insertAndReplace({ + return { compact: true, hasThreadView: this.hasThreadView, thread: this.thread ? this.thread : clear(), - }); + }; }, /** * @private @@ -573,7 +573,7 @@ registerModel({ isCausal: true, }), chatWindowHeaderView: one('ChatWindowHeaderView', { - default: insertAndReplace(), + default: {}, inverse: 'chatWindowOwner', isCausal: true, }), diff --git a/addons/mail/static/src/models/chat_window_manager.js b/addons/mail/static/src/models/chat_window_manager.js index 9d2d71e10cd..22175d6d80d 100644 --- a/addons/mail/static/src/models/chat_window_manager.js +++ b/addons/mail/static/src/models/chat_window_manager.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, many, one } from '@mail/model/model_field'; -import { clear, insertAndReplace, link } from '@mail/model/model_field_command'; +import { clear, link } from '@mail/model/model_field_command'; const BASE_VISUAL = { /** @@ -86,7 +86,7 @@ registerModel({ }, openNewMessage() { if (!this.newMessageChatWindow) { - this.update({ newMessageChatWindow: insertAndReplace({ manager: this }) }); + this.update({ newMessageChatWindow: { manager: this } }); } this.newMessageChatWindow.makeActive(); }, @@ -207,7 +207,7 @@ registerModel({ */ _computeHiddenChatWindowHeaderViews() { if (this.allOrderedHidden.length > 0) { - return insertAndReplace(this.allOrderedHidden.map(chatWindow => ({ chatWindowOwner: chatWindow }))); + return this.allOrderedHidden.map(chatWindow => ({ chatWindowOwner: chatWindow })); } return clear(); }, diff --git a/addons/mail/static/src/models/chatter.js b/addons/mail/static/src/models/chatter.js index 7bf905fa7d3..f4b44bd641b 100644 --- a/addons/mail/static/src/models/chatter.js +++ b/addons/mail/static/src/models/chatter.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, one } from '@mail/model/model_field'; -import { clear, insert, insertAndReplace, link } from '@mail/model/model_field_command'; +import { clear, insert, link } from '@mail/model/model_field_command'; import { OnChange } from '@mail/model/model_onchange'; const getThreadNextTemporaryId = (function () { @@ -30,7 +30,10 @@ registerModel({ } }, onAttachmentsLoadingTimeout() { - this.update({ isShowingAttachmentsLoading: true }); + this.update({ + attachmentsLoaderTimer: clear(), + isShowingAttachmentsLoading: true, + }); }, /** * Handles click on the attach button. @@ -42,7 +45,7 @@ registerModel({ * Handles click on the attachments button. */ onClickButtonToggleAttachments() { - this.update({ attachmentBoxView: this.attachmentBoxView ? clear() : insertAndReplace() }); + this.update({ attachmentBoxView: this.attachmentBoxView ? clear() : {} }); }, /** * Handles click on top bar close button. @@ -114,7 +117,7 @@ registerModel({ this.threadView.messageListView.component.onScroll(ev); }, openAttachmentBoxView() { - this.update({ attachmentBoxView: insertAndReplace() }); + this.update({ attachmentBoxView: {} }); }, /** * Open a dialog to add partners as followers. @@ -172,12 +175,12 @@ registerModel({ } }, showLogNote() { - this.update({ composerView: insertAndReplace() }); + this.update({ composerView: {} }); this.composerView.composer.update({ isLog: true }); this.focus(); }, showSendMessage() { - this.update({ composerView: insertAndReplace() }); + this.update({ composerView: {} }); this.composerView.composer.update({ isLog: false }); this.focus(); }, @@ -187,7 +190,7 @@ registerModel({ */ _computeActivityBoxView() { if (this.thread && this.thread.hasActivities && this.thread.activities.length > 0) { - return insertAndReplace(); + return {}; } return clear(); }, @@ -197,7 +200,7 @@ registerModel({ */ _computeDropZoneView() { if (this.useDragVisibleDropZone.isVisible) { - return insertAndReplace(); + return {}; } return clear(); }, @@ -206,7 +209,7 @@ registerModel({ * @returns {FieldCommand} */ _computeFileUploader() { - return this.thread ? insertAndReplace() : clear(); + return this.thread ? {} : clear(); }, /** * @private @@ -214,7 +217,7 @@ registerModel({ */ _computeFollowButtonView() { if (this.hasFollowers && this.thread && (!this.thread.channel || this.thread.channel.channel_type !== 'chat')) { - return insertAndReplace(); + return {}; } return clear(); }, @@ -224,7 +227,7 @@ registerModel({ */ _computeFollowerListMenuView() { if (this.hasFollowers && this.thread) { - return insertAndReplace(); + return {}; } return clear(); }, @@ -261,11 +264,11 @@ registerModel({ * @returns {ThreadViewer} */ _computeThreadViewer() { - return insertAndReplace({ + return { hasThreadView: this.hasThreadView, order: 'desc', thread: this.thread ? this.thread : clear(), - }); + }; }, /** * @private @@ -276,7 +279,7 @@ registerModel({ this.thread.delete(); } this.update({ - attachmentBoxView: this.isAttachmentBoxVisibleInitially ? insertAndReplace() : clear(), + attachmentBoxView: this.isAttachmentBoxVisibleInitially ? {} : clear(), thread: insert({ // If the thread was considered to have the activity // mixin once, it will have it forever. @@ -326,7 +329,7 @@ registerModel({ * @private */ _prepareAttachmentsLoading() { - this.update({ attachmentsLoaderTimer: insertAndReplace() }); + this.update({ attachmentsLoaderTimer: {} }); }, }, fields: { @@ -486,12 +489,12 @@ registerModel({ required: true, }), topbar: one('ChatterTopbar', { - default: insertAndReplace(), + default: {}, inverse: 'chatter', isCausal: true, }), useDragVisibleDropZone: one('UseDragVisibleDropZone', { - default: insertAndReplace(), + default: {}, inverse: 'chatterOwner', isCausal: true, readonly: true, diff --git a/addons/mail/static/src/models/composer_suggested_recipient_list_view.js b/addons/mail/static/src/models/composer_suggested_recipient_list_view.js index b98ec4a866f..dbbb3f5487e 100644 --- a/addons/mail/static/src/models/composer_suggested_recipient_list_view.js +++ b/addons/mail/static/src/models/composer_suggested_recipient_list_view.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, many, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; registerModel({ name: 'ComposerSuggestedRecipientListView', @@ -34,17 +34,9 @@ registerModel({ return clear(); } if (this.hasShowMoreButton) { - return insertAndReplace( - this.thread.suggestedRecipientInfoList.map( - suggestedRecipientInfo => ({ suggestedRecipientInfo }) - ), - ); + return this.thread.suggestedRecipientInfoList.map(suggestedRecipientInfo => ({ suggestedRecipientInfo })); } else { - return insertAndReplace( - this.thread.suggestedRecipientInfoList.slice(0, 3).map( - suggestedRecipientInfo => ({ suggestedRecipientInfo }) - ), - ); + return this.thread.suggestedRecipientInfoList.slice(0, 3).map(suggestedRecipientInfo => ({ suggestedRecipientInfo })); } }, /** diff --git a/addons/mail/static/src/models/composer_suggestion_list_view.js b/addons/mail/static/src/models/composer_suggestion_list_view.js index 1ae7fdba718..775eef2eb80 100644 --- a/addons/mail/static/src/models/composer_suggestion_list_view.js +++ b/addons/mail/static/src/models/composer_suggestion_list_view.js @@ -2,7 +2,6 @@ import { registerModel } from '@mail/model/model_core'; import { attr, many, one } from '@mail/model/model_field'; -import { insertAndReplace } from '@mail/model/model_field_command'; registerModel({ name: 'ComposerSuggestionListView', @@ -73,21 +72,13 @@ registerModel({ * @returns {FieldCommand} */ _computeComposerSuggestionListViewExtraComposerSuggestionViewItems() { - return insertAndReplace(this.composerViewOwner.extraSuggestions.map(suggestable => { - return { - suggestable, - }; - })); + return this.composerViewOwner.extraSuggestions.map(suggestable => ({ suggestable })); }, /** * @returns {FieldCommand} */ _computeComposerSuggestionListViewMainComposerSuggestionViewItems() { - return insertAndReplace(this.composerViewOwner.mainSuggestions.map(suggestable => { - return { - suggestable, - }; - })); + return this.composerViewOwner.mainSuggestions.map(suggestable => ({ suggestable })); }, /** * @returns {FieldCommand} diff --git a/addons/mail/static/src/models/composer_suggestion_list_view_extra_composer_suggestion_view_item.js b/addons/mail/static/src/models/composer_suggestion_list_view_extra_composer_suggestion_view_item.js index 27114c49122..4cb05bb619b 100644 --- a/addons/mail/static/src/models/composer_suggestion_list_view_extra_composer_suggestion_view_item.js +++ b/addons/mail/static/src/models/composer_suggestion_list_view_extra_composer_suggestion_view_item.js @@ -2,7 +2,6 @@ import { registerModel } from '@mail/model/model_core'; import { one } from '@mail/model/model_field'; -import { insertAndReplace } from '@mail/model/model_field_command'; /** * Models a relation between a ComposerSuggestionListView and a @@ -17,7 +16,7 @@ registerModel({ inverse: 'composerSuggestionListViewExtraComposerSuggestionViewItems', }), composerSuggestionView: one('ComposerSuggestionView', { - default: insertAndReplace(), + default: {}, inverse: 'composerSuggestionListViewExtraComposerSuggestionViewItemOwner', isCausal: true, readonly: true, diff --git a/addons/mail/static/src/models/composer_suggestion_list_view_main_composer_suggestion_view_item.js b/addons/mail/static/src/models/composer_suggestion_list_view_main_composer_suggestion_view_item.js index 4dff87a726a..a8c78e310a8 100644 --- a/addons/mail/static/src/models/composer_suggestion_list_view_main_composer_suggestion_view_item.js +++ b/addons/mail/static/src/models/composer_suggestion_list_view_main_composer_suggestion_view_item.js @@ -2,7 +2,6 @@ import { registerModel } from '@mail/model/model_core'; import { one } from '@mail/model/model_field'; -import { insertAndReplace } from '@mail/model/model_field_command'; /** * Models a relation between a ComposerSuggestionListView and a @@ -17,7 +16,7 @@ registerModel({ inverse: 'composerSuggestionListViewMainComposerSuggestionViewItems', }), composerSuggestionView: one('ComposerSuggestionView', { - default: insertAndReplace(), + default: {}, inverse: 'composerSuggestionListViewMainComposerSuggestionViewItemOwner', isCausal: true, readonly: true, diff --git a/addons/mail/static/src/models/composer_suggestion_view.js b/addons/mail/static/src/models/composer_suggestion_view.js index daa9f638607..3a45539c777 100644 --- a/addons/mail/static/src/models/composer_suggestion_view.js +++ b/addons/mail/static/src/models/composer_suggestion_view.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; import { sprintf } from '@web/core/utils/strings'; /** @@ -65,7 +65,7 @@ registerModel({ * @returns {FieldCommand} */ _computePersonaImStatusIconView() { - return this.suggestable && this.suggestable.partner && this.suggestable.partner.isImStatusSet ? insertAndReplace() : clear(); + return this.suggestable && this.suggestable.partner && this.suggestable.partner.isImStatusSet ? {} : clear(); }, /** * @private diff --git a/addons/mail/static/src/models/composer_view.js b/addons/mail/static/src/models/composer_view.js index 30ff9a57e0c..924b6235e03 100644 --- a/addons/mail/static/src/models/composer_view.js +++ b/addons/mail/static/src/models/composer_view.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, many, one } from '@mail/model/model_field'; -import { clear, insertAndReplace, link, unlink } from '@mail/model/model_field_command'; +import { clear, link, unlink } from '@mail/model/model_field_command'; import { OnChange } from '@mail/model/model_onchange'; import { addLink, escapeAndCompactTextContent, parseAndTransform } from '@mail/js/utils'; import { isEventHandled, markEventHandled } from '@mail/utils/utils'; @@ -169,7 +169,7 @@ registerModel({ */ onClickButtonEmojis() { if (!this.emojisPopoverView) { - this.update({ emojisPopoverView: insertAndReplace() }); + this.update({ emojisPopoverView: {} }); } else { this.update({ emojisPopoverView: clear() }); } @@ -689,7 +689,7 @@ registerModel({ async updateMessage() { const composer = this.composer; if (!composer.textInputContent) { - this.messageViewInEditing.messageActionList.update({ deleteConfirmDialog: insertAndReplace() }); + this.messageViewInEditing.messageActionList.update({ deleteConfirmDialog: {} }); return; } const escapedAndCompactContent = escapeAndCompactTextContent(composer.textInputContent); @@ -720,7 +720,7 @@ registerModel({ */ _computeAttachmentList() { return (this.composer && this.composer.attachments.length > 0) - ? insertAndReplace() + ? {} : clear(); }, /** @@ -729,7 +729,7 @@ registerModel({ */ _computeComposerSuggestedRecipientListView() { if (this.hasHeader && this.hasFollowers && !this.composer.isLog) { - return insertAndReplace(); + return {}; } return clear(); }, @@ -775,7 +775,7 @@ registerModel({ */ _computeDropZoneView() { if (this.useDragVisibleDropZone.isVisible) { - return insertAndReplace(); + return {}; } return clear(); }, @@ -1354,7 +1354,7 @@ registerModel({ */ _computeComposerSuggestionListView() { if (this.hasSuggestions) { - return insertAndReplace(); + return {}; } return clear(); } @@ -1428,7 +1428,7 @@ registerModel({ compute: '_computeExtraSuggestions', }), fileUploader: one('FileUploader', { - default: insertAndReplace(), + default: {}, inverse: 'composerView', isCausal: true, readonly: true, @@ -1613,7 +1613,7 @@ registerModel({ inverse: 'composerView', }), useDragVisibleDropZone: one('UseDragVisibleDropZone', { - default: insertAndReplace(), + default: {}, inverse: 'composerViewOwner', isCausal: true, readonly: true, diff --git a/addons/mail/static/src/models/delete_message_confirm_view.js b/addons/mail/static/src/models/delete_message_confirm_view.js index 2b30b621ebc..0f31145150d 100644 --- a/addons/mail/static/src/models/delete_message_confirm_view.js +++ b/addons/mail/static/src/models/delete_message_confirm_view.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; registerModel({ name: 'DeleteMessageConfirmView', @@ -37,7 +37,7 @@ registerModel({ * @returns {MessageView} */ _computeMessageView() { - return this.message ? insertAndReplace({ message: this.message }) : clear(); + return this.message ? { message: this.message } : clear(); }, }, fields: { diff --git a/addons/mail/static/src/models/dialog.js b/addons/mail/static/src/models/dialog.js index 966384a2431..2572e7c90ca 100644 --- a/addons/mail/static/src/models/dialog.js +++ b/addons/mail/static/src/models/dialog.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; registerModel({ name: 'Dialog', @@ -31,10 +31,10 @@ registerModel({ */ _computeAttachmentDeleteConfirmView() { if (this.attachmentCardOwnerAsAttachmentDeleteConfirm) { - return insertAndReplace(); + return {}; } if (this.attachmentImageOwnerAsAttachmentDeleteConfirm) { - return insertAndReplace(); + return {}; } return clear(); }, @@ -44,7 +44,7 @@ registerModel({ */ _computeAttachmentViewer() { if (this.attachmentListOwnerAsAttachmentView) { - return insertAndReplace(); + return {}; } return clear(); }, @@ -95,14 +95,14 @@ registerModel({ * @returns {FieldCommand} */ _computeDeleteMessageConfirmView() { - return this.messageActionListOwnerAsDeleteConfirm ? insertAndReplace() : clear(); + return this.messageActionListOwnerAsDeleteConfirm ? {} : clear(); }, /** * @private * @returns {FieldCommand} */ _computeFollowerSubtypeList() { - return this.followerOwnerAsSubtypeList ? insertAndReplace() : clear(); + return this.followerOwnerAsSubtypeList ? {} : clear(); }, /** /** diff --git a/addons/mail/static/src/models/discuss.js b/addons/mail/static/src/models/discuss.js index 0e4caa6ee65..1829eadbe5f 100644 --- a/addons/mail/static/src/models/discuss.js +++ b/addons/mail/static/src/models/discuss.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; import { escape, sprintf } from '@web/core/utils/strings'; registerModel({ @@ -125,7 +125,7 @@ registerModel({ }); }, open() { - this.update({ discussView: insertAndReplace() }); + this.update({ discussView: {} }); }, /** * Opens thread from init active id if the thread exists. @@ -270,7 +270,7 @@ registerModel({ this.messaging.device.isSmall && !(this.threadView && this.threadView.replyingToMessageView) ) { - return insertAndReplace(); + return {}; } return clear(); }, @@ -279,7 +279,7 @@ registerModel({ * @returns {FieldCommand} */ _computeNotificationListView() { - return (this.messaging.device.isSmall && this.activeMobileNavbarTabId !== 'mailbox') ? insertAndReplace() : clear(); + return (this.messaging.device.isSmall && this.activeMobileNavbarTabId !== 'mailbox') ? {} : clear(); }, /** * Only mailboxes and pinned channels are allowed in Discuss. @@ -304,12 +304,12 @@ registerModel({ * @returns {ThreadViewer} */ _computeThreadViewer() { - return insertAndReplace({ + return { hasMemberList: true, hasThreadView: this.hasThreadView, hasTopbar: true, thread: this.thread ? this.thread : clear(), - }); + }; }, }, fields: { @@ -339,7 +339,7 @@ registerModel({ * Discuss sidebar category for `channel` type channel threads. */ categoryChannel: one('DiscussSidebarCategory', { - default: insertAndReplace(), + default: {}, inverse: 'discussAsChannel', isCausal: true, }), @@ -347,7 +347,7 @@ registerModel({ * Discuss sidebar category for `chat` type channel threads. */ categoryChat: one('DiscussSidebarCategory', { - default: insertAndReplace(), + default: {}, inverse: 'discussAsChat', isCausal: true, }), diff --git a/addons/mail/static/src/models/discuss_public_view.js b/addons/mail/static/src/models/discuss_public_view.js index 02e0806aeb3..cf4b42fe33e 100644 --- a/addons/mail/static/src/models/discuss_public_view.js +++ b/addons/mail/static/src/models/discuss_public_view.js @@ -2,7 +2,7 @@ import { attr, one } from '@mail/model/model_field'; import { registerModel } from '@mail/model/model_core'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; registerModel({ name: 'DiscussPublicView', @@ -12,13 +12,13 @@ registerModel({ */ async switchToThreadView() { this.update({ - threadViewer: insertAndReplace({ + threadViewer: { extraClass: 'flex-grow-1', hasMemberList: true, hasThreadView: true, hasTopbar: true, thread: this.channel, - }), + }, welcomeView: clear(), }); if (this.isChannelTokenSecret) { @@ -36,12 +36,12 @@ registerModel({ switchToWelcomeView() { this.update({ threadViewer: clear(), - welcomeView: insertAndReplace({ + welcomeView: { channel: this.channel, isDoFocusGuestNameInput: true, originalGuestName: this.messaging.currentGuest && this.messaging.currentGuest.name, pendingGuestName: this.messaging.currentGuest && this.messaging.currentGuest.name, - }), + }, }); if (this.welcomeView.callDemoView) { this.welcomeView.callDemoView.enableMicrophone(); diff --git a/addons/mail/static/src/models/discuss_sidebar_category.js b/addons/mail/static/src/models/discuss_sidebar_category.js index 0dbf88e6a27..d00085ba98e 100644 --- a/addons/mail/static/src/models/discuss_sidebar_category.js +++ b/addons/mail/static/src/models/discuss_sidebar_category.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, many, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; import { OnChange } from '@mail/model/model_onchange'; registerModel({ @@ -56,10 +56,10 @@ registerModel({ _computeActiveItem() { const channel = this.messaging.discuss.thread && this.messaging.discuss.thread.channel; if (channel && this.supportedChannelTypes.includes(channel.channel_type)) { - return insertAndReplace({ + return { thread: channel.thread, category: this, - }); + }; } return clear(); }, @@ -69,7 +69,7 @@ registerModel({ */ _computeAddingItemAutocompleteInputView() { if (this.isOpen && this.isAddingItem) { - return insertAndReplace(); + return {}; } return clear(); }, diff --git a/addons/mail/static/src/models/discuss_view.js b/addons/mail/static/src/models/discuss_view.js index 32d9bea830c..22cc7a7e6b9 100644 --- a/addons/mail/static/src/models/discuss_view.js +++ b/addons/mail/static/src/models/discuss_view.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, many, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; import { OnChange } from '@mail/model/model_onchange'; registerModel({ @@ -105,7 +105,7 @@ registerModel({ this.messaging.device.isSmall && (this.discuss.isAddingChannel || this.discuss.isAddingChat) ) { - return insertAndReplace(); + return {}; } return clear(); }, @@ -139,12 +139,12 @@ registerModel({ inverse: 'discussView', }), historyView: one('DiscussSidebarMailboxView', { - default: insertAndReplace(), + default: {}, inverse: 'discussViewOwnerAsHistory', isCausal: true, }), inboxView: one('DiscussSidebarMailboxView', { - default: insertAndReplace(), + default: {}, inverse: 'discussViewOwnerAsInbox', isCausal: true, }), @@ -163,7 +163,7 @@ registerModel({ */ quickSearchInputRef: attr(), starredView: one('DiscussSidebarMailboxView', { - default: insertAndReplace(), + default: {}, inverse: 'discussViewOwnerAsStarred', isCausal: true, }), diff --git a/addons/mail/static/src/models/emoji_category_bar_view.js b/addons/mail/static/src/models/emoji_category_bar_view.js index ca229c57171..e2f7f398a0f 100644 --- a/addons/mail/static/src/models/emoji_category_bar_view.js +++ b/addons/mail/static/src/models/emoji_category_bar_view.js @@ -2,7 +2,6 @@ import { registerModel } from '@mail/model/model_core'; import { many, one } from '@mail/model/model_field'; -import { insertAndReplace } from '@mail/model/model_field_command'; registerModel({ name: 'EmojiCategoryBarView', @@ -22,21 +21,17 @@ registerModel({ * @returns {FieldCommand} */ _computeDefaultActiveCategoryView() { - return insertAndReplace({ - emojiCategory: insertAndReplace({ categoryName: "all" }), + return { + emojiCategory: { categoryName: "all" }, emojiCategoryBarViewOwner: this, - }); + }; }, /** * @private * @returns {FieldCommand} */ _computeEmojiCategoryViews() { - return insertAndReplace( - this.messaging.emojiRegistry.allCategories.map(emojiCategory => { - return { emojiCategory }; - }) - ); + return this.messaging.emojiRegistry.allCategories.map(emojiCategory => ({ emojiCategory })); }, }, fields: { diff --git a/addons/mail/static/src/models/emoji_grid_view.js b/addons/mail/static/src/models/emoji_grid_view.js index ad61d322085..34cf91b6255 100644 --- a/addons/mail/static/src/models/emoji_grid_view.js +++ b/addons/mail/static/src/models/emoji_grid_view.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { many, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; registerModel({ name: 'EmojiGridView', @@ -15,11 +15,7 @@ registerModel({ if (!this.emojiPickerViewOwner.emojiCategoryBarView.activeCategoryView) { return clear(); } - return insertAndReplace( - this.emojiPickerViewOwner.emojiCategoryBarView.activeCategoryView.emojiCategory.allEmojis.map(emoji => { - return { emoji }; - }) - ); + return this.emojiPickerViewOwner.emojiCategoryBarView.activeCategoryView.emojiCategory.allEmojis.map(emoji => ({ emoji })); }, }, fields: { diff --git a/addons/mail/static/src/models/emoji_picker_view.js b/addons/mail/static/src/models/emoji_picker_view.js index a228d58d5ac..fc7455bb45c 100644 --- a/addons/mail/static/src/models/emoji_picker_view.js +++ b/addons/mail/static/src/models/emoji_picker_view.js @@ -2,20 +2,19 @@ import { registerModel } from '@mail/model/model_core'; import { one } from '@mail/model/model_field'; -import { insertAndReplace } from '@mail/model/model_field_command'; registerModel({ name: 'EmojiPickerView', fields: { emojiCategoryBarView: one('EmojiCategoryBarView', { - default: insertAndReplace(), + default: {}, inverse: 'emojiPickerViewOwner', readonly: true, required: true, isCausal: true, }), emojiGridView: one('EmojiGridView', { - default: insertAndReplace(), + default: {}, inverse: 'emojiPickerViewOwner', readonly: true, required: true, diff --git a/addons/mail/static/src/models/emoji_registry.js b/addons/mail/static/src/models/emoji_registry.js index e0150656665..32dae118dac 100644 --- a/addons/mail/static/src/models/emoji_registry.js +++ b/addons/mail/static/src/models/emoji_registry.js @@ -2,13 +2,12 @@ import { registerModel } from '@mail/model/model_core'; import { many } from '@mail/model/model_field'; -import { insertAndReplace } from '@mail/model/model_field_command'; registerModel({ name: 'EmojiRegistry', fields: { allEmojis: many('Emoji', { - default: insertAndReplace([ + default: [ { unicode: "😊", sources: [":)", ":-)", "=)", ":]"], description: ":)" }, { unicode: "😃", sources: [":D", ":-D", "=D"], description: ":D" }, { unicode: "😆", sources: ["xD", "XD"], description: "xD" }, @@ -90,20 +89,19 @@ registerModel({ { unicode: "🎬", sources: [":clapper"], description: ":clapper" }, { unicode: "🎤", sources: [":microphone"], description: ":microphone" }, { unicode: "🧀", sources: [":cheese"], description: ":cheese" }, - ]), + ], inverse: 'emojiRegistry', }), allCategories: many('EmojiCategory', { - default: insertAndReplace([ - { categoryName: "all", allEmojis: insertAndReplace(["😊", "😃", "😆", "😂", "😉", "😎", "😜", "😋", "😝", "😳", "😐", "😕", "😞", "😱", "😲", "😨", "😠", "😈", "😘", "😇", "😢", "😭", "❤️", "💔", "😍", "👳", "👍", "👎", "👌", "💩", "🙈", "🙉", "🙊", "🐞", "😺", "🐻", "🐌", "🐗", "🍀", "🌹", "🔥", "☀️", "⛅️", "🌈", "☁️", "⚡️", "⭐️", "🍪", "🍕", "🍔", "🍟", "🎂", "🍰", "☕️", "🍌", "🍣", "🍙", "🍺", "🍷", "🍸", "🍹", "🍻", "🧀", "👻", "💀", "👽", "🎉", "🏆", "🔑", "📌", "📯", "🎵", "🎺", "🎸", "🏃", "🚲", "⚽️", "🏈", "🎱", "🎬", "🎤"].map(unicode => ({ unicode }))) }, - { categoryName: "🤠", allEmojis: insertAndReplace(["😊", "😃", "😆", "😂", "😉", "😎", "😜", "😋", "😝", "😳", "😐", "😕", "😞", "😱", "😲", "😨", "😠", "😈", "😘", "😇", "😢", "😭", "❤️", "💔", "😍", "👳", "👍", "👎", "👌", "💩"].map(unicode => ({ unicode }))) }, - { categoryName: "🐿", allEmojis: insertAndReplace(["🙈", "🙉", "🙊", "🐞", "😺", "🐻", "🐌", "🐗"].map(unicode => ({ unicode }))) }, - { categoryName: "🌿", allEmojis: insertAndReplace(["🍀", "🌹", "🔥", "☀️", "⛅️", "🌈", "☁️", "⚡️", "⭐️"].map(unicode => ({ unicode }))) }, - { categoryName: "🍽", allEmojis: insertAndReplace(["🍪", "🍕", "🍔", "🍟", "🎂", "🍰", "☕️", "🍌", "🍣", "🍙", "🍺", "🍷", "🍸", "🍹", "🍻", "🧀"].map(unicode => ({ unicode }))) }, - { categoryName: "📦", allEmojis: insertAndReplace(["👻", "💀", "👽", "🎉", "🏆", "🔑", "📌", "📯", "🎵", "🎺", "🎸"].map(unicode => ({ unicode }))) }, - { categoryName: "⚽️", allEmojis: insertAndReplace(["🏃", "🚲", "⚽️", "🏈", "🎱", "🎬", "🎤"].map(unicode => ({ unicode }))) }, - - ]), + default: [ + { categoryName: "all", allEmojis: ["😊", "😃", "😆", "😂", "😉", "😎", "😜", "😋", "😝", "😳", "😐", "😕", "😞", "😱", "😲", "😨", "😠", "😈", "😘", "😇", "😢", "😭", "❤️", "💔", "😍", "👳", "👍", "👎", "👌", "💩", "🙈", "🙉", "🙊", "🐞", "😺", "🐻", "🐌", "🐗", "🍀", "🌹", "🔥", "☀️", "⛅️", "🌈", "☁️", "⚡️", "⭐️", "🍪", "🍕", "🍔", "🍟", "🎂", "🍰", "☕️", "🍌", "🍣", "🍙", "🍺", "🍷", "🍸", "🍹", "🍻", "🧀", "👻", "💀", "👽", "🎉", "🏆", "🔑", "📌", "📯", "🎵", "🎺", "🎸", "🏃", "🚲", "⚽️", "🏈", "🎱", "🎬", "🎤"].map(unicode => ({ unicode })) }, + { categoryName: "🤠", allEmojis: ["😊", "😃", "😆", "😂", "😉", "😎", "😜", "😋", "😝", "😳", "😐", "😕", "😞", "😱", "😲", "😨", "😠", "😈", "😘", "😇", "😢", "😭", "❤️", "💔", "😍", "👳", "👍", "👎", "👌", "💩"].map(unicode => ({ unicode })) }, + { categoryName: "🐿", allEmojis: ["🙈", "🙉", "🙊", "🐞", "😺", "🐻", "🐌", "🐗"].map(unicode => ({ unicode })) }, + { categoryName: "🌿", allEmojis: ["🍀", "🌹", "🔥", "☀️", "⛅️", "🌈", "☁️", "⚡️", "⭐️"].map(unicode => ({ unicode })) }, + { categoryName: "🍽", allEmojis: ["🍪", "🍕", "🍔", "🍟", "🎂", "🍰", "☕️", "🍌", "🍣", "🍙", "🍺", "🍷", "🍸", "🍹", "🍻", "🧀"].map(unicode => ({ unicode })) }, + { categoryName: "📦", allEmojis: ["👻", "💀", "👽", "🎉", "🏆", "🔑", "📌", "📯", "🎵", "🎺", "🎸"].map(unicode => ({ unicode })) }, + { categoryName: "⚽️", allEmojis: ["🏃", "🚲", "⚽️", "🏈", "🎱", "🎬", "🎤"].map(unicode => ({ unicode })) }, + ], }), }, }); diff --git a/addons/mail/static/src/models/follower.js b/addons/mail/static/src/models/follower.js index 5650bd12ff5..9fbd411c774 100644 --- a/addons/mail/static/src/models/follower.js +++ b/addons/mail/static/src/models/follower.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, many, one } from '@mail/model/model_field'; -import { clear, insert, insertAndReplace, link, unlink } from '@mail/model/model_field_command'; +import { clear, insert, link, unlink } from '@mail/model/model_field_command'; registerModel({ name: 'Follower', @@ -33,7 +33,7 @@ registerModel({ } } if (data.partner) { - data2.partner = insertAndReplace(this.models['Partner'].convertData(data.partner)); + data2.partner = this.models['Partner'].convertData(data.partner); } return data2; }, @@ -102,7 +102,7 @@ registerModel({ this.update({ selectedSubtypes: unlink(subtype) }); } } - this.update({ followerSubtypeListDialog: insertAndReplace() }); + this.update({ followerSubtypeListDialog: {} }); }, /** * @param {FollowerSubtype} subtype diff --git a/addons/mail/static/src/models/follower_list_menu_view.js b/addons/mail/static/src/models/follower_list_menu_view.js index be022319263..f7d4de31513 100644 --- a/addons/mail/static/src/models/follower_list_menu_view.js +++ b/addons/mail/static/src/models/follower_list_menu_view.js @@ -2,7 +2,6 @@ import { registerModel } from '@mail/model/model_core'; import { attr, many, one } from '@mail/model/model_field'; -import { insertAndReplace } from '@mail/model/model_field_command'; registerModel({ name: 'FollowerListMenuView', @@ -33,9 +32,7 @@ registerModel({ * @returns {FieldCommand} */ _computeFollowerViews() { - return insertAndReplace(this.chatterOwner.thread.followers.map(follower => { - return { follower }; - })); + return this.chatterOwner.thread.followers.map(follower => ({ follower })); }, /** * @private diff --git a/addons/mail/static/src/models/follower_subtype_list.js b/addons/mail/static/src/models/follower_subtype_list.js index b94b9a5d4a0..a7f90030e9a 100644 --- a/addons/mail/static/src/models/follower_subtype_list.js +++ b/addons/mail/static/src/models/follower_subtype_list.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, many, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; registerModel({ name: 'FollowerSubtypeList', @@ -40,7 +40,7 @@ registerModel({ if (this.follower.subtypes.length === 0) { return clear(); } - return insertAndReplace(this.follower.subtypes.map(subtype => ({ subtype }))); + return this.follower.subtypes.map(subtype => ({ subtype })); }, /** * @private diff --git a/addons/mail/static/src/models/guest.js b/addons/mail/static/src/models/guest.js index b30c8d47dcc..84284a5d805 100644 --- a/addons/mail/static/src/models/guest.js +++ b/addons/mail/static/src/models/guest.js @@ -2,7 +2,6 @@ import { attr, many, one } from '@mail/model/model_field'; import { registerModel } from '@mail/model/model_core'; -import { insertAndReplace } from '@mail/model/model_field_command'; registerModel({ name: 'Guest', @@ -54,7 +53,7 @@ registerModel({ }), name: attr(), persona: one('Persona', { - default: insertAndReplace(), + default: {}, inverse: 'guest', isCausal: true, readonly: true, diff --git a/addons/mail/static/src/models/mailbox.js b/addons/mail/static/src/models/mailbox.js index 8fe3dc97c6a..2c2a9248f28 100644 --- a/addons/mail/static/src/models/mailbox.js +++ b/addons/mail/static/src/models/mailbox.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; import { OnChange } from '@mail/model/model_onchange'; registerModel({ @@ -80,10 +80,10 @@ registerModel({ if (!threadId) { return clear(); } - return insertAndReplace({ + return { id: threadId, model: 'mail.box', - }); + }; }, _onChangeCounter() { if (this !== this.messaging.inbox) { diff --git a/addons/mail/static/src/models/message.js b/addons/mail/static/src/models/message.js index d051c651ba6..6150febf24a 100644 --- a/addons/mail/static/src/models/message.js +++ b/addons/mail/static/src/models/message.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, many, one } from '@mail/model/model_field'; -import { clear, insert, insertAndReplace } from '@mail/model/model_field_command'; +import { clear, insert } from '@mail/model/model_field_command'; import { addLink, htmlToTextContentInline, parseAndTransform } from '@mail/js/utils'; import { session } from '@web/session'; @@ -81,7 +81,7 @@ registerModel({ if ('module_icon' in data) { originThreadData.moduleIcon = data.module_icon; } - data2.originThread = insertAndReplace(originThreadData); + data2.originThread = originThreadData; } if ('needaction_partner_ids' in data && this.messaging.currentPartner) { data2.isNeedaction = data.needaction_partner_ids.includes(this.messaging.currentPartner.id); @@ -95,11 +95,11 @@ registerModel({ if (!data.parentMessage) { data2.parentMessage = clear(); } else { - data2.parentMessage = insertAndReplace(this.convertData(data.parentMessage)); + data2.parentMessage = this.convertData(data.parentMessage); } } if ('recipients' in data) { - data2.recipients = insertAndReplace(data.recipients); + data2.recipients = data.recipients; } if ('starred_partner_ids' in data && this.messaging.currentPartner) { data2.isStarred = data.starred_partner_ids.includes(this.messaging.currentPartner.id); diff --git a/addons/mail/static/src/models/message_action_list.js b/addons/mail/static/src/models/message_action_list.js index 78c98f8cc98..910bd38be8b 100644 --- a/addons/mail/static/src/models/message_action_list.js +++ b/addons/mail/static/src/models/message_action_list.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; import { markEventHandled } from '@mail/utils/utils'; registerModel({ @@ -20,7 +20,7 @@ registerModel({ * @param {MouseEvent} ev */ onClickDelete(ev) { - this.update({ deleteConfirmDialog: insertAndReplace() }); + this.update({ deleteConfirmDialog: {} }); }, /** * @private @@ -41,7 +41,7 @@ registerModel({ */ onClickActionReaction() { if (!this.reactionPopoverView) { - this.update({ reactionPopoverView: insertAndReplace() }); + this.update({ reactionPopoverView: {} }); } else { this.update({ reactionPopoverView: clear() }); } diff --git a/addons/mail/static/src/models/message_list_view.js b/addons/mail/static/src/models/message_list_view.js index 9d1f69f3050..e668f8f838c 100644 --- a/addons/mail/static/src/models/message_list_view.js +++ b/addons/mail/static/src/models/message_list_view.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, many, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; registerModel({ name: 'MessageListView', @@ -79,7 +79,7 @@ registerModel({ }); prevMessage = message; } - return insertAndReplace(messageViewsData); + return messageViewsData; }, }, fields: { diff --git a/addons/mail/static/src/models/message_list_view_message_view_item.js b/addons/mail/static/src/models/message_list_view_message_view_item.js index 6a9a31c12fd..bc1a7b1288d 100644 --- a/addons/mail/static/src/models/message_list_view_message_view_item.js +++ b/addons/mail/static/src/models/message_list_view_message_view_item.js @@ -2,7 +2,6 @@ import { registerModel } from '@mail/model/model_core'; import { attr, one } from '@mail/model/model_field'; -import { insertAndReplace } from '@mail/model/model_field_command'; /** * Models a relation between a message list view and a message view where @@ -23,7 +22,7 @@ registerModel({ inverse: 'messageListViewMessageViewItems', }), messageView: one('MessageView', { - default: insertAndReplace(), + default: {}, inverse: 'messageListViewMessageViewItemOwner', isCausal: true, readonly: true, diff --git a/addons/mail/static/src/models/message_seen_indicator_view.js b/addons/mail/static/src/models/message_seen_indicator_view.js index 25b209c281d..87175afa5f5 100644 --- a/addons/mail/static/src/models/message_seen_indicator_view.js +++ b/addons/mail/static/src/models/message_seen_indicator_view.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; registerModel({ name: 'MessageSeenIndicatorView', @@ -13,10 +13,10 @@ registerModel({ */ _computeMessageSeenIndicator() { if (this.messageViewOwner.messageListViewMessageViewItemOwner && this.messageViewOwner.messageListViewMessageViewItemOwner.messageListViewOwner.threadViewOwner.thread) { - return insertAndReplace({ + return { message: this.messageViewOwner.message, thread: this.messageViewOwner.messageListViewMessageViewItemOwner.messageListViewOwner.threadViewOwner.thread, - }); + }; } return clear(); }, diff --git a/addons/mail/static/src/models/message_view.js b/addons/mail/static/src/models/message_view.js index 68c8e79434f..cb1760db9f7 100644 --- a/addons/mail/static/src/models/message_view.js +++ b/addons/mail/static/src/models/message_view.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; import { isEventHandled, markEventHandled } from '@mail/utils/utils'; registerModel({ @@ -14,7 +14,7 @@ registerModel({ */ highlight() { this.update({ - highlightTimer: [clear(), insertAndReplace()], + highlightTimer: { doReset: this.highlightTimer ? true : undefined }, isHighlighted: true, }); }, @@ -117,7 +117,10 @@ registerModel({ } }, onHighlightTimerTimeout() { - this.update({ isHighlighted: false }); + this.update({ + highlightTimer: clear(), + isHighlighted: false, + }); }, onMouseenter() { this.update({ isHovered: true }); @@ -138,15 +141,15 @@ registerModel({ return; } this.message.originThread.update({ - composer: insertAndReplace({ + composer: { isLog: !this.message.is_discussion && !this.message.is_notification, - }), + }, }); this.messageListViewMessageViewItemOwner.messageListViewOwner.threadViewOwner.update({ replyingToMessageView: this, - composerView: insertAndReplace({ + composerView: { doFocus: true, - }), + }, }); }, /** @@ -157,17 +160,17 @@ registerModel({ const htmlDoc = parser.parseFromString(this.message.body.replaceAll('
', '\n').replaceAll('
', '\n'), "text/html"); const textInputContent = htmlDoc.body.textContent; this.update({ - composerForEditing: insertAndReplace({ + composerForEditing: { mentionedPartners: this.message.recipients, textInputContent, textInputCursorEnd: textInputContent.length, textInputCursorStart: textInputContent.length, textInputSelectionDirection: 'none', - }), - composerViewInEditing: insertAndReplace({ + }, + composerViewInEditing: { doFocus: true, hasToRestoreContent: true, - }), + }, }); }, /** @@ -188,7 +191,7 @@ registerModel({ */ _computeAttachmentList() { return (this.message && this.message.attachments.length > 0) - ? insertAndReplace() + ? {} : clear(); }, /** @@ -382,7 +385,7 @@ registerModel({ * @returns {FieldCommand} */ _computeMessageActionList() { - return this.deleteMessageConfirmViewOwner ? clear() : insertAndReplace(); + return this.deleteMessageConfirmViewOwner ? clear() : {}; }, /** * @private @@ -394,7 +397,7 @@ registerModel({ this.message.originThread && this.message.originThread.model === 'mail.channel' && this.message.parentMessage - ) ? insertAndReplace() : clear(); + ) ? {} : clear(); }, /** * @private @@ -407,7 +410,7 @@ registerModel({ this.messageListViewMessageViewItemOwner.messageListViewOwner.threadViewOwner.thread && this.messageListViewMessageViewItemOwner.messageListViewOwner.threadViewOwner.thread.hasSeenIndicators ) { - return insertAndReplace(); + return {}; } return clear(); }, @@ -417,9 +420,9 @@ registerModel({ */ _computePersonaImStatusIconView() { if (this.message.guestAuthor && this.message.guestAuthor.im_status) { - return insertAndReplace(); + return {}; } - return this.message.author && this.message.author.isImStatusSet ? insertAndReplace() : clear(); + return this.message.author && this.message.author.isImStatusSet ? {} : clear(); }, }, fields: { @@ -437,11 +440,11 @@ registerModel({ compute: '_computeAuthorTitleText', }), clockWatcher: one('ClockWatcher', { - default: insertAndReplace({ - clock: insertAndReplace({ + default: { + clock: { frequency: 60 * 1000, - }), - }), + }, + }, inverse: 'messageViewOwner', isCausal: true, }), diff --git a/addons/mail/static/src/models/messaging.js b/addons/mail/static/src/models/messaging.js index 74ea9b122d0..1f75c450ae6 100644 --- a/addons/mail/static/src/models/messaging.js +++ b/addons/mail/static/src/models/messaging.js @@ -3,7 +3,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, many, one } from '@mail/model/model_field'; import { OnChange } from '@mail/model/model_onchange'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; import { makeDeferred } from '@mail/utils/deferred'; import { browser } from '@web/core/browser/browser'; @@ -204,7 +204,9 @@ registerModel({ this.update({ isNotificationPermissionDefault: this._computeIsNotificationPermissionDefault() }); }, async startFetchImStatus() { - this.update({ fetchImStatusTimer: [clear(), insertAndReplace()] }); + this.update({ + fetchImStatusTimer: { doReset: this.fetchImStatusTimer ? true : undefined }, + }); const partnerIds = []; for (const partner of this.models['Partner'].all()) { if (partner.im_status !== 'im_partner' && partner.id > 0) { @@ -307,7 +309,7 @@ registerModel({ * @returns {FieldCommand} */ _computeNotificationHandler() { - return insertAndReplace(); + return {}; }, /** * @private @@ -337,7 +339,7 @@ registerModel({ }), cannedResponses: many('CannedResponse'), chatWindowManager: one('ChatWindowManager', { - default: insertAndReplace(), + default: {}, isCausal: true, readonly: true, }), @@ -353,12 +355,12 @@ registerModel({ currentPartner: one('Partner'), currentUser: one('User'), device: one('Device', { - default: insertAndReplace(), + default: {}, isCausal: true, readonly: true, }), dialogManager: one('DialogManager', { - default: insertAndReplace(), + default: {}, isCausal: true, readonly: true, }), @@ -369,12 +371,12 @@ registerModel({ default: false, }), discuss: one('Discuss', { - default: insertAndReplace(), + default: {}, isCausal: true, readonly: true, }), emojiRegistry: one('EmojiRegistry', { - default: insertAndReplace(), + default: {}, isCausal: true, readonly: true, }), @@ -386,12 +388,12 @@ registerModel({ default: 50 * 1000, }), history: one('Mailbox', { - default: insertAndReplace(), + default: {}, inverse: 'messagingAsHistory', isCausal: true, }), inbox: one('Mailbox', { - default: insertAndReplace(), + default: {}, inverse: 'messagingAsInbox', isCausal: true, }), @@ -404,7 +406,7 @@ registerModel({ readonly: true, }), initializer: one('MessagingInitializer', { - default: insertAndReplace(), + default: {}, isCausal: true, readonly: true, }), @@ -429,7 +431,7 @@ registerModel({ compute: '_computeIsNotificationPermissionDefault', }), locale: one('Locale', { - default: insertAndReplace(), + default: {}, isCausal: true, readonly: true, }), @@ -449,7 +451,7 @@ registerModel({ required: true, }), messagingMenu: one('MessagingMenu', { - default: insertAndReplace(), + default: {}, isCausal: true, }), notificationHandler: one('MessagingNotificationHandler', { @@ -462,7 +464,7 @@ registerModel({ }), partnerRoot: one('Partner'), popoverManager: one('PopoverManager', { - default: insertAndReplace(), + default: {}, isCausal: true, readonly: true, }), @@ -479,7 +481,7 @@ registerModel({ inverse: 'messagingAsRingingThread', }), rtc: one('Rtc', { - default: insertAndReplace(), + default: {}, isCausal: true, readonly: true, }), @@ -488,22 +490,22 @@ registerModel({ isCausal: true, }), soundEffects: one('SoundEffects', { - default: insertAndReplace(), + default: {}, isCausal: true, readonly: true, }), starred: one('Mailbox', { - default: insertAndReplace(), + default: {}, inverse: 'messagingAsStarred', isCausal: true, }), userNotificationManager: one('UserNotificationManager', { - default: insertAndReplace(), + default: {}, isCausal: true, readonly: true, }), userSetting: one('UserSetting', { - default: insertAndReplace(), + default: {}, isCausal: true, }), }, diff --git a/addons/mail/static/src/models/messaging_menu.js b/addons/mail/static/src/models/messaging_menu.js index d6df1c06ea4..ceb755f15c4 100644 --- a/addons/mail/static/src/models/messaging_menu.js +++ b/addons/mail/static/src/models/messaging_menu.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, many, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; registerModel({ name: 'MessagingMenu', @@ -125,7 +125,7 @@ registerModel({ */ _computeMobileMessagingNavbarView() { if (this.messaging.device && this.messaging.device.isSmall) { - return insertAndReplace(); + return {}; } return clear(); }, @@ -135,7 +135,7 @@ registerModel({ */ _computeMobileNewMessageAutocompleteInputView() { if (this.isOpen && this.messaging.isInitialized && this.messaging.device.isSmall && this.isMobileNewMessageToggled) { - return insertAndReplace(); + return {}; } return clear(); }, @@ -150,7 +150,7 @@ registerModel({ * @returns {FieldCommand} */ _computeNotificationListView() { - return this.isOpen ? insertAndReplace() : clear(); + return this.isOpen ? {} : clear(); }, /** * @private diff --git a/addons/mail/static/src/models/messaging_notification_handler.js b/addons/mail/static/src/models/messaging_notification_handler.js index 1ab8b5ed371..cb1f9f14091 100644 --- a/addons/mail/static/src/models/messaging_notification_handler.js +++ b/addons/mail/static/src/models/messaging_notification_handler.js @@ -1,7 +1,7 @@ /** @odoo-module **/ import { registerModel } from '@mail/model/model_core'; -import { decrement, increment, insert, insertAndReplace, unlink } from '@mail/model/model_field_command'; +import { decrement, increment, insert, unlink } from '@mail/model/model_field_command'; import { htmlToTextContentInline } from '@mail/js/utils'; import { escape, sprintf } from '@web/core/utils/strings'; @@ -175,11 +175,11 @@ registerModel({ } this.messaging.models['ThreadPartnerSeenInfo'].insert({ lastFetchedMessage: insert({ id: last_message_id }), - partner: insertAndReplace({ id: partner_id }), + partner: { id: partner_id }, thread: channel.thread, }); this.messaging.models['MessageSeenIndicator'].insert({ - message: insertAndReplace({ id: last_message_id }), + message: { id: last_message_id }, thread: channel.thread, }); }, @@ -318,7 +318,7 @@ registerModel({ if (shouldComputeSeenIndicators) { this.messaging.models['ThreadPartnerSeenInfo'].insert({ lastSeenMessage: lastMessage, - partner: insertAndReplace({ id: partner_id }), + partner: { id: partner_id }, thread: channel.thread, }); this.messaging.models['MessageSeenIndicator'].insert({ diff --git a/addons/mail/static/src/models/notification.js b/addons/mail/static/src/models/notification.js index 0e4dd73715e..b4e3b691d65 100644 --- a/addons/mail/static/src/models/notification.js +++ b/addons/mail/static/src/models/notification.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, one } from '@mail/model/model_field'; -import { clear, insert, insertAndReplace } from '@mail/model/model_field_command'; +import { clear, insert } from '@mail/model/model_field_command'; registerModel({ name: 'Notification', @@ -107,12 +107,12 @@ registerModel({ // Except for channel where they are also grouped by id because // we want to open the actual channel in discuss or chat window // and not its kanban/list/form view. - return insertAndReplace({ + return { notification_type: this.notification_type, res_id: thread.model === 'mail.channel' ? thread.id : null, res_model: thread.model, res_model_name: thread.model_name, - }); + }; }, }, fields: { diff --git a/addons/mail/static/src/models/notification_list_view.js b/addons/mail/static/src/models/notification_list_view.js index 2b8ac283597..5009bfd61af 100644 --- a/addons/mail/static/src/models/notification_list_view.js +++ b/addons/mail/static/src/models/notification_list_view.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, many, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; registerModel({ name: 'NotificationListView', @@ -67,21 +67,17 @@ registerModel({ if (this.filter !== 'all') { return clear(); } - return insertAndReplace( - this.models['NotificationGroup'] - .all() - .sort((group1, group2) => group1.sequence - group2.sequence) - .map(notificationGroup => { - return { notificationGroup }; - }) - ); + return this.models['NotificationGroup'] + .all() + .sort((group1, group2) => group1.sequence - group2.sequence) + .map(notificationGroup => ({ notificationGroup })); }, /** * @private * @returns {FieldCommand} */ _computeNotificationRequestView() { - return (this.filter === 'all' && this.messaging.isNotificationPermissionDefault) ? insertAndReplace() : clear(); + return (this.filter === 'all' && this.messaging.isNotificationPermissionDefault) ? {} : clear(); }, /** * @private @@ -105,63 +101,53 @@ registerModel({ if (this.filter !== 'all') { return clear(); } - return insertAndReplace( - this.messaging.models['Thread'] - .all(t => !t.mailbox && t.needactionMessagesAsOriginThread.length > 0) - .sort((t1, t2) => { - if (t1.needactionMessagesAsOriginThread.length > 0 && t2.needactionMessagesAsOriginThread.length === 0) { - return -1; - } - if (t1.needactionMessagesAsOriginThread.length === 0 && t2.needactionMessagesAsOriginThread.length > 0) { - return 1; - } - if (t1.lastNeedactionMessageAsOriginThread && t2.lastNeedactionMessageAsOriginThread) { - return t1.lastNeedactionMessageAsOriginThread.id < t2.lastNeedactionMessageAsOriginThread.id ? 1 : -1; - } - if (t1.lastNeedactionMessageAsOriginThread) { - return -1; - } - if (t2.lastNeedactionMessageAsOriginThread) { - return 1; - } - return t1.id < t2.id ? -1 : 1; - }) - .map(thread => { - return { thread }; - }) - ); + return this.messaging.models['Thread'] + .all(t => !t.mailbox && t.needactionMessagesAsOriginThread.length > 0) + .sort((t1, t2) => { + if (t1.needactionMessagesAsOriginThread.length > 0 && t2.needactionMessagesAsOriginThread.length === 0) { + return -1; + } + if (t1.needactionMessagesAsOriginThread.length === 0 && t2.needactionMessagesAsOriginThread.length > 0) { + return 1; + } + if (t1.lastNeedactionMessageAsOriginThread && t2.lastNeedactionMessageAsOriginThread) { + return t1.lastNeedactionMessageAsOriginThread.id < t2.lastNeedactionMessageAsOriginThread.id ? 1 : -1; + } + if (t1.lastNeedactionMessageAsOriginThread) { + return -1; + } + if (t2.lastNeedactionMessageAsOriginThread) { + return 1; + } + return t1.id < t2.id ? -1 : 1; + }) + .map(thread => ({ thread })); }, /** * @private * @returns {FieldCommand} */ _computeThreadPreviewViews() { - return insertAndReplace( - this.filteredThreads - .sort((t1, t2) => { - if (t1.localMessageUnreadCounter > 0 && t2.localMessageUnreadCounter === 0) { - return -1; - } - if (t1.localMessageUnreadCounter === 0 && t2.localMessageUnreadCounter > 0) { - return 1; - } - if (t1.lastMessage && t2.lastMessage) { - return t1.lastMessage.id < t2.lastMessage.id ? 1 : -1; - } - if (t1.lastMessage) { - return -1; - } - if (t2.lastMessage) { - return 1; - } - return t1.id < t2.id ? -1 : 1; - }) - .map(thread => { - return { - thread, - }; - }) - ); + return this.filteredThreads + .sort((t1, t2) => { + if (t1.localMessageUnreadCounter > 0 && t2.localMessageUnreadCounter === 0) { + return -1; + } + if (t1.localMessageUnreadCounter === 0 && t2.localMessageUnreadCounter > 0) { + return 1; + } + if (t1.lastMessage && t2.lastMessage) { + return t1.lastMessage.id < t2.lastMessage.id ? 1 : -1; + } + if (t1.lastMessage) { + return -1; + } + if (t2.lastMessage) { + return 1; + } + return t1.id < t2.id ? -1 : 1; + }) + .map(thread => ({ thread })); }, /** * Load previews of given thread. Basically consists of fetching all missing diff --git a/addons/mail/static/src/models/notification_request_view.js b/addons/mail/static/src/models/notification_request_view.js index 0d1220f2bbe..f586e491def 100644 --- a/addons/mail/static/src/models/notification_request_view.js +++ b/addons/mail/static/src/models/notification_request_view.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; import { sprintf } from '@web/core/utils/strings'; @@ -27,7 +27,7 @@ registerModel({ * @returns {FieldCommand} */ _computePersonaImStatusIconView() { - return this.messaging.partnerRoot && this.messaging.partnerRoot.isImStatusSet ? insertAndReplace() : clear(); + return this.messaging.partnerRoot && this.messaging.partnerRoot.isImStatusSet ? {} : clear(); }, }, fields: { diff --git a/addons/mail/static/src/models/other_member_long_typing_in_thread_timer.js b/addons/mail/static/src/models/other_member_long_typing_in_thread_timer.js index f4b2f46a8b6..9197471845a 100644 --- a/addons/mail/static/src/models/other_member_long_typing_in_thread_timer.js +++ b/addons/mail/static/src/models/other_member_long_typing_in_thread_timer.js @@ -2,7 +2,6 @@ import { registerModel } from '@mail/model/model_core'; import { one } from '@mail/model/model_field'; -import { insertAndReplace } from '@mail/model/model_field_command'; registerModel({ name: 'OtherMemberLongTypingInThreadTimer', @@ -21,7 +20,7 @@ registerModel({ inverse: 'otherMembersLongTypingTimers', }), timer: one('Timer', { - default: insertAndReplace(), + default: {}, inverse: 'otherMemberLongTypingInThreadTimerOwner', isCausal: true, required: true, diff --git a/addons/mail/static/src/models/partner.js b/addons/mail/static/src/models/partner.js index 95e802a58bc..b172746f977 100644 --- a/addons/mail/static/src/models/partner.js +++ b/addons/mail/static/src/models/partner.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, many, one } from '@mail/model/model_field'; -import { clear, insert, insertAndReplace, link } from '@mail/model/model_field_command'; +import { clear, insert, link } from '@mail/model/model_field_command'; import { cleanSearchTerm } from '@mail/utils/utils'; registerModel({ @@ -433,14 +433,14 @@ registerModel({ isCausal: true, }), persona: one('Persona', { - default: insertAndReplace(), + default: {}, inverse: 'partner', isCausal: true, readonly: true, required: true, }), suggestable: one('ComposerSuggestable', { - default: insertAndReplace(), + default: {}, inverse: 'partner', isCausal: true, readonly: true, diff --git a/addons/mail/static/src/models/popover_view.js b/addons/mail/static/src/models/popover_view.js index 590a11000eb..d6335d15694 100644 --- a/addons/mail/static/src/models/popover_view.js +++ b/addons/mail/static/src/models/popover_view.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; registerModel({ name: 'PopoverView', @@ -32,7 +32,7 @@ registerModel({ */ _computeActivityMarkDonePopoverContentView() { if (this.activityViewOwnerAsMarkDone) { - return insertAndReplace(); + return {}; } return clear(); }, @@ -61,7 +61,7 @@ registerModel({ */ _computeChannelInvitationForm() { if (this.threadViewTopbarOwnerAsInvite) { - return insertAndReplace(); + return {}; } return clear(); }, @@ -116,10 +116,10 @@ registerModel({ */ _computeEmojiPickerView() { if (this.composerViewOwnerAsEmoji) { - return insertAndReplace(); + return {}; } if (this.messageActionListOwnerAsReaction) { - return insertAndReplace(); + return {}; } return clear(); }, diff --git a/addons/mail/static/src/models/record.js b/addons/mail/static/src/models/record.js index 6ede22fd9f2..391176f5910 100644 --- a/addons/mail/static/src/models/record.js +++ b/addons/mail/static/src/models/record.js @@ -2,7 +2,6 @@ import { registerModel } from '@mail/model/model_core'; import { one } from '@mail/model/model_field'; -import { insertAndReplace } from '@mail/model/model_field_command'; /** * The object below defines a model. Instances of such model (or inherited @@ -181,7 +180,7 @@ registerModel({ * manager at creation. */ messaging: one('Messaging', { - default: insertAndReplace(), + default: {}, inverse: 'allRecords', readonly: true, required: true, diff --git a/addons/mail/static/src/models/rtc.js b/addons/mail/static/src/models/rtc.js index c5e4706fade..3c47606cc65 100644 --- a/addons/mail/static/src/models/rtc.js +++ b/addons/mail/static/src/models/rtc.js @@ -4,7 +4,7 @@ import { browser } from "@web/core/browser/browser"; import { registerModel } from '@mail/model/model_core'; import { attr, many, one } from '@mail/model/model_field'; -import { clear, insert, insertAndReplace, unlink } from '@mail/model/model_field_command'; +import { clear, insert, unlink } from '@mail/model/model_field_command'; import { monitorAudio } from '@mail/utils/media_monitoring'; import { sprintf } from '@web/core/utils/strings'; @@ -490,7 +490,7 @@ registerModel({ this._addLogEntry(rtcSession.id, `failed to send on datachannel; dataChannelInfo: ${this._serializeRTCDataChannel(dataChannel)}`, { error: e }); } }; - rtcSession.update({ rtcPeerConnection: insertAndReplace({ peerConnection }) }); + rtcSession.update({ rtcPeerConnection: { peerConnection } }); this.messaging.models['RtcDataChannel'].insert({ dataChannel, rtcSession, @@ -1211,7 +1211,7 @@ registerModel({ default: 3000, }), callSystrayMenu: one('CallSystrayMenu', { - default: insertAndReplace(), + default: {}, inverse: 'rtc', isCausal: true, }), diff --git a/addons/mail/static/src/models/rtc_session.js b/addons/mail/static/src/models/rtc_session.js index b3fdf9063c0..22f036c5f81 100644 --- a/addons/mail/static/src/models/rtc_session.js +++ b/addons/mail/static/src/models/rtc_session.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, many, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; registerModel({ name: 'RtcSession', @@ -13,6 +13,7 @@ registerModel({ }, recordMethods: { onBroadcastTimeout() { + this.update({ broadcastTimer: clear() }); this.messaging.rpc( { route: '/mail/rtc/session/update_and_broadcast', @@ -111,8 +112,10 @@ registerModel({ if (!this.rtcAsCurrentSession) { return; } - const data2 = Object.assign({}, data, { broadcastTimer: [clear(), insertAndReplace()] }); - this.update(data2); + this.update({ + ...data, + broadcastTimer: { doReset: this.broadcastTimer ? true : undefined }, + }); }, /** * Updates the rtcSession with information on the type of candidate used diff --git a/addons/mail/static/src/models/sound_effects.js b/addons/mail/static/src/models/sound_effects.js index c7973f318f8..f38ed9903a0 100644 --- a/addons/mail/static/src/models/sound_effects.js +++ b/addons/mail/static/src/models/sound_effects.js @@ -2,57 +2,56 @@ import { registerModel } from '@mail/model/model_core'; import { one } from '@mail/model/model_field'; -import { insertAndReplace } from '@mail/model/model_field_command'; registerModel({ name: 'SoundEffects', fields: { channelJoin: one('SoundEffect', { - default: insertAndReplace({ defaultVolume: 0.3, filename: 'channel_01_in' }), + default: { defaultVolume: 0.3, filename: 'channel_01_in' }, isCausal: true, }), channelLeave: one('SoundEffect', { - default: insertAndReplace({ filename: 'channel_04_out' }), + default: { filename: 'channel_04_out' }, isCausal: true, }), deafen: one('SoundEffect', { - default: insertAndReplace({ defaultVolume: 0.15, filename: 'deafen_new_01' }), + default: { defaultVolume: 0.15, filename: 'deafen_new_01' }, isCausal: true, }), incomingCall: one('SoundEffect', { - default: insertAndReplace({ defaultVolume: 0.15, filename: 'call_02_in_' }), + default: { defaultVolume: 0.15, filename: 'call_02_in_' }, isCausal: true, }), memberLeave: one('SoundEffect', { - default: insertAndReplace({ defaultVolume: 0.5, filename: 'channel_01_out' }), + default: { defaultVolume: 0.5, filename: 'channel_01_out' }, isCausal: true, }), mute: one('SoundEffect', { - default: insertAndReplace({ defaultVolume: 0.2, filename: 'mute_1' }), + default: { defaultVolume: 0.2, filename: 'mute_1' }, isCausal: true, }), newMessage: one('SoundEffect', { - default: insertAndReplace({ filename: 'dm_02' }), + default: { filename: 'dm_02' }, isCausal: true, }), pushToTalkOn: one('SoundEffect', { - default: insertAndReplace({ defaultVolume: 0.05, filename: 'ptt_push_1' }), + default: { defaultVolume: 0.05, filename: 'ptt_push_1' }, isCausal: true, }), pushToTalkOff: one('SoundEffect', { - default: insertAndReplace({ defaultVolume: 0.05, filename: 'ptt_release_1' }), + default: { defaultVolume: 0.05, filename: 'ptt_release_1' }, isCausal: true, }), screenSharing: one('SoundEffect', { - default: insertAndReplace({ defaultVolume: 0.5, filename: 'share_02' }), + default: { defaultVolume: 0.5, filename: 'share_02' }, isCausal: true, }), undeafen: one('SoundEffect', { - default: insertAndReplace({ defaultVolume: 0.15, filename: 'undeafen_new_01' }), + default: { defaultVolume: 0.15, filename: 'undeafen_new_01' }, isCausal: true, }), unmute: one('SoundEffect', { - default: insertAndReplace({ defaultVolume: 0.2, filename: 'unmute_1' }), + default: { defaultVolume: 0.2, filename: 'unmute_1' }, isCausal: true, }), }, diff --git a/addons/mail/static/src/models/thread.js b/addons/mail/static/src/models/thread.js index d9ec350dc6d..1aefe0bc9ef 100644 --- a/addons/mail/static/src/models/thread.js +++ b/addons/mail/static/src/models/thread.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, many, one } from '@mail/model/model_field'; -import { clear, insert, insertAndReplace, insertAndUnlink, link, unlink } from '@mail/model/model_field_command'; +import { clear, insert, insertAndUnlink, link, unlink } from '@mail/model/model_field_command'; import { OnChange } from '@mail/model/model_onchange'; import { cleanSearchTerm } from '@mail/utils/utils'; import * as mailUtils from '@mail/js/utils'; @@ -124,13 +124,12 @@ registerModel({ // relations if ('members' in data) { - // The list syntax is kept here because it is used in livechat override if (!data.members) { - data2.members = [clear()]; + data2.members = []; } else { - data2.members = [insertAndReplace(data.members.map(memberData => + data2.members = data.members.map(memberData => this.messaging.models['Partner'].convertData(memberData) - ))]; + ); } } if ('rtc_inviting_session' in data) { @@ -143,16 +142,14 @@ registerModel({ if (!data.seen_partners_info) { data2.partnerSeenInfos = clear(); } else { - data2.partnerSeenInfos = insertAndReplace( - data.seen_partners_info.map( - ({ fetched_message_id, partner_id, seen_message_id }) => { - return { - lastFetchedMessage: fetched_message_id ? insert({ id: fetched_message_id }) : clear(), - lastSeenMessage: seen_message_id ? insert({ id: seen_message_id }) : clear(), - partner: insertAndReplace({ id: partner_id }), - }; - }) - ); + data2.partnerSeenInfos = data.seen_partners_info.map( + ({ fetched_message_id, partner_id, seen_message_id }) => { + return { + lastFetchedMessage: fetched_message_id ? insert({ id: fetched_message_id }) : clear(), + lastSeenMessage: seen_message_id ? insert({ id: seen_message_id }) : clear(), + partner: { id: partner_id }, + }; + }); if (data.id || this.id) { const messageIds = data.seen_partners_info.reduce((currentSet, { fetched_message_id, seen_message_id }) => { if (fetched_message_id) { @@ -164,11 +161,11 @@ registerModel({ return currentSet; }, new Set()); if (messageIds.size > 0) { - data2.messageSeenIndicators = insertAndReplace([...messageIds].map(messageId => { + data2.messageSeenIndicators = [...messageIds].map(messageId => { return { - message: insertAndReplace({ id: messageId }), + message: { id: messageId }, }; - })); + }); } } } @@ -432,10 +429,10 @@ registerModel({ }); return this.insert(channelsData.map(channelData => this.messaging.models['Thread'].convertData({ - channel: insertAndReplace({ + channel: { channel_type: channelData.channel_type, id: channelData.id, - }), + }, id: channelData.id, name: channelData.name, }) @@ -545,23 +542,23 @@ registerModel({ const values = { hasWriteAccess, mainAttachment, hasReadAccess }; if (activitiesData) { Object.assign(values, { - activities: insertAndReplace(activitiesData.map(activityData => + activities: activitiesData.map(activityData => this.messaging.models['Activity'].convertData(activityData) - )), + ), }); } if (attachmentsData) { Object.assign(values, { areAttachmentsLoaded: true, isLoadingAttachments: false, - originThreadAttachments: insertAndReplace(attachmentsData), + originThreadAttachments: attachmentsData, }); } if (followersData) { Object.assign(values, { - followers: insertAndReplace(followersData.map(followerData => + followers: followersData.map(followerData => this.messaging.models['Follower'].convertData(followerData) - )), + ), }); } if (suggestedRecipientsData) { @@ -578,7 +575,7 @@ registerModel({ }; }); Object.assign(values, { - suggestedRecipientInfoList: insertAndReplace(recipientInfoList), + suggestedRecipientInfoList: recipientInfoList, }); } this.update(values); @@ -864,7 +861,9 @@ registerModel({ * Refresh the typing status of the current partner. */ refreshCurrentPartnerIsTyping() { - this.update({ currentPartnerInactiveTypingTimer: [clear(), insertAndReplace()] }); + this.update({ + currentPartnerInactiveTypingTimer: { doReset: this.currentPartnerInactiveTypingTimer ? true : undefined }, + }); }, /** * Called to refresh a registered other member partner that is typing @@ -888,8 +887,8 @@ registerModel({ async registerCurrentPartnerIsTyping() { // Handling of typing timers. this.update({ - currentPartnerInactiveTypingTimer: insertAndReplace(), - currentPartnerLongTypingTimer: insertAndReplace(), + currentPartnerInactiveTypingTimer: {}, + currentPartnerLongTypingTimer: {}, }); // Manage typing member relation. const currentPartner = this.messaging.currentPartner; @@ -1063,7 +1062,7 @@ registerModel({ if (this.mailbox) { return clear(); } - return insertAndReplace(); + return {}; }, /** * @private @@ -1122,7 +1121,7 @@ registerModel({ if (!discussSidebarCategory) { return clear(); } - return insertAndReplace({ category: discussSidebarCategory }); + return { category: discussSidebarCategory }; }, /** * @private @@ -1221,6 +1220,7 @@ registerModel({ */ _computeIsDescriptionEditableByCurrentUser() { return Boolean( + this.messaging && this.messaging.currentUser && this.messaging.currentUser.isInternalUser && this.isChannelDescriptionChangeable @@ -1449,7 +1449,7 @@ registerModel({ * @returns {FieldCommand} */ _computeMessagingMenuAsPinnedAndUnreadChannel() { - if (!this.messaging.messagingMenu) { + if (!this.messaging || !this.messaging.messagingMenu) { return clear(); } return (this.model === 'mail.channel' && this.isPinned && this.localMessageUnreadCounter > 0) @@ -1522,7 +1522,7 @@ registerModel({ */ _computeCallInviteRequestPopup() { if (this.rtcInvitingSession) { - return insertAndReplace(); + return {}; } return clear(); }, @@ -1531,9 +1531,9 @@ registerModel({ * @returns {Throttle} */ _computeThrottleNotifyCurrentPartnerTypingStatus() { - return insertAndReplace({ + return { func: () => this._notifyCurrentPartnerTypingStatus(), - }); + }; }, /** * @private @@ -1625,7 +1625,7 @@ registerModel({ } } if (this.isCurrentPartnerTyping && this.currentPartnerLongTypingTimer) { - this.update({ currentPartnerLongTypingTimer: [clear(), insertAndReplace()] }); + this.currentPartnerLongTypingTimer.update({ doReset: true }); } } this.update({ @@ -1722,8 +1722,9 @@ registerModel({ */ async onCurrentPartnerLongTypingTimeout() { this.update({ - isCurrentPartnerTyping: true, + currentPartnerLongTypingTimer: clear(), forceNotifyNextCurrentPartnerTypingStatus: true, + isCurrentPartnerTyping: true, }); this.throttleNotifyCurrentPartnerTypingStatus.clear(); await this.throttleNotifyCurrentPartnerTypingStatus.do(); @@ -1759,7 +1760,7 @@ registerModel({ */ avatarCacheKey: attr(), cache: one('ThreadCache', { - default: insertAndReplace(), + default: {}, inverse: 'thread', isCausal: true, readonly: true, @@ -2274,7 +2275,7 @@ registerModel({ default: 0, }), suggestable: one('ComposerSuggestable', { - default: insertAndReplace(), + default: {}, inverse: 'thread', isCausal: true, readonly: true, diff --git a/addons/mail/static/src/models/thread_needaction_preview_view.js b/addons/mail/static/src/models/thread_needaction_preview_view.js index 97d416d7933..dd47a45d21f 100644 --- a/addons/mail/static/src/models/thread_needaction_preview_view.js +++ b/addons/mail/static/src/models/thread_needaction_preview_view.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; import { htmlToTextContentInline } from '@mail/js/utils'; registerModel({ @@ -71,7 +71,7 @@ registerModel({ this.thread.lastNeedactionMessageAsOriginThread && this.thread.lastNeedactionMessageAsOriginThread.author ) { - return insertAndReplace(); + return {}; } return clear(); }, @@ -80,7 +80,7 @@ registerModel({ * @returns {FieldCommand} */ _computePersonaImStatusIconView() { - return this.thread.correspondent && this.thread.correspondent.isImStatusSet ? insertAndReplace() : clear(); + return this.thread.correspondent && this.thread.correspondent.isImStatusSet ? {} : clear(); }, }, fields: { diff --git a/addons/mail/static/src/models/thread_preview_view.js b/addons/mail/static/src/models/thread_preview_view.js index e62c734634e..060d32012d8 100644 --- a/addons/mail/static/src/models/thread_preview_view.js +++ b/addons/mail/static/src/models/thread_preview_view.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; import { htmlToTextContentInline } from '@mail/js/utils'; registerModel({ @@ -69,7 +69,7 @@ registerModel({ this.thread.lastMessage && this.thread.lastMessage.author ) { - return insertAndReplace(); + return {}; } return clear(); }, @@ -78,7 +78,7 @@ registerModel({ * @returns {FieldCommand} */ _computePersonaImStatusIconView() { - return this.thread.correspondent && this.thread.correspondent.isImStatusSet ? insertAndReplace() : clear(); + return this.thread.correspondent && this.thread.correspondent.isImStatusSet ? {} : clear(); }, }, fields: { diff --git a/addons/mail/static/src/models/thread_view.js b/addons/mail/static/src/models/thread_view.js index f1b82c4986d..5f9e9a70025 100644 --- a/addons/mail/static/src/models/thread_view.js +++ b/addons/mail/static/src/models/thread_view.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, many, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; import { OnChange } from '@mail/model/model_onchange'; registerModel({ @@ -88,7 +88,7 @@ registerModel({ */ _computeCallView() { return (this.thread && this.thread.model === 'mail.channel' && this.thread.rtcSessions.length > 0) - ? insertAndReplace() + ? {} : clear(); }, /** @@ -97,7 +97,7 @@ registerModel({ */ _computeChannelMemberListView() { if (this.thread && this.thread.hasMemberListFeature && this.hasMemberList && this.isMemberListOpened) { - return insertAndReplace(); + return {}; } return clear(); }, @@ -112,7 +112,7 @@ registerModel({ if (this.threadViewer && this.threadViewer.chatter) { return clear(); } - return insertAndReplace(); + return {}; }, /** * @private @@ -160,7 +160,7 @@ registerModel({ return ( (this.thread && this.thread.isTemporary) || (this.threadCache && this.threadCache.isLoaded) - ) ? insertAndReplace() : clear(); + ) ? {} : clear(); }, /** * @private @@ -224,7 +224,7 @@ registerModel({ * @private */ _computeTopbar() { - return this.hasTopbar ? insertAndReplace() : clear(); + return this.hasTopbar ? {} : clear(); }, /** * @private diff --git a/addons/mail/static/src/models/thread_view_topbar.js b/addons/mail/static/src/models/thread_view_topbar.js index fe6d2ba3c14..ff255416a60 100644 --- a/addons/mail/static/src/models/thread_view_topbar.js +++ b/addons/mail/static/src/models/thread_view_topbar.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; registerModel({ name: 'ThreadViewTopbar', @@ -336,7 +336,7 @@ registerModel({ * Open the invite popover view in this thread view topbar. */ openInvitePopoverView() { - this.update({ invitePopoverView: insertAndReplace() }); + this.update({ invitePopoverView: {} }); if (this.messaging.isCurrentUserGuest) { return; } diff --git a/addons/mail/static/src/models/thread_viewer.js b/addons/mail/static/src/models/thread_viewer.js index 78a6ddf76b3..1ec6770abe9 100644 --- a/addons/mail/static/src/models/thread_viewer.js +++ b/addons/mail/static/src/models/thread_viewer.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; registerModel({ name: 'ThreadViewer', @@ -55,7 +55,7 @@ registerModel({ * @returns {ThreadViewer|undefined} */ _computeThreadView() { - return this.hasThreadView ? insertAndReplace() : clear(); + return this.hasThreadView ? {} : clear(); }, /** * @private diff --git a/addons/mail/static/src/models/throttle.js b/addons/mail/static/src/models/throttle.js index d6eb8816795..df45ab6aa6f 100644 --- a/addons/mail/static/src/models/throttle.js +++ b/addons/mail/static/src/models/throttle.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; /** * This model defines a "Throttle", which is an abstraction to throttle calls on a @@ -28,7 +28,7 @@ registerModel({ async do() { if (!this.cooldownTimer) { this.func(); - this.update({ cooldownTimer: insertAndReplace() }); + this.update({ cooldownTimer: {} }); } else { this.update({ shouldInvoke: true }); } @@ -37,7 +37,10 @@ registerModel({ if (this.shouldInvoke) { this.func(); } - this.update({ shouldInvoke: false }); + this.update({ + cooldownTimer: clear(), + shouldInvoke: false, + }); }, /** * @private diff --git a/addons/mail/static/src/models/timer.js b/addons/mail/static/src/models/timer.js index f47bc9613a1..c97f2884b54 100644 --- a/addons/mail/static/src/models/timer.js +++ b/addons/mail/static/src/models/timer.js @@ -3,11 +3,15 @@ import { registerModel } from '@mail/model/model_core'; import { attr, one } from '@mail/model/model_field'; import { clear } from '@mail/model/model_field_command'; +import { OnChange } from "@mail/model/model_onchange"; registerModel({ name: 'Timer', identifyingMode: 'xor', lifecycleHooks: { + _created() { + this.update({ timeoutId: this.messaging.browser.setTimeout(this._onTimeout, this.duration) }); + }, _willDelete() { this.messaging.browser.clearTimeout(this.timeoutId); }, @@ -47,32 +51,11 @@ registerModel({ } return clear(); }, - /** - * @private - * @returns {number} - */ - _computeTimeoutId() { - if (this.duration === undefined) { - return; // ensure duration is computed first - } - if (this.timeoutId) { - return; - } - return this.messaging.browser.setTimeout(this._onTimeout, this.duration); - }, /** * @private */ _onTimeout() { - this._onTimeoutOwner(); - if (this.exists()) { // owner might have deleted the timer itself - this.delete(); - } - }, - /** - * @private - */ - _onTimeoutOwner() { + this.update({ timeoutId: clear() }); if (this.callMainViewAsShowOverlay) { this.callMainViewAsShowOverlay.onShowOverlayTimeout(); return; @@ -110,6 +93,16 @@ registerModel({ return; } }, + _onChangeDoReset() { + if (!this.doReset) { + return; + } + this.messaging.browser.clearTimeout(this.timeoutId); + this.update({ + doReset: clear(), + timeoutId: this.messaging.browser.setTimeout(this._onTimeout, this.duration), + }); + }, }, fields: { callMainViewAsShowOverlay: one('CallMainView', { @@ -120,6 +113,9 @@ registerModel({ identifying: true, inverse: 'attachmentsLoaderTimer', }), + doReset: attr({ + default: false, + }), /** * Duration, in milliseconds, until timer times out and calls the * timeout function. @@ -162,10 +158,12 @@ registerModel({ * Internal reference of `setTimeout()` that is used to invoke function * when timer times out. Useful to clear it when timer is cleared/reset. */ - timeoutId: attr({ - compute: '_computeTimeoutId', - readonly: true, - required: true, - }), + timeoutId: attr(), }, + onChanges: [ + new OnChange({ + dependencies: ["doReset"], + methodName: '_onChangeDoReset', + }), + ], }); diff --git a/addons/mail/static/src/models/user_setting.js b/addons/mail/static/src/models/user_setting.js index 30a7a79f241..c2a3e207a7b 100644 --- a/addons/mail/static/src/models/user_setting.js +++ b/addons/mail/static/src/models/user_setting.js @@ -4,7 +4,7 @@ import { browser } from "@web/core/browser/browser"; import { registerModel } from '@mail/model/model_core'; import { attr, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; /** * Models various user settings. It is used as a complement to @@ -286,7 +286,7 @@ registerModel({ * Model for the component with the controls for RTC related settings. */ callSettingsMenu: one('CallSettingsMenu', { - default: insertAndReplace(), + default: {}, inverse: 'userSetting', isCausal: true, }), diff --git a/addons/mail/static/src/models/welcome_view.js b/addons/mail/static/src/models/welcome_view.js index 63154f4ef2e..5debdc62ec3 100644 --- a/addons/mail/static/src/models/welcome_view.js +++ b/addons/mail/static/src/models/welcome_view.js @@ -2,7 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; const getNextGuestNameInputId = (function () { let id = 0; @@ -94,7 +94,7 @@ registerModel({ */ _computeCallDemoView() { return (this.channel && this.channel.defaultDisplayMode === 'video_full_screen') - ? insertAndReplace() + ? {} : clear(); }, /** diff --git a/addons/mail/static/tests/helpers/mock_server.js b/addons/mail/static/tests/helpers/mock_server.js index 05272d68e7b..073e26fbec1 100644 --- a/addons/mail/static/tests/helpers/mock_server.js +++ b/addons/mail/static/tests/helpers/mock_server.js @@ -533,7 +533,7 @@ patch(MockServer.prototype, 'mail', { [['res_id', '=', thread.id], ['res_model', '=', thread_model]], ); // order not done for simplicity res['attachments'] = this._mockIrAttachment_attachmentFormat(attachments.map(attachment => attachment.id)); - res['mainAttachment'] = thread.message_main_attachment_id ? [['insert-and-replace', { 'id': thread.message_main_attachment_id[0] }]] : [['clear']]; + res['mainAttachment'] = thread.message_main_attachment_id ? { 'id': thread.message_main_attachment_id[0] } : [['clear']]; } if (request_list.includes('followers')) { const followers = this.pyEnv['mail.followers'].searchRead([['id', 'in', thread.message_follower_ids || []]]); @@ -1035,7 +1035,7 @@ patch(MockServer.prototype, 'mail', { res['rtc_inviting_session'] = { 'id': memberOfCurrentUser.rtc_inviting_session_id }; } } - res.channel = [['insert-and-replace', channelData]]; + res.channel = channelData; return res; }); }, @@ -1323,11 +1323,11 @@ patch(MockServer.prototype, 'mail', { { fields: ['id', 'name', 'im_status'] } ); persona = { - 'partner': [['insert-and-replace', { + 'partner': { 'id': partner.id, 'name': partner.name, 'im_status': partner.im_status, - }]], + }, }; } if (member.guest_id) { @@ -1336,15 +1336,15 @@ patch(MockServer.prototype, 'mail', { { fields: ['id', 'name'] } ); persona = { - 'guest': [['insert-and-replace', { + 'guest': { 'id': guest.id, 'name': guest.name, - }]], + }, }; } membersData.push({ 'id': member.id, - 'persona': [['insert-and-replace', persona]], + 'persona': persona, }); } return { @@ -1500,7 +1500,7 @@ patch(MockServer.prototype, 'mail', { const attachments = this.getRecords('ir.attachment', [ ['id', 'in', message.attachment_ids], ]); - const formattedAttachments = [['insert-and-replace', this._mockIrAttachment_attachmentFormat(attachments.map(attachment => attachment.id))]]; + const formattedAttachments = this._mockIrAttachment_attachmentFormat(attachments.map(attachment => attachment.id)); const allNotifications = this.getRecords('mail.notification', [ ['mail_message_id', '=', message.id], ]); @@ -1519,7 +1519,7 @@ patch(MockServer.prototype, 'mail', { const trackingValueIds = this.getRecords('mail.tracking.value', [ ['id', 'in', message.tracking_value_ids], ]); - const formattedTrackingValues = [['insert-and-replace', this._mockMailTrackingValue_TrackingValueFormat(trackingValueIds)]]; + const formattedTrackingValues = this._mockMailTrackingValue_TrackingValueFormat(trackingValueIds); const partners = this.getRecords( 'res.partner', [['id', 'in', message.partner_ids]], @@ -2094,14 +2094,14 @@ patch(MockServer.prototype, 'mail', { const trackingValues = tracking_value_ids.map(tracking => ({ changedField: tracking.field_desc, id: tracking.id, - newValue: [['insert-and-replace', { + newValue: { fieldType: tracking.field_type, value: this._mockMailTrackingValue_GetDisplayValue(tracking, 'new') - }]], - oldValue: [['insert-and-replace', { + }, + oldValue: { fieldType: tracking.field_type, value: this._mockMailTrackingValue_GetDisplayValue(tracking, 'old') - }]], + }, })); return trackingValues; }, @@ -2225,7 +2225,7 @@ patch(MockServer.prototype, 'mail', { const filterPredicate = fieldsToFormat ? ([fieldName]) => fieldsToFormat.includes(fieldName) : ([fieldName]) => !ormAutomaticFields.has(fieldName); const res = Object.fromEntries(Object.entries(settings).filter(filterPredicate)); if (Object.prototype.hasOwnProperty.call(res, 'user_id')) { - res.user_id = [['insert-and-replace', { id: settings.user_id }]]; + res.user_id = { id: settings.user_id }; } if (Object.prototype.hasOwnProperty.call(res, 'volume_settings_ids')) { const volumeSettings = this._mockResUsersSettingsVolumes_DiscussUsersSettingsVolumeFormat(settings.volume_settings_ids); @@ -2263,9 +2263,9 @@ patch(MockServer.prototype, 'mail', { const [relatedGuest] = this.getRecords('mail.guest', [['id', '=', volumeSettingsRecord.guest_id]]); const [relatedPartner] = this.getRecords('res.partner', [['id', '=', volumeSettingsRecord.partner_id]]); return { - guest_id: relatedGuest ? [['insert-and-replace', { id: relatedGuest.id, name: relatedGuest.name }]] : [['clear']], + guest_id: relatedGuest ? { id: relatedGuest.id, name: relatedGuest.name } : [['clear']], id: volumeSettingsRecord.id, - partner_id: relatedPartner ? [['insert-and-replace', { id: relatedPartner.id, name: relatedPartner.name }]] : [['clear']], + partner_id: relatedPartner ? { id: relatedPartner.id, name: relatedPartner.name } : [['clear']], volume: volumeSettingsRecord.volume, }; }); diff --git a/addons/mail/static/tests/helpers/webclient_setup.js b/addons/mail/static/tests/helpers/webclient_setup.js index a2ecd0d49fb..5ef25aef926 100644 --- a/addons/mail/static/tests/helpers/webclient_setup.js +++ b/addons/mail/static/tests/helpers/webclient_setup.js @@ -6,7 +6,6 @@ import { makeBusServiceToLegacyEnv } from '@bus/services/legacy/make_bus_service import { makeMultiTabToLegacyEnv } from '@bus/services/legacy/make_multi_tab_to_legacy_env'; import { makeFakePresenceService } from '@bus/../tests/helpers/mock_services'; -import { insertAndReplace } from '@mail/model/model_field_command'; import { ChatWindowManagerContainer } from '@mail/components/chat_window_manager_container/chat_window_manager_container'; import { DialogManagerContainer } from '@mail/components/dialog_manager_container/dialog_manager_container'; import { DiscussContainer } from '@mail/components/discuss_container/discuss_container'; @@ -82,7 +81,7 @@ function setupMessagingServiceRegistries({ disableAnimation: true, loadingBaseDelayDuration, messagingBus, - userNotificationManager: insertAndReplace({ canPlayAudio: false }), + userNotificationManager: { canPlayAudio: false }, }; } }; diff --git a/addons/mail/static/tests/models/test_models.js b/addons/mail/static/tests/models/test_models.js index f95e5c2cbbd..49b3d3d92b4 100644 --- a/addons/mail/static/tests/models/test_models.js +++ b/addons/mail/static/tests/models/test_models.js @@ -2,7 +2,6 @@ import { registerModel } from '@mail/model/model_core'; import { attr, many, one } from '@mail/model/model_field'; -import { insertAndReplace } from '@mail/model/model_field_command'; registerModel({ name: 'TestAddress', @@ -27,13 +26,13 @@ registerModel({ inverse: 'contact', }), favorite: one('TestHobby', { - default: insertAndReplace({ description: 'football' }), + default: { description: 'football' }, }), hobbies: many('TestHobby', { - default: insertAndReplace([ + default: [ { description: 'hiking' }, { description: 'fishing' }, - ]), + ], }), tasks: many('TestTask', { inverse: 'responsible' diff --git a/addons/mail/static/tests/qunit_suite_tests/model_field_commands/clear_tests.js b/addons/mail/static/tests/qunit_suite_tests/model_field_commands/clear_tests.js index fe18db0d73c..2dc53781e6c 100644 --- a/addons/mail/static/tests/qunit_suite_tests/model_field_commands/clear_tests.js +++ b/addons/mail/static/tests/qunit_suite_tests/model_field_commands/clear_tests.js @@ -1,6 +1,6 @@ /** @odoo-module **/ -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; import { start } from '@mail/../tests/helpers/test_utils'; QUnit.module('mail', {}, function () { @@ -44,7 +44,7 @@ QUnit.test('clear: should set x2one field undefined if no default value is given const contact = messaging.models['TestContact'].insert({ id: 10, - address: insertAndReplace({ id: 20 }), + address: { id: 20 }, }); const address = messaging.models['TestAddress'].findFromIdentifyingData({ id: 20 }); contact.update({ address: clear() }); @@ -65,7 +65,7 @@ QUnit.test('clear: should set x2one field the default value', async function (as const { messaging } = await start(); const contact = messaging.models['TestContact'].insert({ - favorite: insertAndReplace({ description: 'pingpong' }), + favorite: { description: 'pingpong' }, id: 10, }); contact.update({ favorite: clear() }); @@ -82,7 +82,7 @@ QUnit.test('clear: should set x2many field empty array if no default value is gi const contact = messaging.models['TestContact'].insert({ id: 10, - tasks: insertAndReplace({ id: 20 }), + tasks: { id: 20 }, }); const task = messaging.models['TestTask'].findFromIdentifyingData({ id: 20 }); contact.update({ tasks: clear() }); @@ -105,9 +105,9 @@ QUnit.test('clear: should set x2many field the default value', async function (a const contact = messaging.models['TestContact'].insert({ id: 10, hobbies: [ - insertAndReplace({ description: 'basketball' }), - insertAndReplace({ description: 'running' }), - insertAndReplace({ description: 'photographing' }), + { description: 'basketball' }, + { description: 'running' }, + { description: 'photographing' }, ], }); contact.update({ hobbies: clear() }); diff --git a/addons/mail/static/tests/qunit_suite_tests/model_field_commands/insert_and_replace_tests.js b/addons/mail/static/tests/qunit_suite_tests/model_field_commands/insert_and_replace_tests.js index 0e11a511820..f68bab4fe36 100644 --- a/addons/mail/static/tests/qunit_suite_tests/model_field_commands/insert_and_replace_tests.js +++ b/addons/mail/static/tests/qunit_suite_tests/model_field_commands/insert_and_replace_tests.js @@ -1,6 +1,5 @@ /** @odoo-module **/ -import { insertAndReplace } from '@mail/model/model_field_command'; import { start } from '@mail/../tests/helpers/test_utils'; QUnit.module('mail', {}, function () { @@ -12,7 +11,7 @@ QUnit.test('insertAndReplace: should create and link a new record for an empty x const { messaging } = await start(); const contact = messaging.models['TestContact'].insert({ id: 10 }); - contact.update({ address: insertAndReplace({ id: 10 }) }); + contact.update({ address: { id: 10 } }); const address = messaging.models['TestAddress'].findFromIdentifyingData({ id: 10 }); assert.strictEqual( contact.address, @@ -32,10 +31,10 @@ QUnit.test('insertAndReplace: should create and replace a new record for a non-e const contact = messaging.models['TestContact'].insert({ id: 10, - address: insertAndReplace({ id: 10 }), + address: { id: 10 }, }); const address10 = messaging.models['TestAddress'].findFromIdentifyingData({ id: 10 }); - contact.update({ address: insertAndReplace({ id: 20 }) }); + contact.update({ address: { id: 20 } }); const address20 = messaging.models['TestAddress'].findFromIdentifyingData({ id: 20 }); assert.strictEqual( contact.address, @@ -60,17 +59,17 @@ QUnit.test('insertAndReplace: should update the existing record for an x2one fie const contact = messaging.models['TestContact'].insert({ id: 10, - address: insertAndReplace({ + address: { id: 10, addressInfo: 'address 10', - }), + }, }); const address10 = messaging.models['TestAddress'].findFromIdentifyingData({ id: 10 }); contact.update({ - address: insertAndReplace({ + address: { id: 10, addressInfo: 'address 10 updated', - }), + }, }); assert.strictEqual( contact.address, @@ -90,10 +89,10 @@ QUnit.test('insertAndReplace: should create and replace the records for an x2man const contact = messaging.models['TestContact'].insert({ id: 10, - tasks: insertAndReplace({ id: 10 }), + tasks: { id: 10 }, }); const task10 = messaging.models['TestTask'].findFromIdentifyingData({ id: 10 }); - contact.update({ tasks: insertAndReplace({ id: 20 }) }); + contact.update({ tasks: { id: 20 } }); const task20 = messaging.models['TestTask'].findFromIdentifyingData({ id: 20 }); assert.strictEqual( contact.tasks.length, @@ -123,18 +122,18 @@ QUnit.test('insertAndReplace: should update and replace the records for an x2man const contact = messaging.models['TestContact'].insert({ id: 10, - tasks: insertAndReplace([ + tasks: [ { id: 10, title: 'task 10' }, { id: 20, title: 'task 20' }, - ]), + ], }); const task10 = messaging.models['TestTask'].findFromIdentifyingData({ id: 10 }); const task20 = messaging.models['TestTask'].findFromIdentifyingData({ id: 20 }); contact.update({ - tasks: insertAndReplace({ + tasks: { id: 10, title: 'task 10 updated', - }), + }, }); assert.strictEqual( contact.tasks.length, diff --git a/addons/mail/static/tests/qunit_suite_tests/model_field_commands/insert_tests.js b/addons/mail/static/tests/qunit_suite_tests/model_field_commands/insert_tests.js index 5df1d22cd4f..961c40e0aed 100644 --- a/addons/mail/static/tests/qunit_suite_tests/model_field_commands/insert_tests.js +++ b/addons/mail/static/tests/qunit_suite_tests/model_field_commands/insert_tests.js @@ -1,6 +1,6 @@ /** @odoo-module **/ -import { insert, insertAndReplace } from '@mail/model/model_field_command'; +import { insert } from '@mail/model/model_field_command'; import { start } from '@mail/../tests/helpers/test_utils'; QUnit.module('mail', {}, function () { @@ -32,7 +32,7 @@ QUnit.test('insert: should create and replace a new record for a non-empty x2one const contact = messaging.models['TestContact'].insert({ id: 10, - address: insertAndReplace({ id: 10 }), + address: { id: 10 }, }); const address10 = messaging.models['TestAddress'].findFromIdentifyingData({ id: 10 }); contact.update({ address: insert({ id: 20 }) }); @@ -60,10 +60,10 @@ QUnit.test('insert: should update the existing record for an x2one field', async const contact = messaging.models['TestContact'].insert({ id: 10, - address: insertAndReplace({ + address: { id: 10, addressInfo: 'address 10', - }), + }, }); const address10 = messaging.models['TestAddress'].findFromIdentifyingData({ id: 10 }); contact.update({ @@ -114,7 +114,7 @@ QUnit.test('insert: should create and add a new record for an x2many field', asy const contact = messaging.models['TestContact'].insert({ id: 10, - tasks: insertAndReplace({ id: 10 }), + tasks: { id: 10 }, }); const task10 = messaging.models['TestTask'].findFromIdentifyingData({ id: 10 }); contact.update({ tasks: insert({ id: 20 }) }); @@ -147,10 +147,10 @@ QUnit.test('insert: should update existing records for an x2many field', async f const contact = messaging.models['TestContact'].insert({ id: 10, - tasks: insertAndReplace({ + tasks: { id: 10, title: 'task 10', - }), + }, }); const task = messaging.models['TestTask'].findFromIdentifyingData({ id: 10 }); contact.update({ diff --git a/addons/mail/static/tests/qunit_suite_tests/model_field_commands/link_tests.js b/addons/mail/static/tests/qunit_suite_tests/model_field_commands/link_tests.js index 1a0a63f0a92..2b9366c8a96 100644 --- a/addons/mail/static/tests/qunit_suite_tests/model_field_commands/link_tests.js +++ b/addons/mail/static/tests/qunit_suite_tests/model_field_commands/link_tests.js @@ -1,6 +1,6 @@ /** @odoo-module **/ -import { insertAndReplace, link } from '@mail/model/model_field_command'; +import { link } from '@mail/model/model_field_command'; import { start } from '@mail/../tests/helpers/test_utils'; QUnit.module('mail', {}, function () { @@ -32,7 +32,7 @@ QUnit.test('link: should replace a record to a non-empty x2one field', async fun const contact = messaging.models['TestContact'].insert({ id: 10, - address: insertAndReplace({ id: 10 }), + address: { id: 10 }, }); const address10 = messaging.models['TestAddress'].findFromIdentifyingData({ id: 10 }); const address20 = messaging.models['TestAddress'].insert({ id: 20 }); @@ -84,7 +84,7 @@ QUnit.test('link: should link and add a record to a non-empty x2many field', asy const contact = messaging.models['TestContact'].insert({ id: 10, - tasks: insertAndReplace({ id: 10 }), + tasks: { id: 10 }, }); const task10 = messaging.models['TestTask'].findFromIdentifyingData({ id: 10 }); const task20 = messaging.models['TestTask'].insert({ id: 20 }); diff --git a/addons/mail/static/tests/qunit_suite_tests/model_field_commands/replace_tests.js b/addons/mail/static/tests/qunit_suite_tests/model_field_commands/replace_tests.js index 687f50faff3..f97fa9f9d2c 100644 --- a/addons/mail/static/tests/qunit_suite_tests/model_field_commands/replace_tests.js +++ b/addons/mail/static/tests/qunit_suite_tests/model_field_commands/replace_tests.js @@ -1,6 +1,5 @@ /** @odoo-module **/ -import { insertAndReplace } from '@mail/model/model_field_command'; import { start } from '@mail/../tests/helpers/test_utils'; QUnit.module('mail', {}, function () { @@ -32,7 +31,7 @@ QUnit.test('replace: should replace a record for a non-empty x2one field', async const contact = messaging.models['TestContact'].insert({ id: 10, - address: insertAndReplace({ id: 10 }), + address: { id: 10 }, }); const address10 = messaging.models['TestAddress'].findFromIdentifyingData({ id: 10 }); const address20 = messaging.models['TestAddress'].insert({ id: 20 }); @@ -89,10 +88,10 @@ QUnit.test('replace: should replace all records for a non-empty field', async fu const contact = messaging.models['TestContact'].insert({ id: 10, - tasks: insertAndReplace([ + tasks: [ { id: 10 }, { id: 20 }, - ]), + ], }); const task10 = messaging.models['TestTask'].findFromIdentifyingData({ id: 10 }); const task20 = messaging.models['TestTask'].findFromIdentifyingData({ id: 20 }); @@ -131,10 +130,10 @@ QUnit.test('replace: should order the existing records for x2many field', async const contact = messaging.models['TestContact'].insert({ id: 10, - tasks: insertAndReplace([ + tasks: [ { id: 10 }, { id: 20 }, - ]), + ], }); const task10 = messaging.models['TestTask'].findFromIdentifyingData({ id: 10 }); const task20 = messaging.models['TestTask'].findFromIdentifyingData({ id: 20 }); diff --git a/addons/mail/static/tests/qunit_suite_tests/model_field_commands/unlink_all_tests.js b/addons/mail/static/tests/qunit_suite_tests/model_field_commands/unlink_all_tests.js index 5bbbba94319..95e897a5683 100644 --- a/addons/mail/static/tests/qunit_suite_tests/model_field_commands/unlink_all_tests.js +++ b/addons/mail/static/tests/qunit_suite_tests/model_field_commands/unlink_all_tests.js @@ -1,6 +1,6 @@ /** @odoo-module **/ -import { insertAndReplace, unlinkAll } from '@mail/model/model_field_command'; +import { unlinkAll } from '@mail/model/model_field_command'; import { start } from '@mail/../tests/helpers/test_utils'; QUnit.module('mail', {}, function () { @@ -13,7 +13,7 @@ QUnit.test('unlinkAll: should set x2one field undefined', async function (assert const contact = messaging.models['TestContact'].insert({ id: 10, - address: insertAndReplace({ id: 20 }), + address: { id: 20 }, }); const address = messaging.models['TestAddress'].findFromIdentifyingData({ id: 20 }); contact.update({ address: unlinkAll() }); @@ -35,9 +35,9 @@ QUnit.test('unlinkAll: should set x2many field an empty array', async function ( const contact = messaging.models['TestContact'].insert({ id: 10, - tasks: insertAndReplace({ + tasks: { id: 20, - }), + }, }); const task = messaging.models['TestTask'].findFromIdentifyingData({ id: 20 }); contact.update({ tasks: unlinkAll() }); diff --git a/addons/mail/static/tests/qunit_suite_tests/model_field_commands/unlink_tests.js b/addons/mail/static/tests/qunit_suite_tests/model_field_commands/unlink_tests.js index 41f6b63b2b6..c0647f53bfa 100644 --- a/addons/mail/static/tests/qunit_suite_tests/model_field_commands/unlink_tests.js +++ b/addons/mail/static/tests/qunit_suite_tests/model_field_commands/unlink_tests.js @@ -1,6 +1,6 @@ /** @odoo-module **/ -import { clear, insertAndReplace, unlink } from '@mail/model/model_field_command'; +import { clear, unlink } from '@mail/model/model_field_command'; import { start } from '@mail/../tests/helpers/test_utils'; QUnit.module('mail', {}, function () { @@ -14,7 +14,7 @@ QUnit.test('unlink: should unlink the record for x2one field', async function (a const contact = messaging.models['TestContact'].insert({ id: 10, - address: insertAndReplace({ id: 10 }), + address: { id: 10 }, }); const address = messaging.models['TestAddress'].findFromIdentifyingData({ id: 10 }); contact.update({ address: clear() }); @@ -36,10 +36,10 @@ QUnit.test('unlink: should unlink the specified record for x2many field', async const contact = messaging.models['TestContact'].insert({ id: 10, - tasks: insertAndReplace([ + tasks: [ { id: 10 }, { id: 20 }, - ]), + ], }); const task10 = messaging.models['TestTask'].findFromIdentifyingData({ id: 10 }); const task20 = messaging.models['TestTask'].findFromIdentifyingData({ id: 20 }); diff --git a/addons/mail/static/tests/qunit_suite_tests/models/clock_tests.js b/addons/mail/static/tests/qunit_suite_tests/models/clock_tests.js index e759a1e2492..0de2e8d9013 100644 --- a/addons/mail/static/tests/qunit_suite_tests/models/clock_tests.js +++ b/addons/mail/static/tests/qunit_suite_tests/models/clock_tests.js @@ -1,6 +1,5 @@ /** @odoo-module **/ -import { insertAndReplace } from '@mail/model/model_field_command'; import { start } from '@mail/../tests/helpers/test_utils'; import { patchDate } from '@web/../tests/helpers/utils'; @@ -14,8 +13,8 @@ QUnit.test('Deleting all the watchers of a clock should result in the deletion o const { messaging } = await start(); const watcher = messaging.models['ClockWatcher'].insert({ - clock: insertAndReplace({ frequency: 180 * 1000 }), - qunitTestOwner: insertAndReplace(), + clock: { frequency: 180 * 1000 }, + qunitTestOwner: {}, }); const { clock } = watcher; @@ -36,8 +35,8 @@ QUnit.test('[technical] Before ticking for the first time, the clock should indi patchDate(2016, 8, 8, 14, 55, 15, 352); const { clock } = messaging.models['ClockWatcher'].insert({ - clock: insertAndReplace({ frequency: 3600 * 1000 }), - qunitTestOwner: insertAndReplace(), + clock: { frequency: 3600 * 1000 }, + qunitTestOwner: {}, }); assert.strictEqual( clock.date.getFullYear(), // no need to be more precise than the year diff --git a/addons/mail/static/tests/qunit_suite_tests/models/message_tests.js b/addons/mail/static/tests/qunit_suite_tests/models/message_tests.js index 4bd26a745c0..6cbc22e87ac 100644 --- a/addons/mail/static/tests/qunit_suite_tests/models/message_tests.js +++ b/addons/mail/static/tests/qunit_suite_tests/models/message_tests.js @@ -1,6 +1,6 @@ /** @odoo-module **/ -import { insert, insertAndReplace } from '@mail/model/model_field_command'; +import { insert } from '@mail/model/model_field_command'; import { start } from '@mail/../tests/helpers/test_utils'; import { str_to_datetime } from 'web.time'; @@ -27,12 +27,12 @@ QUnit.test('create', async function (assert) { name: "General", }); const message = messaging.models['Message'].insert({ - attachments: insertAndReplace({ + attachments: { filename: "test.txt", id: 750, mimetype: 'text/plain', name: "test.txt", - }), + }, author: insert({ id: 5, display_name: "Demo" }), body: "

Test

", date: moment(str_to_datetime("2019-05-05 10:00:00")), diff --git a/addons/mail/static/tests/qunit_suite_tests/models/thread_tests.js b/addons/mail/static/tests/qunit_suite_tests/models/thread_tests.js index 033aa436beb..123d685bbf6 100644 --- a/addons/mail/static/tests/qunit_suite_tests/models/thread_tests.js +++ b/addons/mail/static/tests/qunit_suite_tests/models/thread_tests.js @@ -1,6 +1,6 @@ /** @odoo-module **/ -import { insert, insertAndReplace } from '@mail/model/model_field_command'; +import { insert } from '@mail/model/model_field_command'; import { start } from '@mail/../tests/helpers/test_utils'; QUnit.module('mail', {}, function () { @@ -34,10 +34,10 @@ QUnit.test('create (channel)', async function (assert) { assert.notOk(messaging.models['Channel'].findFromIdentifyingData({ id: 100 })); messaging.models['Thread'].insert({ - channel: insertAndReplace({ + channel: { channel_type: 'channel', id: 100, - }), + }, id: 100, members: insert([{ email: "john@example.com", @@ -84,10 +84,10 @@ QUnit.test('create (chat)', async function (assert) { assert.notOk(messaging.models['Channel'].findFromIdentifyingData({ id: 200 })); messaging.models['Thread'].insert({ - channel: insertAndReplace({ + channel: { channel_type: 'chat', id: 200, - }), + }, id: 200, members: insert({ email: "demo@example.com", diff --git a/addons/mail/static/tests/qunit_suite_tests/utils/throttle_tests.js b/addons/mail/static/tests/qunit_suite_tests/utils/throttle_tests.js index 14f8c3df787..76de0fa74da 100644 --- a/addons/mail/static/tests/qunit_suite_tests/utils/throttle_tests.js +++ b/addons/mail/static/tests/qunit_suite_tests/utils/throttle_tests.js @@ -1,7 +1,6 @@ /** @odoo-module **/ import { start } from '@mail/../tests/helpers/test_utils'; -import { insertAndReplace } from '@mail/model/model_field_command'; import { nextTick } from '@mail/utils/utils'; QUnit.module('mail', {}, function () { @@ -18,7 +17,7 @@ QUnit.test('single call', async function (assert) { let hasInvokedFunc = false; const throttle = messaging.models['Throttle'].insert({ func: () => hasInvokedFunc = true, - qunitTestOwner1: insertAndReplace(), + qunitTestOwner1: {}, }); assert.notOk( hasInvokedFunc, @@ -48,7 +47,7 @@ QUnit.test('2nd (throttled) call', async function (assert) { let funcCalledAmount = 0; const throttle = messaging.models['Throttle'].insert({ func: () => funcCalledAmount++, - qunitTestOwner2: insertAndReplace(), + qunitTestOwner2: {}, }); throttle.do(); await nextTick(); @@ -90,7 +89,7 @@ QUnit.test('throttled call reinvocation', async function (assert) { let funcCalledAmount = 0; const throttle = messaging.models['Throttle'].insert({ func: () => funcCalledAmount++, - qunitTestOwner2: insertAndReplace(), + qunitTestOwner2: {}, }); throttle.do(); await nextTick(); @@ -134,7 +133,7 @@ QUnit.test('clear throttled call', async function (assert) { let funcCalledAmount = 0; const throttle = messaging.models['Throttle'].insert({ func: () => funcCalledAmount++, - qunitTestOwner2: insertAndReplace(), + qunitTestOwner2: {}, }); throttle.do(); await nextTick(); diff --git a/addons/mail/static/tests/qunit_suite_tests/utils/timer_tests.js b/addons/mail/static/tests/qunit_suite_tests/utils/timer_tests.js index 6077ccb0161..3c02afdd39e 100644 --- a/addons/mail/static/tests/qunit_suite_tests/utils/timer_tests.js +++ b/addons/mail/static/tests/qunit_suite_tests/utils/timer_tests.js @@ -1,6 +1,5 @@ /** @odoo-module **/ -import { insertAndReplace } from '@mail/model/model_field_command'; import { start } from '@mail/../tests/helpers/test_utils'; QUnit.module('mail', {}, function () { @@ -13,16 +12,16 @@ QUnit.test('timer insert (duration: 0ms)', async function (assert) { const { advanceTime, messaging } = await start({ hasTimeControl: true }); const timer = messaging.models['Timer'].insert({ - qunitTestOwner1: insertAndReplace(), + qunitTestOwner1: {}, }); assert.ok( - timer.exists(), + timer.timeoutId, "timer should not have timed out immediately after insert" ); await advanceTime(0); assert.notOk( - timer.exists(), + timer.timeoutId, "timer should have timed out on insert after 0ms" ); }); @@ -32,34 +31,34 @@ QUnit.test('timer insert (duration: 1000s)', async function (assert) { const { advanceTime, messaging } = await start({ hasTimeControl: true }); const timer = messaging.models['Timer'].insert({ - qunitTestOwner2: insertAndReplace(), + qunitTestOwner2: {}, }); assert.ok( - timer.exists(), + timer.timeoutId, "timer should not have timed out immediately after insert" ); await advanceTime(0); assert.ok( - timer.exists(), + timer.timeoutId, "timer should not have timed out on insert after 0ms" ); await advanceTime(1000); assert.ok( - timer.exists(), + timer.timeoutId, "timer should not have timed out on insert after 1000ms" ); await advanceTime(998 * 1000 + 999); assert.ok( - timer.exists(), + timer.timeoutId, "timer should not have timed out on insert after 9999ms" ); await advanceTime(1); assert.notOk( - timer.exists(), + timer.timeoutId, "timer should have timed out on insert after 10s" ); }); diff --git a/addons/mail/tests/test_rtc.py b/addons/mail/tests/test_rtc.py index 691ee23a975..c148c7eb475 100644 --- a/addons/mail/tests/test_rtc.py +++ b/addons/mail/tests/test_rtc.py @@ -47,17 +47,17 @@ class TestChannelInternals(MailCommon): 'id': channel.id, 'rtcSessions': [('insert', [{ 'id': channel_member.rtc_session_ids.id + 1, - 'channelMember': [("insert-and-replace", { + 'channelMember': { "id": channel_member.id, - "channel": [("insert-and-replace", {"id": channel_member.channel_id.id})], - "persona": [("insert-and-replace", { - "partner": [("insert-and-replace", { + "channel": {"id": channel_member.channel_id.id}, + "persona": { + "partner": { "id": channel_member.partner_id.id, "name": channel_member.partner_id.name, "im_status": channel_member.partner_id.im_status, - })], - })], - })], + }, + }, + }, 'isCameraOn': False, 'isDeaf': False, 'isSelfMuted': False, @@ -73,17 +73,17 @@ class TestChannelInternals(MailCommon): 'rtcSessions': [ ('insert', [{ 'id': channel_member.rtc_session_ids.id, - 'channelMember': [("insert-and-replace", { + 'channelMember': { "id": channel_member.id, - "channel": [("insert-and-replace", {"id": channel_member.channel_id.id})], - "persona": [("insert-and-replace", { - "partner": [("insert-and-replace", { + "channel": {"id": channel_member.channel_id.id}, + "persona": { + "partner": { "id": channel_member.partner_id.id, "name": channel_member.partner_id.name, "im_status": channel_member.partner_id.im_status, - })], - })], - })], + }, + }, + }, 'isCameraOn': False, 'isDeaf': False, 'isSelfMuted': False, @@ -122,17 +122,17 @@ class TestChannelInternals(MailCommon): 'id': channel.id, 'rtcSessions': [('insert', [{ 'id': last_rtc_session_id + 1, - 'channelMember': [("insert-and-replace", { + 'channelMember': { "id": channel_member.id, - "channel": [("insert-and-replace", {"id": channel_member.channel_id.id})], - "persona": [("insert-and-replace", { - "partner": [("insert-and-replace", { + "channel": {"id": channel_member.channel_id.id}, + "persona": { + "partner": { "id": channel_member.partner_id.id, "name": channel_member.partner_id.name, "im_status": channel_member.partner_id.im_status, - })], - })], - })], + }, + }, + }, 'isCameraOn': False, 'isDeaf': False, 'isSelfMuted': False, @@ -146,14 +146,14 @@ class TestChannelInternals(MailCommon): 'id': channel.id, 'invitedMembers': [('insert', [{ 'id': channel_member_test_user.id, - 'channel': [('insert-and-replace', {'id': channel_member_test_user.channel_id.id})], - 'persona': [('insert-and-replace', { - 'partner': [('insert-and-replace', { + 'channel': {'id': channel_member_test_user.channel_id.id}, + 'persona': { + 'partner': { 'id': channel_member_test_user.partner_id.id, 'name': channel_member_test_user.partner_id.name, 'im_status': channel_member_test_user.partner_id.im_status, - })], - })], + }, + }, }])], }, }, @@ -163,14 +163,14 @@ class TestChannelInternals(MailCommon): self.assertIn('invitedMembers', res) self.assertEqual(res['invitedMembers'], [('insert', [{ 'id': channel_member_test_user.id, - 'channel': [('insert-and-replace', {'id': channel_member_test_user.channel_id.id})], - 'persona': [('insert-and-replace', { - 'partner': [('insert-and-replace', { + 'channel': {'id': channel_member_test_user.channel_id.id}, + 'persona': { + 'partner': { 'id': channel_member_test_user.partner_id.id, 'name': channel_member_test_user.partner_id.name, 'im_status': channel_member_test_user.partner_id.im_status, - })], - })], + }, + }, }])]) @users('employee') @@ -205,17 +205,17 @@ class TestChannelInternals(MailCommon): 'id': channel.id, 'rtcSessions': [('insert', [{ 'id': last_rtc_session_id + 1, - 'channelMember': [("insert-and-replace", { + 'channelMember': { "id": channel_member.id, - "channel": [("insert-and-replace", {"id": channel_member.channel_id.id})], - "persona": [("insert-and-replace", { - "partner": [("insert-and-replace", { + "channel": {"id": channel_member.channel_id.id}, + "persona": { + "partner": { "id": channel_member.partner_id.id, "name": channel_member.partner_id.name, "im_status": channel_member.partner_id.im_status, - })], - })], - })], + }, + }, + }, 'isCameraOn': False, 'isDeaf': False, 'isSelfMuted': False, @@ -229,17 +229,17 @@ class TestChannelInternals(MailCommon): 'id': channel.id, 'rtcSessions': [('insert', [{ 'id': last_rtc_session_id + 1, - 'channelMember': [("insert-and-replace", { + 'channelMember': { "id": channel_member.id, - "channel": [("insert-and-replace", {"id": channel_member.channel_id.id})], - "persona": [("insert-and-replace", { - "partner": [("insert-and-replace", { + "channel": {"id": channel_member.channel_id.id}, + "persona": { + "partner": { "id": channel_member.partner_id.id, "name": channel_member.partner_id.name, "im_status": channel_member.partner_id.im_status, - })], - })], - })], + }, + }, + }, 'isCameraOn': False, 'isDeaf': False, 'isSelfMuted': False, @@ -254,25 +254,25 @@ class TestChannelInternals(MailCommon): 'invitedMembers': [('insert', [ { 'id': channel_member_test_user.id, - 'channel': [('insert-and-replace', {'id': channel_member_test_user.channel_id.id})], - 'persona': [('insert-and-replace', { - 'partner': [('insert-and-replace', { + 'channel': {'id': channel_member_test_user.channel_id.id}, + 'persona': { + 'partner': { 'id': channel_member_test_user.partner_id.id, 'name': channel_member_test_user.partner_id.name, 'im_status': channel_member_test_user.partner_id.im_status, - })], - })], + }, + }, }, { 'id': channel_member_test_guest.id, - 'channel': [('insert-and-replace', {'id': channel_member_test_guest.channel_id.id})], - 'persona': [('insert-and-replace', { - 'guest': [('insert-and-replace', { + 'channel': {'id': channel_member_test_guest.channel_id.id}, + 'persona': { + 'guest': { 'id': channel_member_test_guest.guest_id.id, 'name': channel_member_test_guest.guest_id.name, 'im_status': channel_member_test_guest.guest_id.im_status, - })], - })], + }, + }, }, ])], }, @@ -284,25 +284,25 @@ class TestChannelInternals(MailCommon): self.assertEqual(res['invitedMembers'], [('insert', [ { 'id': channel_member_test_user.id, - 'channel': [('insert-and-replace', {'id': channel_member_test_user.channel_id.id})], - 'persona': [('insert-and-replace', { - 'partner': [('insert-and-replace', { + 'channel': {'id': channel_member_test_user.channel_id.id}, + 'persona': { + 'partner': { 'id': channel_member_test_user.partner_id.id, 'name': channel_member_test_user.partner_id.name, 'im_status': channel_member_test_user.partner_id.im_status, - })], - })], + }, + }, }, { 'id': channel_member_test_guest.id, - 'channel': [('insert-and-replace', {'id': channel_member_test_guest.channel_id.id})], - 'persona': [('insert-and-replace', { - 'guest': [('insert-and-replace', { + 'channel': {'id': channel_member_test_guest.channel_id.id}, + 'persona': { + 'guest': { 'id': channel_member_test_guest.guest_id.id, 'name': channel_member_test_guest.guest_id.name, 'im_status': channel_member_test_guest.guest_id.im_status, - })], - })], + }, + }, }, ])]) @@ -338,14 +338,14 @@ class TestChannelInternals(MailCommon): 'id': channel.id, 'invitedMembers': [('insert-and-unlink', [{ 'id': channel_member_test_user.id, - 'channel': [('insert-and-replace', {'id': channel_member_test_user.channel_id.id})], - 'persona': [('insert-and-replace', { - 'partner': [('insert-and-replace', { + 'channel': {'id': channel_member_test_user.channel_id.id}, + 'persona': { + 'partner': { 'id': channel_member_test_user.partner_id.id, 'name': channel_member_test_user.partner_id.name, 'im_status': channel_member_test_user.partner_id.im_status, - })], - })], + }, + }, }])], }, }, @@ -356,17 +356,17 @@ class TestChannelInternals(MailCommon): 'rtcSessions': [('insert', [ { 'id': channel_member.rtc_session_ids.id + 1, - 'channelMember': [("insert-and-replace", { + 'channelMember': { "id": channel_member_test_user.id, - "channel": [("insert-and-replace", {"id": channel_member_test_user.channel_id.id})], - "persona": [("insert-and-replace", { - "partner": [("insert-and-replace", { + "channel": {"id": channel_member_test_user.channel_id.id}, + "persona": { + "partner": { "id": channel_member_test_user.partner_id.id, "name": channel_member_test_user.partner_id.name, "im_status": channel_member_test_user.partner_id.im_status, - })], - })], - })], + }, + }, + }, 'isCameraOn': False, 'isDeaf': False, 'isSelfMuted': False, @@ -401,14 +401,14 @@ class TestChannelInternals(MailCommon): 'id': channel.id, 'invitedMembers': [('insert-and-unlink', [{ 'id': channel_member_test_guest.id, - 'channel': [('insert-and-replace', {'id': channel_member_test_guest.channel_id.id})], - 'persona': [('insert-and-replace', { - 'guest': [('insert-and-replace', { + 'channel': {'id': channel_member_test_guest.channel_id.id}, + 'persona': { + 'guest': { 'id': channel_member_test_guest.guest_id.id, 'name': channel_member_test_guest.guest_id.name, 'im_status': channel_member_test_guest.guest_id.im_status, - })], - })], + }, + }, }])], }, }, @@ -419,17 +419,17 @@ class TestChannelInternals(MailCommon): 'rtcSessions': [('insert', [ { 'id': channel_member.rtc_session_ids.id + 2, - 'channelMember': [("insert-and-replace", { + 'channelMember': { "id": channel_member_test_guest.id, - "channel": [("insert-and-replace", {"id": channel_member_test_guest.channel_id.id})], - "persona": [("insert-and-replace", { - "guest": [("insert-and-replace", { + "channel": {"id": channel_member_test_guest.channel_id.id}, + "persona": { + "guest": { "id": channel_member_test_guest.guest_id.id, "name": channel_member_test_guest.guest_id.name, 'im_status': channel_member_test_guest.guest_id.im_status, - })], - })], - })], + }, + }, + }, 'isCameraOn': False, 'isDeaf': False, 'isSelfMuted': False, @@ -473,14 +473,14 @@ class TestChannelInternals(MailCommon): 'id': channel.id, 'invitedMembers': [('insert-and-unlink', [{ 'id': channel_member_test_user.id, - 'channel': [('insert-and-replace', {'id': channel_member_test_user.channel_id.id})], - 'persona': [('insert-and-replace', { - 'partner': [('insert-and-replace', { + 'channel': {'id': channel_member_test_user.channel_id.id}, + 'persona': { + 'partner': { 'id': channel_member_test_user.partner_id.id, 'name': channel_member_test_user.partner_id.name, 'im_status': channel_member_test_user.partner_id.im_status, - })], - })], + }, + }, }])], }, }, @@ -509,14 +509,14 @@ class TestChannelInternals(MailCommon): 'id': channel.id, 'invitedMembers': [('insert-and-unlink', [{ 'id': channel_member_test_guest.id, - 'channel': [('insert-and-replace', {'id': channel_member_test_guest.channel_id.id})], - 'persona': [('insert-and-replace', { - 'guest': [('insert-and-replace', { + 'channel': {'id': channel_member_test_guest.channel_id.id}, + 'persona': { + 'guest': { 'id': channel_member_test_guest.guest_id.id, 'name': channel_member_test_guest.guest_id.name, 'im_status': channel_member_test_guest.guest_id.im_status, - })], - })], + }, + }, }])], }, }, @@ -573,25 +573,25 @@ class TestChannelInternals(MailCommon): 'invitedMembers': [('insert-and-unlink', [ { 'id': channel_member_test_user.id, - 'channel': [('insert-and-replace', {'id': channel_member_test_user.channel_id.id})], - 'persona': [('insert-and-replace', { - 'partner': [('insert-and-replace', { + 'channel': {'id': channel_member_test_user.channel_id.id}, + 'persona': { + 'partner': { 'id': channel_member_test_user.partner_id.id, 'name': channel_member_test_user.partner_id.name, 'im_status': channel_member_test_user.partner_id.im_status, - })], - })], + }, + }, }, { 'id': channel_member_test_guest.id, - 'channel': [('insert-and-replace', {'id': channel_member_test_guest.channel_id.id})], - 'persona': [('insert-and-replace', { - 'guest': [('insert-and-replace', { + 'channel': {'id': channel_member_test_guest.channel_id.id}, + 'persona': { + 'guest': { 'id': channel_member_test_guest.guest_id.id, 'name': channel_member_test_guest.guest_id.name, 'im_status': channel_member_test_guest.guest_id.im_status, - })], - })], + }, + }, }, ])], }, @@ -617,7 +617,6 @@ class TestChannelInternals(MailCommon): channel_member._rtc_join_call() self.env['bus.bus'].sudo().search([]).unlink() - with self.mock_bus(): channel.add_members(partner_ids=test_user.partner_id.ids, guest_ids=test_guest.ids, invite_to_rtc_call=True) @@ -636,7 +635,7 @@ class TestChannelInternals(MailCommon): (self.cr.dbname, 'res.partner', self.user_employee.partner_id.id), # update of last interest (not asserted below) (self.cr.dbname, 'res.partner', test_user.partner_id.id), # update of last interest (not asserted below) (self.cr.dbname, 'mail.channel', channel.id), # new member (guest) (not asserted below) - (self.cr.dbname, 'mail.guest', test_guest.id), # channel joined for guest (not asserted below) + (self.cr.dbname, 'mail.guest', test_guest.id), # channel joined for guest (not asserted below) ], message_items=[ { @@ -645,17 +644,17 @@ class TestChannelInternals(MailCommon): 'id': channel.id, 'rtcInvitingSession': [('insert', { 'id': channel_member.rtc_session_ids.id, - 'channelMember': [("insert-and-replace", { + 'channelMember': { "id": channel_member.id, - "channel": [("insert-and-replace", {"id": channel_member.channel_id.id})], - "persona": [("insert-and-replace", { - "partner": [("insert-and-replace", { + "channel": {"id": channel_member.channel_id.id}, + "persona": { + "partner": { "id": channel_member.partner_id.id, "name": channel_member.partner_id.name, "im_status": channel_member.partner_id.im_status, - })], - })], - })], + }, + }, + }, 'isCameraOn': False, 'isDeaf': False, 'isSelfMuted': False, @@ -669,17 +668,17 @@ class TestChannelInternals(MailCommon): 'id': channel.id, 'rtcInvitingSession': [('insert', { 'id': channel_member.rtc_session_ids.id, - 'channelMember': [("insert-and-replace", { + 'channelMember': { "id": channel_member.id, - "channel": [("insert-and-replace", {"id": channel_member.channel_id.id})], - "persona": [("insert-and-replace", { - "partner": [("insert-and-replace", { + "channel": {"id": channel_member.channel_id.id}, + "persona": { + "partner": { "id": channel_member.partner_id.id, "name": channel_member.partner_id.name, "im_status": channel_member.partner_id.im_status, - })], - })], - })], + }, + }, + }, 'isCameraOn': False, 'isDeaf': False, 'isSelfMuted': False, @@ -694,25 +693,25 @@ class TestChannelInternals(MailCommon): 'invitedMembers': [('insert', [ { 'id': channel_member_test_user.id, - 'channel': [('insert-and-replace', {'id': channel_member_test_user.channel_id.id})], - 'persona': [('insert-and-replace', { - 'partner': [('insert-and-replace', { + 'channel': {'id': channel_member_test_user.channel_id.id}, + 'persona': { + 'partner': { 'id': channel_member_test_user.partner_id.id, 'name': channel_member_test_user.partner_id.name, 'im_status': channel_member_test_user.partner_id.im_status, - })], - })], + }, + }, }, { 'id': channel_member_test_guest.id, - 'channel': [('insert-and-replace', {'id': channel_member_test_guest.channel_id.id})], - 'persona': [('insert-and-replace', { - 'guest': [('insert-and-replace', { + 'channel': {'id': channel_member_test_guest.channel_id.id}, + 'persona': { + 'guest': { 'id': channel_member_test_guest.guest_id.id, 'name': channel_member_test_guest.guest_id.name, 'im_status': channel_member_test_guest.guest_id.im_status, - })], - })], + }, + }, }, ])], }, diff --git a/addons/rating/models/mail_message.py b/addons/rating/models/mail_message.py index a0a668fc0ef..694d7e151f3 100644 --- a/addons/rating/models/mail_message.py +++ b/addons/rating/models/mail_message.py @@ -35,9 +35,9 @@ class MailMessage(models.Model): for vals in message_values: if vals['id'] in rating_by_message_id: rating = rating_by_message_id[vals['id']] - vals['rating'] = [('insert-and-replace', { + vals['rating'] = { 'id': rating.id, 'ratingImageUrl': rating.rating_image_url, 'ratingText': rating.rating_text, - })] + } return message_values diff --git a/addons/rating/static/tests/helpers/mock_server.js b/addons/rating/static/tests/helpers/mock_server.js index 7f0570cef2d..3c3c7a20209 100644 --- a/addons/rating/static/tests/helpers/mock_server.js +++ b/addons/rating/static/tests/helpers/mock_server.js @@ -16,11 +16,11 @@ patch(MockServer.prototype, 'rating', { ['message_id', '=', formattedMessage.id], ]); if (rating) { - formattedMessage['rating'] = [['insert-and-replace', { + formattedMessage['rating'] = { 'id': rating.id, 'ratingImageUrl': rating.rating_image_url, 'ratingText': rating.rating_text, - }]]; + }; } } return formattedMessages; diff --git a/addons/snailmail/static/src/models/dialog.js b/addons/snailmail/static/src/models/dialog.js index fc0969ba22f..e4dfb67044f 100644 --- a/addons/snailmail/static/src/models/dialog.js +++ b/addons/snailmail/static/src/models/dialog.js @@ -2,7 +2,7 @@ import { addFields, addRecordMethods, patchRecordMethods } from '@mail/model/model_core'; import { one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; // ensure that the model definition is loaded before the patch import '@mail/models/dialog'; @@ -25,7 +25,7 @@ addRecordMethods('Dialog', { */ _computeSnailmailErrorView() { if (this.messageViewOwnerAsSnailmailError) { - return insertAndReplace(); + return {}; } return clear(); }, diff --git a/addons/snailmail/static/src/models/message_view.js b/addons/snailmail/static/src/models/message_view.js index e641858b000..7bbb50215ab 100644 --- a/addons/snailmail/static/src/models/message_view.js +++ b/addons/snailmail/static/src/models/message_view.js @@ -2,7 +2,6 @@ import { addFields, patchRecordMethods } from '@mail/model/model_core'; import { one } from '@mail/model/model_field'; -import { insertAndReplace } from '@mail/model/model_field_command'; // ensure that the model definition is loaded before the patch import '@mail/models/message_view'; @@ -29,10 +28,10 @@ patchRecordMethods('MessageView', { case 'sn_credit': // URL only used in this component, not received at init this.messaging.fetchSnailmailCreditsUrl(); - this.update({ snailmailErrorDialog: insertAndReplace() }); + this.update({ snailmailErrorDialog: {} }); break; case 'sn_error': - this.update({ snailmailErrorDialog: insertAndReplace() }); + this.update({ snailmailErrorDialog: {} }); break; case 'sn_fields': this.message.openMissingFieldsLetterAction(); @@ -41,12 +40,12 @@ patchRecordMethods('MessageView', { this.message.openFormatLetterAction(); break; case 'sn_price': - this.update({ snailmailErrorDialog: insertAndReplace() }); + this.update({ snailmailErrorDialog: {} }); break; case 'sn_trial': // URL only used in this component, not received at init this.messaging.fetchSnailmailCreditsUrlTrial(); - this.update({ snailmailErrorDialog: insertAndReplace() }); + this.update({ snailmailErrorDialog: {} }); break; } } else { diff --git a/addons/test_discuss_full/tests/test_performance.py b/addons/test_discuss_full/tests/test_performance.py index e27873c86ef..bc661a37df7 100644 --- a/addons/test_discuss_full/tests/test_performance.py +++ b/addons/test_discuss_full/tests/test_performance.py @@ -119,10 +119,10 @@ class TestDiscussFullPerformance(TransactionCase): { 'authorizedGroupFullName': self.group_user.full_name, 'avatarCacheKey': self.channel_general._get_avatar_cache_key(), - 'channel': [('insert-and-replace', { + 'channel': { 'channel_type': 'channel', 'id': self.channel_general.id, - })], + }, 'create_uid': self.user_root.id, 'custom_channel_name': False, 'defaultDisplayMode': False, @@ -147,10 +147,10 @@ class TestDiscussFullPerformance(TransactionCase): { 'authorizedGroupFullName': self.group_user.full_name, 'avatarCacheKey': self.channel_channel_public_1._get_avatar_cache_key(), - 'channel': [('insert-and-replace', { + 'channel': { 'channel_type': 'channel', 'id': self.channel_channel_public_1.id, - })], + }, 'create_uid': self.env.user.id, 'custom_channel_name': False, 'defaultDisplayMode': False, @@ -175,10 +175,10 @@ class TestDiscussFullPerformance(TransactionCase): { 'authorizedGroupFullName': self.group_user.full_name, 'avatarCacheKey': self.channel_channel_public_2._get_avatar_cache_key(), - 'channel': [('insert-and-replace', { + 'channel': { 'channel_type': 'channel', 'id': self.channel_channel_public_2.id, - })], + }, 'create_uid': self.env.user.id, 'custom_channel_name': False, 'defaultDisplayMode': False, @@ -203,10 +203,10 @@ class TestDiscussFullPerformance(TransactionCase): { 'authorizedGroupFullName': self.group_user.full_name, 'avatarCacheKey': self.channel_channel_group_1._get_avatar_cache_key(), - 'channel': [('insert-and-replace', { + 'channel': { 'channel_type': 'channel', 'id': self.channel_channel_group_1.id, - })], + }, 'create_uid': self.env.user.id, 'custom_channel_name': False, 'defaultDisplayMode': False, @@ -231,10 +231,10 @@ class TestDiscussFullPerformance(TransactionCase): { 'authorizedGroupFullName': self.group_user.full_name, 'avatarCacheKey': self.channel_channel_group_2._get_avatar_cache_key(), - 'channel': [('insert-and-replace', { + 'channel': { 'channel_type': 'channel', 'id': self.channel_channel_group_2.id, - })], + }, 'create_uid': self.env.user.id, 'custom_channel_name': False, 'defaultDisplayMode': False, @@ -259,10 +259,10 @@ class TestDiscussFullPerformance(TransactionCase): { 'authorizedGroupFullName': self.group_user.full_name, 'avatarCacheKey': self.channel_channel_private_1._get_avatar_cache_key(), - 'channel': [('insert-and-replace', { + 'channel': { 'channel_type': 'channel', 'id': self.channel_channel_private_1.id, - })], + }, 'create_uid': self.env.user.id, 'custom_channel_name': False, 'defaultDisplayMode': False, @@ -287,10 +287,10 @@ class TestDiscussFullPerformance(TransactionCase): { 'authorizedGroupFullName': self.group_user.full_name, 'avatarCacheKey': self.channel_channel_private_2._get_avatar_cache_key(), - 'channel': [('insert-and-replace', { + 'channel': { 'channel_type': 'channel', 'id': self.channel_channel_private_2.id, - })], + }, 'create_uid': self.env.user.id, 'custom_channel_name': False, 'defaultDisplayMode': False, @@ -315,10 +315,10 @@ class TestDiscussFullPerformance(TransactionCase): { 'authorizedGroupFullName': False, 'avatarCacheKey': self.channel_group_1._get_avatar_cache_key(), - 'channel': [('insert-and-replace', { + 'channel': { 'channel_type': 'group', 'id': self.channel_group_1.id, - })], + }, 'create_uid': self.env.user.id, 'custom_channel_name': False, 'defaultDisplayMode': False, @@ -382,10 +382,10 @@ class TestDiscussFullPerformance(TransactionCase): { 'authorizedGroupFullName': False, 'avatarCacheKey': self.channel_chat_1._get_avatar_cache_key(), - 'channel': [('insert-and-replace', { + 'channel': { 'channel_type': 'chat', 'id': self.channel_chat_1.id, - })], + }, 'create_uid': self.env.user.id, 'custom_channel_name': False, 'defaultDisplayMode': False, @@ -449,10 +449,10 @@ class TestDiscussFullPerformance(TransactionCase): { 'authorizedGroupFullName': False, 'avatarCacheKey': self.channel_chat_2._get_avatar_cache_key(), - 'channel': [('insert-and-replace', { + 'channel': { 'channel_type': 'chat', 'id': self.channel_chat_2.id, - })], + }, 'create_uid': self.env.user.id, 'custom_channel_name': False, 'defaultDisplayMode': False, @@ -516,10 +516,10 @@ class TestDiscussFullPerformance(TransactionCase): { 'authorizedGroupFullName': False, 'avatarCacheKey': self.channel_chat_3._get_avatar_cache_key(), - 'channel': [('insert-and-replace', { + 'channel': { 'channel_type': 'chat', 'id': self.channel_chat_3.id, - })], + }, 'create_uid': self.env.user.id, 'custom_channel_name': False, 'defaultDisplayMode': False, @@ -583,10 +583,10 @@ class TestDiscussFullPerformance(TransactionCase): { 'authorizedGroupFullName': False, 'avatarCacheKey': self.channel_chat_4._get_avatar_cache_key(), - 'channel': [('insert-and-replace', { + 'channel': { 'channel_type': 'chat', 'id': self.channel_chat_4.id, - })], + }, 'create_uid': self.env.user.id, 'custom_channel_name': False, 'defaultDisplayMode': False, @@ -650,10 +650,10 @@ class TestDiscussFullPerformance(TransactionCase): { 'authorizedGroupFullName': False, 'avatarCacheKey': self.channel_livechat_1._get_avatar_cache_key(), - 'channel': [('insert-and-replace', { + 'channel': { 'channel_type': 'livechat', 'id': self.channel_livechat_1.id, - })], + }, 'create_uid': self.env.user.id, 'custom_channel_name': False, 'defaultDisplayMode': False, @@ -717,10 +717,10 @@ class TestDiscussFullPerformance(TransactionCase): { 'authorizedGroupFullName': False, 'avatarCacheKey': self.channel_livechat_2._get_avatar_cache_key(), - 'channel': [('insert-and-replace', { + 'channel': { 'channel_type': 'livechat', 'id': self.channel_livechat_2.id, - })], + }, 'create_uid': self.env.ref('base.public_user').id, 'custom_channel_name': False, 'defaultDisplayMode': False, @@ -830,7 +830,7 @@ class TestDiscussFullPerformance(TransactionCase): 'is_discuss_sidebar_category_livechat_open': True, 'push_to_talk_key': False, 'use_push_to_talk': False, - 'user_id': [('insert-and-replace', {'id': self.users[0].id})], + 'user_id': {'id': self.users[0].id}, 'voice_active_duration': 0, 'volume_settings_ids': [('insert', [])], }, diff --git a/addons/test_mail/tests/test_message_track.py b/addons/test_mail/tests/test_message_track.py index b64dbb61822..b593381af4d 100644 --- a/addons/test_mail/tests/test_message_track.py +++ b/addons/test_mail/tests/test_message_track.py @@ -378,21 +378,21 @@ class TestTrackingInternals(TestMailCommon): msg_emp = self.record.message_ids.message_format() msg_sudo = self.record.sudo().message_ids.message_format() tracking_values = self.env['mail.tracking.value'].search([('mail_message_id', '=', self.record.message_ids.id)]) - formattedTrackingValues = [('insert-and-replace', [{ + formattedTrackingValues = [{ 'changedField': 'Email From', 'id': tracking_values[0]['id'], - 'newValue': [('insert-and-replace', { + 'newValue': { 'currencyId': False, 'fieldType': 'char', 'value': 'X', - })], - 'oldValue': [('insert-and-replace', { + }, + 'oldValue': { 'currencyId': False, 'fieldType': 'char', 'value': False, - })], - }])] - self.assertEqual(msg_emp[0].get('trackingValues'), [('insert-and-replace', [])], "should not have protected tracking values") + }, + }] + self.assertEqual(msg_emp[0].get('trackingValues'), [], "should not have protected tracking values") self.assertEqual(msg_sudo[0].get('trackingValues'), formattedTrackingValues, "should have protected tracking values") msg_emp = self.record._notify_by_email_prepare_rendering_context(self.record.message_ids, {}) diff --git a/addons/test_mail/tests/test_performance.py b/addons/test_mail/tests/test_performance.py index 7ea074977af..8be8bc41d19 100644 --- a/addons/test_mail/tests/test_performance.py +++ b/addons/test_mail/tests/test_performance.py @@ -1089,7 +1089,7 @@ class TestMailComplexPerformance(BaseMailPerformance): res = messages.message_format() self.assertEqual(len(res), 2) for message in res: - self.assertEqual(len(message['attachment_ids'][0][1]), 2) + self.assertEqual(len(message['attachment_ids']), 2) self.env.flush_all() self.env.invalidate_all() @@ -1098,7 +1098,7 @@ class TestMailComplexPerformance(BaseMailPerformance): res = messages.message_format() self.assertEqual(len(res), 2) for message in res: - self.assertEqual(len(message['attachment_ids'][0][1]), 2) + self.assertEqual(len(message['attachment_ids']), 2) @mute_logger('odoo.tests', 'odoo.addons.mail.models.mail_mail', 'odoo.models.unlink') @users('employee') diff --git a/addons/website_livechat/static/src/legacy/website_livechat_chatbot_test_script.js b/addons/website_livechat/static/src/legacy/website_livechat_chatbot_test_script.js index cc4a5677a0e..296f13351d2 100644 --- a/addons/website_livechat/static/src/legacy/website_livechat_chatbot_test_script.js +++ b/addons/website_livechat/static/src/legacy/website_livechat_chatbot_test_script.js @@ -5,8 +5,6 @@ import utils from 'web.utils'; import LivechatButton from '@im_livechat/legacy/widgets/livechat_button'; -import { insertAndReplace } from '@mail/model/model_field_command'; - /** * Override of the LivechatButton to create a testing environment for the chatbot script. * @@ -30,9 +28,9 @@ const LivechatButtonTestChatbot = LivechatButton.extend({ this.messaging.publicLivechatGlobal.update({ isTestChatbot: true }); this.messaging.publicLivechatGlobal.livechatButtonView.update({ testChatbotData: chatbotData.chatbot }); this.messaging.publicLivechatGlobal.chatbot.update({ - currentStep: insertAndReplace({ + currentStep: { data: this.messaging.publicLivechatGlobal.chatbot.lastWelcomeStep, - }), + }, }); }, }); @@ -54,7 +52,7 @@ publicWidget.registry.livechatChatbotTestScript = publicWidget.Widget.extend({ const messaging = await this.env.services.messaging.get(); return this._super(...arguments).then(() => { messaging.update({ - publicLivechatGlobal: insertAndReplace({ isAvailable: true, chatbotServerUrl: this.$el.data().serverUrl }), + publicLivechatGlobal: { isAvailable: true, chatbotServerUrl: this.$el.data().serverUrl }, }); this.livechatButton = new LivechatButtonTestChatbot(this, messaging, this.$el.data()); this.livechatButton.appendTo(document.body); diff --git a/addons/website_livechat/static/src/models/livechat_button_view.js b/addons/website_livechat/static/src/models/livechat_button_view.js index b252b4d8a8d..c7e15543547 100644 --- a/addons/website_livechat/static/src/models/livechat_button_view.js +++ b/addons/website_livechat/static/src/models/livechat_button_view.js @@ -1,7 +1,7 @@ /** @odoo-module **/ import { patchRecordMethods } from '@mail/model/model_core'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear } from '@mail/model/model_field_command'; // ensure that the model definition is loaded before the patch import '@im_livechat/models/livechat_button_view'; @@ -45,7 +45,7 @@ patchRecordMethods('LivechatButtonView', { return this._super(); } this.messaging.publicLivechatGlobal.update({ - publicLivechat: insertAndReplace({ data: this.testChatbotData.channel }), + publicLivechat: { data: this.testChatbotData.channel }, }); await this.openChatWindow(); this.widget._sendWelcomeMessage();