[IMP] mail, website_livechat: introduce Discuss View
Task-2694206 closes odoo/odoo#83246 Signed-off-by: Sébastien Theys (seb) <seb@odoo.com>
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
<templates xml:space="preserve">
|
||||
<t t-inherit="mail.DiscussSidebar" t-inherit-mode="extension">
|
||||
<xpath expr="//*[@name='beforeCategoryChat']" position="before">
|
||||
<t t-set="categoryLivechat" t-value="messaging.discuss.categoryLivechat"/>
|
||||
<t t-set="categoryLivechat" t-value="discussView.discuss.categoryLivechat"/>
|
||||
<t t-if="categoryLivechat and categoryLivechat.categoryItems.length">
|
||||
<DiscussSidebarCategory
|
||||
className="'o_DiscussSidebar_category o_DiscussSidebar_categoryLivechat'"
|
||||
|
||||
+8
-8
@@ -977,10 +977,10 @@ QUnit.test('chat window: composer state conservation on toggle discuss', async f
|
||||
"composer should have 2 total attachments after adding 2 attachments"
|
||||
);
|
||||
|
||||
await afterNextRender(() => this.messaging.discuss.update({ isOpen: true }));
|
||||
await afterNextRender(() => this.messaging.discuss.open());
|
||||
assert.containsNone(document.body, '.o_ChatWindow', "should not have any chat window after opening discuss");
|
||||
|
||||
await afterNextRender(() => this.messaging.discuss.update({ isOpen: false }));
|
||||
await afterNextRender(() => this.messaging.discuss.close());
|
||||
assert.strictEqual(
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`).value,
|
||||
"XDU for the win !",
|
||||
@@ -1039,12 +1039,12 @@ QUnit.test('chat window: scroll conservation on toggle discuss', async function
|
||||
},
|
||||
});
|
||||
|
||||
await afterNextRender(() => this.messaging.discuss.update({ isOpen: true }));
|
||||
await afterNextRender(() => this.messaging.discuss.open());
|
||||
assert.containsNone(document.body, '.o_ChatWindow', "should not have any chat window after opening discuss");
|
||||
|
||||
await this.afterEvent({
|
||||
eventName: 'o-component-message-list-scrolled',
|
||||
func: () => this.messaging.discuss.update({ isOpen: false }),
|
||||
func: () => this.messaging.discuss.close(),
|
||||
message: "should wait until channel 20 restored its scroll to 142 after closing discuss",
|
||||
predicate: ({ scrollTop, thread }) => {
|
||||
return (
|
||||
@@ -1968,10 +1968,10 @@ QUnit.test('chat window with a thread: keep scroll position in message list on t
|
||||
});
|
||||
// fold chat window
|
||||
await afterNextRender(() => document.querySelector('.o_ChatWindow_header').click());
|
||||
await afterNextRender(() => this.messaging.discuss.update({ isOpen: true }));
|
||||
await afterNextRender(() => this.messaging.discuss.open());
|
||||
assert.containsNone(document.body, '.o_ChatWindow', "should not have any chat window after opening discuss");
|
||||
|
||||
await afterNextRender(() => this.messaging.discuss.update({ isOpen: false }));
|
||||
await afterNextRender(() => this.messaging.discuss.close());
|
||||
// unfold chat window
|
||||
await this.afterEvent({
|
||||
eventName: 'o-component-message-list-scrolled',
|
||||
@@ -2039,10 +2039,10 @@ QUnit.test('chat window with a thread: keep scroll position in message list on t
|
||||
});
|
||||
// fold chat window
|
||||
await afterNextRender(() => document.querySelector('.o_ChatWindow_header').click());
|
||||
await afterNextRender(() => this.messaging.discuss.update({ isOpen: true }));
|
||||
await afterNextRender(() => this.messaging.discuss.open());
|
||||
assert.containsNone(document.body, '.o_ChatWindow', "should not have any chat window after opening discuss");
|
||||
|
||||
await afterNextRender(() => this.messaging.discuss.update({ isOpen: false }));
|
||||
await afterNextRender(() => this.messaging.discuss.close());
|
||||
// unfold chat window
|
||||
await this.afterEvent({
|
||||
eventName: 'o-component-message-list-scrolled',
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { registerMessagingComponent } from '@mail/utils/messaging_component';
|
||||
import { useUpdate } from '@mail/component_hooks/use_update/use_update';
|
||||
import { registerMessagingComponent } from '@mail/utils/messaging_component';
|
||||
|
||||
const { Component, onWillUnmount } = owl;
|
||||
const { Component } = owl;
|
||||
|
||||
export class Discuss extends Component {
|
||||
|
||||
@@ -17,39 +17,31 @@ export class Discuss extends Component {
|
||||
this._onMobileAddItemHeaderInputSelect = this._onMobileAddItemHeaderInputSelect.bind(this);
|
||||
this._onMobileAddItemHeaderInputSource = this._onMobileAddItemHeaderInputSource.bind(this);
|
||||
useUpdate({ func: () => this._update() });
|
||||
onWillUnmount(() => this._willUnmount());
|
||||
this._onHideMobileAddItemHeader = this._onHideMobileAddItemHeader.bind(this);
|
||||
}
|
||||
|
||||
_update() {
|
||||
if (!this.discuss) {
|
||||
if (!this.discussView) {
|
||||
return;
|
||||
}
|
||||
this.discuss.update({ isOpen: true });
|
||||
if (this.discuss.thread) {
|
||||
if (this.discussView.discuss.thread) {
|
||||
this.trigger('o-push-state-action-manager');
|
||||
} else if (!this._activeThreadCache && this.discuss.messaging.isInitialized) {
|
||||
this.discuss.openInitThread();
|
||||
} else if (!this._activeThreadCache) {
|
||||
this.discussView.discuss.openInitThread();
|
||||
}
|
||||
if (
|
||||
this.discuss.thread &&
|
||||
this.discuss.thread === this.messaging.inbox &&
|
||||
this.discuss.threadView &&
|
||||
this._lastThreadCache === this.discuss.threadView.threadCache.localId &&
|
||||
this._lastThreadCounter > 0 && this.discuss.thread.counter === 0
|
||||
this.discussView.discuss.thread &&
|
||||
this.discussView.discuss.thread === this.messaging.inbox &&
|
||||
this.discussView.discuss.threadView &&
|
||||
this._lastThreadCache === this.discussView.discuss.threadView.threadCache.localId &&
|
||||
this._lastThreadCounter > 0 && this.discussView.discuss.thread.counter === 0
|
||||
) {
|
||||
this.trigger('o-show-rainbow-man');
|
||||
}
|
||||
this._activeThreadCache = this.discuss.threadView && this.discuss.threadView.threadCache;
|
||||
this._activeThreadCache = this.discussView.discuss.threadView && this.discussView.discuss.threadView.threadCache;
|
||||
this._updateLocalStoreProps();
|
||||
}
|
||||
|
||||
_willUnmount() {
|
||||
if (this.discuss) {
|
||||
this.discuss.close();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Public
|
||||
//--------------------------------------------------------------------------
|
||||
@@ -69,10 +61,10 @@ export class Discuss extends Component {
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {Discuss}
|
||||
* @returns {DiscussView}
|
||||
*/
|
||||
get discuss() {
|
||||
return this.messaging && this.messaging.discuss;
|
||||
get discussView() {
|
||||
return this.messaging && this.messaging.models['DiscussView'].get(this.props.localId);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
@@ -83,7 +75,7 @@ export class Discuss extends Component {
|
||||
* @private
|
||||
*/
|
||||
_updateLocalStoreProps() {
|
||||
if (!this.discuss) {
|
||||
if (!this.discussView) {
|
||||
return;
|
||||
}
|
||||
/**
|
||||
@@ -92,17 +84,17 @@ export class Discuss extends Component {
|
||||
* rainbox man on inbox.
|
||||
*/
|
||||
this._lastThreadCache = (
|
||||
this.discuss.threadView &&
|
||||
this.discuss.threadView.threadCache &&
|
||||
this.discuss.threadView.threadCache.localId
|
||||
this.discussView.discuss.threadView &&
|
||||
this.discussView.discuss.threadView.threadCache &&
|
||||
this.discussView.discuss.threadView.threadCache.localId
|
||||
);
|
||||
/**
|
||||
* Locally tracked store props `threadCounter`.
|
||||
* Useful to display the rainbow man on inbox.
|
||||
*/
|
||||
this._lastThreadCounter = (
|
||||
this.discuss.thread &&
|
||||
this.discuss.thread.counter
|
||||
this.discussView.discuss.thread &&
|
||||
this.discussView.discuss.thread.counter
|
||||
);
|
||||
}
|
||||
|
||||
@@ -114,7 +106,10 @@ export class Discuss extends Component {
|
||||
* @private
|
||||
*/
|
||||
_onHideMobileAddItemHeader() {
|
||||
this.discuss.clearIsAddingItem();
|
||||
if (!this.discussView) {
|
||||
return;
|
||||
}
|
||||
this.discussView.discuss.clearIsAddingItem();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -125,7 +120,10 @@ export class Discuss extends Component {
|
||||
* @param {integer} ui.item.id
|
||||
*/
|
||||
_onMobileAddItemHeaderInputSelect(ev, ui) {
|
||||
const discuss = this.discuss;
|
||||
if (!this.discussView) {
|
||||
return;
|
||||
}
|
||||
const discuss = this.discussView.discuss;
|
||||
if (discuss.isAddingChannel) {
|
||||
discuss.handleAddChannelAutocompleteSelect(ev, ui);
|
||||
} else {
|
||||
@@ -140,17 +138,20 @@ export class Discuss extends Component {
|
||||
* @param {function} res
|
||||
*/
|
||||
_onMobileAddItemHeaderInputSource(req, res) {
|
||||
if (this.discuss.isAddingChannel) {
|
||||
this.discuss.handleAddChannelAutocompleteSource(req, res);
|
||||
if (!this.discussView) {
|
||||
return;
|
||||
}
|
||||
if (this.discussView.discuss.isAddingChannel) {
|
||||
this.discussView.discuss.handleAddChannelAutocompleteSource(req, res);
|
||||
} else {
|
||||
this.discuss.handleAddChatAutocompleteSource(req, res);
|
||||
this.discussView.discuss.handleAddChatAutocompleteSource(req, res);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Object.assign(Discuss, {
|
||||
props: {},
|
||||
props: { localId: String },
|
||||
template: 'mail.Discuss',
|
||||
});
|
||||
|
||||
|
||||
@@ -30,17 +30,6 @@
|
||||
flex-flow: column;
|
||||
}
|
||||
|
||||
.o_Discuss_messagingNotInitialized {
|
||||
flex: 1 1 auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.o_Discuss_messagingNotInitializedIcon {
|
||||
margin-right: map-get($spacers, 1);
|
||||
}
|
||||
|
||||
.o_Discuss_mobileAddItemHeader {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
@@ -4,17 +4,14 @@
|
||||
<t t-name="mail.Discuss" owl="1">
|
||||
<div class="o_Discuss" t-attf-class="{{ className }}"
|
||||
t-att-class="{
|
||||
'o-adding-item': discuss ? discuss.isAddingChannel or discuss.isAddingChat : false,
|
||||
'o-adding-item': discussView ? discussView.discuss.isAddingChannel or discussView.discuss.isAddingChat : false,
|
||||
'o-mobile': messaging ? messaging.device.isMobile : false,
|
||||
}"
|
||||
t-ref="root"
|
||||
>
|
||||
<t t-if="!discuss or !messaging.isInitialized">
|
||||
<div class="o_Discuss_messagingNotInitialized"><i class="o_Discuss_messagingNotInitializedIcon fa fa-circle-o-notch fa-spin"/>Please wait...</div>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<t t-if="discussView">
|
||||
<t t-if="!messaging.device.isMobile">
|
||||
<DiscussSidebar className="'o_Discuss_sidebar bg-light border-right'" localId="discuss.localId"/>
|
||||
<DiscussSidebar className="'o_Discuss_sidebar bg-light border-right'" localId="discussView.localId"/>
|
||||
</t>
|
||||
<t t-if="messaging.device.isMobile" t-call="mail.Discuss.content"/>
|
||||
<t t-else="">
|
||||
@@ -27,58 +24,58 @@
|
||||
</t>
|
||||
|
||||
<t t-name="mail.Discuss.content" owl="1">
|
||||
<t t-if="messaging.device.isMobile and discuss.activeMobileNavbarTabId === 'mailbox'">
|
||||
<t t-if="messaging.device.isMobile and discussView.discuss.activeMobileNavbarTabId === 'mailbox'">
|
||||
<DiscussMobileMailboxSelection className="'o_Discuss_mobileMailboxSelection border-bottom'"/>
|
||||
</t>
|
||||
<t t-if="messaging.device.isMobile and (discuss.isAddingChannel or discuss.isAddingChat)">
|
||||
<t t-if="messaging.device.isMobile and (discussView.discuss.isAddingChannel or discussView.discuss.isAddingChat)">
|
||||
<div class="o_Discuss_mobileAddItemHeader border-bottom">
|
||||
<AutocompleteInput
|
||||
className="'o_Discuss_mobileAddItemHeaderInput'"
|
||||
isFocusOnMount="true"
|
||||
isHtml="discuss.isAddingChannel"
|
||||
placeholder="discuss.isAddingChannel ? addChannelInputPlaceholder : addChatInputPlaceholder"
|
||||
isHtml="discussView.discuss.isAddingChannel"
|
||||
placeholder="discussView.discuss.isAddingChannel ? addChannelInputPlaceholder : addChatInputPlaceholder"
|
||||
select="_onMobileAddItemHeaderInputSelect"
|
||||
source="_onMobileAddItemHeaderInputSource"
|
||||
onHide="_onHideMobileAddItemHeader"
|
||||
/>
|
||||
</div>
|
||||
</t>
|
||||
<t t-if="discuss.threadView">
|
||||
<t t-if="discussView.discuss.threadView">
|
||||
<t name="beforeThread"/>
|
||||
<ThreadView
|
||||
className="'o_Discuss_thread'"
|
||||
t-att-class="{ 'o-mobile': messaging.device.isMobile }"
|
||||
hasComposerCurrentPartnerAvatar="!messaging.device.isMobile"
|
||||
hasComposerDiscardButton="discuss.thread === messaging.inbox"
|
||||
hasComposerThreadName="discuss.thread === messaging.inbox"
|
||||
hasComposerDiscardButton="discussView.discuss.thread === messaging.inbox"
|
||||
hasComposerThreadName="discussView.discuss.thread === messaging.inbox"
|
||||
hasComposerThreadTyping="true"
|
||||
localId="discuss.threadView.localId"
|
||||
localId="discussView.discuss.threadView.localId"
|
||||
/>
|
||||
</t>
|
||||
<t t-if="!discuss.thread and (!messaging.device.isMobile or discuss.activeMobileNavbarTabId === 'mailbox')">
|
||||
<t t-if="!discussView.discuss.thread and (!messaging.device.isMobile or discussView.discuss.activeMobileNavbarTabId === 'mailbox')">
|
||||
<div class="o_Discuss_noThread">
|
||||
No conversation selected.
|
||||
</div>
|
||||
</t>
|
||||
<t t-if="messaging.device.isMobile and discuss.activeMobileNavbarTabId !== 'mailbox'">
|
||||
<t t-if="discuss.activeMobileNavbarTabId === 'chat'">
|
||||
<button class="o_Discuss_mobileNewChatButton btn btn-secondary" t-on-click="discuss.onClickMobileNewChatButton.bind(discuss)">
|
||||
<t t-if="messaging.device.isMobile and discussView.discuss.activeMobileNavbarTabId !== 'mailbox'">
|
||||
<t t-if="discussView.discuss.activeMobileNavbarTabId === 'chat'">
|
||||
<button class="o_Discuss_mobileNewChatButton btn btn-secondary" t-on-click="discussView.discuss.onClickMobileNewChatButton">
|
||||
Start a conversation
|
||||
</button>
|
||||
</t>
|
||||
<t t-if="discuss.activeMobileNavbarTabId === 'channel'">
|
||||
<button class="o_Discuss_mobileNewChannelButton btn btn-secondary" t-on-click="discuss.onClickMobileNewChannelButton.bind(discuss)">
|
||||
<t t-if="discussView.discuss.activeMobileNavbarTabId === 'channel'">
|
||||
<button class="o_Discuss_mobileNewChannelButton btn btn-secondary" t-on-click="discussView.discuss.onClickMobileNewChannelButton">
|
||||
New Channel
|
||||
</button>
|
||||
</t>
|
||||
</t>
|
||||
<t t-if="discuss.notificationListView">
|
||||
<NotificationList className="'o_Discuss_notificationList'" localId="discuss.notificationListView.localId"/>
|
||||
<t t-if="discussView.discuss.notificationListView">
|
||||
<NotificationList className="'o_Discuss_notificationList'" localId="discussView.discuss.notificationListView.localId"/>
|
||||
</t>
|
||||
<t t-if="discuss.mobileMessagingNavbarView">
|
||||
<t t-if="discussView.discuss.mobileMessagingNavbarView">
|
||||
<MobileMessagingNavbar
|
||||
className="'o_Discuss_mobileNavbar'"
|
||||
localId="discuss.mobileMessagingNavbarView.localId"
|
||||
localId="discussView.discuss.mobileMessagingNavbarView.localId"
|
||||
/>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
@@ -49,7 +49,7 @@ QUnit.test('messaging not created', async function (assert) {
|
||||
messagingBeforeCreationDeferred,
|
||||
waitUntilMessagingCondition: 'none'
|
||||
});
|
||||
assert.containsOnce(document.body, '.o_Discuss_messagingNotInitialized', "should display messaging not initialized");
|
||||
assert.containsOnce(document.body, '.o_DiscussContainer_spinner', "should display messaging not initialized");
|
||||
messagingBeforeCreationDeferred.resolve();
|
||||
});
|
||||
|
||||
@@ -64,7 +64,7 @@ QUnit.test('discuss should be marked as opened if the component is already rende
|
||||
|
||||
await afterNextRender(() => messagingBeforeCreationDeferred.resolve());
|
||||
assert.ok(
|
||||
this.messaging.discuss.isOpen,
|
||||
this.messaging.discuss.discussView,
|
||||
"discuss should be marked as opened if the component is already rendered and messaging becomes created afterwards"
|
||||
);
|
||||
});
|
||||
@@ -76,7 +76,7 @@ QUnit.test('discuss should be marked as closed when the component is unmounted',
|
||||
|
||||
await afterNextRender(() => widget.destroy());
|
||||
assert.notOk(
|
||||
this.messaging.discuss.isOpen,
|
||||
this.messaging.discuss.discussView,
|
||||
"discuss should be marked as closed when the component is unmounted"
|
||||
);
|
||||
});
|
||||
@@ -95,7 +95,7 @@ QUnit.test('messaging not initialized', async function (assert) {
|
||||
waitUntilMessagingCondition: 'created',
|
||||
});
|
||||
assert.strictEqual(
|
||||
document.querySelectorAll('.o_Discuss_messagingNotInitialized').length,
|
||||
document.querySelectorAll('.o_DiscussContainer_spinner').length,
|
||||
1,
|
||||
"should display messaging not initialized"
|
||||
);
|
||||
@@ -117,14 +117,14 @@ QUnit.test('messaging becomes initialized', async function (assert) {
|
||||
waitUntilMessagingCondition: 'created',
|
||||
});
|
||||
assert.strictEqual(
|
||||
document.querySelectorAll('.o_Discuss_messagingNotInitialized').length,
|
||||
document.querySelectorAll('.o_DiscussContainer_spinner').length,
|
||||
1,
|
||||
"should display messaging not initialized"
|
||||
);
|
||||
|
||||
await afterNextRender(() => messagingInitializedProm.resolve());
|
||||
assert.strictEqual(
|
||||
document.querySelectorAll('.o_Discuss_messagingNotInitialized').length,
|
||||
document.querySelectorAll('.o_DiscussContainer_spinner').length,
|
||||
0,
|
||||
"should no longer display messaging not initialized"
|
||||
);
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { useModels } from "@mail/component_hooks/use_models/use_models";
|
||||
import { useUpdate } from '@mail/component_hooks/use_update/use_update';
|
||||
import { getMessagingComponent } from "@mail/utils/messaging_component";
|
||||
|
||||
const { Component, onWillUnmount } = owl;
|
||||
|
||||
export class DiscussContainer extends Component {
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
setup() {
|
||||
// for now, the legacy env is needed for internal functions such as
|
||||
// `useModels` to work
|
||||
this.env = Component.env;
|
||||
useModels();
|
||||
super.setup();
|
||||
useUpdate({ func: () => this._update() });
|
||||
onWillUnmount(() => this._willUnmount());
|
||||
}
|
||||
|
||||
_update() {
|
||||
if (!this.messaging || !this.messaging.discuss) {
|
||||
return;
|
||||
}
|
||||
this.messaging.discuss.open();
|
||||
}
|
||||
|
||||
_willUnmount() {
|
||||
if (this.messaging && this.messaging.discuss) {
|
||||
this.messaging.discuss.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Object.assign(DiscussContainer, {
|
||||
components: { Discuss: getMessagingComponent('Discuss') },
|
||||
template: 'mail.DiscussContainer',
|
||||
});
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates xml:space="preserve">
|
||||
|
||||
<t t-name="mail.DiscussContainer" owl="1">
|
||||
<div class="o_DiscussContainer d-flex flex-grow-1">
|
||||
<Discuss t-if="messaging and messaging.discuss and messaging.discuss.discussView and messaging.isInitialized" className="'flex-grow-1'" localId="messaging.discuss.discussView.localId"/>
|
||||
<div t-else="" class="o_DiscussContainer_spinner d-flex flex-grow-1 align-items-center justify-content-center">
|
||||
<i class="o_DiscussContainer_spinnerIcon fa fa-circle-o-notch fa-spin me-2"/>Please wait...
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
@@ -25,10 +25,10 @@ export class DiscussSidebar extends Component {
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @returns {Discuss}
|
||||
* @returns {DiscussView}
|
||||
*/
|
||||
get discuss() {
|
||||
return this.messaging && this.messaging.models['Discuss'].get(this.props.localId);
|
||||
get discussView() {
|
||||
return this.messaging && this.messaging.models['DiscussView'].get(this.props.localId);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
@@ -39,11 +39,11 @@ export class DiscussSidebar extends Component {
|
||||
* @private
|
||||
*/
|
||||
_update() {
|
||||
if (!this.discuss) {
|
||||
if (!this.discussView) {
|
||||
return;
|
||||
}
|
||||
if (this._quickSearchInputRef.el) {
|
||||
this._quickSearchInputRef.el.value = this.discuss.sidebarQuickSearchValue;
|
||||
this._quickSearchInputRef.el.value = this.discussView.discuss.sidebarQuickSearchValue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ export class DiscussSidebar extends Component {
|
||||
*/
|
||||
_onInputQuickSearch(ev) {
|
||||
ev.stopPropagation();
|
||||
this.discuss.onInputQuickSearch(this._quickSearchInputRef.el.value);
|
||||
this.discussView.discuss.onInputQuickSearch(this._quickSearchInputRef.el.value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,30 +3,34 @@
|
||||
|
||||
<t t-name="mail.DiscussSidebar" owl="1">
|
||||
<div name="root" class="o_DiscussSidebar" t-attf-class="{{ className }}" t-ref="root">
|
||||
<div class="d-flex justify-content-center">
|
||||
<button class="o_DiscussSidebar_startAMeetingButton btn btn-primary rounded" title="Start a meeting" t-on-click="discuss.onClickStartAMeetingButton">
|
||||
Start a meeting
|
||||
</button>
|
||||
</div>
|
||||
<hr class="o_DiscussSidebar_separator"/>
|
||||
<div class="o_DiscussSidebar_category o_DiscussSidebar_categoryMailbox">
|
||||
<DiscussSidebarMailbox threadLocalId="messaging.inbox.localId"/>
|
||||
<DiscussSidebarMailbox threadLocalId="messaging.starred.localId"/>
|
||||
<DiscussSidebarMailbox threadLocalId="messaging.history.localId"/>
|
||||
</div>
|
||||
<hr class="o_DiscussSidebar_separator"/>
|
||||
<t t-if="messaging.models['Thread'].all(thread => thread.isPinned and thread.model === 'mail.channel').length > 19">
|
||||
<input class="o_DiscussSidebar_quickSearch" t-on-input="_onInputQuickSearch" placeholder="Quick search..." t-ref="quickSearchInput" t-esc="discuss.sidebarQuickSearchValue"/>
|
||||
<t t-if="discussView">
|
||||
<div class="d-flex justify-content-center">
|
||||
<button class="o_DiscussSidebar_startAMeetingButton btn btn-primary rounded" title="Start a meeting" t-on-click="discussView.discuss.onClickStartAMeetingButton">
|
||||
Start a meeting
|
||||
</button>
|
||||
</div>
|
||||
<hr class="o_DiscussSidebar_separator"/>
|
||||
<div class="o_DiscussSidebar_category o_DiscussSidebar_categoryMailbox">
|
||||
<DiscussSidebarMailbox threadLocalId="messaging.inbox.localId"/>
|
||||
<DiscussSidebarMailbox threadLocalId="messaging.starred.localId"/>
|
||||
<DiscussSidebarMailbox threadLocalId="messaging.history.localId"/>
|
||||
</div>
|
||||
<hr class="o_DiscussSidebar_separator"/>
|
||||
<t t-if="messaging.models['Thread'].all(thread => thread.isPinned and thread.model === 'mail.channel').length > 19">
|
||||
<input class="o_DiscussSidebar_quickSearch" t-on-input="_onInputQuickSearch" placeholder="Quick search..." t-ref="quickSearchInput" t-esc="discussView.discuss.sidebarQuickSearchValue"/>
|
||||
</t>
|
||||
<DiscussSidebarCategory
|
||||
t-if="discussView.discuss.categoryChannel"
|
||||
className="'o_DiscussSidebar_category o_DiscussSidebar_categoryChannel'"
|
||||
localId="discussView.discuss.categoryChannel.localId"
|
||||
/>
|
||||
<t name="beforeCategoryChat"/>
|
||||
<DiscussSidebarCategory
|
||||
t-if="discussView.discuss.categoryChat"
|
||||
className="'o_DiscussSidebar_category o_DiscussSidebar_categoryChat'"
|
||||
localId="discussView.discuss.categoryChat.localId"
|
||||
/>
|
||||
</t>
|
||||
<DiscussSidebarCategory
|
||||
className="'o_DiscussSidebar_category o_DiscussSidebar_categoryChannel'"
|
||||
localId="discuss.categoryChannel.localId"
|
||||
/>
|
||||
<t name="beforeCategoryChat"/>
|
||||
<DiscussSidebarCategory
|
||||
className="'o_DiscussSidebar_category o_DiscussSidebar_categoryChat'"
|
||||
localId="discuss.categoryChat.localId"
|
||||
/>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
<t t-call="mail.MessagingMenu.newMessageButton"/>
|
||||
</t>
|
||||
<div class="o-autogrow"/>
|
||||
<t t-if="!messaging.device.isMobile and !messaging.discuss.isOpen">
|
||||
<t t-if="!messaging.device.isMobile and !messaging.discuss.discussView">
|
||||
<t t-call="mail.MessagingMenu.newMessageButton"/>
|
||||
</t>
|
||||
<t t-if="messaging.device.isMobile and messagingMenu.isMobileNewMessageToggled">
|
||||
|
||||
@@ -19,7 +19,7 @@ registerModel({
|
||||
if (notifyServer === undefined) {
|
||||
notifyServer = !this.messaging.device.isMobile;
|
||||
}
|
||||
if (this.messaging.device.isMobile && !this.messaging.discuss.isOpen) {
|
||||
if (this.messaging.device.isMobile && !this.messaging.discuss.discussView) {
|
||||
// If we are in mobile and discuss is not open, it means the
|
||||
// chat window was opened from the messaging menu. In that
|
||||
// case it should be re-opened to simulate it was always
|
||||
|
||||
@@ -272,7 +272,7 @@ registerModel({
|
||||
const HIDDEN_MENU_WIDTH = 200; // max width, including width of dropup list items
|
||||
const START_GAP_WIDTH = device.isMobile ? 0 : 10;
|
||||
const chatWindows = this.allOrdered;
|
||||
if (!device.isMobile && discuss.isOpen) {
|
||||
if (!device.isMobile && discuss.discussView) {
|
||||
return visual;
|
||||
}
|
||||
if (!chatWindows.length) {
|
||||
|
||||
@@ -21,7 +21,7 @@ registerModel({
|
||||
* Close the discuss app. Should reset its internal state.
|
||||
*/
|
||||
close() {
|
||||
this.update({ isOpen: false });
|
||||
this.update({ discussView: clear() });
|
||||
},
|
||||
focus() {
|
||||
if (this.threadView && this.threadView.composerView) {
|
||||
@@ -158,6 +158,9 @@ registerModel({
|
||||
}
|
||||
this.threadView.topbar.openInvitePopoverView();
|
||||
},
|
||||
open() {
|
||||
this.update({ discussView: insertAndReplace() });
|
||||
},
|
||||
/**
|
||||
* Open thread from init active id. `initActiveId` is used to refer to
|
||||
* a thread that we may not have full data yet, such as when messaging
|
||||
@@ -193,7 +196,7 @@ registerModel({
|
||||
if (focus !== undefined ? focus : !this.messaging.device.isMobileDevice) {
|
||||
this.focus();
|
||||
}
|
||||
if (!this.isOpen) {
|
||||
if (!this.discussView) {
|
||||
this.env.bus.trigger('do-action', {
|
||||
action: 'mail.action_discuss',
|
||||
options: {
|
||||
@@ -237,7 +240,7 @@ registerModel({
|
||||
* @returns {string}
|
||||
*/
|
||||
_computeAddingChannelValue() {
|
||||
if (!this.isOpen) {
|
||||
if (!this.discussView) {
|
||||
return "";
|
||||
}
|
||||
return this.addingChannelValue;
|
||||
@@ -247,7 +250,7 @@ registerModel({
|
||||
* @returns {boolean}
|
||||
*/
|
||||
_computeHasThreadView() {
|
||||
if (!this.thread || !this.isOpen) {
|
||||
if (!this.thread || !this.discussView) {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
@@ -266,7 +269,7 @@ registerModel({
|
||||
* @returns {boolean}
|
||||
*/
|
||||
_computeIsAddingChannel() {
|
||||
if (!this.isOpen) {
|
||||
if (!this.discussView) {
|
||||
return false;
|
||||
}
|
||||
return this.isAddingChannel;
|
||||
@@ -276,7 +279,7 @@ registerModel({
|
||||
* @returns {boolean}
|
||||
*/
|
||||
_computeIsAddingChat() {
|
||||
if (!this.isOpen) {
|
||||
if (!this.discussView) {
|
||||
return false;
|
||||
}
|
||||
return this.isAddingChat;
|
||||
@@ -357,6 +360,10 @@ registerModel({
|
||||
inverse: 'discussAsChat',
|
||||
isCausal: true,
|
||||
}),
|
||||
discussView: one('DiscussView', {
|
||||
inverse: 'discuss',
|
||||
isCausal: true,
|
||||
}),
|
||||
/**
|
||||
* Determines whether `this.thread` should be displayed.
|
||||
*/
|
||||
@@ -390,13 +397,6 @@ registerModel({
|
||||
compute: '_computeIsAddingChat',
|
||||
default: false,
|
||||
}),
|
||||
/**
|
||||
* Whether the discuss app is open or not. Useful to determine
|
||||
* whether the discuss or chat window logic should be applied.
|
||||
*/
|
||||
isOpen: attr({
|
||||
default: false,
|
||||
}),
|
||||
/**
|
||||
* The menu_id of discuss app, received on mail/init_messaging and
|
||||
* used to open discuss from elsewhere.
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { registerModel } from '@mail/model/model_core';
|
||||
import { one } from '@mail/model/model_field';
|
||||
|
||||
registerModel({
|
||||
name: 'DiscussView',
|
||||
identifyingFields: ['discuss'],
|
||||
fields: {
|
||||
discuss: one('Discuss', {
|
||||
inverse: 'discussView',
|
||||
readonly: true,
|
||||
required: true,
|
||||
}),
|
||||
},
|
||||
});
|
||||
@@ -40,7 +40,7 @@ registerModel({
|
||||
route: '/mail/init_messaging',
|
||||
}, { shadow: true }));
|
||||
await this.async(() => this._init(data));
|
||||
if (discuss.isOpen) {
|
||||
if (discuss.discussView) {
|
||||
discuss.openInitThread();
|
||||
}
|
||||
if (this.messaging.autofetchPartnerImStatus) {
|
||||
|
||||
@@ -942,7 +942,7 @@ registerModel({
|
||||
const discuss = this.messaging.discuss;
|
||||
// check if thread must be opened in form view
|
||||
if (!['mail.box', 'mail.channel'].includes(this.model)) {
|
||||
if (expanded || discuss.isOpen) {
|
||||
if (expanded || discuss.discussView) {
|
||||
// Close chat window because having the same thread opened
|
||||
// both in chat window and as main document does not look
|
||||
// good.
|
||||
@@ -957,7 +957,7 @@ registerModel({
|
||||
// check if thread must be opened in discuss
|
||||
const device = this.messaging.device;
|
||||
if (
|
||||
(!device.isMobile && (discuss.isOpen || expanded)) ||
|
||||
(!device.isMobile && (discuss.discussView || expanded)) ||
|
||||
this.model === 'mail.box'
|
||||
) {
|
||||
return discuss.openThread(this, {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { getMessagingComponent } from "@mail/utils/messaging_component";
|
||||
import { DiscussContainer } from "@mail/components/discuss_container/discuss_container";
|
||||
|
||||
import AbstractAction from 'web.AbstractAction';
|
||||
|
||||
@@ -63,8 +63,7 @@ export const DiscussWidget = AbstractAction.extend({
|
||||
// prevent twice call to on_attach_callback (FIXME)
|
||||
return;
|
||||
}
|
||||
const DiscussComponent = getMessagingComponent("Discuss");
|
||||
this.component = new DiscussComponent();
|
||||
this.component = new DiscussContainer();
|
||||
this._pushStateActionManagerEventListener = ev => {
|
||||
ev.stopPropagation();
|
||||
if (this._lastPushStateActiveThread === this.discuss.thread) {
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
<templates xml:space="preserve">
|
||||
<t t-inherit="mail.Discuss.content" t-inherit-mode="extension">
|
||||
<xpath expr="//*[@name='beforeThread']" position="before">
|
||||
<t t-if="discuss.thread.visitor">
|
||||
<t t-if="discussView.discuss.thread.visitor">
|
||||
<VisitorBanner
|
||||
visitorLocalId="discuss.thread.visitor.localId"
|
||||
visitorLocalId="discussView.discuss.thread.visitor.localId"
|
||||
/>
|
||||
</t>
|
||||
</xpath>
|
||||
|
||||
Reference in New Issue
Block a user