[IMP] mail, *: tweak style of messaging menu/notification list items

* = sms, snailmail

task-2789056

closes odoo/odoo#86598

Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
This commit is contained in:
Sébastien Theys
2022-03-31 16:28:02 +02:00
parent 7bab57a50a
commit 06cbb5793d
16 changed files with 99 additions and 119 deletions
@@ -21,7 +21,7 @@
&:not(.o-mobile) {
flex: 0 1 auto;
width: 350px;
width: 450px;
min-height: 50px;
/**
* Note: Min() refers to CSS min() and not SCSS min().
@@ -106,7 +106,6 @@
}
.o_MessagingMenu_dropdownMenuHeader {
border-bottom: $border-width solid gray('400');
z-index: 1;
}
@@ -16,12 +16,12 @@
</t>
</a>
<t t-if="messagingMenu.isOpen">
<div class="o_MessagingMenu_dropdownMenu dropdown-menu dropdown-menu-right" t-att-class="{ 'o-mobile': messaging.device.isMobile, 'o-messaging-not-initialized': !messaging.isInitialized }" role="menu">
<div class="o_MessagingMenu_dropdownMenu dropdown-menu dropdown-menu-right border" t-att-class="{ 'o-mobile': messaging.device.isMobile, 'o-messaging-not-initialized': !messaging.isInitialized }" role="menu">
<t t-if="!messaging.isInitialized">
<span><i class="o_MessagingMenu_dropdownLoadingIcon fa fa-circle-o-notch fa-spin"/>Please wait...</span>
</t>
<t t-else="">
<div class="o_MessagingMenu_dropdownMenuHeader" t-att-class="{ 'o-mobile': messaging.device.isMobile }">
<div class="o_MessagingMenu_dropdownMenuHeader border-bottom" t-att-class="{ 'o-mobile': messaging.device.isMobile }">
<t t-if="!messaging.device.isMobile">
<t t-foreach="['all', 'chat', 'channel']" t-as="tabId" t-key="tabId">
<button class="o_MessagingMenu_tabButton o-desktop btn btn-link" t-att-class="{ 'o-active': messagingMenu.activeTabId === tabId, }" t-on-click="_onClickDesktopTabButton" type="button" role="tab" t-att-data-tab-id="tabId">
@@ -16,10 +16,6 @@
@include o-mail-notification-list-item-content-layout();
}
.o_NotificationGroup_core {
@include o-mail-notification-list-item-core-layout();
}
.o_NotificationGroup_coreItem {
@include o-mail-notification-list-item-core-item-layout();
}
@@ -68,10 +64,6 @@
@include o-mail-notification-list-item-style();
}
.o_NotificationGroup_core {
@include o-mail-notification-list-item-core-style();
}
.o_NotificationGroup_counter {
@include o-mail-notification-list-item-bold-style();
}
@@ -14,9 +14,11 @@
<span class="o_NotificationGroup_name text-truncate">
<t t-esc="notificationGroupView.notificationGroup.res_model_name"/>
</span>
<span class="o_NotificationGroup_counter">
(<t t-esc="notificationGroupView.notificationGroup.notifications.length"/>)
</span>
<t t-if="notificationGroupView.notificationGroup.notifications.length > 1">
<span class="o_NotificationGroup_counter">
(<t t-esc="notificationGroupView.notificationGroup.notifications.length"/>)
</span>
</t>
<span class="o-autogrow"/>
<t t-if="notificationGroupView.notificationGroup.date">
<span class="o_NotificationGroup_date">
@@ -24,7 +26,7 @@
</span>
</t>
</div>
<div class="o_NotificationGroup_core">
<div class="o_NotificationGroup_core d-flex align-items-baseline">
<span class="o_NotificationGroup_coreItem o_NotificationGroup_inlineText text-truncate">
<t t-if="notificationGroupView.notificationGroup.notification_type === 'email'">
An error occurred when sending an email.
@@ -28,10 +28,6 @@
// Style
// ------------------------------------------------------------------
.o_NotificationList_separator {
border-bottom: $border-width solid $border-color;
}
.o_NotificationList_noConversation {
color: $text-muted;
}
@@ -39,7 +39,7 @@
/>
</t>
<t t-if="!notificationView_last">
<div class="o_NotificationList_separator"/>
<div class="o_NotificationList_separator border-bottom"/>
</t>
</t>
</t>
@@ -22,10 +22,6 @@
margin: map-get($spacers, 2);
}
@mixin o-mail-notification-list-item-core-layout {
display: flex;
}
@mixin o-mail-notification-list-item-core-item-layout {
margin: map-get($spacers, 0) map-get($spacers, 2);
@@ -39,7 +35,7 @@
}
@mixin o-mail-notification-list-item-counter-layout() {
margin: map-get($spacers, 0) map-get($spacers, 2);
margin: map-get($spacers, 0) map-get($spacers, 1);
}
@mixin o-mail-notification-list-item-date-layout() {
@@ -48,7 +44,6 @@
@mixin o-mail-notification-list-item-header-layout {
display: flex;
margin-bottom: map-get($spacers, 1);
}
@mixin o-mail-notification-list-item-image-layout {
@@ -121,20 +116,15 @@ $o-mail-notification-list-item-muted-hover-background-color:
}
@mixin o-mail-notification-list-item-bold-style {
font-weight: bold;
font-weight: $font-weight-bold;
&.o-muted {
font-weight: initial;
color: gray('600');
}
}
@mixin o-mail-notification-list-item-core-style {
color: gray('500');
}
@mixin o-mail-notification-list-item-date-style() {
@include o-mail-notification-list-item-bold-style();
font-size: x-small;
font-size: $font-size-sm;
color: gray('500');
}
@@ -143,7 +133,7 @@ $o-mail-notification-list-item-muted-hover-background-color:
}
@mixin o-mail-notification-list-item-mark-as-read-style() {
opacity: 0;
color: gray('300');
&:hover {
color: gray('600');
@@ -10,10 +10,6 @@
@include o-mail-notification-list-item-content-layout();
}
.o_NotificationRequest_core {
@include o-mail-notification-list-item-core-layout();
}
.o_NotificationRequest_coreItem {
@include o-mail-notification-list-item-core-item-layout();
}
@@ -60,10 +56,6 @@
}
}
.o_NotificationRequest_core {
@include o-mail-notification-list-item-core-style();
}
.o_NotificationRequest_image {
@include o-mail-notification-list-item-image-style();
}
@@ -4,20 +4,12 @@
.o_ThreadNeedactionPreview {
@include o-mail-notification-list-item-layout();
&:hover .o_ThreadNeedactionPreview_markAsRead {
opacity: 1;
}
}
.o_ThreadNeedactionPreview_content {
@include o-mail-notification-list-item-content-layout();
}
.o_ThreadNeedactionPreview_core {
@include o-mail-notification-list-item-core-layout();
}
.o_ThreadNeedactionPreview_coreItem {
@include o-mail-notification-list-item-core-item-layout();
}
@@ -68,21 +60,14 @@
.o_ThreadNeedactionPreview {
@include o-mail-notification-list-item-style();
background-color: rgba($o-brand-primary, 0.1);
&:hover {
background-color: rgba($o-brand-primary, 0.2);
.o_ThreadNeedactionPreview_partnerImStatusIcon {
@include o-mail-notification-list-item-hover-partner-im-status-icon-style();
}
}
}
.o_ThreadNeedactionPreview_core {
@include o-mail-notification-list-item-core-style();
}
.o_ThreadNeedactionPreview_counter {
@include o-mail-notification-list-item-bold-style();
}
@@ -27,9 +27,11 @@
<span class="o_ThreadNeedactionPreview_name text-truncate" t-att-class="{ 'o-mobile': messaging.device.isMobile }">
<t t-esc="threadNeedactionPreviewView.thread.displayName"/>
</span>
<span class="o_ThreadNeedactionPreview_counter">
(<t t-esc="threadNeedactionPreviewView.thread.needactionMessagesAsOriginThread.length"/>)
</span>
<t t-if="threadNeedactionPreviewView.thread.needactionMessagesAsOriginThread.length > 1">
<span class="o_ThreadNeedactionPreview_counter">
(<t t-esc="threadNeedactionPreviewView.thread.needactionMessagesAsOriginThread.length"/>)
</span>
</t>
<span class="o-autogrow"/>
<t t-if="threadNeedactionPreviewView.thread.lastNeedactionMessageAsOriginThread and threadNeedactionPreviewView.thread.lastNeedactionMessageAsOriginThread.date">
<span class="o_ThreadNeedactionPreview_date">
@@ -37,7 +39,7 @@
</span>
</t>
</div>
<div class="o_ThreadNeedactionPreview_core">
<div class="o_ThreadNeedactionPreview_core d-flex align-items-baseline">
<span class="o_ThreadNeedactionPreview_coreItem o_ThreadNeedactionPreview_inlineText text-truncate" t-att-class="{ 'o-empty': inlineLastNeedactionMessageAsOriginThreadBody.length === 0 }">
<t t-if="threadNeedactionPreviewView.messageAuthorPrefixView">
<MessageAuthorPrefix localId="threadNeedactionPreviewView.messageAuthorPrefixView.localId"/>
@@ -14,10 +14,6 @@
@include o-mail-notification-list-item-content-layout();
}
.o_ThreadPreview_core {
@include o-mail-notification-list-item-core-layout();
}
.o_ThreadPreview_coreItem {
@include o-mail-notification-list-item-core-item-layout();
}
@@ -88,10 +84,6 @@
color: red;
}
.o_ThreadPreview_core {
@include o-mail-notification-list-item-core-style();
}
.o_ThreadPreview_counter {
@include o-mail-notification-list-item-bold-style();
}
@@ -28,8 +28,8 @@
<span class="o_ThreadPreview_name text-truncate" t-att-class="{ 'o-mobile': messaging.device.isMobile, 'o-muted': threadPreviewView.thread.localMessageUnreadCounter === 0 }">
<t t-esc="threadPreviewView.thread.displayName"/>
</span>
<t t-if="threadPreviewView.thread.localMessageUnreadCounter > 0">
<span class="o_ThreadPreview_counter" t-att-class="{ 'o-muted': threadPreviewView.thread.localMessageUnreadCounter === 0 }">
<t t-if="threadPreviewView.thread.localMessageUnreadCounter > 1">
<span class="o_ThreadPreview_counter">
(<t t-esc="threadPreviewView.thread.localMessageUnreadCounter"/>)
</span>
</t>
@@ -43,7 +43,7 @@
</span>
</t>
</div>
<div class="o_ThreadPreview_core">
<div class="o_ThreadPreview_core d-flex align-items-baseline">
<span class="o_ThreadPreview_coreItem o_ThreadPreview_inlineText text-truncate" t-att-class="{ 'o-empty': inlineLastMessageBody.length === 0 }">
<t t-if="threadPreviewView.messageAuthorPrefixView">
<MessageAuthorPrefix localId="threadPreviewView.messageAuthorPrefixView.localId"/>
@@ -19,12 +19,18 @@ QUnit.test('notification group basic layout', async function (assert) {
res_id: mailChannelId1,
res_model_name: "Channel", // random res model name, will be asserted in the test
});
// failure that is expected to be used in the test
pyEnv['mail.notification'].create({
mail_message_id: mailMessageId1, // id of the related message
notification_status: 'exception', // necessary value to have a failure
notification_type: 'email', // expected failure type for email message
});
pyEnv['mail.notification'].create([
{
mail_message_id: mailMessageId1,
notification_status: 'exception',
notification_type: 'email',
},
{
mail_message_id: mailMessageId1,
notification_status: 'exception',
notification_type: 'email',
},
]);
const { createNotificationListComponent } = await start();
await createNotificationListComponent();
assert.containsOnce(
@@ -49,8 +55,8 @@ QUnit.test('notification group basic layout', async function (assert) {
);
assert.strictEqual(
document.querySelector('.o_NotificationGroup_counter').textContent.trim(),
"(1)",
"should have only 1 notification in the group"
"(2)",
"should have 2 notifications in the group"
);
assert.containsOnce(
document.body,
@@ -327,17 +333,26 @@ QUnit.test('different mail.channel are not grouped', async function (assert) {
},
]);
pyEnv['mail.notification'].create([
// first failure that is expected to be used in the test
{
mail_message_id: mailMessageId1, // id of the related first message
notification_status: 'exception', // one possible value to have a failure
notification_type: 'email', // expected failure type for email message
}, // second failure that is expected to be used in the test
},
{
mail_message_id: mailMessageId1,
notification_status: 'exception',
notification_type: 'email',
},
{
mail_message_id: mailMessageId2, // id of the related second message
notification_status: 'bounce', // other possible value to have a failure
notification_type: 'email', // expected failure type for email message
},
{
mail_message_id: mailMessageId2,
notification_status: 'bounce',
notification_type: 'email',
},
]);
const { createNotificationListComponent } = await start({
// needed to assert thread.open
@@ -358,8 +373,8 @@ QUnit.test('different mail.channel are not grouped', async function (assert) {
);
assert.strictEqual(
groups[0].querySelector('.o_NotificationGroup_counter').textContent.trim(),
"(1)",
"should have 1 notification in first group"
"(2)",
"should have 2 notifications in first group"
);
assert.containsOnce(
groups[1],
@@ -368,8 +383,8 @@ QUnit.test('different mail.channel are not grouped', async function (assert) {
);
assert.strictEqual(
groups[1].querySelector('.o_NotificationGroup_counter').textContent.trim(),
"(1)",
"should have 1 notification in second group"
"(2)",
"should have 2 notifications in second group"
);
await afterNextRender(() => groups[0].click());
@@ -401,18 +416,26 @@ QUnit.test('multiple grouped notifications by document model, sorted by the most
},
]);
pyEnv['mail.notification'].create([
// first failure that is expected to be used in the test
{
mail_message_id: mailMessageId1, // id of the related first message
notification_status: 'exception', // one possible value to have a failure
notification_type: 'email', // expected failure type for email message
},
// second failure that is expected to be used in the test
{
mail_message_id: mailMessageId1,
notification_status: 'exception',
notification_type: 'email',
},
{
mail_message_id: mailMessageId2, // id of the related second message
notification_status: 'bounce', // other possible value to have a failure
notification_type: 'email', // expected failure type for email message
},
{
mail_message_id: mailMessageId2,
notification_status: 'bounce',
notification_type: 'email',
},
]);
const { createNotificationListComponent } = await start();
await createNotificationListComponent();
@@ -440,8 +463,8 @@ QUnit.test('multiple grouped notifications by document model, sorted by the most
);
assert.strictEqual(
groups[0].querySelector('.o_NotificationGroup_counter').textContent.trim(),
"(1)",
"should have 1 notification in first group"
"(2)",
"should have 2 notifications in first group"
);
assert.containsOnce(
groups[1],
@@ -460,8 +483,8 @@ QUnit.test('multiple grouped notifications by document model, sorted by the most
);
assert.strictEqual(
groups[1].querySelector('.o_NotificationGroup_counter').textContent.trim(),
"(1)",
"should have 1 notification in second group"
"(2)",
"should have 2 notifications in second group"
);
});
@@ -11,7 +11,8 @@ QUnit.module('thread_preview_tests.js', {
});
QUnit.test('mark as read', async function (assert) {
assert.expect(8);
assert.expect(6);
this.data['mail.channel'].records.push({
id: 11,
message_unread_counter: 1,
@@ -40,11 +41,6 @@ QUnit.test('mark as read', async function (assert) {
'.o_ThreadPreview_markAsRead',
"should have the mark as read button"
);
assert.containsOnce(
document.body,
'.o_ThreadPreview_counter',
"should have an unread counter"
);
await afterNextRender(() =>
document.querySelector('.o_ThreadPreview_markAsRead').click()
@@ -63,11 +59,6 @@ QUnit.test('mark as read', async function (assert) {
'.o_ThreadPreview_markAsRead',
"should no longer have the mark as read button"
);
assert.containsNone(
document.body,
'.o_ThreadPreview_counter',
"should no longer have an unread counter"
);
assert.containsNone(
document.body,
'.o_ChatWindow',
@@ -91,18 +91,26 @@ QUnit.test('notifications grouped by notification_type', async function (assert)
}
);
this.data['mail.notification'].records.push(
// first failure that is expected to be used in the test
{
mail_message_id: 11, // id of the related first message
notification_status: 'exception', // necessary value to have a failure
notification_type: 'sms', // different type from second failure
},
// second failure that is expected to be used in the test
{
mail_message_id: 11,
notification_status: 'exception',
notification_type: 'sms',
},
{
mail_message_id: 12, // id of the related second message
notification_status: 'exception', // necessary value to have a failure
notification_type: 'email', // different type from first failure
}
},
{
mail_message_id: 12,
notification_status: 'exception',
notification_type: 'email',
},
);
const { createNotificationListComponent } = await start({ data: this.data });
await createNotificationListComponent();
@@ -131,8 +139,8 @@ QUnit.test('notifications grouped by notification_type', async function (assert)
);
assert.strictEqual(
groups[0].querySelector('.o_NotificationGroup_counter').textContent.trim(),
"(1)",
"should have 1 notification in first group"
"(2)",
"should have 2 notifications in first group"
);
assert.strictEqual(
groups[0].querySelector('.o_NotificationGroup_inlineText').textContent.trim(),
@@ -156,8 +164,8 @@ QUnit.test('notifications grouped by notification_type', async function (assert)
);
assert.strictEqual(
groups[1].querySelector('.o_NotificationGroup_counter').textContent.trim(),
"(1)",
"should have 1 notification in second group"
"(2)",
"should have 2 notifications in second group"
);
assert.strictEqual(
groups[1].querySelector('.o_NotificationGroup_inlineText').textContent.trim(),
@@ -85,18 +85,26 @@ QUnit.test('notifications grouped by notification_type', async function (assert)
}
);
this.data['mail.notification'].records.push(
// first failure that is expected to be used in the test
{
mail_message_id: 11, // id of the related first message
notification_status: 'exception', // necessary value to have a failure
notification_type: 'snail', // different type from second failure
},
// second failure that is expected to be used in the test
{
mail_message_id: 11,
notification_status: 'exception',
notification_type: 'snail',
},
{
mail_message_id: 12, // id of the related second message
notification_status: 'exception', // necessary value to have a failure
notification_type: 'email', // different type from first failure
}
},
{
mail_message_id: 12,
notification_status: 'exception',
notification_type: 'email',
},
);
const { createNotificationListComponent } = await start({ data: this.data });
await createNotificationListComponent();
@@ -125,8 +133,8 @@ QUnit.test('notifications grouped by notification_type', async function (assert)
);
assert.strictEqual(
groups[0].querySelector('.o_NotificationGroup_counter').textContent.trim(),
"(1)",
"should have 1 notification in first group"
"(2)",
"should have 2 notifications in first group"
);
assert.strictEqual(
groups[0].querySelector('.o_NotificationGroup_inlineText').textContent.trim(),
@@ -150,8 +158,8 @@ QUnit.test('notifications grouped by notification_type', async function (assert)
);
assert.strictEqual(
groups[1].querySelector('.o_NotificationGroup_counter').textContent.trim(),
"(1)",
"should have 1 notification in second group"
"(2)",
"should have 2 notifications in second group"
);
assert.strictEqual(
groups[1].querySelector('.o_NotificationGroup_inlineText').textContent.trim(),