[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:
committed by
Alexandre Kühn
parent
c3a27689c3
commit
396d79aef3
+18
-120
@@ -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);
|
||||
|
||||
+2
-2
@@ -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>
|
||||
|
||||
+1
-4
@@ -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');
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user