[IMP] im_livechat, *: make JS models available in livechat external lib

This commit make messaging service available in the frontend and in
the livechat external lib bundle.

This is preparation to refactoring JS livechat to use models and OWL.

*: bus, mail, survey, web, website_livechat

Task-2870899

closes odoo/odoo#92786

Signed-off-by: Sébastien Theys (seb) <seb@odoo.com>
This commit is contained in:
Alexandre Kühn
2022-06-13 16:51:27 +02:00
parent 12dcc5f46e
commit 190feb8d6d
19 changed files with 221 additions and 53 deletions
+1
View File
@@ -17,6 +17,7 @@
'bus/static/src/js/crosstab_bus.js',
'bus/static/src/js/services/bus_service.js',
'bus/static/src/js/services/legacy/*.js',
'bus/static/src/js/*.js',
],
'web.qunit_suite_tests': [
'bus/static/tests/*.js',
+41
View File
@@ -50,6 +50,20 @@ Help your customers with this chat, and analyse their feedback.
'im_livechat/static/src/components/*/*',
'im_livechat/static/src/models/*.js',
],
'web.assets_frontend': [
'im_livechat/static/src/models/*.js',
'im_livechat/static/src/public/main.js',
'im_livechat/static/src/services/*.js',
'im_livechat/static/src/legacy/public_livechat_constants.js',
'im_livechat/static/src/legacy/public_livechat_history_tracking.js',
'im_livechat/static/src/legacy/models/*',
'im_livechat/static/src/legacy/widgets/*',
'im_livechat/static/src/legacy/widgets/*/*',
'im_livechat/static/src/legacy/public_livechat_chatbot.js',
'im_livechat/static/src/legacy/website_livechat_message_chatbot.js',
'im_livechat/static/src/legacy/public_livechat.scss',
'im_livechat/static/src/legacy/public_livechat_chatbot.scss',
],
'web.assets_backend': [
'im_livechat/static/src/js/im_livechat_channel_form_view.js',
'im_livechat/static/src/js/im_livechat_channel_form_controller.js',
@@ -189,6 +203,33 @@ Help your customers with this chat, and analyse their feedback.
'im_livechat/static/src/scss/im_livechat_bootstrap.scss',
'im_livechat/static/src/legacy/public_livechat.scss',
'im_livechat/static/src/legacy/public_livechat_chatbot.scss',
'web/static/src/core/utils/transitions.scss',
'mail/static/src/utils/*.js',
'mail/static/src/js/emojis.js',
'mail/static/src/component_hooks/*.js',
'mail/static/src/model/*.js',
'mail/static/src/models/*.js',
'im_livechat/static/src/models/*.js',
'mail/static/src/services/messaging_service.js',
# Framework JS
'bus/static/src/js/*.js',
'bus/static/src/js/services/bus_service.js',
'bus/static/src/js/services/legacy/legacy_bus_service.js',
'web/static/lib/luxon/luxon.js',
'web/static/src/core/**/*',
# FIXME: debug menu currently depends on webclient, once it doesn't we don't need to remove the contents of the debug folder
('remove', 'web/static/src/core/debug/**/*'),
'web/static/src/env.js',
'web/static/src/legacy/js/core/dialog.js',
'web/static/src/legacy/js/core/owl_dialog.js',
'web/static/src/legacy/js/core/misc.js',
'web/static/src/legacy/js/fields/field_utils.js',
'im_livechat/static/src/public/*.js',
'im_livechat/static/src/services/*.js',
]
},
'license': 'LGPL-3',
+1 -1
View File
@@ -45,7 +45,7 @@ class LivechatController(http.Controller):
username = kwargs.get("username", _("Visitor"))
channel = request.env['im_livechat.channel'].sudo().browse(channel_id)
info = channel.get_livechat_info(username=username)
return request.render('im_livechat.loader', {'info': info, 'web_session_required': True}, headers=[('Content-Type', 'application/javascript')])
return request.render('im_livechat.loader', {'info': info}, headers=[('Content-Type', 'application/javascript')])
@http.route('/im_livechat/init', type='json', auth="public", cors="*")
def livechat_init(self, channel_id):
@@ -28,9 +28,10 @@ const LivechatButton = Widget.extend({
events: {
'click': '_openChat'
},
init(parent, serverURL, options) {
init(parent, messaging) {
this._super(parent);
this.options = _.defaults(options || {}, {
this.messaging = messaging;
this.options = _.defaults(this.messaging.publicLivechatOptions || {}, {
input_placeholder: _t("Ask something ..."),
default_username: _t("Visitor"),
button_text: _t("Chat with one of our collaborators"),
@@ -43,7 +44,7 @@ const LivechatButton = Widget.extend({
// livechat window
this._chatWindow = null;
this._messages = [];
this._serverURL = serverURL;
this._serverURL = this.messaging.publicLivechatServerUrl;
},
async willStart() {
const cookie = utils.get_cookie('im_livechat_session');
@@ -0,0 +1,8 @@
/** @odoo-module **/
import { registerModel } from '@mail/model/model_core';
registerModel({
name: 'LivechatButtonView',
identifyingFields: ['messaging'],
});
@@ -1,11 +1,22 @@
/** @odoo-module **/
import { addFields } from '@mail/model/model_core';
import { many } from '@mail/model/model_field';
import { addFields, addRecordMethods, patchRecordMethods } from '@mail/model/model_core';
import { attr, many, one } from '@mail/model/model_field';
import { clear, insertAndReplace } from '@mail/model/model_field_command';
// ensure that the model definition is loaded before the patch
import '@mail/models/messaging';
addFields('Messaging', {
isInPublicLivechat: attr({
default: false,
}),
isPublicLivechatAvailable: attr({
default: false,
}),
livechatButtonView: one('LivechatButtonView', {
compute: '_computeLivechatButtonView',
isCausal: true,
}),
/**
* All pinned livechats that are known.
*/
@@ -13,4 +24,35 @@ addFields('Messaging', {
inverse: 'messagingAsPinnedLivechat',
readonly: true,
}),
publicLivechatOptions: attr({
default: {},
}),
publicLivechatServerUrl: attr({
default: '',
}),
});
addRecordMethods('Messaging', {
/**
* @private
* @returns {FieldCommand}
*/
_computeLivechatButtonView() {
if (this.isInPublicLivechat && this.isPublicLivechatAvailable) {
return insertAndReplace();
}
return clear();
},
});
patchRecordMethods('Messaging', {
/**
* @override
*/
_computeNotificationHandler() {
if (this.isInPublicLivechat) {
return clear();
}
return this._super();
},
});
@@ -6,6 +6,16 @@ import { insert, insertAndReplace } from '@mail/model/model_field_command';
import '@mail/models/messaging_initializer';
patchRecordMethods('MessagingInitializer', {
/**
* @override
*/
async performInitRpc() {
if (this.messaging.isInPublicLivechat) {
return {};
} else {
return this._super();
}
},
/**
* @override
* @param {Object} resUsersSettings
@@ -0,0 +1,26 @@
/** @odoo-module **/
import { publicLivechatService } from '@im_livechat/services/public_livechat_service';
import { isAvailable, options, serverUrl } from 'im_livechat.loaderData';
import { messagingService } from '@mail/services/messaging_service';
import { makeMessagingToLegacyEnv } from '@mail/utils/make_messaging_to_legacy_env';
import { registry } from '@web/core/registry';
const messagingValuesService = {
start() {
return {
isInPublicLivechat: true,
isPublicLivechatAvailable: isAvailable,
publicLivechatOptions: options,
publicLivechatServerUrl: serverUrl,
};
}
};
const serviceRegistry = registry.category('services');
serviceRegistry.add('messaging', messagingService);
serviceRegistry.add('messagingValues', messagingValuesService);
serviceRegistry.add('messaging_service_to_legacy_env', makeMessagingToLegacyEnv(owl.Component.env));
serviceRegistry.add('public_livechat_service', publicLivechatService);
@@ -0,0 +1,7 @@
odoo.define('web.session', function (require) {
const Session = require('web.Session');
const { serverUrl } = require('im_livechat.loaderData');
return new Session(undefined, serverUrl, { use_cors: true });
});
@@ -0,0 +1,16 @@
/** @odoo-module **/
import LivechatButton from '@im_livechat/legacy/widgets/livechat_button';
import rootWidget from 'root.widget';
export const publicLivechatService = {
dependencies: ['messaging'],
async start(env, { messaging: messagingService }) {
const messaging = await messagingService.get();
if (messaging.livechatButtonView) {
const livechatButton = new LivechatButton(rootWidget, messaging);
livechatButton.appendTo(document.body);
}
},
};
@@ -91,26 +91,12 @@
<template id="loader" name="Livechat : Javascript appending the livechat button">
<t t-translation="off">
window.addEventListener('load', function () {
<t t-if="web_session_required">
odoo.define('web.session', function (require) {
var Session = require('web.Session');
var modules = odoo._modules;
return new Session(undefined, "<t t-esc="info['server_url']"/>", {modules:modules, use_cors: true});
});
</t>
odoo.define('im_livechat.livesupport', function (require) {
<t t-if="info['available']" t-translation="off">
var rootWidget = require('root.widget');
var LivechatButton = require('@im_livechat/legacy/widgets/livechat_button')[Symbol.for("default")];
var button = new LivechatButton(
rootWidget,
"<t t-esc="info['server_url']"/>",
<t t-out="json.dumps(info.get('options', {}))"/>
);
button.appendTo(document.body);
window.livechat_button = button;
</t>
odoo.define('im_livechat.loaderData', function() {
return {
isAvailable: <t t-out="info['available']"/>,
serverUrl: "<t t-out="info['server_url']"/>",
options: <t t-out="json.dumps(info.get('options', {}))"/>,
};
});
});
</t>
+9
View File
@@ -108,6 +108,15 @@
'web/static/src/legacy/utils.js',
'web/static/src/legacy/xml/base.xml',
],
'web.assets_frontend': [
'mail/static/src/utils/*.js',
'mail/static/src/js/emojis.js',
'mail/static/src/js/utils.js',
'mail/static/src/component_hooks/*.js',
'mail/static/src/model/*.js',
'mail/static/src/models/*.js',
'mail/static/src/services/messaging_service.js',
],
'web._assets_primary_variables': [
'mail/static/src/scss/variables/primary_variables.scss',
],
+11 -2
View File
@@ -34,7 +34,9 @@ registerModel({
if (!this.exists()) {
return;
}
this.notificationHandler.start();
if (this.notificationHandler) {
this.notificationHandler.start();
}
this.update({ isInitialized: true });
this.initializedPromise.resolve();
},
@@ -291,6 +293,13 @@ registerModel({
part: '_chat',
});
},
/**
* @private
* @returns {FieldCommand}
*/
_computeNotificationHandler() {
return insertAndReplace();
},
/**
* @private
*/
@@ -428,7 +437,7 @@ registerModel({
readonly: true,
}),
notificationHandler: one('MessagingNotificationHandler', {
default: insertAndReplace(),
compute: '_computeNotificationHandler',
isCausal: true,
readonly: true,
}),
@@ -8,6 +8,14 @@ registerModel({
name: 'MessagingInitializer',
identifyingFields: ['messaging'],
recordMethods: {
/**
* @returns {Object}
*/
async performInitRpc() {
return await this.messaging.rpc({
route: '/mail/init_messaging',
}, { shadow: true });
},
/**
* Fetch messaging data initially to populate the store specifically for
* the current user. This includes pinned channels for instance.
@@ -35,9 +43,7 @@ registerModel({
});
this.messaging.device.start();
const discuss = this.messaging.discuss;
const data = await this.messaging.rpc({
route: '/mail/init_messaging',
}, { shadow: true });
const data = await this.performInitRpc();
if (!this.exists()) {
return;
}
@@ -114,7 +120,9 @@ registerModel({
this._initCommands();
}
// channels when the rest of messaging is ready
await this._initChannels(channels);
if (channels) {
await this._initChannels(channels);
}
if (!this.exists()) {
return;
}
@@ -279,9 +287,11 @@ registerModel({
currentUser: insert({ id: currentUserId }),
});
}
this.messaging.update({
partnerRoot: insert(this.messaging.models['Partner'].convertData(partner_root)),
});
if (partner_root) {
this.messaging.update({
partnerRoot: insert(this.messaging.models['Partner'].convertData(partner_root)),
});
}
},
/**
* @private
@@ -390,7 +390,7 @@ registerModel({
},
/**
* @private
* @returns {string}
* @returns {string|FieldCommand}
*/
_computeAvatarUrl() {
if (this.messaging.isCurrentUserGuest) {
@@ -399,7 +399,10 @@ registerModel({
}
return `/mail/channel/${this.thread.id}/guest/${this.messaging.currentGuest.id}/avatar_128?unique=${this.messaging.currentGuest.name}`;
}
return this.messaging.currentPartner.avatarUrl;
if (this.messaging.currentPartner) {
return this.messaging.currentPartner.avatarUrl;
}
return clear();
},
/**
* @private
@@ -481,6 +484,7 @@ registerModel({
*/
avatarUrl: attr({
compute: '_computeAvatarUrl',
default: '',
readonly: true,
}),
/**
-1
View File
@@ -61,7 +61,6 @@ sent mails with personal token for the invitation of the survey.
'assets': {
'survey.survey_assets': [
'web/static/lib/Chart/Chart.js',
'web/static/src/legacy/js/fields/field_utils.js',
'survey/static/src/js/survey_quick_access.js',
'survey/static/src/js/survey_timer.js',
'survey/static/src/js/survey_breadcrumb.js',
+2
View File
@@ -229,6 +229,7 @@ This module provides the core of the Odoo Web Client.
('include', 'web.assets_frontend_minimal'),
'web/static/src/legacy/utils.js',
'web/static/src/legacy/js/core/misc.js',
'web/static/src/legacy/js/owl_compatibility.js',
'web/static/src/legacy/js/services/session.js',
'web/static/src/legacy/js/public/public_env.js',
@@ -237,6 +238,7 @@ This module provides the core of the Odoo Web Client.
'web/static/src/legacy/js/public/public_widget.js',
'web/static/src/legacy/legacy_promise_error_handler.js',
'web/static/src/legacy/legacy_rpc_error_handler.js',
'web/static/src/legacy/js/fields/field_utils.js',
('include', 'web.frontend_legacy'),
],
-10
View File
@@ -29,18 +29,8 @@ Allow website visitors to chat with the collaborators. This module also brings a
'website_livechat/static/src/models/*.js',
],
'web.assets_frontend': [
'mail/static/src/js/utils.js',
'im_livechat/static/src/legacy/public_livechat_constants.js',
'im_livechat/static/src/legacy/public_livechat_history_tracking.js',
'im_livechat/static/src/legacy/models/*',
'im_livechat/static/src/legacy/widgets/*',
'im_livechat/static/src/legacy/widgets/*/*',
'im_livechat/static/src/legacy/public_livechat_chatbot.js',
'im_livechat/static/src/legacy/website_livechat_message_chatbot.js',
'website_livechat/static/src/legacy/public_livechat.js',
'website_livechat/static/src/legacy/website_livechat_chatbot_test_script.js',
'im_livechat/static/src/legacy/public_livechat.scss',
'im_livechat/static/src/legacy/public_livechat_chatbot.scss',
'website_livechat/static/src/legacy/public_livechat.scss',
],
'website.assets_editor': [
@@ -17,7 +17,7 @@ const LivechatButtonTestChatbot = LivechatButton.extend({
/**
* Initialize various data received from the 'chatbot_test_script_page' template.
*/
init: function (parent, chatbotData) {
init: function (parent, messaging, chatbotData) {
this._super(...arguments);
this._rule = {
@@ -73,18 +73,25 @@ const LivechatButtonTestChatbot = LivechatButton.extend({
publicWidget.registry.livechatChatbotTestScript = publicWidget.Widget.extend({
selector: '.o_livechat_js_chatbot_test_script',
init(parent) {
this._super(...arguments);
this.env = parent.env;
},
/**
* Remove any existing session cookie to start fresh
*/
start: function () {
async start() {
utils.set_cookie('im_livechat_session', '', -1);
utils.set_cookie('im_livechat_auto_popup', '', -1);
utils.set_cookie('im_livechat_history', '', -1);
utils.set_cookie('im_livechat_previous_operator_pid', '', -1);
const messaging = this.env.services.messaging.get();
return this._super(...arguments).then(() => {
this.livechatButton = new LivechatButtonTestChatbot(this, this.$el.data());
messaging.update({
isInPublicLivechat: true,
isPublicLivechatAvailable: true,
});
this.livechatButton = new LivechatButtonTestChatbot(this, messaging, this.$el.data());
this.livechatButton.appendTo(document.body);
});
}