[IMP] im_livechat, *: Refactor JS Public Livechat (step 2)
*: website_livechat This commit is a step towards refactoring the JS of public livechat, so that it reuses the same architecture as the code of Discuss. This implies code that uses JS models and OWL components. Task-2888734 closes odoo/odoo#94090 Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
This commit is contained in:
@@ -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,
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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',
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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/**/*',
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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(),
|
||||
});
|
||||
@@ -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);
|
||||
|
||||
@@ -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('<p>' + message.content + '</p>'),
|
||||
|
||||
Reference in New Issue
Block a user