diff --git a/addons/im_livechat/static/tests/tours/im_livechat_chatbot_steps_sequence_tour.js b/addons/im_livechat/static/tests/tours/im_livechat_chatbot_steps_sequence_tour.js index 61ce569a08e..990843d439d 100644 --- a/addons/im_livechat/static/tests/tours/im_livechat_chatbot_steps_sequence_tour.js +++ b/addons/im_livechat/static/tests/tours/im_livechat_chatbot_steps_sequence_tour.js @@ -16,7 +16,7 @@ const commonSteps = [tour.stepUtils.showAppsMenuItem(), { }, { trigger: 'div[name="script_step_ids"] .o_field_x2many_list_row_add a' }, { - trigger: 'textarea[name="message"]', + trigger: 'textarea#message', run: 'text Step 1' }, { trigger: 'button:contains("Save & New")' @@ -25,7 +25,7 @@ const commonSteps = [tour.stepUtils.showAppsMenuItem(), { in_modal: false, run: () => {} }, { - trigger: 'textarea[name="message"]', + trigger: 'textarea#message', run: 'text Step 2' }, { trigger: 'button:contains("Save & New")' @@ -34,7 +34,7 @@ const commonSteps = [tour.stepUtils.showAppsMenuItem(), { in_modal: false, run: () => {} }, { - trigger: 'textarea[name="message"]', + trigger: 'textarea#message', run: 'text Step 3' }]; @@ -68,7 +68,7 @@ tour.register('im_livechat_chatbot_steps_sequence_with_move_tour', { in_modal: false, run: () => {} }, { - trigger: 'textarea[name="message"]', + trigger: 'textarea#message', run: 'text Step 4' }, { trigger: 'button:contains("Save & New")' @@ -77,7 +77,7 @@ tour.register('im_livechat_chatbot_steps_sequence_with_move_tour', { in_modal: false, run: () => {} }, { - trigger: 'textarea[name="message"]', + trigger: 'textarea#message', run: 'text Step 5' }, { trigger: 'button:contains("Save & Close")' @@ -108,7 +108,7 @@ tour.register('im_livechat_chatbot_steps_sequence_with_move_tour', { }, { trigger: 'div[name="script_step_ids"] .o_field_x2many_list_row_add a' }, { - trigger: 'textarea[name="message"]', + trigger: 'textarea#message', run: 'text Step 6' }, { trigger: 'button:contains("Save & Close")' diff --git a/addons/mail/static/src/js/emojis_dropdown.js b/addons/mail/static/src/js/emojis_dropdown.js new file mode 100644 index 00000000000..71533ff4caf --- /dev/null +++ b/addons/mail/static/src/js/emojis_dropdown.js @@ -0,0 +1,19 @@ +/** @odoo-module **/ + +import emojis from '@mail/js/emojis'; + +const { Component, useRef, onMounted } = owl; + +export class EmojisDropdown extends Component { + setup() { + this.toggleRef = useRef('toggleRef'); + this.emojis = emojis; + super.setup(); + onMounted(() => { + new Dropdown(this.toggleRef.el, { + popperConfig: { placement: 'bottom-end', strategy: 'fixed' }, + }); + }); + } +}; +EmojisDropdown.template = 'mail.EmojisDropdown'; diff --git a/addons/mail/static/src/js/emojis_mixin.js b/addons/mail/static/src/js/emojis_mixin.js index d2902f508f7..b7d4a466d86 100644 --- a/addons/mail/static/src/js/emojis_mixin.js +++ b/addons/mail/static/src/js/emojis_mixin.js @@ -28,10 +28,10 @@ export default { * * @param {MouseEvent} ev */ - _onEmojiClick: function (ev) { - var unicode = ev.currentTarget.textContent.trim(); - var textInput = this._getTargetTextElement($(ev.currentTarget))[0]; - var selectionStart = textInput.selectionStart; + onEmojiClick(ev) { + const unicode = ev.currentTarget.textContent.trim(); + const textInput = this._getTargetTextElement($(ev.currentTarget)); + const selectionStart = textInput.selectionStart; textInput.value = textInput.value.slice(0, selectionStart) + unicode + textInput.value.slice(selectionStart); textInput.focus(); @@ -49,7 +49,7 @@ export default { * * @param {String} message a text message to format */ - _formatText: function (message) { + _formatText(message) { message = escape(message); message = this._wrapEmojis(message); message = message.replace(/(?:\r\n|\r|\n)/g, '
'); @@ -63,7 +63,7 @@ export default { * * @param {String} message */ - _wrapEmojis: function (message) { + _wrapEmojis(message) { emojis.forEach(function (emoji) { message = message.replace( new RegExp(emoji.unicode.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g'), diff --git a/addons/mail/static/src/scss/emojis.scss b/addons/mail/static/src/scss/emojis.scss index 64238a95784..92c3cf5ab80 100644 --- a/addons/mail/static/src/scss/emojis.scss +++ b/addons/mail/static/src/scss/emojis.scss @@ -17,20 +17,11 @@ $o-mail-emoji-height: 2rem; } } -.o_form_view { - // Emojis widgets should hide the emoji dropdown button when the field is invisible. - // This is necessary because the button is added *after* the main element (and not inside) - // (see '_attachEmojisDropdown' for more details) - .o_invisible_modifier + .o_mail_add_emoji, .o_invisible_modifier + textarea + .o_mail_add_emoji{ - display: none !important; - } -} - .o_mail_emojis_dropdown { height: $o-mail-emoji-height; width: 40px; float: right; - bottom: 33px; + bottom: 26px; margin-bottom: -$o-mail-emoji-height; * { @@ -50,15 +41,12 @@ $o-mail-emoji-height: 2rem; margin-right: 20px; } -.o_mail_emojis_dropdown_textarea{ - bottom: 40px; +.o_mail_emojis_dropdown_textarea { + bottom: 30px; } .o_xxs_form_view { - .o_mail_emojis_dropdown { - bottom: 50px; - } .o_mail_add_emoji { .dropdown-menu { max-width: 320px; diff --git a/addons/mail/static/src/views/fields/emojis_char_field/emojis_char_field.js b/addons/mail/static/src/views/fields/emojis_char_field/emojis_char_field.js index 0279c730fc8..5d91606dbde 100644 --- a/addons/mail/static/src/views/fields/emojis_char_field/emojis_char_field.js +++ b/addons/mail/static/src/views/fields/emojis_char_field/emojis_char_field.js @@ -1,16 +1,28 @@ /** @odoo-module **/ +import { CharField } from "@web/views/fields/char/char_field"; +import { patch } from "@web/core/utils/patch"; import MailEmojisMixin from '@mail/js/emojis_mixin'; -import EmojisFieldCommon from '@mail/views/fields/emojis_field_common'; +import { EmojisDropdown } from '@mail/js/emojis_dropdown'; +import { EmojisFieldCommon } from '@mail/views/fields/emojis_field_common'; +import { registry } from "@web/core/registry"; -import basicFields from 'web.basic_fields'; -import registry from 'web.field_registry'; +const { useRef } = owl; /** * Extension of the FieldChar that will add emojis support */ -var EmojisCharField = basicFields.FieldChar.extend(MailEmojisMixin, EmojisFieldCommon); +export class EmojisCharField extends CharField { + setup() { + super.setup(); + this.targetEditElement = useRef('input'); + this._setupOverride(); + } +}; -registry.add('char_emojis', EmojisCharField); - -export default EmojisCharField; +patch(EmojisCharField.prototype, 'emojis_char_field_mail_mixin', MailEmojisMixin); +patch(EmojisCharField.prototype, 'emojis_char_field_field_mixin', EmojisFieldCommon); +EmojisCharField.template = 'mail.EmojisCharField'; +EmojisCharField.components = { ...CharField.components, EmojisDropdown }; +EmojisCharField.additionalClasses = [...(CharField.additionalClasses || []), 'o_field_text']; +registry.category("fields").add("char_emojis", EmojisCharField); diff --git a/addons/mail/static/src/views/fields/emojis_char_field/emojis_char_field.xml b/addons/mail/static/src/views/fields/emojis_char_field/emojis_char_field.xml new file mode 100644 index 00000000000..e65bf1b0524 --- /dev/null +++ b/addons/mail/static/src/views/fields/emojis_char_field/emojis_char_field.xml @@ -0,0 +1,12 @@ + + + + + + targetReadonlyElement + + + + + + diff --git a/addons/mail/static/src/views/fields/emojis_field_common.js b/addons/mail/static/src/views/fields/emojis_field_common.js index 8ca93f9402c..2ef023e678c 100644 --- a/addons/mail/static/src/views/fields/emojis_field_common.js +++ b/addons/mail/static/src/views/fields/emojis_field_common.js @@ -1,144 +1,39 @@ /** @odoo-module **/ -import { debounce } from "@web/core/utils/timing"; -import emojis from '@mail/js/emojis'; import MailEmojisMixin from '@mail/js/emojis_mixin'; -import core from 'web.core'; -var _onEmojiClickMixin = MailEmojisMixin._onEmojiClick; -var QWeb = core.qweb; +const _onEmojiClickMixin = MailEmojisMixin.onEmojiClick; +const { useRef, onMounted } = owl; /* - * Common code for FieldTextEmojis and FieldCharEmojis + * Common code for EmojisTextField and EmojisCharField */ -var EmojisFieldCommon = { - /** - * @override - * @private - */ - init: function () { - this._super.apply(this, arguments); - if (this.nodeOptions.keydown_debounce_delay === undefined) { - this.nodeOptions.keydown_debounce_delay = 2000; - } - this._triggerOnchange = debounce(this._triggerOnchange, this.nodeOptions.keydown_debounce_delay); - this.emojis = emojis; - }, - - /** - * @override - */ - on_attach_callback: function () { - this._attachEmojisDropdown(); - }, - - //-------------------------------------------------------------------------- - // Handlers - //-------------------------------------------------------------------------- - - /** - * @override - * @private - */ - _render: function () { - this._super.apply(this, arguments); - - if (this.mode !== 'edit') { - this.$el.html(this._formatText(this.$el.text())); - } - }, - - /** - * Overridden because we need to add the Emoji to the input AND trigger - * the 'change' event to refresh the value. - * - * @override - * @private - */ - _onEmojiClick: function () { - _onEmojiClickMixin.apply(this, arguments); - this._isDirty = true; - this.$input.trigger('change'); - }, - - /** - * - * By default, the 'change' event is only triggered when the text element is blurred. - * - * We override this method because we want to update the value while - * the user is typing their message (and not only on blur). - * - * @override - * @private - */ - _onKeydown: function () { - this._super.apply(this, arguments); - if (this.nodeOptions.onchange_on_keydown) { - this._triggerOnchange(); +export const EmojisFieldCommon = { + _setupOverride() { + this.targetReadonlyElement = useRef('targetReadonlyElement'); + this.emojisDropdown = useRef('emojisDropdown'); + if (this.props.readonly) { + onMounted(() => { + this.targetReadonlyElement.el.innerHTML = this._formatText(this.targetReadonlyElement.el.textContent); + }); } + this.onEmojiClick = this._onEmojiClick.bind(this); }, //-------------------------------------------------------------------------- // Private //-------------------------------------------------------------------------- + _onEmojiClick() { + _onEmojiClickMixin.apply(this, arguments); + this.props.update(this._getTargetTextElement().value); + }, /** * Used by MailEmojisMixin, check its document for more info. * * @private */ _getTargetTextElement() { - return this.$el; + return this.props.readonly ? this.targetReadonlyElement.el : this.targetEditElement.el; }, - - /** - * Triggers the 'change' event to refresh the value. - * This method is debounced to run after given debouce delay on typing ends. - * (to avoid spamming the server while the user is typing their message) - * - * @private - */ - _triggerOnchange: function () { - this.$input.trigger('change'); - }, - - /** - * This will add an emoji button that shows the emojis selection dropdown. - * - * Should be used inside 'on_attach_callback' because we need the element to be attached to the form first. - * That's because the $emojisIcon element needs to be rendered outside of this $el - * (which is an text element, that can't 'contain' any other elements). - * - * @private - */ - _attachEmojisDropdown: function () { - if (!this.$emojisIcon) { - this.$emojisIcon = $(QWeb.render('mail.EmojisDropdown', {widget: this})); - this.$emojisIcon.find('.o_mail_emoji').on('click', this._onEmojiClick.bind(this)); - - if (this.$el.filter('span.o_field_translate').length) { - // multi-languages activated, place the button on the left of the translation button - this.$emojisIcon.addClass('o_mail_emojis_dropdown_translation'); - } - if (this.$el.filter('textarea').length) { - this.$emojisIcon.addClass('o_mail_emojis_dropdown_textarea'); - } - this.$el.last().after(this.$emojisIcon); - } - - if (this.mode === 'edit') { - this.$emojisIcon.show(); - } else { - this.$emojisIcon.hide(); - } - }, - - destroy() { - this._super(...arguments); - if (this.$emojisIcon) { - this.$emojisIcon.remove(); - } - } }; - -export default EmojisFieldCommon; diff --git a/addons/mail/static/src/views/fields/emojis_text_field/emojis_text_field.js b/addons/mail/static/src/views/fields/emojis_text_field/emojis_text_field.js index 29be82b1548..4d1de9e9847 100644 --- a/addons/mail/static/src/views/fields/emojis_text_field/emojis_text_field.js +++ b/addons/mail/static/src/views/fields/emojis_text_field/emojis_text_field.js @@ -1,16 +1,26 @@ /** @odoo-module **/ +import { TextField } from "@web/views/fields/text/text_field"; +import { patch } from "@web/core/utils/patch"; import MailEmojisMixin from '@mail/js/emojis_mixin'; -import EmojisFieldCommon from '@mail/views/fields/emojis_field_common'; - -import basicFields from 'web.basic_fields'; -import registry from 'web.field_registry'; +import { EmojisDropdown } from '@mail/js/emojis_dropdown'; +import { EmojisFieldCommon } from '@mail/views/fields/emojis_field_common'; +import { registry } from "@web/core/registry"; /** * Extension of the FieldText that will add emojis support */ -var EmojisTextField = basicFields.FieldText.extend(MailEmojisMixin, EmojisFieldCommon); +export class EmojisTextField extends TextField { + setup() { + super.setup(); + this.targetEditElement = this.textareaRef; + this._setupOverride(); + } +}; -registry.add('text_emojis', EmojisTextField); - -export default EmojisTextField; +patch(EmojisTextField.prototype, 'emojis_text_field_mail_mixin', MailEmojisMixin); +patch(EmojisTextField.prototype, 'emojis_text_field_field_mixin', EmojisFieldCommon); +EmojisTextField.template = 'mail.EmojisTextField'; +EmojisTextField.components = { ...TextField.components, EmojisDropdown }; +EmojisTextField.additionalClasses = [...(TextField.additionalClasses || []), 'o_field_text']; +registry.category("fields").add("text_emojis", EmojisTextField); diff --git a/addons/mail/static/src/views/fields/emojis_text_field/emojis_text_field.xml b/addons/mail/static/src/views/fields/emojis_text_field/emojis_text_field.xml new file mode 100644 index 00000000000..a3e5d4cdd07 --- /dev/null +++ b/addons/mail/static/src/views/fields/emojis_text_field/emojis_text_field.xml @@ -0,0 +1,13 @@ + + + + + + targetReadonlyElement + + + + + + diff --git a/addons/mail/static/src/xml/composer.xml b/addons/mail/static/src/xml/composer.xml deleted file mode 100644 index 1d905770b0c..00000000000 --- a/addons/mail/static/src/xml/composer.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - -
- - - - - -
-
diff --git a/addons/mail/static/src/xml/text_emojis.xml b/addons/mail/static/src/xml/text_emojis.xml index 882aca9fbb8..32104b49c20 100644 --- a/addons/mail/static/src/xml/text_emojis.xml +++ b/addons/mail/static/src/xml/text_emojis.xml @@ -1,7 +1,12 @@ -