[REF] mail, im_livechat, *: move code and remove patches from sidebar

* = hr_holidays

Part of task-3265211

closes odoo/odoo#130003

Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
This commit is contained in:
Sébastien Theys
2023-08-01 22:30:47 +02:00
parent 600bd9c81f
commit f9aedceb9f
49 changed files with 724 additions and 553 deletions
@@ -21,7 +21,7 @@ QUnit.test("thread icon of a chat when correspondent is on leave & online", asyn
await openDiscuss();
assert.containsOnce(
$,
".o-mail-DiscussCategoryItem:contains(Demo) .o-mail-ThreadIcon .fa-plane[title='Online']"
".o-mail-DiscussSidebarChannel:contains(Demo) .o-mail-ThreadIcon .fa-plane[title='Online']"
);
});
@@ -42,7 +42,7 @@ QUnit.test("thread icon of a chat when correspondent is on leave & away", async
await openDiscuss();
assert.containsOnce(
$,
".o-mail-DiscussCategoryItem:contains(Demo) .o-mail-ThreadIcon .fa-plane[title='Away']"
".o-mail-DiscussSidebarChannel:contains(Demo) .o-mail-ThreadIcon .fa-plane[title='Away']"
);
});
@@ -63,6 +63,6 @@ QUnit.test("thread icon of a chat when correspondent is on leave & offline", asy
await openDiscuss();
assert.containsOnce(
$,
".o-mail-DiscussCategoryItem:contains(Demo) .o-mail-ThreadIcon .fa-plane[title='Out of office']"
".o-mail-DiscussSidebarChannel:contains(Demo) .o-mail-ThreadIcon .fa-plane[title='Out of office']"
);
});
@@ -9,7 +9,7 @@ patch(Store.prototype, "im_livechat", {
setup(env) {
this._super(env);
this.discuss.livechat = {
extraClass: "o-mail-DiscussCategory-livechat",
extraClass: "o-mail-DiscussSidebarCategory-livechat",
id: "livechat",
name: _t("Livechat"),
isOpen: false,
@@ -0,0 +1,13 @@
/* @odoo-module */
import { discussSidebarCategoriesRegistry } from "@mail/discuss/core/web/discuss_sidebar_categories";
discussSidebarCategoriesRegistry.add(
"livechats",
{
predicate: (store) =>
store.discuss.livechat.threads.some((localId) => store.threads[localId]?.is_pinned),
value: (store) => store.discuss.livechat,
},
{ sequence: 20 }
);
@@ -1,13 +0,0 @@
/* @odoo-module */
import { Sidebar } from "@mail/core/web/sidebar";
import { patch } from "@web/core/utils/patch";
patch(Sidebar.prototype, "im_livechat", {
get shouldDisplayLivechatCategory() {
return this.store.discuss.livechat.threads.some(
(localId) => this.store.threads[localId]?.is_pinned
);
},
});
@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates>
<t t-name="im_livechat.DiscussSidebar" t-inherit="mail.DiscussSidebar" t-inherit-mode="extension" owl="1">
<xpath expr="//*[@name='chatCategory']" position="before">
<t t-if="shouldDisplayLivechatCategory" t-call="mail.DiscussCategory">
<t t-set="category" t-value="store.discuss.livechat"/>
</t>
</xpath>
</t>
</templates>
@@ -98,11 +98,11 @@ QUnit.test("Partners invited most frequently by the current user come first", as
const { openDiscuss } = await start();
await openDiscuss();
await click(".o-mail-DiscussCategoryItem:contains(Visitor #1)");
await click(".o-mail-DiscussSidebarChannel:contains(Visitor #1)");
await click("button[title='Add Users']");
await click(".o-discuss-ChannelInvitation-selectable:contains(John) input");
await click("button:contains(Invite)");
await click(".o-mail-DiscussCategoryItem:contains(Visitor #2)");
await click(".o-mail-DiscussSidebarChannel:contains(Visitor #2)");
await click("button[title='Add Users']");
const partnerSuggestions = document.querySelectorAll(".o-discuss-ChannelInvitation-selectable");
assert.ok(partnerSuggestions[0].textContent.includes("John"));
@@ -85,7 +85,7 @@ QUnit.test("add livechat in the sidebar on visitor sending first message", async
});
const { env, openDiscuss } = await start();
await openDiscuss();
assert.containsNone($, ".o-mail-DiscussCategory-livechat");
assert.containsNone($, ".o-mail-DiscussSidebarCategory-livechat");
// simulate livechat visitor sending a message
const [channel] = pyEnv["discuss.channel"].searchRead([["id", "=", channelId]]);
await afterNextRender(async () =>
@@ -95,11 +95,14 @@ QUnit.test("add livechat in the sidebar on visitor sending first message", async
message_content: "new message",
})
);
assert.containsOnce($, ".o-mail-DiscussCategory-livechat");
assert.containsOnce($, ".o-mail-DiscussCategory-livechat + .o-mail-DiscussCategoryItem");
assert.containsOnce($, ".o-mail-DiscussSidebarCategory-livechat");
assert.containsOnce(
$,
".o-mail-DiscussCategory-livechat + .o-mail-DiscussCategoryItem:contains(Visitor (Belgium))"
".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel"
);
assert.containsOnce(
$,
".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel:contains(Visitor (Belgium))"
);
});
@@ -175,14 +178,14 @@ QUnit.test(
]);
const { openDiscuss } = await start();
await openDiscuss();
assert.strictEqual($(".o-mail-DiscussCategoryItem:eq(0)").text(), "Visitor 12");
assert.strictEqual($(".o-mail-DiscussCategoryItem:eq(1)").text(), "Visitor 11");
assert.strictEqual($(".o-mail-DiscussSidebarChannel:eq(0)").text(), "Visitor 12");
assert.strictEqual($(".o-mail-DiscussSidebarChannel:eq(1)").text(), "Visitor 11");
// post a new message on the last channel
await click(".o-mail-DiscussCategoryItem:eq(1)");
await click(".o-mail-DiscussSidebarChannel:eq(1)");
await insertText(".o-mail-Composer-input", "Blabla");
await click(".o-mail-Composer-send");
assert.containsN($, ".o-mail-DiscussCategoryItem", 2);
assert.strictEqual($(".o-mail-DiscussCategoryItem:eq(0)").text(), "Visitor 11");
assert.strictEqual($(".o-mail-DiscussCategoryItem:eq(1)").text(), "Visitor 12");
assert.containsN($, ".o-mail-DiscussSidebarChannel", 2);
assert.strictEqual($(".o-mail-DiscussSidebarChannel:eq(0)").text(), "Visitor 11");
assert.strictEqual($(".o-mail-DiscussSidebarChannel:eq(1)").text(), "Visitor 12");
}
);
@@ -70,21 +70,18 @@ QUnit.test("tab on discuss composer goes to oldest unread livechat", async (asse
const { openDiscuss } = await start();
await openDiscuss(channelIds[0]);
assert.containsOnce($, ".o-mail-DiscussCategoryItem.o-active:contains(Visitor 11)");
assert.containsOnce(
$,
".o-mail-Composer-footer:contains(Tab to next livechat)"
);
assert.containsOnce($, ".o-mail-DiscussSidebarChannel.o-active:contains(Visitor 11)");
assert.containsOnce($, ".o-mail-Composer-footer:contains(Tab to next livechat)");
await afterNextRender(() => {
document.querySelector(".o-mail-Composer-input").focus();
triggerHotkey("Tab");
});
assert.containsOnce($, ".o-mail-DiscussCategoryItem.o-active:contains(Visitor 13)");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel.o-active:contains(Visitor 13)");
await afterNextRender(() => {
document.querySelector(".o-mail-Composer-input").focus();
triggerHotkey("Tab");
});
assert.containsOnce($, ".o-mail-DiscussCategoryItem.o-active:contains(Visitor 12)");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel.o-active:contains(Visitor 12)");
});
QUnit.test("switching to folded chat window unfolds it", async (assert) => {
@@ -231,7 +228,7 @@ QUnit.test("tab on composer doesn't switch thread if user is typing", async (ass
await insertText(".o-mail-Composer-input", "Hello, ");
triggerHotkey("Tab");
await nextTick();
assert.containsOnce($, ".o-mail-DiscussCategoryItem.o-active:contains(Visitor 11)");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel.o-active:contains(Visitor 11)");
});
QUnit.test("tab on composer doesn't switch thread if no unread thread", async (assert) => {
@@ -264,5 +261,5 @@ QUnit.test("tab on composer doesn't switch thread if no unread thread", async (a
document.querySelector(".o-mail-Composer-input").focus();
triggerHotkey("Tab");
await nextTick();
assert.containsOnce($, ".o-mail-DiscussCategoryItem.o-active:contains(Visitor 11)");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel.o-active:contains(Visitor 11)");
});
@@ -20,8 +20,8 @@ QUnit.test("Unknown visitor", async (assert) => {
});
const { openDiscuss } = await start();
await openDiscuss();
assert.containsOnce($, ".o-mail-DiscussSidebar .o-mail-DiscussCategory-livechat");
assert.containsOnce($, ".o-mail-DiscussCategoryItem:contains(Visitor 11)");
assert.containsOnce($, ".o-mail-DiscussSidebar .o-mail-DiscussSidebarCategory-livechat");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel:contains(Visitor 11)");
});
QUnit.test("Known user with country", async (assert) => {
@@ -44,7 +44,7 @@ QUnit.test("Known user with country", async (assert) => {
});
const { openDiscuss } = await start();
await openDiscuss();
assert.containsOnce($, ".o-mail-DiscussCategoryItem:contains(Jean (Belgium))");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel:contains(Jean (Belgium))");
});
QUnit.test("Do not show channel when visitor is typing", async (assert) => {
@@ -71,7 +71,7 @@ QUnit.test("Do not show channel when visitor is typing", async (assert) => {
});
const { env, openDiscuss } = await start();
await openDiscuss();
assert.containsNone($, ".o-mail-DiscussCategory-livechat");
assert.containsNone($, ".o-mail-DiscussSidebarCategory-livechat");
// simulate livechat visitor typing
const channel = pyEnv["discuss.channel"].searchRead([["id", "=", channelId]])[0];
await env.services.rpc("/im_livechat/notify_typing", {
@@ -82,7 +82,7 @@ QUnit.test("Do not show channel when visitor is typing", async (assert) => {
uuid: channel.uuid,
});
await nextTick();
assert.containsNone($, ".o-mail-DiscussCategory-livechat");
assert.containsNone($, ".o-mail-DiscussSidebarCategory-livechat");
});
QUnit.test("Close should update the value on the server", async (assert) => {
@@ -109,7 +109,7 @@ QUnit.test("Close should update the value on the server", async (assert) => {
[[currentUserId]]
);
assert.ok(initalSettings.is_discuss_sidebar_category_livechat_open);
await click(".o-mail-DiscussCategory-livechat .btn");
await click(".o-mail-DiscussSidebarCategory-livechat .btn");
const newSettings = await env.services.orm.call(
"res.users.settings",
"_find_or_create_for_user",
@@ -142,7 +142,7 @@ QUnit.test("Open should update the value on the server", async (assert) => {
[[currentUserId]]
);
assert.notOk(initalSettings.is_discuss_sidebar_category_livechat_open);
await click(".o-mail-DiscussCategory-livechat .btn");
await click(".o-mail-DiscussSidebarCategory-livechat .btn");
const newSettings = await env.services.orm.call(
"res.users.settings",
"_find_or_create_for_user",
@@ -168,7 +168,10 @@ QUnit.test("Open from the bus", async (assert) => {
});
const { openDiscuss } = await start();
await openDiscuss();
assert.containsNone($, ".o-mail-DiscussCategory-livechat + .o-mail-DiscussCategoryItem");
assert.containsNone(
$,
".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel"
);
await afterNextRender(() => {
pyEnv["bus.bus"]._sendone(pyEnv.currentPartner, "mail.record/insert", {
"res.users.settings": {
@@ -177,7 +180,10 @@ QUnit.test("Open from the bus", async (assert) => {
},
});
});
assert.containsOnce($, ".o-mail-DiscussCategory-livechat + .o-mail-DiscussCategoryItem");
assert.containsOnce(
$,
".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel"
);
});
QUnit.test("Close from the bus", async (assert) => {
@@ -197,7 +203,10 @@ QUnit.test("Close from the bus", async (assert) => {
});
const { openDiscuss } = await start();
await openDiscuss();
assert.containsOnce($, ".o-mail-DiscussCategory-livechat + .o-mail-DiscussCategoryItem");
assert.containsOnce(
$,
".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel"
);
await afterNextRender(() => {
pyEnv["bus.bus"]._sendone(pyEnv.currentPartner, "mail.record/insert", {
"res.users.settings": {
@@ -206,7 +215,10 @@ QUnit.test("Close from the bus", async (assert) => {
},
});
});
assert.containsNone($, ".o-mail-DiscussCategory-livechat + .o-mail-DiscussCategoryItem");
assert.containsNone(
$,
".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel"
);
});
QUnit.test("Smiley face avatar for an anonymous livechat item", async (assert) => {
@@ -223,7 +235,8 @@ QUnit.test("Smiley face avatar for an anonymous livechat item", async (assert) =
const { openDiscuss } = await start();
await openDiscuss();
assert.strictEqual(
$(".o-mail-DiscussCategory-livechat + .o-mail-DiscussCategoryItem img")[0].dataset.src,
$(".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel img")[0].dataset
.src,
"/mail/static/src/img/smiley/avatar.jpg"
);
});
@@ -242,7 +255,8 @@ QUnit.test("Partner profile picture for livechat item linked to a partner", asyn
const { openDiscuss } = await start();
await openDiscuss(channelId);
assert.strictEqual(
$(".o-mail-DiscussCategory-livechat + .o-mail-DiscussCategoryItem img")[0].dataset.src,
$(".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel img")[0].dataset
.src,
`/web/image/res.partner/${partnerId}/avatar_128`
);
});
@@ -269,7 +283,7 @@ QUnit.test("No counter if the category is unfolded and with unread messages", as
await openDiscuss();
assert.containsNone(
$,
".o-mail-DiscussCategory-livechat .o-mail-Discuss-category-counter",
".o-mail-DiscussSidebarCategory-livechat .o-mail-Discuss-category-counter",
"should not have a counter if the category is unfolded and with unread messages"
);
});
@@ -293,7 +307,7 @@ QUnit.test("No counter if category is folded and without unread messages", async
await openDiscuss();
assert.containsNone(
$,
".o-mail-DiscussCategory-livechat .o-discuss-badge",
".o-mail-DiscussSidebarCategory-livechat .o-discuss-badge",
"should not have a counter if the category is unfolded and with unread messages"
);
});
@@ -324,7 +338,10 @@ QUnit.test(
});
const { openDiscuss } = await start();
await openDiscuss();
assert.strictEqual($(".o-mail-DiscussCategory-livechat .o-discuss-badge").text(), "1");
assert.strictEqual(
$(".o-mail-DiscussSidebarCategory-livechat .o-discuss-badge").text(),
"1"
);
}
);
@@ -347,12 +364,12 @@ QUnit.test("Close manually by clicking the title", async (assert) => {
await openDiscuss();
assert.containsOnce(
$,
".o-mail-DiscussCategory-livechat + .o-mail-DiscussCategoryItem",
".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel",
"Category is unfolded initially"
);
// fold the livechat category
await click(".o-mail-DiscussCategory-livechat .btn");
assert.containsNone($, ".o-mail-DiscussCategoryItem");
await click(".o-mail-DiscussSidebarCategory-livechat .btn");
assert.containsNone($, ".o-mail-DiscussSidebarChannel");
});
QUnit.test("Open manually by clicking the title", async (assert) => {
@@ -374,12 +391,15 @@ QUnit.test("Open manually by clicking the title", async (assert) => {
await openDiscuss();
assert.containsNone(
$,
".o-mail-DiscussCategory-livechat + .o-mail-DiscussCategoryItem",
".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel",
"Category is folded initially"
);
// open the livechat category
await click(".o-mail-DiscussCategory-livechat .btn");
assert.containsOnce($, ".o-mail-DiscussCategory-livechat + .o-mail-DiscussCategoryItem");
await click(".o-mail-DiscussSidebarCategory-livechat .btn");
assert.containsOnce(
$,
".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel"
);
});
QUnit.test("Category item should be invisible if the category is closed", async (assert) => {
@@ -395,9 +415,15 @@ QUnit.test("Category item should be invisible if the category is closed", async
});
const { openDiscuss } = await start();
await openDiscuss();
assert.containsOnce($, ".o-mail-DiscussCategory-livechat + .o-mail-DiscussCategoryItem");
await click(".o-mail-DiscussCategory-livechat .btn");
assert.containsNone($, ".o-mail-DiscussCategory-livechat + .o-mail-DiscussCategoryItem");
assert.containsOnce(
$,
".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel"
);
await click(".o-mail-DiscussSidebarCategory-livechat .btn");
assert.containsNone(
$,
".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel"
);
});
QUnit.test(
@@ -415,14 +441,20 @@ QUnit.test(
});
const { openDiscuss } = await start();
await openDiscuss();
assert.containsOnce($, ".o-mail-DiscussCategory-livechat + .o-mail-DiscussCategoryItem");
await click(".o-mail-DiscussCategory-livechat + .o-mail-DiscussCategoryItem");
assert.containsOnce(
$,
".o-mail-DiscussCategory-livechat + .o-mail-DiscussCategoryItem.o-active"
".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel"
);
await click(".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel");
assert.containsOnce(
$,
".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel.o-active"
);
await click(".o-mail-DiscussSidebarCategory-livechat .btn");
assert.containsOnce(
$,
".o-mail-DiscussSidebarCategory-livechat + .o-mail-DiscussSidebarChannel"
);
await click(".o-mail-DiscussCategory-livechat .btn");
assert.containsOnce($, ".o-mail-DiscussCategory-livechat + .o-mail-DiscussCategoryItem");
}
);
@@ -443,7 +475,7 @@ QUnit.test("Clicking on unpin button unpins the channel", async (assert) => {
},
});
await openDiscuss();
await click(".o-mail-DiscussCategoryItem [title='Unpin Conversation']");
await click(".o-mail-DiscussSidebarChannel [title='Unpin Conversation']");
assert.verifySteps(["You unpinned your conversation with Visitor 11"]);
});
@@ -469,5 +501,5 @@ QUnit.test("Message unread counter", async (assert) => {
uuid: pyEnv["discuss.channel"].searchRead([["id", "=", channelId]])[0].uuid,
})
);
assert.containsOnce($, ".o-mail-DiscussCategoryItem .badge:contains(1)");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel .badge:contains(1)");
});
@@ -107,7 +107,7 @@ export class Store {
isActive: false,
threadLocalId: null,
channels: {
extraClass: "o-mail-DiscussCategory-channel",
extraClass: "o-mail-DiscussSidebarCategory-channel",
id: "channels",
name: _t("Channels"),
isOpen: false,
@@ -118,7 +118,7 @@ export class Store {
threads: [], // list of ids
},
chats: {
extraClass: "o-mail-DiscussCategory-chat",
extraClass: "o-mail-DiscussSidebarCategory-chat",
id: "chats",
name: _t("Direct messages"),
isOpen: false,
@@ -1022,7 +1022,7 @@ export class ThreadService {
return thread.message_needaction_counter;
}
getDiscussCategoryCounter(categoryId) {
getDiscussSidebarCategoryCounter(categoryId) {
return this.store.discuss[categoryId].threads.reduce((acc, threadLocalId) => {
const channel = this.store.threads[threadLocalId];
if (categoryId === "channels") {
@@ -1,11 +1,7 @@
/* @odoo-module */
import { Discuss } from "@mail/core/common/discuss";
import { DiscussSidebar } from "@mail/core/web/discuss_sidebar";
import { MessagingMenu } from "@mail/core/web/messaging_menu";
import { Sidebar } from "@mail/core/web/sidebar";
import { patch } from "@web/core/utils/patch";
patch(Discuss, "mail/core/web", {
components: { ...Discuss.components, Sidebar, MessagingMenu },
});
Object.assign(Discuss.components, { DiscussSidebar, MessagingMenu });
@@ -2,7 +2,7 @@
<templates xml:space="preserve">
<t t-inherit="mail.Discuss" t-inherit-mode="extension" owl="1">
<xpath expr="//*[@t-ref='mobileTopbar']" position="before">
<Sidebar t-if="!props.public and !ui.isSmall"/>
<DiscussSidebar t-if="!ui.isSmall"/>
</xpath>
<xpath expr="//*[@t-ref='root']" position="inside">
<MessagingMenu t-if="ui.isSmall"/>
@@ -1,4 +1,3 @@
.o-mail-DiscussSidebar-item {
&:hover, &.o-active {
background-color: $o-gray-100 !important;
@@ -0,0 +1,27 @@
/* @odoo-module */
import { useStore } from "@mail/core/common/messaging_hook";
import { Component } from "@odoo/owl";
import { registry } from "@web/core/registry";
export const discussSidebarItemsRegistry = registry.category("mail.discuss_sidebar_items");
/**
* @typedef {Object} Props
* @extends {Component<Props, Env>}
*/
export class DiscussSidebar extends Component {
static template = "mail.DiscussSidebar";
static props = {};
static components = {};
setup() {
this.store = useStore();
}
get discussSidebarItems() {
return discussSidebarItemsRegistry.getAll();
}
}
@@ -0,0 +1,13 @@
.o-mail-DiscussSidebar {
width: 300px;
}
.o-mail-DiscussSidebar-badge {
padding: 3px 6px;
}
.o-mail-DiscussSidebar-item {
&:hover, &.o-active {
background-color: $o-gray-200 !important;
}
}
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="mail.DiscussSidebar" owl="1">
<div class="o-mail-DiscussSidebar d-flex flex-column overflow-auto flex-shrink-0 h-100 pt-3 border-end bg-view">
<t t-foreach="discussSidebarItems" t-as="item" t-key="item_index" t-component="item"/>
</div>
</t>
</templates>
@@ -0,0 +1,37 @@
/* @odoo-module */
import { useStore } from "@mail/core/common/messaging_hook";
import { ThreadIcon } from "@mail/core/common/thread_icon";
import { discussSidebarItemsRegistry } from "@mail/core/web/discuss_sidebar";
import { Component, useState } from "@odoo/owl";
import { useService } from "@web/core/utils/hooks";
import { markEventHandled } from "@web/core/utils/misc";
/**
* @typedef {Object} Props
* @extends {Component<Props, Env>}
*/
export class DiscussSidebarMailboxes extends Component {
static template = "mail.DiscussSidebarMailboxes";
static props = {};
static components = { ThreadIcon };
setup() {
this.store = useStore();
/** @type {import("@mail/core/common/thread_service").ThreadService} */
this.threadService = useState(useService("mail.thread"));
}
/**
* @param {MouseEvent} ev
* @param {import("@mail/core/common/thread_model").Thread} thread
*/
openThread(ev, thread) {
markEventHandled(ev, "sidebar.openThread");
this.threadService.setDiscussThread(thread);
}
}
discussSidebarItemsRegistry.add("mailbox", DiscussSidebarMailboxes, { sequence: 20 });
@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates xml:space="preserve">
<t t-name="mail.DiscussSidebarMailboxes" owl="1">
<div class="d-flex flex-column flex-grow-0">
<t t-call="mail.Mailbox">
<t t-set="mailbox" t-value="store.discuss.inbox"/>
</t>
<t t-call="mail.Mailbox">
<t t-set="mailbox" t-value="store.discuss.starred"/>
</t>
<t t-call="mail.Mailbox">
<t t-set="mailbox" t-value="store.discuss.history"/>
</t>
</div>
</t>
<t t-name="mail.Mailbox" owl="1">
<button
class="o-mail-DiscussSidebar-item btn d-flex align-items-center py-1 px-0 border-0 rounded-0 fw-normal text-reset"
t-att-class="{
'o-bg-inherit': mailbox.localId !== store.discuss.threadLocalId,
'o-active': mailbox.localId === store.discuss.threadLocalId,
}"
t-on-click="(ev) => this.openThread(ev, mailbox)"
>
<ThreadIcon className="'ms-4 me-2 o-bg-inherit'" thread="mailbox"/>
<div class="me-2 text-truncate" t-esc="mailbox.name"/>
<div t-attf-class="flex-grow-1 {{ mailbox.counter === 0 ? 'me-3': '' }}"/>
<span
t-if="mailbox.counter > 0"
class="o-mail-DiscussSidebar-badge o-discuss-badge badge rounded-pill ms-1 me-3 fw-bold"
t-att-class="{ 'bg-400 text-light': mailbox.id === 'starred' }"
t-esc="mailbox.counter"
/>
</button>
</t>
</templates>
@@ -1,32 +0,0 @@
.o-mail-DiscussSidebar {
width: 300px;
.o-mail-DiscussCategory-icon {
width: 15px;
height: 15px;
}
.o-mail-DiscussCategory-im-status {
transform: scale(0.75);
}
}
.o-mail-DiscussSidebar-badge {
padding: 3px 6px;
}
.o-mail-DiscussSidebar-item {
&:hover, &.o-active {
background-color: $o-gray-200 !important;
}
&:hover .o-mail-DiscussCategoryItem-commands {
display: flex !important;
}
}
.o-mail-DiscussCategoryItem-threadIcon {
font-size: xx-small;
width: 13px;
height: 13px;
}
-104
View File
@@ -1,104 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates xml:space="preserve">
<t t-name="mail.DiscussSidebar" owl="1">
<div class="o-mail-DiscussSidebar d-flex flex-column overflow-auto flex-shrink-0 h-100 pt-3 border-end bg-view">
<div class="d-flex flex-column flex-grow-0" t-ref="mailboxes">
<t t-call="mail.Mailbox">
<t t-set="mailbox" t-value="store.discuss.inbox"/>
</t>
<t t-call="mail.Mailbox">
<t t-set="mailbox" t-value="store.discuss.starred"/>
</t>
<t t-call="mail.Mailbox">
<t t-set="mailbox" t-value="store.discuss.history"/>
</t>
</div>
<hr class="w-100 opacity-0"/>
<input t-if="hasQuickSearch" class="form-control mx-4 mb-2 rounded-3 w-auto" placeholder="Quick search..." t-model="state.quickSearchVal"/>
<t t-call="mail.DiscussCategory">
<t t-set="category" t-value="store.discuss.channels"/>
</t>
<t name="chatCategory" t-call="mail.DiscussCategory">
<t t-set="category" t-value="store.discuss.chats"/>
</t>
</div>
</t>
<t t-name="mail.Mailbox" owl="1">
<button class="o-mail-DiscussSidebar-item btn d-flex align-items-center py-1 px-0 border-0 rounded-0 fw-normal text-reset"
t-att-class="{
'o-bg-inherit': mailbox.localId !== store.discuss.threadLocalId,
'o-active': mailbox.localId === store.discuss.threadLocalId,
}"
t-on-click="(ev) => this.openThread(ev, mailbox)"
>
<ThreadIcon className="'ms-4 me-2 o-bg-inherit'" thread="mailbox"/>
<div class="me-2 text-truncate">
<t t-esc="mailbox.name"/>
</div>
<div t-attf-class="flex-grow-1 {{ mailbox.counter === 0 ? 'me-3': '' }}"/>
<div t-if="mailbox.counter > 0">
<span t-attf-class="o-mail-DiscussSidebar-badge badge rounded-pill o-discuss-badge {{ mailbox.id === 'starred' ? 'bg-400 text-light' : '' }} ms-1 me-3 fw-bold" t-esc="mailbox.counter"/>
</div>
</button>
</t>
<t t-name="mail.DiscussCategory" owl="1">
<t t-set="hover_class" t-value="'btn p-0 text-start text-700 opacity-100-hover opacity-75'"/>
<div class="o-mail-DiscussCategory d-flex align-items-center my-1" t-att-class="category.extraClass">
<div t-attf-class="d-flex align-items-baseline mx-1 {{ hover_class }}" t-on-click="() => this.toggleCategory(category)">
<i class="o-mail-DiscussCategory-icon small me-1" t-att-class="category.isOpen ? 'oi oi-chevron-down' : 'oi oi-chevron-right'"/>
<span class="btn-sm p-0 text-uppercase fw-bolder"><t t-esc="category.name"/></span>
</div>
<div class="flex-grow-1"/>
<div class="d-flex me-3">
<i t-if="category.canView" t-attf-class="fa fa-cog {{ hover_class }}" title="View or join channels" t-on-click="() => this.openCategory(category)" role="img"/>
<i t-if="category.canAdd and category.isOpen" class="o-mail-DiscussCategory-add" t-attf-class="fa fa-plus {{ hover_class }} ms-1" t-on-click="() => this.addToCategory(category)" t-att-title="category.addTitle" role="img"/>
</div>
<div t-if="!category.isOpen and threadService.getDiscussCategoryCounter(category.id) > 0" class="o-mail-DiscussSidebar-badge badge rounded-pill me-3 o-discuss-badge fw-bold">
<t t-esc="threadService.getDiscussCategoryCounter(category.id)"/>
</div>
</div>
<t t-if="category.isOpen">
<t t-foreach="filteredThreads(category)" t-as="threadLocalId" t-key="threadLocalId" t-call="mail.DiscussCategoryItem">
<t t-set="thread" t-value="store.threads[threadLocalId]"/>
</t>
</t>
<t t-elif="category.threads.includes(store.discuss.threadLocalId)" t-call="mail.DiscussCategoryItem">
<t t-set="threadLocalId" t-value="store.discuss.threadLocalId"/>
<t t-set="thread" t-value="store.threads[threadLocalId]"/>
</t>
</t>
<t t-name="mail.DiscussCategoryItem" owl="1">
<t t-set="counter" t-value="threadService.getCounter(thread)"/>
<button class="o-mail-DiscussCategoryItem o-mail-DiscussSidebar-item btn btn-secondary d-flex align-items-center w-100 px-0 py-2 border-0 rounded-0 text-reset"
t-att-class="{
'o-bg-inherit': threadLocalId !== store.discuss.threadLocalId,
'o-active': threadLocalId === store.discuss.threadLocalId,
'o-unread': thread.message_unread_counter > 0,
}"
t-on-click="(ev) => this.openThread(ev, thread)"
>
<div class="o-bg-inherit position-relative d-flex ms-4 flex-shrink-0" style="width:30px;height:30px">
<img class="w-100 h-100 rounded" t-att-src="thread.imgUrl" alt="Thread Image"/>
<ThreadIcon t-if="thread.type === 'chat' or (thread.type === 'channel' and !thread.authorizedGroupFullName)" thread="thread" size="'small'" className="'o-mail-DiscussCategoryItem-threadIcon position-absolute bottom-0 end-0 p-1 me-n1 mb-n1 d-flex align-items-center justify-content-center rounded-circle o-bg-inherit'"/>
</div>
<span class="ms-3 me-2 text-truncate" t-att-class="{ 'o-item-unread fw-bolder': thread.message_unread_counter > 0 }">
<t t-esc="thread.displayName"/>
</span>
<div class="flex-grow-1"/>
<div class="o-mail-DiscussCategoryItem-commands d-none ms-1 me-3">
<i t-if="thread.type === 'channel'" t-attf-class="fa fa-cog {{ hover_class }}" title="Channel settings" t-on-click.stop="() => this.openSettings(thread)" role="img"/>
<div t-if="threadService.canLeave(thread)" class="fa fa-times ms-1" t-attf-class="{{ hover_class }}"
t-on-click.stop="() => this.leaveChannel(thread)" title="Leave this channel" role="img"/>
<div t-if="threadService.canUnpin(thread)" t-attf-class="fa fa-times ms-1 {{ hover_class }}" t-on-click.stop="() => threadService.unpin(thread)" title="Unpin Conversation" role="img"/>
</div>
<div t-if="Object.keys(thread.rtcSessions).length > 0" class="fa fa-volume-up ms-1 me-3" t-att-class="{ 'text-danger': rtc.state.channel?.id === thread.id }"/>
<div t-if="counter > 0">
<span t-attf-class="o-mail-DiscussSidebar-badge badge rounded-pill o-discuss-badge ms-1 me-3 fw-bold" t-esc="counter"/>
</div>
</button>
</t>
</templates>
@@ -1,25 +1,27 @@
/* @odoo-module */
import { Discuss } from "@mail/core/common/discuss";
import { useEffect } from "@odoo/owl";
import { useChildSubEnv, useEffect, useState } from "@odoo/owl";
import { patch } from "@web/core/utils/patch";
patch(Discuss.prototype, "discuss/call/web", {
setup(...args) {
this._super(...args);
Object.assign(this.state, { openInviteButton: 0 });
const state = useState({ openInviteButton: 0 });
useChildSubEnv({
onStartMeeting: () => {
state.openInviteButton++;
},
});
useEffect(
() => {
if (this.state.openInviteButton === 0) {
if (state.openInviteButton === 0) {
return;
}
this.threadActions.actions.find((action) => action.id === "add-users")?.onSelect();
},
() => [this.state.openInviteButton]
() => [state.openInviteButton]
);
},
onStartMeeting() {
this.state.openInviteButton++;
},
});
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-inherit="mail.Discuss" t-inherit-mode="extension" owl="1">
<xpath expr="//Sidebar" position="attributes">
<attribute name="onStartMeeting.bind">onStartMeeting</attribute>
</t>
</t>
</templates>
@@ -0,0 +1,24 @@
/* @odoo-module */
import { Thread } from "@mail/core/common/thread_model";
import { useRtc } from "@mail/discuss/call/common/rtc_hook";
import { discussSidebarChannelIndicatorsRegistry } from "@mail/discuss/core/web/discuss_sidebar_categories";
import { Component } from "@odoo/owl";
/**
* @typedef {Object} Props
* @property {import("@mail/core/common/thread_model").Thread} thread
* @extends {Component<Props, Env>}
*/
export class DiscussSidebarCallIndicator extends Component {
static template = "mail.DiscussSidebarCallIndicator";
static props = { thread: { type: Thread } };
static components = {};
setup() {
this.rtc = useRtc();
}
}
discussSidebarChannelIndicatorsRegistry.add("call-indicator", DiscussSidebarCallIndicator);
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="mail.DiscussSidebarCallIndicator" owl="1">
<div
t-if="Object.keys(props.thread.rtcSessions).length > 0"
class="fa fa-volume-up ms-1 me-3"
t-att-class="{ 'text-danger': rtc.state.channel?.id === props.thread.id }"
/>
</t>
</templates>
@@ -1,25 +0,0 @@
/* @odoo-module */
import { Sidebar } from "@mail/core/web/sidebar";
import { useRtc } from "@mail/discuss/call/common/rtc_hook";
import { useDiscussCoreCommon } from "@mail/discuss/core/common/discuss_core_common_service";
import { patch } from "@web/core/utils/patch";
Sidebar.props = [...Sidebar.props, "onStartMeeting?"];
patch(Sidebar.prototype, "discuss/call/web", {
setup() {
this._super(...arguments);
this.discussCoreCommonService = useDiscussCoreCommon();
this.rtc = useRtc();
},
async onClickStartMeeting() {
const thread = await this.discussCoreCommonService.createGroupChat({
default_display_mode: "video_full_screen",
partners_to: [this.store.self.id],
});
this.rtc.toggleCall(thread, { video: true });
this.props.onStartMeeting?.();
},
});
@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-inherit="mail.DiscussSidebar" t-inherit-mode="extension" owl="1">
<xpath expr="//*[@t-ref='mailboxes']" position="before">
<div class="d-flex justify-content-center">
<button t-on-click="onClickStartMeeting" class="btn btn-primary rounded" title="Start a meeting">
Start a meeting
</button>
</div>
<hr class="w-100 opacity-0"/>
</xpath>
</t>
</templates>
@@ -0,0 +1,35 @@
/* @odoo-module */
import { useStore } from "@mail/core/common/messaging_hook";
import { discussSidebarItemsRegistry } from "@mail/core/web/discuss_sidebar";
import { useRtc } from "@mail/discuss/call/common/rtc_hook";
import { useDiscussCoreCommon } from "@mail/discuss/core/common/discuss_core_common_service";
import { Component } from "@odoo/owl";
/**
* @typedef {Object} Props
* @extends {Component<Props, Env>}
*/
export class DiscussSidebarStartMeeting extends Component {
static template = "mail.DiscussSidebarStartMeeting";
static props = {};
static components = {};
setup() {
this.discussCoreCommonService = useDiscussCoreCommon();
this.rtc = useRtc();
this.store = useStore();
}
async onClickStartMeeting() {
const thread = await this.discussCoreCommonService.createGroupChat({
default_display_mode: "video_full_screen",
partners_to: [this.store.self.id],
});
this.rtc.toggleCall(thread, { video: true });
this.env.onStartMeeting?.();
}
}
discussSidebarItemsRegistry.add("start-meeting", DiscussSidebarStartMeeting, { sequence: 10 });
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="mail.DiscussSidebarStartMeeting" owl="1">
<div class="d-flex justify-content-center">
<button class="btn btn-primary rounded" t-on-click="onClickStartMeeting">Start a meeting</button>
</div>
<hr class="w-100 opacity-0"/>
</t>
</templates>
@@ -1,63 +1,123 @@
/* @odoo-module */
import { ImStatus } from "@mail/core/common/im_status";
import { useMessaging, useStore } from "@mail/core/common/messaging_hook";
import { useStore } from "@mail/core/common/messaging_hook";
import { ThreadIcon } from "@mail/core/common/thread_icon";
import { discussSidebarItemsRegistry } from "@mail/core/web/discuss_sidebar";
import { ChannelSelector } from "@mail/discuss/core/web/channel_selector";
import { onExternalClick } from "@mail/utils/common/hooks";
import { markEventHandled } from "@web/core/utils/misc";
import { Component, useState } from "@odoo/owl";
import { ConfirmationDialog } from "@web/core/confirmation_dialog/confirmation_dialog";
import { _t } from "@web/core/l10n/translation";
import { registry } from "@web/core/registry";
import { useService } from "@web/core/utils/hooks";
import { markEventHandled } from "@web/core/utils/misc";
export const discussSidebarCategoriesRegistry = registry.category(
"mail.discuss_sidebar_categories"
);
export const discussSidebarChannelIndicatorsRegistry = registry.category(
"mail.discuss_sidebar_channel_indicators"
);
discussSidebarCategoriesRegistry.add(
"channels",
{ value: (store) => store.discuss.channels },
{ sequence: 10 }
);
discussSidebarCategoriesRegistry.add(
"chats",
{ value: (store) => store.discuss.chats },
{ sequence: 30 }
);
/**
* @typedef {Object} Props
* @extends {Component<Props, Env>}
*/
export class Sidebar extends Component {
static template = "mail.DiscussSidebar";
static components = { ThreadIcon, ImStatus };
static props = [];
export class DiscussSidebarCategories extends Component {
static template = "mail.DiscussSidebarCategories";
static props = {};
static components = { ChannelSelector, ImStatus, ThreadIcon };
setup() {
this.messaging = useMessaging();
this.store = useStore();
/** @type {import("@mail/core/common/thread_service").ThreadService} */
this.threadService = useState(useService("mail.thread"));
this.actionService = useService("action");
this.dialogService = useService("dialog");
this.userSettings = useService("mail.user_settings");
this.orm = useService("orm");
this.state = useState({
editing: false,
quickSearchVal: "",
});
this.actionService = useService("action");
this.dialogService = useService("dialog");
this.userSettings = useService("mail.user_settings");
this.orm = useService("orm");
onExternalClick("selector", () => {
this.state.editing = false;
});
}
openThread(ev, thread) {
markEventHandled(ev, "sidebar.openThread");
this.threadService.setDiscussThread(thread);
addToCategory(category) {
this.state.editing = category.id;
}
async toggleCategory(category) {
category.isOpen = !category.isOpen;
await this.orm.call(
"res.users.settings",
"set_res_users_settings",
[[this.userSettings.id]],
{
new_settings: {
[category.serverStateKey]: category.isOpen,
},
}
askConfirmation(body) {
return new Promise((resolve) => {
this.dialogService.add(ConfirmationDialog, {
body: body,
confirm: resolve,
cancel: () => {},
});
});
}
get categories() {
return discussSidebarCategoriesRegistry.getAll();
}
get channelIndicators() {
return discussSidebarChannelIndicatorsRegistry.getAll();
}
filteredThreads(category) {
return category.threads.filter((threadLocalId) => {
const thread = this.store.threads[threadLocalId];
return (
(thread.is_pinned || thread.group_based_subscription) &&
(!this.state.quickSearchVal || thread.name.includes(this.state.quickSearchVal))
);
});
}
get hasQuickSearch() {
return (
Object.values(this.store.threads).filter(
(thread) => thread.is_pinned && thread.model === "discuss.channel"
).length > 19
);
}
/**
* @param {import("@mail/core/common/thread_model").Thread} thread
*/
async leaveChannel(thread) {
if (thread.type !== "group" && thread.isAdmin) {
await this.askConfirmation(
_t("You are the administrator of this channel. Are you sure you want to leave?")
);
}
if (thread.type === "group") {
await this.askConfirmation(
_t(
"You are about to leave this group conversation and will no longer have access to it unless you are invited again. Are you sure you want to continue?"
)
);
}
this.threadService.leaveChannel(thread);
}
openCategory(category) {
if (category.id === "channels") {
this.actionService.doAction({
@@ -73,6 +133,9 @@ export class Sidebar extends Component {
}
}
/**
* @param {import("@mail/core/common/thread_model").Thread} thread
*/
openSettings(thread) {
if (thread.type === "channel") {
this.actionService.doAction({
@@ -85,55 +148,32 @@ export class Sidebar extends Component {
}
}
addToCategory(category) {
this.state.editing = category.id;
/**
* @param {MouseEvent} ev
* @param {import("@mail/core/common/thread_model").Thread} thread
*/
openThread(ev, thread) {
markEventHandled(ev, "sidebar.openThread");
this.threadService.setDiscussThread(thread);
}
stopEditing() {
this.state.editing = false;
}
async leaveChannel(thread) {
if (thread.type !== "group" && thread.isAdmin) {
await this.askConfirmation(
_t("You are the administrator of this channel. Are you sure you want to leave?")
);
}
if (thread.type === "group") {
await this.askConfirmation(
_t(
"You are about to leave this group conversation and will no longer have access to it unless you are invited again. Are you sure you want to continue?"
)
);
}
this.threadService.leaveChannel(thread);
}
askConfirmation(body) {
return new Promise((resolve) => {
this.dialogService.add(ConfirmationDialog, {
body: body,
confirm: resolve,
cancel: () => {},
});
});
}
get hasQuickSearch() {
return (
Object.values(this.store.threads).filter(
(thread) => thread.is_pinned && thread.model === "discuss.channel"
).length > 19
async toggleCategory(category) {
category.isOpen = !category.isOpen;
await this.orm.call(
"res.users.settings",
"set_res_users_settings",
[[this.userSettings.id]],
{
new_settings: {
[category.serverStateKey]: category.isOpen,
},
}
);
}
filteredThreads(category) {
return category.threads.filter((threadLocalId) => {
const thread = this.store.threads[threadLocalId];
return (
(thread.is_pinned || thread.group_based_subscription) &&
(!this.state.quickSearchVal || thread.name.includes(this.state.quickSearchVal))
);
});
}
}
discussSidebarItemsRegistry.add("channels", DiscussSidebarCategories, { sequence: 30 });
@@ -0,0 +1,21 @@
.o-mail-DiscussSidebar {
.o-mail-DiscussSidebarCategory-icon {
width: 15px;
height: 15px;
}
.o-mail-DiscussSidebarCategory-im-status {
transform: scale(0.75);
}
}
.o-mail-DiscussSidebar-item {
&:hover .o-mail-DiscussSidebarChannel-commands {
display: flex !important;
}
}
.o-mail-DiscussSidebarChannel-threadIcon {
font-size: xx-small;
width: 13px;
height: 13px;
}
@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="mail.DiscussSidebarCategories" owl="1">
<hr class="w-100 opacity-0"/>
<input t-if="hasQuickSearch" class="form-control mx-4 mb-2 rounded-3 w-auto" placeholder="Quick search..." t-model="state.quickSearchVal"/>
<t t-foreach="categories" t-as="categoryData" t-key="categoryData_index">
<t t-if="categoryData.predicate?.(store) ?? true" t-call="mail.DiscussSidebarCategory">
<t t-set="category" t-value="categoryData.value(store)"/>
</t>
</t>
</t>
<t t-name="mail.DiscussSidebarCategory" owl="1">
<t t-set="hover_class" t-value="'btn p-0 text-start text-700 opacity-100-hover opacity-75'"/>
<div class="o-mail-DiscussSidebarCategory d-flex align-items-center my-1" t-att-class="category.extraClass">
<div t-attf-class="d-flex align-items-baseline mx-1 {{ hover_class }}" t-on-click="() => this.toggleCategory(category)">
<i class="o-mail-DiscussSidebarCategory-icon small me-1" t-att-class="category.isOpen ? 'oi oi-chevron-down' : 'oi oi-chevron-right'"/>
<span class="btn-sm p-0 text-uppercase fw-bolder"><t t-esc="category.name"/></span>
</div>
<div class="flex-grow-1"/>
<div class="d-flex me-3">
<i t-if="category.canView" t-attf-class="fa fa-cog {{ hover_class }}" title="View or join channels" t-on-click="() => this.openCategory(category)" role="img"/>
<i t-if="category.canAdd and category.isOpen" class="o-mail-DiscussSidebarCategory-add" t-attf-class="fa fa-plus {{ hover_class }} ms-1" t-on-click="() => this.addToCategory(category)" t-att-title="category.addTitle" role="img"/>
</div>
<div t-if="!category.isOpen and threadService.getDiscussSidebarCategoryCounter(category.id) > 0" class="o-mail-DiscussSidebar-badge badge rounded-pill me-3 o-discuss-badge fw-bold">
<t t-esc="threadService.getDiscussSidebarCategoryCounter(category.id)"/>
</div>
</div>
<t t-if="category.isOpen">
<div t-if="state.editing === category.id" class="p-2" t-ref="selector">
<ChannelSelector category="category" onValidate.bind="stopEditing" autofocus="true"/>
</div>
<t t-foreach="filteredThreads(category)" t-as="threadLocalId" t-key="threadLocalId" t-call="mail.DiscussSidebarChannel">
<t t-set="thread" t-value="store.threads[threadLocalId]"/>
</t>
</t>
<t t-elif="category.threads.includes(store.discuss.threadLocalId)" t-call="mail.DiscussSidebarChannel">
<t t-set="threadLocalId" t-value="store.discuss.threadLocalId"/>
<t t-set="thread" t-value="store.threads[threadLocalId]"/>
</t>
</t>
<t t-name="mail.DiscussSidebarChannel" owl="1">
<t t-set="counter" t-value="threadService.getCounter(thread)"/>
<button class="o-mail-DiscussSidebarChannel o-mail-DiscussSidebar-item btn btn-secondary d-flex align-items-center w-100 px-0 py-2 border-0 rounded-0 text-reset"
t-att-class="{
'o-bg-inherit': threadLocalId !== store.discuss.threadLocalId,
'o-active': threadLocalId === store.discuss.threadLocalId,
'o-unread': thread.message_unread_counter > 0,
}"
t-on-click="(ev) => this.openThread(ev, thread)"
>
<div class="o-bg-inherit position-relative d-flex ms-4 flex-shrink-0" style="width:30px;height:30px">
<img class="w-100 h-100 rounded" t-att-src="thread.imgUrl" alt="Thread Image"/>
<ThreadIcon t-if="thread.type === 'chat' or (thread.type === 'channel' and !thread.authorizedGroupFullName)" thread="thread" size="'small'" className="'o-mail-DiscussSidebarChannel-threadIcon position-absolute bottom-0 end-0 p-1 me-n1 mb-n1 d-flex align-items-center justify-content-center rounded-circle o-bg-inherit'"/>
</div>
<span class="ms-3 me-2 text-truncate" t-att-class="{ 'o-item-unread fw-bolder': thread.message_unread_counter > 0 }">
<t t-esc="thread.displayName"/>
</span>
<div class="flex-grow-1"/>
<div class="o-mail-DiscussSidebarChannel-commands d-none ms-1 me-3">
<i t-if="thread.type === 'channel'" t-attf-class="fa fa-cog {{ hover_class }}" title="Channel settings" t-on-click.stop="() => this.openSettings(thread)" role="img"/>
<div t-if="threadService.canLeave(thread)" class="fa fa-times ms-1" t-attf-class="{{ hover_class }}"
t-on-click.stop="() => this.leaveChannel(thread)" title="Leave this channel" role="img"/>
<div t-if="threadService.canUnpin(thread)" t-attf-class="fa fa-times ms-1 {{ hover_class }}" t-on-click.stop="() => threadService.unpin(thread)" title="Unpin Conversation" role="img"/>
</div>
<t t-foreach="channelIndicators" t-as="indicator" t-key="indicator_index" t-component="indicator" t-props="{ thread }"/>
<div t-if="counter > 0">
<span t-attf-class="o-mail-DiscussSidebar-badge badge rounded-pill o-discuss-badge ms-1 me-3 fw-bold" t-esc="counter"/>
</div>
</button>
</t>
</templates>
@@ -10,7 +10,7 @@ registry.category("web_tour.tours").add("mail_tour", {
sequence: 80,
steps: () => [
{
trigger: ".o-mail-DiscussCategory-channel .o-mail-DiscussCategory-add",
trigger: ".o-mail-DiscussSidebarCategory-channel .o-mail-DiscussSidebarCategory-add",
content: Markup(
_t(
"<p>Channels make it easy to organize information across different topics and groups.</p> <p>Try to <b>create your first channel</b> (e.g. sales, marketing, product XYZ, after work party, etc).</p>"
@@ -81,7 +81,7 @@ registry.category("web_tour.tours").add("mail_tour", {
position: "bottom",
},
{
trigger: ".o-mail-DiscussCategory-chat .o-mail-DiscussCategory-add",
trigger: ".o-mail-DiscussSidebarCategory-chat .o-mail-DiscussSidebarCategory-add",
content: Markup(
_t(
"<p><b>Chat with coworkers</b> in real-time using direct messages.</p><p><i>You might need to invite users from the Settings app first.</i></p>"
@@ -1,6 +0,0 @@
/* @odoo-module */
import { Sidebar } from "@mail/core/web/sidebar";
import { ChannelSelector } from "@mail/discuss/core/web/channel_selector";
Object.assign(Sidebar.components, { ChannelSelector });
@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-inherit="mail.DiscussCategory" t-inherit-mode="extension" owl="1">
<xpath expr="//t[@t-call='mail.DiscussCategoryItem']" position="before">
<div t-if="state.editing === category.id" class="p-2" t-ref="selector">
<ChannelSelector category="category" onValidate.bind="stopEditing" autofocus="true"/>
</div>
</xpath>
</t>
</templates>
@@ -6,7 +6,7 @@ registry.category("web_tour.tours").add("mail.load_message_order", {
test: true,
steps: () => [
{
trigger: ".o-mail-DiscussCategoryItem:contains(MyTestChannel)",
trigger: ".o-mail-DiscussSidebarChannel:contains(MyTestChannel)",
run: "click",
},
{
@@ -190,8 +190,8 @@ QUnit.test(
const textarea = $(".o-mail-Composer-input")[0];
textarea.setSelectionRange(0, textarea.value.length);
await nextTick();
await click($(".o-mail-DiscussCategoryItem:eq(1)"));
await click($(".o-mail-DiscussCategoryItem:eq(0)"));
await click($(".o-mail-DiscussSidebarChannel:eq(1)"));
await click($(".o-mail-DiscussSidebarChannel:eq(0)"));
assert.ok(textarea.selectionStart === 0 && textarea.selectionEnd === textarea.value.length);
}
);
@@ -478,10 +478,10 @@ QUnit.test("leave command on channel", async (assert) => {
},
});
await openDiscuss(channelId);
assert.hasClass($(".o-mail-DiscussCategoryItem:contains(general)"), "o-active");
assert.hasClass($(".o-mail-DiscussSidebarChannel:contains(general)"), "o-active");
await insertText(".o-mail-Composer-input", "/leave");
await afterNextRender(() => triggerHotkey("Enter"));
assert.containsNone($, ".o-mail-DiscussCategoryItem:contains(general)");
assert.containsNone($, ".o-mail-DiscussSidebarChannel:contains(general)");
assert.containsOnce($, ".o-mail-Discuss:contains(No conversation selected.)");
assert.verifySteps(["You unsubscribed from general."]);
});
@@ -525,10 +525,10 @@ QUnit.test("leave command on chat", async (assert) => {
},
});
await openDiscuss(channelId);
assert.hasClass($(".o-mail-DiscussCategoryItem:contains(Chuck Norris)"), "o-active");
assert.hasClass($(".o-mail-DiscussSidebarChannel:contains(Chuck Norris)"), "o-active");
await insertText(".o-mail-Composer-input", "/leave");
await afterNextRender(() => triggerHotkey("Enter"));
assert.containsNone($, ".o-mail-DiscussCategoryItem:contains(Chuck Norris)");
assert.containsNone($, ".o-mail-DiscussSidebarChannel:contains(Chuck Norris)");
assert.containsOnce($, ".o-mail-Discuss:contains(No conversation selected.)");
assert.verifySteps(["You unpinned your conversation with Chuck Norris"]);
});
@@ -66,7 +66,7 @@ QUnit.test("Thread rename", async (assert) => {
await tab1.insertText(".o-mail-Discuss-threadName", "Sales", { replace: true });
await afterNextRender(() => triggerHotkey("Enter"));
assert.containsOnce(tab2.target, ".o-mail-Discuss-threadName[title='Sales']");
assert.containsOnce(tab2.target, ".o-mail-DiscussCategoryItem:contains(Sales)");
assert.containsOnce(tab2.target, ".o-mail-DiscussSidebarChannel:contains(Sales)");
});
QUnit.test("Thread description update", async (assert) => {
@@ -118,7 +118,7 @@ QUnit.test("Channel subscription is renewed when channel is left", async (assert
},
});
await openDiscuss();
await click(".o-mail-DiscussCategoryItem .btn[title='Leave this channel']");
await click(".o-mail-DiscussSidebarChannel .btn[title='Leave this channel']");
assert.verifySteps(["update-channels"]);
});
@@ -207,6 +207,6 @@ QUnit.test("Create a direct message channel when clicking on start a meeting", a
const { openDiscuss } = await start();
await openDiscuss();
await click("button:contains(Start a meeting)");
assert.containsOnce($, ".o-mail-DiscussCategoryItem:contains(Mitchell Admin)");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel:contains(Mitchell Admin)");
assert.containsOnce($, ".o-discuss-Call");
});
@@ -12,7 +12,7 @@ QUnit.test("no default rtc after joining a chat conversation", async (assert) =>
pyEnv["res.users"].create({ partner_id: partnerId });
const { openDiscuss } = await start();
await openDiscuss();
assert.containsNone($, ".o-mail-DiscussCategoryItem");
assert.containsNone($, ".o-mail-DiscussSidebarChannel");
await click(".o-mail-DiscussSidebar i[title='Start a conversation']");
await afterNextRender(() =>
@@ -22,7 +22,7 @@ QUnit.test("no default rtc after joining a chat conversation", async (assert) =>
await triggerEvent(document.body, ".o-discuss-ChannelSelector input", "keydown", {
key: "Enter",
});
assert.containsOnce($, ".o-mail-DiscussCategoryItem");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel");
assert.containsNone($, ".o-mail-Discuss-content .o-mail-Message");
assert.containsNone($, ".o-discuss-Call");
});
@@ -36,7 +36,7 @@ QUnit.test("no default rtc after joining a group conversation", async (assert) =
pyEnv["res.users"].create([{ partner_id: partnerId_1 }, { partner_id: partnerId_2 }]);
const { openDiscuss } = await start();
await openDiscuss();
assert.containsNone($, ".o-mail-DiscussCategoryItem");
assert.containsNone($, ".o-mail-DiscussSidebarChannel");
await click(".o-mail-DiscussSidebar i[title='Start a conversation']");
await afterNextRender(() =>
editInput(document.body, ".o-discuss-ChannelSelector input", "mario")
@@ -49,7 +49,7 @@ QUnit.test("no default rtc after joining a group conversation", async (assert) =
await triggerEvent(document.body, ".o-discuss-ChannelSelector input", "keydown", {
key: "Enter",
});
assert.containsOnce($, ".o-mail-DiscussCategoryItem");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel");
assert.containsNone($, ".o-mail-Discuss-content .o-mail-Message");
assert.containsNone($, ".o-discuss-Call");
});
@@ -118,11 +118,11 @@ QUnit.test("Sort partner suggestions by recent chats", async (assert) => {
]);
const { openDiscuss } = await start();
await openDiscuss();
await click(".o-mail-DiscussCategoryItem:contains('User 2')");
await click(".o-mail-DiscussSidebarChannel:contains('User 2')");
await insertText(".o-mail-Composer-input", "This is a test");
await click(".o-mail-Composer-send:not(:disabled)");
assert.containsOnce($, ".o-mail-Message:contains('This is a test')");
await click(".o-mail-DiscussCategoryItem:contains('General')");
await click(".o-mail-DiscussSidebarChannel:contains('General')");
await insertText(".o-mail-Composer-input", "@");
await insertText(".o-mail-Composer-input", "User");
assert.containsN($, ".o-mail-Composer-suggestion", 3);
@@ -29,14 +29,14 @@ QUnit.test("can create a new channel [REQUIRE FOCUS]", async (assert) => {
},
});
await openDiscuss();
assert.containsNone($, ".o-mail-DiscussCategoryItem");
assert.containsNone($, ".o-mail-DiscussSidebarChannel");
await click(".o-mail-DiscussSidebar i[title='Add or join a channel']");
await afterNextRender(() =>
editInput(document.body, ".o-discuss-ChannelSelector input", "abc")
);
await click(".o-discuss-ChannelSelector-suggestion");
assert.containsOnce($, ".o-mail-DiscussCategoryItem");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel");
assert.containsNone($, ".o-mail-Discuss-content .o-mail-Message");
assert.verifySteps([
"/mail/init_messaging",
@@ -56,7 +56,7 @@ QUnit.test(
pyEnv["res.users"].create({ partner_id: partnerId });
const { openDiscuss } = await start();
await openDiscuss();
assert.containsNone($, ".o-mail-DiscussCategoryItem");
assert.containsNone($, ".o-mail-DiscussSidebarChannel");
await click("i[title='Start a conversation']");
await afterNextRender(() =>
@@ -64,7 +64,7 @@ QUnit.test(
);
await click(".o-discuss-ChannelSelector-suggestion");
assert.containsOnce($, ".o-discuss-ChannelSelector span[title='Mario']");
assert.containsNone($, ".o-mail-DiscussCategoryItem");
assert.containsNone($, ".o-mail-DiscussSidebarChannel");
await triggerEvent(document.body, ".o-discuss-ChannelSelector input", "keydown", {
key: "Backspace",
@@ -78,7 +78,7 @@ QUnit.test(
key: "Enter",
});
assert.containsOnce($, ".o-discuss-ChannelSelector span[title='Mario']");
assert.containsNone($, ".o-mail-DiscussCategoryItem");
assert.containsNone($, ".o-mail-DiscussSidebarChannel");
}
);
@@ -101,7 +101,7 @@ QUnit.test("can join a chat conversation", async (assert) => {
},
});
await openDiscuss();
assert.containsNone($, ".o-mail-DiscussCategoryItem");
assert.containsNone($, ".o-mail-DiscussSidebarChannel");
await click(".o-mail-DiscussSidebar i[title='Start a conversation']");
await afterNextRender(() =>
@@ -111,7 +111,7 @@ QUnit.test("can join a chat conversation", async (assert) => {
await triggerEvent(document.body, ".o-discuss-ChannelSelector input", "keydown", {
key: "Enter",
});
assert.containsOnce($, ".o-mail-DiscussCategoryItem");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel");
assert.containsNone($, ".o-mail-Message");
assert.verifySteps([
"/mail/init_messaging",
@@ -131,7 +131,7 @@ QUnit.test("can create a group chat conversation", async (assert) => {
pyEnv["res.users"].create([{ partner_id: partnerId_1 }, { partner_id: partnerId_2 }]);
const { openDiscuss } = await start();
await openDiscuss();
assert.containsNone($, ".o-mail-DiscussCategoryItem");
assert.containsNone($, ".o-mail-DiscussSidebarChannel");
await click(".o-mail-DiscussSidebar i[title='Start a conversation']");
await insertText(".o-discuss-ChannelSelector input", "Mario");
await click(".o-discuss-ChannelSelector-suggestion");
@@ -140,7 +140,7 @@ QUnit.test("can create a group chat conversation", async (assert) => {
await triggerEvent(document.body, ".o-discuss-ChannelSelector input", "keydown", {
key: "Enter",
});
assert.containsN($, ".o-mail-DiscussCategoryItem", 1);
assert.containsN($, ".o-mail-DiscussSidebarChannel", 1);
assert.containsNone($, ".o-mail-Message");
});
@@ -150,7 +150,7 @@ QUnit.test("should create DM chat when adding self and another user", async (ass
pyEnv["res.users"].create({ partner_id });
const { openDiscuss } = await start();
await openDiscuss();
assert.containsNone($, ".o-mail-DiscussCategoryItem");
assert.containsNone($, ".o-mail-DiscussSidebarChannel");
await click(".o-mail-DiscussSidebar i[title='Start a conversation']");
await insertText(".o-discuss-ChannelSelector input", "Mi"); // Mitchell Admin
await click(".o-discuss-ChannelSelector-suggestion");
@@ -159,7 +159,7 @@ QUnit.test("should create DM chat when adding self and another user", async (ass
await triggerEvent(document.body, ".o-discuss-ChannelSelector input", "keydown", {
key: "Enter",
});
assert.strictEqual($(".o-mail-DiscussCategoryItem:contains(Mario)").text(), "Mario");
assert.strictEqual($(".o-mail-DiscussSidebarChannel:contains(Mario)").text(), "Mario");
});
QUnit.test("chat search should display no result when no matches found", async (assert) => {
@@ -178,7 +178,7 @@ QUnit.test(
pyEnv["res.users"].create({ partner_id: partnerId });
const { openDiscuss } = await start();
await openDiscuss();
assert.containsNone($, ".o-mail-DiscussCategoryItem");
assert.containsNone($, ".o-mail-DiscussSidebarChannel");
await click(".o-mail-DiscussSidebar i[title='Start a conversation']");
await insertText(".o-discuss-ChannelSelector", "Panda");
assert.containsOnce($, ".o-discuss-ChannelSelector-suggestion");
@@ -190,13 +190,16 @@ QUnit.test(
QUnit.test("sidebar: add channel", async (assert) => {
const { openDiscuss } = await start();
await openDiscuss();
assert.containsOnce($, ".o-mail-DiscussCategory-channel .o-mail-DiscussCategory-add");
assert.containsOnce(
$,
".o-mail-DiscussSidebarCategory-channel .o-mail-DiscussSidebarCategory-add"
);
assert.hasAttrValue(
$(".o-mail-DiscussCategory-channel .o-mail-DiscussCategory-add")[0],
$(".o-mail-DiscussSidebarCategory-channel .o-mail-DiscussSidebarCategory-add")[0],
"title",
"Add or join a channel"
);
await click(".o-mail-DiscussCategory-channel .o-mail-DiscussCategory-add");
await click(".o-mail-DiscussSidebarCategory-channel .o-mail-DiscussSidebarCategory-add");
assert.containsOnce($, ".o-discuss-ChannelSelector");
assert.containsOnce($, ".o-discuss-ChannelSelector input[placeholder='Add or join a channel']");
});
@@ -209,10 +212,10 @@ QUnit.test("Chat is added to discuss on other tab that the one that joined", asy
const tab2 = await start({ asTab: true });
await tab1.openDiscuss();
await tab2.openDiscuss();
await tab1.click(".o-mail-DiscussCategory-chat .o-mail-DiscussCategory-add");
await tab1.click(".o-mail-DiscussSidebarCategory-chat .o-mail-DiscussSidebarCategory-add");
await tab1.insertText(".o-discuss-ChannelSelector input", "Jer");
await tab1.click(".o-discuss-ChannelSelector-suggestion");
await afterNextRender(() => triggerHotkey("Enter"));
assert.containsOnce(tab1.target, ".o-mail-DiscussCategoryItem:contains(Jerry Golay)");
assert.containsOnce(tab2.target, ".o-mail-DiscussCategoryItem:contains(Jerry Golay)");
assert.containsOnce(tab1.target, ".o-mail-DiscussSidebarChannel:contains(Jerry Golay)");
assert.containsOnce(tab2.target, ".o-mail-DiscussSidebarChannel:contains(Jerry Golay)");
});
@@ -30,7 +30,7 @@ QUnit.test("sidebar find shows channels matching search term", async (assert) =>
},
});
await openDiscuss();
await click(".o-mail-DiscussCategory-add");
await click(".o-mail-DiscussSidebarCategory-add");
await insertText(".o-discuss-ChannelSelector input", "test");
await def;
await nextAnimationFrame(); // ensures search_read rpc is rendered.
@@ -60,7 +60,7 @@ QUnit.test(
},
});
await openDiscuss();
await click(".o-mail-DiscussCategory-add");
await click(".o-mail-DiscussSidebarCategory-add");
await insertText(".o-discuss-ChannelSelector input", "test");
await def;
await nextAnimationFrame(); // ensures search_read rpc is rendered.
@@ -337,7 +337,10 @@ QUnit.test("chat: correspondent is typing", async (assert) => {
});
const { env, openDiscuss } = await start();
await openDiscuss();
assert.containsOnce($(".o-mail-DiscussCategoryItem"), ".o-mail-DiscussCategoryItem-threadIcon");
assert.containsOnce(
$(".o-mail-DiscussSidebarChannel"),
".o-mail-DiscussSidebarChannel-threadIcon"
);
assert.containsOnce($, ".fa-circle.text-success");
// simulate receive typing notification from demo "is typing"
@@ -240,10 +240,10 @@ QUnit.test("sidebar: chat im_status rendering", async (assert) => {
]);
const { openDiscuss } = await start({ hasTimeControl: true });
await openDiscuss();
assert.containsN($, ".o-mail-DiscussCategoryItem-threadIcon", 3);
const chat1 = $(".o-mail-DiscussCategoryItem")[0];
const chat2 = $(".o-mail-DiscussCategoryItem")[1];
const chat3 = $(".o-mail-DiscussCategoryItem")[2];
assert.containsN($, ".o-mail-DiscussSidebarChannel-threadIcon", 3);
const chat1 = $(".o-mail-DiscussSidebarChannel")[0];
const chat2 = $(".o-mail-DiscussSidebarChannel")[1];
const chat3 = $(".o-mail-DiscussSidebarChannel")[2];
assert.strictEqual(chat1.textContent, "Partner1");
assert.strictEqual(chat2.textContent, "Partner2");
assert.strictEqual(chat3.textContent, "Partner3");
@@ -313,7 +313,7 @@ QUnit.test("sidebar: chat custom name", async (assert) => {
});
const { openDiscuss } = await start();
await openDiscuss();
assert.strictEqual($(".o-mail-DiscussCategoryItem span").text(), "Marc");
assert.strictEqual($(".o-mail-DiscussSidebarChannel span").text(), "Marc");
});
QUnit.test("reply to message from inbox (message linked to document)", async (assert) => {
@@ -473,11 +473,11 @@ QUnit.test("basic rendering: sidebar", async (assert) => {
assert.containsOnce($, ".o-mail-DiscussSidebar button:contains(Inbox)");
assert.containsOnce($, ".o-mail-DiscussSidebar button:contains(Starred)");
assert.containsOnce($, ".o-mail-DiscussSidebar button:contains(History)");
assert.containsN($, ".o-mail-DiscussCategory", 2);
assert.containsOnce($, ".o-mail-DiscussCategory-channel");
assert.containsOnce($, ".o-mail-DiscussCategory-chat");
assert.strictEqual($(".o-mail-DiscussCategory-channel").text(), "Channels");
assert.strictEqual($(".o-mail-DiscussCategory-chat").text(), "Direct messages");
assert.containsN($, ".o-mail-DiscussSidebarCategory", 2);
assert.containsOnce($, ".o-mail-DiscussSidebarCategory-channel");
assert.containsOnce($, ".o-mail-DiscussSidebarCategory-chat");
assert.strictEqual($(".o-mail-DiscussSidebarCategory-channel").text(), "Channels");
assert.strictEqual($(".o-mail-DiscussSidebarCategory-chat").text(), "Direct messages");
});
QUnit.test("sidebar: Inbox should have icon", async (assert) => {
@@ -511,20 +511,23 @@ QUnit.test("sidebar: basic channel rendering", async (assert) => {
pyEnv["discuss.channel"].create({ name: "General" });
const { openDiscuss } = await start();
await openDiscuss();
assert.containsOnce($, ".o-mail-DiscussCategoryItem");
assert.strictEqual($(".o-mail-DiscussCategoryItem").text(), "General");
assert.containsOnce($(".o-mail-DiscussCategoryItem"), "img[data-alt='Thread Image']");
assert.containsOnce($(".o-mail-DiscussCategoryItem"), ".o-mail-DiscussCategoryItem-commands");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel");
assert.strictEqual($(".o-mail-DiscussSidebarChannel").text(), "General");
assert.containsOnce($(".o-mail-DiscussSidebarChannel"), "img[data-alt='Thread Image']");
assert.containsOnce(
$(".o-mail-DiscussSidebarChannel"),
".o-mail-DiscussSidebarChannel-commands"
);
assert.hasClass(
$(".o-mail-DiscussCategoryItem .o-mail-DiscussCategoryItem-commands"),
$(".o-mail-DiscussSidebarChannel .o-mail-DiscussSidebarChannel-commands"),
"d-none"
);
assert.containsOnce(
$(".o-mail-DiscussCategoryItem .o-mail-DiscussCategoryItem-commands"),
$(".o-mail-DiscussSidebarChannel .o-mail-DiscussSidebarChannel-commands"),
"i[title='Channel settings']"
);
assert.containsOnce(
$(".o-mail-DiscussCategoryItem .o-mail-DiscussCategoryItem-commands"),
$(".o-mail-DiscussSidebarChannel .o-mail-DiscussSidebarChannel-commands"),
"div[title='Leave this channel']"
);
});
@@ -534,10 +537,10 @@ QUnit.test("channel become active", async (assert) => {
pyEnv["discuss.channel"].create({ name: "General" });
const { openDiscuss } = await start();
await openDiscuss();
assert.containsOnce($, ".o-mail-DiscussCategoryItem");
assert.containsNone($, ".o-mail-DiscussCategoryItem.o-active");
await click(".o-mail-DiscussCategoryItem");
assert.containsOnce($, ".o-mail-DiscussCategoryItem.o-active");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel");
assert.containsNone($, ".o-mail-DiscussSidebarChannel.o-active");
await click(".o-mail-DiscussSidebarChannel");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel.o-active");
});
QUnit.test("channel become active - show composer in discuss content", async (assert) => {
@@ -545,7 +548,7 @@ QUnit.test("channel become active - show composer in discuss content", async (as
pyEnv["discuss.channel"].create({ name: "General" });
const { openDiscuss } = await start();
await openDiscuss();
await click(".o-mail-DiscussCategoryItem");
await click(".o-mail-DiscussSidebarChannel");
assert.containsOnce($, ".o-mail-Thread");
assert.containsOnce($, ".o-mail-Composer");
});
@@ -565,8 +568,8 @@ QUnit.test("sidebar: channel rendering with needaction counter", async (assert)
});
const { openDiscuss } = await start();
await openDiscuss();
assert.containsOnce($, ".o-mail-DiscussCategoryItem:contains(general)");
assert.containsOnce($, ".o-mail-DiscussCategoryItem:contains(general) .badge:contains(1)");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel:contains(general)");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel:contains(general) .badge:contains(1)");
});
QUnit.test("sidebar: chat rendering with unread counter", async (assert) => {
@@ -579,10 +582,10 @@ QUnit.test("sidebar: chat rendering with unread counter", async (assert) => {
});
const { openDiscuss } = await start();
await openDiscuss();
assert.containsOnce($, ".o-mail-DiscussCategoryItem .badge:contains(100)");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel .badge:contains(100)");
assert.containsNone(
$,
".o-mail-DiscussCategoryItem .o-mail-DiscussCategoryItem-commands:contains(Unpin Conversation)"
".o-mail-DiscussSidebarChannel .o-mail-DiscussSidebarChannel-commands:contains(Unpin Conversation)"
);
});
@@ -621,7 +624,7 @@ QUnit.test("basic top bar rendering", async (assert) => {
assert.isVisible($unstarAll);
assert.ok($unstarAll[0].disabled);
await click(".o-mail-DiscussCategoryItem:contains(General)");
await click(".o-mail-DiscussSidebarChannel:contains(General)");
assert.strictEqual($(".o-mail-Discuss-threadName").val(), "General");
assert.isVisible($(".o-mail-Discuss-header button[title='Add Users']"));
});
@@ -927,19 +930,19 @@ QUnit.test("auto-focus composer on opening thread", async (assert) => {
await openDiscuss();
assert.containsOnce($, "button:contains(Inbox)");
assert.hasClass($("button:contains(Inbox)"), "o-active");
assert.containsOnce($, ".o-mail-DiscussCategoryItem:contains(General)");
assert.doesNotHaveClass($(".o-mail-DiscussCategoryItem:contains(General)"), "o-active");
assert.containsOnce($, ".o-mail-DiscussCategoryItem:contains(Demo User)");
assert.doesNotHaveClass($(".o-mail-DiscussCategoryItem:contains(Demo User)"), "o-active");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel:contains(General)");
assert.doesNotHaveClass($(".o-mail-DiscussSidebarChannel:contains(General)"), "o-active");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel:contains(Demo User)");
assert.doesNotHaveClass($(".o-mail-DiscussSidebarChannel:contains(Demo User)"), "o-active");
assert.containsNone($, ".o-mail-Composer");
await click(".o-mail-DiscussCategoryItem:contains(General)");
assert.hasClass($(".o-mail-DiscussCategoryItem:contains(General)"), "o-active");
await click(".o-mail-DiscussSidebarChannel:contains(General)");
assert.hasClass($(".o-mail-DiscussSidebarChannel:contains(General)"), "o-active");
assert.containsOnce($, ".o-mail-Composer");
assert.strictEqual(document.activeElement, $(".o-mail-Composer-input")[0]);
await click(".o-mail-DiscussCategoryItem:contains(Demo User)");
assert.hasClass($(".o-mail-DiscussCategoryItem:contains(Demo User)"), "o-active");
await click(".o-mail-DiscussSidebarChannel:contains(Demo User)");
assert.hasClass($(".o-mail-DiscussSidebarChannel:contains(Demo User)"), "o-active");
assert.containsOnce($, ".o-mail-Composer");
assert.strictEqual(document.activeElement, $(".o-mail-Composer-input")[0]);
});
@@ -1110,7 +1113,7 @@ QUnit.test("should auto-pin chat when receiving a new DM", async (assert) => {
});
const { env, openDiscuss } = await start();
await openDiscuss();
assert.containsNone($, ".o-mail-DiscussCategoryItem:contains(Demo)");
assert.containsNone($, ".o-mail-DiscussSidebarChannel:contains(Demo)");
// simulate receiving the first message on channel 11
await afterNextRender(() =>
@@ -1121,7 +1124,7 @@ QUnit.test("should auto-pin chat when receiving a new DM", async (assert) => {
thread_model: "discuss.channel",
})
);
assert.containsOnce($, ".o-mail-DiscussCategoryItem:contains(Demo)");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel:contains(Demo)");
});
QUnit.test("'Add Users' button should be displayed in the topbar of channels", async (assert) => {
@@ -1254,18 +1257,18 @@ QUnit.test(
]);
const { openDiscuss } = await start();
await openDiscuss();
await click(".o-mail-DiscussCategoryItem:contains('Michel Online')");
await click(".o-mail-DiscussSidebarChannel:contains('Michel Online')");
assert.containsOnce($, ".o-mail-Discuss-header .o-mail-ImStatus [title='Online']");
await click(".o-mail-DiscussCategoryItem:contains('Jacqueline Offline')");
await click(".o-mail-DiscussSidebarChannel:contains('Jacqueline Offline')");
assert.containsOnce($, ".o-mail-Discuss-header .o-mail-ImStatus [title='Offline']");
await click(".o-mail-DiscussCategoryItem:contains('Nabuchodonosor Idle')");
await click(".o-mail-DiscussSidebarChannel:contains('Nabuchodonosor Idle')");
assert.containsOnce($, ".o-mail-Discuss-header .o-mail-ImStatus [title='Idle']");
await click(".o-mail-DiscussCategoryItem:contains('Robert Fired')");
await click(".o-mail-DiscussSidebarChannel:contains('Robert Fired')");
assert.containsOnce(
$,
".o-mail-Discuss-header .o-mail-ImStatus [title='No IM status available']"
);
await click(".o-mail-DiscussCategoryItem:contains('OdooBot')");
await click(".o-mail-DiscussSidebarChannel:contains('OdooBot')");
assert.containsOnce($, ".o-mail-Discuss-header .o-mail-ImStatus [title='Bot']");
}
);
@@ -1338,14 +1341,14 @@ QUnit.test("Channel is added to discuss after invitation", async (assert) => {
},
});
await openDiscuss();
assert.containsNone($, ".o-mail-DiscussCategoryItem:contains(General)");
assert.containsNone($, ".o-mail-DiscussSidebarChannel:contains(General)");
await afterNextRender(() => {
env.services.orm.call("discuss.channel", "add_members", [[channelId]], {
partner_ids: [pyEnv.currentPartnerId],
context: { mockedUserId: userId },
});
});
assert.containsOnce($, ".o-mail-DiscussCategoryItem:contains(General)");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel:contains(General)");
assert.verifySteps(["You have been invited to #General"]);
});
@@ -1828,7 +1831,9 @@ QUnit.test("Message shows up even if channel data is incomplete", async (assert)
thread_model: "discuss.channel",
})
);
await click(".o-mail-DiscussCategory-chat + .o-mail-DiscussCategoryItem:contains(Albert)");
await click(
".o-mail-DiscussSidebarCategory-chat + .o-mail-DiscussSidebarChannel:contains(Albert)"
);
assert.containsOnce($, ".o-mail-Message:contains(hello world)");
});
@@ -1841,7 +1846,7 @@ QUnit.test("Create a direct message channel when clicking on start a meeting", a
const { openDiscuss } = await start();
await openDiscuss(channelId);
await click("button:contains(Start a meeting)");
assert.containsOnce($, ".o-mail-DiscussCategoryItem:contains(Mitchell Admin)");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel:contains(Mitchell Admin)");
assert.containsOnce($, ".o-discuss-Call");
await waitUntil(".o-discuss-ChannelInvitation");
assert.containsOnce($, ".o-discuss-ChannelInvitation");
@@ -1857,7 +1862,7 @@ QUnit.test(
await click(".o-mail-NotificationItem:contains(General)");
await click("[title='Open Actions Menu']");
await click("[title='Open in Discuss']");
await click(".o-mail-DiscussCategoryItem:contains(General) [title='Channel settings']");
await click(".o-mail-DiscussSidebarChannel:contains(General) [title='Channel settings']");
assert.strictEqual($(".o_breadcrumb").text(), "DiscussGeneral");
}
);
@@ -404,13 +404,13 @@ QUnit.test("inbox: mark all messages as read", async (assert) => {
const { openDiscuss } = await start();
await openDiscuss();
assert.containsOnce($, "button:contains(Inbox) .badge:contains(2)");
assert.containsOnce($, ".o-mail-DiscussCategoryItem:contains(General) .badge:contains(2)");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel:contains(General) .badge:contains(2)");
assert.containsN($, ".o-mail-Discuss-content .o-mail-Message", 2);
assert.notOk($("button:contains(Mark all read)")[0].disabled);
await click(".o-mail-Discuss-header button:contains(Mark all read)");
assert.containsNone($, "button:contains(Inbox) .badge");
assert.containsNone($, ".o-mail-DiscussCategoryItem:contains(General) .badge");
assert.containsNone($, ".o-mail-DiscussSidebarChannel:contains(General) .badge");
assert.containsNone($, ".o-mail-Message");
assert.ok($("button:contains(Mark all read)")[0].disabled);
});
@@ -501,7 +501,7 @@ QUnit.test("inbox messages are never squashed", async (assert) => {
assert.containsN($, ".o-mail-Message", 2);
assert.doesNotHaveClass($(".o-mail-Message:contains(body1)"), "o-squashed");
assert.doesNotHaveClass($(".o-mail-Message:contains(body2)"), "o-squashed");
await click(".o-mail-DiscussCategoryItem:contains(test)");
await click(".o-mail-DiscussSidebarChannel:contains(test)");
assert.hasClass($(".o-mail-Message:contains(body2)"), "o-squashed");
});
@@ -25,10 +25,10 @@ QUnit.test("toggling category button hide category items", async (assert) => {
const { openDiscuss } = await start();
await openDiscuss();
assert.containsOnce($, "button.o-active:contains('Inbox')");
assert.containsOnce($, ".o-mail-DiscussCategoryItem");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel");
await click(".o-mail-DiscussCategory-icon");
assert.containsNone($, ".o-mail-DiscussCategoryItem");
await click(".o-mail-DiscussSidebarCategory-icon");
assert.containsNone($, ".o-mail-DiscussSidebarChannel");
});
QUnit.test("toggling category button does not hide active category items", async (assert) => {
@@ -39,12 +39,12 @@ QUnit.test("toggling category button does not hide active category items", async
]);
const { openDiscuss } = await start();
await openDiscuss(channelId);
assert.containsN($, ".o-mail-DiscussCategoryItem", 2);
assert.containsOnce($, ".o-mail-DiscussCategoryItem.o-active");
assert.containsN($, ".o-mail-DiscussSidebarChannel", 2);
assert.containsOnce($, ".o-mail-DiscussSidebarChannel.o-active");
await click(".o-mail-DiscussCategory-icon");
assert.containsOnce($, ".o-mail-DiscussCategoryItem");
assert.containsOnce($, ".o-mail-DiscussCategoryItem.o-active");
await click(".o-mail-DiscussSidebarCategory-icon");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel.o-active");
});
QUnit.test("Closing a category sends the updated user setting to the server.", async (assert) => {
@@ -60,7 +60,7 @@ QUnit.test("Closing a category sends the updated user setting to the server.", a
},
});
await openDiscuss();
await click(".o-mail-DiscussCategory-icon");
await click(".o-mail-DiscussSidebarCategory-icon");
assert.verifySteps(["/web/dataset/call_kw/res.users.settings/set_res_users_settings"]);
});
@@ -82,7 +82,7 @@ QUnit.test("Opening a category sends the updated user setting to the server.", a
},
});
await openDiscuss();
await click(".o-mail-DiscussCategory-icon");
await click(".o-mail-DiscussSidebarCategory-icon");
assert.verifySteps(["/web/dataset/call_kw/res.users.settings/set_res_users_settings"]);
});
@@ -105,7 +105,7 @@ QUnit.test(
});
const { openDiscuss } = await start();
await openDiscuss();
await click(".o-mail-DiscussCategory-channel span:contains(Channels)");
await click(".o-mail-DiscussSidebarCategory-channel span:contains(Channels)");
assert.containsOnce($, "i[title='View or join channels']");
}
);
@@ -142,9 +142,9 @@ QUnit.test("channel - states: close manually by clicking the title", async (asse
});
const { openDiscuss } = await start();
await openDiscuss();
assert.containsOnce($, ".o-mail-DiscussCategoryItem:contains(general)");
await click(".o-mail-DiscussCategory-channel span:contains(Channels)");
assert.containsNone($, ".o-mail-DiscussCategoryItem:contains(general)");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel:contains(general)");
await click(".o-mail-DiscussSidebarCategory-channel span:contains(Channels)");
assert.containsNone($, ".o-mail-DiscussSidebarChannel:contains(general)");
});
QUnit.test("channel - states: open manually by clicking the title", async (assert) => {
@@ -156,9 +156,9 @@ QUnit.test("channel - states: open manually by clicking the title", async (asser
});
const { openDiscuss } = await start();
await openDiscuss();
assert.containsNone($, ".o-mail-DiscussCategoryItem:contains(general)");
await click(".o-mail-DiscussCategory-channel span:contains(Channels)");
assert.containsOnce($, ".o-mail-DiscussCategoryItem:contains(general)");
assert.containsNone($, ".o-mail-DiscussSidebarChannel:contains(general)");
await click(".o-mail-DiscussSidebarCategory-channel span:contains(Channels)");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel:contains(general)");
});
QUnit.test("sidebar: inbox with counter", async (assert) => {
@@ -180,7 +180,7 @@ QUnit.test("default thread rendering", async (assert) => {
assert.containsOnce($, "button:contains(Inbox)");
assert.containsOnce($, "button:contains(Starred)");
assert.containsOnce($, "button:contains(History)");
assert.containsOnce($, ".o-mail-DiscussCategoryItem:contains(General)");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel:contains(General)");
assert.hasClass($("button:contains(Inbox)"), "o-active");
assert.containsOnce(
$,
@@ -201,8 +201,8 @@ QUnit.test("default thread rendering", async (assert) => {
".o-mail-Thread:contains(No history messages Messages marked as read will appear in the history.)"
);
await click(".o-mail-DiscussCategoryItem:contains(General)");
assert.hasClass($(".o-mail-DiscussCategoryItem:contains(General)"), "o-active");
await click(".o-mail-DiscussSidebarChannel:contains(General)");
assert.hasClass($(".o-mail-DiscussSidebarChannel:contains(General)"), "o-active");
assert.containsOnce($, ".o-mail-Thread:contains(There are no messages in this conversation.)");
});
@@ -213,7 +213,7 @@ QUnit.test("sidebar quick search at 20 or more pinned channels", async (assert)
}
const { openDiscuss } = await start();
await openDiscuss();
assert.containsN($, ".o-mail-DiscussCategoryItem", 20);
assert.containsN($, ".o-mail-DiscussSidebarChannel", 20);
assert.containsOnce($, ".o-mail-DiscussSidebar input[placeholder='Quick search...']");
await editInput(
@@ -221,22 +221,22 @@ QUnit.test("sidebar quick search at 20 or more pinned channels", async (assert)
".o-mail-DiscussSidebar input[placeholder='Quick search...']",
"1"
);
assert.containsN($, ".o-mail-DiscussCategoryItem", 11);
assert.containsN($, ".o-mail-DiscussSidebarChannel", 11);
await editInput(
document.body,
".o-mail-DiscussSidebar input[placeholder='Quick search...']",
"12"
);
assert.containsOnce($, ".o-mail-DiscussCategoryItem");
assert.containsOnce($, ".o-mail-DiscussCategoryItem:contains(channel12)");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel:contains(channel12)");
await editInput(
document.body,
".o-mail-DiscussSidebar input[placeholder='Quick search...']",
"123"
);
assert.containsNone($, ".o-mail-DiscussCategoryItem");
assert.containsNone($, ".o-mail-DiscussSidebarChannel");
});
QUnit.test("sidebar: basic chat rendering", async (assert) => {
@@ -251,14 +251,14 @@ QUnit.test("sidebar: basic chat rendering", async (assert) => {
});
const { openDiscuss } = await start();
await openDiscuss();
assert.containsOnce($, ".o-mail-DiscussCategoryItem:contains(Demo)");
const $chat = $(".o-mail-DiscussCategoryItem:contains(Demo)");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel:contains(Demo)");
const $chat = $(".o-mail-DiscussSidebarChannel:contains(Demo)");
assert.containsOnce($chat, "img[data-alt='Thread Image']");
assert.containsOnce($chat, "span:contains(Demo)");
assert.containsOnce($chat, ".o-mail-DiscussCategoryItem-commands");
assert.containsOnce($chat, ".o-mail-DiscussSidebarChannel-commands");
assert.containsOnce(
$chat,
".o-mail-DiscussCategoryItem-commands div[title='Unpin Conversation']"
".o-mail-DiscussSidebarChannel-commands div[title='Unpin Conversation']"
);
assert.containsNone($chat, ".badge");
});
@@ -268,7 +268,7 @@ QUnit.test("sidebar: show pinned channel", async (assert) => {
pyEnv["discuss.channel"].create({ name: "General" });
const { openDiscuss } = await start();
await openDiscuss();
assert.containsOnce($, ".o-mail-DiscussCategoryItem:contains(General)");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel:contains(General)");
});
QUnit.test("sidebar: open pinned channel", async (assert) => {
@@ -276,7 +276,7 @@ QUnit.test("sidebar: open pinned channel", async (assert) => {
pyEnv["discuss.channel"].create({ name: "General" });
const { openDiscuss } = await start();
await openDiscuss();
await click(".o-mail-DiscussCategoryItem:contains(General)");
await click(".o-mail-DiscussSidebarChannel:contains(General)");
assert.strictEqual($(".o-mail-Discuss-threadName").val(), "General");
assert.containsOnce($, ".o-mail-Composer-input[placeholder='Message #General…']");
});
@@ -302,12 +302,12 @@ QUnit.test("sidebar: open channel and leave it", async (assert) => {
},
});
await openDiscuss();
await click(".o-mail-DiscussCategoryItem:contains(General)");
await click(".o-mail-DiscussSidebarChannel:contains(General)");
assert.verifySteps([]);
await click(".o-mail-DiscussCategoryItem:contains(General) .btn[title='Leave this channel']");
await click(".o-mail-DiscussSidebarChannel:contains(General) .btn[title='Leave this channel']");
assert.verifySteps(["action_unfollow"]);
assert.containsNone($, ".o-mail-DiscussCategoryItem:contains(General)");
assert.containsNone($, ".o-mail-DiscussSidebarChannel:contains(General)");
assert.notOk($(".o-mail-Discuss-threadName")?.val() === "General");
});
@@ -316,9 +316,9 @@ QUnit.test("sidebar: unpin channel from bus", async (assert) => {
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
const { openDiscuss } = await start();
await openDiscuss();
assert.containsOnce($, ".o-mail-DiscussCategoryItem:contains(General)");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel:contains(General)");
await click(".o-mail-DiscussCategoryItem:contains(General)");
await click(".o-mail-DiscussSidebarChannel:contains(General)");
assert.strictEqual($(".o-mail-Discuss-threadName").val(), "General");
// Simulate receiving a leave channel notification
@@ -326,7 +326,7 @@ QUnit.test("sidebar: unpin channel from bus", async (assert) => {
await afterNextRender(() => {
pyEnv["bus.bus"]._sendone(pyEnv.currentPartner, "discuss.channel/unpin", { id: channelId });
});
assert.containsNone($, ".o-mail-DiscussCategoryItem:contains(General)");
assert.containsNone($, ".o-mail-DiscussSidebarChannel:contains(General)");
assert.notOk($(".o-mail-Discuss-threadName")?.val() === "General");
});
@@ -354,7 +354,7 @@ QUnit.test("chat - channel should count unread message [REQUIRE FOCUS]", async (
assert.containsOnce($, ".o-discuss-badge");
assert.strictEqual($(".o-discuss-badge").text(), "1");
await click(".o-mail-DiscussCategoryItem:contains(Demo)");
await click(".o-mail-DiscussSidebarChannel:contains(Demo)");
assert.containsNone($, ".o-discuss-badge");
});
@@ -373,11 +373,11 @@ QUnit.test("mark channel as seen on last message visible [REQUIRE FOCUS]", async
});
const { openDiscuss } = await start();
await openDiscuss();
assert.containsOnce($, ".o-mail-DiscussCategoryItem:contains(test)");
assert.hasClass($(".o-mail-DiscussCategoryItem:contains(test)"), "o-unread");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel:contains(test)");
assert.hasClass($(".o-mail-DiscussSidebarChannel:contains(test)"), "o-unread");
await click(".o-mail-DiscussCategoryItem:contains(test)");
assert.doesNotHaveClass($(".o-mail-DiscussCategoryItem:contains(test)"), "o-unread");
await click(".o-mail-DiscussSidebarChannel:contains(test)");
assert.doesNotHaveClass($(".o-mail-DiscussSidebarChannel:contains(test)"), "o-unread");
});
QUnit.test(
@@ -391,7 +391,7 @@ QUnit.test(
pyEnv["discuss.channel"].create({ name: "general" });
const { openDiscuss } = await start();
await openDiscuss();
assert.containsNone($, ".o-mail-DiscussCategory:contains(Channels) .badge");
assert.containsNone($, ".o-mail-DiscussSidebarCategory:contains(Channels) .badge");
}
);
@@ -433,7 +433,7 @@ QUnit.test(
]);
const { openDiscuss } = await start();
await openDiscuss();
assert.containsNone($, ".o-mail-DiscussCategory:contains(Channels) .badge");
assert.containsNone($, ".o-mail-DiscussSidebarCategory:contains(Channels) .badge");
}
);
@@ -448,7 +448,7 @@ QUnit.test(
});
const { openDiscuss } = await start();
await openDiscuss();
assert.containsNone($, ".o-mail-DiscussCategory:contains(Channels) .badge");
assert.containsNone($, ".o-mail-DiscussSidebarCategory:contains(Channels) .badge");
}
);
@@ -490,7 +490,10 @@ QUnit.test(
});
const { openDiscuss } = await start();
await openDiscuss();
assert.containsOnce($, ".o-mail-DiscussCategory:contains(Channels) .badge:contains(2)");
assert.containsOnce(
$,
".o-mail-DiscussSidebarCategory:contains(Channels) .badge:contains(2)"
);
}
);
@@ -510,7 +513,7 @@ QUnit.test(
});
const { openDiscuss } = await start();
await openDiscuss();
assert.containsNone($, ".o-mail-DiscussCategory:contains(Direct messages) .badge");
assert.containsNone($, ".o-mail-DiscussSidebarCategory:contains(Direct messages) .badge");
}
);
@@ -530,7 +533,7 @@ QUnit.test(
});
const { openDiscuss } = await start();
await openDiscuss();
assert.containsNone($, ".o-mail-DiscussCategory:contains(Direct messages) .badge");
assert.containsNone($, ".o-mail-DiscussSidebarCategory:contains(Direct messages) .badge");
}
);
@@ -550,7 +553,7 @@ QUnit.test(
});
const { openDiscuss } = await start();
await openDiscuss();
assert.containsNone($, ".o-mail-DiscussCategory:contains(Direct messages) .badge");
assert.containsNone($, ".o-mail-DiscussSidebarCategory:contains(Direct messages) .badge");
}
);
@@ -586,7 +589,7 @@ QUnit.test(
await openDiscuss();
assert.containsOnce(
$,
".o-mail-DiscussCategory:contains(Direct messages) .badge:contains(2)"
".o-mail-DiscussSidebarCategory:contains(Direct messages) .badge:contains(2)"
);
}
);
@@ -596,7 +599,7 @@ QUnit.test("chat - command: should have add command when category is unfolded",
await openDiscuss();
assert.containsOnce(
$,
".o-mail-DiscussCategory:contains(Direct messages) i[title='Start a conversation']"
".o-mail-DiscussSidebarCategory:contains(Direct messages) i[title='Start a conversation']"
);
});
@@ -612,7 +615,7 @@ QUnit.test(
await openDiscuss();
assert.containsNone(
$,
".o-mail-DiscussCategory:contains(Direct messages) i[title='Start a conversation']"
".o-mail-DiscussSidebarCategory:contains(Direct messages) i[title='Start a conversation']"
);
}
);
@@ -626,9 +629,9 @@ QUnit.test("chat - states: close manually by clicking the title", async (assert)
});
const { openDiscuss } = await start();
await openDiscuss();
assert.containsOnce($, ".o-mail-DiscussCategoryItem");
await click(".o-mail-DiscussCategory:contains(Direct messages) div");
assert.containsNone($, ".o-mail-DiscussCategoryItem");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel");
await click(".o-mail-DiscussSidebarCategory:contains(Direct messages) div");
assert.containsNone($, ".o-mail-DiscussSidebarChannel");
});
QUnit.test("sidebar channels should be ordered case insensitive alphabetically", async (assert) => {
@@ -643,10 +646,10 @@ QUnit.test("sidebar channels should be ordered case insensitive alphabetically",
await openDiscuss();
assert.deepEqual(
[
$(".o-mail-DiscussCategoryItem:eq(0)").text(),
$(".o-mail-DiscussCategoryItem:eq(1)").text(),
$(".o-mail-DiscussCategoryItem:eq(2)").text(),
$(".o-mail-DiscussCategoryItem:eq(3)").text(),
$(".o-mail-DiscussSidebarChannel:eq(0)").text(),
$(".o-mail-DiscussSidebarChannel:eq(1)").text(),
$(".o-mail-DiscussSidebarChannel:eq(2)").text(),
$(".o-mail-DiscussSidebarChannel:eq(3)").text(),
],
["abc", "Abc", "Xyz", "Xyz"]
);
@@ -673,7 +676,7 @@ QUnit.test("channel - avatar: should have correct avatar", async (assert) => {
});
const { openDiscuss } = await start();
await openDiscuss();
assert.containsOnce($, ".o-mail-DiscussCategoryItem img");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel img");
assert.containsOnce(
$,
`img[data-src='${getOrigin()}/discuss/channel/${channelId}/avatar_128?unique=100111']`
@@ -721,7 +724,7 @@ QUnit.test("channel - states: close should update the value on the server", asyn
[[currentUserId]]
);
assert.ok(initalSettings.is_discuss_sidebar_category_channel_open);
await click(".o-mail-DiscussCategory span:contains(Channels)");
await click(".o-mail-DiscussSidebarCategory span:contains(Channels)");
const newSettings = await env.services.orm.call(
"res.users.settings",
"_find_or_create_for_user",
@@ -747,7 +750,7 @@ QUnit.test("channel - states: open should update the value on the server", async
);
assert.notOk(initalSettings.is_discuss_sidebar_category_channel_open);
await click(".o-mail-DiscussCategory span:contains(Channels)");
await click(".o-mail-DiscussSidebarCategory span:contains(Channels)");
const newSettings = await env.services.orm.call(
"res.users.settings",
"_find_or_create_for_user",
@@ -773,7 +776,7 @@ QUnit.test("channel - states: close from the bus", async (assert) => {
},
});
});
assert.containsOnce($, ".o-mail-DiscussCategory-channel .oi-chevron-right");
assert.containsOnce($, ".o-mail-DiscussSidebarCategory-channel .oi-chevron-right");
assert.containsNone($, "button:contains(channel1)");
});
@@ -794,7 +797,7 @@ QUnit.test("channel - states: open from the bus", async (assert) => {
},
});
});
assert.containsOnce($, ".o-mail-DiscussCategory-channel .oi-chevron-down");
assert.containsOnce($, ".o-mail-DiscussSidebarCategory-channel .oi-chevron-down");
assert.containsOnce($, "button:contains(channel1)");
});
@@ -805,11 +808,11 @@ QUnit.test(
pyEnv["discuss.channel"].create({ name: "channel1" });
const { openDiscuss } = await start();
await openDiscuss();
await click(".o-mail-DiscussCategoryItem:contains(channel1)");
await click(".o-mail-DiscussSidebarChannel:contains(channel1)");
assert.containsOnce($, "button:contains(channel1).o-active");
await click(".o-mail-DiscussCategory span:contains(Channels)");
assert.containsOnce($, ".o-mail-DiscussCategory-channel .oi-chevron-right");
await click(".o-mail-DiscussSidebarCategory span:contains(Channels)");
assert.containsOnce($, ".o-mail-DiscussSidebarCategory-channel .oi-chevron-right");
assert.containsOnce($, "button:contains(channel1)");
await click("button:contains(Inbox)");
@@ -828,7 +831,7 @@ QUnit.test("chat - states: open manually by clicking the title", async (assert)
});
const { openDiscuss } = await start();
await openDiscuss();
await click(".o-mail-DiscussCategory-chat span:contains(Direct messages)");
await click(".o-mail-DiscussSidebarCategory-chat span:contains(Direct messages)");
assert.containsOnce($, "button:contains(Mitchell Admin)");
});
@@ -849,7 +852,7 @@ QUnit.test("chat - states: close should call update server data", async (assert)
);
assert.ok(initalSettings.is_discuss_sidebar_category_chat_open);
await click(".o-mail-DiscussCategory-chat span:contains(Direct messages)");
await click(".o-mail-DiscussSidebarCategory-chat span:contains(Direct messages)");
const newSettings = await env.services.orm.call(
"res.users.settings",
"_find_or_create_for_user",
@@ -875,7 +878,7 @@ QUnit.test("chat - states: open should call update server data", async (assert)
);
assert.notOk(initalSettings.is_discuss_sidebar_category_chat_open);
await click(".o-mail-DiscussCategory-chat span:contains(Direct messages)");
await click(".o-mail-DiscussSidebarCategory-chat span:contains(Direct messages)");
const newSettings = await env.services.orm.call(
"res.users.settings",
"_find_or_create_for_user",
@@ -901,7 +904,7 @@ QUnit.test("chat - states: close from the bus", async (assert) => {
},
});
});
assert.containsOnce($, ".o-mail-DiscussCategory-chat .oi-chevron-right");
assert.containsOnce($, ".o-mail-DiscussSidebarCategory-chat .oi-chevron-right");
assert.containsNone($, "button:contains(Mitchell Admin)");
});
@@ -922,7 +925,7 @@ QUnit.test("chat - states: open from the bus", async (assert) => {
},
});
});
assert.containsOnce($, ".o-mail-DiscussCategory-chat .oi-chevron-down");
assert.containsOnce($, ".o-mail-DiscussSidebarCategory-chat .oi-chevron-down");
assert.containsOnce($, "button:contains(Mitchell Admin)");
});
@@ -933,18 +936,18 @@ QUnit.test(
pyEnv["discuss.channel"].create({ channel_type: "chat" });
const { openDiscuss } = await start();
await openDiscuss();
assert.containsOnce($, ".o-mail-DiscussCategory-chat .oi-chevron-down");
assert.containsOnce($, ".o-mail-DiscussSidebarCategory-chat .oi-chevron-down");
assert.containsOnce($, "button:contains(Mitchell Admin)");
await click("button:contains(Mitchell Admin)");
assert.containsOnce($, "button:contains(Mitchell Admin).o-active");
await click(".o-mail-DiscussCategory-chat span:contains(Direct messages)");
assert.containsOnce($, ".o-mail-DiscussCategory-chat .oi-chevron-right");
await click(".o-mail-DiscussSidebarCategory-chat span:contains(Direct messages)");
assert.containsOnce($, ".o-mail-DiscussSidebarCategory-chat .oi-chevron-right");
assert.containsOnce($, "button:contains(Mitchell Admin)");
await click("button:contains(Inbox)");
assert.containsOnce($, ".o-mail-DiscussCategory-chat .oi-chevron-right");
assert.containsOnce($, ".o-mail-DiscussSidebarCategory-chat .oi-chevron-right");
assert.containsNone($, "button:contains(Mitchell Admin)");
}
);
@@ -965,7 +968,7 @@ QUnit.test("chat - avatar: should have correct avatar", async (assert) => {
const { openDiscuss } = await start();
await openDiscuss();
assert.containsOnce($, ".o-mail-DiscussCategoryItem img");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel img");
assert.containsOnce($, `img[data-src='/web/image/res.partner/${partnerId}/avatar_128']`);
});
@@ -1005,7 +1008,7 @@ QUnit.test("chat should be sorted by last activity time [REQUIRE FOCUS]", async
]);
const { openDiscuss } = await start();
await openDiscuss();
let $chats = $(".o-mail-DiscussCategory-chat ~ .o-mail-DiscussCategoryItem");
let $chats = $(".o-mail-DiscussSidebarCategory-chat ~ .o-mail-DiscussSidebarChannel");
assert.strictEqual($chats.length, 2);
assert.strictEqual($($chats[0]).text(), "Yoshi");
assert.strictEqual($($chats[1]).text(), "Demo");
@@ -1014,7 +1017,7 @@ QUnit.test("chat should be sorted by last activity time [REQUIRE FOCUS]", async
await click($($chats[1]));
await insertText(".o-mail-Composer-input", "Blabla");
await click(".o-mail-Composer-send");
$chats = $(".o-mail-DiscussCategory-chat ~ .o-mail-DiscussCategoryItem");
$chats = $(".o-mail-DiscussSidebarCategory-chat ~ .o-mail-DiscussSidebarChannel");
assert.strictEqual($chats.length, 2);
assert.strictEqual($($chats[0]).text(), "Demo");
assert.strictEqual($($chats[1]).text(), "Yoshi");
@@ -1025,9 +1028,9 @@ QUnit.test("Can unpin chat channel", async (assert) => {
pyEnv["discuss.channel"].create({ channel_type: "chat" });
const { openDiscuss } = await start();
await openDiscuss();
assert.containsOnce($, ".o-mail-DiscussCategoryItem:contains(Mitchell Admin)");
await click(".o-mail-DiscussCategoryItem [title='Unpin Conversation']");
assert.containsNone($, ".o-mail-DiscussCategoryItem:contains(Mitchell Admin)");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel:contains(Mitchell Admin)");
await click(".o-mail-DiscussSidebarChannel [title='Unpin Conversation']");
assert.containsNone($, ".o-mail-DiscussSidebarChannel:contains(Mitchell Admin)");
});
QUnit.test("Unpinning chat should display notification", async (assert) => {
@@ -1039,7 +1042,7 @@ QUnit.test("Unpinning chat should display notification", async (assert) => {
},
});
await openDiscuss();
await click(".o-mail-DiscussCategoryItem [title='Unpin Conversation']");
await click(".o-mail-DiscussSidebarChannel [title='Unpin Conversation']");
assert.verifySteps(["You unpinned your conversation with Mitchell Admin"]);
});
@@ -1048,7 +1051,7 @@ QUnit.test("Can leave channel", async (assert) => {
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
const { env, openDiscuss } = await start();
await openDiscuss(channelId);
assert.containsOnce($, ".o-mail-DiscussCategoryItem:contains(General)");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel:contains(General)");
const messageId = pyEnv["mail.message"].create({
body: '<div class="o_mail_notification">Mitchell Admin left the channel</div>',
model: "discuss.channel",
@@ -1062,7 +1065,7 @@ QUnit.test("Can leave channel", async (assert) => {
[channelId, "discuss.channel/new_message", { id: channelId, message }],
]);
});
assert.containsNone($, ".o-mail-DiscussCategoryItem:contains(General)");
assert.containsNone($, ".o-mail-DiscussSidebarChannel:contains(General)");
});
QUnit.test("Do no channel_info after unpin", async (assert) => {
@@ -1077,7 +1080,7 @@ QUnit.test("Do no channel_info after unpin", async (assert) => {
},
});
await openDiscuss(channelId);
await click(".o-mail-DiscussCategoryItem-commands [title='Unpin Conversation']");
await click(".o-mail-DiscussSidebarChannel-commands [title='Unpin Conversation']");
await afterNextRender(() => {
env.services.rpc("/mail/message/post", {
thread_id: channelId,
@@ -1118,8 +1121,8 @@ QUnit.test("Group unread counter up to date after mention is marked as seen", as
]);
const { openDiscuss } = await start();
await openDiscuss();
assert.containsOnce($, ".o-mail-DiscussCategoryItem .o-discuss-badge");
await click(".o-mail-DiscussCategoryItem");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel .o-discuss-badge");
await click(".o-mail-DiscussSidebarChannel");
await waitUntil(".o-discuss-badge", 0);
});
@@ -1132,7 +1135,7 @@ QUnit.test("Unpinning channel closes its chat window", async (assert) => {
await click(".o-mail-NotificationItem");
assert.containsOnce($, ".o-mail-ChatWindow:contains(Sales)");
await openDiscuss();
await click(".o-mail-DiscussCategoryItem:contains(Sales) [title='Leave this channel']");
await click(".o-mail-DiscussSidebarChannel:contains(Sales) [title='Leave this channel']");
await openFormView("discuss.channel");
assert.containsNone($, ".o-mail-ChatWindow:contains(Sales)");
});
@@ -690,11 +690,11 @@ QUnit.test("redirect to author (open chat)", async (assert) => {
});
const { openDiscuss } = await start();
await openDiscuss(channelId_1);
assert.containsOnce($, ".o-mail-DiscussCategoryItem.o-active:contains(General)");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel.o-active:contains(General)");
assert.containsOnce($, ".o-mail-Discuss-content .o-mail-Message-avatarContainer img");
await click(".o-mail-Discuss-content .o-mail-Message-avatarContainer img");
assert.containsOnce($, ".o-mail-DiscussCategoryItem.o-active:contains(Demo)");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel.o-active:contains(Demo)");
});
QUnit.test("open chat from avatar should not work on self-authored messages", async (assert) => {
@@ -720,7 +720,7 @@ QUnit.test("open chat from avatar should not work on self-authored messages", as
// try to click on self, to test it doesn't work
click(".o-mail-Message-avatar").catch(() => {});
await nextAnimationFrame();
assert.containsNone($, ".o-mail-DiscussCategoryItem.o-active:contains(Mitchell Admin)");
assert.containsNone($, ".o-mail-DiscussSidebarChannel.o-active:contains(Mitchell Admin)");
assert.containsNone($, ".breadcrumb:contains(Mitchell Admin)"); // should not open form view neither
});
@@ -1500,7 +1500,7 @@ QUnit.test("Mark as unread", async (assert) => {
await click("[title='Expand']");
await click("[title='Mark as Unread']");
assert.containsOnce($, ".o-mail-Thread-newMessage");
assert.containsOnce($, ".o-mail-DiscussCategoryItem .badge:contains(1)");
assert.containsOnce($, ".o-mail-DiscussSidebarChannel .badge:contains(1)");
});
QUnit.test("Avatar of unknown author", async (assert) => {
@@ -175,12 +175,12 @@ QUnit.test(
await openDiscuss(channelId_1);
const scrolltop_1 = $(".o-mail-Thread")[0].scrollHeight / 2;
$(".o-mail-Thread")[0].scrollTo({ top: scrolltop_1 });
await click(".o-mail-DiscussCategoryItem:contains(channel-2)");
await click(".o-mail-DiscussSidebarChannel:contains(channel-2)");
const scrolltop_2 = $(".o-mail-Thread")[0].scrollHeight / 3;
$(".o-mail-Thread")[0].scrollTo({ top: scrolltop_2 });
await click(".o-mail-DiscussCategoryItem:contains(channel-1)");
await click(".o-mail-DiscussSidebarChannel:contains(channel-1)");
assert.ok(isScrolledTo($(".o-mail-Thread")[0], scrolltop_1));
await click(".o-mail-DiscussCategoryItem:contains(channel-2)");
await click(".o-mail-DiscussSidebarChannel:contains(channel-2)");
assert.ok(isScrolledTo($(".o-mail-Thread")[0], scrolltop_2));
}
);
@@ -869,11 +869,11 @@ QUnit.test("Thread messages are only loaded once", async (assert) => {
},
]);
await openDiscuss();
await click(".o-mail-DiscussCategoryItem:eq(0)");
await click(".o-mail-DiscussSidebarChannel:eq(0)");
await waitUntil(".o-mail-Message:contains(channel1)");
await click(".o-mail-DiscussCategoryItem:eq(1)");
await click(".o-mail-DiscussSidebarChannel:eq(1)");
await waitUntil(".o-mail-Message:contains(channel2)");
await click(".o-mail-DiscussCategoryItem:eq(0)");
await click(".o-mail-DiscussSidebarChannel:eq(0)");
await waitUntil(".o-mail-Message:contains(channel1)");
assert.verifySteps([`load messages - ${channelIds[0]}`, `load messages - ${channelIds[1]}`]);
});
@@ -983,7 +983,7 @@ QUnit.test("can be marked as read while loading", async function (assert) {
});
await openDiscuss(undefined, { waitUntilMessagesLoaded: false });
assert.containsOnce($, ".o-discuss-badge:contains(1)");
await click(".o-mail-DiscussCategoryItem:contains(Demo)");
await click(".o-mail-DiscussSidebarChannel:contains(Demo)");
await afterNextRender(loadDeferred.resolve);
assert.containsNone($, ".o-discuss-badge");
});