[IMP] mail: rename ComposerSuggestion to ComposerSuggestionView
Part of task-2741982 Part-of: odoo/odoo#95341
This commit is contained in:
+4
-4
@@ -4,7 +4,7 @@ import { registerMessagingComponent } from '@mail/utils/messaging_component';
|
||||
|
||||
const { Component } = owl;
|
||||
|
||||
export class ComposerSuggestionList extends Component {
|
||||
export class ComposerSuggestionListView extends Component {
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Public
|
||||
@@ -19,9 +19,9 @@ export class ComposerSuggestionList extends Component {
|
||||
|
||||
}
|
||||
|
||||
Object.assign(ComposerSuggestionList, {
|
||||
Object.assign(ComposerSuggestionListView, {
|
||||
props: { record: Object },
|
||||
template: 'mail.ComposerSuggestionList',
|
||||
template: 'mail.ComposerSuggestionListView',
|
||||
});
|
||||
|
||||
registerMessagingComponent(ComposerSuggestionList);
|
||||
registerMessagingComponent(ComposerSuggestionListView);
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
// Layout
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
.o_ComposerSuggestionList_list {
|
||||
.o_ComposerSuggestionListView_list {
|
||||
// prevent from overflowing chat window, must be smaller than its height
|
||||
// minus the max height taken by composer and attachment list
|
||||
max-height: 150px;
|
||||
|
||||
+9
-9
@@ -1,19 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates xml:space="preserve">
|
||||
|
||||
<t t-name="mail.ComposerSuggestionList" owl="1">
|
||||
<t t-name="mail.ComposerSuggestionListView" owl="1">
|
||||
<t t-if="composerSuggestionListView">
|
||||
<div class="o_ComposerSuggestionList position-absolute w-100" t-att-class="{ 'o-lowPosition bottom-0': composerSuggestionListView.composerViewOwner.hasMentionSuggestionsBelowPosition }" t-attf-class="{{ className }}" t-ref="root">
|
||||
<div class="o_ComposerSuggestionList_drop w-100" t-att-class="{ 'dropdown': composerSuggestionListView.composerViewOwner.hasMentionSuggestionsBelowPosition, 'dropup': !composerSuggestionListView.composerViewOwner.hasMentionSuggestionsBelowPosition }">
|
||||
<div class="o_ComposerSuggestionList_list dropdown-menu show w-100 overflow-auto" t-att-class="{ 'bottom-100': !composerSuggestionListView.composerViewOwner.hasMentionSuggestionsBelowPosition }">
|
||||
<t t-foreach="composerSuggestionListView.composerViewOwner.mainSuggestions" t-as="suggestion" t-key="suggestion.localId">
|
||||
<ComposerSuggestion record="suggestion"/>
|
||||
<div class="o_ComposerSuggestionListView position-absolute w-100" t-att-class="{ 'o-lowPosition bottom-0': composerSuggestionListView.composerViewOwner.hasMentionSuggestionsBelowPosition }" t-attf-class="{{ className }}" t-ref="root">
|
||||
<div class="o_ComposerSuggestionListView_drop w-100" t-att-class="{ 'dropdown': composerSuggestionListView.composerViewOwner.hasMentionSuggestionsBelowPosition, 'dropup': !composerSuggestionListView.composerViewOwner.hasMentionSuggestionsBelowPosition }">
|
||||
<div class="o_ComposerSuggestionListView_list dropdown-menu show w-100 overflow-auto" t-att-class="{ 'bottom-100': !composerSuggestionListView.composerViewOwner.hasMentionSuggestionsBelowPosition }">
|
||||
<t t-foreach="composerSuggestionListView.composerViewOwner.mainSuggestionViews" t-as="composerSuggestionView" t-key="composerSuggestionView.localId">
|
||||
<ComposerSuggestionView record="composerSuggestionView"/>
|
||||
</t>
|
||||
<t t-if="composerSuggestionListView.composerViewOwner.mainSuggestions.length > 0 and composerSuggestionListView.composerViewOwner.extraSuggestions.length > 0">
|
||||
<t t-if="composerSuggestionListView.composerViewOwner.mainSuggestionViews.length > 0 and composerSuggestionListView.composerViewOwner.extraSuggestionViews.length > 0">
|
||||
<div role="separator" class="dropdown-divider"/>
|
||||
</t>
|
||||
<t t-foreach="composerSuggestionListView.composerViewOwner.extraSuggestions" t-as="suggestion" t-key="suggestion.localId">
|
||||
<ComposerSuggestion record="suggestion"/>
|
||||
<t t-foreach="composerSuggestionListView.composerViewOwner.extraSuggestionViews" t-as="composerSuggestionView" t-key="composerSuggestionView.localId">
|
||||
<ComposerSuggestionView record="composerSuggestionView"/>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+9
-9
@@ -5,7 +5,7 @@ import { registerMessagingComponent } from '@mail/utils/messaging_component';
|
||||
|
||||
const { Component } = owl;
|
||||
|
||||
export class ComposerSuggestion extends Component {
|
||||
export class ComposerSuggestionView extends Component {
|
||||
|
||||
/**
|
||||
* @override
|
||||
@@ -20,9 +20,9 @@ export class ComposerSuggestion extends Component {
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @returns {ComposerSuggestion}
|
||||
* @returns {ComposerSuggestionView}
|
||||
*/
|
||||
get composerSuggestion() {
|
||||
get composerSuggestionView() {
|
||||
return this.props.record;
|
||||
}
|
||||
|
||||
@@ -36,21 +36,21 @@ export class ComposerSuggestion extends Component {
|
||||
_update() {
|
||||
if (
|
||||
this.root.el &&
|
||||
this.composerSuggestion.composerViewOwner.hasToScrollToActiveSuggestion &&
|
||||
this.composerSuggestion.isActive
|
||||
this.composerSuggestionView.composerViewOwner.hasToScrollToActiveSuggestionView &&
|
||||
this.composerSuggestionView.isActive
|
||||
) {
|
||||
this.root.el.scrollIntoView({
|
||||
block: 'center',
|
||||
});
|
||||
this.composerSuggestion.composerViewOwner.update({ hasToScrollToActiveSuggestion: false });
|
||||
this.composerSuggestionView.composerViewOwner.update({ hasToScrollToActiveSuggestionView: false });
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Object.assign(ComposerSuggestion, {
|
||||
Object.assign(ComposerSuggestionView, {
|
||||
props: { record: Object },
|
||||
template: 'mail.ComposerSuggestion',
|
||||
template: 'mail.ComposerSuggestionView',
|
||||
});
|
||||
|
||||
registerMessagingComponent(ComposerSuggestion);
|
||||
registerMessagingComponent(ComposerSuggestionView);
|
||||
|
||||
+1
-1
@@ -2,6 +2,6 @@
|
||||
// Layout
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
.o_ComposerSuggestion:active {
|
||||
.o_ComposerSuggestionView:active {
|
||||
background-color: $gray-300;
|
||||
}
|
||||
|
||||
+22
-21
@@ -1,30 +1,31 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates xml:space="preserve">
|
||||
|
||||
<t t-name="mail.ComposerSuggestion" owl="1">
|
||||
<t t-if="composerSuggestion">
|
||||
<a class="o_ComposerSuggestion dropdown-item d-flex w-100 py-2 px-4" t-att-class="{ 'active bg-300': composerSuggestion.isActive }" t-attf-class="{{ className }}" href="#" t-att-title="composerSuggestion.title" role="menuitem" t-on-click="composerSuggestion.onClick" t-ref="root">
|
||||
<t t-if="composerSuggestion.suggestable.cannedResponse">
|
||||
<strong class="o_ComposerSuggestion_part1 flex-shrink-0 mw-100 pe-2 text-truncate"><t t-esc="composerSuggestion.suggestable.cannedResponse.source"/></strong>
|
||||
<em class="o_ComposerSuggestion_part2 text-600 text-truncate"><t t-esc="composerSuggestion.suggestable.cannedResponse.substitution"/></em>
|
||||
<t t-name="mail.ComposerSuggestionView" owl="1">
|
||||
<t t-if="composerSuggestionView">
|
||||
<a class="o_ComposerSuggestionView dropdown-item d-flex w-100 py-2 px-4" t-att-class="{ 'active bg-300': composerSuggestionView.isActive }" t-attf-class="{{ className }}" href="#" t-att-title="composerSuggestionView.title" role="menuitem" t-on-click="composerSuggestionView.onClick" t-ref="root">
|
||||
<t t-if="composerSuggestionView.suggestable.cannedResponse">
|
||||
<strong class="o_ComposerSuggestionView_part1 flex-shrink-0 mw-100 pe-2 text-truncate"><t t-esc="composerSuggestionView.suggestable.cannedResponse.source"/></strong>
|
||||
<em class="o_ComposerSuggestionView_part2 text-600 text-truncate"><t t-esc="composerSuggestionView.suggestable.cannedResponse.substitution"/></em>
|
||||
</t>
|
||||
<t t-if="composerSuggestion.suggestable.thread">
|
||||
<strong class="o_ComposerSuggestion_part1 flex-shrink-0 mw-100 pe-2 text-truncate"><t t-esc="composerSuggestion.suggestable.thread.name"/></strong>
|
||||
<t t-if="composerSuggestionView.suggestable.thread">
|
||||
<strong class="o_ComposerSuggestionView_part1 flex-shrink-0 mw-100 pe-2 text-truncate"><t t-esc="composerSuggestionView.suggestable.thread.name"/></strong>
|
||||
</t>
|
||||
<t t-if="composerSuggestion.suggestable.channelCommand">
|
||||
<strong class="o_ComposerSuggestion_part1 flex-shrink-0 mw-100 pe-2 text-truncate"><t t-esc="composerSuggestion.suggestable.channelCommand.name"/></strong>
|
||||
<em class="o_ComposerSuggestion_part2 text-600 text-truncate"><t t-esc="composerSuggestion.suggestable.channelCommand.help"/></em>
|
||||
<t t-if="composerSuggestionView.suggestable.channelCommand">
|
||||
<strong class="o_ComposerSuggestionView_part1 flex-shrink-0 mw-100 pe-2 text-truncate"><t t-esc="composerSuggestionView.suggestable.channelCommand.name"/></strong>
|
||||
<em class="o_ComposerSuggestionView_part2 text-600 text-truncate"><t t-esc="composerSuggestionView.suggestable.channelCommand.help"/></em>
|
||||
</t>
|
||||
<t t-if="composerSuggestion.suggestable.partner">
|
||||
<PersonaImStatusIcon
|
||||
t-if="composerSuggestion.personaImStatusIconView"
|
||||
className="'o_ComposerSuggestion_personaImStatusIcon flex-shrink-0 me-1'"
|
||||
hasBackground="false"
|
||||
record="composerSuggestion.personaImStatusIconView"
|
||||
/>
|
||||
<strong class="o_ComposerSuggestion_part1 flex-shrink-0 mw-100 pe-2 text-truncate"><t t-esc="composerSuggestion.suggestable.partner.nameOrDisplayName"/></strong>
|
||||
<t t-if="composerSuggestion.suggestable.partner.email">
|
||||
<em class="o_ComposerSuggestion_part2 text-600 text-truncate">(<t t-esc="composerSuggestion.suggestable.partner.email"/>)</em>
|
||||
<t t-if="composerSuggestionView.suggestable.partner">
|
||||
<t t-if="composerSuggestionView.personaImStatusIconView">
|
||||
<PersonaImStatusIcon
|
||||
className="'o_ComposerSuggestionView_personaImStatusIcon flex-shrink-0 me-1'"
|
||||
hasBackground="false"
|
||||
record="composerSuggestionView.personaImStatusIconView"
|
||||
/>
|
||||
</t>
|
||||
<strong class="o_ComposerSuggestionView_part1 flex-shrink-0 mw-100 pe-2 text-truncate"><t t-esc="composerSuggestionView.suggestable.partner.nameOrDisplayName"/></strong>
|
||||
<t t-if="composerSuggestionView.suggestable.partner.email">
|
||||
<em class="o_ComposerSuggestionView_part2 text-600 text-truncate">(<t t-esc="composerSuggestionView.suggestable.partner.email"/>)</em>
|
||||
</t>
|
||||
</t>
|
||||
</a>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<t t-if="composerView">
|
||||
<div class="o_ComposerTextInput position-relative bg-white" t-attf-class="{{ className }} {{ composerView.isCompact ? 'border border-end-0' : 'border-0' }}" t-on-paste="composerView.onPasteTextInput" t-ref="root">
|
||||
<t t-if="composerView.composerSuggestionListView">
|
||||
<ComposerSuggestionList record="composerView.composerSuggestionListView"/>
|
||||
<ComposerSuggestionListView record="composerView.composerSuggestionListView"/>
|
||||
</t>
|
||||
<textarea class="o_ComposerTextInput_textarea o_ComposerTextInput_textareaStyle form-control px-3 border-0 shadow-none overflow-auto" t-att-class="{ 'o-composer-is-compact rounded-0 rounded-start-3': composerView.isCompact, 'rounded-3': !composerView.isCompact }" t-esc="composerView.composer.textInputContent" t-att-placeholder="composerView.composer.placeholder" t-on-click="composerView.onClickTextarea" t-on-focusin="composerView.onFocusinTextarea" t-on-focusout="composerView.onFocusoutTextarea" t-on-keydown="composerView.onKeydownTextarea" t-on-keyup="composerView.onKeyupTextarea" t-on-input="composerView.onInputTextarea" t-ref="textarea"/>
|
||||
<!--
|
||||
|
||||
@@ -15,7 +15,7 @@ registerModel({
|
||||
inverse: 'suggestable',
|
||||
readonly: true,
|
||||
}),
|
||||
composerSuggestions: many('ComposerSuggestion', {
|
||||
composerSuggestionViews: many('ComposerSuggestionView', {
|
||||
inverse: 'suggestable',
|
||||
isCausal: true,
|
||||
}),
|
||||
|
||||
@@ -12,7 +12,7 @@ import { sprintf } from '@web/core/utils/strings';
|
||||
* and display suggested partners to mention.
|
||||
*/
|
||||
registerModel({
|
||||
name: 'ComposerSuggestion',
|
||||
name: 'ComposerSuggestionView',
|
||||
identifyingFields: [['composerViewOwnerAsExtraSuggestion', 'composerViewOwnerAsMainSuggestion'], 'suggestable'],
|
||||
recordMethods: {
|
||||
/**
|
||||
@@ -40,10 +40,10 @@ registerModel({
|
||||
* @returns {boolean|FieldCommand}
|
||||
*/
|
||||
_computeIsActive() {
|
||||
if (this.composerViewOwnerAsMainSuggestion && this === this.composerViewOwnerAsMainSuggestion.activeSuggestion) {
|
||||
if (this.composerViewOwnerAsMainSuggestion && this === this.composerViewOwnerAsMainSuggestion.activeSuggestionView) {
|
||||
return true;
|
||||
}
|
||||
if (this.composerViewOwnerAsExtraSuggestion && this === this.composerViewOwnerAsExtraSuggestion.activeSuggestion) {
|
||||
if (this.composerViewOwnerAsExtraSuggestion && this === this.composerViewOwnerAsExtraSuggestion.activeSuggestionView) {
|
||||
return true;
|
||||
}
|
||||
return clear();
|
||||
@@ -102,11 +102,11 @@ registerModel({
|
||||
required: true,
|
||||
}),
|
||||
composerViewOwnerAsExtraSuggestion: one('ComposerView', {
|
||||
inverse: 'extraSuggestions',
|
||||
inverse: 'extraSuggestionViews',
|
||||
readonly: true,
|
||||
}),
|
||||
composerViewOwnerAsMainSuggestion: one('ComposerView', {
|
||||
inverse: 'mainSuggestions',
|
||||
inverse: 'mainSuggestionViews',
|
||||
readonly: true,
|
||||
}),
|
||||
isActive: attr({
|
||||
@@ -126,7 +126,7 @@ registerModel({
|
||||
readonly: true,
|
||||
}),
|
||||
suggestable: one('ComposerSuggestable', {
|
||||
inverse: 'composerSuggestions',
|
||||
inverse: 'composerSuggestionViews',
|
||||
readonly: true,
|
||||
required: true,
|
||||
}),
|
||||
|
||||
@@ -134,7 +134,7 @@ registerModel({
|
||||
this.composer.textInputContent.length
|
||||
);
|
||||
}
|
||||
const recordReplacement = this.activeSuggestion.mentionText;
|
||||
const recordReplacement = this.activeSuggestionView.mentionText;
|
||||
const updateData = {
|
||||
textInputContent: textLeft + recordReplacement + ' ' + textRight,
|
||||
textInputCursorEnd: textLeft.length + recordReplacement.length + 1,
|
||||
@@ -143,11 +143,11 @@ registerModel({
|
||||
// Specific cases for channel and partner mentions: the message with
|
||||
// the mention will appear in the target channel, or be notified to
|
||||
// the target partner.
|
||||
if (this.activeSuggestion.suggestable.thread) {
|
||||
Object.assign(updateData, { mentionedChannels: link(this.activeSuggestion.suggestable.thread) });
|
||||
if (this.activeSuggestionView.suggestable.thread) {
|
||||
Object.assign(updateData, { mentionedChannels: link(this.activeSuggestionView.suggestable.thread) });
|
||||
}
|
||||
if (this.activeSuggestion.suggestable.partner) {
|
||||
Object.assign(updateData, { mentionedPartners: link(this.activeSuggestion.suggestable.partner) });
|
||||
if (this.activeSuggestionView.suggestable.partner) {
|
||||
Object.assign(updateData, { mentionedPartners: link(this.activeSuggestionView.suggestable.partner) });
|
||||
}
|
||||
this.composer.update(updateData);
|
||||
for (const composerView of this.composer.composerViews) {
|
||||
@@ -274,10 +274,10 @@ registerModel({
|
||||
});
|
||||
},
|
||||
/**
|
||||
* @param {ComposerSuggestion} suggestion
|
||||
* @param {ComposerSuggestionView} suggestionView
|
||||
*/
|
||||
onClickSuggestion(suggestion) {
|
||||
this.update({ activeSuggestion: replace(suggestion) });
|
||||
onClickSuggestion(suggestionView) {
|
||||
this.update({ activeSuggestionView: replace(suggestionView) });
|
||||
this.insertSuggestion();
|
||||
this.closeSuggestions();
|
||||
this.update({ doFocus: true });
|
||||
@@ -448,8 +448,8 @@ registerModel({
|
||||
break;
|
||||
}
|
||||
if (this.hasSuggestions) {
|
||||
this.setPreviousSuggestionActive();
|
||||
this.update({ hasToScrollToActiveSuggestion: true });
|
||||
this.setPreviousSuggestionViewActive();
|
||||
this.update({ hasToScrollToActiveSuggestionView: true });
|
||||
}
|
||||
break;
|
||||
case 'ArrowDown':
|
||||
@@ -459,30 +459,30 @@ registerModel({
|
||||
break;
|
||||
}
|
||||
if (this.hasSuggestions) {
|
||||
this.setNextSuggestionActive();
|
||||
this.update({ hasToScrollToActiveSuggestion: true });
|
||||
this.setNextSuggestionViewActive();
|
||||
this.update({ hasToScrollToActiveSuggestionView: true });
|
||||
}
|
||||
break;
|
||||
case 'Home':
|
||||
if (this.hasSuggestions) {
|
||||
this.setFirstSuggestionActive();
|
||||
this.update({ hasToScrollToActiveSuggestion: true });
|
||||
this.setFirstSuggestionViewActive();
|
||||
this.update({ hasToScrollToActiveSuggestionView: true });
|
||||
}
|
||||
break;
|
||||
case 'End':
|
||||
if (this.hasSuggestions) {
|
||||
this.setLastSuggestionActive();
|
||||
this.update({ hasToScrollToActiveSuggestion: true });
|
||||
this.setLastSuggestionViewActive();
|
||||
this.update({ hasToScrollToActiveSuggestionView: true });
|
||||
}
|
||||
break;
|
||||
case 'Tab':
|
||||
if (this.hasSuggestions) {
|
||||
if (ev.shiftKey) {
|
||||
this.setPreviousSuggestionActive();
|
||||
this.update({ hasToScrollToActiveSuggestion: true });
|
||||
this.setPreviousSuggestionViewActive();
|
||||
this.update({ hasToScrollToActiveSuggestionView: true });
|
||||
} else {
|
||||
this.setNextSuggestionActive();
|
||||
this.update({ hasToScrollToActiveSuggestion: true });
|
||||
this.setNextSuggestionViewActive();
|
||||
this.update({ hasToScrollToActiveSuggestionView: true });
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -682,53 +682,53 @@ registerModel({
|
||||
* Sets the first suggestion as active. Main and extra records are
|
||||
* considered together.
|
||||
*/
|
||||
setFirstSuggestionActive() {
|
||||
const suggestions = this.mainSuggestions.concat(this.extraSuggestions);
|
||||
const firstSuggestion = suggestions[0];
|
||||
this.update({ activeSuggestion: replace(firstSuggestion) });
|
||||
setFirstSuggestionViewActive() {
|
||||
const suggestionViews = this.mainSuggestionViews.concat(this.extraSuggestionViews);
|
||||
const firstSuggestionView = suggestionViews[0];
|
||||
this.update({ activeSuggestionView: replace(firstSuggestionView) });
|
||||
},
|
||||
/**
|
||||
* Sets the last suggestion as active. Main and extra records are
|
||||
* considered together.
|
||||
*/
|
||||
setLastSuggestionActive() {
|
||||
const suggestions = this.mainSuggestions.concat(this.extraSuggestions);
|
||||
const { length, [length - 1]: lastSuggestion } = suggestions;
|
||||
this.update({ activeSuggestion: replace(lastSuggestion) });
|
||||
setLastSuggestionViewActive() {
|
||||
const suggestionViews = this.mainSuggestionViews.concat(this.extraSuggestionViews);
|
||||
const { length, [length - 1]: lastSuggestionView } = suggestionViews;
|
||||
this.update({ activeSuggestionView: replace(lastSuggestionView) });
|
||||
},
|
||||
/**
|
||||
* Sets the next suggestion as active. Main and extra records are
|
||||
* considered together.
|
||||
*/
|
||||
setNextSuggestionActive() {
|
||||
const suggestions = this.mainSuggestions.concat(this.extraSuggestions);
|
||||
const activeElementIndex = suggestions.findIndex(
|
||||
suggestion => suggestion === this.activeSuggestion
|
||||
setNextSuggestionViewActive() {
|
||||
const suggestionViews = this.mainSuggestionViews.concat(this.extraSuggestionViews);
|
||||
const activeElementIndex = suggestionViews.findIndex(
|
||||
suggestion => suggestion === this.activeSuggestionView
|
||||
);
|
||||
if (activeElementIndex === suggestions.length - 1) {
|
||||
if (activeElementIndex === suggestionViews.length - 1) {
|
||||
// loop when reaching the end of the list
|
||||
this.setFirstSuggestionActive();
|
||||
this.setFirstSuggestionViewActive();
|
||||
return;
|
||||
}
|
||||
const nextSuggestion = suggestions[activeElementIndex + 1];
|
||||
this.update({ activeSuggestion: replace(nextSuggestion) });
|
||||
const nextSuggestionView = suggestionViews[activeElementIndex + 1];
|
||||
this.update({ activeSuggestionView: replace(nextSuggestionView) });
|
||||
},
|
||||
/**
|
||||
* Sets the previous suggestion as active. Main and extra records are
|
||||
* considered together.
|
||||
*/
|
||||
setPreviousSuggestionActive() {
|
||||
const suggestions = this.mainSuggestions.concat(this.extraSuggestions);
|
||||
const activeElementIndex = suggestions.findIndex(
|
||||
suggestion => suggestion === this.activeSuggestion
|
||||
setPreviousSuggestionViewActive() {
|
||||
const suggestionViews = this.mainSuggestionViews.concat(this.extraSuggestionViews);
|
||||
const activeElementIndex = suggestionViews.findIndex(
|
||||
suggestion => suggestion === this.activeSuggestionView
|
||||
);
|
||||
if (activeElementIndex === 0) {
|
||||
// loop when reaching the start of the list
|
||||
this.setLastSuggestionActive();
|
||||
this.setLastSuggestionViewActive();
|
||||
return;
|
||||
}
|
||||
const previousSuggestion = suggestions[activeElementIndex - 1];
|
||||
this.update({ activeSuggestion: replace(previousSuggestion) });
|
||||
const previousSuggestionView = suggestionViews[activeElementIndex - 1];
|
||||
this.update({ activeSuggestionView: replace(previousSuggestionView) });
|
||||
},
|
||||
/**
|
||||
* Updates the textarea height of text input.
|
||||
@@ -775,22 +775,22 @@ registerModel({
|
||||
* @private
|
||||
* @returns {FieldCommand}
|
||||
*/
|
||||
_computeActiveSuggestion() {
|
||||
_computeActiveSuggestionView() {
|
||||
if (
|
||||
this.mainSuggestions.length === 0 &&
|
||||
this.extraSuggestions.length === 0
|
||||
this.mainSuggestionViews.length === 0 &&
|
||||
this.extraSuggestionViews.length === 0
|
||||
) {
|
||||
return clear();
|
||||
}
|
||||
if (
|
||||
this.mainSuggestions.includes(this.activeSuggestion) ||
|
||||
this.extraSuggestions.includes(this.activeSuggestion)
|
||||
this.mainSuggestionViews.includes(this.activeSuggestionView) ||
|
||||
this.extraSuggestionViews.includes(this.activeSuggestionView)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
const suggestions = this.mainSuggestions.concat(this.extraSuggestions);
|
||||
const firstSuggestion = suggestions[0];
|
||||
return replace(firstSuggestion);
|
||||
const suggestionViews = this.mainSuggestionViews.concat(this.extraSuggestionViews);
|
||||
const firstSuggestionView = suggestionViews[0];
|
||||
return replace(firstSuggestionView);
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
@@ -884,11 +884,11 @@ registerModel({
|
||||
* @private
|
||||
* @returns {FieldCommand}
|
||||
*/
|
||||
_computeExtraSuggestions() {
|
||||
_computeExtraSuggestionViews() {
|
||||
if (this.suggestionDelimiterPosition === undefined) {
|
||||
return clear();
|
||||
}
|
||||
return unlink(this.mainSuggestions);
|
||||
return unlink(this.mainSuggestionViews);
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
@@ -960,7 +960,7 @@ registerModel({
|
||||
* @return {boolean}
|
||||
*/
|
||||
_computeHasSuggestions() {
|
||||
return this.mainSuggestions.length > 0 || this.extraSuggestions.length > 0;
|
||||
return this.mainSuggestionViews.length > 0 || this.extraSuggestionViews.length > 0;
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
@@ -1024,7 +1024,7 @@ registerModel({
|
||||
* @private
|
||||
* @returns {Record[]}
|
||||
*/
|
||||
_computeMainSuggestions() {
|
||||
_computeMainSuggestionViews() {
|
||||
if (this.suggestionDelimiterPosition === undefined) {
|
||||
return clear();
|
||||
}
|
||||
@@ -1389,15 +1389,15 @@ registerModel({
|
||||
mainSuggestedRecords.length = Math.min(mainSuggestedRecords.length, limit);
|
||||
extraSuggestedRecords.length = Math.min(extraSuggestedRecords.length, limit - mainSuggestedRecords.length);
|
||||
this.update({
|
||||
extraSuggestions: insertAndReplace(
|
||||
extraSuggestionViews: insertAndReplace(
|
||||
extraSuggestedRecords.map(record => {
|
||||
return {
|
||||
suggestable: replace(record.suggestable),
|
||||
};
|
||||
}),
|
||||
),
|
||||
hasToScrollToActiveSuggestion: true,
|
||||
mainSuggestions: insertAndReplace(
|
||||
hasToScrollToActiveSuggestionView: true,
|
||||
mainSuggestionViews: insertAndReplace(
|
||||
mainSuggestedRecords.map(record => {
|
||||
return {
|
||||
suggestable: replace(record.suggestable),
|
||||
@@ -1423,8 +1423,8 @@ registerModel({
|
||||
* is highlighted in the UI and it will be selected when the
|
||||
* suggestion is confirmed by the user.
|
||||
*/
|
||||
activeSuggestion: one('ComposerSuggestion', {
|
||||
compute: '_computeActiveSuggestion',
|
||||
activeSuggestionView: one('ComposerSuggestionView', {
|
||||
compute: '_computeActiveSuggestionView',
|
||||
}),
|
||||
/**
|
||||
* Determines the attachment list that will be used to display the attachments.
|
||||
@@ -1493,8 +1493,8 @@ registerModel({
|
||||
/**
|
||||
* Determines the extra suggestions.
|
||||
*/
|
||||
extraSuggestions: many('ComposerSuggestion', {
|
||||
compute: '_computeExtraSuggestions',
|
||||
extraSuggestionViews: many('ComposerSuggestionView', {
|
||||
compute: '_computeExtraSuggestionViews',
|
||||
inverse: 'composerViewOwnerAsExtraSuggestion',
|
||||
isCausal: true,
|
||||
}),
|
||||
@@ -1574,7 +1574,7 @@ registerModel({
|
||||
* Determines whether the currently active suggestion should be scrolled
|
||||
* into view.
|
||||
*/
|
||||
hasToScrollToActiveSuggestion: attr({
|
||||
hasToScrollToActiveSuggestionView: attr({
|
||||
default: false,
|
||||
}),
|
||||
isCompact: attr({
|
||||
@@ -1598,8 +1598,8 @@ registerModel({
|
||||
/**
|
||||
* Determines the main suggestions.
|
||||
*/
|
||||
mainSuggestions: many('ComposerSuggestion', {
|
||||
compute: '_computeMainSuggestions',
|
||||
mainSuggestionViews: many('ComposerSuggestionView', {
|
||||
compute: '_computeMainSuggestionViews',
|
||||
inverse: 'composerViewOwnerAsMainSuggestion',
|
||||
isCausal: true,
|
||||
}),
|
||||
|
||||
@@ -54,7 +54,7 @@ registerModel({
|
||||
inverse: 'personaImStatusIconView',
|
||||
readonly: true,
|
||||
}),
|
||||
composerSuggestionViewOwner: one('ComposerSuggestion', {
|
||||
composerSuggestionViewOwner: one('ComposerSuggestionView', {
|
||||
inverse: 'personaImStatusIconView',
|
||||
readonly: true,
|
||||
}),
|
||||
|
||||
@@ -387,14 +387,14 @@ function getCreateComposerComponent({ env, target }) {
|
||||
};
|
||||
}
|
||||
|
||||
function getCreateComposerSuggestionComponent({ env, target }) {
|
||||
return async function createComposerSuggestionComponent(composer, props) {
|
||||
function getCreateComposerSuggestionViewComponent({ env, target }) {
|
||||
return async function createComposerSuggestionViewComponent(composer, props) {
|
||||
const composerView = env.services.messaging.modelManager.messaging.models['ComposerView'].create({
|
||||
qunitTest: insertAndReplace({
|
||||
composer: replace(composer),
|
||||
}),
|
||||
});
|
||||
await createRootMessagingComponent(env, "ComposerSuggestion", {
|
||||
await createRootMessagingComponent(env, "ComposerSuggestionView", {
|
||||
props: { ...props, composerView: composerView },
|
||||
target,
|
||||
});
|
||||
@@ -573,7 +573,7 @@ async function start(param0 = {}) {
|
||||
afterNextRender,
|
||||
click: getClick({ afterNextRender }),
|
||||
createComposerComponent: getCreateComposerComponent({ env: webClient.env, target }),
|
||||
createComposerSuggestionComponent: getCreateComposerSuggestionComponent({ env: webClient.env, target }),
|
||||
createComposerSuggestionViewComponent: getCreateComposerSuggestionViewComponent({ env: webClient.env, target }),
|
||||
createNotificationListComponent: getCreateNotificationListComponent({ env: webClient.env, target }),
|
||||
createRootMessagingComponent: (componentName, props) => createRootMessagingComponent(webClient.env, componentName, { props, target }),
|
||||
env: webClient.env,
|
||||
|
||||
@@ -757,7 +757,7 @@ QUnit.test('chat window: close on ESCAPE', async function (assert) {
|
||||
|
||||
await insertText('.o_ComposerTextInput_textarea', "@");
|
||||
assert.hasClass(
|
||||
document.querySelector('.o_ComposerSuggestionList_list'),
|
||||
document.querySelector('.o_ComposerSuggestionListView_list'),
|
||||
'show',
|
||||
"should display mention suggestions on typing '@'"
|
||||
);
|
||||
@@ -768,7 +768,7 @@ QUnit.test('chat window: close on ESCAPE', async function (assert) {
|
||||
});
|
||||
assert.containsNone(
|
||||
document.body,
|
||||
'.o_ComposerSuggestionList_list',
|
||||
'.o_ComposerSuggestionListView_list',
|
||||
"mention suggestion should be closed after pressing escape on mention suggestion"
|
||||
);
|
||||
assert.containsOnce(
|
||||
|
||||
+6
-6
@@ -26,7 +26,7 @@ QUnit.test('canned response suggestion displayed', async function (assert) {
|
||||
await insertText('.o_ComposerTextInput_textarea', ":hello");
|
||||
assert.containsOnce(
|
||||
document.body,
|
||||
`.o_ComposerSuggestion`,
|
||||
`.o_ComposerSuggestionView`,
|
||||
"Canned response suggestion should be present"
|
||||
);
|
||||
});
|
||||
@@ -51,21 +51,21 @@ QUnit.test('canned response suggestion correct data', async function (assert) {
|
||||
await insertText('.o_ComposerTextInput_textarea', ":hello");
|
||||
assert.containsOnce(
|
||||
document.body,
|
||||
'.o_ComposerSuggestion_part1',
|
||||
'.o_ComposerSuggestionView_part1',
|
||||
"Canned response source should be present"
|
||||
);
|
||||
assert.strictEqual(
|
||||
document.querySelector(`.o_ComposerSuggestion_part1`).textContent,
|
||||
document.querySelector(`.o_ComposerSuggestionView_part1`).textContent,
|
||||
"hello",
|
||||
"Canned response source should be displayed"
|
||||
);
|
||||
assert.containsOnce(
|
||||
document.body,
|
||||
'.o_ComposerSuggestion_part2',
|
||||
'.o_ComposerSuggestionView_part2',
|
||||
"Canned response substitution should be present"
|
||||
);
|
||||
assert.strictEqual(
|
||||
document.querySelector(`.o_ComposerSuggestion_part2`).textContent,
|
||||
document.querySelector(`.o_ComposerSuggestionView_part2`).textContent,
|
||||
"Hello, how are you?",
|
||||
"Canned response substitution should be displayed"
|
||||
);
|
||||
@@ -90,7 +90,7 @@ QUnit.test('canned response suggestion active', async function (assert) {
|
||||
await openDiscuss();
|
||||
await insertText('.o_ComposerTextInput_textarea', ":hello");
|
||||
assert.hasClass(
|
||||
document.querySelector('.o_ComposerSuggestion'),
|
||||
document.querySelector('.o_ComposerSuggestionView'),
|
||||
'active',
|
||||
"should be active initially"
|
||||
);
|
||||
|
||||
+4
-4
@@ -22,7 +22,7 @@ QUnit.test('channel mention suggestion displayed', async function (assert) {
|
||||
await insertText('.o_ComposerTextInput_textarea', "#my-channel");
|
||||
assert.containsOnce(
|
||||
document.body,
|
||||
`.o_ComposerSuggestion`,
|
||||
`.o_ComposerSuggestionView`,
|
||||
"Channel mention suggestion should be present"
|
||||
);
|
||||
});
|
||||
@@ -43,11 +43,11 @@ QUnit.test('channel mention suggestion correct data', async function (assert) {
|
||||
await insertText('.o_ComposerTextInput_textarea', "#General");
|
||||
assert.containsOnce(
|
||||
document.body,
|
||||
'.o_ComposerSuggestion_part1',
|
||||
'.o_ComposerSuggestionView_part1',
|
||||
"Channel name should be present"
|
||||
);
|
||||
assert.strictEqual(
|
||||
document.querySelector(`.o_ComposerSuggestion_part1`).textContent,
|
||||
document.querySelector(`.o_ComposerSuggestionView_part1`).textContent,
|
||||
"General",
|
||||
"Channel name should be displayed"
|
||||
);
|
||||
@@ -68,7 +68,7 @@ QUnit.test('channel mention suggestion active', async function (assert) {
|
||||
await openDiscuss();
|
||||
await insertText('.o_ComposerTextInput_textarea', "#my-channel");
|
||||
assert.hasClass(
|
||||
document.querySelector('.o_ComposerSuggestion'),
|
||||
document.querySelector('.o_ComposerSuggestionView'),
|
||||
'active',
|
||||
"should be active initially"
|
||||
);
|
||||
|
||||
+7
-7
@@ -22,7 +22,7 @@ QUnit.test('command suggestion displayed', async function (assert) {
|
||||
await insertText('.o_ComposerTextInput_textarea', "/who");
|
||||
assert.containsOnce(
|
||||
document.body,
|
||||
'.o_ComposerSuggestion',
|
||||
'.o_ComposerSuggestionView',
|
||||
"Command suggestion should be present",
|
||||
);
|
||||
});
|
||||
@@ -43,21 +43,21 @@ QUnit.test('command suggestion correct data', async function (assert) {
|
||||
await insertText('.o_ComposerTextInput_textarea', "/who");
|
||||
assert.containsOnce(
|
||||
document.body,
|
||||
'.o_ComposerSuggestion_part1',
|
||||
'.o_ComposerSuggestionView_part1',
|
||||
"Command name should be present"
|
||||
);
|
||||
assert.strictEqual(
|
||||
document.querySelector(`.o_ComposerSuggestion_part1`).textContent,
|
||||
document.querySelector(`.o_ComposerSuggestionView_part1`).textContent,
|
||||
"who",
|
||||
"Command name should be displayed"
|
||||
);
|
||||
assert.containsOnce(
|
||||
document.querySelector('.o_ComposerSuggestion'),
|
||||
'.o_ComposerSuggestion_part2',
|
||||
document.querySelector('.o_ComposerSuggestionView'),
|
||||
'.o_ComposerSuggestionView_part2',
|
||||
"Command help should be present"
|
||||
);
|
||||
assert.strictEqual(
|
||||
document.querySelector(`.o_ComposerSuggestion_part2`).textContent,
|
||||
document.querySelector(`.o_ComposerSuggestionView_part2`).textContent,
|
||||
"List users in the current channel",
|
||||
"Command help should be displayed"
|
||||
);
|
||||
@@ -78,7 +78,7 @@ QUnit.test('command suggestion active', async function (assert) {
|
||||
await openDiscuss();
|
||||
await insertText('.o_ComposerTextInput_textarea', "/who");
|
||||
assert.hasClass(
|
||||
document.querySelector('.o_ComposerSuggestion'),
|
||||
document.querySelector('.o_ComposerSuggestionView'),
|
||||
'active',
|
||||
"1st suggestion should be active initially"
|
||||
);
|
||||
|
||||
+7
-7
@@ -27,7 +27,7 @@ QUnit.test('partner mention suggestion displayed', async function (assert) {
|
||||
await insertText('.o_ComposerTextInput_textarea', "@demo");
|
||||
assert.containsOnce(
|
||||
document.body,
|
||||
`.o_ComposerSuggestion`,
|
||||
`.o_ComposerSuggestionView`,
|
||||
"Partner mention suggestion should be present"
|
||||
);
|
||||
});
|
||||
@@ -52,27 +52,27 @@ QUnit.test('partner mention suggestion correct data', async function (assert) {
|
||||
await openDiscuss();
|
||||
await insertText('.o_ComposerTextInput_textarea', "@demo");
|
||||
assert.containsOnce(
|
||||
document.querySelector('.o_ComposerSuggestion'),
|
||||
document.querySelector('.o_ComposerSuggestionView'),
|
||||
'.o_PersonaImStatusIcon',
|
||||
"Partner's im_status should be displayed"
|
||||
);
|
||||
assert.containsOnce(
|
||||
document.body,
|
||||
'.o_ComposerSuggestion_part1',
|
||||
'.o_ComposerSuggestionView_part1',
|
||||
"Partner's name should be present"
|
||||
);
|
||||
assert.strictEqual(
|
||||
document.querySelector('.o_ComposerSuggestion_part1').textContent,
|
||||
document.querySelector('.o_ComposerSuggestionView_part1').textContent,
|
||||
"Demo User",
|
||||
"Partner's name should be displayed"
|
||||
);
|
||||
assert.containsOnce(
|
||||
document.body,
|
||||
'.o_ComposerSuggestion_part2',
|
||||
'.o_ComposerSuggestionView_part2',
|
||||
"Partner's email should be present"
|
||||
);
|
||||
assert.strictEqual(
|
||||
document.querySelector('.o_ComposerSuggestion_part2').textContent,
|
||||
document.querySelector('.o_ComposerSuggestionView_part2').textContent,
|
||||
"(demo_user@odoo.com)",
|
||||
"Partner's email should be displayed"
|
||||
);
|
||||
@@ -98,7 +98,7 @@ QUnit.test('partner mention suggestion active', async function (assert) {
|
||||
await openDiscuss();
|
||||
await insertText('.o_ComposerTextInput_textarea', "@demo");
|
||||
assert.hasClass(
|
||||
document.querySelector('.o_ComposerSuggestion'),
|
||||
document.querySelector('.o_ComposerSuggestionView'),
|
||||
'active',
|
||||
"should be active initially"
|
||||
);
|
||||
|
||||
@@ -261,12 +261,12 @@ QUnit.test('display canned response suggestions on typing ":"', async function (
|
||||
|
||||
assert.containsNone(
|
||||
document.body,
|
||||
'.o_ComposerSuggestionList_list',
|
||||
'.o_ComposerSuggestionListView_list',
|
||||
"Canned responses suggestions list should not be present"
|
||||
);
|
||||
await insertText('.o_ComposerTextInput_textarea', ':');
|
||||
assert.hasClass(
|
||||
document.querySelector('.o_ComposerSuggestionList_list'),
|
||||
document.querySelector('.o_ComposerSuggestionListView_list'),
|
||||
'show',
|
||||
"should display canned response suggestions on typing ':'"
|
||||
);
|
||||
@@ -287,7 +287,7 @@ QUnit.test('use a canned response', async function (assert) {
|
||||
|
||||
assert.containsNone(
|
||||
document.body,
|
||||
'.o_ComposerSuggestionList_list',
|
||||
'.o_ComposerSuggestionListView_list',
|
||||
"canned response suggestions list should not be present"
|
||||
);
|
||||
assert.strictEqual(
|
||||
@@ -298,10 +298,10 @@ QUnit.test('use a canned response', async function (assert) {
|
||||
await insertText('.o_ComposerTextInput_textarea', ':');
|
||||
assert.containsOnce(
|
||||
document.body,
|
||||
'.o_ComposerSuggestion',
|
||||
'.o_ComposerSuggestionView',
|
||||
"should have a canned response suggestion"
|
||||
);
|
||||
await click('.o_ComposerSuggestion');
|
||||
await click('.o_ComposerSuggestionView');
|
||||
assert.strictEqual(
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`).value.replace(/\s/, " "),
|
||||
"Hello! How are you? ",
|
||||
@@ -324,7 +324,7 @@ QUnit.test('use a canned response some text', async function (assert) {
|
||||
|
||||
assert.containsNone(
|
||||
document.body,
|
||||
'.o_ComposerSuggestion',
|
||||
'.o_ComposerSuggestionView',
|
||||
"canned response suggestions list should not be present"
|
||||
);
|
||||
assert.strictEqual(
|
||||
@@ -341,10 +341,10 @@ QUnit.test('use a canned response some text', async function (assert) {
|
||||
await insertText('.o_ComposerTextInput_textarea', ':');
|
||||
assert.containsOnce(
|
||||
document.body,
|
||||
'.o_ComposerSuggestion',
|
||||
'.o_ComposerSuggestionView',
|
||||
"should have a canned response suggestion"
|
||||
);
|
||||
await click('.o_ComposerSuggestion');
|
||||
await click('.o_ComposerSuggestionView');
|
||||
assert.strictEqual(
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`).value.replace(/\s/, " "),
|
||||
"bluhbluh Hello! How are you? ",
|
||||
@@ -367,7 +367,7 @@ QUnit.test('add an emoji after a canned response', async function (assert) {
|
||||
|
||||
assert.containsNone(
|
||||
document.body,
|
||||
'.o_ComposerSuggestion',
|
||||
'.o_ComposerSuggestionView',
|
||||
"canned response suggestions list should not be present"
|
||||
);
|
||||
assert.strictEqual(
|
||||
@@ -378,10 +378,10 @@ QUnit.test('add an emoji after a canned response', async function (assert) {
|
||||
await insertText('.o_ComposerTextInput_textarea', ':');
|
||||
assert.containsOnce(
|
||||
document.body,
|
||||
'.o_ComposerSuggestion',
|
||||
'.o_ComposerSuggestionView',
|
||||
"should have a canned response suggestion"
|
||||
);
|
||||
await click('.o_ComposerSuggestion');
|
||||
await click('.o_ComposerSuggestionView');
|
||||
assert.strictEqual(
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`).value.replace(/\s/, " "),
|
||||
"Hello! How are you? ",
|
||||
@@ -412,12 +412,12 @@ QUnit.test('display channel mention suggestions on typing "#"', async function (
|
||||
|
||||
assert.containsNone(
|
||||
document.body,
|
||||
'.o_ComposerSuggestionList_list',
|
||||
'.o_ComposerSuggestionListView_list',
|
||||
"channel mention suggestions list should not be present"
|
||||
);
|
||||
await insertText('.o_ComposerTextInput_textarea', "#");
|
||||
assert.hasClass(
|
||||
document.querySelector('.o_ComposerSuggestionList_list'),
|
||||
document.querySelector('.o_ComposerSuggestionListView_list'),
|
||||
'show',
|
||||
"should display channel mention suggestions on typing '#'"
|
||||
);
|
||||
@@ -437,7 +437,7 @@ QUnit.test('mention a channel', async function (assert) {
|
||||
|
||||
assert.containsNone(
|
||||
document.body,
|
||||
'.o_ComposerSuggestionList_list',
|
||||
'.o_ComposerSuggestionListView_list',
|
||||
"channel mention suggestions list should not be present"
|
||||
);
|
||||
assert.strictEqual(
|
||||
@@ -448,10 +448,10 @@ QUnit.test('mention a channel', async function (assert) {
|
||||
await insertText('.o_ComposerTextInput_textarea', "#");
|
||||
assert.containsOnce(
|
||||
document.body,
|
||||
'.o_ComposerSuggestion',
|
||||
'.o_ComposerSuggestionView',
|
||||
"should have a channel mention suggestion"
|
||||
);
|
||||
await click('.o_ComposerSuggestion');
|
||||
await click('.o_ComposerSuggestionView');
|
||||
assert.strictEqual(
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`).value.replace(/\s/, " "),
|
||||
"#General ",
|
||||
@@ -473,7 +473,7 @@ QUnit.test('mention a channel after some text', async function (assert) {
|
||||
|
||||
assert.containsNone(
|
||||
document.body,
|
||||
'.o_ComposerSuggestion',
|
||||
'.o_ComposerSuggestionView',
|
||||
"channel mention suggestions list should not be present"
|
||||
);
|
||||
assert.strictEqual(
|
||||
@@ -490,10 +490,10 @@ QUnit.test('mention a channel after some text', async function (assert) {
|
||||
await insertText('.o_ComposerTextInput_textarea', "#");
|
||||
assert.containsOnce(
|
||||
document.body,
|
||||
'.o_ComposerSuggestion',
|
||||
'.o_ComposerSuggestionView',
|
||||
"should have a channel mention suggestion"
|
||||
);
|
||||
await click('.o_ComposerSuggestion');
|
||||
await click('.o_ComposerSuggestionView');
|
||||
assert.strictEqual(
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`).value.replace(/\s/, " "),
|
||||
"bluhbluh #General ",
|
||||
@@ -515,7 +515,7 @@ QUnit.test('add an emoji after a channel mention', async function (assert) {
|
||||
|
||||
assert.containsNone(
|
||||
document.body,
|
||||
'.o_ComposerSuggestion',
|
||||
'.o_ComposerSuggestionView',
|
||||
"mention suggestions list should not be present"
|
||||
);
|
||||
assert.strictEqual(
|
||||
@@ -526,10 +526,10 @@ QUnit.test('add an emoji after a channel mention', async function (assert) {
|
||||
await insertText('.o_ComposerTextInput_textarea', "#");
|
||||
assert.containsOnce(
|
||||
document.body,
|
||||
'.o_ComposerSuggestion',
|
||||
'.o_ComposerSuggestionView',
|
||||
"should have a channel mention suggestion"
|
||||
);
|
||||
await click('.o_ComposerSuggestion');
|
||||
await click('.o_ComposerSuggestionView');
|
||||
assert.strictEqual(
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`).value.replace(/\s/, " "),
|
||||
"#General ",
|
||||
@@ -560,12 +560,12 @@ QUnit.test('display command suggestions on typing "/"', async function (assert)
|
||||
|
||||
assert.containsNone(
|
||||
document.body,
|
||||
'.o_ComposerSuggestionList_list',
|
||||
'.o_ComposerSuggestionListView_list',
|
||||
"command suggestions list should not be present"
|
||||
);
|
||||
await insertText('.o_ComposerTextInput_textarea', "/");
|
||||
assert.hasClass(
|
||||
document.querySelector('.o_ComposerSuggestionList_list'),
|
||||
document.querySelector('.o_ComposerSuggestionListView_list'),
|
||||
'show',
|
||||
"should display command suggestions on typing '/'"
|
||||
);
|
||||
@@ -614,7 +614,7 @@ QUnit.test('do not send typing notification on typing after selecting suggestion
|
||||
await openDiscuss();
|
||||
|
||||
await insertText('.o_ComposerTextInput_textarea', "/");
|
||||
await click('.o_ComposerSuggestion');
|
||||
await click('.o_ComposerSuggestionView');
|
||||
await insertText('.o_ComposerTextInput_textarea', " is user?");
|
||||
assert.verifySteps([], "No rpc done");
|
||||
});
|
||||
@@ -633,7 +633,7 @@ QUnit.test('use a command for a specific channel type', async function (assert)
|
||||
|
||||
assert.containsNone(
|
||||
document.body,
|
||||
'.o_ComposerSuggestionList_list',
|
||||
'.o_ComposerSuggestionListView_list',
|
||||
"command suggestions list should not be present"
|
||||
);
|
||||
assert.strictEqual(
|
||||
@@ -642,7 +642,7 @@ QUnit.test('use a command for a specific channel type', async function (assert)
|
||||
"text content of composer should be empty initially"
|
||||
);
|
||||
await insertText('.o_ComposerTextInput_textarea', "/");
|
||||
await click('.o_ComposerSuggestion');
|
||||
await click('.o_ComposerSuggestionView');
|
||||
assert.strictEqual(
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`).value.replace(/\s/, " "),
|
||||
"/who ",
|
||||
@@ -663,7 +663,7 @@ QUnit.test('command suggestion should only open if command is the first characte
|
||||
await createComposerComponent(thread.composer);
|
||||
assert.containsNone(
|
||||
document.body,
|
||||
'.o_ComposerSuggestion',
|
||||
'.o_ComposerSuggestionView',
|
||||
"command suggestions list should not be present"
|
||||
);
|
||||
assert.strictEqual(
|
||||
@@ -680,7 +680,7 @@ QUnit.test('command suggestion should only open if command is the first characte
|
||||
await insertText('.o_ComposerTextInput_textarea', "/");
|
||||
assert.containsNone(
|
||||
document.body,
|
||||
'.o_ComposerSuggestion',
|
||||
'.o_ComposerSuggestionView',
|
||||
"should not have a command suggestion"
|
||||
);
|
||||
});
|
||||
@@ -699,7 +699,7 @@ QUnit.test('add an emoji after a command', async function (assert) {
|
||||
|
||||
assert.containsNone(
|
||||
document.body,
|
||||
'.o_ComposerSuggestion',
|
||||
'.o_ComposerSuggestionView',
|
||||
"command suggestions list should not be present"
|
||||
);
|
||||
assert.strictEqual(
|
||||
@@ -708,7 +708,7 @@ QUnit.test('add an emoji after a command', async function (assert) {
|
||||
"text content of composer should be empty initially"
|
||||
);
|
||||
await insertText('.o_ComposerTextInput_textarea', "/");
|
||||
await click('.o_ComposerSuggestion');
|
||||
await click('.o_ComposerSuggestionView');
|
||||
assert.strictEqual(
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`).value.replace(/\s/, " "),
|
||||
"/who ",
|
||||
@@ -743,12 +743,12 @@ QUnit.test('display partner mention suggestions on typing "@"', async function (
|
||||
|
||||
assert.containsNone(
|
||||
document.body,
|
||||
'.o_ComposerSuggestionList_list',
|
||||
'.o_ComposerSuggestionListView_list',
|
||||
"mention suggestions list should not be present"
|
||||
);
|
||||
await insertText('.o_ComposerTextInput_textarea', "@");
|
||||
assert.hasClass(
|
||||
document.querySelector('.o_ComposerSuggestionList_list'),
|
||||
document.querySelector('.o_ComposerSuggestionListView_list'),
|
||||
'show',
|
||||
"should display mention suggestions on typing '@'"
|
||||
);
|
||||
@@ -774,7 +774,7 @@ QUnit.test('mention a partner', async function (assert) {
|
||||
|
||||
assert.containsNone(
|
||||
document.body,
|
||||
'.o_ComposerSuggestionList_list',
|
||||
'.o_ComposerSuggestionListView_list',
|
||||
"mention suggestions list should not be present"
|
||||
);
|
||||
assert.strictEqual(
|
||||
@@ -785,10 +785,10 @@ QUnit.test('mention a partner', async function (assert) {
|
||||
await insertText('.o_ComposerTextInput_textarea', '@Te');
|
||||
assert.containsOnce(
|
||||
document.body,
|
||||
'.o_ComposerSuggestion',
|
||||
'.o_ComposerSuggestionView',
|
||||
"should have a mention suggestion"
|
||||
);
|
||||
await click('.o_ComposerSuggestion');
|
||||
await click('.o_ComposerSuggestionView');
|
||||
assert.strictEqual(
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`).value.replace(/\s/, " "),
|
||||
"@TestPartner ",
|
||||
@@ -811,7 +811,7 @@ QUnit.test('mention a partner after some text', async function (assert) {
|
||||
|
||||
assert.containsNone(
|
||||
document.body,
|
||||
'.o_ComposerSuggestion',
|
||||
'.o_ComposerSuggestionView',
|
||||
"mention suggestions list should not be present"
|
||||
);
|
||||
assert.strictEqual(
|
||||
@@ -828,10 +828,10 @@ QUnit.test('mention a partner after some text', async function (assert) {
|
||||
await insertText('.o_ComposerTextInput_textarea', "@Te");
|
||||
assert.containsOnce(
|
||||
document.body,
|
||||
'.o_ComposerSuggestion',
|
||||
'.o_ComposerSuggestionView',
|
||||
"should have a mention suggestion"
|
||||
);
|
||||
await click('.o_ComposerSuggestion');
|
||||
await click('.o_ComposerSuggestionView');
|
||||
assert.strictEqual(
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`).value.replace(/\s/, " "),
|
||||
"bluhbluh @TestPartner ",
|
||||
@@ -854,7 +854,7 @@ QUnit.test('add an emoji after a partner mention', async function (assert) {
|
||||
|
||||
assert.containsNone(
|
||||
document.body,
|
||||
'.o_ComposerSuggestion',
|
||||
'.o_ComposerSuggestionView',
|
||||
"mention suggestions list should not be present"
|
||||
);
|
||||
assert.strictEqual(
|
||||
@@ -865,10 +865,10 @@ QUnit.test('add an emoji after a partner mention', async function (assert) {
|
||||
await insertText('.o_ComposerTextInput_textarea', "@Te");
|
||||
assert.containsOnce(
|
||||
document.body,
|
||||
'.o_ComposerSuggestion',
|
||||
'.o_ComposerSuggestionView',
|
||||
"should have a mention suggestion"
|
||||
);
|
||||
await click('.o_ComposerSuggestion');
|
||||
await click('.o_ComposerSuggestionView');
|
||||
assert.strictEqual(
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`).value.replace(/\s/, " "),
|
||||
"@TestPartner ",
|
||||
|
||||
@@ -86,7 +86,7 @@ QUnit.test('reply: discard on pressing escape', async function (assert) {
|
||||
await insertText('.o_ComposerTextInput_textarea', "@Te");
|
||||
assert.containsOnce(
|
||||
document.body,
|
||||
'.o_ComposerSuggestion',
|
||||
'.o_ComposerSuggestionView',
|
||||
"mention suggestion should be opened after typing @"
|
||||
);
|
||||
|
||||
@@ -96,7 +96,7 @@ QUnit.test('reply: discard on pressing escape', async function (assert) {
|
||||
});
|
||||
assert.containsNone(
|
||||
document.body,
|
||||
'.o_ComposerSuggestion',
|
||||
'.o_ComposerSuggestionView',
|
||||
"mention suggestion should be closed after pressing escape on mention suggestion"
|
||||
);
|
||||
assert.containsOnce(
|
||||
|
||||
@@ -878,7 +878,7 @@ QUnit.test('Post a message containing an email address followed by a mention on
|
||||
await openDiscuss();
|
||||
await insertText('.o_ComposerTextInput_textarea', "email@odoo.com\n");
|
||||
await insertText('.o_ComposerTextInput_textarea', "@Te");
|
||||
await click('.o_ComposerSuggestion');
|
||||
await click('.o_ComposerSuggestionView');
|
||||
await click('.o_Composer_buttonSend');
|
||||
assert.containsOnce(
|
||||
document.querySelector(`.o_Message_content`),
|
||||
@@ -903,7 +903,7 @@ QUnit.test(`Mention a partner with special character (e.g. apostrophe ')`, async
|
||||
});
|
||||
await openDiscuss();
|
||||
await insertText('.o_ComposerTextInput_textarea', "@Pyn");
|
||||
await click('.o_ComposerSuggestion');
|
||||
await click('.o_ComposerSuggestionView');
|
||||
await click('.o_Composer_buttonSend');
|
||||
assert.containsOnce(
|
||||
document.querySelector(`.o_Message_content`),
|
||||
@@ -934,9 +934,9 @@ QUnit.test('mention 2 different partners that have the same name', async functio
|
||||
});
|
||||
await openDiscuss();
|
||||
await insertText('.o_ComposerTextInput_textarea', "@Te");
|
||||
await afterNextRender(() => document.querySelectorAll('.o_ComposerSuggestion')[0].click());
|
||||
await afterNextRender(() => document.querySelectorAll('.o_ComposerSuggestionView')[0].click());
|
||||
await insertText('.o_ComposerTextInput_textarea', "@Te");
|
||||
await afterNextRender(() => document.querySelectorAll('.o_ComposerSuggestion')[1].click());
|
||||
await afterNextRender(() => document.querySelectorAll('.o_ComposerSuggestionView')[1].click());
|
||||
await click('.o_Composer_buttonSend');
|
||||
assert.containsOnce(document.body, '.o_Message_content', 'should have one message after posting it');
|
||||
assert.containsOnce(
|
||||
@@ -965,7 +965,7 @@ QUnit.test('mention a channel with space in the name', async function (assert) {
|
||||
});
|
||||
await openDiscuss();
|
||||
await insertText('.o_ComposerTextInput_textarea', "#");
|
||||
await click('.o_ComposerSuggestion');
|
||||
await click('.o_ComposerSuggestionView');
|
||||
await click('.o_Composer_buttonSend');
|
||||
assert.containsOnce(
|
||||
document.querySelector('.o_Message_content'),
|
||||
@@ -994,7 +994,7 @@ QUnit.test('mention a channel with "&" in the name', async function (assert) {
|
||||
await openDiscuss();
|
||||
|
||||
await insertText('.o_ComposerTextInput_textarea', "#");
|
||||
await click('.o_ComposerSuggestion');
|
||||
await click('.o_ComposerSuggestionView');
|
||||
await click('.o_Composer_buttonSend');
|
||||
assert.containsOnce(
|
||||
document.querySelector('.o_Message_content'),
|
||||
@@ -1023,7 +1023,7 @@ QUnit.test('mention a channel on a second line when the first line contains #',
|
||||
await openDiscuss();
|
||||
await insertText('.o_ComposerTextInput_textarea', "#blabla\n");
|
||||
await insertText('.o_ComposerTextInput_textarea', "#");
|
||||
await click('.o_ComposerSuggestion');
|
||||
await click('.o_ComposerSuggestionView');
|
||||
await click('.o_Composer_buttonSend');
|
||||
assert.containsOnce(
|
||||
document.querySelector('.o_Message_content'),
|
||||
@@ -1052,7 +1052,7 @@ QUnit.test('mention a channel when replacing the space after the mention by anot
|
||||
await openDiscuss();
|
||||
|
||||
await insertText('.o_ComposerTextInput_textarea', "#");
|
||||
await click('.o_ComposerSuggestion');
|
||||
await click('.o_ComposerSuggestionView');
|
||||
const text = document.querySelector(`.o_ComposerTextInput_textarea`).value;
|
||||
document.querySelector(`.o_ComposerTextInput_textarea`).value = text.slice(0, -1);
|
||||
await insertText('.o_ComposerTextInput_textarea', ", test");
|
||||
@@ -1090,9 +1090,9 @@ QUnit.test('mention 2 different channels that have the same name', async functio
|
||||
await openDiscuss();
|
||||
document.querySelector('.o_ComposerTextInput_textarea').focus();
|
||||
await insertText('.o_ComposerTextInput_textarea', "#my");
|
||||
await afterNextRender(() => document.querySelectorAll('.o_ComposerSuggestion')[0].click());
|
||||
await afterNextRender(() => document.querySelectorAll('.o_ComposerSuggestionView')[0].click());
|
||||
await insertText('.o_ComposerTextInput_textarea', "#my");
|
||||
await afterNextRender(() => document.querySelectorAll('.o_ComposerSuggestion')[1].click());
|
||||
await afterNextRender(() => document.querySelectorAll('.o_ComposerSuggestionView')[1].click());
|
||||
await click('.o_Composer_buttonSend');
|
||||
assert.containsOnce(document.body, '.o_Message_content', 'should have one message after posting it');
|
||||
assert.containsOnce(
|
||||
|
||||
Reference in New Issue
Block a user