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 b2d7a94a776..914488e002b 100644 --- a/addons/im_livechat/static/src/legacy/public_livechat_chatbot.js +++ b/addons/im_livechat/static/src/legacy/public_livechat_chatbot.js @@ -7,7 +7,7 @@ import time from 'web.time'; import utils from 'web.utils'; import LivechatButton from '@im_livechat/legacy/widgets/livechat_button'; -import { clear } from '@mail/model/model_field_command'; +import { clear, insertAndReplace } from '@mail/model/model_field_command'; const _t = core._t; const QWeb = core.qweb; @@ -52,19 +52,14 @@ const QWeb = core.qweb; const superResult = await this._super(...arguments); if (this.messaging.livechatButtonView.rule && !!this.messaging.livechatButtonView.rule.chatbot) { - this.messaging.livechatButtonView.update({ isChatbot: true }); - this.messaging.livechatButtonView.update({ chatbotState: 'init' }); + // noop } else if (this.messaging.livechatButtonView.history !== null && this.messaging.livechatButtonView.history.length === 0) { - this.messaging.livechatButtonView.update({ livechatInit: await session.rpc('/im_livechat/init', {channel_id: this.options.channel_id}) }); - if (this.messaging.livechatButtonView.livechatInit.rule.chatbot) { - this.messaging.livechatButtonView.update({ isChatbot: true }); - this.messaging.livechatButtonView.update({ chatbotState: 'welcome' }); - } + this.messaging.livechatButtonView.update({ livechatInit: await session.rpc('/im_livechat/init', {channel_id: this.messaging.livechatButtonView.channelId}) }); } else if (this.messaging.livechatButtonView.history !== null && this.messaging.livechatButtonView.history.length !== 0) { const sessionCookie = utils.get_cookie('im_livechat_session'); if (sessionCookie) { - const sessionKey = 'im_livechat.chatbot.state.uuid_' + JSON.parse(sessionCookie).uuid; - if (localStorage.getItem(sessionKey)) { + this.messaging.livechatButtonView.update({ sessionCookie }); + if (localStorage.getItem(this.messaging.livechatButtonView.sessionCookieKey)) { this.messaging.livechatButtonView.update({ isChatbot: true }); this.messaging.livechatButtonView.update({ chatbotState: 'restore_session' }); } @@ -74,14 +69,11 @@ const QWeb = core.qweb; if (this.messaging.livechatButtonView.chatbotState === 'init') { // we landed on a website page where a channel rule is configured to run a chatbot.script // -> initialize necessary state - this.messaging.livechatButtonView.update({ - chatbot: this.messaging.livechatButtonView.rule.chatbot, - }); if (this.messaging.livechatButtonView.rule.chatbot_welcome_steps && this.messaging.livechatButtonView.rule.chatbot_welcome_steps.length !== 0) { - this.messaging.livechatButtonView.update({ - chatbotCurrentStep: this.messaging.livechatButtonView.chatbot.chatbot_welcome_steps[ - this.messaging.livechatButtonView.chatbot.chatbot_welcome_steps.length - 1 - ], + this.messaging.livechatButtonView.chatbot.update({ + currentStep: insertAndReplace({ + data: this.messaging.livechatButtonView.chatbot.lastWelcomeStep, + }), }); } } else if (this.messaging.livechatButtonView.chatbotState === 'welcome') { @@ -93,13 +85,11 @@ const QWeb = core.qweb; utils.set_cookie('im_livechat_auto_popup', '', -1); this.messaging.livechatButtonView.update({ history: clear() }); this.messaging.livechatButtonView.update({ rule: this.messaging.livechatButtonView.livechatInit.rule }); - this.messaging.livechatButtonView.update({ chatbot: this.messaging.livechatButtonView.livechatInit.rule.chatbot }); - this.messaging.livechatButtonView.update({ isChatbot: true }); this.messaging.livechatButtonView.update({ isChatbotBatchWelcomeMessages: true }); } else if (this.messaging.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(utils.get_cookie('im_livechat_session')); + this._chatbotRestoreSession(); } return superResult; @@ -148,7 +138,7 @@ const QWeb = core.qweb; } else { this._chatbotSetIsTyping(); this.nextStepTimeout = setTimeout( - this._chatbotTriggerNextStep.bind(this), this.messaging.livechatButtonView.chatbotMessageDelay); + this._chatbotTriggerNextStep.bind(this), this.messaging.livechatButtonView.chatbot.messageDelay); } } }, @@ -176,7 +166,7 @@ const QWeb = core.qweb; const postedWelcomeMessages = await session.rpc('/chatbot/post_welcome_steps', { channel_uuid: this.messaging.livechatButtonView.livechat.getUUID(), - chatbot_script_id: this.messaging.livechatButtonView.chatbot.chatbot_script_id, + chatbot_script_id: this.messaging.livechatButtonView.chatbot.data.chatbot_script_id, }); const welcomeMessagesIds = welcomeMessages.map(welcomeMessage => welcomeMessage._id); @@ -225,7 +215,7 @@ const QWeb = core.qweb; $composerTextField.off('keydown', this.chatbotInputKeyDownHandler); } - if (this.messaging.livechatButtonView.chatbotCurrentStep.chatbot_step_type === 'free_input_multi') { + if (this.messaging.livechatButtonView.chatbot.currentStep.data.chatbot_step_type === 'free_input_multi') { this.chatbotInputKeyDownHandler = this._onChatbotInputKeyDown.bind(this); $composerTextField.on('keydown', this.chatbotInputKeyDownHandler); } @@ -237,7 +227,11 @@ const QWeb = core.qweb; * @private */ _chatbotEndScript() { - if (this.messaging.livechatButtonView.chatbotCurrentStep && this.messaging.livechatButtonView.chatbotCurrentStep.conversation_closed) { + if ( + this.messaging.livechatButtonView.chatbot.currentStep && + this.messaging.livechatButtonView.chatbot.currentStep.data && + this.messaging.livechatButtonView.chatbot.currentStep.data.conversation_closed + ) { // don't touch anything if the user has closed the conversation, let the chat window // handle the display return; @@ -257,9 +251,9 @@ const QWeb = core.qweb; * @private */ _chatbotDisplayRestartButton() { - return this.messaging.livechatButtonView.isChatbot && (!this.messaging.livechatButtonView.chatbotCurrentStep || - (this.messaging.livechatButtonView.chatbotCurrentStep.chatbot_step_type !== 'forward_operator' || - !this.messaging.livechatButtonView.chatbotCurrentStep.chatbot_operator_found)); + return this.messaging.livechatButtonView.isChatbot && (!this.messaging.livechatButtonView.chatbot.currentStep || + (this.messaging.livechatButtonView.chatbot.currentStep.data.chatbot_step_type !== 'forward_operator' || + !this.messaging.livechatButtonView.chatbot.currentStep.data.chatbot_operator_found)); }, /** * Works as a hook since other modules can add their own step types. @@ -272,7 +266,7 @@ const QWeb = core.qweb; 'question_email', 'free_input_single', 'free_input_multi', - ].includes(this.messaging.livechatButtonView.chatbotCurrentStep.chatbot_step_type); + ].includes(this.messaging.livechatButtonView.chatbot.currentStep.data.chatbot_step_type); }, /** * Processes the step, depending on the current state of the script and the author of the last @@ -304,21 +298,21 @@ const QWeb = core.qweb; _chatbotProcessStep() { if (this._chatbotShouldEndScript()) { this._chatbotEndScript(); - } else if (this.messaging.livechatButtonView.chatbotCurrentStep.chatbot_step_type === 'forward_operator' - && this.messaging.livechatButtonView.chatbotCurrentStep.chatbot_operator_found) { + } else if (this.messaging.livechatButtonView.chatbot.currentStep.data.chatbot_step_type === 'forward_operator' + && this.messaging.livechatButtonView.chatbot.currentStep.data.chatbot_operator_found) { this._chatbotEnableInput(); } else if (this._chatbotIsExpectingUserInput()) { if (this._isLastMessageFromCustomer()) { // user has already typed a message in -> trigger next step this._chatbotSetIsTyping(); this.nextStepTimeout = setTimeout( - this._chatbotTriggerNextStep.bind(this), this.messaging.livechatButtonView.chatbotMessageDelay); + this._chatbotTriggerNextStep.bind(this), this.messaging.livechatButtonView.chatbot.messageDelay); } else { this._chatbotEnableInput(); } } else { let triggerNextStep = true; - if (this.messaging.livechatButtonView.chatbotCurrentStep.chatbot_step_type === 'question_selection') { + if (this.messaging.livechatButtonView.chatbot.currentStep.data.chatbot_step_type === 'question_selection') { if (!this._isLastMessageFromCustomer()) { // if there is no last message or if the last message is from the bot // -> don't trigger the next step, we are waiting for the user to pick an option @@ -327,7 +321,7 @@ const QWeb = core.qweb; } if (triggerNextStep) { - let nextStepDelay = this.messaging.livechatButtonView.chatbotMessageDelay; + let nextStepDelay = this.messaging.livechatButtonView.chatbot.messageDelay; if (this.messaging.livechatButtonView.chatWindow.$('.o_livechat_chatbot_typing').length !== 0) { // special case where we already have a "is typing" message displayed // can happen when the previous step did not trigger any message posted from the bot @@ -359,25 +353,22 @@ const QWeb = core.qweb; * * @private */ - _chatbotRestoreSession(sessionCookie) { - const sessionKey = 'im_livechat.chatbot.state.uuid_' + JSON.parse(sessionCookie).uuid; + _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 !== sessionKey) { + if (key.startsWith('im_livechat.chatbot.state.uuid_') && key !== this.messaging.livechatButtonView.sessionCookieKey) { browserLocalStorage.removeItem(key); } } } - let chatbotState = localStorage.getItem(sessionKey); + let chatbotState = localStorage.getItem(this.messaging.livechatButtonView.sessionCookieKey); if (chatbotState) { - chatbotState = JSON.parse(chatbotState); - this.messaging.livechatButtonView.update({ isChatbot: true }); - this.messaging.livechatButtonView.update({ chatbot: chatbotState._chatbot }); - this.messaging.livechatButtonView.update({ chatbotCurrentStep: chatbotState._chatbotCurrentStep }); + this.messaging.livechatButtonView.update({ localStorageChatbotState: JSON.parse(chatbotState) }); + this.messaging.livechatButtonView.chatbot.update({ currentStep: insertAndReplace({ data: this.messaging.livechatButtonView.localStorageChatbotState._chatbotCurrentStep }) }); } }, /** @@ -392,8 +383,8 @@ const QWeb = core.qweb; _chatbotSaveSession() { const chatUuid = this.messaging.livechatButtonView.livechat.toData().uuid; localStorage.setItem('im_livechat.chatbot.state.uuid_' + chatUuid, JSON.stringify({ - '_chatbot': this.messaging.livechatButtonView.chatbot, - '_chatbotCurrentStep': this.messaging.livechatButtonView.chatbotCurrentStep, + '_chatbot': this.messaging.livechatButtonView.chatbot.data, + '_chatbotCurrentStep': this.messaging.livechatButtonView.chatbot.currentStep.data, })); }, /** @@ -415,13 +406,13 @@ const QWeb = core.qweb; 'chatbotImageSrc': `/im_livechat/operator/${ this.messaging.livechatButtonView.livechat.getOperatorPID()[0] }/avatar`, - 'chatbotName': this.messaging.livechatButtonView.chatbot.chatbot_name, + 'chatbotName': this.messaging.livechatButtonView.chatbot.name, 'isWelcomeMessage': isWelcomeMessage, })) ); this.messaging.livechatButtonView.chatWindow.scrollToBottom(); - }, this.messaging.livechatButtonView.chatbotMessageDelay / 3), + }, this.messaging.livechatButtonView.chatbot.messageDelay / 3), }); }, /** @@ -439,21 +430,21 @@ const QWeb = core.qweb; * @private */ _chatbotShouldEndScript() { - if (this.messaging.livechatButtonView.chatbotCurrentStep.conversation_closed) { + if (this.messaging.livechatButtonView.chatbot.currentStep.data.conversation_closed) { return true; } - if (this.messaging.livechatButtonView.chatbotCurrentStep.chatbot_step_is_last && - (this.messaging.livechatButtonView.chatbotCurrentStep.chatbot_step_type !== 'forward_operator' || - !this.messaging.livechatButtonView.chatbotCurrentStep.chatbot_operator_found) + if (this.messaging.livechatButtonView.chatbot.currentStep.data.chatbot_step_is_last && + (this.messaging.livechatButtonView.chatbot.currentStep.data.chatbot_step_type !== 'forward_operator' || + !this.messaging.livechatButtonView.chatbot.currentStep.data.chatbot_operator_found) ) { - if (this.messaging.livechatButtonView.chatbotCurrentStep.chatbot_step_type === 'question_email' - && !this.messaging.livechatButtonView.chatbotCurrentStep.is_email_valid + if (this.messaging.livechatButtonView.chatbot.currentStep.data.chatbot_step_type === 'question_email' + && !this.messaging.livechatButtonView.chatbot.currentStep.data.is_email_valid ) { // email is not (yet) valid, let the user answer / try again return false; } else if ( (this._chatbotIsExpectingUserInput() || - this.messaging.livechatButtonView.chatbotCurrentStep.chatbot_step_type === 'question_selection') && + this.messaging.livechatButtonView.chatbot.currentStep.data.chatbot_step_type === 'question_selection') && this.messaging.livechatButtonView.messages.length !== 0 ) { const lastMessage = this.messaging.livechatButtonView.messages[this.messaging.livechatButtonView.messages.length - 1]; @@ -489,7 +480,7 @@ const QWeb = core.qweb; }); if (emailValidResult.success) { - this.messaging.livechatButtonView.chatbotCurrentStep.is_email_valid = true; + this.messaging.livechatButtonView.chatbot.currentStep.data.is_email_valid = true; this._chatbotSaveSession(); return true; @@ -511,7 +502,11 @@ const QWeb = core.qweb; */ async _chatbotTriggerNextStep() { let triggerNextStep = true; - if (this.messaging.livechatButtonView.chatbotCurrentStep && this.messaging.livechatButtonView.chatbotCurrentStep.chatbot_step_type === 'question_email') { + if ( + this.messaging.livechatButtonView.chatbot.currentStep && + this.messaging.livechatButtonView.chatbot.currentStep.data && + this.messaging.livechatButtonView.chatbot.currentStep.data.chatbot_step_type === 'question_email' + ) { triggerNextStep = await this._chatbotValidateEmail(); } @@ -521,7 +516,7 @@ const QWeb = core.qweb; const nextStep = await session.rpc('/chatbot/step/trigger', { channel_uuid:this.messaging.livechatButtonView.livechat.getUUID(), - chatbot_script_id: this.messaging.livechatButtonView.chatbot.chatbot_script_id, + chatbot_script_id: this.messaging.livechatButtonView.chatbot.data.chatbot_script_id, }); if (nextStep) { @@ -529,12 +524,12 @@ const QWeb = core.qweb; this._chatbotAddMessage(nextStep.chatbot_posted_message); } - this.messaging.livechatButtonView.update({ chatbotCurrentStep: nextStep.chatbot_step }); + this.messaging.livechatButtonView.chatbot.update({ currentStep: insertAndReplace({ data: nextStep.chatbot_step }) }); this._chatbotProcessStep(); } else { // did not find next step -> end the script - this.messaging.livechatButtonView.chatbotCurrentStep['chatbot_step_is_last'] = true; + this.messaging.livechatButtonView.chatbot.currentStep.data.chatbot_step_is_last = true; this._renderMessages(); this._chatbotEndScript(); } @@ -578,8 +573,12 @@ const QWeb = core.qweb; _askFeedback() { this._super(...arguments); - if (this.messaging.livechatButtonView.chatbotCurrentStep) { - this.messaging.livechatButtonView.chatbotCurrentStep.conversation_closed = true; + if ( + this.messaging.livechatButtonView.chatbot && + this.messaging.livechatButtonView.chatbot.currentStep && + this.messaging.livechatButtonView.chatbot.currentStep.data + ) { + this.messaging.livechatButtonView.chatbot.currentStep.data.conversation_closed = true; this._chatbotSaveSession(); } this.messaging.livechatButtonView.chatWindow.$('.o_livechat_chatbot_main_restart').addClass('d-none'); @@ -607,7 +606,13 @@ const QWeb = core.qweb; } }); - if (this.messaging.livechatButtonView.chatbotCurrentStep && this.messaging.livechatButtonView.messages && this.messaging.livechatButtonView.messages.length !== 0) { + if ( + this.messaging.livechatButtonView.chatbot && + this.messaging.livechatButtonView.chatbot.currentStep && + this.messaging.livechatButtonView.chatbot.currentStep.data && + this.messaging.livechatButtonView.messages && + this.messaging.livechatButtonView.messages.length !== 0 + ) { this._chatbotProcessStep(); } }); @@ -620,7 +625,7 @@ const QWeb = core.qweb; const parameters = this._super(...arguments); if (this.messaging.livechatButtonView.isChatbot) { - parameters.chatbot_script_id = this.messaging.livechatButtonView.chatbot.chatbot_script_id; + parameters.chatbot_script_id = this.messaging.livechatButtonView.chatbot.data.chatbot_script_id; } return parameters; @@ -670,7 +675,11 @@ const QWeb = core.qweb; const superArguments = arguments; const superMethod = this._super; - if (this.messaging.livechatButtonView.isChatbot && this.messaging.livechatButtonView.chatbotCurrentStep) { + if ( + this.messaging.livechatButtonView.isChatbot && + this.messaging.livechatButtonView.chatbot.currentStep && + this.messaging.livechatButtonView.chatbot.currentStep.data + ) { await this._chatbotPostWelcomeMessages(); } @@ -679,18 +688,22 @@ const QWeb = core.qweb; return; } - if (this.messaging.livechatButtonView.isChatbot && this.messaging.livechatButtonView.chatbotCurrentStep) { + if ( + this.messaging.livechatButtonView.isChatbot && + this.messaging.livechatButtonView.chatbot.currentStep && + this.messaging.livechatButtonView.chatbot.currentStep.data + ) { if ( - this.messaging.livechatButtonView.chatbotCurrentStep.chatbot_step_type === 'forward_operator' && - this.messaging.livechatButtonView.chatbotCurrentStep.chatbot_operator_found + this.messaging.livechatButtonView.chatbot.currentStep.data.chatbot_step_type === 'forward_operator' && + this.messaging.livechatButtonView.chatbot.currentStep.data.chatbot_operator_found ) { return; // operator has taken over the conversation, let them speak - } else if (this.messaging.livechatButtonView.chatbotCurrentStep.chatbot_step_type === 'free_input_multi') { + } else if (this.messaging.livechatButtonView.chatbot.currentStep.data.chatbot_step_type === 'free_input_multi') { this._debouncedChatbotAwaitUserInput(); } else if (!this._chatbotShouldEndScript()) { this._chatbotSetIsTyping(); this.nextStepTimeout = setTimeout( - this._chatbotTriggerNextStep.bind(this), this.messaging.livechatButtonView.chatbotMessageDelay); + this._chatbotTriggerNextStep.bind(this), this.messaging.livechatButtonView.chatbot.messageDelay); } else { this._chatbotEndScript(); } @@ -707,7 +720,7 @@ const QWeb = core.qweb; if (this.messaging.livechatButtonView.isChatbot) { this._sendWelcomeChatbotMessage( 0, - this.messaging.livechatButtonView.isChatbotBatchWelcomeMessages ? 0 : this.messaging.livechatButtonView.chatbotMessageDelay, + this.messaging.livechatButtonView.isChatbotBatchWelcomeMessages ? 0 : this.messaging.livechatButtonView.chatbot.messageDelay, ); } else { this._super(...arguments); @@ -735,8 +748,8 @@ const QWeb = core.qweb; * @private */ _sendWelcomeChatbotMessage(stepIndex, welcomeMessageDelay) { - const chatbotStep = this.messaging.livechatButtonView.chatbot.chatbot_welcome_steps[stepIndex]; - this.messaging.livechatButtonView.update({ chatbotCurrentStep: chatbotStep }); + const chatbotStep = this.messaging.livechatButtonView.chatbot.welcomeSteps[stepIndex]; + this.messaging.livechatButtonView.chatbot.update({ currentStep: insertAndReplace({ data: chatbotStep }) }); if (chatbotStep.chatbot_step_message) { this._addMessage({ @@ -754,7 +767,7 @@ const QWeb = core.qweb; }); } - if (stepIndex + 1 < this.messaging.livechatButtonView.chatbot.chatbot_welcome_steps.length) { + if (stepIndex + 1 < this.messaging.livechatButtonView.chatbot.welcomeSteps.length) { if (welcomeMessageDelay !== 0) { this._chatbotSetIsTyping(true); } @@ -764,7 +777,7 @@ const QWeb = core.qweb; this._renderMessages(); }, welcomeMessageDelay); } else { - if (this.messaging.livechatButtonView.chatbotCurrentStep.chatbot_step_type === 'forward_operator') { + if (this.messaging.livechatButtonView.chatbot.currentStep.data.chatbot_step_type === 'forward_operator') { // special case when the last welcome message is a forward to an operator // we need to save the welcome messages before continuing the script // indeed, if there are no operator available, the script will continue @@ -802,23 +815,24 @@ const QWeb = core.qweb; const postedMessage = await session.rpc('/chatbot/restart', { channel_uuid: this.messaging.livechatButtonView.livechat.getUUID(), - chatbot_script_id: this.messaging.livechatButtonView.chatbot.chatbot_script_id, + chatbot_script_id: this.messaging.livechatButtonView.chatbot.data.chatbot_script_id, }); if (postedMessage) { this._chatbotAddMessage(postedMessage); } - this.messaging.livechatButtonView.update({ chatbotCurrentStep: clear() }); + this.messaging.livechatButtonView.chatbot.update({ currentStep: clear() }); this._chatbotSetIsTyping(); this.nextStepTimeout = setTimeout( - this._chatbotTriggerNextStep.bind(this), this.messaging.livechatButtonView.chatbotMessageDelay); + this._chatbotTriggerNextStep.bind(this), this.messaging.livechatButtonView.chatbot.messageDelay); }, _onChatbotInputKeyDown() { if ( - this.messaging.livechatButtonView.chatbotCurrentStep && - this.messaging.livechatButtonView.chatbotCurrentStep.chatbot_step_type === 'free_input_multi' + this.messaging.livechatButtonView.chatbot.currentStep && + this.messaging.livechatButtonView.chatbot.currentStep.data && + this.messaging.livechatButtonView.chatbot.currentStep.data.chatbot_step_type === 'free_input_multi' ) { this._debouncedChatbotAwaitUserInput(); } @@ -863,7 +877,7 @@ const QWeb = core.qweb; } const messageId = stepMessage.getID(); stepMessage.setChatbotStepAnswerId(selectedAnswer); - this.messaging.livechatButtonView.chatbotCurrentStep['chatbot_selected_answer_id'] = selectedAnswer; + this.messaging.livechatButtonView.chatbot.currentStep.data.chatbot_selected_answer_id = selectedAnswer; this._renderMessages(); this._chatbotSaveSession(); diff --git a/addons/im_livechat/static/src/legacy/website_livechat_message_chatbot.js b/addons/im_livechat/static/src/legacy/website_livechat_message_chatbot.js index 98b3ac46351..6e0f6fcec54 100644 --- a/addons/im_livechat/static/src/legacy/website_livechat_message_chatbot.js +++ b/addons/im_livechat/static/src/legacy/website_livechat_message_chatbot.js @@ -20,10 +20,6 @@ WebsiteLivechatMessage.include({ this._super(...arguments); if (parent.messaging.livechatButtonView.isChatbot) { - this._chatbotId = parent.messaging.livechatButtonView.chatbot.chatbot_script_id; - this._chatbotName = parent.messaging.livechatButtonView.chatbot.chatbot_name; - this._chatbotOperatorPartnerId = parent.messaging.livechatButtonView.chatbot.chatbot_operator_partner_id; - this._chatbotStepId = data.chatbot_script_step_id; this._chatbotStepAnswers = data.chatbot_step_answers; this._chatbotStepAnswerId = data.chatbot_selected_answer_id; 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 eabcb581033..38d65ab3e8b 100644 --- a/addons/im_livechat/static/src/legacy/widgets/livechat_button.js +++ b/addons/im_livechat/static/src/legacy/widgets/livechat_button.js @@ -36,6 +36,7 @@ const LivechatButton = Widget.extend({ this.options = _.defaults(this.messaging.publicLivechatOptions || {}); }, async willStart() { + this.messaging.livechatButtonView.update({ widget: this }); const cookie = utils.get_cookie('im_livechat_session'); if (cookie) { const channel = JSON.parse(cookie); @@ -46,7 +47,7 @@ const LivechatButton = Widget.extend({ message.body = utils.Markup(message.body); } } else { - const result = await session.rpc('/im_livechat/init', {channel_id: this.options.channel_id}); + const result = await session.rpc('/im_livechat/init', {channel_id: this.messaging.livechatButtonView.channelId}); if (!result.available_for_me) { return Promise.reject(); } @@ -332,7 +333,7 @@ const LivechatButton = Widget.extend({ */ _prepareGetSessionParameters() { return { - channel_id: this.options.channel_id, + channel_id: this.messaging.livechatButtonView.channelId, anonymous_name: this.messaging.livechatButtonView.defaultUsername, previous_operator_id: this._get_previous_operator_id(), }; diff --git a/addons/im_livechat/static/src/models/chatbot.js b/addons/im_livechat/static/src/models/chatbot.js new file mode 100644 index 00000000000..0b6e276a5c9 --- /dev/null +++ b/addons/im_livechat/static/src/models/chatbot.js @@ -0,0 +1,71 @@ +/** @odoo-module **/ + +import { registerModel } from '@mail/model/model_core'; +import { attr, one } from '@mail/model/model_field'; +import { clear } from '@mail/model/model_field_command'; + +registerModel({ + name: 'Chatbot', + identifyingFields: ['livechatButtonViewOwner'], + recordMethods: { + /** + * @private + * @returns {string} + */ + _computeName() { + return this.data.name; + }, + /** + * @private + * @returns {Array|FieldCommand} + */ + _computeLastWelcomeStep() { + if (!this.welcomeSteps) { + return clear(); + } + return this.welcomeSteps[this.welcomeSteps.length - 1]; + }, + /** + * @private + * @returns {integer|FieldCommand} + */ + _computeMessageDelay() { + if (this.livechatButtonViewOwner.isWebsiteLivechatChatbotFlow) { + return 100; + } + return clear(); + }, + /** + * @private + * @returns {Array|FieldCommand} + */ + _computeWelcomeSteps() { + return this.data.chatbot_welcome_steps; + }, + }, + fields: { + data: attr(), + currentStep: one('ChatbotStep', { + inverse: 'chabotOwner', + isCausal: true, + }), + lastWelcomeStep: attr({ + compute: '_computeLastWelcomeStep', + }), + livechatButtonViewOwner: one('LivechatButtonView', { + inverse: 'chatbot', + readonly: true, + required: true, + }), + name: attr({ + compute: '_computeName', + }), + messageDelay: attr({ + compute: '_computeMessageDelay', + default: 3500, // in milliseconds + }), + welcomeSteps: attr({ + compute: '_computeWelcomeSteps', + }), + }, +}); diff --git a/addons/im_livechat/static/src/models/chatbot_step.js b/addons/im_livechat/static/src/models/chatbot_step.js new file mode 100644 index 00000000000..722f45a437a --- /dev/null +++ b/addons/im_livechat/static/src/models/chatbot_step.js @@ -0,0 +1,17 @@ +/** @odoo-module **/ + +import { registerModel } from '@mail/model/model_core'; +import { attr, one } from '@mail/model/model_field'; + +registerModel({ + name: 'ChatbotStep', + identifyingFields: ['chabotOwner'], + fields: { + chabotOwner: one('Chatbot', { + inverse: 'currentStep', + readonly: true, + required: true, + }), + data: attr(), + }, +}); 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 fec2acf2c03..64104489dd3 100644 --- a/addons/im_livechat/static/src/models/livechat_button_view.js +++ b/addons/im_livechat/static/src/models/livechat_button_view.js @@ -1,8 +1,8 @@ /** @odoo-module **/ import { registerModel } from '@mail/model/model_core'; -import { attr } from '@mail/model/model_field'; -import { clear } from '@mail/model/model_field_command'; +import { attr, one } from '@mail/model/model_field'; +import { clear, insertAndReplace } from '@mail/model/model_field_command'; registerModel({ name: 'LivechatButtonView', @@ -27,9 +27,35 @@ registerModel({ /** * @returns {string} */ - _computeButtonTextColor() { + _computeButtonTextColor() { return this.messaging.publicLivechatOptions.button_text_color; }, + /** + * @private + * @returns {integer} + */ + _computeChannelId() { + return this.messaging.publicLivechatOptions.channel_id; + }, + /** + * @private + * @returns {FieldCommand} + */ + _computeChatbot() { + if (this.isTestChatbot) { + return insertAndReplace({ data: this.testChatbotData.chatbot }); + } + if (this.chatbotState === 'init') { + return insertAndReplace({ data: this.rule.chatbot }); + } + if (this.chatbotState === 'welcome') { + return insertAndReplace({ data: this.livechatInit.rule.chatbot }); + } + if (this.chatbotState === 'restore_session' && this.localStorageChatbotState) { + return insertAndReplace({ data: this.localStorageChatbotState._chatbot }); + } + return clear(); + }, /** * @private * @returns {integer|FieldCommand} @@ -40,6 +66,19 @@ registerModel({ } return clear(); }, + /** + * @private + * @returns {string|FieldCommand} + */ + _computeChatbotState() { + if (this.rule && !!this.rule.chatbot) { + return 'init'; + } + if (this.livechatInit && this.livechatInit.rule.chatbot) { + return 'welcome'; + } + return clear(); + }, /** * @private * @returns {integer} @@ -92,6 +131,28 @@ registerModel({ } return this.env._t("Ask something ..."); }, + /** + * @private + * @returns {boolean} + */ + _computeIsChatbot() { + if (this.isTestChatbot) { + return true; + } + if (this.rule && this.rule.chatbot) { + return true; + } + if (this.livechatInit && this.livechatInit.rule.chatbot) { + return true; + } + if (this.chatbotState === 'welcome') { + return true; + } + if (this.localStorageChatbotState) { + return true; + } + return clear(); + }, /** * @private * @returns {string} @@ -102,6 +163,15 @@ registerModel({ } return this.messaging.publicLivechatServerUrl; }, + /** + * @returns {string|FieldCommand} + */ + _computeSessionCookieKey() { + if (!this.sessionCookie) { + return clear(); + } + return 'im_livechat.chatbot.state.uuid_' + JSON.parse(this.sessionCookie).uuid; + }, /** * @private * @returns {string} @@ -121,13 +191,17 @@ registerModel({ buttonTextColor: attr({ compute: '_computeButtonTextColor', }), - chatbot: attr(), - chatbotCurrentStep: attr(), - chatbotMessageDelay: attr({ - compute: '_computeChatbotMessageDelay', - default: 3500, // in milliseconds + channelId: attr({ + compute: '_computeChannelId', + }), + chatbot: one('Chatbot', { + compute: '_computeChatbot', + inverse: 'livechatButtonViewOwner', + isCausal: true, + }), + chatbotState: attr({ + compute: '_computeChatbotState', }), - chatbotState: attr(), // livechat window chatWindow: attr({ default: null, @@ -152,6 +226,7 @@ registerModel({ default: '', }), isChatbot: attr({ + compute: '_computeIsChatbot', default: false, }), isChatbotBatchWelcomeMessages: attr({ @@ -163,6 +238,9 @@ registerModel({ isOpeningChat: attr({ default: false, }), + isTestChatbot: attr({ + default: false, + }), isTypingTimeout: attr(), isWebsiteLivechatChatbotFlow: attr({ default: false, @@ -172,6 +250,7 @@ registerModel({ default: null, }), livechatInit: attr(), + localStorageChatbotState: attr(), messages: attr({ default: [], }), @@ -179,8 +258,14 @@ registerModel({ serverUrl: attr({ compute: '_computeServerUrl', }), + sessionCookie: attr(), + sessionCookieKey: attr({ + compute: '_computeSessionCookieKey', + }), + testChatbotData: attr(), titleColor: attr({ compute: '_computeTitleColor', }), + widget: attr(), }, }); 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 9c704a972a7..c9c6f0f342b 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 @@ -6,6 +6,8 @@ import utils from 'web.utils'; import LivechatButton from '@im_livechat/legacy/widgets/livechat_button'; import WebsiteLivechat from '@im_livechat/legacy/models/website_livechat'; +import { insertAndReplace } from '@mail/model/model_field_command'; + /** * Override of the LivechatButton to create a testing environment for the chatbot script. * @@ -26,14 +28,14 @@ const LivechatButtonTestChatbot = LivechatButton.extend({ 'auto_popup_timer': 0, }, }); - this.messaging.livechatButtonView.update({ chatbot: chatbotData.chatbot }); - this.messaging.livechatButtonView.update({ - chatbotCurrentStep: this.messaging.livechatButtonView.chatbot.chatbot_welcome_steps[ - this.messaging.livechatButtonView.chatbot.chatbot_welcome_steps.length - 1 - ], + this.messaging.livechatButtonView.update({ isTestChatbot: true }); + this.messaging.livechatButtonView.update({ testChatbotData: chatbotData.chatbot }); + this.messaging.livechatButtonView.chatbot.update({ + currentStep: insertAndReplace({ + data: this.messaging.livechatButtonView.chatbot.lastWelcomeStep, + }), }); - this._channelData = chatbotData.channel; - this.messaging.livechatButtonView.update({ isChatbot: true }); + this._channelData = this.messaging.livechatButtonView.testChatbotData.channel; }, /**