diff --git a/addons/im_livechat/static/src/legacy/public_livechat_chatbot.js b/addons/im_livechat/static/src/legacy/public_livechat_chatbot.js index fe1f0ed83a6..483c188f5dc 100644 --- a/addons/im_livechat/static/src/legacy/public_livechat_chatbot.js +++ b/addons/im_livechat/static/src/legacy/public_livechat_chatbot.js @@ -86,8 +86,8 @@ const QWeb = core.qweb; this.messaging.publicLivechatGlobal.livechatButtonView.update({ rule: this.messaging.publicLivechatGlobal.livechatButtonView.livechatInit.rule }); } else if (this.messaging.publicLivechatGlobal.livechatButtonView.chatbotState === 'restore_session') { // we landed on a website page and a chatbot script is currently running - // -> restore the user's session (see '_chatbotRestoreSession') - this._chatbotRestoreSession(); + // -> restore the user's session (see 'chatbotRestoreSession') + this.messaging.publicLivechatGlobal.livechatButtonView.chatbotRestoreSession(); } return superResult; @@ -106,7 +106,7 @@ const QWeb = core.qweb; */ _chatbotAddMessage(message, options) { message.body = utils.Markup(message.body); - this._addMessage(message, options); + this.messaging.publicLivechatGlobal.livechatButtonView.addMessage(message, options); if (this.messaging.publicLivechatGlobal.publicLivechat.isFolded || !this.messaging.publicLivechatGlobal.livechatButtonView.chatWindow.legacyChatWindow._publicLivechatView.isAtBottom()) { this.messaging.publicLivechatGlobal.publicLivechat.update({ unreadCounter: increment() }); } @@ -135,8 +135,12 @@ const QWeb = core.qweb; this._chatbotEndScript(); } else { this._chatbotSetIsTyping(); - this.nextStepTimeout = setTimeout( - this._chatbotTriggerNextStep.bind(this), this.messaging.publicLivechatGlobal.livechatButtonView.chatbot.messageDelay); + this.messaging.publicLivechatGlobal.livechatButtonView.update({ + chatbotNextStepTimeout: setTimeout( + this._chatbotTriggerNextStep.bind(this), + this.messaging.publicLivechatGlobal.livechatButtonView.chatbot.messageDelay, + ) + }); } } }, @@ -305,8 +309,12 @@ const QWeb = core.qweb; if (this._isLastMessageFromCustomer()) { // user has already typed a message in -> trigger next step this._chatbotSetIsTyping(); - this.nextStepTimeout = setTimeout( - this._chatbotTriggerNextStep.bind(this), this.messaging.publicLivechatGlobal.livechatButtonView.chatbot.messageDelay); + this.messaging.publicLivechatGlobal.livechatButtonView.update({ + chatbotNextStepTimeout: setTimeout( + this._chatbotTriggerNextStep.bind(this), + this.messaging.publicLivechatGlobal.livechatButtonView.chatbot.messageDelay, + ), + }); } else { this._chatbotEnableInput(); } @@ -332,8 +340,12 @@ const QWeb = core.qweb; this._chatbotSetIsTyping(); } - this.nextStepTimeout = setTimeout( - this._chatbotTriggerNextStep.bind(this), nextStepDelay); + this.messaging.publicLivechatGlobal.livechatButtonView.update({ + chatbotNextStepTimeout: setTimeout( + this._chatbotTriggerNextStep.bind(this), + nextStepDelay, + ), + }); } } @@ -341,35 +353,6 @@ const QWeb = core.qweb; this.messaging.publicLivechatGlobal.livechatButtonView.chatWindow.legacyChatWindow.$('.o_livechat_chatbot_main_restart').addClass('d-none'); } }, - /** - * See '_chatbotSaveSession'. - * - * We retrieve the livechat uuid from the session cookie since the livechat Widget is not yet - * initialized when we restore the chatbot state. - * - * We also clear any older keys that store a previously saved chatbot session. - * (In that case we clear the actual browser's local storage, we don't use the localStorage - * object as it does not allow browsing existing keys, see 'local_storage.js'.) - * - * @private - */ - _chatbotRestoreSession() { - const browserLocalStorage = window.localStorage; - if (browserLocalStorage && browserLocalStorage.length) { - for (let i = 0; i < browserLocalStorage.length; i++) { - const key = browserLocalStorage.key(i); - if (key.startsWith('im_livechat.chatbot.state.uuid_') && key !== this.messaging.publicLivechatGlobal.livechatButtonView.chatbotSessionCookieKey) { - browserLocalStorage.removeItem(key); - } - } - } - - let chatbotState = localStorage.getItem(this.messaging.publicLivechatGlobal.livechatButtonView.chatbotSessionCookieKey); - - if (chatbotState) { - this.messaging.publicLivechatGlobal.livechatButtonView.chatbot.update({ currentStep: insertAndReplace({ data: this.messaging.publicLivechatGlobal.livechatButtonView.localStorageChatbotState._chatbotCurrentStep }) }); - } - }, /** * Register current chatbot step state into localStorage to be able to resume if the visitor * goes to another website page or if he refreshes his page. @@ -700,8 +683,12 @@ const QWeb = core.qweb; this._debouncedChatbotAwaitUserInput(); } else if (!this._chatbotShouldEndScript()) { this._chatbotSetIsTyping(); - this.nextStepTimeout = setTimeout( - this._chatbotTriggerNextStep.bind(this), this.messaging.publicLivechatGlobal.livechatButtonView.chatbot.messageDelay); + this.messaging.publicLivechatGlobal.livechatButtonView.update({ + chatbotNextStepTimeout: setTimeout( + this._chatbotTriggerNextStep.bind(this), + this.messaging.publicLivechatGlobal.livechatButtonView.chatbot.messageDelay, + ), + }); } else { this._chatbotEndScript(); } @@ -750,7 +737,7 @@ const QWeb = core.qweb; this.messaging.publicLivechatGlobal.livechatButtonView.chatbot.update({ currentStep: insertAndReplace({ data: chatbotStep }) }); if (chatbotStep.chatbot_step_message) { - this._addMessage({ + this.messaging.publicLivechatGlobal.livechatButtonView.addMessage({ id: '_welcome_' + stepIndex, is_discussion: true, // important for css style -> we only want white background for chatbot attachment_ids: [], @@ -777,10 +764,12 @@ const QWeb = core.qweb; this._chatbotSetIsTyping(true); } - this.welcomeMessageTimeout = setTimeout(() => { - this._sendWelcomeChatbotMessage(stepIndex + 1, welcomeMessageDelay); - this._renderMessages(); - }, welcomeMessageDelay); + this.messaging.publicLivechatGlobal.livechatButtonView.update({ + chatbotWelcomeMessageTimeout: setTimeout(() => { + this._sendWelcomeChatbotMessage(stepIndex + 1, welcomeMessageDelay); + this._renderMessages(); + }, welcomeMessageDelay), + }); } else { if (this.messaging.publicLivechatGlobal.livechatButtonView.chatbot.currentStep.data.chatbot_step_type === 'forward_operator') { // special case when the last welcome message is a forward to an operator @@ -810,12 +799,12 @@ const QWeb = core.qweb; this.messaging.publicLivechatGlobal.livechatButtonView.chatWindow.legacyChatWindow.$('.o_composer_text_field').removeClass('d-none'); this.messaging.publicLivechatGlobal.livechatButtonView.chatWindow.legacyChatWindow.$('.o_livechat_chatbot_end').hide(); - if (this.nextStepTimeout) { - clearTimeout(this.nextStepTimeout); + if (this.messaging.publicLivechatGlobal.livechatButtonView.chatbotNextStepTimeout) { + clearTimeout(this.messaging.publicLivechatGlobal.livechatButtonView.chatbotNextStepTimeout); } - if (this.welcomeMessageTimeout) { - clearTimeout(this.welcomeMessageTimeout); + if (this.messaging.publicLivechatGlobal.livechatButtonView.chatbotWelcomeMessageTimeout) { + clearTimeout(this.messaging.publicLivechatGlobal.livechatButtonView.chatbotWelcomeMessageTimeout); } const postedMessage = await session.rpc('/chatbot/restart', { @@ -829,8 +818,12 @@ const QWeb = core.qweb; this.messaging.publicLivechatGlobal.livechatButtonView.chatbot.update({ currentStep: clear() }); this._chatbotSetIsTyping(); - this.nextStepTimeout = setTimeout( - this._chatbotTriggerNextStep.bind(this), this.messaging.publicLivechatGlobal.livechatButtonView.chatbot.messageDelay); + this.messaging.publicLivechatGlobal.livechatButtonView.update({ + chatbotNextStepTimeout: setTimeout( + this._chatbotTriggerNextStep.bind(this), + this.messaging.publicLivechatGlobal.livechatButtonView.chatbot.messageDelay, + ), + }); }, _onChatbotInputKeyDown() { diff --git a/addons/im_livechat/static/src/legacy/widgets/livechat_button.js b/addons/im_livechat/static/src/legacy/widgets/livechat_button.js index c96b4277138..7a2da22e5f6 100644 --- a/addons/im_livechat/static/src/legacy/widgets/livechat_button.js +++ b/addons/im_livechat/static/src/legacy/widgets/livechat_button.js @@ -7,12 +7,9 @@ import time from 'web.time'; import utils from 'web.utils'; import Widget from 'web.Widget'; -import PublicLivechatMessage from '@im_livechat/legacy/models/public_livechat_message'; - -import { clear, insertAndReplace, link, replace } from '@mail/model/model_field_command'; +import { clear, insertAndReplace } from '@mail/model/model_field_command'; const _t = core._t; -const QWeb = core.qweb; const LivechatButton = Widget.extend({ className: 'openerp o_livechat_button d-print-none', @@ -48,13 +45,13 @@ const LivechatButton = Widget.extend({ } this.messaging.publicLivechatGlobal.livechatButtonView.update({ rule: result.rule }); } - return this._loadQWebTemplate(); + return this.messaging.publicLivechatGlobal.loadQWebTemplate(); }, start() { this.$el.text(this.messaging.publicLivechatGlobal.livechatButtonView.buttonText); if (this.messaging.publicLivechatGlobal.livechatButtonView.history) { for (const m of this.messaging.publicLivechatGlobal.livechatButtonView.history) { - this._addMessage(m); + this.messaging.publicLivechatGlobal.livechatButtonView.addMessage(m); } this._openChat(); } else if (!config.device.isMobile && this.messaging.publicLivechatGlobal.livechatButtonView.rule.action === 'auto_popup') { @@ -85,45 +82,6 @@ const LivechatButton = Widget.extend({ // Private //-------------------------------------------------------------------------- - - /** - * @private - * @param {Object} data - * @param {Object} [options={}] - */ - _addMessage(data, options) { - const legacyMessage = new PublicLivechatMessage(this, this.messaging, data); - - const hasAlreadyMessage = _.some(this.messaging.publicLivechatGlobal.livechatButtonView.messages, function (msg) { - return legacyMessage.getID() === msg.id; - }); - if (hasAlreadyMessage) { - return; - } - const message = this.messaging.models['PublicLivechatMessage'].insert({ - id: data.id, - legacyPublicLivechatMessage: legacyMessage, - }); - if (this.messaging.publicLivechatGlobal.publicLivechat) { - this.messaging.publicLivechatGlobal.publicLivechat.update({ - messages: link(message), - }); - } - - if (this.messaging.publicLivechatGlobal.publicLivechat && this.messaging.publicLivechatGlobal.publicLivechat.legacyPublicLivechat) { - this.messaging.publicLivechatGlobal.publicLivechat.legacyPublicLivechat.addMessage(legacyMessage); - } - - if (options && options.prepend) { - this.messaging.publicLivechatGlobal.livechatButtonView.update({ - messages: replace([message, ...this.messaging.publicLivechatGlobal.livechatButtonView.messages]), - }); - } else { - this.messaging.publicLivechatGlobal.livechatButtonView.update({ - messages: replace([...this.messaging.publicLivechatGlobal.livechatButtonView.messages, message]), - }); - } - }, /** * @private */ @@ -138,16 +96,6 @@ const LivechatButton = Widget.extend({ this.messaging.publicLivechatGlobal.livechatButtonView.update({ chatWindow: clear() }); utils.set_cookie('im_livechat_session', "", -1); // remove cookie }, - /** - * @private - */ - _loadQWebTemplate() { - return session.rpc('/im_livechat/load_templates').then(function (templates) { - for (let template of templates) { - QWeb.add_template(template); - } - }); - }, /** * @private */ @@ -302,7 +250,7 @@ const LivechatButton = Widget.extend({ */ _sendWelcomeMessage() { if (this.messaging.publicLivechatGlobal.livechatButtonView.defaultMessage) { - this._addMessage({ + this.messaging.publicLivechatGlobal.livechatButtonView.addMessage({ id: '_welcome', attachment_ids: [], author_id: [ diff --git a/addons/im_livechat/static/src/legacy/widgets/public_livechat_window/public_livechat_window.js b/addons/im_livechat/static/src/legacy/widgets/public_livechat_window/public_livechat_window.js index 77ccad96424..0dd1efe2c1d 100644 --- a/addons/im_livechat/static/src/legacy/widgets/public_livechat_window/public_livechat_window.js +++ b/addons/im_livechat/static/src/legacy/widgets/public_livechat_window/public_livechat_window.js @@ -32,13 +32,10 @@ const PublicLivechatWindow = Widget.extend({ * @param {Widget} parent * @param {Messaging} messaging * @param {@im_livechat/legacy/models/public_livechat} thread - * @param {Object} options - * @param {string} options.titleColor */ - init(parent, messaging, thread, options) { + init(parent, messaging, thread) { this._super(parent); this.messaging = messaging; - this.options = options; this._debouncedOnScroll = _.debounce(this._onScroll.bind(this), 100); }, @@ -75,8 +72,8 @@ const PublicLivechatWindow = Widget.extend({ if (this.messaging.publicLivechatGlobal.livechatButtonView.headerBackgroundColor) { this.$('.o_thread_window_header').css('background-color', this.messaging.publicLivechatGlobal.livechatButtonView.headerBackgroundColor); } - if (this.options.titleColor) { - this.$('.o_thread_window_header').css('color', this.options.titleColor); + if (this.messaging.publicLivechatGlobal.livechatButtonView.titleColor) { + this.$('.o_thread_window_header').css('color', this.messaging.publicLivechatGlobal.livechatButtonView.titleColor); } }, diff --git a/addons/im_livechat/static/src/models/livechat_button_view.js b/addons/im_livechat/static/src/models/livechat_button_view.js index 3fcaf91eb8a..eed3d6bc1dd 100644 --- a/addons/im_livechat/static/src/models/livechat_button_view.js +++ b/addons/im_livechat/static/src/models/livechat_button_view.js @@ -1,13 +1,73 @@ /** @odoo-module **/ +import PublicLivechatMessage from '@im_livechat/legacy/models/public_livechat_message'; + import { registerModel } from '@mail/model/model_core'; import { attr, many, one } from '@mail/model/model_field'; -import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { clear, insertAndReplace, replace } from '@mail/model/model_field_command'; registerModel({ name: 'LivechatButtonView', identifyingFields: ['publicLivechatGlobalOwner'], recordMethods: { + /** + * @param {Object} data + * @param {Object} [options={}] + */ + addMessage(data, options) { + const legacyMessage = new PublicLivechatMessage(this, this.messaging, data); + + const hasAlreadyMessage = _.some(this.messages, function (msg) { + return legacyMessage.getID() === msg.id; + }); + if (hasAlreadyMessage) { + return; + } + const message = this.messaging.models['PublicLivechatMessage'].insert({ + data, + id: data.id, + legacyPublicLivechatMessage: legacyMessage, + }); + + if (this.messaging.publicLivechatGlobal.publicLivechat && this.messaging.publicLivechatGlobal.publicLivechat.legacyPublicLivechat) { + this.messaging.publicLivechatGlobal.publicLivechat.legacyPublicLivechat.addMessage(legacyMessage); + } + + if (options && options.prepend) { + this.update({ + messages: replace([message, ...this.messages]), + }); + } else { + this.update({ + messages: replace([...this.messages, message]), + }); + } + }, + /** + * See '_chatbotSaveSession'. + * + * We retrieve the livechat uuid from the session cookie since the livechat Widget is not yet + * initialized when we restore the chatbot state. + * + * We also clear any older keys that store a previously saved chatbot session. + * (In that case we clear the actual browser's local storage, we don't use the localStorage + * object as it does not allow browsing existing keys, see 'local_storage.js'.) + */ + chatbotRestoreSession() { + const browserLocalStorage = window.localStorage; + if (browserLocalStorage && browserLocalStorage.length) { + for (let i = 0; i < browserLocalStorage.length; i++) { + const key = browserLocalStorage.key(i); + if (key.startsWith('im_livechat.chatbot.state.uuid_') && key !== this.chatbotSessionCookieKey) { + browserLocalStorage.removeItem(key); + } + } + } + const chatbotState = localStorage.getItem(this.chatbotSessionCookieKey); + if (chatbotState) { + this.chatbot.update({ currentStep: insertAndReplace({ data: this.localStorageChatbotState._chatbotCurrentStep }) }); + } + }, /** * @private * @returns {string} @@ -213,12 +273,14 @@ registerModel({ inverse: 'livechatButtonViewOwner', isCausal: true, }), + chatbotNextStepTimeout: attr(), chatbotSessionCookieKey: attr({ compute: '_computeChatbotSessionCookieKey', }), chatbotState: attr({ compute: '_computeChatbotState', }), + chatbotWelcomeMessageTimeout: attr(), chatWindow: one('PublicLivechatWindow', { inverse: 'livechatButtonViewOwner', isCausal: true, diff --git a/addons/im_livechat/static/src/models/public_livechat.js b/addons/im_livechat/static/src/models/public_livechat.js index 844166361e7..70efa97a0d7 100644 --- a/addons/im_livechat/static/src/models/public_livechat.js +++ b/addons/im_livechat/static/src/models/public_livechat.js @@ -3,7 +3,7 @@ import PublicLivechat from '@im_livechat/legacy/models/public_livechat'; import { registerModel } from '@mail/model/model_core'; -import { attr, many, one } from '@mail/model/model_field'; +import { attr, one } from '@mail/model/model_field'; import { clear, insertAndReplace } from '@mail/model/model_field_command'; registerModel({ @@ -97,7 +97,6 @@ registerModel({ readonly: true, required: true, }), - messages: many('PublicLivechatMessage'), name: attr({ compute: '_computeName', }), diff --git a/addons/im_livechat/static/src/models/public_livechat_global.js b/addons/im_livechat/static/src/models/public_livechat_global.js index 7300b053cbe..5828175186f 100644 --- a/addons/im_livechat/static/src/models/public_livechat_global.js +++ b/addons/im_livechat/static/src/models/public_livechat_global.js @@ -4,6 +4,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, one } from '@mail/model/model_field'; import { clear, insertAndReplace } from '@mail/model/model_field_command'; +import { qweb } from 'web.core'; import utils from 'web.utils'; registerModel({ @@ -28,6 +29,12 @@ registerModel({ }, }, recordMethods: { + async loadQWebTemplate() { + const templates = await this.messaging.rpc({ route: '/im_livechat/load_templates' }); + for (const template of templates) { + qweb.add_template(template); + } + }, /** * @private * @returns {FieldCommand} diff --git a/addons/im_livechat/static/src/models/public_livechat_global_notification_handler.js b/addons/im_livechat/static/src/models/public_livechat_global_notification_handler.js index ca25f5c54c5..e3bdedb03e7 100644 --- a/addons/im_livechat/static/src/models/public_livechat_global_notification_handler.js +++ b/addons/im_livechat/static/src/models/public_livechat_global_notification_handler.js @@ -65,7 +65,7 @@ registerModel({ return; } notificationData.body = utils.Markup(notificationData.body); - this.messaging.publicLivechatGlobal.livechatButtonView.widget._addMessage(notificationData); + this.messaging.publicLivechatGlobal.livechatButtonView.addMessage(notificationData); if (this.messaging.publicLivechatGlobal.publicLivechat.isFolded || !this.messaging.publicLivechatGlobal.livechatButtonView.chatWindow.legacyChatWindow._publicLivechatView.isAtBottom()) { this.messaging.publicLivechatGlobal.publicLivechat.update({ unreadCounter: increment() }); } diff --git a/addons/im_livechat/static/src/models/public_livechat_message.js b/addons/im_livechat/static/src/models/public_livechat_message.js index e0853e88b87..8a92f022229 100644 --- a/addons/im_livechat/static/src/models/public_livechat_message.js +++ b/addons/im_livechat/static/src/models/public_livechat_message.js @@ -7,6 +7,7 @@ registerModel({ name: 'PublicLivechatMessage', identifyingFields: ['id'], fields: { + data: attr(), id: attr({ readonly: true, required: true, diff --git a/addons/im_livechat/static/src/models/public_livechat_window.js b/addons/im_livechat/static/src/models/public_livechat_window.js index 95eb56ad1da..4f61034a4b1 100644 --- a/addons/im_livechat/static/src/models/public_livechat_window.js +++ b/addons/im_livechat/static/src/models/public_livechat_window.js @@ -15,7 +15,6 @@ registerModel({ this.livechatButtonViewOwner.widget, this.messaging, this.messaging.publicLivechatGlobal.publicLivechat.legacyPublicLivechat, - { titleColor: this.livechatButtonViewOwner.titleColor }, ), }); }, diff --git a/addons/website_livechat/static/src/legacy/website_livechat_chatbot_test_script.js b/addons/website_livechat/static/src/legacy/website_livechat_chatbot_test_script.js index 47ff9e09c1c..0e9a369719f 100644 --- a/addons/website_livechat/static/src/legacy/website_livechat_chatbot_test_script.js +++ b/addons/website_livechat/static/src/legacy/website_livechat_chatbot_test_script.js @@ -44,7 +44,7 @@ const LivechatButtonTestChatbot = LivechatButton.extend({ * @override */ willStart: function () { - return this._loadQWebTemplate(); + return this.messaging.publicLivechatGlobal.loadQWebTemplate(); }, /**