diff --git a/addons/im_livechat/static/src/components/notification_list/notification_list.js b/addons/im_livechat/static/src/components/notification_list/notification_list.js deleted file mode 100644 index 10499b86249..00000000000 --- a/addons/im_livechat/static/src/components/notification_list/notification_list.js +++ /dev/null @@ -1,32 +0,0 @@ -/** @odoo-module **/ - -import { NotificationList } from '@mail/components/notification_list/notification_list'; -import { patch } from 'web.utils'; - -const components = { NotificationList }; - -components.NotificationList._allowedFilters.push('livechat'); - -patch(components.NotificationList.prototype, 'im_livechat/static/src/components/notification_list/notification_list.js', { - - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- - - /** - * Override to include livechat channels. - * - * @override - */ - _getThreads(props) { - if (props.filter === 'livechat') { - return this.messaging.models['Thread'].all(thread => - thread.channel_type === 'livechat' && - thread.isPinned && - thread.model === 'mail.channel' - ); - } - return this._super(...arguments); - }, - -}); diff --git a/addons/im_livechat/static/src/components/thread_needaction_preview/thread_needaction_preview.js b/addons/im_livechat/static/src/components/thread_needaction_preview/thread_needaction_preview.js index 2760850225d..730a02aae6c 100644 --- a/addons/im_livechat/static/src/components/thread_needaction_preview/thread_needaction_preview.js +++ b/addons/im_livechat/static/src/components/thread_needaction_preview/thread_needaction_preview.js @@ -16,7 +16,7 @@ patch(components.ThreadNeedactionPreview.prototype, 'thread_needaction_preview', * @override */ image(...args) { - if (this.thread.channel_type === 'livechat') { + if (this.threadNeedactionPreviewView.thread.channel_type === 'livechat') { return '/mail/static/src/img/smiley/avatar.jpg'; } return this._super(...args); diff --git a/addons/im_livechat/static/src/components/thread_preview/thread_preview.js b/addons/im_livechat/static/src/components/thread_preview/thread_preview.js index 46b65eb6fdd..d3e44e46967 100644 --- a/addons/im_livechat/static/src/components/thread_preview/thread_preview.js +++ b/addons/im_livechat/static/src/components/thread_preview/thread_preview.js @@ -16,7 +16,7 @@ patch(components.ThreadPreview.prototype, 'im_livechat/static/src/components/thr * @override */ image(...args) { - if (this.thread.channel_type === 'livechat') { + if (this.threadPreviewView.thread.channel_type === 'livechat') { return '/mail/static/src/img/smiley/avatar.jpg'; } return this._super(...args); diff --git a/addons/im_livechat/static/src/models/notification_list_view/notification_list_view.js b/addons/im_livechat/static/src/models/notification_list_view/notification_list_view.js new file mode 100644 index 00000000000..7679c784300 --- /dev/null +++ b/addons/im_livechat/static/src/models/notification_list_view/notification_list_view.js @@ -0,0 +1,21 @@ +/** @odoo-module **/ + +import { patchRecordMethods } from '@mail/model/model_core'; +import { replace } from '@mail/model/model_field_command'; +import '@mail/models/notification_list_view/notification_list_view'; // ensure the model definition is loaded before the patch + +patchRecordMethods('NotificationListView', { + /** + * @override + */ + _computeFilteredThreads() { + if (this.filter === 'livechat') { + return replace(this.messaging.models['Thread'].all(thread => + thread.channel_type === 'livechat' && + thread.isPinned && + thread.model === 'mail.channel' + )); + } + return this._super(); + }, +}); diff --git a/addons/mail/static/src/components/discuss/discuss.xml b/addons/mail/static/src/components/discuss/discuss.xml index 6a9a03bc3c1..1e52dde7ea8 100644 --- a/addons/mail/static/src/components/discuss/discuss.xml +++ b/addons/mail/static/src/components/discuss/discuss.xml @@ -71,10 +71,9 @@ New Channel - + + + - + + +
- +
Message delivery failure image @@ -12,21 +12,21 @@
- + - () + () - + - +
- + An error occurred when sending an email. diff --git a/addons/mail/static/src/components/notification_list/notification_list.js b/addons/mail/static/src/components/notification_list/notification_list.js index 36e238e3596..c65922258bd 100644 --- a/addons/mail/static/src/components/notification_list/notification_list.js +++ b/addons/mail/static/src/components/notification_list/notification_list.js @@ -19,95 +19,11 @@ export class NotificationList extends Component { this._loadPreviews(); } - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- - /** - * @returns {Object[]} + * @returns {NotificationListView} */ - get notifications() { - if (!this.messaging) { - return []; - } - const threads = this._getThreads(this.props); - let threadNeedactionNotifications = []; - if (this.props.filter === 'all') { - // threads with needactions - threadNeedactionNotifications = this.messaging.models['Thread'] - .all(t => t.model !== 'mail.box' && t.needactionMessagesAsOriginThread.length > 0) - .sort((t1, t2) => { - if (t1.needactionMessagesAsOriginThread.length > 0 && t2.needactionMessagesAsOriginThread.length === 0) { - return -1; - } - if (t1.needactionMessagesAsOriginThread.length === 0 && t2.needactionMessagesAsOriginThread.length > 0) { - return 1; - } - if (t1.lastNeedactionMessageAsOriginThread && t2.lastNeedactionMessageAsOriginThread) { - return t1.lastNeedactionMessageAsOriginThread.id < t2.lastNeedactionMessageAsOriginThread.id ? 1 : -1; - } - if (t1.lastNeedactionMessageAsOriginThread) { - return -1; - } - if (t2.lastNeedactionMessageAsOriginThread) { - return 1; - } - return t1.id < t2.id ? -1 : 1; - }) - .map(thread => { - return { - thread, - type: 'thread_needaction', - uniqueId: thread.localId + '_needaction', - }; - }); - } - // thread notifications - const threadNotifications = threads - .sort((t1, t2) => { - if (t1.localMessageUnreadCounter > 0 && t2.localMessageUnreadCounter === 0) { - return -1; - } - if (t1.localMessageUnreadCounter === 0 && t2.localMessageUnreadCounter > 0) { - return 1; - } - if (t1.lastMessage && t2.lastMessage) { - return t1.lastMessage.id < t2.lastMessage.id ? 1 : -1; - } - if (t1.lastMessage) { - return -1; - } - if (t2.lastMessage) { - return 1; - } - return t1.id < t2.id ? -1 : 1; - }) - .map(thread => { - return { - thread, - type: 'thread', - uniqueId: thread.localId, - }; - }); - let notifications = threadNeedactionNotifications.concat(threadNotifications); - if (this.props.filter === 'all') { - notifications = Object.values(this.messaging.models['NotificationGroup'].all()) - .sort((group1, group2) => group1.sequence - group2.sequence) - .map(notificationGroup => { - return { - notificationGroup, - uniqueId: notificationGroup.localId, - }; - }).concat(notifications); - } - // native notification request - if (this.props.filter === 'all' && this.messaging.isNotificationPermissionDefault) { - notifications.unshift({ - type: 'odoobotRequest', - uniqueId: 'odoobotRequest', - }); - } - return notifications; + get notificationListView() { + return this.messaging && this.messaging.models['NotificationListView'].get(this.props.localId); } //-------------------------------------------------------------------------- @@ -121,78 +37,15 @@ export class NotificationList extends Component { * @private */ async _loadPreviews() { - const threads = this.notifications - .filter(notification => notification.thread && notification.thread.exists()) - .map(notification => notification.thread); + const threads = this.notificationListView.threadPreviewViews + .map(threadPreviewView => threadPreviewView.thread); this.messaging.models['Thread'].loadPreviews(threads); } - /** - * @private - * @param {Object} props - * @throws {Error} in case `props.filter` is not supported - * @returns {Thread[]} - */ - _getThreads(props) { - if (props.filter === 'mailbox') { - return this.messaging.models['Thread'] - .all(thread => thread.isPinned && thread.model === 'mail.box') - .sort((mailbox1, mailbox2) => { - if (mailbox1 === this.messaging.inbox) { - return -1; - } - if (mailbox2 === this.messaging.inbox) { - return 1; - } - if (mailbox1 === this.messaging.starred) { - return -1; - } - if (mailbox2 === this.messaging.starred) { - return 1; - } - const mailbox1Name = mailbox1.displayName; - const mailbox2Name = mailbox2.displayName; - mailbox1Name < mailbox2Name ? -1 : 1; - }); - } else if (props.filter === 'channel') { - return this.messaging.models['Thread'] - .all(thread => - thread.channel_type === 'channel' && - thread.isPinned && - thread.model === 'mail.channel' - ) - .sort((c1, c2) => c1.displayName < c2.displayName ? -1 : 1); - } else if (props.filter === 'chat') { - return this.messaging.models['Thread'] - .all(thread => - thread.isChatChannel && - thread.isPinned && - thread.model === 'mail.channel' - ) - .sort((c1, c2) => c1.displayName < c2.displayName ? -1 : 1); - } else if (props.filter === 'all') { - // "All" filter is for channels and chats - return this.messaging.models['Thread'] - .all(thread => thread.isPinned && thread.model === 'mail.channel') - .sort((c1, c2) => c1.displayName < c2.displayName ? -1 : 1); - } else { - throw new Error(`Unsupported filter ${props.filter}`); - } - } - } Object.assign(NotificationList, { - _allowedFilters: ['all', 'mailbox', 'channel', 'chat'], - defaultProps: { - filter: 'all', - }, - props: { - filter: { - type: String, - validate: prop => NotificationList._allowedFilters.includes(prop), - }, - }, + props: { localId: String }, template: 'mail.NotificationList', }); diff --git a/addons/mail/static/src/components/notification_list/notification_list.xml b/addons/mail/static/src/components/notification_list/notification_list.xml index 69eb938cdd7..1243a1d1ae0 100644 --- a/addons/mail/static/src/components/notification_list/notification_list.xml +++ b/addons/mail/static/src/components/notification_list/notification_list.xml @@ -2,42 +2,45 @@ -
- -
- No conversation yet... -
-
- - - - - - - - - - - - - - - -
+
+ + +
+ No conversation yet... +
+
+ + + + + + + + + + + + + + + +
+ diff --git a/addons/mail/static/src/components/notification_list/tests/notification_list_notification_group_tests.js b/addons/mail/static/src/components/notification_list/tests/notification_list_notification_group_tests.js index 824d77e3f3b..5aecaeebb7e 100644 --- a/addons/mail/static/src/components/notification_list/tests/notification_list_notification_group_tests.js +++ b/addons/mail/static/src/components/notification_list/tests/notification_list_notification_group_tests.js @@ -1,12 +1,6 @@ /** @odoo-module **/ -import { - afterEach, - afterNextRender, - beforeEach, - createRootMessagingComponent, - start, -} from '@mail/utils/test_utils'; +import { afterEach, afterNextRender, beforeEach, start, } from '@mail/utils/test_utils'; import Bus from 'web.Bus'; @@ -17,23 +11,14 @@ QUnit.module('notification_list_notification_group_tests.js', { beforeEach() { beforeEach(this); - /** - * @param {Object} param0 - * @param {string} [param0.filter='all'] - */ - this.createNotificationListComponent = async ({ filter = 'all' } = {}) => { - await createRootMessagingComponent(this, "NotificationList", { - props: { filter }, - target: this.widget.el, - }); - }; - this.start = async params => { - const { env, widget } = await start(Object.assign({}, params, { + const res = await start(Object.assign({}, params, { data: this.data, })); + const { env, widget } = res; this.env = env; this.widget = widget; + return res; }; }, afterEach() { @@ -58,8 +43,8 @@ QUnit.test('notification group basic layout', async function (assert) { notification_status: 'exception', // necessary value to have a failure notification_type: 'email', // expected failure type for email message }); - await this.start(); - await this.createNotificationListComponent(); + const { createNotificationListComponent } = await this.start(); + await createNotificationListComponent(); assert.containsOnce( document.body, '.o_NotificationGroup', @@ -148,8 +133,8 @@ QUnit.test('mark as read', async function (assert) { "action should have the group notification length as unread_counter" ); }); - await this.start({ env: { bus } }); - await this.createNotificationListComponent(); + const { createNotificationListComponent } = await this.start({ env: { bus } }); + await createNotificationListComponent(); assert.containsOnce( document.body, '.o_NotificationGroup_markAsRead', @@ -200,8 +185,8 @@ QUnit.test('grouped notifications by document', async function (assert) { notification_type: 'email', // expected failure type for email message } ); - await this.start({ hasChatWindow: true }); - await this.createNotificationListComponent(); + const { createNotificationListComponent } = await this.start({ hasChatWindow: true }); + await createNotificationListComponent(); assert.containsOnce( document.body, @@ -312,8 +297,8 @@ QUnit.test('grouped notifications by document model', async function (assert) { ); }); - await this.start({ env: { bus } }); - await this.createNotificationListComponent(); + const { createNotificationListComponent } = await this.start({ env: { bus } }); + await createNotificationListComponent(); assert.containsOnce( document.body, @@ -376,10 +361,10 @@ QUnit.test('different mail.channel are not grouped', async function (assert) { notification_type: 'email', // expected failure type for email message } ); - await this.start({ + const { createNotificationListComponent } = await this.start({ hasChatWindow: true, // needed to assert thread.open }); - await this.createNotificationListComponent(); + await createNotificationListComponent(); assert.containsN( document.body, '.o_NotificationGroup', @@ -451,8 +436,8 @@ QUnit.test('multiple grouped notifications by document model, sorted by the most notification_type: 'email', // expected failure type for email message } ); - await this.start(); - await this.createNotificationListComponent(); + const { createNotificationListComponent } = await this.start(); + await createNotificationListComponent(); assert.containsN( document.body, '.o_NotificationGroup', @@ -522,8 +507,8 @@ QUnit.test('non-failure notifications are ignored', async function (assert) { notification_type: 'email', // expected notification type for email message }, ); - await this.start(); - await this.createNotificationListComponent(); + const { createNotificationListComponent } = await this.start(); + await createNotificationListComponent(); assert.containsNone( document.body, '.o_NotificationGroup', diff --git a/addons/mail/static/src/components/notification_list/tests/notification_list_tests.js b/addons/mail/static/src/components/notification_list/tests/notification_list_tests.js index fb93547386d..2930800d7c0 100644 --- a/addons/mail/static/src/components/notification_list/tests/notification_list_tests.js +++ b/addons/mail/static/src/components/notification_list/tests/notification_list_tests.js @@ -1,12 +1,6 @@ /** @odoo-module **/ -import { - afterEach, - afterNextRender, - beforeEach, - createRootMessagingComponent, - start, -} from '@mail/utils/test_utils'; +import { afterEach, afterNextRender, beforeEach, start } from '@mail/utils/test_utils'; QUnit.module('mail', {}, function () { QUnit.module('components', {}, function () { @@ -15,23 +9,14 @@ QUnit.module('notification_list_tests.js', { beforeEach() { beforeEach(this); - /** - * @param {Object} param0 - * @param {string} [param0.filter='all'] - */ - this.createNotificationListComponent = async ({ filter = 'all' }) => { - await createRootMessagingComponent(this, "NotificationList", { - props: { filter }, - target: this.widget.el, - }); - }; - this.start = async params => { - const { env, widget } = await start(Object.assign({}, params, { + const res = await start(Object.assign({}, params, { data: this.data, })); + const { env, widget } = res; this.env = env; this.widget = widget; + return res; }; }, afterEach() { @@ -60,8 +45,8 @@ QUnit.test('marked as read thread notifications are ordered by last message date res_id: 200, } ); - await this.start(); - await this.createNotificationListComponent({ filter: 'all' }); + const { createNotificationListComponent } = await this.start(); + await createNotificationListComponent({ filter: 'all' }); assert.containsN( document.body, '.o_ThreadPreview', @@ -102,8 +87,8 @@ QUnit.test('thread notifications are re-ordered on receiving a new message', asy res_id: 200, } ); - await this.start(); - await this.createNotificationListComponent({ filter: 'all' }); + const { createNotificationListComponent } = await this.start(); + await createNotificationListComponent({ filter: 'all' }); assert.containsN( document.body, '.o_ThreadPreview', diff --git a/addons/mail/static/src/components/notification_request/notification_request.js b/addons/mail/static/src/components/notification_request/notification_request.js index bfbbdee27a6..43dcd2edeb1 100644 --- a/addons/mail/static/src/components/notification_request/notification_request.js +++ b/addons/mail/static/src/components/notification_request/notification_request.js @@ -62,7 +62,7 @@ export class NotificationRequest extends Component { } Object.assign(NotificationRequest, { - props: {}, + props: { localId: String }, template: 'mail.NotificationRequest', }); diff --git a/addons/mail/static/src/components/thread_needaction_preview/tests/thread_needaction_preview_tests.js b/addons/mail/static/src/components/thread_needaction_preview/tests/thread_needaction_preview_tests.js index d91469ed06b..c7bd28e5bf1 100644 --- a/addons/mail/static/src/components/thread_needaction_preview/tests/thread_needaction_preview_tests.js +++ b/addons/mail/static/src/components/thread_needaction_preview/tests/thread_needaction_preview_tests.js @@ -1,12 +1,6 @@ /** @odoo-module **/ -import { - afterEach, - afterNextRender, - beforeEach, - createRootMessagingComponent, - start, -} from '@mail/utils/test_utils'; +import { afterEach, afterNextRender, beforeEach, start } from '@mail/utils/test_utils'; import Bus from 'web.Bus'; @@ -17,13 +11,6 @@ QUnit.module('thread_needaction_preview_tests.js', { beforeEach() { beforeEach(this); - this.createThreadNeedactionPreviewComponent = async props => { - await createRootMessagingComponent(this, "ThreadNeedactionPreview", { - props, - target: this.widget.el - }); - }; - this.start = async params => { const res = await start(Object.assign({}, params, { data: this.data, diff --git a/addons/mail/static/src/components/thread_needaction_preview/thread_needaction_preview.js b/addons/mail/static/src/components/thread_needaction_preview/thread_needaction_preview.js index 68e56026ab5..d270bd0225e 100644 --- a/addons/mail/static/src/components/thread_needaction_preview/thread_needaction_preview.js +++ b/addons/mail/static/src/components/thread_needaction_preview/thread_needaction_preview.js @@ -31,14 +31,14 @@ export class ThreadNeedactionPreview extends Component { * @returns {string} */ image() { - if (this.thread.moduleIcon) { - return this.thread.moduleIcon; + if (this.threadNeedactionPreviewView.thread.moduleIcon) { + return this.threadNeedactionPreviewView.thread.moduleIcon; } - if (this.thread.correspondent) { - return this.thread.correspondent.avatarUrl; + if (this.threadNeedactionPreviewView.thread.correspondent) { + return this.threadNeedactionPreviewView.thread.correspondent.avatarUrl; } - if (this.thread.model === 'mail.channel') { - return `/web/image/mail.channel/${this.thread.id}/avatar_128?unique=${this.thread.avatarCacheKey}`; + if (this.threadNeedactionPreviewView.thread.model === 'mail.channel') { + return `/web/image/mail.channel/${this.threadNeedactionPreviewView.thread.id}/avatar_128?unique=${this.threadNeedactionPreviewView.thread.avatarCacheKey}`; } return '/mail/static/src/img/smiley/avatar.jpg'; } @@ -49,17 +49,17 @@ export class ThreadNeedactionPreview extends Component { * @returns {string} */ get inlineLastNeedactionMessageAsOriginThreadBody() { - if (!this.thread.lastNeedactionMessageAsOriginThread) { + if (!this.threadNeedactionPreviewView.thread.lastNeedactionMessageAsOriginThread) { return ''; } - return mailUtils.htmlToTextContentInline(this.thread.lastNeedactionMessageAsOriginThread.prettyBody); + return mailUtils.htmlToTextContentInline(this.threadNeedactionPreviewView.thread.lastNeedactionMessageAsOriginThread.prettyBody); } /** - * @returns {Thread} + * @returns {ThreadNeedactionPreviewView} */ - get thread() { - return this.messaging && this.messaging.models['Thread'].get(this.props.threadLocalId); + get threadNeedactionPreviewView() { + return this.messaging && this.messaging.models['ThreadNeedactionPreviewView'].get(this.props.localId); } //-------------------------------------------------------------------------- @@ -76,7 +76,7 @@ export class ThreadNeedactionPreview extends Component { // handled in `_onClickMarkAsRead` return; } - this.thread.open(); + this.threadNeedactionPreviewView.thread.open(); if (!this.messaging.device.isMobile) { this.messaging.messagingMenu.close(); } @@ -88,17 +88,15 @@ export class ThreadNeedactionPreview extends Component { */ _onClickMarkAsRead(ev) { this.messaging.models['Message'].markAllAsRead([ - ['model', '=', this.thread.model], - ['res_id', '=', this.thread.id], + ['model', '=', this.threadNeedactionPreviewView.thread.model], + ['res_id', '=', this.threadNeedactionPreviewView.thread.id], ]); } } Object.assign(ThreadNeedactionPreview, { - props: { - threadLocalId: String, - }, + props: { localId: String }, template: 'mail.ThreadNeedactionPreview', }); diff --git a/addons/mail/static/src/components/thread_needaction_preview/thread_needaction_preview.xml b/addons/mail/static/src/components/thread_needaction_preview/thread_needaction_preview.xml index b282238bbc2..f7f04590bb9 100644 --- a/addons/mail/static/src/components/thread_needaction_preview/thread_needaction_preview.xml +++ b/addons/mail/static/src/components/thread_needaction_preview/thread_needaction_preview.xml @@ -6,18 +6,18 @@ The preview template is used by the discuss in mobile, and by the systray menu in order to show preview of threads. --> -
- +
+
Thread Image - +
@@ -25,24 +25,24 @@
- + - () + () - + - +
- + diff --git a/addons/mail/static/src/components/thread_preview/tests/thread_preview_tests.js b/addons/mail/static/src/components/thread_preview/tests/thread_preview_tests.js index 2b5244b9e47..56363cc0604 100644 --- a/addons/mail/static/src/components/thread_preview/tests/thread_preview_tests.js +++ b/addons/mail/static/src/components/thread_preview/tests/thread_preview_tests.js @@ -1,12 +1,6 @@ /** @odoo-module **/ -import { - afterEach, - afterNextRender, - beforeEach, - createRootMessagingComponent, - start, -} from '@mail/utils/test_utils'; +import { afterEach, afterNextRender, beforeEach, start } from '@mail/utils/test_utils'; QUnit.module('mail', {}, function () { QUnit.module('components', {}, function () { @@ -15,19 +9,14 @@ QUnit.module('thread_preview_tests.js', { beforeEach() { beforeEach(this); - this.createThreadPreviewComponent = async props => { - await createRootMessagingComponent(this, "ThreadPreview", { - props, - target: this.widget.el, - }); - }; - this.start = async params => { - const { env, widget } = await start(Object.assign({}, params, { + const res = await start(Object.assign({}, params, { data: this.data, })); + const { env, widget } = res; this.env = env; this.widget = widget; + return res; }; }, afterEach() { @@ -40,6 +29,7 @@ QUnit.test('mark as read', async function (assert) { this.data['mail.channel'].records.push({ id: 11, message_unread_counter: 1, + seen_message_id: 99, }); this.data['mail.message'].records.push({ id: 100, @@ -47,7 +37,7 @@ QUnit.test('mark as read', async function (assert) { res_id: 11, }); - await this.start({ + const { click, createMessagingMenuComponent } = await this.start({ hasChatWindow: true, async mockRPC(route, args) { if (route.includes('set_last_seen_message')) { @@ -56,11 +46,8 @@ QUnit.test('mark as read', async function (assert) { return this._super(...arguments); }, }); - const thread = this.messaging.models['Thread'].findFromIdentifyingData({ - id: 11, - model: 'mail.channel', - }); - await this.createThreadPreviewComponent({ threadLocalId: thread.localId }); + await createMessagingMenuComponent(); + await click('.o_MessagingMenu_toggler'); assert.containsOnce( document.body, '.o_ThreadPreview_markAsRead', diff --git a/addons/mail/static/src/components/thread_preview/thread_preview.js b/addons/mail/static/src/components/thread_preview/thread_preview.js index 1b423cb5c76..6601a3b6348 100644 --- a/addons/mail/static/src/components/thread_preview/thread_preview.js +++ b/addons/mail/static/src/components/thread_preview/thread_preview.js @@ -31,10 +31,10 @@ export class ThreadPreview extends Component { * @returns {string} */ image() { - if (this.thread.correspondent) { - return this.thread.correspondent.avatarUrl; + if (this.threadPreviewView.thread.correspondent) { + return this.threadPreviewView.thread.correspondent.avatarUrl; } - return `/web/image/mail.channel/${this.thread.id}/avatar_128?unique=${this.thread.avatarCacheKey}`; + return `/web/image/mail.channel/${this.threadPreviewView.thread.id}/avatar_128?unique=${this.threadPreviewView.thread.avatarCacheKey}`; } /** @@ -43,17 +43,17 @@ export class ThreadPreview extends Component { * @returns {string} */ get inlineLastMessageBody() { - if (!this.thread.lastMessage) { + if (!this.threadPreviewView.thread.lastMessage) { return ''; } - return mailUtils.htmlToTextContentInline(this.thread.lastMessage.prettyBody); + return mailUtils.htmlToTextContentInline(this.threadPreviewView.thread.lastMessage.prettyBody); } /** - * @returns {Thread} + * @returns {ThreadPreviewView} */ - get thread() { - return this.messaging && this.messaging.models['Thread'].get(this.props.threadLocalId); + get threadPreviewView() { + return this.messaging && this.messaging.models['ThreadPreviewView'].get(this.props.localId); } //-------------------------------------------------------------------------- @@ -70,7 +70,7 @@ export class ThreadPreview extends Component { // handled in `_onClickMarkAsRead` return; } - this.thread.open(); + this.threadPreviewView.thread.open(); if (!this.messaging.device.isMobile) { this.messaging.messagingMenu.close(); } @@ -81,17 +81,15 @@ export class ThreadPreview extends Component { * @param {MouseEvent} ev */ _onClickMarkAsRead(ev) { - if (this.thread.lastNonTransientMessage) { - this.thread.markAsSeen(this.thread.lastNonTransientMessage); + if (this.threadPreviewView.thread.lastNonTransientMessage) { + this.threadPreviewView.thread.markAsSeen(this.threadPreviewView.thread.lastNonTransientMessage); } } } Object.assign(ThreadPreview, { - props: { - threadLocalId: String, - }, + props: { localId: String }, template: 'mail.ThreadPreview', }); diff --git a/addons/mail/static/src/components/thread_preview/thread_preview.xml b/addons/mail/static/src/components/thread_preview/thread_preview.xml index a31d3259c08..0e035afa3f7 100644 --- a/addons/mail/static/src/components/thread_preview/thread_preview.xml +++ b/addons/mail/static/src/components/thread_preview/thread_preview.xml @@ -6,55 +6,55 @@ The preview template is used by the discuss in mobile, and by the systray menu in order to show preview of threads. --> -
- +
+
Thread Image - +
- - + + - - - () + + + () - - + + - - - + + +
- + - +
diff --git a/addons/mail/static/src/models/discuss/discuss.js b/addons/mail/static/src/models/discuss/discuss.js index c186f3b0ea1..4ee23455618 100644 --- a/addons/mail/static/src/models/discuss/discuss.js +++ b/addons/mail/static/src/models/discuss/discuss.js @@ -299,6 +299,13 @@ registerModel({ } return clear(); }, + /** + * @private + * @returns {FieldCommand} + */ + _computeNotificationListView() { + return (this.messaging.device.isMobile && this.activeMobileNavbarTabId !== 'mailbox') ? insertAndReplace() : clear(); + }, /** * Only pinned threads are allowed in discuss. * @@ -401,6 +408,11 @@ registerModel({ menu_id: attr({ default: null, }), + notificationListView: one2one('NotificationListView', { + compute: '_computeNotificationListView', + inverse: 'discussOwner', + isCausal: true, + }), /** * The navbar view on the discuss app when in mobile and when not * replying to a message from inbox. diff --git a/addons/mail/static/src/models/messaging_menu/messaging_menu.js b/addons/mail/static/src/models/messaging_menu/messaging_menu.js index 73dfa549ad2..e295075ce7b 100644 --- a/addons/mail/static/src/models/messaging_menu/messaging_menu.js +++ b/addons/mail/static/src/models/messaging_menu/messaging_menu.js @@ -51,7 +51,7 @@ registerModel({ }, /** * @private - * @returns {MobileMessagingNavbarView|FieldCommand} + * @returns {FieldCommand} */ _computeMobileMessagingNavbarView() { if (this.messaging.device && this.messaging.device.isMobile) { @@ -59,6 +59,12 @@ registerModel({ } return clear(); }, + /** + * @returns {FieldCommand} + */ + _computeNotificationListView() { + return this.isOpen ? insertAndReplace() : clear(); + }, }, fields: { /** @@ -88,6 +94,11 @@ registerModel({ isOpen: attr({ default: false, }), + notificationListView: one2one('NotificationListView', { + compute: '_computeNotificationListView', + inverse: 'messagingMenuOwner', + isCausal: true, + }), /** * The navbar view on the messaging menu when in mobile. */ diff --git a/addons/mail/static/src/models/notification_group/notification_group.js b/addons/mail/static/src/models/notification_group/notification_group.js index d246907d0bc..930a3130730 100644 --- a/addons/mail/static/src/models/notification_group/notification_group.js +++ b/addons/mail/static/src/models/notification_group/notification_group.js @@ -127,6 +127,10 @@ registerModel({ notifications: one2many('Notification', { inverse: 'notificationGroup', }), + notificationGroupViews: one2many('NotificationGroupView', { + inverse: 'notificationGroup', + isCausal: true, + }), res_id: attr({ readonly: true, }), diff --git a/addons/mail/static/src/models/notification_group_view/notification_group_view.js b/addons/mail/static/src/models/notification_group_view/notification_group_view.js new file mode 100644 index 00000000000..24e8c0e2762 --- /dev/null +++ b/addons/mail/static/src/models/notification_group_view/notification_group_view.js @@ -0,0 +1,21 @@ +/** @odoo-module **/ + +import { registerModel } from '@mail/model/model_core'; +import { many2one } from '@mail/model/model_field'; + +registerModel({ + name: 'NotificationGroupView', + identifyingFields: ['notificationListViewOwner', 'notificationGroup'], + fields: { + notificationGroup: many2one('NotificationGroup', { + inverse: 'notificationGroupViews', + readonly: true, + required: true, + }), + notificationListViewOwner: many2one('NotificationListView', { + inverse: 'notificationGroupViews', + readonly: true, + required: true, + }), + }, +}); diff --git a/addons/mail/static/src/models/notification_list_view/notification_list_view.js b/addons/mail/static/src/models/notification_list_view/notification_list_view.js new file mode 100644 index 00000000000..e372b5fa2fa --- /dev/null +++ b/addons/mail/static/src/models/notification_list_view/notification_list_view.js @@ -0,0 +1,227 @@ +/** @odoo-module **/ + +import { registerModel } from '@mail/model/model_core'; +import { attr, many2many, one2many, one2one } from '@mail/model/model_field'; +import { clear, insertAndReplace, replace } from '@mail/model/model_field_command'; + +registerModel({ + name: 'NotificationListView', + identifyingFields: [['discussOwner', 'messagingMenuOwner']], + recordMethods: { + /** + * @private + * @returns {string|FieldCommand} + */ + _computeFilter() { + if (this.discussOwner) { + return this.discussOwner.activeMobileNavbarTabId; + } + if (this.messagingMenuOwner) { + return this.messagingMenuOwner.activeTabId; + } + return clear(); + }, + /** + * @private + * @returns {FieldCommand} + */ + _computeFilteredThreads() { + switch (this.filter) { + case 'mailbox': { + return replace(this.messaging.models['Thread'] + .all(thread => thread.isPinned && thread.model === 'mail.box') + .sort((mailbox1, mailbox2) => { + if (mailbox1 === this.messaging.inbox) { + return -1; + } + if (mailbox2 === this.messaging.inbox) { + return 1; + } + if (mailbox1 === this.messaging.starred) { + return -1; + } + if (mailbox2 === this.messaging.starred) { + return 1; + } + const mailbox1Name = mailbox1.displayName; + const mailbox2Name = mailbox2.displayName; + mailbox1Name < mailbox2Name ? -1 : 1; + }) + ); + } + case 'channel': { + return replace(this.messaging.models['Thread'] + .all(thread => + thread.channel_type === 'channel' && + thread.isPinned && + thread.model === 'mail.channel' + ) + .sort((c1, c2) => c1.displayName < c2.displayName ? -1 : 1) + ); + } + case 'chat': { + return replace(this.messaging.models['Thread'] + .all(thread => + thread.isChatChannel && + thread.isPinned && + thread.model === 'mail.channel' + ) + .sort((c1, c2) => c1.displayName < c2.displayName ? -1 : 1) + ); + } + case 'all': { + // "All" filter is for channels and chats + return replace(this.messaging.models['Thread'] + .all(thread => thread.isPinned && thread.model === 'mail.channel') + .sort((c1, c2) => c1.displayName < c2.displayName ? -1 : 1) + ); + } + } + return clear(); + }, + /** + * @private + * @returns {FieldCommand} + */ + _computeNotificationGroupViews() { + if (this.filter !== 'all') { + return clear(); + } + return insertAndReplace( + this.models['NotificationGroup'] + .all() + .sort((group1, group2) => group1.sequence - group2.sequence) + .map(notificationGroup => { + return { notificationGroup: replace(notificationGroup) }; + }) + ); + }, + /** + * @private + * @returns {FieldCommand} + */ + _computeNotificationRequestView() { + return (this.filter === 'all' && this.messaging.isNotificationPermissionDefault) ? insertAndReplace() : clear(); + }, + /** + * @private + * @returns {FieldCommand} + */ + _computeNotificationViews() { + const notifications = []; + if (this.notificationRequestView) { + notifications.push(this.notificationRequestView); + } + notifications.push(...this.notificationGroupViews); + notifications.push(...this.threadNeedactionPreviewViews); + notifications.push(...this.threadPreviewViews); + return replace(notifications); + }, + /** + * @private + * @returns {FieldCommand} + */ + _computeThreadNeedactionPreviewViews() { + if (this.filter !== 'all') { + return clear(); + } + return insertAndReplace( + this.messaging.models['Thread'] + .all(t => t.model !== 'mail.box' && t.needactionMessagesAsOriginThread.length > 0) + .sort((t1, t2) => { + if (t1.needactionMessagesAsOriginThread.length > 0 && t2.needactionMessagesAsOriginThread.length === 0) { + return -1; + } + if (t1.needactionMessagesAsOriginThread.length === 0 && t2.needactionMessagesAsOriginThread.length > 0) { + return 1; + } + if (t1.lastNeedactionMessageAsOriginThread && t2.lastNeedactionMessageAsOriginThread) { + return t1.lastNeedactionMessageAsOriginThread.id < t2.lastNeedactionMessageAsOriginThread.id ? 1 : -1; + } + if (t1.lastNeedactionMessageAsOriginThread) { + return -1; + } + if (t2.lastNeedactionMessageAsOriginThread) { + return 1; + } + return t1.id < t2.id ? -1 : 1; + }) + .map(thread => { + return { thread: replace(thread) }; + }) + ); + }, + /** + * @private + * @returns {FieldCommand} + */ + _computeThreadPreviewViews() { + return insertAndReplace( + this.filteredThreads + .sort((t1, t2) => { + if (t1.localMessageUnreadCounter > 0 && t2.localMessageUnreadCounter === 0) { + return -1; + } + if (t1.localMessageUnreadCounter === 0 && t2.localMessageUnreadCounter > 0) { + return 1; + } + if (t1.lastMessage && t2.lastMessage) { + return t1.lastMessage.id < t2.lastMessage.id ? 1 : -1; + } + if (t1.lastMessage) { + return -1; + } + if (t2.lastMessage) { + return 1; + } + return t1.id < t2.id ? -1 : 1; + }) + .map(thread => { + return { + thread: replace(thread), + }; + }) + ); + }, + }, + fields: { + discussOwner: one2one('Discuss', { + inverse: 'notificationListView', + readonly: true, + }), + filter: attr({ + compute: '_computeFilter', + }), + filteredThreads: many2many('Thread', { + compute: '_computeFilteredThreads', + }), + messagingMenuOwner: one2one('MessagingMenu', { + inverse: 'notificationListView', + readonly: true, + }), + notificationGroupViews: one2many('NotificationGroupView', { + compute: '_computeNotificationGroupViews', + inverse: 'notificationListViewOwner', + isCausal: true, + }), + notificationRequestView: one2one('NotificationRequestView', { + compute: '_computeNotificationRequestView', + inverse: 'notificationListViewOwner', + isCausal: true, + }), + notificationViews: one2many('Model', { + compute: '_computeNotificationViews', + isCausal: true, + }), + threadNeedactionPreviewViews: one2many('ThreadNeedactionPreviewView', { + compute: '_computeThreadNeedactionPreviewViews', + inverse: 'notificationListViewOwner', + isCausal: true, + }), + threadPreviewViews: one2many('ThreadPreviewView', { + compute: '_computeThreadPreviewViews', + inverse: 'notificationListViewOwner', + isCausal: true, + }), + }, +}); diff --git a/addons/mail/static/src/models/notification_list_view/tests/notification_list_view_qunit_tests.js b/addons/mail/static/src/models/notification_list_view/tests/notification_list_view_qunit_tests.js new file mode 100644 index 00000000000..ae07d813502 --- /dev/null +++ b/addons/mail/static/src/models/notification_list_view/tests/notification_list_view_qunit_tests.js @@ -0,0 +1,25 @@ +/** @odoo-module **/ + +import { addFields, patchIdentifyingFields, patchRecordMethods } from '@mail/model/model_core'; +import { one2one } from '@mail/model/model_field'; +import '@mail/models/notification_list_view/notification_list_view'; // ensure the model definition is loaded before the patch + +addFields('NotificationListView', { + qunitTestOwner: one2one('QUnitTest', { + inverse: 'notificationListView', + readonly: true, + }), +}); + +patchIdentifyingFields('NotificationListView', identifyingFields => { + identifyingFields[0].push('qunitTestOwner'); +}); + +patchRecordMethods('NotificationListView', { + _computeFilter() { + if (this.qunitTestOwner) { + return this.filter; + } + return this._super(); + }, +}); diff --git a/addons/mail/static/src/models/notification_request_view/notification_request_view.js b/addons/mail/static/src/models/notification_request_view/notification_request_view.js new file mode 100644 index 00000000000..dd8363918ea --- /dev/null +++ b/addons/mail/static/src/models/notification_request_view/notification_request_view.js @@ -0,0 +1,16 @@ +/** @odoo-module **/ + +import { registerModel } from '@mail/model/model_core'; +import { one2one } from '@mail/model/model_field'; + +registerModel({ + name: 'NotificationRequestView', + identifyingFields: ['notificationListViewOwner'], + fields: { + notificationListViewOwner: one2one('NotificationListView', { + inverse: 'notificationRequestView', + required: true, + readonly: true, + }), + }, +}); diff --git a/addons/mail/static/src/models/thread/thread.js b/addons/mail/static/src/models/thread/thread.js index 8d42b27f3ea..1747ddf0d0a 100644 --- a/addons/mail/static/src/models/thread/thread.js +++ b/addons/mail/static/src/models/thread/thread.js @@ -2421,6 +2421,14 @@ registerModel({ todayActivities: one2many('Activity', { compute: '_computeTodayActivities', }), + threadNeedactionPreviewViews: one2many('ThreadNeedactionPreviewView', { + inverse: 'thread', + isCausal: true, + }), + threadPreviewViews: one2many('ThreadPreviewView', { + inverse: 'thread', + isCausal: true, + }), /** * Members that are currently typing something in the composer of this * thread, including current partner. diff --git a/addons/mail/static/src/models/thread_needaction_preview_view/thread_needaction_preview_view.js b/addons/mail/static/src/models/thread_needaction_preview_view/thread_needaction_preview_view.js new file mode 100644 index 00000000000..24fa3f23953 --- /dev/null +++ b/addons/mail/static/src/models/thread_needaction_preview_view/thread_needaction_preview_view.js @@ -0,0 +1,21 @@ +/** @odoo-module **/ + +import { registerModel } from '@mail/model/model_core'; +import { many2one } from '@mail/model/model_field'; + +registerModel({ + name: 'ThreadNeedactionPreviewView', + identifyingFields: ['notificationListViewOwner', 'thread'], + fields: { + notificationListViewOwner: many2one('NotificationListView', { + inverse: 'threadNeedactionPreviewViews', + readonly: true, + required: true, + }), + thread: many2one('Thread', { + inverse: 'threadNeedactionPreviewViews', + readonly: true, + required: true, + }), + }, +}); diff --git a/addons/mail/static/src/models/thread_preview_view/thread_preview_view.js b/addons/mail/static/src/models/thread_preview_view/thread_preview_view.js new file mode 100644 index 00000000000..5cd9b47df25 --- /dev/null +++ b/addons/mail/static/src/models/thread_preview_view/thread_preview_view.js @@ -0,0 +1,21 @@ +/** @odoo-module **/ + +import { registerModel } from '@mail/model/model_core'; +import { many2one } from '@mail/model/model_field'; + +registerModel({ + name: 'ThreadPreviewView', + identifyingFields: ['notificationListViewOwner', 'thread'], + fields: { + notificationListViewOwner: many2one('NotificationListView', { + inverse: 'threadPreviewViews', + readonly: true, + required: true, + }), + thread: many2one('Thread', { + inverse: 'threadPreviewViews', + readonly: true, + required: true, + }), + }, +}); diff --git a/addons/mail/static/src/utils/test_utils.js b/addons/mail/static/src/utils/test_utils.js index 423a14fc8f1..e58b242cc2b 100644 --- a/addons/mail/static/src/utils/test_utils.js +++ b/addons/mail/static/src/utils/test_utils.js @@ -472,6 +472,19 @@ function getCreateMessagingMenuComponent({ components, env, widget }) { }; } +function getCreateNotificationListComponent({ components, env, modelManager, widget }) { + return async function createNotificationListComponent({ filter = 'all' } = {}) { + const notificationListView = modelManager.messaging.models['NotificationListView'].create({ + filter, + qunitTestOwner: insertAndReplace(), + }); + await createRootMessagingComponent({ components, env }, "NotificationList", { + props: { localId: notificationListView.localId }, + target: widget.el, + }); + }; +} + function getCreateThreadViewComponent({ afterEvent, components, env, widget }) { return async function createThreadViewComponent(threadView, otherProps = {}, { isFixedSize = false, waitUntilMessagesLoaded = true } = {}) { let target; @@ -830,6 +843,7 @@ async function start(param0 = {}) { createComposerSuggestionComponent: getCreateComposerSuggestionComponent({ components, env: testEnv, modelManager, widget }), createMessageComponent: getCreateMessageComponent({ components, env: testEnv, modelManager, widget }), createMessagingMenuComponent: getCreateMessagingMenuComponent({ components, env: testEnv, widget }), + createNotificationListComponent: getCreateNotificationListComponent({ components, env: testEnv, modelManager, widget }), createThreadViewComponent: getCreateThreadViewComponent({ afterEvent, components, env: testEnv, widget }), openDiscuss, }; diff --git a/addons/mail/static/tests/qunit_test.js b/addons/mail/static/tests/qunit_test.js index 784afa29976..be6742052a3 100644 --- a/addons/mail/static/tests/qunit_test.js +++ b/addons/mail/static/tests/qunit_test.js @@ -18,6 +18,10 @@ registerModel({ inverse: 'qunitTest', isCausal: true, }), + notificationListView: one2one('NotificationListView', { + inverse: 'qunitTestOwner', + isCausal: true, + }), threadViewer: one2one('ThreadViewer', { inverse: 'qunitTest', isCausal: true, diff --git a/addons/sms/static/src/components/notification_group/notification_group.js b/addons/sms/static/src/components/notification_group/notification_group.js index ab3002efbba..aa746b9bab7 100644 --- a/addons/sms/static/src/components/notification_group/notification_group.js +++ b/addons/sms/static/src/components/notification_group/notification_group.js @@ -14,7 +14,7 @@ patch(NotificationGroup.prototype, 'sms/static/src/components/notification_group * @override */ image() { - if (this.group.notification_type === 'sms') { + if (this.notificationGroupView.notificationGroup.notification_type === 'sms') { return '/sms/static/img/sms_failure.svg'; } return this._super(...arguments); diff --git a/addons/sms/static/src/components/notification_group/notification_group.xml b/addons/sms/static/src/components/notification_group/notification_group.xml index c5f5a8db5dc..aab9f52728e 100644 --- a/addons/sms/static/src/components/notification_group/notification_group.xml +++ b/addons/sms/static/src/components/notification_group/notification_group.xml @@ -3,7 +3,7 @@ - + An error occurred when sending an SMS. diff --git a/addons/sms/static/src/components/notification_list/tests/notification_list_notification_group_tests.js b/addons/sms/static/src/components/notification_list/tests/notification_list_notification_group_tests.js index 4d2e23916f1..901a7c1da15 100644 --- a/addons/sms/static/src/components/notification_list/tests/notification_list_notification_group_tests.js +++ b/addons/sms/static/src/components/notification_list/tests/notification_list_notification_group_tests.js @@ -1,14 +1,8 @@ -odoo.define('sms/static/src/components/notification_list/notification_list_notification_group_tests.js', function (require) { -'use strict'; +/** @odoo-module **/ -const { - afterEach, - beforeEach, - createRootMessagingComponent, - start, -} = require('@mail/utils/test_utils'); +import { afterEach, beforeEach, start } from '@mail/utils/test_utils'; -const Bus = require('web.Bus'); +import Bus from 'web.Bus'; QUnit.module('sms', {}, function () { QUnit.module('components', {}, function () { @@ -17,23 +11,14 @@ QUnit.module('notification_list_notification_group_tests.js', { beforeEach() { beforeEach(this); - /** - * @param {Object} param0 - * @param {string} [param0.filter='all'] - */ - this.createNotificationListComponent = async ({ filter = 'all' } = {}) => { - await createRootMessagingComponent(this, "NotificationList", { - props: { filter }, - target: this.widget.el, - }); - }; - this.start = async params => { - const { env, widget } = await start(Object.assign({}, params, { + const res = await start(Object.assign({}, params, { data: this.data, })); + const { env, widget } = res; this.env = env; this.widget = widget; + return res; }; }, afterEach() { @@ -81,8 +66,8 @@ QUnit.test('mark as read', async function (assert) { ); }); - await this.start({ env: { bus } }); - await this.createNotificationListComponent(); + const { createNotificationListComponent } = await this.start({ env: { bus } }); + await createNotificationListComponent(); assert.containsOnce( document.body, @@ -132,8 +117,8 @@ QUnit.test('notifications grouped by notification_type', async function (assert) notification_type: 'email', // different type from first failure } ); - await this.start(); - await this.createNotificationListComponent(); + const { createNotificationListComponent } = await this.start(); + await createNotificationListComponent(); assert.containsN( document.body, @@ -272,8 +257,8 @@ QUnit.test('grouped notifications by document model', async function (assert) { ); }); - await this.start({ env: { bus } }); - await this.createNotificationListComponent(); + const { createNotificationListComponent } = await this.start({ env: { bus } }); + await createNotificationListComponent(); assert.containsOnce( document.body, @@ -301,5 +286,3 @@ QUnit.test('grouped notifications by document model', async function (assert) { }); }); }); - -}); diff --git a/addons/snailmail/static/src/components/notification_group/notification_group.js b/addons/snailmail/static/src/components/notification_group/notification_group.js index a36d8f5678b..3b71701f897 100644 --- a/addons/snailmail/static/src/components/notification_group/notification_group.js +++ b/addons/snailmail/static/src/components/notification_group/notification_group.js @@ -14,7 +14,7 @@ patch(NotificationGroup.prototype, 'snailmail/static/src/components/notification * @override */ image() { - if (this.group.notification_type === 'snail') { + if (this.notificationGroupView.notificationGroup.notification_type === 'snail') { return '/snailmail/static/img/snailmail_failure.png'; } return this._super(...arguments); diff --git a/addons/snailmail/static/src/components/notification_group/notification_group.xml b/addons/snailmail/static/src/components/notification_group/notification_group.xml index 7f04e716072..3a445bea711 100644 --- a/addons/snailmail/static/src/components/notification_group/notification_group.xml +++ b/addons/snailmail/static/src/components/notification_group/notification_group.xml @@ -3,7 +3,7 @@ - + An error occurred when sending a letter with Snailmail. diff --git a/addons/snailmail/static/src/components/notification_list/tests/notification_list_notification_group_tests.js b/addons/snailmail/static/src/components/notification_list/tests/notification_list_notification_group_tests.js index 34a80641843..7fe8aca956d 100644 --- a/addons/snailmail/static/src/components/notification_list/tests/notification_list_notification_group_tests.js +++ b/addons/snailmail/static/src/components/notification_list/tests/notification_list_notification_group_tests.js @@ -1,11 +1,6 @@ /** @odoo-module **/ -import { - afterEach, - beforeEach, - createRootMessagingComponent, - start, -} from '@mail/utils/test_utils'; +import { afterEach, beforeEach, start } from '@mail/utils/test_utils'; import Bus from 'web.Bus'; @@ -16,23 +11,14 @@ QUnit.module('notification_list_notification_group_tests.js', { beforeEach() { beforeEach(this); - /** - * @param {Object} param0 - * @param {string} [param0.filter='all'] - */ - this.createNotificationListComponent = async ({ filter = 'all' } = {}) => { - await createRootMessagingComponent(this, "NotificationList", { - props: { filter }, - target: this.widget.el, - }); - }; - this.start = async params => { - const { env, widget } = await start(Object.assign({}, params, { + const res = await start(Object.assign({}, params, { data: this.data, })); + const { env, widget } = res; this.env = env; this.widget = widget; + return res; }; }, afterEach() { @@ -75,8 +61,8 @@ QUnit.test('mark as read', async function (assert) { "action should have the group notification length as unread_counter" ); }); - await this.start({ env: { bus } }); - await this.createNotificationListComponent(); + const { createNotificationListComponent } = await this.start({ env: { bus } }); + await createNotificationListComponent(); assert.containsOnce( document.body, @@ -126,8 +112,8 @@ QUnit.test('notifications grouped by notification_type', async function (assert) notification_type: 'email', // different type from first failure } ); - await this.start(); - await this.createNotificationListComponent(); + const { createNotificationListComponent } = await this.start(); + await createNotificationListComponent(); assert.containsN( document.body, @@ -266,8 +252,8 @@ QUnit.test('grouped notifications by document model', async function (assert) { ); }); - await this.start({ env: { bus } }); - await this.createNotificationListComponent(); + const { createNotificationListComponent } = await this.start({ env: { bus } }); + await createNotificationListComponent(); assert.containsOnce( document.body,