[IMP] web,*: properly define env in the frontend
*bus,mail This commit extracts the common basis of the env to use both in the frontend and the backend. The public env now contains most of the features that were previously (only) in the webclient env. Moreover, the PublicRoot no longer uses the ServiceProviderMixin, such that services are only deployed once, in the (public) env. Owl components can now be defined in the website, and rely on a properly built env. Legacy widgets still works as they access services through the PublicRoot (via trigger_up) which redirects those requests to the env.
This commit is contained in:
@@ -4,6 +4,7 @@ odoo.define('bus.BusService', function (require) {
|
||||
var CrossTab = require('bus.CrossTab');
|
||||
var core = require('web.core');
|
||||
var ServicesMixin = require('web.ServicesMixin');
|
||||
const session = require('web.session');
|
||||
|
||||
var BusService = CrossTab.extend(ServicesMixin, {
|
||||
dependencies : ['local_storage'],
|
||||
@@ -11,6 +12,38 @@ var BusService = CrossTab.extend(ServicesMixin, {
|
||||
// properties
|
||||
_audio: null,
|
||||
|
||||
/**
|
||||
* As the BusService doesn't extend AbstractService, we have to replicate
|
||||
* here what is done in AbstractService
|
||||
*
|
||||
* @param {Object} env
|
||||
*/
|
||||
init: function (env) {
|
||||
this.env = env;
|
||||
this._super();
|
||||
},
|
||||
|
||||
/**
|
||||
* Replicate the behavior of AbstractService:
|
||||
*
|
||||
* Directly calls the requested service, instead of triggering a
|
||||
* 'call_service' event up, which wouldn't work as services have no parent.
|
||||
*
|
||||
* @param {OdooEvent} ev
|
||||
*/
|
||||
_trigger_up: function (ev) {
|
||||
if (ev.name === 'call_service') {
|
||||
const payload = ev.data;
|
||||
let args = payload.args || [];
|
||||
if (payload.service === 'ajax' && payload.method === 'rpc') {
|
||||
// ajax service uses an extra 'target' argument for rpc
|
||||
args = args.concat(ev.target);
|
||||
}
|
||||
const service = this.env.services[payload.service];
|
||||
const result = service[payload.method].apply(service, args);
|
||||
payload.callback(result);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* This method is necessary in order for this Class to be used to instantiate services
|
||||
*
|
||||
@@ -77,7 +110,6 @@ var BusService = CrossTab.extend(ServicesMixin, {
|
||||
if (!this._audio) {
|
||||
this._audio = new Audio();
|
||||
var ext = this._audio.canPlayType("audio/ogg; codecs=vorbis") ? ".ogg" : ".mp3";
|
||||
var session = this.getSession();
|
||||
this._audio.src = session.url("/mail/static/src/audio/ting" + ext);
|
||||
}
|
||||
Promise.resolve(this._audio.play()).catch(_.noop);
|
||||
|
||||
@@ -1004,7 +1004,7 @@ var MailManager = AbstractService.extend({
|
||||
_t("%d Messages"),
|
||||
this._outOfFocusUnreadMessageCounter
|
||||
);
|
||||
this.trigger_up('set_title_part', {
|
||||
this.env.bus.trigger('set_title_part', {
|
||||
part: '_chat',
|
||||
title: tabTitle
|
||||
});
|
||||
@@ -1048,12 +1048,14 @@ var MailManager = AbstractService.extend({
|
||||
* @param {string} viewID
|
||||
*/
|
||||
_redirectToDocument: function (resModel, resID, viewID) {
|
||||
this.do_action({
|
||||
type: 'ir.actions.act_window',
|
||||
view_mode: 'form',
|
||||
res_model: resModel,
|
||||
views: [[viewID || false, 'form']],
|
||||
res_id: resID,
|
||||
this.env.bus.trigger('do-action', {
|
||||
action: {
|
||||
type: 'ir.actions.act_window',
|
||||
view_mode: 'form',
|
||||
res_model: resModel,
|
||||
views: [[viewID || false, 'form']],
|
||||
res_id: resID,
|
||||
},
|
||||
});
|
||||
},
|
||||
/**
|
||||
@@ -1345,7 +1347,7 @@ var MailManager = AbstractService.extend({
|
||||
*/
|
||||
_onWindowFocus: function () {
|
||||
this._resetOutOfFocusUnreadMessageCounter();
|
||||
this.trigger_up('set_title_part', { part: '_chat' });
|
||||
this.env.bus.trigger('set_title_part', { part: '_chat' });
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@ var data_manager = require('web.data_manager');
|
||||
var dom = require('web.dom');
|
||||
var KeyboardNavigationMixin = require('web.KeyboardNavigationMixin');
|
||||
var Loading = require('web.Loading');
|
||||
var local_storage = require('web.local_storage');
|
||||
var RainbowMan = require('web.RainbowMan');
|
||||
var session = require('web.session');
|
||||
var utils = require('web.utils');
|
||||
@@ -103,7 +102,7 @@ var AbstractWebClient = Widget.extend(KeyboardNavigationMixin, {
|
||||
this.action_mutex = new concurrency.Mutex();
|
||||
this.set('title_part', {"zopenerp": "Odoo"});
|
||||
this.env = env;
|
||||
core.bus.on('legacy_webclient_request', this, this._onLegacyWebclientRequest);
|
||||
this.env.bus.on('set_title_part', this, this._onSetTitlePart);
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
@@ -206,6 +205,11 @@ var AbstractWebClient = Widget.extend(KeyboardNavigationMixin, {
|
||||
set_action_manager: function () {
|
||||
var self = this;
|
||||
this.action_manager = new ActionManager(this, session.user_context);
|
||||
this.env.bus.on('do-action', this, payload => {
|
||||
this.action_manager.doAction(payload.action, payload.options)
|
||||
.then(payload.on_success || (() => {}))
|
||||
.guardedCatch(payload.on_fail || (() => {}));
|
||||
});
|
||||
var fragment = document.createDocumentFragment();
|
||||
return this.action_manager.appendTo(fragment).then(function () {
|
||||
dom.append(self.$el, fragment, {
|
||||
@@ -439,20 +443,6 @@ var AbstractWebClient = Widget.extend(KeyboardNavigationMixin, {
|
||||
_onGetScrollPosition: function (ev) {
|
||||
ev.data.callback(this.getScrollPosition());
|
||||
},
|
||||
/**
|
||||
* Services used to trigger_up some events (e.g. do_action, get_session,
|
||||
* set_title_part) when the webclient was still instantiating them. Now that
|
||||
* services have been moved to the env, the webclient is no longer their
|
||||
* parent and they can thus no longer communicate with the webclient by
|
||||
* trigger_up. Instead, they trigger those events on the bus, and we end up
|
||||
* in this handler. Eventually, services should stop triggering events up.
|
||||
*
|
||||
* @private
|
||||
* @param {CustomEvent} ev
|
||||
*/
|
||||
_onLegacyWebclientRequest: function (ev) {
|
||||
this._trigger_up(ev);
|
||||
},
|
||||
/**
|
||||
* Loads an action from the database given its ID.
|
||||
*
|
||||
@@ -502,13 +492,13 @@ var AbstractWebClient = Widget.extend(KeyboardNavigationMixin, {
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {OdooEvent} ev
|
||||
* @param {string} ev.data.part
|
||||
* @param {string} [ev.data.title]
|
||||
* @param {Object} payload
|
||||
* @param {string} payload.part
|
||||
* @param {string} [payload.title]
|
||||
*/
|
||||
_onSetTitlePart: function (ev) {
|
||||
var part = ev.data.part;
|
||||
var title = ev.data.title;
|
||||
_onSetTitlePart: function (payload) {
|
||||
var part = payload.part;
|
||||
var title = payload.title;
|
||||
this.set_title_part(part, title);
|
||||
},
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
odoo.define("web.commonEnv", function (require) {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* This file defines the common environment, which contains everything that
|
||||
* is needed in the env for both the backend and the frontend (Odoo
|
||||
* terminology). This module shouldn't be used as is. It should only be
|
||||
* imported by the module defining the final env to use (in the frontend or
|
||||
* in the backend). For instance, module 'web.env' imports it, adds stuff to
|
||||
* it, and exports the final env that is used by the whole webclient
|
||||
* application.
|
||||
*
|
||||
* There should be as much dependencies as possible in the env object. This
|
||||
* will allow an easier testing of components. See [1] for more information
|
||||
* on environments.
|
||||
*
|
||||
* [1] https://github.com/odoo/owl/blob/master/doc/reference/environment.md#content-of-an-environment
|
||||
*/
|
||||
|
||||
const { jsonRpc } = require("web.ajax");
|
||||
const { device, isDebug } = require("web.config");
|
||||
const { bus, serviceRegistry } = require("web.core");
|
||||
const rpc = require("web.rpc");
|
||||
const session = require("web.session");
|
||||
const { _t } = require("web.translation");
|
||||
const utils = require("web.utils");
|
||||
|
||||
|
||||
// Build the basic env
|
||||
const env = {
|
||||
_t,
|
||||
bus,
|
||||
device,
|
||||
isDebug,
|
||||
qweb: new owl.QWeb({ translateFn: _t }),
|
||||
services: {
|
||||
ajaxJsonRPC() {
|
||||
return jsonRpc(...arguments);
|
||||
},
|
||||
getCookie() {
|
||||
return utils.get_cookie(...arguments);
|
||||
},
|
||||
httpRequest(route, params = {}, readMethod = 'json') {
|
||||
const info = {
|
||||
method: params.method || 'POST',
|
||||
};
|
||||
if (params.method !== 'GET') {
|
||||
const formData = new FormData();
|
||||
for (const key in params) {
|
||||
if (key === 'method') {
|
||||
continue;
|
||||
}
|
||||
const value = params[key];
|
||||
if (Array.isArray(value) && value.length) {
|
||||
for (const val of value) {
|
||||
formData.append(key, val);
|
||||
}
|
||||
} else {
|
||||
formData.append(key, value);
|
||||
}
|
||||
}
|
||||
info.body = formData;
|
||||
}
|
||||
return fetch(route, info).then(response => response[readMethod]());
|
||||
},
|
||||
navigate(url, params) {
|
||||
window.location = $.param.querystring(url, params);
|
||||
},
|
||||
reloadPage() {
|
||||
window.location.reload();
|
||||
},
|
||||
rpc(params, options) {
|
||||
const query = rpc.buildQuery(params);
|
||||
return session.rpc(query.route, query.params, options);
|
||||
},
|
||||
setCookie() {
|
||||
utils.set_cookie(...arguments);
|
||||
},
|
||||
},
|
||||
session,
|
||||
};
|
||||
|
||||
|
||||
// Deploy services in the env (specializations of AbstractService registered
|
||||
// into the serviceRegistry)
|
||||
const UndeployedServices = Object.assign({}, serviceRegistry.map);
|
||||
function _deployServices() {
|
||||
let done = false;
|
||||
while (!done) {
|
||||
// find a service with no missing dependency
|
||||
const serviceName = Object.keys(UndeployedServices).find(serviceName => {
|
||||
const Service = UndeployedServices[serviceName];
|
||||
return Service.prototype.dependencies.every(depName => {
|
||||
return env.services[depName];
|
||||
});
|
||||
});
|
||||
if (serviceName) {
|
||||
const Service = UndeployedServices[serviceName];
|
||||
const service = new Service(env);
|
||||
env.services[serviceName] = service;
|
||||
delete UndeployedServices[serviceName];
|
||||
service.start();
|
||||
} else {
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
serviceRegistry.onAdd((serviceName, Service) => {
|
||||
if (serviceName in env.services || serviceName in UndeployedServices) {
|
||||
throw new Error(`Service ${serviceName} is already loaded.`);
|
||||
}
|
||||
UndeployedServices[serviceName] = Service;
|
||||
_deployServices();
|
||||
});
|
||||
_deployServices();
|
||||
|
||||
|
||||
return env;
|
||||
});
|
||||
@@ -7,14 +7,39 @@ var ServicesMixin = require('web.ServicesMixin');
|
||||
|
||||
var AbstractService = Class.extend(Mixins.EventDispatcherMixin, ServicesMixin, {
|
||||
dependencies: [],
|
||||
init: function (parent) {
|
||||
init: function (env) {
|
||||
Mixins.EventDispatcherMixin.init.call(this, arguments);
|
||||
this.setParent(parent);
|
||||
this.env = env;
|
||||
},
|
||||
/**
|
||||
* @abstract
|
||||
*/
|
||||
start: function () {},
|
||||
/**
|
||||
* Directly calls the requested service, instead of triggering a
|
||||
* 'call_service' event up, which wouldn't work as services have no parent
|
||||
*
|
||||
* @param {OdooEvent} ev
|
||||
*/
|
||||
_trigger_up: function (ev) {
|
||||
Mixins.EventDispatcherMixin._trigger_up.apply(this, arguments);
|
||||
if (ev.is_stopped()) {
|
||||
return;
|
||||
}
|
||||
const payload = ev.data;
|
||||
if (ev.name === 'call_service') {
|
||||
let args = payload.args || [];
|
||||
if (payload.service === 'ajax' && payload.method === 'rpc') {
|
||||
// ajax service uses an extra 'target' argument for rpc
|
||||
args = args.concat(ev.target);
|
||||
}
|
||||
const service = this.env.services[payload.service];
|
||||
const result = service[payload.method].apply(service, args);
|
||||
payload.callback(result);
|
||||
} else if (ev.name === 'do_action') {
|
||||
this.env.bus.trigger('do-action', payload);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return AbstractService;
|
||||
|
||||
@@ -3,6 +3,8 @@ odoo.define('web.ServiceProviderMixin', function (require) {
|
||||
|
||||
var core = require('web.core');
|
||||
|
||||
// ServiceProviderMixin is deprecated. It is only used by the ProjectTimesheet
|
||||
// app. As soon as it no longer uses it, we can remove it.
|
||||
var ServiceProviderMixin = {
|
||||
services: {}, // dict containing deployed service instances
|
||||
UndeployedServices: {}, // dict containing classes of undeployed services
|
||||
|
||||
@@ -1,157 +1,16 @@
|
||||
odoo.define("web.env", function (require) {
|
||||
"use strict";
|
||||
|
||||
const { jsonRpc } = require('web.ajax');
|
||||
const { device, isDebug } = require("web.config");
|
||||
const { bus, serviceRegistry } = require("web.core");
|
||||
/**
|
||||
* This file defines the env to use in the webclient.
|
||||
*/
|
||||
|
||||
const commonEnv = require('web.commonEnv');
|
||||
const dataManager = require('web.data_manager');
|
||||
const { blockUI, unblockUI } = require("web.framework");
|
||||
const rpc = require("web.rpc");
|
||||
const session = require("web.session");
|
||||
const { _t } = require('web.translation');
|
||||
const utils = require("web.utils");
|
||||
|
||||
const qweb = new owl.QWeb({ translateFn: _t });
|
||||
const env = Object.assign(commonEnv, { dataManager });
|
||||
env.services = Object.assign(env.services, { blockUI, unblockUI });
|
||||
|
||||
function ajaxJsonRPC() {
|
||||
return jsonRpc(...arguments);
|
||||
}
|
||||
|
||||
function getCookie() {
|
||||
return utils.get_cookie(...arguments);
|
||||
}
|
||||
|
||||
function httpRequest(route, params = {}, readMethod = 'json') {
|
||||
const info = {
|
||||
method: params.method || 'POST',
|
||||
};
|
||||
if (params.method !== 'GET') {
|
||||
const formData = new FormData();
|
||||
for (const key in params) {
|
||||
if (key === 'method') {
|
||||
continue;
|
||||
}
|
||||
const value = params[key];
|
||||
if (Array.isArray(value) && value.length) {
|
||||
for (const val of value) {
|
||||
formData.append(key, val);
|
||||
}
|
||||
} else {
|
||||
formData.append(key, value);
|
||||
}
|
||||
}
|
||||
info.body = formData;
|
||||
}
|
||||
|
||||
return fetch(route, info).then(response => response[readMethod]());
|
||||
}
|
||||
|
||||
function navigate(url, params) {
|
||||
window.location = $.param.querystring(url, params);
|
||||
}
|
||||
|
||||
function performRPC(params, options) {
|
||||
const query = rpc.buildQuery(params);
|
||||
return session.rpc(query.route, query.params, options);
|
||||
}
|
||||
|
||||
function reloadPage() {
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
function setCookie() {
|
||||
utils.set_cookie(...arguments);
|
||||
}
|
||||
|
||||
// ServiceProvider
|
||||
const services = {}; // dict containing deployed service instances
|
||||
const UndeployedServices = {}; // dict containing classes of undeployed services
|
||||
function _deployServices() {
|
||||
let done = false;
|
||||
while (!done) {
|
||||
const serviceName = _.findKey(UndeployedServices, Service => {
|
||||
// no missing dependency
|
||||
return !_.some(Service.prototype.dependencies, depName => {
|
||||
return !services[depName];
|
||||
});
|
||||
});
|
||||
if (serviceName) {
|
||||
const Service = UndeployedServices[serviceName];
|
||||
// we created a patched version of the Service in which the 'trigger_up'
|
||||
// function directly calls the requested service, instead of triggering
|
||||
// a 'call_service' event up, which wouldn't work as services have
|
||||
// no parent
|
||||
const PatchedService = Service.extend({
|
||||
_trigger_up: function (ev) {
|
||||
this._super(...arguments);
|
||||
if (!ev.is_stopped() && ev.name === 'call_service') {
|
||||
const payload = ev.data;
|
||||
let args = payload.args || [];
|
||||
if (payload.service === 'ajax' && payload.method === 'rpc') {
|
||||
// ajax service uses an extra 'target' argument for rpc
|
||||
args = args.concat(ev.target);
|
||||
}
|
||||
const service = services[payload.service];
|
||||
const result = service[payload.method].apply(service, args);
|
||||
payload.callback(result);
|
||||
} else {
|
||||
// historically, some services could reach the webclient
|
||||
// by triggering events up, as the webclient was their
|
||||
// parent. Since services have been moved to the env,
|
||||
// this is no longer the case, so we re-trigger those
|
||||
// events on the bus for now. Eventually, services
|
||||
// should stop triggering events up (they can still
|
||||
// communicate with other services through the env).
|
||||
bus.trigger('legacy_webclient_request', ev);
|
||||
}
|
||||
},
|
||||
});
|
||||
const service = new PatchedService();
|
||||
services[serviceName] = service;
|
||||
delete UndeployedServices[serviceName];
|
||||
service.start();
|
||||
} else {
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
_.each(serviceRegistry.map, (Service, serviceName) => {
|
||||
if (serviceName in UndeployedServices) {
|
||||
throw new Error(`Service ${serviceName} is already loaded.`);
|
||||
}
|
||||
UndeployedServices[serviceName] = Service;
|
||||
});
|
||||
serviceRegistry.onAdd((serviceName, Service) => {
|
||||
if (serviceName in services || serviceName in UndeployedServices) {
|
||||
throw new Error(`Service ${serviceName} is already loaded.`);
|
||||
}
|
||||
UndeployedServices[serviceName] = Service;
|
||||
_deployServices();
|
||||
});
|
||||
_deployServices();
|
||||
|
||||
// There should be as much dependencies as possible in the env object.
|
||||
// This will allow an easier testing of components.
|
||||
// See https://github.com/odoo/owl/blob/master/doc/reference/environment.md#content-of-an-environment
|
||||
// for more information on environments.
|
||||
return {
|
||||
_t,
|
||||
bus,
|
||||
dataManager,
|
||||
device,
|
||||
isDebug,
|
||||
qweb,
|
||||
services: Object.assign(services, {
|
||||
ajaxJsonRPC,
|
||||
blockUI,
|
||||
getCookie,
|
||||
httpRequest,
|
||||
navigate,
|
||||
reloadPage,
|
||||
rpc: performRPC,
|
||||
setCookie,
|
||||
unblockUI,
|
||||
}),
|
||||
session,
|
||||
};
|
||||
return env;
|
||||
});
|
||||
|
||||
@@ -1,24 +1,11 @@
|
||||
odoo.define("web.public_env", function (require) {
|
||||
"use strict";
|
||||
|
||||
const { _t } = require("web.core");
|
||||
const rpc = require("web.rpc");
|
||||
/**
|
||||
* This file defines the env to use in the public side.
|
||||
*/
|
||||
|
||||
const qweb = new owl.QWeb({ translateFn: _t });
|
||||
const commonEnv = require("web.commonEnv");
|
||||
|
||||
function performRPC(params, options) {
|
||||
const query = rpc.buildQuery(params);
|
||||
return session.rpc(query.route, query.params, options);
|
||||
}
|
||||
|
||||
// There should be as much dependencies as possible in the env object.
|
||||
// This will allow an easier testing of components.
|
||||
// See https://github.com/odoo/owl/blob/master/doc/reference/environment.md#content-of-an-environment
|
||||
// for more information on environments.
|
||||
return {
|
||||
qweb,
|
||||
services: {
|
||||
rpc: performRPC,
|
||||
},
|
||||
};
|
||||
return commonEnv;
|
||||
});
|
||||
|
||||
@@ -3,7 +3,7 @@ odoo.define('web.public.root', function (require) {
|
||||
|
||||
var ajax = require('web.ajax');
|
||||
var dom = require('web.dom');
|
||||
var ServiceProviderMixin = require('web.ServiceProviderMixin');
|
||||
const env = require('web.public_env');
|
||||
var session = require('web.session');
|
||||
var utils = require('web.utils');
|
||||
var publicWidget = require('web.public.widget');
|
||||
@@ -25,16 +25,17 @@ var localeDef = ajax.loadJS('/web/webclient/locale/' + lang.replace('-', '_'));
|
||||
* this Class instance. Its main role will be to retrieve RPC demands from its
|
||||
* children and handle them.
|
||||
*/
|
||||
var PublicRoot = publicWidget.RootWidget.extend(ServiceProviderMixin, {
|
||||
var PublicRoot = publicWidget.RootWidget.extend({
|
||||
events: _.extend({}, publicWidget.RootWidget.prototype.events || {}, {
|
||||
'submit .js_website_submit_form': '_onWebsiteFormSubmit',
|
||||
'click .js_disable_on_click': '_onDisableOnClick',
|
||||
}),
|
||||
custom_events: _.extend({}, publicWidget.RootWidget.prototype.custom_events || {}, {
|
||||
'context_get': '_onContextGet',
|
||||
'main_object_request': '_onMainObjectRequest',
|
||||
'widgets_start_request': '_onWidgetsStartRequest',
|
||||
'widgets_stop_request': '_onWidgetsStopRequest',
|
||||
call_service: '_onCallService',
|
||||
context_get: '_onContextGet',
|
||||
main_object_request: '_onMainObjectRequest',
|
||||
widgets_start_request: '_onWidgetsStartRequest',
|
||||
widgets_stop_request: '_onWidgetsStopRequest',
|
||||
}),
|
||||
|
||||
/**
|
||||
@@ -42,7 +43,7 @@ var PublicRoot = publicWidget.RootWidget.extend(ServiceProviderMixin, {
|
||||
*/
|
||||
init: function () {
|
||||
this._super.apply(this, arguments);
|
||||
ServiceProviderMixin.init.call(this);
|
||||
this.env = env;
|
||||
this.publicWidgets = [];
|
||||
},
|
||||
/**
|
||||
@@ -90,37 +91,6 @@ var PublicRoot = publicWidget.RootWidget.extend(ServiceProviderMixin, {
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Automatically adds the global context to RPCs.
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
_call_service: function (ev) {
|
||||
if (ev.data.service === 'ajax' && ev.data.method === 'rpc') {
|
||||
var route = ev.data.args[0];
|
||||
if (_.str.startsWith(route, '/web/dataset/call_kw/')) {
|
||||
var params = ev.data.args[1];
|
||||
var options = ev.data.args[2];
|
||||
var noContextKeys = undefined;
|
||||
if (options) {
|
||||
noContextKeys = options.noContextKeys;
|
||||
ev.data.args[2] = _.omit(options, 'noContextKeys');
|
||||
}
|
||||
params.kwargs.context = _computeContext.call(this, params.kwargs.context, noContextKeys);
|
||||
}
|
||||
} else if (ev.data.service === 'ajax' && ev.data.method === 'loadLibs') {
|
||||
ev.data.args[1] = _computeContext.call(this, ev.data.args[1]);
|
||||
}
|
||||
return ServiceProviderMixin._call_service.apply(this, arguments);
|
||||
|
||||
function _computeContext(context, noContextKeys) {
|
||||
context = _.extend({}, this._getContext(), context);
|
||||
if (noContextKeys) {
|
||||
context = _.omit(context, noContextKeys);
|
||||
}
|
||||
return JSON.parse(JSON.stringify(context));
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Retrieves the global context of the public environment. This is the
|
||||
* context which is automatically added to each RPC.
|
||||
@@ -234,6 +204,47 @@ var PublicRoot = publicWidget.RootWidget.extend(ServiceProviderMixin, {
|
||||
// Handlers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Calls the requested service from the env. Automatically adds the global
|
||||
* context to RPCs.
|
||||
*
|
||||
* @private
|
||||
* @param {OdooEvent} event
|
||||
*/
|
||||
_onCallService: function (ev) {
|
||||
function _computeContext(context, noContextKeys) {
|
||||
context = _.extend({}, this._getContext(), context);
|
||||
if (noContextKeys) {
|
||||
context = _.omit(context, noContextKeys);
|
||||
}
|
||||
return JSON.parse(JSON.stringify(context));
|
||||
}
|
||||
|
||||
const payload = ev.data;
|
||||
let args = payload.args || [];
|
||||
if (payload.service === 'ajax' && payload.method === 'rpc') {
|
||||
// ajax service uses an extra 'target' argument for rpc
|
||||
args = args.concat(ev.target);
|
||||
|
||||
var route = args[0];
|
||||
if (_.str.startsWith(route, '/web/dataset/call_kw/')) {
|
||||
var params = args[1];
|
||||
var options = args[2];
|
||||
var noContextKeys;
|
||||
if (options) {
|
||||
noContextKeys = options.noContextKeys;
|
||||
args[2] = _.omit(options, 'noContextKeys');
|
||||
}
|
||||
params.kwargs.context = _computeContext.call(this, params.kwargs.context, noContextKeys);
|
||||
}
|
||||
} else if (payload.service === 'ajax' && payload.method === 'loadLibs') {
|
||||
args[1] = _computeContext.call(this, args[1]);
|
||||
}
|
||||
|
||||
const service = this.env.services[payload.service];
|
||||
const result = service[payload.method].apply(service, args);
|
||||
payload.callback(result);
|
||||
},
|
||||
/**
|
||||
* Called when someone asked for the global public context.
|
||||
*
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
odoo.define('root.widget', function (require) {
|
||||
'use strict';
|
||||
|
||||
const env = require('web.public_env');
|
||||
var lazyloader = require('web.public.lazyloader');
|
||||
var rootData = require('web.public.root');
|
||||
|
||||
/**
|
||||
* Configure Owl with the public env
|
||||
*/
|
||||
owl.config.mode = env.isDebug() ? "dev" : "prod";
|
||||
owl.Component.env = env;
|
||||
|
||||
/**
|
||||
* This widget is important, because the tour manager needs a root widget in
|
||||
* order to work. The root widget must be a service provider with the ajax
|
||||
|
||||
@@ -167,6 +167,8 @@
|
||||
|
||||
<script type="text/javascript" src="/web/static/src/js/tools/debug_manager.js"></script>
|
||||
|
||||
<script type="text/javascript" src="/web/static/src/js/common_env.js"></script>
|
||||
|
||||
<script type="text/javascript" src="/web/static/src/js/widgets/name_and_signature.js"></script>
|
||||
<script type="text/javascript" src="/web/static/src/js/widgets/notification.js"></script>
|
||||
<script type="text/javascript" src="/web/static/src/js/widgets/rainbow_man.js"></script>
|
||||
|
||||
Reference in New Issue
Block a user