[IMP] mail: autocompleteInput refactor

task-2974765

closes odoo/odoo#99839

Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
This commit is contained in:
Zelong Lin
2022-09-19 21:58:05 +02:00
committed by Alexandre Kühn
parent c3a27689c3
commit 396d79aef3
8 changed files with 117 additions and 138 deletions
@@ -5,7 +5,7 @@ import { registerMessagingComponent } from '@mail/utils/messaging_component';
const { Component, onMounted, onWillUnmount } = owl;
export class AutocompleteInput extends Component {
export class AutocompleteInputView extends Component {
/**
* @override
@@ -25,11 +25,18 @@ export class AutocompleteInput extends Component {
this.root.el.focus();
}
let args = {
const args = {
autoFocus: true,
select: (ev, ui) => this._onAutocompleteSelect(ev, ui),
source: (req, res) => this._onAutocompleteSource(req, res),
focus: ev => this._onAutocompleteFocus(ev),
select: (ev, ui) => {
if (this.autocompleteInputView) {
this.autocompleteInputView.onSelect(ev, ui);
}
},
source: (req, res) => {
if (this.autocompleteInputView) {
this.autocompleteInputView.onSource(req, res);
}
},
html: this.autocompleteInputView.isHtml,
};
@@ -40,7 +47,7 @@ export class AutocompleteInput extends Component {
const autoCompleteElem = $(this.root.el).autocomplete(args);
// Resize the autocomplete dropdown options to handle the long strings
// By setting the width of dropdown based on the width of the input element.
autoCompleteElem.data("ui-autocomplete")._resizeMenu = function () {
autoCompleteElem.data('ui-autocomplete')._resizeMenu = function () {
const ul = this.menu.element;
ul.outerWidth(this.element.outerWidth());
};
@@ -56,124 +63,15 @@ export class AutocompleteInput extends Component {
/**
* @returns {AutocompleteInputView}
*/
get autocompleteInputView() {
get autocompleteInputView() {
return this.props.record;
}
//--------------------------------------------------------------------------
// Public
//--------------------------------------------------------------------------
/**
* Returns whether the given node is self or a children of self, including
* the suggestion menu.
*
* @param {Node} node
* @returns {boolean}
*/
contains(node) {
if (!this.root.el) {
return false;
}
if (this.root.el.contains(node)) {
return true;
}
if (!this.autocompleteInputView.customClass) {
return false;
}
const element = document.querySelector(`.${this.autocompleteInputView.customClass}`);
if (!element) {
return false;
}
return element.contains(node);
}
//--------------------------------------------------------------------------
// Handlers
//--------------------------------------------------------------------------
/**
* @private
* @param {FocusEvent} ev
*/
_onAutocompleteFocus(ev) {
if (this.props.focus) {
this.props.focus(ev);
} else {
ev.preventDefault();
}
}
/**
* @private
* @param {Event} ev
* @param {Object} ui
*/
_onAutocompleteSelect(ev, ui) {
if (this.props.select) {
this.props.select(ev, ui);
}
}
/**
* @private
* @param {Object} req
* @param {function} res
*/
_onAutocompleteSource(req, res) {
if (this.props.source) {
this.props.source(req, res);
}
if (this.messaging) {
this.messaging.messagingBus.trigger('o-AutocompleteInput-source', {});
}
}
/**
* @private
* @param {MouseEvent} ev
*/
_onBlur(ev) {
if (this.props.onHide) {
this.props.onHide();
}
}
/**
* @private
* @param {MouseEvent} ev
*/
_onKeydown(ev) {
if (ev.key === 'Escape') {
if (this.props.onHide) {
this.props.onHide();
}
}
}
}
Object.assign(AutocompleteInput, {
props: {
focus: {
type: Function,
optional: true,
},
record: Object,
onHide: {
type: Function,
optional: true,
},
select: {
type: Function,
optional: true,
},
source: {
type: Function,
optional: true,
},
},
template: 'mail.AutocompleteInput',
Object.assign(AutocompleteInputView, {
props: { record: Object },
template: 'mail.AutocompleteInputView',
});
registerMessagingComponent(AutocompleteInput);
registerMessagingComponent(AutocompleteInputView);
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="mail.AutocompleteInput" owl="1">
<input class="o_AutocompleteInput form-control" t-attf-class="{{ className }}" t-on-blur="_onBlur" t-on-focusin="autocompleteInputView.onFocusin" t-on-keydown="_onKeydown" t-att-placeholder="autocompleteInputView.placeholder" t-ref="root"/>
<t t-name="mail.AutocompleteInputView" owl="1">
<input class="o_AutocompleteInputView form-control" t-attf-class="{{ className }}" t-on-blur="autocompleteInputView.onBlur" t-on-focusin="autocompleteInputView.onFocusin" t-on-keydown="autocompleteInputView.onKeydown" t-att-placeholder="autocompleteInputView.placeholder" t-ref="root"/>
</t>
</templates>
@@ -39,11 +39,9 @@
<span class="o_ChatWindow_newMessageFormLabel flex-grow-0 flex-shrink-0 me-2">
To:
</span>
<AutocompleteInput
<AutocompleteInputView
className="'o_ChatWindow_newMessageFormInput flex-grow-1 flex-shrink-1 border'"
record="chatWindow.newMessageAutocompleteInputView"
select="chatWindow.onAutocompleteSelect"
source="chatWindow.onAutocompleteSource"
/>
</div>
</t>
@@ -26,12 +26,9 @@
</t>
<t t-if="discussView.mobileAddItemHeaderAutocompleteInputView">
<div class="o_Discuss_mobileAddItemHeader d-flex justify-content-center w-100 p-3 border-bottom bg-light">
<AutocompleteInput
<AutocompleteInputView
className="'o_Discuss_mobileAddItemHeaderInput flex-grow-1 mb-3 p-2 rounded border'"
record="discussView.mobileAddItemHeaderAutocompleteInputView"
select="discussView.onMobileAddItemHeaderInputSelect"
source="discussView.onMobileAddItemHeaderInputSource"
onHide="discussView.onHideMobileAddItemHeader"
/>
</div>
</t>
@@ -29,12 +29,9 @@
<t t-if="category.isOpen">
<t t-if="category.addingItemAutocompleteInputView">
<div class="o_DiscussSidebarCategory_addingItem d-flex mb-2">
<AutocompleteInput
<AutocompleteInputView
className="'o_DiscussSidebarCategory_addingItemInput form-control mx-4 rounded'"
record="category.addingItemAutocompleteInputView"
select="category.onAddItemAutocompleteSelect"
source="category.onAddItemAutocompleteSource"
onHide="category.onHideAddingItem"
/>
</div>
</t>
@@ -35,12 +35,9 @@
<t t-call="mail.MessagingMenu.newMessageButton"/>
</t>
<t t-if="messagingMenu.mobileNewMessageAutocompleteInputView">
<AutocompleteInput
<AutocompleteInputView
className="'o_MessagingMenu_mobileNewMessageInput mt-2 p-2 rounded-3'"
record="messagingMenu.mobileNewMessageAutocompleteInputView"
select="messagingMenu.onMobileNewMessageInputSelect"
source="messagingMenu.onMobileNewMessageInputSource"
onHide="messagingMenu.onHideMobileNewMessage"
/>
</t>
</div>
@@ -8,16 +8,96 @@ registerModel({
name: 'AutocompleteInputView',
identifyingMode: 'xor',
recordMethods: {
onBlur() {
if (!this.exists()) {
return;
}
if (this.discussSidebarCategoryOwnerAsAddingItem) {
this.discussSidebarCategoryOwnerAsAddingItem.onHideAddingItem();
return;
}
if (this.discussViewOwnerAsMobileAddItemHeader) {
this.discussViewOwnerAsMobileAddItemHeader.onHideMobileAddItemHeader();
return;
}
if (this.messagingMenuOwnerAsMobileNewMessageInput) {
this.messagingMenuOwnerAsMobileNewMessageInput.onHideMobileNewMessage();
return;
}
},
/**
* @param {FocusEvent} ev
*/
onFocusin(ev) {
if (!this.exists()) {
return;
}
if (this.chatWindowOwnerAsNewMessage) {
this.chatWindowOwnerAsNewMessage.onFocusInNewMessageFormInput(ev);
return;
}
},
/**
/**
* @param {MouseEvent} ev
*/
onKeydown(ev) {
if (!this.exists()) {
return;
}
if (ev.key === 'Escape') {
this.onBlur();
}
},
/**
* @param {MouseEvent} ev
*/
onSelect(ev, ui) {
if (!this.exists()) {
return;
}
if (this.chatWindowOwnerAsNewMessage) {
this.chatWindowOwnerAsNewMessage.onAutocompleteSelect(ev, ui);
return;
}
if (this.discussSidebarCategoryOwnerAsAddingItem) {
this.discussSidebarCategoryOwnerAsAddingItem.onAddItemAutocompleteSelect(ev, ui);
return;
}
if (this.discussViewOwnerAsMobileAddItemHeader) {
this.discussViewOwnerAsMobileAddItemHeader.onMobileAddItemHeaderInputSelect(ev, ui);
return;
}
if (this.messagingMenuOwnerAsMobileNewMessageInput) {
this.messagingMenuOwnerAsMobileNewMessageInput.onMobileNewMessageInputSelect(ev, ui);
return;
}
},
/**
* @param {Object} req
* @param {function} res
*/
onSource(req, res) {
if (!this.exists()) {
return;
}
if (this.chatWindowOwnerAsNewMessage) {
this.chatWindowOwnerAsNewMessage.onAutocompleteSource(req, res);
return;
}
if (this.discussSidebarCategoryOwnerAsAddingItem) {
this.discussSidebarCategoryOwnerAsAddingItem.onAddItemAutocompleteSource(req, res);
return;
}
if (this.discussViewOwnerAsMobileAddItemHeader) {
this.discussViewOwnerAsMobileAddItemHeader.onMobileAddItemHeaderInputSource(req, res);
return;
}
if (this.messagingMenuOwnerAsMobileNewMessageInput) {
this.messagingMenuOwnerAsMobileNewMessageInput.onMobileNewMessageInputSource(req, res);
return;
}
},
/**
* @private
* @returns {boolean|FieldCommand}
*/
@@ -0,0 +1,12 @@
/** @odoo-module **/
import { patchRecordMethods } from '@mail/model/model_core';
// ensure that the model definition is loaded before the patch
import '@mail/models/autocomplete_input_view';
patchRecordMethods('AutocompleteInputView', {
onSource(req, res) {
this._super(req, res);
this.messaging.messagingBus.trigger('o-AutocompleteInput-source');
},
});