[IMP] mail, *: move code from components to models (ThreadIcon)
Task-3002515. * = hr_holidays, im_livechat closes odoo/odoo#101774 Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
This commit is contained in:
@@ -2,13 +2,13 @@
|
||||
<templates xml:space="preserve">
|
||||
<t t-inherit="mail.ThreadIcon" t-inherit-mode="extension">
|
||||
<xpath expr="//*[@name='noImStatusCondition']" position="before">
|
||||
<t t-elif="thread.channel.correspondent.im_status === 'leave_online'">
|
||||
<t t-elif="threadIconView.thread.channel.correspondent.im_status === 'leave_online'">
|
||||
<div class="o_ThreadIcon_online fa fa-fw fa-plane" title="Online"/>
|
||||
</t>
|
||||
<t t-elif="thread.channel.correspondent.im_status === 'leave_away'">
|
||||
<t t-elif="threadIconView.thread.channel.correspondent.im_status === 'leave_away'">
|
||||
<div class="o_ThreadIcon_away fa fa-fw fa-plane text-warning" title="Away"/>
|
||||
</t>
|
||||
<t t-elif="thread.channel.correspondent.im_status === 'leave_offline'">
|
||||
<t t-elif="threadIconView.thread.channel.correspondent.im_status === 'leave_offline'">
|
||||
<div class="o_ThreadIcon_offline fa fa-fw fa-plane" title="Out of office"/>
|
||||
</t>
|
||||
</xpath>
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
<templates xml:space="preserve">
|
||||
<t t-inherit="mail.ThreadIcon" t-inherit-mode="extension">
|
||||
<xpath expr="//*[@name='root']" position="inside">
|
||||
<t t-elif="thread.channel and thread.channel.channel_type === 'livechat'">
|
||||
<t t-if="thread.orderedOtherTypingMembers.length > 0">
|
||||
<t t-elif="threadIconView.thread.channel and threadIconView.thread.channel.channel_type === 'livechat'">
|
||||
<t t-if="threadIconView.thread.orderedOtherTypingMembers.length > 0">
|
||||
<ThreadTypingIcon
|
||||
className="'o_ThreadIcon_typing'"
|
||||
animation="'pulse'"
|
||||
title="thread.typingStatusText"
|
||||
title="threadIconView.thread.typingStatusText"
|
||||
/>
|
||||
</t>
|
||||
<t t-else="">
|
||||
|
||||
@@ -32,14 +32,6 @@ registerPatch({
|
||||
return this._super();
|
||||
},
|
||||
},
|
||||
hasThreadIcon: {
|
||||
compute() {
|
||||
if (this.channel.channel_type === 'livechat') {
|
||||
return clear();
|
||||
}
|
||||
return this._super();
|
||||
},
|
||||
},
|
||||
hasUnpinCommand: {
|
||||
compute() {
|
||||
if (this.channel.channel_type === 'livechat') {
|
||||
@@ -48,5 +40,13 @@ registerPatch({
|
||||
return this._super();
|
||||
},
|
||||
},
|
||||
threadIconView: {
|
||||
compute() {
|
||||
if (this.channel.channel_type === 'livechat') {
|
||||
return clear();
|
||||
}
|
||||
return this._super();
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
<i class="fa fa-arrow-left"/>
|
||||
</div>
|
||||
</t>
|
||||
<t t-if="chatWindow.thread and chatWindow.thread.model === 'mail.channel'">
|
||||
<t t-if="chatWindowHeaderView.threadIconView">
|
||||
<ThreadIcon
|
||||
className="'o_ChatWindowHeader_icon o_ChatWindowHeader_item ms-3 me-1 my-0'"
|
||||
thread="chatWindow.thread"
|
||||
record="chatWindowHeaderView.threadIconView"
|
||||
/>
|
||||
</t>
|
||||
<div class="o_ChatWindowHeader_item o_ChatWindowHeader_name mh-100 mx-1 my-0 text-truncate" t-att-class="{'ms-3':!chatWindow.thread or chatWindow.thread.model !== 'mail.channel'}" t-att-title="chatWindow.name">
|
||||
|
||||
+2
-2
@@ -14,8 +14,8 @@
|
||||
<div class="o_DiscussSidebarCategoryItem_item o_DiscussSidebarCategoryItem_avatar ms-4">
|
||||
<div class="o_DiscussSidebarCategoryItem_imageContainer position-relative d-flex">
|
||||
<img class="o_DiscussSidebarCategoryItem_image w-100 h-100 rounded-circle" t-att-src="categoryItem.avatarUrl" alt="Thread Image"/>
|
||||
<t t-if="categoryItem.hasThreadIcon">
|
||||
<ThreadIcon className="'o_DiscussSidebarCategoryItem_threadIcon position-absolute bottom-0 end-0 d-flex align-items-center justify-content-center rounded-circle bg-100'" thread="categoryItem.thread"/>
|
||||
<t t-if="categoryItem.threadIconView">
|
||||
<ThreadIcon className="'o_DiscussSidebarCategoryItem_threadIcon position-absolute bottom-0 end-0 d-flex align-items-center justify-content-center rounded-circle bg-100'" record="categoryItem.threadIconView"/>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@
|
||||
}" t-attf-class="{{ className }}" t-on-click="discussSidebarMailboxView.mailbox.thread.onClick" t-att-data-mailbox-local-id="discussSidebarMailboxView.mailbox.localId" t-att-data-mailbox-name="discussSidebarMailboxView.mailbox.name"
|
||||
t-ref="root"
|
||||
>
|
||||
<ThreadIcon className="'o_DiscussSidebarMailbox_item ms-4 me-2'" thread="discussSidebarMailboxView.mailbox.thread"/>
|
||||
<ThreadIcon className="'o_DiscussSidebarMailbox_item ms-4 me-2'" record="discussSidebarMailboxView.threadIconView"/>
|
||||
<div class="o_DiscussSidebarMailbox_item o_DiscussSidebarMailbox_name me-2 text-truncate">
|
||||
<t t-esc="discussSidebarMailboxView.mailbox.name"/>
|
||||
</div>
|
||||
|
||||
@@ -7,16 +7,16 @@ const { Component } = owl;
|
||||
export class ThreadIcon extends Component {
|
||||
|
||||
/**
|
||||
* @returns {Thread}
|
||||
* @returns {ThreadIconView}
|
||||
*/
|
||||
get thread() {
|
||||
return this.props.thread;
|
||||
get threadIconView() {
|
||||
return this.props.record;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Object.assign(ThreadIcon, {
|
||||
props: { thread: Object },
|
||||
props: { record: Object },
|
||||
template: 'mail.ThreadIcon',
|
||||
});
|
||||
|
||||
|
||||
@@ -2,51 +2,51 @@
|
||||
<templates xml:space="preserve">
|
||||
|
||||
<t t-name="mail.ThreadIcon" owl="1">
|
||||
<t t-if="thread">
|
||||
<t t-if="threadIconView">
|
||||
<div class="o_ThreadIcon d-flex justify-content-center flex-shrink-0" t-attf-class="{{ className }}" t-ref="root" name="root">
|
||||
<t t-if="thread.channel and thread.channel.channel_type === 'channel'">
|
||||
<t t-if="thread.authorizedGroupFullName">
|
||||
<div class="o_ThreadIcon_groupRestrictedChannel fa fa-fw fa-hashtag" t-att-title="thread.accessRestrictedToGroupText"/>
|
||||
<t t-if="threadIconView.thread.channel and threadIconView.thread.channel.channel_type === 'channel'">
|
||||
<t t-if="threadIconView.thread.authorizedGroupFullName">
|
||||
<div class="o_ThreadIcon_groupRestrictedChannel fa fa-fw fa-hashtag" t-att-title="threadIconView.thread.accessRestrictedToGroupText"/>
|
||||
</t>
|
||||
<t t-if="!thread.authorizedGroupFullName">
|
||||
<t t-if="!threadIconView.thread.authorizedGroupFullName">
|
||||
<div class="o_ThreadIcon_publicChannel fa fa-fw fa-globe" title="Public Channel"/>
|
||||
</t>
|
||||
</t>
|
||||
<t t-elif="thread.channel and thread.channel.channel_type === 'chat' and thread.channel.correspondent">
|
||||
<t t-if="thread.orderedOtherTypingMembers.length > 0">
|
||||
<t t-elif="threadIconView.thread.channel and threadIconView.thread.channel.channel_type === 'chat' and threadIconView.thread.channel.correspondent">
|
||||
<t t-if="threadIconView.thread.orderedOtherTypingMembers.length > 0">
|
||||
<ThreadTypingIcon
|
||||
className="'o_ThreadIcon_typing flex-grow-1'"
|
||||
animation="'pulse'"
|
||||
title="thread.typingStatusText"
|
||||
title="threadIconView.thread.typingStatusText"
|
||||
/>
|
||||
</t>
|
||||
<t t-elif="thread.channel.correspondent.im_status === 'online'">
|
||||
<t t-elif="threadIconView.thread.channel.correspondent.im_status === 'online'">
|
||||
<div class="o_ThreadIcon_online fa fa-fw fa-circle" title="Online"/>
|
||||
</t>
|
||||
<t t-elif="thread.channel.correspondent.im_status === 'offline'">
|
||||
<t t-elif="threadIconView.thread.channel.correspondent.im_status === 'offline'">
|
||||
<div class="o_ThreadIcon_offline fa fa-fw fa-circle-o" title="Offline"/>
|
||||
</t>
|
||||
<t t-elif="thread.channel.correspondent.im_status === 'away'">
|
||||
<t t-elif="threadIconView.thread.channel.correspondent.im_status === 'away'">
|
||||
<div class="o_ThreadIcon_away fa fa-fw fa-circle text-warning" title="Away"/>
|
||||
</t>
|
||||
<t t-elif="thread.channel.correspondent === messaging.partnerRoot">
|
||||
<t t-elif="threadIconView.thread.channel.correspondent === messaging.partnerRoot">
|
||||
<div class="o_ThreadIcon_online fa fa-fw fa-heart" title="Bot"/>
|
||||
</t>
|
||||
<t t-else="" name="noImStatusCondition">
|
||||
<div class="o_ThreadIcon_noImStatus fa fa-fw fa-question-circle" title="No IM status available"/>
|
||||
</t>
|
||||
</t>
|
||||
<t t-elif="thread.channel and thread.channel.channel_type === 'group'">
|
||||
<t t-elif="threadIconView.thread.channel and threadIconView.thread.channel.channel_type === 'group'">
|
||||
<div class="o_ThreadIcon fa fa-fw fa-users" title="Grouped Chat"/>
|
||||
</t>
|
||||
<t t-elif="thread.mailbox">
|
||||
<t t-if="thread.mailbox === messaging.inbox">
|
||||
<t t-elif="threadIconView.thread.mailbox">
|
||||
<t t-if="threadIconView.thread.mailbox === messaging.inbox">
|
||||
<div class="o_ThreadIcon_mailboxInbox fa fa-fw fa-inbox"/>
|
||||
</t>
|
||||
<t t-elif="thread.mailbox === messaging.starred">
|
||||
<t t-elif="threadIconView.thread.mailbox === messaging.starred">
|
||||
<div class="o_ThreadIcon_mailboxStarred fa fa-fw fa-star-o"/>
|
||||
</t>
|
||||
<t t-elif="thread.mailbox === messaging.history">
|
||||
<t t-elif="threadIconView.thread.mailbox === messaging.history">
|
||||
<div class="o_ThreadIcon_mailboxHistory fa fa-fw fa-history"/>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
<t t-name="mail.ThreadViewTopbar" owl="1">
|
||||
<t t-if="threadViewTopbar">
|
||||
<div class="o_ThreadViewTopbar d-flex flex-shrink-0 w-100 px-3 bg-100" t-attf-class="{{ className }}" t-ref="root">
|
||||
<t t-if="threadViewTopbar.thread">
|
||||
<ThreadIcon className="'o_ThreadViewTopbar_threadIcon me-2 align-self-center'" thread="threadViewTopbar.thread"/>
|
||||
<t t-if="threadViewTopbar.threadIconView">
|
||||
<ThreadIcon className="'o_ThreadViewTopbar_threadIcon me-2 align-self-center'" record="threadViewTopbar.threadIconView"/>
|
||||
</t>
|
||||
<div class="o_ThreadViewTopbar_title d-flex flex-grow-1 align-self-center align-items-center">
|
||||
<t t-if="threadViewTopbar.thread">
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import { registerModel } from '@mail/model/model_core';
|
||||
import { one } from '@mail/model/model_field';
|
||||
import { clear } from '@mail/model/model_field_command';
|
||||
import { isEventHandled } from '@mail/utils/utils';
|
||||
|
||||
registerModel({
|
||||
@@ -33,5 +34,14 @@ registerModel({
|
||||
identifying: true,
|
||||
inverse: 'chatWindowHeaderView',
|
||||
}),
|
||||
threadIconView: one('ThreadIconView', {
|
||||
compute() {
|
||||
if (this.chatWindowOwner.thread && this.chatWindowOwner.thread.channel) {
|
||||
return {};
|
||||
}
|
||||
return clear();
|
||||
},
|
||||
inverse: 'chatWindowHeaderViewOwner',
|
||||
})
|
||||
},
|
||||
});
|
||||
|
||||
@@ -188,24 +188,6 @@ registerModel({
|
||||
return this.channel.channel_type === 'channel';
|
||||
},
|
||||
}),
|
||||
/**
|
||||
* Boolean determines whether ThreadIcon will be displayed in UI.
|
||||
*/
|
||||
hasThreadIcon: attr({
|
||||
compute() {
|
||||
if (!this.thread) {
|
||||
return clear();
|
||||
}
|
||||
switch (this.channel.channel_type) {
|
||||
case 'channel':
|
||||
return !Boolean(this.thread.authorizedGroupFullName);
|
||||
case 'chat':
|
||||
return true;
|
||||
case 'group':
|
||||
return false;
|
||||
}
|
||||
},
|
||||
}),
|
||||
/**
|
||||
* Boolean determines whether the item has a "unpin" command.
|
||||
*/
|
||||
@@ -236,5 +218,21 @@ registerModel({
|
||||
thread: one('Thread', {
|
||||
related: 'channel.thread'
|
||||
}),
|
||||
threadIconView: one('ThreadIconView', {
|
||||
compute() {
|
||||
if (!this.thread) {
|
||||
return clear();
|
||||
}
|
||||
switch (this.channel.channel_type) {
|
||||
case 'channel':
|
||||
return this.thread.authorizedGroupFullName ? clear() : {};
|
||||
case 'chat':
|
||||
return {};
|
||||
case 'group':
|
||||
return clear();
|
||||
}
|
||||
},
|
||||
inverse: 'discussSidebarCategoryItemOwner',
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -35,5 +35,9 @@ registerModel({
|
||||
},
|
||||
required: true,
|
||||
}),
|
||||
threadIconView: one('ThreadIconView', {
|
||||
default: {},
|
||||
inverse: 'discussSidebarMailboxViewOwner',
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -7,7 +7,6 @@ import { htmlToTextContentInline } from '@mail/js/utils';
|
||||
import { escape, sprintf } from '@web/core/utils/strings';
|
||||
import { str_to_datetime } from 'web.time';
|
||||
import { Markup } from 'web.utils';
|
||||
import { renderToString } from "@web/core/utils/render";
|
||||
|
||||
const PREVIEW_MSG_MAX_SIZE = 350; // optimal for native English speakers
|
||||
|
||||
@@ -651,19 +650,12 @@ registerModel({
|
||||
notificationTitle = this.env._t("New message");
|
||||
} else {
|
||||
if (channel.channel_type === 'channel') {
|
||||
// hack: notification template does not support OWL components,
|
||||
// so we simply use their template to make HTML as if it comes
|
||||
// from component
|
||||
const channelIcon = renderToString('mail.ThreadIcon', {
|
||||
env: this.env,
|
||||
thread: channel.thread,
|
||||
});
|
||||
const channelName = channel.thread.displayName;
|
||||
const channelNameWithIcon = channelIcon + channelName;
|
||||
notificationTitle = sprintf(
|
||||
this.env._t("%s from %s"),
|
||||
author.nameOrDisplayName,
|
||||
channelNameWithIcon
|
||||
this.env._t("%(author name)s from %(channel name)s"),
|
||||
{
|
||||
'author name': author.nameOrDisplayName,
|
||||
'channel name': channel.displayName,
|
||||
}
|
||||
);
|
||||
} else {
|
||||
notificationTitle = author.nameOrDisplayName;
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { registerModel } from '@mail/model/model_core';
|
||||
import { one } from '@mail/model/model_field';
|
||||
|
||||
registerModel({
|
||||
name: 'ThreadIconView',
|
||||
identifyingMode: 'xor',
|
||||
fields: {
|
||||
chatWindowHeaderViewOwner: one('ChatWindowHeaderView', {
|
||||
identifying: true,
|
||||
inverse: 'threadIconView',
|
||||
}),
|
||||
discussSidebarCategoryItemOwner: one('DiscussSidebarCategoryItem', {
|
||||
identifying: true,
|
||||
inverse: 'threadIconView',
|
||||
}),
|
||||
discussSidebarMailboxViewOwner: one('DiscussSidebarMailboxView', {
|
||||
identifying: true,
|
||||
inverse: 'threadIconView',
|
||||
}),
|
||||
thread: one('Thread', {
|
||||
compute() {
|
||||
if (this.chatWindowHeaderViewOwner) {
|
||||
return this.chatWindowHeaderViewOwner.chatWindowOwner.thread;
|
||||
}
|
||||
if (this.discussSidebarCategoryItemOwner) {
|
||||
return this.discussSidebarCategoryItemOwner.thread;
|
||||
}
|
||||
if (this.discussSidebarMailboxViewOwner) {
|
||||
return this.discussSidebarMailboxViewOwner.mailbox.thread;
|
||||
}
|
||||
if (this.threadViewTopbarOwner) {
|
||||
return this.threadViewTopbarOwner.thread
|
||||
}
|
||||
},
|
||||
required: true,
|
||||
}),
|
||||
threadViewTopbarOwner: one('ThreadViewTopbar', {
|
||||
identifying: true,
|
||||
inverse: 'threadIconView',
|
||||
}),
|
||||
},
|
||||
});
|
||||
@@ -688,6 +688,15 @@ registerModel({
|
||||
* Useful to focus it, or to know when a click is done outside of it.
|
||||
*/
|
||||
threadDescriptionInputRef: attr(),
|
||||
threadIconView: one('ThreadIconView', {
|
||||
compute() {
|
||||
if (this.thread) {
|
||||
return {};
|
||||
}
|
||||
return clear();
|
||||
},
|
||||
inverse: 'threadViewTopbarOwner',
|
||||
}),
|
||||
/**
|
||||
* States the thread view managing this top bar.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user