diff --git a/addons/mail/static/src/components/message/message.js b/addons/mail/static/src/components/message/message.js
index 682fed0a4a2..7f765e06e8b 100644
--- a/addons/mail/static/src/components/message/message.js
+++ b/addons/mail/static/src/components/message/message.js
@@ -1,12 +1,12 @@
/** @odoo-module **/
import { useComponentToModel } from '@mail/component_hooks/use_component_to_model';
+import { useRefToModel } from '@mail/component_hooks/use_ref_to_model';
import { useUpdate } from '@mail/component_hooks/use_update';
import { useUpdateToModel } from '@mail/component_hooks/use_update_to_model';
import { registerMessagingComponent } from '@mail/utils/messaging_component';
import { _lt } from 'web.core';
-import Popover from "web.Popover";
const { Component, useRef } = owl;
@@ -21,6 +21,7 @@ export class Message extends Component {
setup() {
super.setup();
useComponentToModel({ fieldName: 'component' });
+ useRefToModel({ fieldName: 'notificationIconRef', refName: 'notificationIcon' });
useUpdateToModel({ methodName: 'onComponentUpdate' });
useUpdate({ func: () => this._update() });
/**
@@ -259,7 +260,6 @@ export class Message extends Component {
Object.assign(Message, {
props: { record: Object },
template: 'mail.Message',
- components: { Popover },
});
registerMessagingComponent(Message);
diff --git a/addons/mail/static/src/components/message/message.xml b/addons/mail/static/src/components/message/message.xml
index b06505cac8d..7d29bd0b863 100644
--- a/addons/mail/static/src/components/message/message.xml
+++ b/addons/mail/static/src/components/message/message.xml
@@ -114,18 +114,13 @@
-
+
-
-
-
-
-
-
-
-
+
+
+
diff --git a/addons/mail/static/src/components/message_notification_popover_content/message_notification_popover_content.js b/addons/mail/static/src/components/message_notification_popover_content/message_notification_popover_content.js
index 61165967656..b456ea6f075 100644
--- a/addons/mail/static/src/components/message_notification_popover_content/message_notification_popover_content.js
+++ b/addons/mail/static/src/components/message_notification_popover_content/message_notification_popover_content.js
@@ -7,9 +7,9 @@ const { Component } = owl;
export class MessageNotificationPopoverContent extends Component {
/**
- * @returns {MessageView}
+ * @returns {MessageNotificationPopoverContentView}
*/
- get messageView() {
+ get messageNotificationPopoverContentView() {
return this.props.record;
}
diff --git a/addons/mail/static/src/components/message_notification_popover_content/message_notification_popover_content.xml b/addons/mail/static/src/components/message_notification_popover_content/message_notification_popover_content.xml
index b78159df5c7..3dcc9deab51 100644
--- a/addons/mail/static/src/components/message_notification_popover_content/message_notification_popover_content.xml
+++ b/addons/mail/static/src/components/message_notification_popover_content/message_notification_popover_content.xml
@@ -2,20 +2,16 @@
-
-
diff --git a/addons/mail/static/src/models/message_notification_popover_content_view.js b/addons/mail/static/src/models/message_notification_popover_content_view.js
new file mode 100644
index 00000000000..fd0c95de61f
--- /dev/null
+++ b/addons/mail/static/src/models/message_notification_popover_content_view.js
@@ -0,0 +1,17 @@
+/** @odoo-module **/
+
+import { registerModel } from '@mail/model/model_core';
+import { one } from '@mail/model/model_field';
+
+registerModel({
+ name: 'MessageNotificationPopoverContentView',
+ fields: {
+ messageView: one('MessageView', {
+ related: 'popoverViewOwner.messageViewOwnerAsNotificationContent',
+ }),
+ popoverViewOwner: one('PopoverView', {
+ identifying: true,
+ inverse: 'messageNotificationPopoverContentView',
+ }),
+ },
+});
diff --git a/addons/mail/static/src/models/message_view.js b/addons/mail/static/src/models/message_view.js
index 46b8f63f5a1..a8b13e5b641 100644
--- a/addons/mail/static/src/models/message_view.js
+++ b/addons/mail/static/src/models/message_view.js
@@ -96,6 +96,9 @@ registerModel({
markEventHandled(ev, 'Message.ClickFailure');
this.message.openResendAction();
},
+ onClickNotificationIcon() {
+ this.update({ notificationPopoverView: {} });
+ },
/**
* @param {MouseEvent} ev
*/
@@ -230,6 +233,20 @@ registerModel({
}
return clear();
},
+ /**
+ * @private
+ * @returns {FieldCommand}
+ */
+ _computeFailureNotificationIconClassName() {
+ return clear();
+ },
+ /**
+ * @private
+ * @returns {FieldCommand}
+ */
+ _computeFailureNotificationIconLabel() {
+ return clear();
+ },
/**
* @private
* @returns {boolean}
@@ -410,6 +427,20 @@ registerModel({
}
return clear();
},
+ /**
+ * @private
+ * @returns {string}
+ */
+ _computeNotificationIconClassName() {
+ return clear();
+ },
+ /**
+ * @private
+ * @returns {FieldCommand}
+ */
+ _computeNotificationIconLabel() {
+ return clear();
+ },
/**
* @private
* @returns {FieldCommand}
@@ -484,6 +515,14 @@ registerModel({
compute: '_computeExtraClass',
default: '',
}),
+ failureNotificationIconClassName: attr({
+ compute: '_computeFailureNotificationIconClassName',
+ default: 'fa fa-envelope',
+ }),
+ failureNotificationIconLabel: attr({
+ compute: '_computeFailureNotificationIconLabel',
+ default: '',
+ }),
/**
* Determines whether author open chat feature is enabled on message.
*/
@@ -603,6 +642,19 @@ registerModel({
messagingAsClickedMessageView: one('Messaging', {
inverse: 'clickedMessageView',
}),
+ notificationIconClassName: attr({
+ compute: '_computeNotificationIconClassName',
+ default: 'fa fa-envelope-o',
+ }),
+ notificationIconLabel: attr({
+ compute: '_computeNotificationIconLabel',
+ default: '',
+ }),
+ notificationIconRef: attr(),
+ notificationPopoverView: one('PopoverView', {
+ inverse: 'messageViewOwnerAsNotificationContent',
+ isCausal: true,
+ }),
personaImStatusIconView: one('PersonaImStatusIconView', {
compute: '_computePersonaImStatusIconView',
inverse: 'messageViewOwner',
diff --git a/addons/mail/static/src/models/popover_view.js b/addons/mail/static/src/models/popover_view.js
index 8982d688b42..1c548b491dd 100644
--- a/addons/mail/static/src/models/popover_view.js
+++ b/addons/mail/static/src/models/popover_view.js
@@ -53,6 +53,9 @@ registerModel({
if (this.messageActionViewOwnerAsReaction) {
return this.messageActionViewOwnerAsReaction.actionRef;
}
+ if (this.messageViewOwnerAsNotificationContent) {
+ return this.messageViewOwnerAsNotificationContent.notificationIconRef;
+ }
return clear();
},
/**
@@ -79,6 +82,9 @@ registerModel({
if (this.emojiPickerView) {
return this.emojiPickerView;
}
+ if (this.messageNotificationPopoverContentView) {
+ return this.messageNotificationPopoverContentView;
+ }
return clear();
},
/**
@@ -108,6 +114,9 @@ registerModel({
if (this.emojiPickerView) {
return 'EmojiPickerView';
}
+ if (this.messageNotificationPopoverContentView) {
+ return 'MessageNotificationPopoverContent';
+ }
return clear();
},
/**
@@ -133,6 +142,16 @@ registerModel({
}
return clear();
},
+ /**
+ * @private
+ * @returns {Object|FieldCommand}
+ */
+ _computeMessageNotificationPopoverContentView() {
+ if (this.messageViewOwnerAsNotificationContent) {
+ return {};
+ }
+ return clear();
+ },
/**
* @private
* @returns {string}
@@ -249,6 +268,15 @@ registerModel({
identifying: true,
inverse: 'reactionPopoverView',
}),
+ messageNotificationPopoverContentView: one('MessageNotificationPopoverContentView', {
+ compute: '_computeMessageNotificationPopoverContentView',
+ inverse: 'popoverViewOwner',
+ isCausal: true,
+ }),
+ messageViewOwnerAsNotificationContent: one('MessageView', {
+ identifying: true,
+ inverse: 'notificationPopoverView',
+ }),
/**
* Position of the popover view relative to its anchor point.
* Valid values: 'top', 'right', 'bottom', 'left'
diff --git a/addons/sms/static/src/components/message/message.xml b/addons/sms/static/src/components/message/message.xml
deleted file mode 100644
index 4d2224cf73e..00000000000
--- a/addons/sms/static/src/components/message/message.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-
-
- SMS
-
- $0
-
-
-
-
- SMS
-
- $0
-
-
-
-
diff --git a/addons/sms/static/src/models/message_view.js b/addons/sms/static/src/models/message_view.js
new file mode 100644
index 00000000000..7b7fef839ad
--- /dev/null
+++ b/addons/sms/static/src/models/message_view.js
@@ -0,0 +1,44 @@
+/** @odoo-module **/
+
+import { patchRecordMethods } from '@mail/model/model_core';
+// ensure that the model definition is loaded before the patch
+import '@mail/models/message_view';
+
+patchRecordMethods('MessageView', {
+ /**
+ * @override
+ */
+ _computeFailureNotificationIconClassName() {
+ if (this.message && this.message.message_type === 'sms') {
+ return 'fa fa-mobile';
+ }
+ return this._super();
+ },
+ /**
+ * @override
+ */
+ _computeFailureNotificationIconLabel() {
+ if (this.message && this.message.message_type === 'sms') {
+ return this.env._t("SMS");
+ }
+ return this._super();
+ },
+ /**
+ * @override
+ */
+ _computeNotificationIconClassName() {
+ if (this.message && this.message.message_type === 'sms') {
+ return 'fa fa-mobile';
+ }
+ return this._super();
+ },
+ /**
+ * @override
+ */
+ _computeNotificationIconLabel() {
+ if (this.message && this.message.message_type === 'sms') {
+ return this.env._t("SMS");
+ }
+ return this._super();
+ },
+});
diff --git a/addons/snailmail/static/src/components/message/message.xml b/addons/snailmail/static/src/components/message/message.xml
deleted file mode 100644
index fbbf9f5b983..00000000000
--- a/addons/snailmail/static/src/components/message/message.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
-
-
-
-
-
- $0
-
-
-
-
-
-
- $0
-
-
-
-
-
-
-
- $0
-
-
-
-
diff --git a/addons/snailmail/static/src/components/snailmail_notification_popover/snailmail_notification_popover.js b/addons/snailmail/static/src/components/snailmail_notification_popover/snailmail_notification_popover.js
index 441a1597ec7..9eaa1649cb1 100644
--- a/addons/snailmail/static/src/components/snailmail_notification_popover/snailmail_notification_popover.js
+++ b/addons/snailmail/static/src/components/snailmail_notification_popover/snailmail_notification_popover.js
@@ -4,7 +4,7 @@ import { registerMessagingComponent } from '@mail/utils/messaging_component';
const { Component } = owl;
-class SnailmailNotificationPopover extends Component {
+export default class SnailmailNotificationPopoverContentView extends Component {
/**
* @returns {string}
@@ -39,10 +39,10 @@ class SnailmailNotificationPopover extends Component {
}
/**
- * @returns {Message}
+ * @returns {SnailmailNotificationPopoverContentView}
*/
- get message() {
- return this.props.message;
+ get snailmailNotificationPopoverContentView() {
+ return this.props.record;
}
/**
@@ -50,16 +50,15 @@ class SnailmailNotificationPopover extends Component {
*/
get notification() {
// Messages from snailmail are considered to have at most one notification.
- return this.message.notifications[0];
+ return this.snailmailNotificationPopoverContentView.message.notifications[0];
}
}
-Object.assign(SnailmailNotificationPopover, {
- props: { message: Object },
- template: 'snailmail.SnailmailNotificationPopover',
+Object.assign(SnailmailNotificationPopoverContentView, {
+ props: { record: Object },
+ template: 'snailmail.SnailmailNotificationPopoverContentView',
});
-registerMessagingComponent(SnailmailNotificationPopover);
+registerMessagingComponent(SnailmailNotificationPopoverContentView);
-export default SnailmailNotificationPopover;
diff --git a/addons/snailmail/static/src/components/snailmail_notification_popover/snailmail_notification_popover.scss b/addons/snailmail/static/src/components/snailmail_notification_popover/snailmail_notification_popover.scss
index 970bc79d997..e2a7c7c11a8 100644
--- a/addons/snailmail/static/src/components/snailmail_notification_popover/snailmail_notification_popover.scss
+++ b/addons/snailmail/static/src/components/snailmail_notification_popover/snailmail_notification_popover.scss
@@ -2,6 +2,6 @@
// Layout
// -----------------------------------------------------------------------------
-.o_SnailmailNotificationPopover_icon {
+.o_SnailmailNotificationPopoverContentView_icon {
margin-inline-end: map-get($spacers, 2);
}
diff --git a/addons/snailmail/static/src/components/snailmail_notification_popover/snailmail_notification_popover.xml b/addons/snailmail/static/src/components/snailmail_notification_popover/snailmail_notification_popover.xml
index 69cc4ed0ec7..ca31bc91c71 100644
--- a/addons/snailmail/static/src/components/snailmail_notification_popover/snailmail_notification_popover.xml
+++ b/addons/snailmail/static/src/components/snailmail_notification_popover/snailmail_notification_popover.xml
@@ -1,15 +1,11 @@
-
-
-
-
-
-
-
-
-
+
+
+
+
+
diff --git a/addons/snailmail/static/src/models/message_view.js b/addons/snailmail/static/src/models/message_view.js
index 7bbb50215ab..dc77f59c1df 100644
--- a/addons/snailmail/static/src/models/message_view.js
+++ b/addons/snailmail/static/src/models/message_view.js
@@ -10,6 +10,10 @@ addFields('MessageView', {
inverse: 'messageViewOwnerAsSnailmailError',
isCausal: true,
}),
+ snailmailNotificationPopoverView: one('PopoverView', {
+ inverse: 'messageViewOwnerAsSnailmailNotificationContent',
+ isCausal: true,
+ }),
});
patchRecordMethods('MessageView', {
@@ -52,4 +56,29 @@ patchRecordMethods('MessageView', {
this._super(...arguments);
}
},
+ onClickNotificationIcon() {
+ if (this.message && this.message.message_type === 'snailmail') {
+ this.update({ snailmailNotificationPopoverView: {} });
+ return;
+ }
+ return this._super();
+ },
+ /**
+ * @override
+ */
+ _computeFailureNotificationIconClassName() {
+ if (this.message && this.message.message_type === 'snailmail') {
+ return 'fa fa-paper-plane';
+ }
+ return this._super();
+ },
+ /**
+ * @override
+ */
+ _computeNotificationIconClassName() {
+ if (this.message && this.message.message_type === 'snailmail') {
+ return 'fa fa-paper-plane';
+ }
+ return this._super();
+ },
});
diff --git a/addons/snailmail/static/src/models/popover_view.js b/addons/snailmail/static/src/models/popover_view.js
new file mode 100644
index 00000000000..64e7926fd75
--- /dev/null
+++ b/addons/snailmail/static/src/models/popover_view.js
@@ -0,0 +1,62 @@
+/** @odoo-module **/
+
+import { addFields, addRecordMethods, 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
+import '@mail/models/popover_view';
+
+addFields('PopoverView', {
+ messageViewOwnerAsSnailmailNotificationContent: one('MessageView', {
+ identifying: true,
+ inverse: 'snailmailNotificationPopoverView',
+ }),
+ snailmailNotificationPopoverContentView: one('SnailmailNotificationPopoverContentView', {
+ compute: '_computeSnailmailNotificationPopoverContentView',
+ inverse: 'popoverViewOwner',
+ isCausal: true,
+ }),
+});
+
+addRecordMethods('PopoverView', {
+ /**
+ * @private
+ * @returns {Object|FieldCommand}
+ */
+ _computeSnailmailNotificationPopoverContentView() {
+ if (this.messageViewOwnerAsSnailmailNotificationContent) {
+ return {};
+ }
+ return clear();
+ },
+});
+
+patchRecordMethods('PopoverView', {
+ /**
+ * @override
+ */
+ _computeAnchorRef() {
+ if (this.messageViewOwnerAsSnailmailNotificationContent) {
+ return this.messageViewOwnerAsSnailmailNotificationContent.notificationIconRef;
+ }
+ return this._super();
+ },
+ /**
+ * @override
+ */
+ _computeContent() {
+ if (this.snailmailNotificationPopoverContentView) {
+ return this.snailmailNotificationPopoverContentView;
+ }
+ return this._super();
+ },
+ /**
+ * @override
+ */
+ _computeContentComponentName() {
+ if (this.snailmailNotificationPopoverContentView) {
+ return 'SnailmailNotificationPopoverContentView';
+ }
+ return this._super();
+ },
+});
diff --git a/addons/snailmail/static/src/models/snailmail_notification_popover_content_view.js b/addons/snailmail/static/src/models/snailmail_notification_popover_content_view.js
new file mode 100644
index 00000000000..154e99d2142
--- /dev/null
+++ b/addons/snailmail/static/src/models/snailmail_notification_popover_content_view.js
@@ -0,0 +1,26 @@
+/** @odoo-module **/
+
+import { registerModel } from '@mail/model/model_core';
+import { one } from '@mail/model/model_field';
+
+registerModel({
+ name: 'SnailmailNotificationPopoverContentView',
+ recordMethods: {
+ /**
+ * @private
+ * @returns {Message}
+ */
+ _computeMessage() {
+ return this.popoverViewOwner.messageViewOwnerAsSnailmailNotificationContent.message;
+ },
+ },
+ fields: {
+ message: one('Message', {
+ compute: '_computeMessage',
+ }),
+ popoverViewOwner: one('PopoverView', {
+ identifying: true,
+ inverse: 'snailmailNotificationPopoverContentView',
+ }),
+ },
+});
diff --git a/addons/snailmail/static/tests/qunit_suite_tests/components/message_tests.js b/addons/snailmail/static/tests/qunit_suite_tests/components/message_tests.js
index 20b333cb00b..70b7d49e076 100644
--- a/addons/snailmail/static/tests/qunit_suite_tests/components/message_tests.js
+++ b/addons/snailmail/static/tests/qunit_suite_tests/components/message_tests.js
@@ -64,21 +64,21 @@ QUnit.test('Sent', async function (assert) {
});
assert.containsOnce(
document.body,
- '.o_SnailmailNotificationPopover',
+ '.o_SnailmailNotificationPopoverContentView',
"notification popover should be open"
);
assert.containsOnce(
document.body,
- '.o_SnailmailNotificationPopover_icon',
+ '.o_SnailmailNotificationPopoverContentView_icon',
"popover should have one icon"
);
assert.hasClass(
- document.querySelector('.o_SnailmailNotificationPopover_icon'),
+ document.querySelector('.o_SnailmailNotificationPopoverContentView_icon'),
'fa-check',
"popover should have the sent icon"
);
assert.strictEqual(
- document.querySelector('.o_SnailmailNotificationPopover').textContent.trim(),
+ document.querySelector('.o_SnailmailNotificationPopoverContentView').textContent.trim(),
"Sent",
"popover should have the sent text"
);
@@ -136,21 +136,21 @@ QUnit.test('Canceled', async function (assert) {
});
assert.containsOnce(
document.body,
- '.o_SnailmailNotificationPopover',
+ '.o_SnailmailNotificationPopoverContentView',
"notification popover should be open"
);
assert.containsOnce(
document.body,
- '.o_SnailmailNotificationPopover_icon',
+ '.o_SnailmailNotificationPopoverContentView_icon',
"popover should have one icon"
);
assert.hasClass(
- document.querySelector('.o_SnailmailNotificationPopover_icon'),
+ document.querySelector('.o_SnailmailNotificationPopoverContentView_icon'),
'fa-trash-o',
"popover should have the canceled icon"
);
assert.strictEqual(
- document.querySelector('.o_SnailmailNotificationPopover').textContent.trim(),
+ document.querySelector('.o_SnailmailNotificationPopoverContentView').textContent.trim(),
"Canceled",
"popover should have the canceled text"
);
@@ -208,21 +208,21 @@ QUnit.test('Pending', async function (assert) {
});
assert.containsOnce(
document.body,
- '.o_SnailmailNotificationPopover',
+ '.o_SnailmailNotificationPopoverContentView',
"notification popover should be open"
);
assert.containsOnce(
document.body,
- '.o_SnailmailNotificationPopover_icon',
+ '.o_SnailmailNotificationPopoverContentView_icon',
"popover should have one icon"
);
assert.hasClass(
- document.querySelector('.o_SnailmailNotificationPopover_icon'),
+ document.querySelector('.o_SnailmailNotificationPopoverContentView_icon'),
'fa-clock-o',
"popover should have the pending icon"
);
assert.strictEqual(
- document.querySelector('.o_SnailmailNotificationPopover').textContent.trim(),
+ document.querySelector('.o_SnailmailNotificationPopoverContentView').textContent.trim(),
"Awaiting Dispatch",
"popover should have the pending text"
);