From 60c87dd4266aad2eff8813998cd8a678fb3f5409 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Theys?= Date: Tue, 16 Aug 2022 13:40:39 +0000 Subject: [PATCH] [IMP] mail, *: introduce identifyingMode and remove identifyingFields * = calendar, hr, im_livechat, rating, snailmail, website_livechat This simplifies definition and overrides and opens up new identification opportunities. Part of task-2741982 closes odoo/odoo#98166 Related: odoo/enterprise#30470 Signed-off-by: Louis Wicket (wil) --- .../static/src/models/calendar_event.js | 2 +- addons/hr/static/src/models/employee.js | 2 +- .../im_livechat/static/src/models/chatbot.js | 2 +- .../static/src/models/chatbot_step.js | 2 +- .../src/models/discuss_sidebar_category.js | 7 +- .../static/src/models/livechat_button_view.js | 2 +- .../static/src/models/livechat_operator.js | 2 +- .../static/src/models/public_livechat.js | 2 +- .../models/public_livechat_feedback_view.js | 2 +- .../src/models/public_livechat_global.js | 1 - ...ic_livechat_global_notification_handler.js | 2 +- .../src/models/public_livechat_message.js | 2 +- .../static/src/models/public_livechat_view.js | 2 +- .../src/models/public_livechat_window.js | 2 +- addons/mail/static/src/model/model_core.js | 27 +-- addons/mail/static/src/model/model_field.js | 5 + addons/mail/static/src/model/model_manager.js | 156 +++++++++++------- addons/mail/static/src/models/activity.js | 2 +- .../static/src/models/activity_box_view.js | 2 +- .../mail/static/src/models/activity_group.js | 2 +- .../static/src/models/activity_group_view.js | 3 +- ...activity_mark_done_popover_content_view.js | 2 +- .../static/src/models/activity_menu_view.js | 1 - .../mail/static/src/models/activity_type.js | 2 +- .../mail/static/src/models/activity_view.js | 3 +- addons/mail/static/src/models/attachment.js | 2 +- .../static/src/models/attachment_box_view.js | 2 +- .../mail/static/src/models/attachment_card.js | 3 +- .../models/attachment_delete_confirm_view.js | 2 +- .../static/src/models/attachment_image.js | 3 +- .../mail/static/src/models/attachment_list.js | 5 +- .../static/src/models/attachment_viewer.js | 2 +- .../src/models/attachment_viewer_viewable.js | 3 +- .../src/models/autocomplete_input_view.js | 11 +- .../src/models/call_action_list_view.js | 2 +- .../mail/static/src/models/call_demo_view.js | 2 +- .../src/models/call_invite_request_popup.js | 2 +- .../mail/static/src/models/call_main_view.js | 2 +- .../static/src/models/call_main_view_tile.js | 3 +- .../static/src/models/call_option_menu.js | 2 +- .../src/models/call_participant_card.js | 4 +- .../src/models/call_participant_video_view.js | 2 +- .../static/src/models/call_settings_menu.js | 2 +- .../static/src/models/call_sidebar_view.js | 2 +- .../src/models/call_sidebar_view_tile.js | 3 +- .../static/src/models/call_systray_menu.js | 2 +- addons/mail/static/src/models/call_view.js | 2 +- .../mail/static/src/models/canned_response.js | 2 +- addons/mail/static/src/models/channel.js | 2 +- .../mail/static/src/models/channel_command.js | 2 +- .../src/models/channel_invitation_form.js | 4 +- ...invitation_form_selectable_partner_view.js | 3 +- ...l_invitation_form_selected_partner_view.js | 3 +- .../mail/static/src/models/channel_member.js | 2 +- .../channel_member_list_category_view.js | 4 +- .../src/models/channel_member_list_view.js | 4 +- .../static/src/models/channel_member_view.js | 5 +- addons/mail/static/src/models/chat_window.js | 4 +- .../src/models/chat_window_header_view.js | 2 +- .../static/src/models/chat_window_manager.js | 1 - addons/mail/static/src/models/chatter.js | 2 +- .../mail/static/src/models/chatter_topbar.js | 2 +- addons/mail/static/src/models/clock.js | 2 +- .../mail/static/src/models/clock_watcher.js | 4 +- addons/mail/static/src/models/composer.js | 4 +- .../static/src/models/composer_suggestable.js | 6 +- .../composer_suggested_recipient_list_view.js | 2 +- .../composer_suggested_recipient_view.js | 3 +- .../models/composer_suggestion_list_view.js | 2 +- ...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 | 5 +- addons/mail/static/src/models/country.js | 2 +- .../src/models/delete_message_confirm_view.js | 2 +- addons/mail/static/src/models/device.js | 1 - addons/mail/static/src/models/dialog.js | 13 +- .../mail/static/src/models/dialog_manager.js | 1 - addons/mail/static/src/models/discuss.js | 1 - .../static/src/models/discuss_public_view.js | 1 - .../src/models/discuss_sidebar_category.js | 4 +- .../models/discuss_sidebar_category_item.js | 3 +- .../models/discuss_sidebar_mailbox_view.js | 5 +- addons/mail/static/src/models/discuss_view.js | 2 +- .../mail/static/src/models/drop_zone_view.js | 4 +- addons/mail/static/src/models/emoji.js | 2 +- .../mail/static/src/models/emoji_category.js | 2 +- .../src/models/emoji_category_bar_view.js | 2 +- .../static/src/models/emoji_category_view.js | 5 +- .../mail/static/src/models/emoji_grid_view.js | 2 +- .../static/src/models/emoji_picker_view.js | 2 +- .../mail/static/src/models/emoji_registry.js | 1 - addons/mail/static/src/models/emoji_view.js | 3 +- .../mail/static/src/models/file_uploader.js | 6 +- .../static/src/models/follow_button_view.js | 2 +- addons/mail/static/src/models/follower.js | 2 +- .../src/models/follower_list_menu_view.js | 2 +- .../static/src/models/follower_subtype.js | 2 +- .../src/models/follower_subtype_list.js | 2 +- .../src/models/follower_subtype_view.js | 3 +- .../mail/static/src/models/follower_view.js | 3 +- addons/mail/static/src/models/guest.js | 2 +- addons/mail/static/src/models/ir_model.js | 2 +- addons/mail/static/src/models/locale.js | 1 - .../mail/static/src/models/mail_template.js | 2 +- .../static/src/models/mail_template_view.js | 3 +- addons/mail/static/src/models/mailbox.js | 5 +- addons/mail/static/src/models/message.js | 2 +- .../static/src/models/message_action_list.js | 2 +- .../src/models/message_author_prefix_view.js | 4 +- .../src/models/message_in_reply_to_view.js | 2 +- .../static/src/models/message_list_view.js | 2 +- .../message_list_view_message_view_item.js | 3 +- .../src/models/message_reaction_group.js | 3 +- .../src/models/message_seen_indicator.js | 3 +- .../src/models/message_seen_indicator_view.js | 2 +- addons/mail/static/src/models/message_view.js | 4 +- addons/mail/static/src/models/messaging.js | 1 - .../src/models/messaging_initializer.js | 1 - .../mail/static/src/models/messaging_menu.js | 1 - .../models/messaging_notification_handler.js | 1 - .../models/mobile_messaging_navbar_view.js | 4 +- addons/mail/static/src/models/notification.js | 2 +- .../static/src/models/notification_group.js | 4 +- .../src/models/notification_group_view.js | 3 +- .../src/models/notification_list_view.js | 4 +- .../src/models/notification_request_view.js | 2 +- ...ther_member_long_typing_in_thread_timer.js | 6 +- addons/mail/static/src/models/partner.js | 2 +- addons/mail/static/src/models/persona.js | 4 +- .../src/models/persona_im_status_icon_view.js | 17 +- .../mail/static/src/models/popover_manager.js | 1 - addons/mail/static/src/models/popover_view.js | 6 +- addons/mail/static/src/models/record.js | 8 - .../static/src/models/res_users_settings.js | 2 +- .../src/models/res_users_settings_volumes.js | 2 +- addons/mail/static/src/models/rtc.js | 1 - .../static/src/models/rtc_data_channel.js | 2 +- .../static/src/models/rtc_peer_connection.js | 2 +- .../src/models/rtc_peer_notification.js | 2 +- addons/mail/static/src/models/rtc_session.js | 2 +- addons/mail/static/src/models/sound_effect.js | 3 +- .../mail/static/src/models/sound_effects.js | 1 - .../src/models/suggested_recipient_info.js | 2 +- addons/mail/static/src/models/thread.js | 3 +- addons/mail/static/src/models/thread_cache.js | 2 +- .../models/thread_needaction_preview_view.js | 3 +- .../src/models/thread_partner_seen_info.js | 3 +- .../static/src/models/thread_preview_view.js | 5 +- addons/mail/static/src/models/thread_view.js | 2 +- .../static/src/models/thread_view_topbar.js | 2 +- .../mail/static/src/models/thread_viewer.js | 6 +- addons/mail/static/src/models/throttle.js | 5 +- addons/mail/static/src/models/timer.js | 21 ++- .../mail/static/src/models/tracking_value.js | 5 +- .../static/src/models/tracking_value_item.js | 7 +- .../src/models/use_drag_visible_drop_zone.js | 4 +- addons/mail/static/src/models/user.js | 2 +- .../src/models/user_notification_manager.js | 1 - addons/mail/static/src/models/user_setting.js | 1 - .../models/web_client_view_attachment_view.js | 2 +- addons/mail/static/src/models/welcome_view.js | 2 +- .../tests/models/clock_watcher_qunit_tests.js | 7 +- addons/mail/static/tests/models/qunit_test.js | 1 - .../mail/static/tests/models/test_models.js | 8 +- .../tests/models/throttle_qunit_tests.js | 9 +- .../static/tests/models/timer_qunit_tests.js | 9 +- addons/rating/static/src/models/rating.js | 2 +- addons/snailmail/static/src/models/dialog.js | 7 +- .../static/src/models/snailmail_error_view.js | 2 +- .../static/src/models/visitor.js | 2 +- 171 files changed, 390 insertions(+), 321 deletions(-) diff --git a/addons/calendar/static/src/models/calendar_event.js b/addons/calendar/static/src/models/calendar_event.js index 1277a23f388..1d5c00ee96b 100644 --- a/addons/calendar/static/src/models/calendar_event.js +++ b/addons/calendar/static/src/models/calendar_event.js @@ -9,7 +9,6 @@ import { getLangTimeFormat } from 'web.time'; registerModel({ name: 'calendar.event', - identifyingFields: ['id'], recordMethods: { _computeFormattedStart() { if (!this.start) { @@ -25,6 +24,7 @@ registerModel({ compute: '_computeFormattedStart', }), id: attr({ + identifying: true, readonly: true, required: true, }), diff --git a/addons/hr/static/src/models/employee.js b/addons/hr/static/src/models/employee.js index 8d394e2e07b..f195791ccdd 100644 --- a/addons/hr/static/src/models/employee.js +++ b/addons/hr/static/src/models/employee.js @@ -6,7 +6,6 @@ import { clear, insert } from '@mail/model/model_field_command'; registerModel({ name: 'Employee', - identifyingFields: ['id'], modelMethods: { /** * @param {Object} data @@ -164,6 +163,7 @@ registerModel({ * Unique identifier for this employee. */ id: attr({ + identifying: true, readonly: true, required: true, }), diff --git a/addons/im_livechat/static/src/models/chatbot.js b/addons/im_livechat/static/src/models/chatbot.js index 637f20f9717..6a7fa8a88b1 100644 --- a/addons/im_livechat/static/src/models/chatbot.js +++ b/addons/im_livechat/static/src/models/chatbot.js @@ -6,7 +6,6 @@ import { clear } from '@mail/model/model_field_command'; registerModel({ name: 'Chatbot', - identifyingFields: ['publicLivechatGlobalOwner'], recordMethods: { /** * @private @@ -157,6 +156,7 @@ registerModel({ default: 3500, // in milliseconds }), publicLivechatGlobalOwner: one('PublicLivechatGlobal', { + identifying: true, inverse: 'chatbot', readonly: true, required: true, diff --git a/addons/im_livechat/static/src/models/chatbot_step.js b/addons/im_livechat/static/src/models/chatbot_step.js index 722f45a437a..41065d2fda1 100644 --- a/addons/im_livechat/static/src/models/chatbot_step.js +++ b/addons/im_livechat/static/src/models/chatbot_step.js @@ -5,9 +5,9 @@ import { attr, one } from '@mail/model/model_field'; registerModel({ name: 'ChatbotStep', - identifyingFields: ['chabotOwner'], fields: { chabotOwner: one('Chatbot', { + identifying: true, inverse: 'currentStep', readonly: true, required: true, diff --git a/addons/im_livechat/static/src/models/discuss_sidebar_category.js b/addons/im_livechat/static/src/models/discuss_sidebar_category.js index b68c4760faf..9155cef9568 100644 --- a/addons/im_livechat/static/src/models/discuss_sidebar_category.js +++ b/addons/im_livechat/static/src/models/discuss_sidebar_category.js @@ -1,6 +1,6 @@ /** @odoo-module **/ -import { addFields, patchIdentifyingFields, patchRecordMethods } from '@mail/model/model_core'; +import { addFields, patchRecordMethods } from '@mail/model/model_core'; import { one } from '@mail/model/model_field'; import { clear } from '@mail/model/model_field_command'; // ensure that the model definition is loaded before the patch @@ -8,15 +8,12 @@ import '@mail/models/discuss_sidebar_category'; addFields('DiscussSidebarCategory', { discussAsLivechat: one('Discuss', { + identifying: true, inverse: 'categoryLivechat', readonly: true, }), }); -patchIdentifyingFields('DiscussSidebarCategory', identifyingFields => { - identifyingFields[0].push('discussAsLivechat'); -}); - patchRecordMethods('DiscussSidebarCategory', { /** * @override 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 efadb3e9f85..943cd5c8a3d 100644 --- a/addons/im_livechat/static/src/models/livechat_button_view.js +++ b/addons/im_livechat/static/src/models/livechat_button_view.js @@ -11,7 +11,6 @@ import { get_cookie, set_cookie, unaccent } from 'web.utils'; registerModel({ name: 'LivechatButtonView', - identifyingFields: ['publicLivechatGlobalOwner'], lifecycleHooks: { _created() { this.update({ widget: this.env.services.public_livechat_service.mountLivechatButton() }); @@ -609,6 +608,7 @@ registerModel({ compute: '_computeOpenChatDebounced', }), publicLivechatGlobalOwner: one('PublicLivechatGlobal', { + identifying: true, inverse: 'livechatButtonView', readonly: true, required: true, diff --git a/addons/im_livechat/static/src/models/livechat_operator.js b/addons/im_livechat/static/src/models/livechat_operator.js index 4bfdf0c11bd..12e16171c04 100644 --- a/addons/im_livechat/static/src/models/livechat_operator.js +++ b/addons/im_livechat/static/src/models/livechat_operator.js @@ -5,9 +5,9 @@ import { attr } from '@mail/model/model_field'; registerModel({ name: 'LivechatOperator', - identifyingFields: ['id'], fields: { id: attr({ + identifying: true, readonly: true, required: true, }), diff --git a/addons/im_livechat/static/src/models/public_livechat.js b/addons/im_livechat/static/src/models/public_livechat.js index 70efa97a0d7..77bf6563395 100644 --- a/addons/im_livechat/static/src/models/public_livechat.js +++ b/addons/im_livechat/static/src/models/public_livechat.js @@ -8,7 +8,6 @@ import { clear, insertAndReplace } from '@mail/model/model_field_command'; registerModel({ name: 'PublicLivechat', - identifyingFields: ['publicLivechatGlobalOwner'], lifecycleHooks: { _created() { this.update({ @@ -93,6 +92,7 @@ registerModel({ }), legacyPublicLivechat: attr(), publicLivechatGlobalOwner: one('PublicLivechatGlobal', { + identifying: true, inverse: 'publicLivechat', readonly: true, required: true, diff --git a/addons/im_livechat/static/src/models/public_livechat_feedback_view.js b/addons/im_livechat/static/src/models/public_livechat_feedback_view.js index 229d842ddbe..92ba28247f3 100644 --- a/addons/im_livechat/static/src/models/public_livechat_feedback_view.js +++ b/addons/im_livechat/static/src/models/public_livechat_feedback_view.js @@ -7,7 +7,6 @@ import { attr, one } from '@mail/model/model_field'; registerModel({ name: 'PublicLivechatFeedbackView', - identifyingFields: ['publicLivechatGlobalOwner'], lifecycleHooks: { _created() { this.update({ @@ -35,6 +34,7 @@ registerModel({ }, fields: { publicLivechatGlobalOwner: one('PublicLivechatGlobal', { + identifying: true, inverse: 'feedbackView', readonly: true, required: true, 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 b35ed49d4e5..bdc7b5c6cb9 100644 --- a/addons/im_livechat/static/src/models/public_livechat_global.js +++ b/addons/im_livechat/static/src/models/public_livechat_global.js @@ -10,7 +10,6 @@ import { get_cookie, Markup, set_cookie } from 'web.utils'; registerModel({ name: 'PublicLivechatGlobal', - identifyingFields: ['messaging'], lifecycleHooks: { _created() { // History tracking diff --git a/addons/im_livechat/static/src/models/public_livechat_global_notification_handler.js b/addons/im_livechat/static/src/models/public_livechat_global_notification_handler.js index fae844edf49..0e00c7947e4 100644 --- a/addons/im_livechat/static/src/models/public_livechat_global_notification_handler.js +++ b/addons/im_livechat/static/src/models/public_livechat_global_notification_handler.js @@ -9,7 +9,6 @@ import utils from 'web.utils'; registerModel({ name: 'PublicLivechatGlobalNotificationHandler', - identifyingFields: ['publicLivechatGlobalOwner'], lifecycleHooks: { _created() { this.env.services['bus_service'].addChannel(this.messaging.publicLivechatGlobal.publicLivechat.uuid); @@ -96,6 +95,7 @@ registerModel({ }, fields: { publicLivechatGlobalOwner: one('PublicLivechatGlobal', { + identifying: true, inverse: 'notificationHandler', readonly: true, required: true, diff --git a/addons/im_livechat/static/src/models/public_livechat_message.js b/addons/im_livechat/static/src/models/public_livechat_message.js index 76f60f51c2c..f468b39240c 100644 --- a/addons/im_livechat/static/src/models/public_livechat_message.js +++ b/addons/im_livechat/static/src/models/public_livechat_message.js @@ -6,7 +6,6 @@ import { clear } from '@mail/model/model_field_command'; registerModel({ name: 'PublicLivechatMessage', - identifyingFields: ['id'], recordMethods: { /** * @private @@ -25,6 +24,7 @@ registerModel({ }), data: attr(), id: attr({ + identifying: true, readonly: true, required: true, }), diff --git a/addons/im_livechat/static/src/models/public_livechat_view.js b/addons/im_livechat/static/src/models/public_livechat_view.js index f191a0e4a1a..f17fe1ef5a9 100644 --- a/addons/im_livechat/static/src/models/public_livechat_view.js +++ b/addons/im_livechat/static/src/models/public_livechat_view.js @@ -7,7 +7,6 @@ import { attr, one } from '@mail/model/model_field'; registerModel({ name: 'PublicLivechatView', - identifyingFields: ['publicLivechatWindowOwner'], lifecycleHooks: { _created() { this.update({ @@ -20,6 +19,7 @@ registerModel({ }, fields: { publicLivechatWindowOwner: one('PublicLivechatWindow', { + identifying: true, inverse: 'publicLivechatView', readonly: true, required: true, 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 505e19ffb90..88ad7aac608 100644 --- a/addons/im_livechat/static/src/models/public_livechat_window.js +++ b/addons/im_livechat/static/src/models/public_livechat_window.js @@ -8,7 +8,6 @@ import { insertAndReplace } from '@mail/model/model_field_command'; registerModel({ name: 'PublicLivechatWindow', - identifyingFields: ['livechatButtonViewOwner'], lifecycleHooks: { _created() { this.update({ @@ -43,6 +42,7 @@ registerModel({ default: null, }), livechatButtonViewOwner: one('LivechatButtonView', { + identifying: true, inverse: 'chatWindow', readonly: true, required: true, diff --git a/addons/mail/static/src/model/model_core.js b/addons/mail/static/src/model/model_core.js index 592562a7537..5e80c0d3351 100644 --- a/addons/mail/static/src/model/model_core.js +++ b/addons/mail/static/src/model/model_core.js @@ -250,23 +250,6 @@ function assertNameIsAvailableOnRecords(name, modelDefinition) { } } -/** - * Applies the provided function to the identifying fields of the model - * specified by the `modelName`. - * - * @param {string} modelName The name of the model to which to apply the patch. - * @param {function} patch The function to be applied on the identifying fields. - */ -export function patchIdentifyingFields(modelName, patch) { - addContextToErrors(() => { - if (!registry.has(modelName)) { - throw new Error(`model must be registered before being patched.`); - } - assertIsFunction(patch); - }, `Cannot patch identifyingFields on model "${modelName}": `); - patch(registry.get(modelName).get('identifyingFields')); -} - /** * Overrides the lifecycle hooks of the model specified by the `modelName`. * @@ -343,7 +326,7 @@ export function patchRecordMethods(modelName, recordMethods) { /** * @param {Object} definition The JSON definition of the model to register. * @param {Object} [definition.fields] - * @param {string[]} definition.identifyingFields + * @param {string} [definition.identifyingMode='and'] * @param {Object} [definition.lifecycleHooks] * @param {Object} [definition.modelGetters] Deprecated; use fields instead. * @param {Object} [definition.modelMethods] @@ -352,19 +335,19 @@ export function patchRecordMethods(modelName, recordMethods) { * @param {Object} [definition.recordGetters] Deprecated; use fields instead. * @param {Object} [definition.recordMethods] */ -export function registerModel({ fields, identifyingFields, lifecycleHooks, modelGetters, modelMethods, name, onChanges, recordGetters, recordMethods }) { +export function registerModel({ fields, identifyingMode = 'and', lifecycleHooks, modelGetters, modelMethods, name, onChanges, recordGetters, recordMethods }) { if (!name) { throw new Error("Model is lacking a name."); } - if (!identifyingFields) { - throw new Error(`Cannot register model "${name}": definition is lacking identifying fields.`); + if (!identifyingMode) { + throw new Error(`Cannot register model "${name}": definition is lacking identifying mode.`); } if (registry.has(name)) { throw new Error(`Cannot register model "${name}": model has already been registered.`); } registry.set(name, new Map([ ['name', name], - ['identifyingFields', identifyingFields], + ['identifyingMode', identifyingMode], ['lifecycleHooks', new Map()], ['modelMethods', new Map()], ['modelGetters', new Map()], diff --git a/addons/mail/static/src/model/model_field.js b/addons/mail/static/src/model/model_field.js index 5057fd5fe44..c7921928cf8 100644 --- a/addons/mail/static/src/model/model_field.js +++ b/addons/mail/static/src/model/model_field.js @@ -18,6 +18,7 @@ export class ModelField { default: def, fieldName, fieldType, + identifying = false, inverse, isCausal = false, readonly = false, @@ -52,6 +53,10 @@ export class ModelField { * 2. 'relation': fields that relate to some other records. */ this.fieldType = fieldType; + /** + * Determines whether this field is an identifying field for its model. + */ + this.identifying = identifying; /** * This prop only makes sense in a relational field. This contains * the name of the field name in the inverse relation. This may not diff --git a/addons/mail/static/src/model/model_manager.js b/addons/mail/static/src/model/model_manager.js index 058d640850b..f00143ab452 100644 --- a/addons/mail/static/src/model/model_manager.js +++ b/addons/mail/static/src/model/model_manager.js @@ -197,8 +197,7 @@ export class ModelManager { for (const model of Object.values(this.models)) { delete model.__fieldList; delete model.__fieldMap; - delete model.__identifyingFields; - delete model.__identifyingFieldsFlattened; + delete model.__identifyingFieldNames; delete model.__records; delete model.__requiredFieldsList; delete model.fields; @@ -418,7 +417,7 @@ export class ModelManager { } /** - * Adds fields, methods, getters, and identifyingFields from the model + * Adds fields, methods, getters, and identifyingMode from the model * definition to the model, then registers it in `this.models`. * * @private @@ -439,17 +438,7 @@ export class ModelManager { model.fields = {}; // Contains all records. key is local id, while value is the record. model.__records = {}; - model.__identifyingFields = definition.get('identifyingFields'); - const identifyingFieldsFlattened = new Set(); - for (const identifyingElement of model.__identifyingFields) { - const identifyingFields = typeof identifyingElement === 'string' - ? [identifyingElement] - : identifyingElement; - for (const identifyingField of identifyingFields) { - identifyingFieldsFlattened.add(identifyingField); - } - } - model.__identifyingFieldsFlattened = identifyingFieldsFlattened; + model.identifyingMode = definition.get('identifyingMode'); this._listenersObservingAllByModel.set(model, new Map()); this.models[model.name] = model; } @@ -476,6 +465,7 @@ export class ModelManager { 'compute', 'default', 'fieldType', + 'identifying', 'readonly', 'related', 'required', @@ -492,6 +482,7 @@ export class ModelManager { 'compute', 'default', 'fieldType', + 'identifying', 'inverse', 'isCausal', 'readonly', @@ -579,6 +570,17 @@ export class ModelManager { */ _checkProcessedFieldsOnModels() { for (const model of Object.values(this.models)) { + switch (model.identifyingMode) { + case 'and': + break; + case 'xor': + if (model.__identifyingFieldNames.size === 0) { + throw new Error(`No identifying fields has been specified for 'xor' identifying mode on ${model}`); + } + break; + default: + throw new Error(`Unsupported identifying mode "${model.identifyingMode}" on ${model}. Must be one of 'and' or 'xor'.`); + } for (const field of model.__fieldList) { const fieldName = field.fieldName; if (!(['attribute', 'relation'].includes(field.fieldType))) { @@ -617,7 +619,7 @@ export class ModelManager { throw new Error(`${field} on ${model} has its inverse ${inverseField} on ${relatedModel} referring to an invalid model (model(${inverseField.to})).`); } } - for (const identifyingField of model.__identifyingFieldsFlattened) { + for (const identifyingField of model.__identifyingFieldNames) { const field = model.__fieldMap[identifyingField]; if (!field) { throw new Error(`Identifying field "${identifyingField}" is not a field on ${model}.`); @@ -966,51 +968,81 @@ export class ModelManager { * @returns {string} */ _getRecordIndex(model, data) { - return `${model.name}(${model.__identifyingFields.map(identifyingElement => { - const fieldName = typeof identifyingElement === 'string' - ? identifyingElement - : identifyingElement.reduce((fieldName, currentFieldName) => { - const fieldValue = data[currentFieldName] !== undefined - ? data[currentFieldName] - : model.__fieldMap[currentFieldName].default; + const parts = []; + switch (model.identifyingMode) { + case 'and': + for (const fieldName of model.__identifyingFieldNames) { + const fieldValue = this._getValueFromDataOrFromDefault(model, fieldName, data); if (fieldValue === undefined) { - return fieldName; + throw new Error(`Identifying field "${fieldName}" is lacking a value on ${model} with 'and' identifying mode`); + } + parts.push(this._getRecordIndexFromField(model, fieldName, fieldValue)); + } + break; + case 'xor': { + const [fieldName, fieldValue] = [...model.__identifyingFieldNames].reduce(([fieldName, fieldValue], currentFieldName) => { + const currentFieldValue = this._getValueFromDataOrFromDefault(model, currentFieldName, data); + if (currentFieldValue === undefined) { + return [fieldName, fieldValue]; } if (fieldName) { - throw new Error(`Identifying element on ${model} with "or" value should have only one of the conditional values given in data. Currently have both ${fieldName} and ${currentFieldName}.`); + throw new Error(`Identifying field on ${model} with 'xor' identifying mode should have only one of the conditional values given in data. Currently have both "${fieldName}" and "${currentFieldName}".`); } - return currentFieldName; - }, undefined); - if (!fieldName) { - throw new Error(`Identifying element "${identifyingElement}" on ${model} is lacking a value.`); + return [currentFieldName, currentFieldValue]; + }, [undefined, undefined]); + parts.push(this._getRecordIndexFromField(model, fieldName, fieldValue)); + break; } - const fieldValue = data[fieldName] !== undefined - ? data[fieldName] - : model.__fieldMap[fieldName].default; - if (fieldValue === undefined) { - throw new Error(`Identifying field "${fieldName}" on ${model} is lacking a value.`); - } - const relationTo = model.__fieldMap[fieldName].to; - if (!relationTo) { - return `${fieldName}: ${fieldValue}`; - } - const OtherModel = this.models[relationTo]; - if (fieldValue instanceof OtherModel) { - return `${fieldName}: ${this._getRecordIndex(OtherModel, fieldValue)}`; - } - const fieldValue2 = model.__fieldMap[fieldName].convertToFieldCommandList(fieldValue)[0]; - if (!(fieldValue2 instanceof FieldCommand)) { - throw new Error(`Identifying element "${model}/${fieldName}" is expecting a command for relational field.`); - } - if (!['link', 'insert', 'replace', 'insert-and-replace'].includes(fieldValue2._name)) { - throw new Error(`Identifying element "${model}/${fieldName}" is expecting a command of type "insert-and-replace", "replace", "insert" or "link". "${fieldValue2._name}" was given instead.`); - } - const relationValue = fieldValue2._value; - if (!relationValue) { - throw new Error(`Identifying element "${model}/${fieldName}" is lacking a relation value.`); - } - return `${fieldName}: ${this._getRecordIndex(OtherModel, relationValue)}`; - }).join(', ')})`; + } + return `${model.name}(${parts.join(', ')})`; + } + + /** + * Returns the part of the record index that comes from the given fieldName + * with the given fieldValue. + * + * @param {Object} model + * @param {string} fieldName + * @param {any} fieldValue + * @returns {string} + */ + _getRecordIndexFromField(model, fieldName, fieldValue) { + const relationTo = model.__fieldMap[fieldName].to; + if (!relationTo) { + return `${fieldName}: ${fieldValue}`; + } + const OtherModel = this.models[relationTo]; + if (fieldValue instanceof OtherModel) { + return `${fieldName}: ${this._getRecordIndex(OtherModel, fieldValue)}`; + } + const fieldValue2 = model.__fieldMap[fieldName].convertToFieldCommandList(fieldValue)[0]; + if (!(fieldValue2 instanceof FieldCommand)) { + throw new Error(`Identifying element "${model}/${fieldName}" is expecting a command for relational field.`); + } + if (!['link', 'insert', 'replace', 'insert-and-replace'].includes(fieldValue2._name)) { + throw new Error(`Identifying element "${model}/${fieldName}" is expecting a command of type "insert-and-replace", "replace", "insert" or "link". "${fieldValue2._name}" was given instead.`); + } + const relationValue = fieldValue2._value; + if (!relationValue) { + throw new Error(`Identifying element "${model}/${fieldName}" is lacking a relation value.`); + } + return `${fieldName}: ${this._getRecordIndex(OtherModel, relationValue)}`; + } + + /** + * Returns the value for the given fieldName from the provided data if it is + * defined or from default value of this field otherwise. + * + * @param {Object} model + * @param {string} fieldName + * @param {Object} data + * @returns {any} + */ + _getValueFromDataOrFromDefault(model, fieldName, data) { + if (data[fieldName] !== undefined) { + return data[fieldName]; + } + return model.__fieldMap[fieldName].default; } /** @@ -1051,7 +1083,7 @@ export class ModelManager { fieldName: `_inverse_${model}/${field.fieldName}`, // Allows the inverse of an identifying field to be // automatically generated. - isCausal: model.__identifyingFieldsFlattened.has(field.fieldName), + isCausal: field.identifying, }, )); return inverseField; @@ -1230,8 +1262,12 @@ export class ModelManager { model.__requiredFieldsList = model.__fieldList.filter( field => field.required ); - // Add field accessors. - for (const fieldName of Object.keys(model.__fieldMap)) { + model.__identifyingFieldNames = new Set(); + for (const [fieldName, field] of Object.entries(model.__fieldMap)) { + if (field.identifying) { + model.__identifyingFieldNames.add(fieldName); + } + // Add field accessors. Object.defineProperty(model.prototype, fieldName, { get: function getFieldValue() { // this is bound to record const field = model.__fieldMap[fieldName]; @@ -1290,10 +1326,10 @@ export class ModelManager { // Always update identifying fields first because updating other relational field will // trigger update of inverse field, which will require this identifying fields to be set // beforehand to properly detect whether this is already linked or not on the inverse. - if (model.__identifyingFieldsFlattened.has(a) && !model.__identifyingFieldsFlattened.has(b)) { + if (model.__identifyingFieldNames.has(a) && !model.__identifyingFieldNames.has(b)) { return -1; } - if (!model.__identifyingFieldsFlattened.has(a) && model.__identifyingFieldsFlattened.has(b)) { + if (!model.__identifyingFieldNames.has(a) && model.__identifyingFieldNames.has(b)) { return 1; } return 0; diff --git a/addons/mail/static/src/models/activity.js b/addons/mail/static/src/models/activity.js index c87d59634b5..58944392f56 100644 --- a/addons/mail/static/src/models/activity.js +++ b/addons/mail/static/src/models/activity.js @@ -8,7 +8,6 @@ const { markup } = owl; registerModel({ name: 'Activity', - identifyingFields: ['id'], modelMethods: { /** * @param {Object} data @@ -289,6 +288,7 @@ registerModel({ }), icon: attr(), id: attr({ + identifying: true, readonly: true, required: true, }), diff --git a/addons/mail/static/src/models/activity_box_view.js b/addons/mail/static/src/models/activity_box_view.js index 9b4b5d7f6ba..88d3806a291 100644 --- a/addons/mail/static/src/models/activity_box_view.js +++ b/addons/mail/static/src/models/activity_box_view.js @@ -6,7 +6,6 @@ import { insertAndReplace, replace } from '@mail/model/model_field_command'; registerModel({ name: 'ActivityBoxView', - identifyingFields: ['chatter'], recordMethods: { /** * Handles click on activity box title. @@ -32,6 +31,7 @@ registerModel({ isCausal: true, }), chatter: one('Chatter', { + identifying: true, inverse: 'activityBoxView', readonly: true, required: true, diff --git a/addons/mail/static/src/models/activity_group.js b/addons/mail/static/src/models/activity_group.js index d604152cc10..58b175f709d 100644 --- a/addons/mail/static/src/models/activity_group.js +++ b/addons/mail/static/src/models/activity_group.js @@ -7,7 +7,6 @@ import { OnChange } from '@mail/model/model_onchange'; registerModel({ name: 'ActivityGroup', - identifyingFields: ['irModel'], modelMethods: { convertData(data) { return { @@ -45,6 +44,7 @@ registerModel({ }), domain: attr(), irModel: one('ir.model', { + identifying: true, inverse: 'activityGroup', readonly: true, required: true, diff --git a/addons/mail/static/src/models/activity_group_view.js b/addons/mail/static/src/models/activity_group_view.js index a77948b43bb..b34ed366f93 100644 --- a/addons/mail/static/src/models/activity_group_view.js +++ b/addons/mail/static/src/models/activity_group_view.js @@ -7,7 +7,6 @@ import session from 'web.session'; registerModel({ name: 'ActivityGroupView', - identifyingFields: ['activityMenuViewOwner', 'activityGroup'], recordMethods: { /** * @param {MouseEvent} ev @@ -78,11 +77,13 @@ registerModel({ }, fields: { activityGroup: one('ActivityGroup', { + identifying: true, inverse: 'activityGroupViews', readonly: true, required: true, }), activityMenuViewOwner: one('ActivityMenuView', { + identifying: true, inverse: 'activityGroupViews', readonly: true, required: true, diff --git a/addons/mail/static/src/models/activity_mark_done_popover_content_view.js b/addons/mail/static/src/models/activity_mark_done_popover_content_view.js index ad4d7a3fa00..b44642395b5 100644 --- a/addons/mail/static/src/models/activity_mark_done_popover_content_view.js +++ b/addons/mail/static/src/models/activity_mark_done_popover_content_view.js @@ -6,7 +6,6 @@ import { clear, replace } from '@mail/model/model_field_command'; registerModel({ name: 'ActivityMarkDonePopoverContentView', - identifyingFields: ['popoverViewOwner'], recordMethods: { /** * Handles blur on this feedback textarea. @@ -105,6 +104,7 @@ registerModel({ default: '', }), popoverViewOwner: one('PopoverView', { + identifying: true, inverse: 'activityMarkDonePopoverContentView', readonly: true, required: true, diff --git a/addons/mail/static/src/models/activity_menu_view.js b/addons/mail/static/src/models/activity_menu_view.js index 7df52d85ee4..af62ea6247a 100644 --- a/addons/mail/static/src/models/activity_menu_view.js +++ b/addons/mail/static/src/models/activity_menu_view.js @@ -8,7 +8,6 @@ import session from 'web.session'; registerModel({ name: 'ActivityMenuView', - identifyingFields: [], lifecycleHooks: { _created() { this.fetchData(); diff --git a/addons/mail/static/src/models/activity_type.js b/addons/mail/static/src/models/activity_type.js index e38321e63c2..0c4154a63a2 100644 --- a/addons/mail/static/src/models/activity_type.js +++ b/addons/mail/static/src/models/activity_type.js @@ -5,13 +5,13 @@ import { attr, many } from '@mail/model/model_field'; registerModel({ name: 'ActivityType', - identifyingFields: ['id'], fields: { activities: many('Activity', { inverse: 'type', }), displayName: attr(), id: attr({ + identifying: true, readonly: true, required: true, }), diff --git a/addons/mail/static/src/models/activity_view.js b/addons/mail/static/src/models/activity_view.js index 890c7e0096f..2947a48e9a9 100644 --- a/addons/mail/static/src/models/activity_view.js +++ b/addons/mail/static/src/models/activity_view.js @@ -9,7 +9,6 @@ import { sprintf } from '@web/core/utils/strings'; registerModel({ name: 'ActivityView', - identifyingFields: ['activityBoxView', 'activity'], recordMethods: { /** * Handles the click on a link inside the activity. @@ -169,11 +168,13 @@ registerModel({ }, fields: { activity: one('Activity', { + identifying: true, inverse: 'activityViews', required: true, readonly: true, }), activityBoxView: one('ActivityBoxView', { + identifying: true, inverse: 'activityViews', readonly: true, required: true, diff --git a/addons/mail/static/src/models/attachment.js b/addons/mail/static/src/models/attachment.js index 5c6491df899..d94e5296922 100644 --- a/addons/mail/static/src/models/attachment.js +++ b/addons/mail/static/src/models/attachment.js @@ -6,7 +6,6 @@ import { clear, insert, replace } from '@mail/model/model_field_command'; registerModel({ name: 'Attachment', - identifyingFields: ['id'], modelMethods: { /** * @static @@ -330,6 +329,7 @@ registerModel({ }), filename: attr(), id: attr({ + identifying: true, readonly: true, required: true, }), diff --git a/addons/mail/static/src/models/attachment_box_view.js b/addons/mail/static/src/models/attachment_box_view.js index 57c2dc3275c..8cc57d840cc 100644 --- a/addons/mail/static/src/models/attachment_box_view.js +++ b/addons/mail/static/src/models/attachment_box_view.js @@ -6,7 +6,6 @@ import { clear, insertAndReplace } from '@mail/model/model_field_command'; registerModel({ name: 'AttachmentBoxView', - identifyingFields: ['chatter'], recordMethods: { /** * Handles click on the "add attachment" button. @@ -35,6 +34,7 @@ registerModel({ readonly: true, }), chatter: one('Chatter', { + identifying: true, inverse: 'attachmentBoxView', readonly: true, required: true, diff --git a/addons/mail/static/src/models/attachment_card.js b/addons/mail/static/src/models/attachment_card.js index 0df52e2dd05..69ece321193 100644 --- a/addons/mail/static/src/models/attachment_card.js +++ b/addons/mail/static/src/models/attachment_card.js @@ -6,7 +6,6 @@ import { insertAndReplace, replace } from '@mail/model/model_field_command'; registerModel({ name: 'AttachmentCard', - identifyingFields: ['attachmentList', 'attachment'], recordMethods: { /** * Opens the attachment viewer when clicking on viewable attachment. @@ -49,6 +48,7 @@ registerModel({ * Determines the attachment of this card. */ attachment: one('Attachment', { + identifying: true, readonly: true, required: true, }), @@ -60,6 +60,7 @@ registerModel({ * States the attachmentList displaying this card. */ attachmentList: one('AttachmentList', { + identifying: true, inverse: 'attachmentCards', readonly: true, required: true, diff --git a/addons/mail/static/src/models/attachment_delete_confirm_view.js b/addons/mail/static/src/models/attachment_delete_confirm_view.js index 566302a59d2..54c07290167 100644 --- a/addons/mail/static/src/models/attachment_delete_confirm_view.js +++ b/addons/mail/static/src/models/attachment_delete_confirm_view.js @@ -7,7 +7,6 @@ import { sprintf } from '@web/core/utils/strings'; registerModel({ name: 'AttachmentDeleteConfirmView', - identifyingFields: ['dialogOwner'], recordMethods: { /** * Returns whether the given html element is inside this attachment delete confirm view. @@ -84,6 +83,7 @@ registerModel({ }), component: attr(), dialogOwner: one('Dialog', { + identifying: true, inverse: 'attachmentDeleteConfirmView', readonly: true, required: true, diff --git a/addons/mail/static/src/models/attachment_image.js b/addons/mail/static/src/models/attachment_image.js index fd61611f49a..7baf446a48b 100644 --- a/addons/mail/static/src/models/attachment_image.js +++ b/addons/mail/static/src/models/attachment_image.js @@ -7,7 +7,6 @@ import { isEventHandled, markEventHandled } from '@mail/utils/utils'; registerModel({ name: 'AttachmentImage', - identifyingFields: ['attachmentList', 'attachment'], recordMethods: { /** * Called when clicking on download icon. @@ -115,6 +114,7 @@ registerModel({ * Determines the attachment of this attachment image.. */ attachment: one('Attachment', { + identifying: true, readonly: true, required: true, }), @@ -126,6 +126,7 @@ registerModel({ * States the attachmentList displaying this attachment image. */ attachmentList: one('AttachmentList', { + identifying: true, inverse: 'attachmentImages', readonly: true, required: true, diff --git a/addons/mail/static/src/models/attachment_list.js b/addons/mail/static/src/models/attachment_list.js index fafd2bb1d48..cc5270f9e1f 100644 --- a/addons/mail/static/src/models/attachment_list.js +++ b/addons/mail/static/src/models/attachment_list.js @@ -6,7 +6,7 @@ import { clear, insertAndReplace, replace } from '@mail/model/model_field_comman registerModel({ name: 'AttachmentList', - identifyingFields: [['composerViewOwner', 'messageViewOwner', 'attachmentBoxViewOwner']], + identifyingMode: 'xor', recordMethods: { /** * Select the next attachment. @@ -137,6 +137,7 @@ registerModel({ * Link with a AttachmentBoxView to handle attachments. */ attachmentBoxViewOwner: one('AttachmentBoxView', { + identifying: true, inverse: 'attachmentList', readonly: true, }), @@ -171,6 +172,7 @@ registerModel({ * Link with a composer view to handle attachments. */ composerViewOwner: one('ComposerView', { + identifying: true, inverse: 'attachmentList', readonly: true, }), @@ -220,6 +222,7 @@ registerModel({ * Link with a message view to handle attachments. */ messageViewOwner: one('MessageView', { + identifying: true, inverse: 'attachmentList', readonly: true, }), diff --git a/addons/mail/static/src/models/attachment_viewer.js b/addons/mail/static/src/models/attachment_viewer.js index 2e24fd88769..9df74cb716d 100644 --- a/addons/mail/static/src/models/attachment_viewer.js +++ b/addons/mail/static/src/models/attachment_viewer.js @@ -6,7 +6,6 @@ import { clear, insertAndReplace, replace } from '@mail/model/model_field_comman registerModel({ name: 'AttachmentViewer', - identifyingFields: ['dialogOwner'], recordMethods: { /** * Close the dialog with this attachment viewer. @@ -249,6 +248,7 @@ registerModel({ * Determines the dialog displaying this attachment viewer. */ dialogOwner: one('Dialog', { + identifying: true, inverse: 'attachmentViewer', isCausal: true, readonly: true, diff --git a/addons/mail/static/src/models/attachment_viewer_viewable.js b/addons/mail/static/src/models/attachment_viewer_viewable.js index 1601fd9453e..ace91ee2e56 100644 --- a/addons/mail/static/src/models/attachment_viewer_viewable.js +++ b/addons/mail/static/src/models/attachment_viewer_viewable.js @@ -10,7 +10,7 @@ import { attr, one } from "@mail/model/model_field"; registerModel({ name: "AttachmentViewerViewable", - identifyingFields: [["attachmentOwner"]], + identifyingMode: 'xor', recordMethods: { download() { return this.attachmentOwner.download(); @@ -94,6 +94,7 @@ registerModel({ }, fields: { attachmentOwner: one("Attachment", { + identifying: true, inverse: 'attachmentViewerViewable', readonly: true, }), diff --git a/addons/mail/static/src/models/autocomplete_input_view.js b/addons/mail/static/src/models/autocomplete_input_view.js index 47dc1cdd430..eb4bf41b875 100644 --- a/addons/mail/static/src/models/autocomplete_input_view.js +++ b/addons/mail/static/src/models/autocomplete_input_view.js @@ -6,12 +6,7 @@ import { clear } from '@mail/model/model_field_command'; registerModel({ name: 'AutocompleteInputView', - identifyingFields: [[ - 'chatWindowOwnerAsNewMessage', - 'discussSidebarCategoryOwnerAsAddingItem', - 'discussViewOwnerAsMobileAddItemHeader', - 'messagingMenuOwnerAsMobileNewMessageInput', - ]], + identifyingMode: 'xor', recordMethods: { /** * @param {FocusEvent} ev @@ -92,6 +87,7 @@ registerModel({ }, fields: { chatWindowOwnerAsNewMessage: one('ChatWindow', { + identifying: true, inverse: 'newMessageAutocompleteInputView', readonly: true, }), @@ -101,10 +97,12 @@ registerModel({ default: '', }), discussSidebarCategoryOwnerAsAddingItem: one('DiscussSidebarCategory', { + identifying: true, inverse: 'addingItemAutocompleteInputView', readonly: true, }), discussViewOwnerAsMobileAddItemHeader: one('DiscussView', { + identifying: true, inverse: 'mobileAddItemHeaderAutocompleteInputView', readonly: true, }), @@ -117,6 +115,7 @@ registerModel({ default: false, }), messagingMenuOwnerAsMobileNewMessageInput: one('MessagingMenu', { + identifying: true, inverse: 'mobileNewMessageAutocompleteInputView', readonly: true, }), 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 b1ce54e8aba..af7881a0072 100644 --- a/addons/mail/static/src/models/call_action_list_view.js +++ b/addons/mail/static/src/models/call_action_list_view.js @@ -6,7 +6,6 @@ import { clear, insertAndReplace } from '@mail/model/model_field_command'; registerModel({ name: 'CallActionListView', - identifyingFields: ['callMainView'], recordMethods: { /** * @param {MouseEvent} ev @@ -150,6 +149,7 @@ registerModel({ default: '', }), callMainView: one('CallMainView', { + identifying: true, inverse: 'callActionListView', readonly: true, required: true, diff --git a/addons/mail/static/src/models/call_demo_view.js b/addons/mail/static/src/models/call_demo_view.js index 0dd100a2972..3aa0e93c94f 100644 --- a/addons/mail/static/src/models/call_demo_view.js +++ b/addons/mail/static/src/models/call_demo_view.js @@ -5,7 +5,6 @@ import { registerModel } from '@mail/model/model_core'; registerModel({ name: 'CallDemoView', - identifyingFields: ['welcomeView'], recordMethods: { /** * Stops recording user's microphone. @@ -174,6 +173,7 @@ registerModel({ * States the welcome view containing this media preview. */ welcomeView: one('WelcomeView', { + identifying: true, inverse: 'callDemoView', readonly: true, }), diff --git a/addons/mail/static/src/models/call_invite_request_popup.js b/addons/mail/static/src/models/call_invite_request_popup.js index 108f95bd8d0..35a30d1b82b 100644 --- a/addons/mail/static/src/models/call_invite_request_popup.js +++ b/addons/mail/static/src/models/call_invite_request_popup.js @@ -5,7 +5,6 @@ import { one } from '@mail/model/model_field'; registerModel({ name: 'CallInviteRequestPopup', - identifyingFields: ['thread'], recordMethods: { /** * @param {MouseEvent} ev @@ -35,6 +34,7 @@ registerModel({ }, fields: { thread: one('Thread', { + identifying: true, inverse: 'callInviteRequestPopup', readonly: true, required: true, diff --git a/addons/mail/static/src/models/call_main_view.js b/addons/mail/static/src/models/call_main_view.js index 1b88381e635..c87614e5fb8 100644 --- a/addons/mail/static/src/models/call_main_view.js +++ b/addons/mail/static/src/models/call_main_view.js @@ -8,7 +8,6 @@ import { isEventHandled, markEventHandled } from '@mail/utils/utils'; registerModel({ name: 'CallMainView', - identifyingFields: ['callView'], recordMethods: { /** * Finds a tile layout and dimensions that respects param0.aspectRatio while maximizing @@ -163,6 +162,7 @@ registerModel({ readonly: true, }), callView: one('CallView', { + identifying: true, inverse: 'callMainView', required: 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 72370d3369a..5bac9dcd614 100644 --- a/addons/mail/static/src/models/call_main_view_tile.js +++ b/addons/mail/static/src/models/call_main_view_tile.js @@ -6,14 +6,15 @@ import { one } from '@mail/model/model_field'; registerModel({ name: 'CallMainViewTile', - identifyingFields: ['callMainViewOwner', 'channelMember'], fields: { callMainViewOwner: one('CallMainView', { + identifying: true, inverse: 'mainTiles', readonly: true, required: true, }), channelMember: one('ChannelMember', { + identifying: true, readonly: true, required: true, }), diff --git a/addons/mail/static/src/models/call_option_menu.js b/addons/mail/static/src/models/call_option_menu.js index 90f8635c32c..6b4d039a7ae 100644 --- a/addons/mail/static/src/models/call_option_menu.js +++ b/addons/mail/static/src/models/call_option_menu.js @@ -6,7 +6,6 @@ import { clear } from '@mail/model/model_field_command'; registerModel({ name: 'CallOptionMenu', - identifyingFields: ['callActionListView'], recordMethods: { /** * @param {Event} ev @@ -67,6 +66,7 @@ registerModel({ */ component: attr(), callActionListView: one('CallActionListView', { + identifying: true, inverse: 'callOptionMenu', readonly: true, required: true, diff --git a/addons/mail/static/src/models/call_participant_card.js b/addons/mail/static/src/models/call_participant_card.js index d1d55f0af5b..5bf38099a8d 100644 --- a/addons/mail/static/src/models/call_participant_card.js +++ b/addons/mail/static/src/models/call_participant_card.js @@ -9,7 +9,7 @@ import { sprintf } from '@web/core/utils/strings'; registerModel({ name: 'CallParticipantCard', - identifyingFields: [['sidebarViewTileOwner', 'mainViewTileOwner']], + identifyingMode: 'xor', recordMethods: { /** * @param {Event} ev @@ -168,6 +168,7 @@ registerModel({ compute: '_computeInboundConnectionTypeText', }), mainViewTileOwner: one('CallMainViewTile', { + identifying: true, inverse: 'participantCard', readonly: true, }), @@ -203,6 +204,7 @@ registerModel({ inverse: 'callParticipantCards', }), sidebarViewTileOwner: one('CallSidebarViewTile', { + identifying: true, inverse: 'participantCard', readonly: true, }), diff --git a/addons/mail/static/src/models/call_participant_video_view.js b/addons/mail/static/src/models/call_participant_video_view.js index de552158e3e..0c3cb1f9478 100644 --- a/addons/mail/static/src/models/call_participant_video_view.js +++ b/addons/mail/static/src/models/call_participant_video_view.js @@ -6,7 +6,6 @@ import { clear, replace } from '@mail/model/model_field_command'; registerModel({ name: 'CallParticipantVideoView', - identifyingFields: ['callParticipantCardOwner'], recordMethods: { /** * Plays the video as some browsers may not support or block autoplay. @@ -38,6 +37,7 @@ registerModel({ }, fields: { callParticipantCardOwner: one('CallParticipantCard', { + identifying: true, inverse: 'callParticipantVideoView', readonly: true, required: true, diff --git a/addons/mail/static/src/models/call_settings_menu.js b/addons/mail/static/src/models/call_settings_menu.js index 5c276d5249e..b1b7d3cdce8 100644 --- a/addons/mail/static/src/models/call_settings_menu.js +++ b/addons/mail/static/src/models/call_settings_menu.js @@ -7,7 +7,6 @@ import { attr, one } from '@mail/model/model_field'; registerModel({ name: 'CallSettingsMenu', - identifyingFields: ['userSetting'], lifecycleHooks: { _created() { browser.addEventListener('keydown', this._onKeyDown); @@ -83,6 +82,7 @@ registerModel({ default: false, }), userSetting: one('UserSetting', { + identifying: true, inverse: 'callSettingsMenu', readonly: true, }), diff --git a/addons/mail/static/src/models/call_sidebar_view.js b/addons/mail/static/src/models/call_sidebar_view.js index 65b296a91ab..36aef23fcbd 100644 --- a/addons/mail/static/src/models/call_sidebar_view.js +++ b/addons/mail/static/src/models/call_sidebar_view.js @@ -6,7 +6,6 @@ import { insertAndReplace, replace } from '@mail/model/model_field_command'; registerModel({ name: 'CallSidebarView', - identifyingFields: ['callView'], recordMethods: { /** * @private @@ -18,6 +17,7 @@ registerModel({ }, fields: { callView: one('CallView', { + identifying: true, inverse: 'callSidebarView', readonly: true, required: true, 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 f031ee4e624..451270c23b3 100644 --- a/addons/mail/static/src/models/call_sidebar_view_tile.js +++ b/addons/mail/static/src/models/call_sidebar_view_tile.js @@ -6,14 +6,15 @@ import { one } from '@mail/model/model_field'; registerModel({ name: 'CallSidebarViewTile', - identifyingFields: ['callSidebarViewOwner', 'channelMember'], fields: { callSidebarViewOwner: one('CallSidebarView', { + identifying: true, inverse: 'sidebarTiles', readonly: true, required: true, }), channelMember: one('ChannelMember', { + identifying: true, readonly: true, required: true, }), diff --git a/addons/mail/static/src/models/call_systray_menu.js b/addons/mail/static/src/models/call_systray_menu.js index 9ed2308b005..99e4d37e6ad 100644 --- a/addons/mail/static/src/models/call_systray_menu.js +++ b/addons/mail/static/src/models/call_systray_menu.js @@ -8,7 +8,6 @@ import { sprintf } from '@web/core/utils/strings'; registerModel({ name: 'CallSystrayMenu', - identifyingFields: ['rtc'], recordMethods: { /** * @private @@ -30,6 +29,7 @@ registerModel({ default: '', }), rtc: one('Rtc', { + identifying: true, inverse: 'callSystrayMenu', readonly: true, required: true, diff --git a/addons/mail/static/src/models/call_view.js b/addons/mail/static/src/models/call_view.js index a17e3ccac5f..8effd460980 100644 --- a/addons/mail/static/src/models/call_view.js +++ b/addons/mail/static/src/models/call_view.js @@ -9,7 +9,6 @@ import { clear, insertAndReplace, replace } from '@mail/model/model_field_comman registerModel({ name: 'CallView', - identifyingFields: ['threadView'], lifecycleHooks: { _created() { browser.addEventListener('fullscreenchange', this._onFullScreenChange); @@ -229,6 +228,7 @@ registerModel({ * ThreadView on which the call view is attached. */ threadView: one('ThreadView', { + identifying: true, inverse: 'callView', readonly: true, required: true, diff --git a/addons/mail/static/src/models/canned_response.js b/addons/mail/static/src/models/canned_response.js index f0d3103288e..a8439d61bce 100644 --- a/addons/mail/static/src/models/canned_response.js +++ b/addons/mail/static/src/models/canned_response.js @@ -7,7 +7,6 @@ import { cleanSearchTerm } from '@mail/utils/utils'; registerModel({ name: 'CannedResponse', - identifyingFields: ['id'], modelMethods: { /** * Fetches canned responses matching the given search term to extend the @@ -71,6 +70,7 @@ registerModel({ }, fields: { id: attr({ + identifying: true, readonly: true, required: true, }), diff --git a/addons/mail/static/src/models/channel.js b/addons/mail/static/src/models/channel.js index baddbc2ebbd..0f535b55f51 100644 --- a/addons/mail/static/src/models/channel.js +++ b/addons/mail/static/src/models/channel.js @@ -6,7 +6,6 @@ import { insertAndReplace, replace } from '@mail/model/model_field_command'; registerModel({ name: 'Channel', - identifyingFields: ['id'], recordMethods: { async fetchChannelMembers() { const channelData = await this.messaging.rpc({ @@ -92,6 +91,7 @@ registerModel({ }), channel_type: attr(), id: attr({ + identifying: true, readonly: true, required: true, }), diff --git a/addons/mail/static/src/models/channel_command.js b/addons/mail/static/src/models/channel_command.js index 826929aca1f..5ab8e4b3589 100644 --- a/addons/mail/static/src/models/channel_command.js +++ b/addons/mail/static/src/models/channel_command.js @@ -7,7 +7,6 @@ import { cleanSearchTerm } from '@mail/utils/utils'; registerModel({ name: 'ChannelCommand', - identifyingFields: ['name'], modelMethods: { /** * Fetches channel commands matching the given search term to extend the @@ -128,6 +127,7 @@ registerModel({ * The keyword to use a specific command. */ name: attr({ + identifying: true, readonly: true, required: true, }), diff --git a/addons/mail/static/src/models/channel_invitation_form.js b/addons/mail/static/src/models/channel_invitation_form.js index ccb73c36133..22669711dd4 100644 --- a/addons/mail/static/src/models/channel_invitation_form.js +++ b/addons/mail/static/src/models/channel_invitation_form.js @@ -9,7 +9,7 @@ import { sprintf } from '@web/core/utils/strings'; registerModel({ name: 'ChannelInvitationForm', - identifyingFields: [['chatWindow', 'popoverViewOwner']], + identifyingMode: 'xor', recordMethods: { /** * Handles click on the "copy" button. @@ -236,6 +236,7 @@ registerModel({ compute: '_computeAccessRestrictedToGroupText', }), chatWindow: one('ChatWindow', { + identifying: true, inverse: 'channelInvitationForm', readonly: true, }), @@ -271,6 +272,7 @@ registerModel({ * If set, this channel invitation form is content of related popover view. */ popoverViewOwner: one('PopoverView', { + identifying: true, inverse: 'channelInvitationForm', isCausal: true, readonly: true, 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 9e83c3356b1..966b10db12c 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 @@ -6,7 +6,6 @@ import { clear, insertAndReplace } from '@mail/model/model_field_command'; registerModel({ name: 'ChannelInvitationFormSelectablePartnerView', - identifyingFields: ['channelInvitationFormOwner', 'partner'], recordMethods: { /** * @private @@ -18,11 +17,13 @@ registerModel({ }, fields: { channelInvitationFormOwner: one('ChannelInvitationForm', { + identifying: true, inverse: 'selectablePartnerViews', readonly: true, required: true, }), partner: one('Partner', { + identifying: true, inverse: 'channelInvitationFormSelectablePartnerViews', readonly: true, required: true, diff --git a/addons/mail/static/src/models/channel_invitation_form_selected_partner_view.js b/addons/mail/static/src/models/channel_invitation_form_selected_partner_view.js index 5a9bdc7c968..34c40ece68e 100644 --- a/addons/mail/static/src/models/channel_invitation_form_selected_partner_view.js +++ b/addons/mail/static/src/models/channel_invitation_form_selected_partner_view.js @@ -5,14 +5,15 @@ import { one } from '@mail/model/model_field'; registerModel({ name: 'ChannelInvitationFormSelectedPartnerView', - identifyingFields: ['channelInvitationFormOwner', 'partner'], fields: { channelInvitationFormOwner: one('ChannelInvitationForm', { + identifying: true, inverse: 'selectedPartnerViews', readonly: true, required: true, }), partner: one('Partner', { + identifying: true, inverse: 'channelInvitationFormSelectedPartnerViews', readonly: true, required: true, diff --git a/addons/mail/static/src/models/channel_member.js b/addons/mail/static/src/models/channel_member.js index 434e329c33d..2a73ffbe53c 100644 --- a/addons/mail/static/src/models/channel_member.js +++ b/addons/mail/static/src/models/channel_member.js @@ -6,7 +6,6 @@ import { clear, replace } from '@mail/model/model_field_command'; registerModel({ name: 'ChannelMember', - identifyingFields: ['id'], recordMethods: { /** * @private @@ -81,6 +80,7 @@ registerModel({ isCausal: true, }), id: attr({ + identifying: true, readonly: true, required: true, }), 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 fbf88197ff1..93d43828a66 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 @@ -8,7 +8,7 @@ import { sprintf } from '@web/core/utils/strings'; registerModel({ name: 'ChannelMemberListCategoryView', - identifyingFields: [['channelMemberListViewOwnerAsOffline', 'channelMemberListViewOwnerAsOnline']], + identifyingMode: 'xor', recordMethods: { /** * @private @@ -77,10 +77,12 @@ registerModel({ required: true, }), channelMemberListViewOwnerAsOffline: one('ChannelMemberListView', { + identifying: true, inverse: 'offlineCategoryView', readonly: true, }), channelMemberListViewOwnerAsOnline: one('ChannelMemberListView', { + identifying: true, inverse: 'onlineCategoryView', readonly: true, }), 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 5bbe728cd7e..3d41ee4a548 100644 --- a/addons/mail/static/src/models/channel_member_list_view.js +++ b/addons/mail/static/src/models/channel_member_list_view.js @@ -6,7 +6,7 @@ import { clear, insertAndReplace, replace } from '@mail/model/model_field_comman registerModel({ name: 'ChannelMemberListView', - identifyingFields: [['chatWindowOwner', 'threadViewOwner']], + identifyingMode: 'xor', lifecycleHooks: { _created() { this.channel.fetchChannelMembers(); @@ -59,6 +59,7 @@ registerModel({ readonly: true, }), chatWindowOwner: one('ChatWindow', { + identifying: true, inverse: 'channelMemberListView', readonly: true, }), @@ -73,6 +74,7 @@ registerModel({ isCausal: true, }), threadViewOwner: one('ThreadView', { + identifying: true, inverse: 'channelMemberListView', readonly: true, }), diff --git a/addons/mail/static/src/models/channel_member_view.js b/addons/mail/static/src/models/channel_member_view.js index c763ed98c90..1140f8f1708 100644 --- a/addons/mail/static/src/models/channel_member_view.js +++ b/addons/mail/static/src/models/channel_member_view.js @@ -3,11 +3,10 @@ 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 { isEventHandled } from '@mail/utils/utils' +import { isEventHandled } from '@mail/utils/utils'; registerModel({ name: 'ChannelMemberView', - identifyingFields: ['channelMemberListCategoryViewOwner', 'channelMember'], recordMethods: { /** * Handles click on channel member in the member list of this channel. @@ -47,11 +46,13 @@ registerModel({ }, fields: { channelMemberListCategoryViewOwner: one('ChannelMemberListCategoryView', { + identifying: true, inverse: 'channelMemberViews', readonly: true, required: true, }), channelMember: one('ChannelMember', { + identifying: true, inverse: 'channelMemberViews', readonly: true, required: true, diff --git a/addons/mail/static/src/models/chat_window.js b/addons/mail/static/src/models/chat_window.js index 12e61ac9647..c00d6c032f8 100644 --- a/addons/mail/static/src/models/chat_window.js +++ b/addons/mail/static/src/models/chat_window.js @@ -7,7 +7,7 @@ import { isEventHandled, markEventHandled } from '@mail/utils/utils'; registerModel({ name: 'ChatWindow', - identifyingFields: ['manager', ['thread', 'managerAsNewMessage']], + identifyingMode: 'xor', recordMethods: { /** * Close this chat window. @@ -658,6 +658,7 @@ registerModel({ readonly: true, }), managerAsNewMessage: one('ChatWindowManager', { + identifying: true, inverse: 'newMessageChatWindow', readonly: true, }), @@ -681,6 +682,7 @@ registerModel({ * If no `Thread` is linked, `this` is considered "new message". */ thread: one('Thread', { + identifying: true, inverse: 'chatWindow', readonly: true, }), diff --git a/addons/mail/static/src/models/chat_window_header_view.js b/addons/mail/static/src/models/chat_window_header_view.js index 7740ddab0e3..b6a80f4cb42 100644 --- a/addons/mail/static/src/models/chat_window_header_view.js +++ b/addons/mail/static/src/models/chat_window_header_view.js @@ -6,7 +6,6 @@ import { isEventHandled } from '@mail/utils/utils'; registerModel({ name: 'ChatWindowHeaderView', - identifyingFields: ['chatWindowOwner'], recordMethods: { /** * @param {MouseEvent} ev @@ -28,6 +27,7 @@ registerModel({ }, fields: { chatWindowOwner: one('ChatWindow', { + identifying: true, inverse: 'chatWindowHeaderView', readonly: true, required: true, diff --git a/addons/mail/static/src/models/chat_window_manager.js b/addons/mail/static/src/models/chat_window_manager.js index e0a399719e2..5960161b31e 100644 --- a/addons/mail/static/src/models/chat_window_manager.js +++ b/addons/mail/static/src/models/chat_window_manager.js @@ -44,7 +44,6 @@ const BASE_VISUAL = { registerModel({ name: 'ChatWindowManager', - identifyingFields: ['messaging'], recordMethods: { /** * Close all chat windows. diff --git a/addons/mail/static/src/models/chatter.js b/addons/mail/static/src/models/chatter.js index 33ba32870e4..edca2cd49e8 100644 --- a/addons/mail/static/src/models/chatter.js +++ b/addons/mail/static/src/models/chatter.js @@ -23,7 +23,6 @@ const getMessageNextTemporaryId = (function () { registerModel({ name: 'Chatter', - identifyingFields: ['id'], recordMethods: { focus() { if (this.composerView) { @@ -439,6 +438,7 @@ registerModel({ * of this record. */ id: attr({ + identifying: true, readonly: true, required: true, }), diff --git a/addons/mail/static/src/models/chatter_topbar.js b/addons/mail/static/src/models/chatter_topbar.js index 4ff0c0205b5..296c791f3d7 100644 --- a/addons/mail/static/src/models/chatter_topbar.js +++ b/addons/mail/static/src/models/chatter_topbar.js @@ -7,7 +7,6 @@ import { sprintf } from '@web/core/utils/strings'; registerModel({ name: 'ChatterTopbar', - identifyingFields: ['chatter'], recordMethods: { /** * @private @@ -41,6 +40,7 @@ registerModel({ compute: '_computeAttachmentButtonText', }), chatter: one('Chatter', { + identifying: true, inverse: 'topbar', readonly: true, required: true, diff --git a/addons/mail/static/src/models/clock.js b/addons/mail/static/src/models/clock.js index 02ad0cf1c4f..6182e33b010 100644 --- a/addons/mail/static/src/models/clock.js +++ b/addons/mail/static/src/models/clock.js @@ -9,7 +9,6 @@ import { OnChange } from '@mail/model/model_onchange'; */ registerModel({ name: 'Clock', - identifyingFields: ['frequency'], lifecycleHooks: { _willDelete() { this.messaging.browser.clearInterval(this.tickInterval); @@ -62,6 +61,7 @@ registerModel({ * must be recomputed. */ frequency: attr({ + identifying: true, readonly: true, required: true, }), diff --git a/addons/mail/static/src/models/clock_watcher.js b/addons/mail/static/src/models/clock_watcher.js index 6a0a8a15fc3..c8bc29e62f7 100644 --- a/addons/mail/static/src/models/clock_watcher.js +++ b/addons/mail/static/src/models/clock_watcher.js @@ -8,9 +8,10 @@ import { one } from '@mail/model/model_field'; */ registerModel({ name: 'ClockWatcher', - identifyingFields: [['activityViewOwner', 'messageViewOwner']], + identifyingMode: 'xor', fields: { activityViewOwner: one('ActivityView', { + identifying: true, inverse: 'clockWatcher', readonly: true, }), @@ -19,6 +20,7 @@ registerModel({ required: true, }), messageViewOwner: one('MessageView', { + identifying: true, inverse: 'clockWatcher', readonly: true, }), diff --git a/addons/mail/static/src/models/composer.js b/addons/mail/static/src/models/composer.js index d407e7d62a2..f5d718a73b0 100644 --- a/addons/mail/static/src/models/composer.js +++ b/addons/mail/static/src/models/composer.js @@ -7,7 +7,7 @@ import { sprintf } from '@web/core/utils/strings'; registerModel({ name: 'Composer', - identifyingFields: [['thread', 'messageViewInEditing']], + identifyingMode: 'xor', recordMethods: { /** * @private @@ -185,6 +185,7 @@ registerModel({ compute: '_computeMentionedPartners', }), messageViewInEditing: one('MessageView', { + identifying: true, inverse: 'composerForEditing', readonly: true, }), @@ -218,6 +219,7 @@ registerModel({ * States the thread which this composer represents the state (if any). */ thread: one('Thread', { + identifying: true, inverse: 'composer', readonly: true, }), diff --git a/addons/mail/static/src/models/composer_suggestable.js b/addons/mail/static/src/models/composer_suggestable.js index 58c8f75bad3..26f633ca4c5 100644 --- a/addons/mail/static/src/models/composer_suggestable.js +++ b/addons/mail/static/src/models/composer_suggestable.js @@ -5,13 +5,15 @@ import { many, one } from '@mail/model/model_field'; registerModel({ name: 'ComposerSuggestable', - identifyingFields: [['cannedResponse', 'channelCommand', 'partner', 'thread']], + identifyingMode: 'xor', fields: { cannedResponse: one('CannedResponse', { + identifying: true, inverse: 'suggestable', readonly: true, }), channelCommand: one('ChannelCommand', { + identifying: true, inverse: 'suggestable', readonly: true, }), @@ -24,10 +26,12 @@ registerModel({ isCausal: true, }), partner: one('Partner', { + identifying: true, inverse: 'suggestable', readonly: true, }), thread: one('Thread', { + identifying: true, inverse: 'suggestable', 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 6b461641053..15247f06f96 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 @@ -6,7 +6,6 @@ import { clear, insertAndReplace, replace } from '@mail/model/model_field_comman registerModel({ name: 'ComposerSuggestedRecipientListView', - identifyingFields: ['composerViewOwner'], recordMethods: { /** * @param {MouseEvent} ev @@ -63,6 +62,7 @@ registerModel({ isCausal: true, }), composerViewOwner: one('ComposerView', { + identifying: true, inverse: 'composerSuggestedRecipientListView', readonly: true, required: true, diff --git a/addons/mail/static/src/models/composer_suggested_recipient_view.js b/addons/mail/static/src/models/composer_suggested_recipient_view.js index 335ae0738cd..a5ac8251dd7 100644 --- a/addons/mail/static/src/models/composer_suggested_recipient_view.js +++ b/addons/mail/static/src/models/composer_suggested_recipient_view.js @@ -5,14 +5,15 @@ import { one } from '@mail/model/model_field'; registerModel({ name: 'ComposerSuggestedRecipientView', - identifyingFields: ['composerSuggestedRecipientListViewOwner', 'suggestedRecipientInfo'], fields: { composerSuggestedRecipientListViewOwner: one('ComposerSuggestedRecipientListView', { + identifying: true, inverse: 'composerSuggestedRecipientViews', readonly: true, required: true, }), suggestedRecipientInfo: one('SuggestedRecipientInfo', { + identifying: true, inverse: 'composerSuggestedRecipientViews', readonly: true, required: true, 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 3128359d9df..aa236fda0f2 100644 --- a/addons/mail/static/src/models/composer_suggestion_list_view.js +++ b/addons/mail/static/src/models/composer_suggestion_list_view.js @@ -6,7 +6,6 @@ import { insertAndReplace, replace } from '@mail/model/model_field_command'; registerModel({ name: 'ComposerSuggestionListView', - identifyingFields: ['composerViewOwner'], recordMethods: { /** * Sets the first suggestion as active. Main and extra records are @@ -120,6 +119,7 @@ registerModel({ isCausal: true, }), composerViewOwner: one('ComposerView', { + identifying: true, inverse: 'composerSuggestionListView', readonly: true, required: true, 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 ccbead6fdbe..80797b393bf 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 @@ -11,9 +11,9 @@ import { insertAndReplace } from '@mail/model/model_field_command'; */ registerModel({ name: 'ComposerSuggestionListViewExtraComposerSuggestionViewItem', - identifyingFields: ['composerSuggestionListViewOwner', 'suggestable'], fields: { composerSuggestionListViewOwner: one('ComposerSuggestionListView', { + identifying: true, inverse: 'composerSuggestionListViewExtraComposerSuggestionViewItems', readonly: true, required: true, @@ -26,6 +26,7 @@ registerModel({ required: true, }), suggestable: one('ComposerSuggestable', { + identifying: true, inverse: 'composerSuggestionListViewExtraComposerSuggestionViewItems', readonly: true, required: 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 1150febb81a..eba44a8ff9f 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 @@ -11,9 +11,9 @@ import { insertAndReplace } from '@mail/model/model_field_command'; */ registerModel({ name: 'ComposerSuggestionListViewMainComposerSuggestionViewItem', - identifyingFields: ['composerSuggestionListViewOwner', 'suggestable'], fields: { composerSuggestionListViewOwner: one('ComposerSuggestionListView', { + identifying: true, inverse: 'composerSuggestionListViewMainComposerSuggestionViewItems', readonly: true, required: true, @@ -26,6 +26,7 @@ registerModel({ required: true, }), suggestable: one('ComposerSuggestable', { + identifying: true, inverse: 'composerSuggestionListViewMainComposerSuggestionViewItems', readonly: true, required: true, diff --git a/addons/mail/static/src/models/composer_suggestion_view.js b/addons/mail/static/src/models/composer_suggestion_view.js index 865cd2f7ba7..09433fe7f69 100644 --- a/addons/mail/static/src/models/composer_suggestion_view.js +++ b/addons/mail/static/src/models/composer_suggestion_view.js @@ -13,7 +13,7 @@ import { sprintf } from '@web/core/utils/strings'; */ registerModel({ name: 'ComposerSuggestionView', - identifyingFields: [['composerSuggestionListViewExtraComposerSuggestionViewItemOwner', 'composerSuggestionListViewMainComposerSuggestionViewItemOwner']], + identifyingMode: 'xor', recordMethods: { /** * @param {Event} ev @@ -115,10 +115,12 @@ registerModel({ inverse: 'activeSuggestionView', }), composerSuggestionListViewExtraComposerSuggestionViewItemOwner: one('ComposerSuggestionListViewExtraComposerSuggestionViewItem', { + identifying: true, inverse: 'composerSuggestionView', readonly: true, }), composerSuggestionListViewMainComposerSuggestionViewItemOwner: one('ComposerSuggestionListViewMainComposerSuggestionViewItem', { + identifying: true, inverse: 'composerSuggestionView', readonly: true, }), diff --git a/addons/mail/static/src/models/composer_view.js b/addons/mail/static/src/models/composer_view.js index 301ebde9775..1bade1f4147 100644 --- a/addons/mail/static/src/models/composer_view.js +++ b/addons/mail/static/src/models/composer_view.js @@ -12,7 +12,7 @@ import { url } from '@web/core/utils/urls'; registerModel({ name: 'ComposerView', - identifyingFields: [['threadView', 'messageViewInEditing', 'chatter']], + identifyingMode: 'xor', lifecycleHooks: { _created() { document.addEventListener('click', this.onClickCaptureGlobal, true); @@ -1377,6 +1377,7 @@ registerModel({ * States the chatter which this composer allows editing (if any). */ chatter: one('Chatter', { + identifying: true, inverse: 'composerView', readonly: true, }), @@ -1542,6 +1543,7 @@ registerModel({ * States the message view on which this composer allows editing (if any). */ messageViewInEditing: one('MessageView', { + identifying: true, inverse: 'composerViewInEditing', readonly: true, }), @@ -1609,6 +1611,7 @@ registerModel({ * States the thread view on which this composer allows editing (if any). */ threadView: one('ThreadView', { + identifying: true, inverse: 'composerView', readonly: true, }), diff --git a/addons/mail/static/src/models/country.js b/addons/mail/static/src/models/country.js index 4960dd64ecb..344a81017d0 100644 --- a/addons/mail/static/src/models/country.js +++ b/addons/mail/static/src/models/country.js @@ -6,7 +6,6 @@ import { clear } from '@mail/model/model_field_command'; registerModel({ name: 'Country', - identifyingFields: ['id'], recordMethods: { /** * @private @@ -25,6 +24,7 @@ registerModel({ compute: '_computeFlagUrl', }), id: attr({ + identifying: true, readonly: true, required: 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 adb7b9127ab..3aff9f59441 100644 --- a/addons/mail/static/src/models/delete_message_confirm_view.js +++ b/addons/mail/static/src/models/delete_message_confirm_view.js @@ -6,7 +6,6 @@ import { clear, insertAndReplace, replace } from '@mail/model/model_field_comman registerModel({ name: 'DeleteMessageConfirmView', - identifyingFields: ['dialogOwner'], recordMethods: { /** * Returns whether the given html element is inside this delete message confirm view. @@ -44,6 +43,7 @@ registerModel({ fields: { component: attr(), dialogOwner: one('Dialog', { + identifying: true, inverse: 'deleteMessageConfirmView', readonly: true, required: true, diff --git a/addons/mail/static/src/models/device.js b/addons/mail/static/src/models/device.js index 0c27246c88d..4338e65efb3 100644 --- a/addons/mail/static/src/models/device.js +++ b/addons/mail/static/src/models/device.js @@ -8,7 +8,6 @@ import { SIZES } from '@web/core/ui/ui_service'; registerModel({ name: 'Device', - identifyingFields: ['messaging'], lifecycleHooks: { _created() { this._refresh(); diff --git a/addons/mail/static/src/models/dialog.js b/addons/mail/static/src/models/dialog.js index f9b26e02a03..f5f973121e2 100644 --- a/addons/mail/static/src/models/dialog.js +++ b/addons/mail/static/src/models/dialog.js @@ -6,13 +6,7 @@ import { clear, insertAndReplace, replace } from '@mail/model/model_field_comman registerModel({ name: 'Dialog', - identifyingFields: [[ - 'attachmentCardOwnerAsAttachmentDeleteConfirm', - 'attachmentImageOwnerAsAttachmentDeleteConfirm', - 'attachmentListOwnerAsAttachmentView', - 'followerOwnerAsSubtypeList', - 'messageActionListOwnerAsDeleteConfirm', - ]], + identifyingMode: 'xor', lifecycleHooks: { _created() { document.addEventListener('click', this._onClickGlobal, true); @@ -188,6 +182,7 @@ registerModel({ }, fields: { attachmentCardOwnerAsAttachmentDeleteConfirm: one('AttachmentCard', { + identifying: true, inverse: 'attachmentDeleteConfirmDialog', readonly: true, }), @@ -197,10 +192,12 @@ registerModel({ isCausal: true, }), attachmentImageOwnerAsAttachmentDeleteConfirm: one('AttachmentImage', { + identifying: true, inverse: 'attachmentDeleteConfirmDialog', readonly: true, }), attachmentListOwnerAsAttachmentView: one('AttachmentList', { + identifying: true, inverse: 'attachmentListViewDialog', readonly: true, }), @@ -225,6 +222,7 @@ registerModel({ isCausal: true, }), followerOwnerAsSubtypeList: one('Follower', { + identifying: true, inverse: 'followerSubtypeListDialog', readonly: true, }), @@ -243,6 +241,7 @@ registerModel({ readonly: true, }), messageActionListOwnerAsDeleteConfirm: one('MessageActionList', { + identifying: true, inverse: 'deleteConfirmDialog', readonly: true, }), diff --git a/addons/mail/static/src/models/dialog_manager.js b/addons/mail/static/src/models/dialog_manager.js index cba39106f66..12b8dd8ee78 100644 --- a/addons/mail/static/src/models/dialog_manager.js +++ b/addons/mail/static/src/models/dialog_manager.js @@ -5,7 +5,6 @@ import { many } from '@mail/model/model_field'; registerModel({ name: 'DialogManager', - identifyingFields: ['messaging'], fields: { // FIXME: dependent on implementation that uses insert order in relations!! dialogs: many('Dialog', { diff --git a/addons/mail/static/src/models/discuss.js b/addons/mail/static/src/models/discuss.js index 3631231947d..a1d5a187757 100644 --- a/addons/mail/static/src/models/discuss.js +++ b/addons/mail/static/src/models/discuss.js @@ -7,7 +7,6 @@ import { escape, sprintf } from '@web/core/utils/strings'; registerModel({ name: 'Discuss', - identifyingFields: ['messaging'], recordMethods: { clearIsAddingItem() { this.update({ diff --git a/addons/mail/static/src/models/discuss_public_view.js b/addons/mail/static/src/models/discuss_public_view.js index 7ec4120de17..69ccae72884 100644 --- a/addons/mail/static/src/models/discuss_public_view.js +++ b/addons/mail/static/src/models/discuss_public_view.js @@ -6,7 +6,6 @@ import { clear, insertAndReplace, replace } from '@mail/model/model_field_comman registerModel({ name: 'DiscussPublicView', - identifyingFields: ['messaging'], recordMethods: { /** * Creates and displays the thread view and clears the welcome view. diff --git a/addons/mail/static/src/models/discuss_sidebar_category.js b/addons/mail/static/src/models/discuss_sidebar_category.js index 9cf845ec54c..05915277377 100644 --- a/addons/mail/static/src/models/discuss_sidebar_category.js +++ b/addons/mail/static/src/models/discuss_sidebar_category.js @@ -7,7 +7,7 @@ import { OnChange } from '@mail/model/model_onchange'; registerModel({ name: 'DiscussSidebarCategory', - identifyingFields: [['discussAsChannel', 'discussAsChat']], + identifyingMode: 'xor', modelMethods: { /** * Performs the `set_res_users_settings` RPC on `res.users.settings`. @@ -377,10 +377,12 @@ registerModel({ sum: 'categoryItems.categoryCounterContribution', }), discussAsChannel: one('Discuss', { + identifying: true, inverse: 'categoryChannel', readonly: true, }), discussAsChat: one('Discuss', { + identifying: true, inverse: 'categoryChat', readonly: true, }), diff --git a/addons/mail/static/src/models/discuss_sidebar_category_item.js b/addons/mail/static/src/models/discuss_sidebar_category_item.js index f12cf450f10..ef6d0d5faf3 100644 --- a/addons/mail/static/src/models/discuss_sidebar_category_item.js +++ b/addons/mail/static/src/models/discuss_sidebar_category_item.js @@ -8,7 +8,6 @@ import Dialog from 'web.Dialog'; registerModel({ name: 'DiscussSidebarCategoryItem', - identifyingFields: ['category', 'thread'], recordMethods: { /** * @private @@ -226,6 +225,7 @@ registerModel({ * Determines the discuss sidebar category displaying this item. */ category: one('DiscussSidebarCategory', { + identifying: true, inverse: 'categoryItems', readonly: true, required: true, @@ -288,6 +288,7 @@ registerModel({ * The related thread. */ thread: one('Thread', { + identifying: true, inverse: 'discussSidebarCategoryItem', readonly: true, required: true, diff --git a/addons/mail/static/src/models/discuss_sidebar_mailbox_view.js b/addons/mail/static/src/models/discuss_sidebar_mailbox_view.js index f87e3718ded..fdf3e8c35dd 100644 --- a/addons/mail/static/src/models/discuss_sidebar_mailbox_view.js +++ b/addons/mail/static/src/models/discuss_sidebar_mailbox_view.js @@ -6,7 +6,7 @@ import { clear, replace } from '@mail/model/model_field_command'; registerModel({ name: 'DiscussSidebarMailboxView', - identifyingFields: [['discussViewOwnerAsHistory', 'discussViewOwnerAsInbox', 'discussViewOwnerAsStarred']], + identifyingMode: 'xor', recordMethods: { /** * @private @@ -27,14 +27,17 @@ registerModel({ }, fields: { discussViewOwnerAsHistory: one('DiscussView', { + identifying: true, inverse: 'historyView', readonly: true, }), discussViewOwnerAsInbox: one('DiscussView', { + identifying: true, inverse: 'inboxView', readonly: true, }), discussViewOwnerAsStarred: one('DiscussView', { + identifying: true, inverse: 'starredView', readonly: true, }), diff --git a/addons/mail/static/src/models/discuss_view.js b/addons/mail/static/src/models/discuss_view.js index 697ef49e456..53382074bc3 100644 --- a/addons/mail/static/src/models/discuss_view.js +++ b/addons/mail/static/src/models/discuss_view.js @@ -7,7 +7,6 @@ import { OnChange } from '@mail/model/model_onchange'; registerModel({ name: 'DiscussView', - identifyingFields: ['discuss'], recordMethods: { /** * Handles click on the mobile "new channel" button. @@ -136,6 +135,7 @@ registerModel({ */ actionId: attr(), discuss: one('Discuss', { + identifying: true, inverse: 'discussView', readonly: true, required: true, diff --git a/addons/mail/static/src/models/drop_zone_view.js b/addons/mail/static/src/models/drop_zone_view.js index df4410abfef..02eb382406b 100644 --- a/addons/mail/static/src/models/drop_zone_view.js +++ b/addons/mail/static/src/models/drop_zone_view.js @@ -6,7 +6,7 @@ import { decrement, increment } from '@mail/model/model_field_command'; registerModel({ name: 'DropZoneView', - identifyingFields: [['chatterOwner', 'composerViewOwner']], + identifyingMode: 'xor', recordMethods: { /** * Shows a visual drop effect when dragging inside the dropzone. @@ -94,10 +94,12 @@ registerModel({ }, fields: { chatterOwner: one('Chatter', { + identifying: true, inverse: 'dropZoneView', readonly: true, }), composerViewOwner: one('ComposerView', { + identifying: true, inverse: 'dropZoneView', readonly: true, }), diff --git a/addons/mail/static/src/models/emoji.js b/addons/mail/static/src/models/emoji.js index 25cb3ceec20..a8c2d955ae7 100644 --- a/addons/mail/static/src/models/emoji.js +++ b/addons/mail/static/src/models/emoji.js @@ -6,7 +6,6 @@ import { replace } from '@mail/model/model_field_command'; registerModel({ name: 'Emoji', - identifyingFields: ['unicode'], recordMethods: { /** * @private @@ -38,6 +37,7 @@ registerModel({ readonly: true, }), unicode: attr({ + identifying: true, readonly: true, required: true, }), diff --git a/addons/mail/static/src/models/emoji_category.js b/addons/mail/static/src/models/emoji_category.js index 980a9732d73..fc7ef2fced5 100644 --- a/addons/mail/static/src/models/emoji_category.js +++ b/addons/mail/static/src/models/emoji_category.js @@ -5,12 +5,12 @@ import { attr, many } from '@mail/model/model_field'; registerModel({ name: 'EmojiCategory', - identifyingFields: ['categoryName'], fields: { allEmojis: many('Emoji', { inverse: 'emojiCategories', }), categoryName: attr({ + identifying: true, readonly: true, required: 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 ab2faa19c38..1b7cce4e85e 100644 --- a/addons/mail/static/src/models/emoji_category_bar_view.js +++ b/addons/mail/static/src/models/emoji_category_bar_view.js @@ -6,7 +6,6 @@ import { insertAndReplace, replace } from '@mail/model/model_field_command'; registerModel({ name: 'EmojiCategoryBarView', - identifyingFields: ['emojiPickerViewOwner'], recordMethods: { /** * @private @@ -58,6 +57,7 @@ registerModel({ isCausal: true, }), emojiPickerViewOwner: one('EmojiPickerView', { + identifying: true, inverse: 'emojiCategoryBarView', readonly: true, required: true, diff --git a/addons/mail/static/src/models/emoji_category_view.js b/addons/mail/static/src/models/emoji_category_view.js index d060659cf01..ddf8cbe0f37 100644 --- a/addons/mail/static/src/models/emoji_category_view.js +++ b/addons/mail/static/src/models/emoji_category_view.js @@ -6,9 +6,8 @@ import { replace } from '@mail/model/model_field_command'; registerModel({ name: 'EmojiCategoryView', - identifyingFields: ['emojiCategoryBarViewOwner', 'emojiCategory'], recordMethods: { - /** + /** * @param {MouseEvent} ev */ onClick() { @@ -29,11 +28,13 @@ registerModel({ }, fields: { emojiCategory: one('EmojiCategory', { + identifying: true, inverse: 'emojiCategoryViews', readonly: true, required: true, }), emojiCategoryBarViewOwner: one('EmojiCategoryBarView', { + identifying: true, inverse: 'emojiCategoryViews', readonly: true, required: true, diff --git a/addons/mail/static/src/models/emoji_grid_view.js b/addons/mail/static/src/models/emoji_grid_view.js index bf82755d27a..e8473d6d06f 100644 --- a/addons/mail/static/src/models/emoji_grid_view.js +++ b/addons/mail/static/src/models/emoji_grid_view.js @@ -6,7 +6,6 @@ import { clear, insertAndReplace, replace } from '@mail/model/model_field_comman registerModel({ name: 'EmojiGridView', - identifyingFields: ['emojiPickerViewOwner'], recordMethods: { /** * @private @@ -25,6 +24,7 @@ registerModel({ }, fields: { emojiPickerViewOwner: one('EmojiPickerView', { + identifying: true, inverse: 'emojiGridView', readonly: true, required: true, diff --git a/addons/mail/static/src/models/emoji_picker_view.js b/addons/mail/static/src/models/emoji_picker_view.js index 2b44269ec6a..9d061033ad0 100644 --- a/addons/mail/static/src/models/emoji_picker_view.js +++ b/addons/mail/static/src/models/emoji_picker_view.js @@ -6,7 +6,6 @@ import { insertAndReplace } from '@mail/model/model_field_command'; registerModel({ name: 'EmojiPickerView', - identifyingFields: ['popoverViewOwner'], fields: { emojiCategoryBarView: one('EmojiCategoryBarView', { default: insertAndReplace(), @@ -23,6 +22,7 @@ registerModel({ isCausal: true, }), popoverViewOwner: one('PopoverView', { + identifying: true, inverse: 'emojiPickerView', 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 2320dedff47..e0150656665 100644 --- a/addons/mail/static/src/models/emoji_registry.js +++ b/addons/mail/static/src/models/emoji_registry.js @@ -6,7 +6,6 @@ import { insertAndReplace } from '@mail/model/model_field_command'; registerModel({ name: 'EmojiRegistry', - identifyingFields: ['messaging'], fields: { allEmojis: many('Emoji', { default: insertAndReplace([ diff --git a/addons/mail/static/src/models/emoji_view.js b/addons/mail/static/src/models/emoji_view.js index a95f292a26c..d18f4a7c78c 100644 --- a/addons/mail/static/src/models/emoji_view.js +++ b/addons/mail/static/src/models/emoji_view.js @@ -5,7 +5,6 @@ import { attr, one } from '@mail/model/model_field'; registerModel({ name: 'EmojiView', - identifyingFields: ['emojiGridView', 'emoji'], recordMethods: { /** * @param {MouseEvent} ev @@ -35,11 +34,13 @@ registerModel({ }, fields: { emoji: one('Emoji', { + identifying: true, inverse: 'emojiViews', readonly: true, required: true, }), emojiGridView: one('EmojiGridView', { + identifying: true, inverse: 'emojiViews', readonly: true, required: true, diff --git a/addons/mail/static/src/models/file_uploader.js b/addons/mail/static/src/models/file_uploader.js index 504e05e3d58..b01ce95cc30 100644 --- a/addons/mail/static/src/models/file_uploader.js +++ b/addons/mail/static/src/models/file_uploader.js @@ -16,7 +16,7 @@ const getAttachmentNextTemporaryId = (function () { registerModel({ name: 'FileUploader', - identifyingFields: [['activityView', 'attachmentBoxView', 'chatterOwner', 'composerView']], + identifyingMode: 'xor', recordMethods: { openBrowserFileUploader() { this.fileInput.click(); @@ -188,18 +188,22 @@ registerModel({ }, fields: { activityView: one('ActivityView', { + identifying: true, inverse: 'fileUploader', readonly: true, }), attachmentBoxView: one('AttachmentBoxView', { + identifying: true, inverse: 'fileUploader', readonly: true, }), chatterOwner: one('Chatter', { + identifying: true, inverse: 'fileUploader', readonly: true, }), composerView: one('ComposerView', { + identifying: true, inverse: 'fileUploader', readonly: true, }), diff --git a/addons/mail/static/src/models/follow_button_view.js b/addons/mail/static/src/models/follow_button_view.js index 1d3d3056630..71fb21c76c8 100644 --- a/addons/mail/static/src/models/follow_button_view.js +++ b/addons/mail/static/src/models/follow_button_view.js @@ -6,7 +6,6 @@ import { clear } from '@mail/model/model_field_command'; registerModel({ name: 'FollowButtonView', - identifyingFields: [['chatterOwner']], recordMethods: { /** * @private @@ -64,6 +63,7 @@ registerModel({ }, fields: { chatterOwner: one('Chatter', { + identifying: true, inverse: 'followButtonView', readonly: true, }), diff --git a/addons/mail/static/src/models/follower.js b/addons/mail/static/src/models/follower.js index 5f3eee65f30..48ed5375dcf 100644 --- a/addons/mail/static/src/models/follower.js +++ b/addons/mail/static/src/models/follower.js @@ -6,7 +6,6 @@ import { clear, insert, insertAndReplace, link, replace, unlink } from '@mail/mo registerModel({ name: 'Follower', - identifyingFields: ['id'], modelMethods: { /** * @param {Object} data @@ -184,6 +183,7 @@ registerModel({ isCausal: true, }), id: attr({ + identifying: true, readonly: true, required: true, }), 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 7600cd5a9c1..bfdee8a5427 100644 --- a/addons/mail/static/src/models/follower_list_menu_view.js +++ b/addons/mail/static/src/models/follower_list_menu_view.js @@ -6,7 +6,6 @@ import { insertAndReplace, replace } from '@mail/model/model_field_command'; registerModel({ name: 'FollowerListMenuView', - identifyingFields: [['chatterOwner']], recordMethods: { hide() { this.update({ isDropdownOpen: false }); @@ -48,6 +47,7 @@ registerModel({ }, fields: { chatterOwner: one('Chatter', { + identifying: true, inverse: 'followerListMenuView', readonly: true, }), diff --git a/addons/mail/static/src/models/follower_subtype.js b/addons/mail/static/src/models/follower_subtype.js index 4484012bfd3..3ddc066fe7f 100644 --- a/addons/mail/static/src/models/follower_subtype.js +++ b/addons/mail/static/src/models/follower_subtype.js @@ -5,7 +5,6 @@ import { attr, many } from '@mail/model/model_field'; registerModel({ name: 'FollowerSubtype', - identifyingFields: ['id'], modelMethods: { /** * @param {Object} data @@ -43,6 +42,7 @@ registerModel({ isCausal: true, }), id: attr({ + identifying: true, readonly: true, required: true, }), diff --git a/addons/mail/static/src/models/follower_subtype_list.js b/addons/mail/static/src/models/follower_subtype_list.js index f770e81c0e2..68c552b3bb8 100644 --- a/addons/mail/static/src/models/follower_subtype_list.js +++ b/addons/mail/static/src/models/follower_subtype_list.js @@ -6,7 +6,6 @@ import { clear, insertAndReplace, replace } from '@mail/model/model_field_comman registerModel({ name: 'FollowerSubtypeList', - identifyingFields: ['dialogOwner'], recordMethods: { /** * Returns whether the given html element is inside this follower subtype list. @@ -68,6 +67,7 @@ registerModel({ * States the dialog displaying this follower subtype list. */ dialogOwner: one('Dialog', { + identifying: true, inverse: 'followerSubtypeList', isCausal: true, readonly: true, diff --git a/addons/mail/static/src/models/follower_subtype_view.js b/addons/mail/static/src/models/follower_subtype_view.js index 6c195e921a9..38e452d86c5 100644 --- a/addons/mail/static/src/models/follower_subtype_view.js +++ b/addons/mail/static/src/models/follower_subtype_view.js @@ -5,7 +5,6 @@ import { one } from '@mail/model/model_field'; registerModel({ name: 'FollowerSubtypeView', - identifyingFields: ['followerSubtypeListOwner', 'subtype'], recordMethods: { /** * Called when clicking on cancel button. @@ -25,11 +24,13 @@ registerModel({ related: 'followerSubtypeListOwner.follower', }), followerSubtypeListOwner: one('FollowerSubtypeList', { + identifying: true, inverse: 'followerSubtypeViews', readonly: true, required: true, }), subtype: one('FollowerSubtype', { + identifying: true, inverse: 'followerSubtypeViews', readonly: true, required: true, diff --git a/addons/mail/static/src/models/follower_view.js b/addons/mail/static/src/models/follower_view.js index 23f88641e3d..7d483c80d37 100644 --- a/addons/mail/static/src/models/follower_view.js +++ b/addons/mail/static/src/models/follower_view.js @@ -5,7 +5,6 @@ import { one } from '@mail/model/model_field'; registerModel({ name: 'FollowerView', - identifyingFields: ['followerListMenuViewOwner', 'follower'], recordMethods: { /** * @param {MouseEvent} ev @@ -38,11 +37,13 @@ registerModel({ }, fields: { follower: one('Follower', { + identifying: true, inverse: 'followerViews', readonly: true, required: true, }), followerListMenuViewOwner: one('FollowerListMenuView', { + identifying: true, inverse: 'followerViews', readonly: true, required: true, diff --git a/addons/mail/static/src/models/guest.js b/addons/mail/static/src/models/guest.js index 08c0c8cb76c..97ca34790f9 100644 --- a/addons/mail/static/src/models/guest.js +++ b/addons/mail/static/src/models/guest.js @@ -6,7 +6,6 @@ import { insertAndReplace } from '@mail/model/model_field_command'; registerModel({ name: 'Guest', - identifyingFields: ['id'], modelMethods: { /** * @param {Object} param0 @@ -47,6 +46,7 @@ registerModel({ compute: '_computeAvatarUrl', }), id: attr({ + identifying: true, required: true, readonly: true, }), diff --git a/addons/mail/static/src/models/ir_model.js b/addons/mail/static/src/models/ir_model.js index 8efcb543023..f5c0187f0f8 100644 --- a/addons/mail/static/src/models/ir_model.js +++ b/addons/mail/static/src/models/ir_model.js @@ -5,7 +5,6 @@ import { attr, one } from '@mail/model/model_field'; registerModel({ name: 'ir.model', - identifyingFields: ['id'], recordMethods: { /** * @private @@ -28,6 +27,7 @@ registerModel({ }), iconUrl: attr(), id: attr({ + identifying: true, required: true, readonly: true, }), diff --git a/addons/mail/static/src/models/locale.js b/addons/mail/static/src/models/locale.js index 98cc402a36f..da891d8e49f 100644 --- a/addons/mail/static/src/models/locale.js +++ b/addons/mail/static/src/models/locale.js @@ -7,7 +7,6 @@ import { localization } from '@web/core/l10n/localization'; registerModel({ name: 'Locale', - identifyingFields: ['messaging'], recordMethods: { /** * @private diff --git a/addons/mail/static/src/models/mail_template.js b/addons/mail/static/src/models/mail_template.js index 0c28e1d0d4e..16bba89aebf 100644 --- a/addons/mail/static/src/models/mail_template.js +++ b/addons/mail/static/src/models/mail_template.js @@ -5,7 +5,6 @@ import { attr, many } from '@mail/model/model_field'; registerModel({ name: 'MailTemplate', - identifyingFields: ['id'], recordMethods: { /** * @param {Activity} activity @@ -50,6 +49,7 @@ registerModel({ inverse: 'mailTemplates', }), id: attr({ + identifying: true, readonly: true, required: true, }), diff --git a/addons/mail/static/src/models/mail_template_view.js b/addons/mail/static/src/models/mail_template_view.js index 02c8d784781..ebf30deb15c 100644 --- a/addons/mail/static/src/models/mail_template_view.js +++ b/addons/mail/static/src/models/mail_template_view.js @@ -5,7 +5,6 @@ import { one } from '@mail/model/model_field'; registerModel({ name: 'MailTemplateView', - identifyingFields: ['activityViewOwner', 'mailTemplate'], recordMethods: { /** * @param {MouseEvent} ev @@ -26,11 +25,13 @@ registerModel({ }, fields: { activityViewOwner: one('ActivityView', { + identifying: true, inverse: 'mailTemplateViews', readonly: true, required: true, }), mailTemplate: one('MailTemplate', { + identifying: true, readonly: true, required: true, }), diff --git a/addons/mail/static/src/models/mailbox.js b/addons/mail/static/src/models/mailbox.js index ce1631a76ef..c55e69a5a21 100644 --- a/addons/mail/static/src/models/mailbox.js +++ b/addons/mail/static/src/models/mailbox.js @@ -7,7 +7,7 @@ import { OnChange } from '@mail/model/model_onchange'; registerModel({ name: 'Mailbox', - identifyingFields: [['messagingAsHistory', 'messagingAsInbox', 'messagingAsStarred']], + identifyingMode: 'xor', recordMethods: { /** * @returns {string|FieldCommand} @@ -116,14 +116,17 @@ registerModel({ inverse: 'allMailboxes', }), messagingAsHistory: one('Messaging', { + identifying: true, inverse: 'history', readonly: true, }), messagingAsInbox: one('Messaging', { + identifying: true, inverse: 'inbox', readonly: true, }), messagingAsStarred: one('Messaging', { + identifying: true, inverse: 'starred', readonly: true, }), diff --git a/addons/mail/static/src/models/message.js b/addons/mail/static/src/models/message.js index d46f30a4782..065e31fd00e 100644 --- a/addons/mail/static/src/models/message.js +++ b/addons/mail/static/src/models/message.js @@ -13,7 +13,6 @@ const { markup } = owl; registerModel({ name: 'Message', - identifyingFields: ['id'], modelMethods: { /** * @param {Object} data @@ -690,6 +689,7 @@ registerModel({ compute: '_computeHasReactionIcon', }), id: attr({ + identifying: true, readonly: true, required: true, }), diff --git a/addons/mail/static/src/models/message_action_list.js b/addons/mail/static/src/models/message_action_list.js index 03f18a996cd..ec1e430d73b 100644 --- a/addons/mail/static/src/models/message_action_list.js +++ b/addons/mail/static/src/models/message_action_list.js @@ -7,7 +7,6 @@ import { markEventHandled } from '@mail/utils/utils'; registerModel({ name: 'MessageActionList', - identifyingFields: ['messageView'], recordMethods: { /** * @private @@ -186,6 +185,7 @@ registerModel({ * States the message view that controls this message action list. */ messageView: one('MessageView', { + identifying: true, inverse: 'messageActionList', readonly: true, required: true, diff --git a/addons/mail/static/src/models/message_author_prefix_view.js b/addons/mail/static/src/models/message_author_prefix_view.js index 7c8f0f6b081..63c5ff74f84 100644 --- a/addons/mail/static/src/models/message_author_prefix_view.js +++ b/addons/mail/static/src/models/message_author_prefix_view.js @@ -6,7 +6,7 @@ import { clear, replace } from '@mail/model/model_field_command'; registerModel({ name: 'MessageAuthorPrefixView', - identifyingFields: [['threadNeedactionPreviewViewOwner', 'threadPreviewViewOwner']], + identifyingMode: 'xor', recordMethods: { /** * @private @@ -43,10 +43,12 @@ registerModel({ compute: '_computeThread', }), threadNeedactionPreviewViewOwner: one('ThreadNeedactionPreviewView', { + identifying: true, inverse: 'messageAuthorPrefixView', readonly: true, }), threadPreviewViewOwner: one('ThreadPreviewView', { + identifying: true, inverse: 'messageAuthorPrefixView', readonly: true, }), diff --git a/addons/mail/static/src/models/message_in_reply_to_view.js b/addons/mail/static/src/models/message_in_reply_to_view.js index 798f365a7b3..455b8f924e4 100644 --- a/addons/mail/static/src/models/message_in_reply_to_view.js +++ b/addons/mail/static/src/models/message_in_reply_to_view.js @@ -7,7 +7,6 @@ import { markEventHandled } from '@mail/utils/utils'; registerModel({ name: 'MessageInReplyToView', - identifyingFields: ['messageView'], recordMethods: { /** * @private @@ -60,6 +59,7 @@ registerModel({ compute: '_computeHasBodyBackLink', }), messageView: one('MessageView', { + identifying: true, inverse: 'messageInReplyToView', readonly: true, required: true, diff --git a/addons/mail/static/src/models/message_list_view.js b/addons/mail/static/src/models/message_list_view.js index f16e8523031..fae14f9b9ac 100644 --- a/addons/mail/static/src/models/message_list_view.js +++ b/addons/mail/static/src/models/message_list_view.js @@ -6,7 +6,6 @@ import { clear, insertAndReplace, replace } from '@mail/model/model_field_comman registerModel({ name: 'MessageListView', - identifyingFields: ['threadViewOwner'], recordMethods: { /** * @returns {Element|undefined} @@ -125,6 +124,7 @@ registerModel({ related: 'threadViewOwner.thread', }), threadViewOwner: one('ThreadView', { + identifying: true, inverse: 'messageListView', readonly: true, required: true, 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 9ed502b8c71..d8e1e0a5348 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 @@ -10,17 +10,18 @@ import { insertAndReplace } from '@mail/model/model_field_command'; */ registerModel({ name: 'MessageListViewMessageViewItem', - identifyingFields: ['messageListViewOwner', 'message'], fields: { isSquashed: attr({ required: true, }), message: one('Message', { + identifying: true, inverse: 'messageListViewMessageViewItems', readonly: true, required: true, }), messageListViewOwner: one('MessageListView', { + identifying: true, inverse: 'messageListViewMessageViewItems', readonly: true, required: true, diff --git a/addons/mail/static/src/models/message_reaction_group.js b/addons/mail/static/src/models/message_reaction_group.js index e2a028f7721..da7197da1b0 100644 --- a/addons/mail/static/src/models/message_reaction_group.js +++ b/addons/mail/static/src/models/message_reaction_group.js @@ -8,7 +8,6 @@ import { sprintf } from '@web/core/utils/strings'; registerModel({ name: 'MessageReactionGroup', - identifyingFields: ['message', 'content'], recordMethods: { /** * Handles click on the reaction group. @@ -75,6 +74,7 @@ registerModel({ }, fields: { content: attr({ + identifying: true, readonly: true, required: true, }), @@ -91,6 +91,7 @@ registerModel({ }), message: one('Message', { compute: '_computeMessage', + identifying: true, inverse: 'messageReactionGroups', readonly: true, required: true, diff --git a/addons/mail/static/src/models/message_seen_indicator.js b/addons/mail/static/src/models/message_seen_indicator.js index 236ce7b4d73..00e8e3273dd 100644 --- a/addons/mail/static/src/models/message_seen_indicator.js +++ b/addons/mail/static/src/models/message_seen_indicator.js @@ -7,7 +7,6 @@ import { sprintf } from '@web/core/utils/strings'; registerModel({ name: 'MessageSeenIndicator', - identifyingFields: ['thread', 'message'], recordMethods: { /** * Manually called as not always called when necessary @@ -258,6 +257,7 @@ registerModel({ * The message concerned by this seen indicator. */ message: one('Message', { + identifying: true, readonly: true, required: true, }), @@ -275,6 +275,7 @@ registerModel({ * The thread concerned by this seen indicator. */ thread: one('Thread', { + identifying: true, inverse: 'messageSeenIndicators', readonly: true, required: 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 6c3ddeaa6eb..38f4c3081fd 100644 --- a/addons/mail/static/src/models/message_seen_indicator_view.js +++ b/addons/mail/static/src/models/message_seen_indicator_view.js @@ -6,7 +6,6 @@ import { clear, insertAndReplace, replace } from '@mail/model/model_field_comman registerModel({ name: 'MessageSeenIndicatorView', - identifyingFields: ['messageViewOwner'], recordMethods: { /** * @private @@ -24,6 +23,7 @@ registerModel({ }, fields: { messageViewOwner: one('MessageView', { + identifying: true, inverse: 'messageSeenIndicatorView', readonly: true, required: true, diff --git a/addons/mail/static/src/models/message_view.js b/addons/mail/static/src/models/message_view.js index f825202968b..e8dafc84e6d 100644 --- a/addons/mail/static/src/models/message_view.js +++ b/addons/mail/static/src/models/message_view.js @@ -7,7 +7,7 @@ import { isEventHandled, markEventHandled } from '@mail/utils/utils'; registerModel({ name: 'MessageView', - identifyingFields: [['messageListViewMessageViewItemOwner', 'deleteMessageConfirmViewOwner']], + identifyingMode: 'xor', recordMethods: { /** * Briefly highlights the message. @@ -471,6 +471,7 @@ registerModel({ * message view. */ deleteMessageConfirmViewOwner: one('DeleteMessageConfirmView', { + identifying: true, inverse: 'messageView', readonly: true, }), @@ -597,6 +598,7 @@ registerModel({ readonly: true, }), messageListViewMessageViewItemOwner: one('MessageListViewMessageViewItem', { + identifying: true, inverse: 'messageView', readonly: true, }), diff --git a/addons/mail/static/src/models/messaging.js b/addons/mail/static/src/models/messaging.js index 7905208d9a8..6f3e0ebedc7 100644 --- a/addons/mail/static/src/models/messaging.js +++ b/addons/mail/static/src/models/messaging.js @@ -12,7 +12,6 @@ const { EventBus } = owl; registerModel({ name: 'Messaging', - identifyingFields: [], lifecycleHooks: { _created() { odoo.__DEBUG__.messaging = this; diff --git a/addons/mail/static/src/models/messaging_initializer.js b/addons/mail/static/src/models/messaging_initializer.js index 8662bc57c23..75b78787357 100644 --- a/addons/mail/static/src/models/messaging_initializer.js +++ b/addons/mail/static/src/models/messaging_initializer.js @@ -6,7 +6,6 @@ import { link, insert, replace } from '@mail/model/model_field_command'; registerModel({ name: 'MessagingInitializer', - identifyingFields: ['messaging'], recordMethods: { /** * @returns {Object} diff --git a/addons/mail/static/src/models/messaging_menu.js b/addons/mail/static/src/models/messaging_menu.js index ea8346fcec6..d6df1c06ea4 100644 --- a/addons/mail/static/src/models/messaging_menu.js +++ b/addons/mail/static/src/models/messaging_menu.js @@ -6,7 +6,6 @@ import { clear, insertAndReplace } from '@mail/model/model_field_command'; registerModel({ name: 'MessagingMenu', - identifyingFields: ['messaging'], lifecycleHooks: { _created() { document.addEventListener('click', this._onClickCaptureGlobal, true); diff --git a/addons/mail/static/src/models/messaging_notification_handler.js b/addons/mail/static/src/models/messaging_notification_handler.js index 01e76cb4c63..9ad914f80b9 100644 --- a/addons/mail/static/src/models/messaging_notification_handler.js +++ b/addons/mail/static/src/models/messaging_notification_handler.js @@ -13,7 +13,6 @@ const PREVIEW_MSG_MAX_SIZE = 350; // optimal for native English speakers registerModel({ name: 'MessagingNotificationHandler', - identifyingFields: ['messaging'], lifecycleHooks: { _willDelete() { this.env.services['bus_service'].removeEventListener('notification', this._handleNotifications); diff --git a/addons/mail/static/src/models/mobile_messaging_navbar_view.js b/addons/mail/static/src/models/mobile_messaging_navbar_view.js index 3965b979ffd..d0fe4aefbb6 100644 --- a/addons/mail/static/src/models/mobile_messaging_navbar_view.js +++ b/addons/mail/static/src/models/mobile_messaging_navbar_view.js @@ -6,7 +6,7 @@ import { clear, replace } from '@mail/model/model_field_command'; registerModel({ name: 'MobileMessagingNavbarView', - identifyingFields: [['discuss', 'messagingMenu']], + identifyingMode: 'xor', recordMethods: { /** * @param {string} tabId @@ -97,10 +97,12 @@ registerModel({ compute: '_computeActiveTabId', }), discuss: one('Discuss', { + identifying: true, inverse: 'mobileMessagingNavbarView', readonly: true, }), messagingMenu: one('MessagingMenu', { + identifying: true, inverse: 'mobileMessagingNavbarView', readonly: true, }), diff --git a/addons/mail/static/src/models/notification.js b/addons/mail/static/src/models/notification.js index 7f05dab2796..61acab0c8fe 100644 --- a/addons/mail/static/src/models/notification.js +++ b/addons/mail/static/src/models/notification.js @@ -6,7 +6,6 @@ import { clear, insert, insertAndReplace } from '@mail/model/model_field_command registerModel({ name: 'Notification', - identifyingFields: ['id'], modelMethods: { /** * @param {Object} data @@ -131,6 +130,7 @@ registerModel({ compute: '_computeIconTitle', }), id: attr({ + identifying: true, readonly: true, required: true, }), diff --git a/addons/mail/static/src/models/notification_group.js b/addons/mail/static/src/models/notification_group.js index fd8f2600927..3e8fda6e3e8 100644 --- a/addons/mail/static/src/models/notification_group.js +++ b/addons/mail/static/src/models/notification_group.js @@ -7,7 +7,6 @@ import { OnChange } from '@mail/model/model_onchange'; registerModel({ name: 'NotificationGroup', - identifyingFields: ['res_model', 'res_id', 'notification_type'], recordMethods: { /** * Cancel notifications of the group. @@ -113,6 +112,7 @@ registerModel({ compute: '_computeDate', }), notification_type: attr({ + identifying: true, readonly: true, }), notifications: many('Notification', { @@ -123,9 +123,11 @@ registerModel({ isCausal: true, }), res_id: attr({ + identifying: true, readonly: true, }), res_model: attr({ + identifying: true, readonly: true, }), res_model_name: attr(), diff --git a/addons/mail/static/src/models/notification_group_view.js b/addons/mail/static/src/models/notification_group_view.js index 379c5fbd240..2289c857920 100644 --- a/addons/mail/static/src/models/notification_group_view.js +++ b/addons/mail/static/src/models/notification_group_view.js @@ -6,7 +6,6 @@ import { clear } from '@mail/model/model_field_command'; registerModel({ name: 'NotificationGroupView', - identifyingFields: ['notificationListViewOwner', 'notificationGroup'], recordMethods: { /** * @param {MouseEvent} ev @@ -52,11 +51,13 @@ registerModel({ */ markAsReadRef: attr(), notificationGroup: one('NotificationGroup', { + identifying: true, inverse: 'notificationGroupViews', readonly: true, required: true, }), notificationListViewOwner: one('NotificationListView', { + identifying: true, inverse: 'notificationGroupViews', readonly: true, required: true, diff --git a/addons/mail/static/src/models/notification_list_view.js b/addons/mail/static/src/models/notification_list_view.js index 0d792b0d914..6baca763e19 100644 --- a/addons/mail/static/src/models/notification_list_view.js +++ b/addons/mail/static/src/models/notification_list_view.js @@ -6,7 +6,7 @@ import { clear, insertAndReplace, replace } from '@mail/model/model_field_comman registerModel({ name: 'NotificationListView', - identifyingFields: [['discussOwner', 'messagingMenuOwner']], + identifyingMode: 'xor', lifecycleHooks: { _created() { this._loadPreviews(); @@ -180,6 +180,7 @@ registerModel({ }, fields: { discussOwner: one('Discuss', { + identifying: true, inverse: 'notificationListView', readonly: true, }), @@ -190,6 +191,7 @@ registerModel({ compute: '_computeFilteredThreads', }), messagingMenuOwner: one('MessagingMenu', { + identifying: true, inverse: 'notificationListView', readonly: true, }), diff --git a/addons/mail/static/src/models/notification_request_view.js b/addons/mail/static/src/models/notification_request_view.js index c7cd26be35f..0029623498b 100644 --- a/addons/mail/static/src/models/notification_request_view.js +++ b/addons/mail/static/src/models/notification_request_view.js @@ -8,7 +8,6 @@ import { sprintf } from '@web/core/utils/strings'; registerModel({ name: 'NotificationRequestView', - identifyingFields: ['notificationListViewOwner'], recordMethods: { /** * @private @@ -36,6 +35,7 @@ registerModel({ compute: '_computeHeaderText', }), notificationListViewOwner: one('NotificationListView', { + identifying: true, inverse: 'notificationRequestView', required: true, readonly: true, 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 45af67e5f39..6c89d9f8367 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 @@ -6,10 +6,6 @@ import { insertAndReplace } from '@mail/model/model_field_command'; registerModel({ name: 'OtherMemberLongTypingInThreadTimer', - identifyingFields: [ - 'partner', - 'thread', - ], recordMethods: { onOtherMemberLongTypingTimeout() { this.thread.unregisterOtherMemberTypingMember(this.partner); @@ -17,11 +13,13 @@ registerModel({ }, fields: { partner: one('Partner', { + identifying: true, inverse: 'otherMemberLongTypingInThreadTimers', readonly: true, required: true, }), thread: one('Thread', { + identifying: true, inverse: 'otherMembersLongTypingTimers', readonly: true, required: true, diff --git a/addons/mail/static/src/models/partner.js b/addons/mail/static/src/models/partner.js index bee98ec5222..e4f276d0b9c 100644 --- a/addons/mail/static/src/models/partner.js +++ b/addons/mail/static/src/models/partner.js @@ -7,7 +7,6 @@ import { cleanSearchTerm } from '@mail/utils/utils'; registerModel({ name: 'Partner', - identifyingFields: ['id'], modelMethods: { /** * @param {Object} data @@ -409,6 +408,7 @@ registerModel({ default: false, }), id: attr({ + identifying: true, readonly: true, required: true, }), diff --git a/addons/mail/static/src/models/persona.js b/addons/mail/static/src/models/persona.js index 2e644b120b3..e3ddee8e2f6 100644 --- a/addons/mail/static/src/models/persona.js +++ b/addons/mail/static/src/models/persona.js @@ -6,7 +6,7 @@ import { clear } from '@mail/model/model_field_command'; registerModel({ name: 'Persona', - identifyingFields: [['guest', 'partner']], + identifyingMode: 'xor', recordMethods: { /** * @private @@ -41,6 +41,7 @@ registerModel({ isCausal: true, }), guest: one('Guest', { + identifying: true, inverse: 'persona', readonly: true, }), @@ -53,6 +54,7 @@ registerModel({ readonly: true, }), partner: one('Partner', { + identifying: true, inverse: 'persona', readonly: true, }), diff --git a/addons/mail/static/src/models/persona_im_status_icon_view.js b/addons/mail/static/src/models/persona_im_status_icon_view.js index 08bbaf32652..2bd2e160c8c 100644 --- a/addons/mail/static/src/models/persona_im_status_icon_view.js +++ b/addons/mail/static/src/models/persona_im_status_icon_view.js @@ -6,15 +6,7 @@ import { clear, replace } from '@mail/model/model_field_command'; registerModel({ name: 'PersonaImStatusIconView', - identifyingFields: [[ - 'channelInvitationFormSelectablePartnerViewOwner', - 'channelMemberViewOwner', - 'composerSuggestionViewOwner', - 'messageViewOwner', - 'notificationRequestViewOwner', - 'threadNeedactionPreviewViewOwner', - 'threadPreviewViewOwner', - ]], + identifyingMode: 'xor', recordMethods: { /** * @private @@ -52,30 +44,37 @@ registerModel({ }, fields: { channelInvitationFormSelectablePartnerViewOwner: one('ChannelInvitationFormSelectablePartnerView', { + identifying: true, inverse: 'personaImStatusIconView', readonly: true, }), channelMemberViewOwner: one('ChannelMemberView', { + identifying: true, inverse: 'personaImStatusIconView', readonly: true, }), composerSuggestionViewOwner: one('ComposerSuggestionView', { + identifying: true, inverse: 'personaImStatusIconView', readonly: true, }), messageViewOwner: one('MessageView', { + identifying: true, inverse: 'personaImStatusIconView', readonly: true, }), notificationRequestViewOwner: one('NotificationRequestView', { + identifying: true, inverse: 'personaImStatusIconView', readonly: true, }), threadNeedactionPreviewViewOwner: one('ThreadNeedactionPreviewView', { + identifying: true, inverse: 'personaImStatusIconView', readonly: true, }), threadPreviewViewOwner: one('ThreadPreviewView', { + identifying: true, inverse: 'personaImStatusIconView', readonly: true, }), diff --git a/addons/mail/static/src/models/popover_manager.js b/addons/mail/static/src/models/popover_manager.js index cd94df48090..e0dad71a892 100644 --- a/addons/mail/static/src/models/popover_manager.js +++ b/addons/mail/static/src/models/popover_manager.js @@ -5,7 +5,6 @@ import { many } from '@mail/model/model_field'; registerModel({ name: 'PopoverManager', - identifyingFields: ['messaging'], fields: { // FIXME: dependent on implementation that uses insert order in relations!! popoverViews: many('PopoverView', { diff --git a/addons/mail/static/src/models/popover_view.js b/addons/mail/static/src/models/popover_view.js index 03ec734d4a0..1af74bdf72b 100644 --- a/addons/mail/static/src/models/popover_view.js +++ b/addons/mail/static/src/models/popover_view.js @@ -6,7 +6,7 @@ import { clear, insertAndReplace, replace } from '@mail/model/model_field_comman registerModel({ name: 'PopoverView', - identifyingFields: [['activityViewOwnerAsMarkDone', 'composerViewOwnerAsEmoji', 'messageActionListOwnerAsReaction', 'threadViewTopbarOwnerAsInvite']], + identifyingMode: 'xor', lifecycleHooks: { _created() { document.addEventListener('click', this._onClickCaptureGlobal, true); @@ -179,6 +179,7 @@ registerModel({ readonly: true, }), activityViewOwnerAsMarkDone: one('ActivityView', { + identifying: true, inverse: 'markDonePopoverView', readonly: true, }), @@ -206,6 +207,7 @@ registerModel({ * If set, this popover view is owned by a composer view. */ composerViewOwnerAsEmoji: one('ComposerView', { + identifying: true, inverse: 'emojisPopoverView', readonly: true, }), @@ -250,6 +252,7 @@ registerModel({ * If set, this popover view is owned by a message action list. */ messageActionListOwnerAsReaction: one('MessageActionList', { + identifying: true, inverse: 'reactionPopoverView', readonly: true, }), @@ -265,6 +268,7 @@ registerModel({ * If set, this popover view is owned by a thread view topbar record. */ threadViewTopbarOwnerAsInvite: one('ThreadViewTopbar', { + identifying: true, inverse: 'invitePopoverView', readonly: true, }), diff --git a/addons/mail/static/src/models/record.js b/addons/mail/static/src/models/record.js index 32b9dde49b4..6ede22fd9f2 100644 --- a/addons/mail/static/src/models/record.js +++ b/addons/mail/static/src/models/record.js @@ -16,14 +16,6 @@ registerModel({ * relational fields. Name of models must be unique. */ name: 'Record', - /** - * Determines which fields are identifying fields for this model. Must be - * overwritten in actual models. This should be a list of either field name - * or sub-list of field name. Each top level element will be parsed as "and" - * and each element of the same sub-list will be parsed as "or". If there - * is no identifying fields, this model generates a singleton. - */ - identifyingFields: ['messaging'], lifecycleHooks: { /** * This function is called after the record has been created, more diff --git a/addons/mail/static/src/models/res_users_settings.js b/addons/mail/static/src/models/res_users_settings.js index 951d31e4dc4..45cf357b7ed 100644 --- a/addons/mail/static/src/models/res_users_settings.js +++ b/addons/mail/static/src/models/res_users_settings.js @@ -8,9 +8,9 @@ import { attr, many, one } from '@mail/model/model_field'; */ registerModel({ name: 'res.users.settings', - identifyingFields: ['id'], fields: { id: attr({ + identifying: true, readonly: true, required: true, }), diff --git a/addons/mail/static/src/models/res_users_settings_volumes.js b/addons/mail/static/src/models/res_users_settings_volumes.js index e15a4002eee..afd02012b06 100644 --- a/addons/mail/static/src/models/res_users_settings_volumes.js +++ b/addons/mail/static/src/models/res_users_settings_volumes.js @@ -9,7 +9,6 @@ import { OnChange } from '@mail/model/model_onchange'; */ registerModel({ name: 'res.users.settings.volumes', - identifyingFields: ['id'], recordMethods: { /** * @private @@ -31,6 +30,7 @@ registerModel({ inverse: 'volumeSetting', }), id: attr({ + identifying: true, readonly: true, required: true, }), diff --git a/addons/mail/static/src/models/rtc.js b/addons/mail/static/src/models/rtc.js index e6abfcb2eeb..08d82bc667e 100644 --- a/addons/mail/static/src/models/rtc.js +++ b/addons/mail/static/src/models/rtc.js @@ -18,7 +18,6 @@ const getRTCPeerNotificationNextTemporaryId = (function () { registerModel({ name: 'Rtc', - identifyingFields: ['messaging'], lifecycleHooks: { _created() { browser.addEventListener('keydown', this._onKeyDown); diff --git a/addons/mail/static/src/models/rtc_data_channel.js b/addons/mail/static/src/models/rtc_data_channel.js index e7e7347fa07..3ab6cf21453 100644 --- a/addons/mail/static/src/models/rtc_data_channel.js +++ b/addons/mail/static/src/models/rtc_data_channel.js @@ -5,7 +5,6 @@ import { attr, one } from '@mail/model/model_field'; registerModel({ name: 'RtcDataChannel', - identifyingFields: ['rtcSession'], lifecycleHooks: { _willDelete() { this.dataChannel.close(); @@ -17,6 +16,7 @@ registerModel({ readonly: true, }), rtcSession: one('RtcSession', { + identifying: true, inverse: 'rtcDataChannel', readonly: true, required: true, diff --git a/addons/mail/static/src/models/rtc_peer_connection.js b/addons/mail/static/src/models/rtc_peer_connection.js index 12b6e40b359..892074173b7 100644 --- a/addons/mail/static/src/models/rtc_peer_connection.js +++ b/addons/mail/static/src/models/rtc_peer_connection.js @@ -6,7 +6,6 @@ import { OnChange } from '@mail/model/model_onchange'; registerModel({ name: 'RtcPeerConnection', - identifyingFields: ['rtcSession'], lifecycleHooks: { _willDelete() { this.peerConnection.close(); @@ -59,6 +58,7 @@ registerModel({ */ peerConnection: attr(), rtcSession: one('RtcSession', { + identifying: true, inverse: 'rtcPeerConnection', readonly: true, required: true, diff --git a/addons/mail/static/src/models/rtc_peer_notification.js b/addons/mail/static/src/models/rtc_peer_notification.js index 1ac7b69ee19..741708ee106 100644 --- a/addons/mail/static/src/models/rtc_peer_notification.js +++ b/addons/mail/static/src/models/rtc_peer_notification.js @@ -5,7 +5,6 @@ import { attr } from '@mail/model/model_field'; registerModel({ name: 'RtcPeerNotification', - identifyingFields: ['id'], fields: { channelId: attr({ readonly: true, @@ -21,6 +20,7 @@ registerModel({ * given by the creator of this record. */ id: attr({ + identifying: true, readonly: true, required: true, }), diff --git a/addons/mail/static/src/models/rtc_session.js b/addons/mail/static/src/models/rtc_session.js index e453885806b..b7722125a7b 100644 --- a/addons/mail/static/src/models/rtc_session.js +++ b/addons/mail/static/src/models/rtc_session.js @@ -6,7 +6,6 @@ import { clear, insertAndReplace, replace } from '@mail/model/model_field_comman registerModel({ name: 'RtcSession', - identifyingFields: ['id'], lifecycleHooks: { _willDelete() { this.reset(); @@ -380,6 +379,7 @@ registerModel({ * Id of the record on the server. */ id: attr({ + identifying: true, readonly: true, required: true, }), diff --git a/addons/mail/static/src/models/sound_effect.js b/addons/mail/static/src/models/sound_effect.js index 6826151a498..36d7c80d735 100644 --- a/addons/mail/static/src/models/sound_effect.js +++ b/addons/mail/static/src/models/sound_effect.js @@ -5,7 +5,6 @@ import { attr } from '@mail/model/model_field'; registerModel({ name: 'SoundEffect', - identifyingFields: ['path', 'filename'], recordMethods: { /** * @param {Object} param0 @@ -61,6 +60,7 @@ registerModel({ * Name of the audio file. */ filename: attr({ + identifying: true, readonly: true, required: true, }), @@ -69,6 +69,7 @@ registerModel({ */ path: attr({ default: '/mail/static/src/audio/', + identifying: true, readonly: true, required: true, }), diff --git a/addons/mail/static/src/models/sound_effects.js b/addons/mail/static/src/models/sound_effects.js index f5267efa0cf..c7973f318f8 100644 --- a/addons/mail/static/src/models/sound_effects.js +++ b/addons/mail/static/src/models/sound_effects.js @@ -6,7 +6,6 @@ import { insertAndReplace } from '@mail/model/model_field_command'; registerModel({ name: 'SoundEffects', - identifyingFields: ['messaging'], fields: { channelJoin: one('SoundEffect', { default: insertAndReplace({ defaultVolume: 0.3, filename: 'channel_01_in' }), diff --git a/addons/mail/static/src/models/suggested_recipient_info.js b/addons/mail/static/src/models/suggested_recipient_info.js index dbbdc461264..42ca42408d9 100644 --- a/addons/mail/static/src/models/suggested_recipient_info.js +++ b/addons/mail/static/src/models/suggested_recipient_info.js @@ -7,7 +7,6 @@ import { sprintf } from '@web/core/utils/strings'; registerModel({ name: 'SuggestedRecipientInfo', - identifyingFields: ['id'], recordMethods: { /** * @private @@ -65,6 +64,7 @@ registerModel({ * given by the creator of this record. */ id: attr({ + identifying: true, readonly: true, }), /** diff --git a/addons/mail/static/src/models/thread.js b/addons/mail/static/src/models/thread.js index 0ef3e2530e0..907c2b5428e 100644 --- a/addons/mail/static/src/models/thread.js +++ b/addons/mail/static/src/models/thread.js @@ -22,7 +22,6 @@ const getSuggestedRecipientInfoNextTemporaryId = (function () { registerModel({ name: 'Thread', - identifyingFields: ['model', 'id'], lifecycleHooks: { _willDelete() { if (this.isTemporary) { @@ -1949,6 +1948,7 @@ registerModel({ default: false, }), id: attr({ + identifying: true, readonly: true, required: true, }), @@ -2145,6 +2145,7 @@ registerModel({ readonly: true, }), model: attr({ + identifying: true, readonly: true, required: true, }), diff --git a/addons/mail/static/src/models/thread_cache.js b/addons/mail/static/src/models/thread_cache.js index 9284ebfbc05..115415cdc37 100644 --- a/addons/mail/static/src/models/thread_cache.js +++ b/addons/mail/static/src/models/thread_cache.js @@ -7,7 +7,6 @@ import { OnChange } from '@mail/model/model_onchange'; registerModel({ name: 'ThreadCache', - identifyingFields: ['thread'], recordMethods: { async loadMoreMessages() { if (this.isAllHistoryLoaded || this.isLoading) { @@ -359,6 +358,7 @@ registerModel({ compute: '_computeOrderedNonEmptyMessages', }), thread: one('Thread', { + identifying: true, inverse: 'cache', readonly: true, required: 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 ef222d02d20..cde4dbecd2f 100644 --- a/addons/mail/static/src/models/thread_needaction_preview_view.js +++ b/addons/mail/static/src/models/thread_needaction_preview_view.js @@ -7,7 +7,6 @@ import { htmlToTextContentInline } from '@mail/js/utils'; registerModel({ name: 'ThreadNeedactionPreviewView', - identifyingFields: ['notificationListViewOwner', 'thread'], recordMethods: { /** * @param {MouseEvent} ev @@ -109,6 +108,7 @@ registerModel({ isCausal: true, }), notificationListViewOwner: one('NotificationListView', { + identifying: true, inverse: 'threadNeedactionPreviewViews', readonly: true, required: true, @@ -120,6 +120,7 @@ registerModel({ readonly: true, }), thread: one('Thread', { + identifying: true, inverse: 'threadNeedactionPreviewViews', readonly: true, required: true, diff --git a/addons/mail/static/src/models/thread_partner_seen_info.js b/addons/mail/static/src/models/thread_partner_seen_info.js index 02777bc0ae4..2dabe1ff527 100644 --- a/addons/mail/static/src/models/thread_partner_seen_info.js +++ b/addons/mail/static/src/models/thread_partner_seen_info.js @@ -5,7 +5,6 @@ import { one } from '@mail/model/model_field'; registerModel({ name: 'ThreadPartnerSeenInfo', - identifyingFields: ['thread', 'partner'], fields: { lastFetchedMessage: one('Message'), lastSeenMessage: one('Message'), @@ -13,6 +12,7 @@ registerModel({ * Partner that this seen info is related to. */ partner: one('Partner', { + identifying: true, readonly: true, required: true, }), @@ -21,6 +21,7 @@ registerModel({ */ thread: one('Thread', { inverse: 'partnerSeenInfos', + identifying: true, readonly: true, required: true, }), diff --git a/addons/mail/static/src/models/thread_preview_view.js b/addons/mail/static/src/models/thread_preview_view.js index f2dbf34b24e..743028bb07a 100644 --- a/addons/mail/static/src/models/thread_preview_view.js +++ b/addons/mail/static/src/models/thread_preview_view.js @@ -7,7 +7,6 @@ import { htmlToTextContentInline } from '@mail/js/utils'; registerModel({ name: 'ThreadPreviewView', - identifyingFields: ['notificationListViewOwner', 'thread'], recordMethods: { /** * @param {MouseEvent} ev @@ -27,7 +26,7 @@ registerModel({ } }, /** - * @param {MouseEvent} ev + * @param {MouseEvent} ev */ onClickMarkAsRead(ev) { if (this.thread.lastNonTransientMessage) { @@ -107,6 +106,7 @@ registerModel({ isCausal: true, }), notificationListViewOwner: one('NotificationListView', { + identifying: true, inverse: 'threadPreviewViews', readonly: true, required: true, @@ -118,6 +118,7 @@ registerModel({ readonly: true, }), thread: one('Thread', { + identifying: true, inverse: 'threadPreviewViews', readonly: true, required: true, diff --git a/addons/mail/static/src/models/thread_view.js b/addons/mail/static/src/models/thread_view.js index 5cc1f98c1ea..b05671c2eba 100644 --- a/addons/mail/static/src/models/thread_view.js +++ b/addons/mail/static/src/models/thread_view.js @@ -7,7 +7,6 @@ import { OnChange } from '@mail/model/model_onchange'; registerModel({ name: 'ThreadView', - identifyingFields: ['threadViewer'], lifecycleHooks: { _willDelete() { this.messaging.browser.clearTimeout(this.loaderTimeout); @@ -526,6 +525,7 @@ registerModel({ * Determines the `ThreadViewer` currently managing `this`. */ threadViewer: one('ThreadViewer', { + identifying: true, inverse: 'threadView', readonly: true, required: true, diff --git a/addons/mail/static/src/models/thread_view_topbar.js b/addons/mail/static/src/models/thread_view_topbar.js index 770326d6c62..463aaf3cb78 100644 --- a/addons/mail/static/src/models/thread_view_topbar.js +++ b/addons/mail/static/src/models/thread_view_topbar.js @@ -6,7 +6,6 @@ import { clear, insertAndReplace } from '@mail/model/model_field_command'; registerModel({ name: 'ThreadViewTopbar', - identifyingFields: ['threadView'], lifecycleHooks: { _created() { document.addEventListener('click', this._onClickCaptureGlobal, true); @@ -697,6 +696,7 @@ registerModel({ * States the thread view managing this top bar. */ threadView: one('ThreadView', { + identifying: true, inverse: 'topbar', readonly: true, required: true, diff --git a/addons/mail/static/src/models/thread_viewer.js b/addons/mail/static/src/models/thread_viewer.js index d5d85703ec5..77da8ed1c11 100644 --- a/addons/mail/static/src/models/thread_viewer.js +++ b/addons/mail/static/src/models/thread_viewer.js @@ -6,7 +6,7 @@ import { clear, insertAndReplace } from '@mail/model/model_field_command'; registerModel({ name: 'ThreadViewer', - identifyingFields: [['chatter', 'chatWindow', 'discuss', 'discussPublicView']], + identifyingMode: 'xor', recordMethods: { /** * @param {integer} scrollHeight @@ -73,10 +73,12 @@ registerModel({ }, fields: { chatter: one('Chatter', { + identifying: true, inverse: 'threadViewer', readonly: true, }), chatWindow: one('ChatWindow', { + identifying: true, inverse: 'threadViewer', readonly: true, }), @@ -87,10 +89,12 @@ registerModel({ default: false, }), discuss: one('Discuss', { + identifying: true, inverse: 'threadViewer', readonly: true, }), discussPublicView: one('DiscussPublicView', { + identifying: true, inverse: 'threadViewer', readonly: true, }), diff --git a/addons/mail/static/src/models/throttle.js b/addons/mail/static/src/models/throttle.js index 166e896bcfb..bb6accc117b 100644 --- a/addons/mail/static/src/models/throttle.js +++ b/addons/mail/static/src/models/throttle.js @@ -13,9 +13,7 @@ import { clear, insertAndReplace } from '@mail/model/model_field_command'; */ registerModel({ name: 'Throttle', - identifyingFields: [[ - 'threadAsThrottleNotifyCurrentPartnerTypingStatus', - ]], + identifyingMode: 'xor', recordMethods: { /** * Clear any buffered function call and immediately terminates any cooling @@ -73,6 +71,7 @@ registerModel({ default: false, }), threadAsThrottleNotifyCurrentPartnerTypingStatus: one('Thread', { + identifying: true, inverse: 'throttleNotifyCurrentPartnerTypingStatus', readonly: true, }), diff --git a/addons/mail/static/src/models/timer.js b/addons/mail/static/src/models/timer.js index f37389dae4e..2e40eff9ba7 100644 --- a/addons/mail/static/src/models/timer.js +++ b/addons/mail/static/src/models/timer.js @@ -6,17 +6,7 @@ import { clear } from '@mail/model/model_field_command'; registerModel({ name: 'Timer', - identifyingFields: [[ - 'callMainViewAsShowOverlay', - 'chatterOwnerAsAttachmentsLoader', - 'messagingOwnerAsFetchImStatusTimer', - 'messageViewOwnerAsHighlight', - 'otherMemberLongTypingInThreadTimerOwner', - 'rtcSessionOwnerAsBroadcast', - 'threadAsCurrentPartnerInactiveTypingTimerOwner', - 'threadAsCurrentPartnerLongTypingTimerOwner', - 'throttleOwner', - ]], + identifyingMode: 'xor', lifecycleHooks: { _willDelete() { this.messaging.browser.clearTimeout(this.timeoutId); @@ -123,10 +113,12 @@ registerModel({ }, fields: { callMainViewAsShowOverlay: one('CallMainView', { + identifying: true, inverse: 'showOverlayTimer', readonly: true, }), chatterOwnerAsAttachmentsLoader: one('Chatter', { + identifying: true, inverse: 'attachmentsLoaderTimer', readonly: true, }), @@ -140,31 +132,38 @@ registerModel({ required: true, }), messagingOwnerAsFetchImStatusTimer: one('Messaging', { + identifying: true, inverse: 'fetchImStatusTimer', readonly: true, }), messageViewOwnerAsHighlight: one('MessageView', { + identifying: true, inverse: 'highlightTimer', readonly: true, }), otherMemberLongTypingInThreadTimerOwner: one('OtherMemberLongTypingInThreadTimer', { + identifying: true, inverse: 'timer', isCausal: true, readonly: true, }), rtcSessionOwnerAsBroadcast: one('RtcSession', { + identifying: true, inverse: 'broadcastTimer', readonly: true, }), threadAsCurrentPartnerInactiveTypingTimerOwner: one('Thread', { + identifying: true, inverse: 'currentPartnerInactiveTypingTimer', readonly: true, }), threadAsCurrentPartnerLongTypingTimerOwner: one('Thread', { + identifying: true, inverse: 'currentPartnerLongTypingTimer', readonly: true, }), throttleOwner: one('Throttle', { + identifying: true, inverse: 'cooldownTimer', readonly: true, }), diff --git a/addons/mail/static/src/models/tracking_value.js b/addons/mail/static/src/models/tracking_value.js index f71215dc9b1..502ed2ffc15 100644 --- a/addons/mail/static/src/models/tracking_value.js +++ b/addons/mail/static/src/models/tracking_value.js @@ -6,7 +6,6 @@ import { sprintf } from '@web/core/utils/strings'; registerModel({ name: 'TrackingValue', - identifyingFields: ['id'], recordMethods: { /** * @private @@ -30,6 +29,7 @@ registerModel({ compute: '_computeFormattedChangedField', }), id: attr({ + identifying: true, readonly: true, required: true, }), @@ -46,4 +46,5 @@ registerModel({ inverse: 'trackingValueAsOldValue', isCausal: true, }), -}}); + }, +}); diff --git a/addons/mail/static/src/models/tracking_value_item.js b/addons/mail/static/src/models/tracking_value_item.js index 7fc320a15d3..1fc8af8a80f 100644 --- a/addons/mail/static/src/models/tracking_value_item.js +++ b/addons/mail/static/src/models/tracking_value_item.js @@ -12,7 +12,7 @@ const formatters = registry.category("formatters"); registerModel({ name: 'TrackingValueItem', - identifyingFields: [['trackingValueAsNewValue','trackingValueAsOldValue']], + identifyingMode: 'xor', recordMethods: { /** * @private @@ -90,10 +90,12 @@ registerModel({ compute: '_computeFormattedValueOrNone', }), trackingValueAsNewValue: one('TrackingValue', { + identifying: true, inverse: 'newValue', readonly: true, }), trackingValueAsOldValue: one('TrackingValue', { + identifying: true, inverse: 'oldValue', readonly: true, }), @@ -101,4 +103,5 @@ registerModel({ * The original value of the tracking value item. */ value: attr(), -}}); + }, +}); diff --git a/addons/mail/static/src/models/use_drag_visible_drop_zone.js b/addons/mail/static/src/models/use_drag_visible_drop_zone.js index 60404c8e22e..feb0f7ba33b 100644 --- a/addons/mail/static/src/models/use_drag_visible_drop_zone.js +++ b/addons/mail/static/src/models/use_drag_visible_drop_zone.js @@ -6,7 +6,7 @@ import { decrement, increment } from '@mail/model/model_field_command'; registerModel({ name: 'UseDragVisibleDropZone', - identifyingFields: [['chatterOwner', 'composerViewOwner']], + identifyingMode: 'xor', lifecycleHooks: { _created() { document.addEventListener('dragenter', this._onDragenterListener, true); @@ -69,10 +69,12 @@ registerModel({ }, fields: { chatterOwner: one('Chatter', { + identifying: true, inverse: 'useDragVisibleDropZone', readonly: true, }), composerViewOwner: one('ComposerView', { + identifying: true, inverse: 'useDragVisibleDropZone', readonly: true, }), diff --git a/addons/mail/static/src/models/user.js b/addons/mail/static/src/models/user.js index ed78e421ab5..0b1a1757bee 100644 --- a/addons/mail/static/src/models/user.js +++ b/addons/mail/static/src/models/user.js @@ -6,7 +6,6 @@ import { clear, insert } from '@mail/model/model_field_command'; registerModel({ name: 'User', - identifyingFields: ['id'], modelMethods: { /** * @param {Object} data @@ -177,6 +176,7 @@ registerModel({ inverse: 'assignee', }), id: attr({ + identifying: true, readonly: true, required: true, }), diff --git a/addons/mail/static/src/models/user_notification_manager.js b/addons/mail/static/src/models/user_notification_manager.js index ceede6de098..dad8934ad2f 100644 --- a/addons/mail/static/src/models/user_notification_manager.js +++ b/addons/mail/static/src/models/user_notification_manager.js @@ -8,7 +8,6 @@ import { url } from '@web/core/utils/urls'; registerModel({ name: 'UserNotificationManager', - identifyingFields: [], recordMethods: { /** * Send a notification, preferably a native one. If native diff --git a/addons/mail/static/src/models/user_setting.js b/addons/mail/static/src/models/user_setting.js index 59938a10402..30a7a79f241 100644 --- a/addons/mail/static/src/models/user_setting.js +++ b/addons/mail/static/src/models/user_setting.js @@ -14,7 +14,6 @@ import { clear, insertAndReplace } from '@mail/model/model_field_command'; */ registerModel({ name: 'UserSetting', - identifyingFields: ['messaging'], lifecycleHooks: { _created() { this._loadLocalSettings(); diff --git a/addons/mail/static/src/models/web_client_view_attachment_view.js b/addons/mail/static/src/models/web_client_view_attachment_view.js index 9d886b950b0..ec0abddd8fd 100644 --- a/addons/mail/static/src/models/web_client_view_attachment_view.js +++ b/addons/mail/static/src/models/web_client_view_attachment_view.js @@ -8,7 +8,6 @@ import { hidePDFJSButtons } from '@web/legacy/js/libs/pdfjs'; registerModel({ name: 'WebClientViewAttachmentView', - identifyingFields: ['id'], recordMethods: { /** * @param {MouseEvent} ev @@ -57,6 +56,7 @@ registerModel({ fields: { component: attr(), id: attr({ + identifying: true, readonly: true, required: true, }), diff --git a/addons/mail/static/src/models/welcome_view.js b/addons/mail/static/src/models/welcome_view.js index 8ee9214e53f..95e424f3eee 100644 --- a/addons/mail/static/src/models/welcome_view.js +++ b/addons/mail/static/src/models/welcome_view.js @@ -11,7 +11,6 @@ const getNextGuestNameInputId = (function () { registerModel({ name: 'WelcomeView', - identifyingFields: ['discussPublicView'], recordMethods: { /** * Updates guest if needed then displays the thread view instead of the @@ -136,6 +135,7 @@ registerModel({ * States discuss public view on which this welcome view is displayed. */ discussPublicView: one('DiscussPublicView', { + identifying: true, inverse: 'welcomeView', readonly: true, required: true, diff --git a/addons/mail/static/tests/models/clock_watcher_qunit_tests.js b/addons/mail/static/tests/models/clock_watcher_qunit_tests.js index f9f08a24888..8873a3684dc 100644 --- a/addons/mail/static/tests/models/clock_watcher_qunit_tests.js +++ b/addons/mail/static/tests/models/clock_watcher_qunit_tests.js @@ -1,16 +1,13 @@ /** @odoo-module **/ -import { addFields, patchIdentifyingFields } from '@mail/model/model_core'; +import { addFields } from '@mail/model/model_core'; import { one } from '@mail/model/model_field'; // ensure that the model definition is loaded before the patch import '@mail/models/clock_watcher'; -patchIdentifyingFields('ClockWatcher', identifyingFields => { - identifyingFields[0].push('qunitTestOwner'); -}); - addFields('ClockWatcher', { qunitTestOwner: one('QUnitTest', { + identifying: true, inverse: 'clockWatcher', readonly: true, }), diff --git a/addons/mail/static/tests/models/qunit_test.js b/addons/mail/static/tests/models/qunit_test.js index 2d6d6ec4c05..1a70ff68fd7 100644 --- a/addons/mail/static/tests/models/qunit_test.js +++ b/addons/mail/static/tests/models/qunit_test.js @@ -5,7 +5,6 @@ import { one } from '@mail/model/model_field'; registerModel({ name: 'QUnitTest', - identifyingFields: [], // singleton acceptable (only one test at a time) fields: { clockWatcher: one('ClockWatcher', { inverse: 'qunitTestOwner', diff --git a/addons/mail/static/tests/models/test_models.js b/addons/mail/static/tests/models/test_models.js index f128128431a..7f1c0672598 100644 --- a/addons/mail/static/tests/models/test_models.js +++ b/addons/mail/static/tests/models/test_models.js @@ -6,9 +6,9 @@ import { insertAndReplace } from '@mail/model/model_field_command'; registerModel({ name: 'TestAddress', - identifyingFields: ['id'], fields: { id: attr({ + identifying: true, readonly: true, required: true, }), @@ -21,9 +21,9 @@ registerModel({ registerModel({ name: 'TestContact', - identifyingFields: ['id'], fields: { id: attr({ + identifying: true, readonly: true, required: true, }), @@ -47,9 +47,9 @@ registerModel({ registerModel({ name: 'TestHobby', - identifyingFields: ['description'], fields: { description: attr({ + identifying: true, readonly: true, required: true, }), @@ -58,9 +58,9 @@ registerModel({ registerModel({ name: 'TestTask', - identifyingFields: ['id'], fields: { id: attr({ + identifying: true, readonly: true, required: true, }), diff --git a/addons/mail/static/tests/models/throttle_qunit_tests.js b/addons/mail/static/tests/models/throttle_qunit_tests.js index 55784555555..46758d328db 100644 --- a/addons/mail/static/tests/models/throttle_qunit_tests.js +++ b/addons/mail/static/tests/models/throttle_qunit_tests.js @@ -1,26 +1,23 @@ /** @odoo-module **/ -import { addFields, patchIdentifyingFields, patchRecordMethods } from '@mail/model/model_core'; +import { addFields, patchRecordMethods } from '@mail/model/model_core'; import { one } from '@mail/model/model_field'; // ensure that the model definition is loaded before the patch import '@mail/models/throttle'; addFields('Throttle', { qunitTestOwner1: one('QUnitTest', { + identifying: true, inverse: 'throttle1', readonly: true, }), qunitTestOwner2: one('QUnitTest', { + identifying: true, inverse: 'throttle2', readonly: true, }), }); -patchIdentifyingFields('Throttle', identifyingFields => { - identifyingFields[0].push('qunitTestOwner1'); - identifyingFields[0].push('qunitTestOwner2'); -}); - patchRecordMethods('Throttle', { _computeDuration() { if (this.qunitTestOwner1) { diff --git a/addons/mail/static/tests/models/timer_qunit_tests.js b/addons/mail/static/tests/models/timer_qunit_tests.js index 2d3043d2dc6..f36b24a2cd2 100644 --- a/addons/mail/static/tests/models/timer_qunit_tests.js +++ b/addons/mail/static/tests/models/timer_qunit_tests.js @@ -1,26 +1,23 @@ /** @odoo-module **/ -import { addFields, patchIdentifyingFields, patchRecordMethods } from '@mail/model/model_core'; +import { addFields, patchRecordMethods } from '@mail/model/model_core'; import { one } from '@mail/model/model_field'; // ensure that the model definition is loaded before the patch import '@mail/models/timer'; addFields('Timer', { qunitTestOwner1: one('QUnitTest', { + identifying: true, inverse: 'timer1', readonly: true, }), qunitTestOwner2: one('QUnitTest', { + identifying: true, inverse: 'timer2', readonly: true, }), }); -patchIdentifyingFields('Timer', identifyingFields => { - identifyingFields[0].push('qunitTestOwner1'); - identifyingFields[0].push('qunitTestOwner2'); -}); - patchRecordMethods('Timer', { _computeDuration() { if (this.qunitTestOwner1) { diff --git a/addons/rating/static/src/models/rating.js b/addons/rating/static/src/models/rating.js index c91419b1ddb..aef285ceceb 100644 --- a/addons/rating/static/src/models/rating.js +++ b/addons/rating/static/src/models/rating.js @@ -5,9 +5,9 @@ import { attr } from '@mail/model/model_field'; registerModel({ name: 'Rating', - identifyingFields: ['id'], fields: { id: attr({ + identifying: true, readonly: true, required: true, }), diff --git a/addons/snailmail/static/src/models/dialog.js b/addons/snailmail/static/src/models/dialog.js index b03d0d3cc24..5532ba7a5a2 100644 --- a/addons/snailmail/static/src/models/dialog.js +++ b/addons/snailmail/static/src/models/dialog.js @@ -1,17 +1,14 @@ /** @odoo-module **/ -import { addFields, addRecordMethods, patchIdentifyingFields, patchRecordMethods } from '@mail/model/model_core'; +import { addFields, addRecordMethods, patchRecordMethods } from '@mail/model/model_core'; import { one } from '@mail/model/model_field'; import { clear, insertAndReplace, replace } from '@mail/model/model_field_command'; // ensure that the model definition is loaded before the patch import '@mail/models/dialog'; -patchIdentifyingFields('Dialog', identifyingFields => { - identifyingFields[0].push('messageViewOwnerAsSnailmailError'); -}); - addFields('Dialog', { messageViewOwnerAsSnailmailError: one('MessageView', { + identifying: true, inverse: 'snailmailErrorDialog', readonly: true, }), diff --git a/addons/snailmail/static/src/models/snailmail_error_view.js b/addons/snailmail/static/src/models/snailmail_error_view.js index 0e7d0f3b7c3..cf6c679f982 100644 --- a/addons/snailmail/static/src/models/snailmail_error_view.js +++ b/addons/snailmail/static/src/models/snailmail_error_view.js @@ -6,7 +6,6 @@ import { replace } from '@mail/model/model_field_command'; registerModel({ name: 'SnailmailErrorView', - identifyingFields: ['dialogOwner'], recordMethods: { /** * Returns whether the given html element is inside this snailmail error view. @@ -59,6 +58,7 @@ registerModel({ fields: { component: attr(), dialogOwner: one('Dialog', { + identifying: true, inverse: 'snailmailErrorView', readonly: true, required: true, diff --git a/addons/website_livechat/static/src/models/visitor.js b/addons/website_livechat/static/src/models/visitor.js index f30d6388ff5..9ffd9ba5b84 100644 --- a/addons/website_livechat/static/src/models/visitor.js +++ b/addons/website_livechat/static/src/models/visitor.js @@ -6,7 +6,6 @@ import { clear, insert, replace } from '@mail/model/model_field_command'; registerModel({ name: 'Visitor', - identifyingFields: ['id'], modelMethods: { convertData(data) { const data2 = {}; @@ -108,6 +107,7 @@ registerModel({ * States the id of this visitor. */ id: attr({ + identifying: true, readonly: true, required: true, }),