From ae5f59775ec91bc73a436be0c2a6626c618fb8ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20K=C3=BChn?= Date: Fri, 22 Apr 2022 11:25:58 +0000 Subject: [PATCH] [IMP] mail: introduce view models (step 1) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit introduces models that define records being 1:1 map with components, as a step to move further to having essentially all business code in models. Having code in models is desirable to have very maintainable code, thanks to robust and declarative code with an ORM-like architecture. Task-2831082 closes odoo/odoo#89735 Related: odoo/enterprise#26637 Signed-off-by: Alexandre Kühn (aku) --- .../channel_member_list.js | 8 ++-- .../channel_member_list.xml | 26 ++++++------- .../components/chat_window/chat_window.xml | 4 +- .../src/components/composer/composer.xml | 2 +- .../composer_suggested_recipient_list.js | 36 ++++++++--------- .../composer_suggested_recipient_list.xml | 8 ++-- .../components/thread_view/thread_view.xml | 4 +- .../src/models/channel_member_list_view.js | 39 +++++++++++++++++++ addons/mail/static/src/models/chat_window.js | 15 +++++++ .../composer_suggested_recipient_list_view.js | 30 ++++++++++++++ .../mail/static/src/models/composer_view.js | 15 +++++++ addons/mail/static/src/models/thread_view.js | 15 +++++++ 12 files changed, 156 insertions(+), 46 deletions(-) create mode 100644 addons/mail/static/src/models/channel_member_list_view.js create mode 100644 addons/mail/static/src/models/composer_suggested_recipient_list_view.js diff --git a/addons/mail/static/src/components/channel_member_list/channel_member_list.js b/addons/mail/static/src/components/channel_member_list/channel_member_list.js index e1b3dfdc578..d0c13536b81 100644 --- a/addons/mail/static/src/components/channel_member_list/channel_member_list.js +++ b/addons/mail/static/src/components/channel_member_list/channel_member_list.js @@ -7,16 +7,16 @@ const { Component } = owl; export class ChannelMemberList extends Component { /** - * @returns {Thread} + * @returns {ChannelMemberListView} */ - get channel() { - return this.messaging.models['Thread'].get(this.props.channelLocalId); + get channelMemberListView() { + return this.messaging && this.messaging.models['ChannelMemberListView'].get(this.props.localId); } } Object.assign(ChannelMemberList, { - props: { channelLocalId: String }, + props: { localId: String }, template: 'mail.ChannelMemberList', }); diff --git a/addons/mail/static/src/components/channel_member_list/channel_member_list.xml b/addons/mail/static/src/components/channel_member_list/channel_member_list.xml index f3e5b5fe3b1..ef23ed11ef0 100644 --- a/addons/mail/static/src/components/channel_member_list/channel_member_list.xml +++ b/addons/mail/static/src/components/channel_member_list/channel_member_list.xml @@ -2,29 +2,29 @@ - +
- + - + Online - + - + Offline - + And 1 other member. - - And other members. + + And other members. - +
- +
@@ -35,8 +35,8 @@
-
-
- Avatar +
+ Avatar
- +
diff --git a/addons/mail/static/src/components/chat_window/chat_window.xml b/addons/mail/static/src/components/chat_window/chat_window.xml index 5283cf34d12..53b3124c818 100644 --- a/addons/mail/static/src/components/chat_window/chat_window.xml +++ b/addons/mail/static/src/components/chat_window/chat_window.xml @@ -17,8 +17,8 @@ chatWindowLocalId="chatWindow.localId" onClicked="chatWindow.onClickHeader" /> - - + + diff --git a/addons/mail/static/src/components/composer/composer.xml b/addons/mail/static/src/components/composer/composer.xml index f72bff416d1..9c9a34444d5 100644 --- a/addons/mail/static/src/components/composer/composer.xml +++ b/addons/mail/static/src/components/composer/composer.xml @@ -48,7 +48,7 @@ - +
diff --git a/addons/mail/static/src/components/composer_suggested_recipient_list/composer_suggested_recipient_list.js b/addons/mail/static/src/components/composer_suggested_recipient_list/composer_suggested_recipient_list.js index 9177315e5b6..3835a13da84 100644 --- a/addons/mail/static/src/components/composer_suggested_recipient_list/composer_suggested_recipient_list.js +++ b/addons/mail/static/src/components/composer_suggested_recipient_list/composer_suggested_recipient_list.js @@ -2,24 +2,21 @@ import { registerMessagingComponent } from '@mail/utils/messaging_component'; -const { Component, useState } = owl; +const { Component } = owl; export class ComposerSuggestedRecipientList extends Component { - /** - * @override - */ - setup() { - super.setup(); - this.state = useState({ - hasShowMoreButton: false, - }); - } - //-------------------------------------------------------------------------- // Public //-------------------------------------------------------------------------- + /** + * @returns {ComposerSuggestedRecipientListView} + */ + get composerSuggestedRecipientListView() { + return this.messaging && this.messaging.models['ComposerSuggestedRecipientListView'].get(this.props.localId); + } + /** * @returns {Thread} */ @@ -31,24 +28,23 @@ export class ComposerSuggestedRecipientList extends Component { // Handlers //-------------------------------------------------------------------------- - /** - * @private - */ - _onClickShowLess(ev) { - this.state.hasShowMoreButton = false; - } - /** * @private */ _onClickShowMore(ev) { - this.state.hasShowMoreButton = true; + if (!this.composerSuggestedRecipientListView) { + return; + } + this.composerSuggestedRecipientListView.update({ hasShowMoreButton: true }); } } Object.assign(ComposerSuggestedRecipientList, { - props: { threadLocalId: String }, + props: { + localId: String, + threadLocalId: String, + }, template: 'mail.ComposerSuggestedRecipientList', }); diff --git a/addons/mail/static/src/components/composer_suggested_recipient_list/composer_suggested_recipient_list.xml b/addons/mail/static/src/components/composer_suggested_recipient_list/composer_suggested_recipient_list.xml index 5c2877addeb..cf7d4992d0e 100644 --- a/addons/mail/static/src/components/composer_suggested_recipient_list/composer_suggested_recipient_list.xml +++ b/addons/mail/static/src/components/composer_suggested_recipient_list/composer_suggested_recipient_list.xml @@ -1,21 +1,21 @@ - +
- + - + - diff --git a/addons/mail/static/src/components/thread_view/thread_view.xml b/addons/mail/static/src/components/thread_view/thread_view.xml index 61be0ff8abf..942da49579c 100644 --- a/addons/mail/static/src/components/thread_view/thread_view.xml +++ b/addons/mail/static/src/components/thread_view/thread_view.xml @@ -44,8 +44,8 @@ />
- - + + diff --git a/addons/mail/static/src/models/channel_member_list_view.js b/addons/mail/static/src/models/channel_member_list_view.js new file mode 100644 index 00000000000..beae3696e82 --- /dev/null +++ b/addons/mail/static/src/models/channel_member_list_view.js @@ -0,0 +1,39 @@ +/** @odoo-module **/ + +import { registerModel } from '@mail/model/model_core'; +import { one } from '@mail/model/model_field'; +import { clear, replace } from '@mail/model/model_field_command'; + +registerModel({ + name: 'ChannelMemberListView', + identifyingFields: [['chatWindowOwner', 'threadViewOwner']], + recordMethods: { + /** + * @private + * @returns {FieldCommand} + */ + _computeChannel() { + if (this.chatWindowOwner) { + return replace(this.chatWindowOwner.thread); + } + if (this.threadViewOwner) { + return replace(this.threadViewOwner.thread); + } + return clear(); + }, + }, + fields: { + channel: one('Thread', { + compute: '_computeChannel', + readonly: true, + }), + chatWindowOwner: one('ChatWindow', { + inverse: 'channelMemberListView', + readonly: true, + }), + threadViewOwner: one('ThreadView', { + inverse: 'channelMemberListView', + readonly: true, + }), + }, +}); diff --git a/addons/mail/static/src/models/chat_window.js b/addons/mail/static/src/models/chat_window.js index 26d2f204966..968dae0ccf5 100644 --- a/addons/mail/static/src/models/chat_window.js +++ b/addons/mail/static/src/models/chat_window.js @@ -325,6 +325,16 @@ registerModel({ this.thread.notifyFoldStateToServer('open'); } }, + /** + * @private + * @returns {FieldCommand} + */ + _computeChannelMemberListView() { + if (this.thread && this.thread.hasMemberListFeature && this.isMemberListOpened) { + return insertAndReplace(); + } + return clear(); + }, /** * @private * @returns {string} @@ -586,6 +596,11 @@ registerModel({ inverse: 'chatWindow', isCausal: true, }), + channelMemberListView: one('ChannelMemberListView', { + compute: '_computeChannelMemberListView', + inverse: 'chatWindowOwner', + isCausal: true, + }), componentStyle: attr({ compute: '_computeComponentStyle', }), 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 new file mode 100644 index 00000000000..d07c7010a2b --- /dev/null +++ b/addons/mail/static/src/models/composer_suggested_recipient_list_view.js @@ -0,0 +1,30 @@ +/** @odoo-module **/ + +import { registerModel } from '@mail/model/model_core'; +import { attr, one } from '@mail/model/model_field'; + +registerModel({ + name: 'ComposerSuggestedRecipientListView', + identifyingFields: ['composerViewOwner'], + recordMethods: { + /** + * @param {MouseEvent} ev + */ + onClickShowLess(ev) { + if (!this.exists()) { + return; + } + this.update({ hasShowMoreButton: false }); + }, + }, + fields: { + composerViewOwner: one('ComposerView', { + inverse: 'composerSuggestedRecipientListView', + readonly: true, + required: true, + }), + hasShowMoreButton: attr({ + default: false, + }), + }, +}); diff --git a/addons/mail/static/src/models/composer_view.js b/addons/mail/static/src/models/composer_view.js index bf03fbe6f7a..a5005f43501 100644 --- a/addons/mail/static/src/models/composer_view.js +++ b/addons/mail/static/src/models/composer_view.js @@ -801,6 +801,16 @@ registerModel({ ? insertAndReplace() : clear(); }, + /** + * @private + * @returns {FieldCommand} + */ + _computeComposerSuggestedRecipientListView() { + if (this.hasHeader && this.hasFollowers && !this.composer.isLog) { + return insertAndReplace(); + } + return clear(); + }, /** * @private * @returns {FieldCommand} @@ -1415,6 +1425,11 @@ registerModel({ inverse: 'composerViews', required: true, }), + composerSuggestedRecipientListView: one('ComposerSuggestedRecipientListView', { + compute: '_computeComposerSuggestedRecipientListView', + inverse: 'composerViewOwner', + isCausal: true, + }), /** * Current partner image URL. */ diff --git a/addons/mail/static/src/models/thread_view.js b/addons/mail/static/src/models/thread_view.js index 287f76268c6..b85badd6ea3 100644 --- a/addons/mail/static/src/models/thread_view.js +++ b/addons/mail/static/src/models/thread_view.js @@ -93,6 +93,16 @@ registerModel({ ? insertAndReplace() : clear(); }, + /** + * @private + * @returns {FieldCommand} + */ + _computeChannelMemberListView() { + if (this.thread && this.thread.hasMemberListFeature && this.hasMemberList && this.isMemberListOpened) { + return insertAndReplace(); + } + return clear(); + }, /** * @private * @returns {FieldCommand} @@ -339,6 +349,11 @@ registerModel({ }, }, fields: { + channelMemberListView: one('ChannelMemberListView', { + compute: '_computeChannelMemberListView', + inverse: 'threadViewOwner', + isCausal: true, + }), compact: attr({ related: 'threadViewer.compact', }),