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 9474d82f776..ce1d595a99f 100644 --- a/addons/im_livechat/static/src/legacy/public_livechat_chatbot.js +++ b/addons/im_livechat/static/src/legacy/public_livechat_chatbot.js @@ -7,6 +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'; const _t = core._t; const QWeb = core.qweb; @@ -54,17 +55,17 @@ const QWeb = core.qweb; this.chatbotState = null; - if (this._rule && !!this._rule.chatbot) { + if (this.messaging.livechatButtonView.rule && this.messaging.livechatButtonView.rule.chatbot) { this.messaging.livechatButtonView.update({ isChatbot: true }); this.chatbotState = 'init'; - } else if (this._history !== null && this._history.length === 0) { - this._livechatInit = await session.rpc('/im_livechat/init', {channel_id: this.options.channel_id}); + } 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._livechatInit.rule.chatbot) { + if (this.messaging.livechatButtonView.livechatInit.rule.chatbot) { this.messaging.livechatButtonView.update({ isChatbot: true }); this.chatbotState = 'welcome'; } - } else if (this._history !== null && this._history.length !== 0) { + } 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; @@ -78,10 +79,12 @@ const QWeb = core.qweb; if (this.chatbotState === 'init') { // we landed on a website page where a channel rule is configured to run a chatbot.script // -> initialize necessary state - this._chatbot = this._rule.chatbot; - if (this._rule.chatbot_welcome_steps && this._rule.chatbot_welcome_steps.length !== 0) { - this._chatbotCurrentStep = this._chatbot.chatbot_welcome_steps[ - this._chatbot.chatbot_welcome_steps.length - 1]; + 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._chatbotCurrentStep = this.messaging.livechatButtonView.chatbot.chatbot_welcome_steps[ + this.messaging.livechatButtonView.chatbot.chatbot_welcome_steps.length - 1]; } } else if (this.chatbotState === 'welcome') { // we landed on a website page and a chatbot script was initialized on a previous one @@ -90,11 +93,11 @@ const QWeb = core.qweb; // -> initialize necessary state // -> batch welcome message (see '_sendWelcomeChatbotMessage') utils.set_cookie('im_livechat_auto_popup', '', -1); - this._history = null; - this._rule = this._livechatInit.rule; - this._chatbot = this._livechatInit.rule.chatbot; + 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._chatbotBatchWelcomeMessages = true; + this.messaging.livechatButtonView.update({ isChatbotBatchWelcomeMessages: true }); } else if (this.chatbotState === 'restore_session') { // we landed on a website page and a chatbot script is currently running // -> restore the user's session (see '_chatbotRestoreSession') @@ -119,7 +122,7 @@ const QWeb = core.qweb; message.body = utils.Markup(message.body); this._addMessage(message, options); if (this.messaging.livechatButtonView.chatWindow.isFolded() || !this.messaging.livechatButtonView.chatWindow.isAtBottom()) { - this._livechat.incrementUnreadCounter(); + this.messaging.livechatButtonView.livechat.incrementUnreadCounter(); } if (!options || !options.skipRenderMessages) { @@ -174,13 +177,15 @@ const QWeb = core.qweb; } const postedWelcomeMessages = await session.rpc('/chatbot/post_welcome_steps', { - channel_uuid: this._livechat.getUUID(), - chatbot_script_id: this._chatbot.chatbot_script_id, + channel_uuid: this.messaging.livechatButtonView.livechat.getUUID(), + chatbot_script_id: this.messaging.livechatButtonView.chatbot.chatbot_script_id, }); const welcomeMessagesIds = welcomeMessages.map(welcomeMessage => welcomeMessage._id); - this._messages = this._messages.filter((message) => { - !welcomeMessagesIds.includes(message._id); + this.messaging.livechatButtonView.update({ + messages: this.messaging.livechatButtonView.messages.filter((message) => { + !welcomeMessagesIds.includes(message._id); + }), }); postedWelcomeMessages.reverse(); @@ -368,7 +373,7 @@ const QWeb = core.qweb; if (chatbotState) { chatbotState = JSON.parse(chatbotState); this.messaging.livechatButtonView.update({ isChatbot: true }); - this._chatbot = chatbotState._chatbot; + this.messaging.livechatButtonView.update({ chatbot: chatbotState._chatbot }); this._chatbotCurrentStep = chatbotState._chatbotCurrentStep; } }, @@ -382,9 +387,9 @@ const QWeb = core.qweb; * @private */ _chatbotSaveSession() { - const chatUuid = this._livechat.toData().uuid; + const chatUuid = this.messaging.livechatButtonView.livechat.toData().uuid; localStorage.setItem('im_livechat.chatbot.state.uuid_' + chatUuid, JSON.stringify({ - '_chatbot': this._chatbot, + '_chatbot': this.messaging.livechatButtonView.chatbot, '_chatbotCurrentStep': this._chatbotCurrentStep, })); }, @@ -394,23 +399,27 @@ const QWeb = core.qweb; * @private */ _chatbotSetIsTyping(isWelcomeMessage=false) { - if (this.isTypingTimeout) { + if (this.messaging.livechatButtonView.isTypingTimeout) { clearTimeout(this.isTypingTimeout); } this._chatbotDisableInput(''); - this.isTypingTimeout = setTimeout(() => { - this.messaging.livechatButtonView.chatWindow.$('.o_mail_thread_content').append( - $(QWeb.render('im_livechat.legacy.chatbot.is_typing_message', { - 'chatbotImageSrc': `/im_livechat/operator/${this._livechat.getOperatorPID()[0]}/avatar`, - 'chatbotName': this._chatbot.chatbot_name, - 'isWelcomeMessage': isWelcomeMessage, - })) - ); + this.messaging.livechatButtonView.update({ + isTypingTimeout: setTimeout(() => { + this.messaging.livechatButtonView.chatWindow.$('.o_mail_thread_content').append( + $(QWeb.render('im_livechat.legacy.chatbot.is_typing_message', { + 'chatbotImageSrc': `/im_livechat/operator/${ + this.messaging.livechatButtonView.livechat.getOperatorPID()[0] + }/avatar`, + 'chatbotName': this.messaging.livechatButtonView.chatbot.chatbot_name, + 'isWelcomeMessage': isWelcomeMessage, + })) + ); - this.messaging.livechatButtonView.chatWindow.scrollToBottom(); - }, this._chatbotMessageDelay / 3); + this.messaging.livechatButtonView.chatWindow.scrollToBottom(); + }, this._chatbotMessageDelay / 3), + }); }, /** * Helper method that checks if the script should be ended or not. @@ -432,11 +441,13 @@ const QWeb = core.qweb; && !this._chatbotCurrentStep.is_email_valid) { // email is not (yet) valid, let the user answer / try again return false; - } else if ((this._chatbotIsExpectingUserInput() || - this._chatbotCurrentStep.chatbot_step_type === 'question_selection') && - this._messages.length !== 0) { - const lastMessage = this._messages[this._messages.length - 1]; - if (lastMessage.getAuthorID() !== this._livechat.getOperatorPID()[0]) { + } else if ( + (this._chatbotIsExpectingUserInput() || + this._chatbotCurrentStep.chatbot_step_type === 'question_selection') && + this.messaging.livechatButtonView.messages.length !== 0 + ) { + const lastMessage = this.messaging.livechatButtonView.messages[this.messaging.livechatButtonView.messages.length - 1]; + if (lastMessage.getAuthorID() !== this.messaging.livechatButtonView.livechat.getOperatorPID()[0]) { // we are on the last step of the script, expect a user input and the user has // already answered // -> end the script @@ -464,7 +475,7 @@ const QWeb = core.qweb; */ async _chatbotValidateEmail() { let emailValidResult = await session.rpc('/chatbot/step/validate_email', { - channel_uuid: this._livechat.getUUID(), + channel_uuid: this.messaging.livechatButtonView.livechat.getUUID(), }); if (emailValidResult.success) { @@ -499,8 +510,8 @@ const QWeb = core.qweb; } const nextStep = await session.rpc('/chatbot/step/trigger', { - channel_uuid: this._livechat.getUUID(), - chatbot_script_id: this._chatbot.chatbot_script_id, + channel_uuid:this.messaging.livechatButtonView.livechat.getUUID(), + chatbot_script_id: this.messaging.livechatButtonView.chatbot.chatbot_script_id, }); if (nextStep) { @@ -523,13 +534,13 @@ const QWeb = core.qweb; return nextStep; }, /** - * Returns the 'this._messages' filtered on our special 'welcome' ones. + * Returns the 'this.messaging.livechatButtonView.messages' filtered on our special 'welcome' ones. * See '_sendWelcomeChatbotMessage'. * * @private */ _getWelcomeMessages() { - return this._messages.filter((message) => { + return this.messaging.livechatButtonView.messages.filter((message) => { return message._id && typeof message._id === 'string' && message._id.startsWith('_welcome_'); }); }, @@ -539,8 +550,8 @@ const QWeb = core.qweb; * @private */ _isLastMessageFromCustomer() { - const lastMessage = this._messages.length !== 0 ? this._messages[this._messages.length - 1] : null; - return lastMessage && lastMessage.getAuthorID() !== this._livechat.getOperatorPID()[0]; + const lastMessage = this.messaging.livechatButtonView.messages.length !== 0 ? this.messaging.livechatButtonView.messages[this.messaging.livechatButtonView.messages.length - 1] : null; + return lastMessage && lastMessage.getAuthorID() !== this.messaging.livechatButtonView.livechat.getOperatorPID()[0]; }, //-------------------------------------------------------------------------- @@ -582,7 +593,7 @@ const QWeb = core.qweb; } }); - if (this._chatbotCurrentStep && this._messages && this._messages.length !== 0) { + if (this._chatbotCurrentStep && this.messaging.livechatButtonView.messages && this.messaging.livechatButtonView.messages.length !== 0) { this._chatbotProcessStep(); } }); @@ -595,7 +606,7 @@ const QWeb = core.qweb; const parameters = this._super(...arguments); if (this.messaging.livechatButtonView.isChatbot) { - parameters.chatbot_script_id = this._chatbot.chatbot_script_id; + parameters.chatbot_script_id = this.messaging.livechatButtonView.chatbot.chatbot_script_id; } return parameters; @@ -615,8 +626,8 @@ const QWeb = core.qweb; this.messaging.livechatButtonView.chatWindow.$('.o_livechat_chatbot_main_restart').on('click', this._onChatbotRestartScript.bind(this)); - if (this._messages.length !== 0) { - const lastMessage = this._messages[this._messages.length - 1]; + if (this.messaging.livechatButtonView.messages.length !== 0) { + const lastMessage = this.messaging.livechatButtonView.messages[this.messaging.livechatButtonView.messages.length - 1]; const stepAnswers = lastMessage.getChatbotStepAnswers(); if (stepAnswers && stepAnswers.length !== 0 && !lastMessage.getChatbotStepAnswerId()) { this._chatbotDisableInput(_t('Select an option above')); @@ -650,7 +661,7 @@ const QWeb = core.qweb; } return superMethod.apply(this, superArguments).then(() => { - if (this._isChatbotRedirecting) { + if (this.messaging.livechatButtonView.isChatbotRedirecting) { return; } @@ -680,7 +691,7 @@ const QWeb = core.qweb; if (this.messaging.livechatButtonView.isChatbot) { this._sendWelcomeChatbotMessage( 0, - this._chatbotBatchWelcomeMessages ? 0 : this._chatbotMessageDelay, + this.messaging.livechatButtonView.isChatbotBatchWelcomeMessages ? 0 : this._chatbotMessageDelay, ); } else { this._super(...arguments); @@ -708,7 +719,7 @@ const QWeb = core.qweb; * @private */ _sendWelcomeChatbotMessage(stepIndex, welcomeMessageDelay) { - const chatbotStep = this._chatbot.chatbot_welcome_steps[stepIndex]; + const chatbotStep = this.messaging.livechatButtonView.chatbot.chatbot_welcome_steps[stepIndex]; this._chatbotCurrentStep = chatbotStep; if (chatbotStep.chatbot_step_message) { @@ -716,18 +727,18 @@ const QWeb = core.qweb; id: '_welcome_' + stepIndex, is_discussion: true, // important for css style -> we only want white background for chatbot attachment_ids: [], - author_id: this._livechat.getOperatorPID(), + author_id: this.messaging.livechatButtonView.livechat.getOperatorPID(), body: utils.Markup(chatbotStep.chatbot_step_message), chatbot_script_step_id: chatbotStep.chatbot_script_step_id, chatbot_step_answers: chatbotStep.chatbot_step_answers, date: time.datetime_to_str(new Date()), model: "mail.channel", message_type: "comment", - res_id: this._livechat.getID(), + res_id: this.messaging.livechatButtonView.livechat.getID(), }); } - if (stepIndex + 1 < this._chatbot.chatbot_welcome_steps.length) { + if (stepIndex + 1 < this.messaging.livechatButtonView.chatbot.chatbot_welcome_steps.length) { if (welcomeMessageDelay !== 0) { this._chatbotSetIsTyping(true); } @@ -774,8 +785,8 @@ const QWeb = core.qweb; } const postedMessage = await session.rpc('/chatbot/restart', { - channel_uuid: this._livechat.getUUID(), - chatbot_script_id: this._chatbot.chatbot_script_id, + channel_uuid: this.messaging.livechatButtonView.livechat.getUUID(), + chatbot_script_id: this.messaging.livechatButtonView.chatbot.chatbot_script_id, }); if (postedMessage) { @@ -797,7 +808,7 @@ const QWeb = core.qweb; /** * Saves the selected chatbot.script.answer onto our chatbot.message. - * Will update the state of the related message (in this._messages) to set the selected option + * Will update the state of the related message (in this.messaging.livechatButtonView.messages) to set the selected option * as well which will in turn adapt the display to not show options anymore. * * This method also handles an optional redirection link placed on the chatbot.script.answer and @@ -814,14 +825,14 @@ const QWeb = core.qweb; const selectedAnswer = $target.data('chatbotStepAnswerId'); const redirectLink = $target.data('chatbotStepRedirectLink'); - this._isChatbotRedirecting = !!redirectLink; + this.messaging.livechatButtonView.update({ isChatbotRedirecting: !!redirectLink }); await this._sendMessage({ content: $target.text().trim(), }); let stepMessage = null; - this._messages.forEach((message) => { + for (const message of this.messaging.livechatButtonView.messages) { // we do NOT want to use a 'find' here because we want the LAST message that respects // this condition. // indeed, if you restart the script, you can have multiple messages with the same step id, @@ -831,7 +842,7 @@ const QWeb = core.qweb; if (message.getChatbotStepId() === stepId) { stepMessage = message; } - }); + } const messageId = stepMessage.getID(); stepMessage.setChatbotStepAnswerId(selectedAnswer); this._chatbotCurrentStep['chatbot_selected_answer_id'] = selectedAnswer; @@ -839,7 +850,7 @@ const QWeb = core.qweb; this._chatbotSaveSession(); const saveAnswerPromise = session.rpc('/chatbot/answer/save', { - channel_uuid: this._livechat.getUUID(), + channel_uuid: this.messaging.livechatButtonView.livechat.getUUID(), message_id: messageId, selected_answer_id: selectedAnswer, }); 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 1ad25dfcc55..98b3ac46351 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,9 +20,9 @@ WebsiteLivechatMessage.include({ this._super(...arguments); if (parent.messaging.livechatButtonView.isChatbot) { - this._chatbotId = parent._chatbot.chatbot_script_id; - this._chatbotName = parent._chatbot.chatbot_name; - this._chatbotOperatorPartnerId = parent._chatbot.chatbot_operator_partner_id; + 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; 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 15d8f9b7814..05e063588ce 100644 --- a/addons/im_livechat/static/src/legacy/widgets/livechat_button.js +++ b/addons/im_livechat/static/src/legacy/widgets/livechat_button.js @@ -13,6 +13,8 @@ import WebsiteLivechat from '@im_livechat/legacy/models/website_livechat'; import WebsiteLivechatMessage from '@im_livechat/legacy/models/website_livechat_message'; import WebsiteLivechatWindow from '@im_livechat/legacy/models/website_livechat_window'; +import { clear } from '@mail/model/model_field_command'; + const _t = core._t; const QWeb = core.qweb; @@ -31,41 +33,39 @@ const LivechatButton = Widget.extend({ init(parent, messaging) { this._super(parent); this.messaging = messaging; - this.options = _.defaults(this.messaging.publicLivechatOptions || {}, { - default_username: _t("Visitor"), - }); - - this._history = null; - // livechat model - this._livechat = null; - this._messages = []; - this._serverURL = this.messaging.publicLivechatServerUrl; + this.options = _.defaults(this.messaging.publicLivechatOptions || {}); }, async willStart() { const cookie = utils.get_cookie('im_livechat_session'); if (cookie) { const channel = JSON.parse(cookie); - this._history = await session.rpc('/mail/chat_history', {uuid: channel.uuid, limit: 100}); - this._history.reverse().forEach(message => { message.body = utils.Markup(message.body); }); + const history = await session.rpc('/mail/chat_history', {uuid: channel.uuid, limit: 100}); + history.reverse(); + this.messaging.livechatButtonView.update({ history }); + for (const message of this.messaging.livechatButtonView.history) { + message.body = utils.Markup(message.body); + } } else { const result = await session.rpc('/im_livechat/init', {channel_id: this.options.channel_id}); if (!result.available_for_me) { return Promise.reject(); } - this._rule = result.rule; + this.messaging.livechatButtonView.update({ rule: result.rule }); } return this._loadQWebTemplate(); }, start() { this.$el.text(this.messaging.livechatButtonView.buttonText); - if (this._history) { - this._history.forEach(m => this._addMessage(m)); + if (this.messaging.livechatButtonView.history) { + for (const m of this.messaging.livechatButtonView.history) { + this._addMessage(m); + } this._openChat(); - } else if (!config.device.isMobile && this._rule.action === 'auto_popup') { + } else if (!config.device.isMobile && this.messaging.livechatButtonView.rule.action === 'auto_popup') { const autoPopupCookie = utils.get_cookie('im_livechat_auto_popup'); if (!autoPopupCookie || JSON.parse(autoPopupCookie)) { this.messaging.livechatButtonView.update({ - autoOpenChatTimeout: setTimeout(this._openChat.bind(this), this._rule.auto_popup_timer * 1000), + autoOpenChatTimeout: setTimeout(this._openChat.bind(this), this.messaging.livechatButtonView.rule.auto_popup_timer * 1000), }); } } @@ -98,25 +98,29 @@ const LivechatButton = Widget.extend({ */ _addMessage(data, options) { options = Object.assign({}, this.options, options, { - serverURL: this._serverURL, + serverURL: this.messaging.livechatButtonView.serverURL, }); const message = new WebsiteLivechatMessage(this, data, options); - const hasAlreadyMessage = _.some(this._messages, function (msg) { + const hasAlreadyMessage = _.some(this.messaging.livechatButtonView.messages, function (msg) { return message.getID() === msg.getID(); }); if (hasAlreadyMessage) { return; } - if (this._livechat) { - this._livechat.addMessage(message); + if (this.messaging.livechatButtonView.livechat) { + this.messaging.livechatButtonView.livechat.addMessage(message); } if (options && options.prepend) { - this._messages.unshift(message); + this.messaging.livechatButtonView.update({ + messages: [message, ...this.messaging.livechatButtonView.messages], + }); } else { - this._messages.push(message); + this.messaging.livechatButtonView.update({ + messages: [...this.messaging.livechatButtonView.messages, message], + }); } }, /** @@ -125,7 +129,7 @@ const LivechatButton = Widget.extend({ _askFeedback() { this.messaging.livechatButtonView.chatWindow.$('.o_thread_composer input').prop('disabled', true); - const feedback = new Feedback(this, this._livechat); + const feedback = new Feedback(this, this.messaging.livechatButtonView.livechat); this.messaging.livechatButtonView.chatWindow.replaceContentWith(feedback); feedback.on('send_message', this, this._sendMessage); @@ -147,20 +151,20 @@ const LivechatButton = Widget.extend({ _handleNotification({ payload, type }) { switch (type) { case 'im_livechat.history_command': { - if (payload.id !== this._livechat._id) { + if (payload.id !== this.messaging.livechatButtonView.livechat._id) { return; } const cookie = utils.get_cookie(LIVECHAT_COOKIE_HISTORY); const history = cookie ? JSON.parse(cookie) : []; session.rpc('/im_livechat/history', { - pid: this._livechat.getOperatorPID()[0], - channel_uuid: this._livechat.getUUID(), + pid: this.messaging.livechatButtonView.livechat.getOperatorPID()[0], + channel_uuid: this.messaging.livechatButtonView.livechat.getUUID(), page_history: history, }); return; } case 'mail.channel.partner/typing_status': { - if (payload.channel_id !== this._livechat._id) { + if (payload.channel_id !== this.messaging.livechatButtonView.livechat._id) { return; } const partnerID = payload.partner_id; @@ -169,31 +173,31 @@ const LivechatButton = Widget.extend({ return; } if (payload.is_typing) { - this._livechat.registerTyping({ partnerID }); + this.messaging.livechatButtonView.livechat.registerTyping({ partnerID }); } else { - this._livechat.unregisterTyping({ partnerID }); + this.messaging.livechatButtonView.livechat.unregisterTyping({ partnerID }); } return; } case 'mail.channel/new_message': { - if (payload.id !== this._livechat._id) { + if (payload.id !== this.messaging.livechatButtonView.livechat._id) { return; } const notificationData = payload.message; // If message from notif is already in chatter messages, stop handling - if (this._messages.some(message => message.getID() === notificationData.id)) { + if (this.messaging.livechatButtonView.messages.some(message => message.getID() === notificationData.id)) { return; } notificationData.body = utils.Markup(notificationData.body); this._addMessage(notificationData); if (this.messaging.livechatButtonView.chatWindow.isFolded() || !this.messaging.livechatButtonView.chatWindow.isAtBottom()) { - this._livechat.incrementUnreadCounter(); + this.messaging.livechatButtonView.livechat.incrementUnreadCounter(); } this._renderMessages(); return; } case 'mail.message/insert': { - const message = this._messages.find(message => message._id === payload.id); + const message = this.messaging.livechatButtonView.messages.find(message => message._id === payload.id); if (!message) { return; } @@ -222,13 +226,13 @@ const LivechatButton = Widget.extend({ } const cookie = utils.get_cookie('im_livechat_session'); let def; - this._openingChat = true; this.messaging.livechatButtonView.update({ isOpeningChat: true }); clearTimeout(this.messaging.livechatButtonView.autoOpenChatTimeout); if (cookie) { def = Promise.resolve(JSON.parse(cookie)); } else { - this._messages = []; // re-initialize messages cache + // re-initialize messages cache + this.messaging.livechatButtonView.update({ messages: clear() }); def = session.rpc( '/im_livechat/get_session', this._prepareGetSessionParameters(), @@ -253,19 +257,21 @@ const LivechatButton = Widget.extend({ console.warn(_t("No available collaborator, please try again later.")); } } else { - this._livechat = new WebsiteLivechat({ - parent: this, - data: livechatData + this.messaging.livechatButtonView.update({ + livechat: new WebsiteLivechat({ + parent: this, + data: livechatData + }), }); return this._openChatWindow().then(() => { - if (!this._history) { + if (!this.messaging.livechatButtonView.history) { this._sendWelcomeMessage(); } this._renderMessages(); - this.call('bus_service', 'addChannel', this._livechat.getUUID()); + this.call('bus_service', 'addChannel', this.messaging.livechatButtonView.livechat.getUUID()); this.call('bus_service', 'startPolling'); - utils.set_cookie('im_livechat_session', utils.unaccent(JSON.stringify(this._livechat.toData()), true), 60 * 60); + utils.set_cookie('im_livechat_session', utils.unaccent(JSON.stringify(this.messaging.livechatButtonView.livechat.toData()), true), 60 * 60); utils.set_cookie('im_livechat_auto_popup', JSON.stringify(false), 60 * 60); if (livechatData.operator_pid[0]) { // livechatData.operator_pid contains a tuple (id, name) @@ -312,7 +318,7 @@ const LivechatButton = Widget.extend({ titleColor: this.options.title_color, }; this.messaging.livechatButtonView.update({ - chatWindow: new WebsiteLivechatWindow(this, this._livechat, options), + chatWindow: new WebsiteLivechatWindow(this, this.messaging.livechatButtonView.livechat, options), }); return this.messaging.livechatButtonView.chatWindow.appendTo($('body')).then(() => { const cssProps = { bottom: 0 }; @@ -327,7 +333,7 @@ const LivechatButton = Widget.extend({ _prepareGetSessionParameters() { return { channel_id: this.options.channel_id, - anonymous_name: this.options.default_username, + anonymous_name: this.messaging.livechatButtonView.defaultUsername, previous_operator_id: this._get_previous_operator_id(), }; }, @@ -336,7 +342,7 @@ const LivechatButton = Widget.extend({ */ _renderMessages() { const shouldScroll = !this.messaging.livechatButtonView.chatWindow.isFolded() && this.messaging.livechatButtonView.chatWindow.isAtBottom(); - this._livechat.setMessages(this._messages); + this.messaging.livechatButtonView.livechat.setMessages(this.messaging.livechatButtonView.messages); this.messaging.livechatButtonView.chatWindow.render(); if (shouldScroll) { this.messaging.livechatButtonView.chatWindow.scrollToBottom(); @@ -348,9 +354,9 @@ const LivechatButton = Widget.extend({ * @return {Promise} */ _sendMessage(message) { - this._livechat._notifyMyselfTyping({ typing: false }); + this.messaging.livechatButtonView.livechat._notifyMyselfTyping({ typing: false }); return session - .rpc('/mail/chat_post', { uuid: this._livechat.getUUID(), message_content: message.content }) + .rpc('/mail/chat_post', { uuid: this.messaging.livechatButtonView.livechat.getUUID(), message_content: message.content }) .then((messageId) => { if (!messageId) { try { @@ -382,11 +388,11 @@ const LivechatButton = Widget.extend({ this._addMessage({ id: '_welcome', attachment_ids: [], - author_id: this._livechat.getOperatorPID(), + author_id: this.messaging.livechatButtonView.livechat.getOperatorPID(), body: this.messaging.livechatButtonView.defaultMessage, date: time.datetime_to_str(new Date()), model: "mail.channel", - res_id: this._livechat.getID(), + res_id: this.messaging.livechatButtonView.livechat.getID(), }, { prepend: true }); } }, @@ -402,7 +408,7 @@ const LivechatButton = Widget.extend({ _onCloseChatWindow(ev) { ev.stopPropagation(); const isComposerDisabled = this.messaging.livechatButtonView.chatWindow.$('.o_thread_composer input').prop('disabled'); - const shouldAskFeedback = !isComposerDisabled && this._messages.find(function (message) { + const shouldAskFeedback = !isComposerDisabled && this.messaging.livechatButtonView.messages.find(function (message) { return message.getID() !== '_welcome'; }); if (shouldAskFeedback) { @@ -441,7 +447,7 @@ const LivechatButton = Widget.extend({ */ _onSaveChatWindow(ev) { ev.stopPropagation(); - utils.set_cookie('im_livechat_session', utils.unaccent(JSON.stringify(this._livechat.toData()), true), 60 * 60); + utils.set_cookie('im_livechat_session', utils.unaccent(JSON.stringify(this.messaging.livechatButtonView.livechat.toData()), true), 60 * 60); }, /** * @private 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 366b51d51a6..baab3001281 100644 --- a/addons/im_livechat/static/src/models/livechat_button_view.js +++ b/addons/im_livechat/static/src/models/livechat_button_view.js @@ -27,6 +27,16 @@ registerModel({ } return this.env._t("How may I help you?"); }, + /** + * @private + * @returns {string} + */ + _computeDefaultUsername() { + if (this.messaging.publicLivechatOptions.default_username) { + return this.messaging.publicLivechatOptions.default_username; + } + return this.env._t("Visitor"); + }, /** * @private * @returns {string|FieldCommand} @@ -42,12 +52,23 @@ registerModel({ } return this.env._t("Ask something ..."); }, + /** + * @private + * @returns {string} + */ + _computeServerUrl() { + if (this.isChatbot) { + return this.messaging.publicLivechatServerUrlChatbot; + } + return this.messaging.publicLivechatServerUrl; + }, }, fields: { autoOpenChatTimeout: attr(), buttonText: attr({ compute: '_computeButtonText', }), + chatbot: attr(), // livechat window chatWindow: attr({ default: null, @@ -55,6 +76,12 @@ registerModel({ defaultMessage: attr({ compute: '_computeDefaultMessage', }), + defaultUsername: attr({ + compute: '_computeDefaultUsername', + }), + history: attr({ + default: null, + }), inputPlaceholder: attr({ compute: '_computeInputPlaceholder', default: '', @@ -62,8 +89,27 @@ registerModel({ isChatbot: attr({ default: false, }), + isChatbotBatchWelcomeMessages: attr({ + default: false, + }), + isChatbotRedirecting: attr({ + default: false, + }), isOpeningChat: attr({ default: false, }), + isTypingTimeout: attr(), + // livechat model + livechat: attr({ + default: null, + }), + livechatInit: attr(), + messages: attr({ + default: [], + }), + rule: attr(), + serverUrl: attr({ + compute: '_computeServerUrl', + }), }, }); diff --git a/addons/website_livechat/__manifest__.py b/addons/website_livechat/__manifest__.py index 15c0f40d257..d44a5235f9c 100644 --- a/addons/website_livechat/__manifest__.py +++ b/addons/website_livechat/__manifest__.py @@ -32,6 +32,7 @@ Allow website visitors to chat with the collaborators. This module also brings a 'website_livechat/static/src/legacy/public_livechat.js', 'website_livechat/static/src/legacy/website_livechat_chatbot_test_script.js', 'website_livechat/static/src/legacy/public_livechat.scss', + 'website_livechat/static/src/models/*.js', ], 'website.assets_editor': [ 'website_livechat/static/src/js/**/*', 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 3774ff0c345..9e9fa515150 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 @@ -20,16 +20,17 @@ const LivechatButtonTestChatbot = LivechatButton.extend({ init: function (parent, messaging, chatbotData) { this._super(...arguments); - this._rule = { - 'action': 'auto_popup', - 'auto_popup_timer': 0, - }; - this._chatbot = chatbotData.chatbot; - this._chatbotCurrentStep = this._chatbot.chatbot_welcome_steps[ - this._chatbot.chatbot_welcome_steps.length - 1]; + this.messaging.livechatButtonView.update({ + rule: { + 'action': 'auto_popup', + 'auto_popup_timer': 0, + }, + }); + this.messaging.livechatButtonView.update({ chatbot: chatbotData.chatbot }); + this._chatbotCurrentStep = this.messaging.livechatButtonView.chatbot.chatbot_welcome_steps[ + this.messaging.livechatButtonView.chatbot.chatbot_welcome_steps.length - 1]; this._channelData = chatbotData.channel; this.messaging.livechatButtonView.update({ isChatbot: true }); - this._serverURL = chatbotData.serverUrl; }, /** @@ -53,17 +54,19 @@ const LivechatButtonTestChatbot = LivechatButton.extend({ * @override */ _openChat: function () { - this._livechat = new WebsiteLivechat({ - parent: this, - data: this._channelData, + this.messaging.livechatButtonView.update({ + livechat: new WebsiteLivechat({ + parent: this, + data: this._channelData, + }), }); return this._openChatWindow().then(() => { this._sendWelcomeMessage(); this._renderMessages(); - this.call('bus_service', 'addChannel', this._livechat.getUUID()); + this.call('bus_service', 'addChannel', this.messaging.livechatButtonView.livechat.getUUID()); this.call('bus_service', 'startPolling'); - utils.set_cookie('im_livechat_session', utils.unaccent(JSON.stringify(this._livechat.toData()), true), 60 * 60); + utils.set_cookie('im_livechat_session', utils.unaccent(JSON.stringify(this.messaging.livechatButtonView.livechat.toData()), true), 60 * 60); this.messaging.livechatButtonView.update({ isOpeningChat: false }); }); }, @@ -88,6 +91,7 @@ publicWidget.registry.livechatChatbotTestScript = publicWidget.Widget.extend({ messaging.update({ isInPublicLivechat: true, isPublicLivechatAvailable: true, + publicLivechatServerUrlChatbot: this.$el.data().serverUrl, }); this.livechatButton = new LivechatButtonTestChatbot(this, messaging, this.$el.data()); this.livechatButton.appendTo(document.body); diff --git a/addons/website_livechat/static/src/models/messaging.js b/addons/website_livechat/static/src/models/messaging.js new file mode 100644 index 00000000000..92f4db61ebf --- /dev/null +++ b/addons/website_livechat/static/src/models/messaging.js @@ -0,0 +1,10 @@ +/** @odoo-module **/ + +import { addFields } from '@mail/model/model_core'; +import { attr } from '@mail/model/model_field'; +// ensure that the model definition is loaded before the patch +import '@mail/models/messaging'; + +addFields('Messaging', { + publicLivechatServerUrlChatbot: attr(), +}); diff --git a/addons/website_livechat/static/tests/tours/website_livechat_chatbot_flow.js b/addons/website_livechat/static/tests/tours/website_livechat_chatbot_flow.js index ab1ab18c314..b0cb9652c45 100644 --- a/addons/website_livechat/static/tests/tours/website_livechat_chatbot_flow.js +++ b/addons/website_livechat/static/tests/tours/website_livechat_chatbot_flow.js @@ -3,6 +3,8 @@ import tour from "web_tour.tour"; import LivechatButton from '@im_livechat/legacy/widgets/livechat_button'; +import { clear } from '@mail/model/model_field_command'; + LivechatButton.include({ /** * Let us make it a bit faster than the default delay (3500ms). @@ -23,7 +25,7 @@ LivechatButton.include({ * the thread and making it hard to write proper jQuery selectors in the tour. */ _onChatbotRestartScript: function () { - this._messages = []; + this.messaging.livechatButtonView.update({ messages: clear() }); this._renderMessages(); this._super(...arguments); diff --git a/addons/website_livechat/static/tests/tours/website_livechat_common.js b/addons/website_livechat/static/tests/tours/website_livechat_common.js index 795d66b390b..c92f50928dd 100644 --- a/addons/website_livechat/static/tests/tours/website_livechat_common.js +++ b/addons/website_livechat/static/tests/tours/website_livechat_common.js @@ -30,9 +30,9 @@ LivechatButton.include({ self._handleNotification({ type: 'mail.channel/new_message', payload: { - id: self._livechat._id, + id: self.messaging.livechatButtonView.livechat._id, message: { - id: self._messages.length + 1, + id: self.messaging.livechatButtonView.messages.length + 1, author_id: [0, 'Website Visitor Test'], email_from: 'Website Visitor Test', body: utils.Markup('

' + message.content + '

'),