[FIX] website, *: lazy load widget assets of the correct website
*: web Before this commit, when a widget declared assets to lazy load through the assetLibs key, the asset was loaded through a context-less call to the server through the base `rpc` function. This caused problems in website: the website ID was not given to the called route and the loaded assets were then stripped of their specific-website parts. This commit solves the problem by allowing the `loadLibs` and `loadAsset` functions to receive an extra argument: an extra `context` to use for the actual call to the server. The method is now available in the ajax service, so that website can add its custom context automatically, the same way it does it for normal `_rpc` calls. Part of https://github.com/odoo/odoo/pull/44596 closes odoo/odoo#44596 Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
This commit is contained in:
@@ -428,6 +428,8 @@ var loadXML = (function () {
|
||||
* Loads a template file according to the given xmlId.
|
||||
*
|
||||
* @param {string} [xmlId] - the template xmlId
|
||||
* @param {Object} [context]
|
||||
* additionnal rpc context to be merged with the default one
|
||||
* @returns {Deferred} resolved with an object
|
||||
* cssLibs: list of css files
|
||||
* cssContents: list of style tag contents
|
||||
@@ -437,16 +439,17 @@ var loadXML = (function () {
|
||||
var loadAsset = (function () {
|
||||
var cache = {};
|
||||
|
||||
var load = function loadAsset(xmlId) {
|
||||
var load = function loadAsset(xmlId, context) {
|
||||
if (cache[xmlId]) {
|
||||
return Promise.resolve(cache[xmlId]);
|
||||
}
|
||||
context = _.extend({}, odoo.session_info.user_context, context);
|
||||
var params = {
|
||||
args: [xmlId, {
|
||||
debug: config.isDebug()
|
||||
}],
|
||||
kwargs: {
|
||||
context: odoo.session_info.user_context,
|
||||
context: context,
|
||||
},
|
||||
method: 'render_template',
|
||||
model: 'ir.ui.view',
|
||||
@@ -499,10 +502,12 @@ var loadAsset = (function () {
|
||||
* List of inline styles to add after loading the CSS files.
|
||||
* @param {string[]} [libs.jsContents=[]]
|
||||
* List of inline scripts to add after loading the JS files.
|
||||
* @param {Object} [context]
|
||||
* additionnal rpc context to be merged with the default one
|
||||
*
|
||||
* @returns {Promise}
|
||||
*/
|
||||
function loadLibs(libs) {
|
||||
function loadLibs(libs, context) {
|
||||
var mutex = new concurrency.Mutex();
|
||||
mutex.exec(function () {
|
||||
var defs = [];
|
||||
@@ -525,7 +530,7 @@ function loadLibs(libs) {
|
||||
});
|
||||
mutex.exec(function () {
|
||||
return _loadArray(libs.assetLibs || [], function (xmlID) {
|
||||
return ajax.loadAsset(xmlID).then(function (asset) {
|
||||
return ajax.loadAsset(xmlID, context).then(function (asset) {
|
||||
return ajax.loadLibs(asset);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -123,6 +123,15 @@ var ServicesMixin = {
|
||||
});
|
||||
return result;
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {Object} libs - @see ajax.loadLibs
|
||||
* @param {Object} [context] - @see ajax.loadLibs
|
||||
* @returns {Promise}
|
||||
*/
|
||||
_loadLibs: function (libs, context) {
|
||||
return this.call('ajax', 'loadLibs', libs, context);
|
||||
},
|
||||
/**
|
||||
* Builds and executes RPC query. Returns a promise resolved with
|
||||
* the RPC result.
|
||||
|
||||
@@ -148,7 +148,7 @@ var Widget = core.Class.extend(mixins.PropertiesMixin, ServicesMixin, {
|
||||
}));
|
||||
}
|
||||
if (this.jsLibs || this.cssLibs || this.assetLibs) {
|
||||
proms.push(ajax.loadLibs(this));
|
||||
proms.push(this._loadLibs(this));
|
||||
}
|
||||
return Promise.all(proms);
|
||||
},
|
||||
|
||||
@@ -101,15 +101,25 @@ var PublicRoot = publicWidget.RootWidget.extend(ServiceProviderMixin, {
|
||||
if (_.str.startsWith(route, '/web/dataset/call_kw/')) {
|
||||
var params = ev.data.args[1];
|
||||
var options = ev.data.args[2];
|
||||
params.kwargs.context = _.extend({}, this._getContext(), params.kwargs.context || {});
|
||||
var noContextKeys = undefined;
|
||||
if (options) {
|
||||
params.kwargs.context = _.omit(params.kwargs.context, options.noContextKeys);
|
||||
noContextKeys = options.noContextKeys;
|
||||
ev.data.args[2] = _.omit(options, 'noContextKeys');
|
||||
}
|
||||
params.kwargs.context = JSON.parse(JSON.stringify(params.kwargs.context));
|
||||
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
|
||||
|
||||
@@ -2,10 +2,18 @@ odoo.define('web.AjaxService', function (require) {
|
||||
"use strict";
|
||||
|
||||
var AbstractService = require('web.AbstractService');
|
||||
var ajax = require('web.ajax');
|
||||
var core = require('web.core');
|
||||
var session = require('web.session');
|
||||
|
||||
var AjaxService = AbstractService.extend({
|
||||
/**
|
||||
* @param {Object} libs - @see ajax.loadLibs
|
||||
* @param {Object} [context] - @see ajax.loadLibs
|
||||
*/
|
||||
loadLibs: function (libs, context) {
|
||||
return ajax.loadLibs(libs, context);
|
||||
},
|
||||
rpc: function (route, args, options, target) {
|
||||
var rpcPromise;
|
||||
var promise = new Promise(function (resolve, reject) {
|
||||
|
||||
@@ -253,7 +253,7 @@ function addMockEnvironment(widget, params) {
|
||||
var service = services[ev.data.service];
|
||||
args = (ev.data.args || []);
|
||||
result = service[ev.data.method].apply(service, args);
|
||||
} else if (ev.data.service === 'ajax') {
|
||||
} else if (ev.data.service === 'ajax' && ev.data.method === 'rpc') {
|
||||
// use ajax service that is mocked by the server
|
||||
var route = ev.data.args[0];
|
||||
args = ev.data.args[1];
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
odoo.define('website.tour.specific_website_editor', function (require) {
|
||||
'use strict';
|
||||
|
||||
var tour = require('web_tour.tour');
|
||||
|
||||
tour.register('generic_website_editor', {
|
||||
test: true,
|
||||
}, [{
|
||||
trigger: 'a[data-action=edit]',
|
||||
content: 'Click edit button',
|
||||
}, {
|
||||
trigger: 'body:not([data-hello="world"])',
|
||||
extra_trigger: '#oe_snippets.o_loaded',
|
||||
content: 'Check that the editor DOM matches its website-generic features',
|
||||
run: function () {}, // Simple check
|
||||
}]);
|
||||
|
||||
tour.register('specific_website_editor', {
|
||||
test: true,
|
||||
}, [{
|
||||
trigger: 'a[data-action=edit]',
|
||||
content: 'Click edit button',
|
||||
}, {
|
||||
trigger: 'body[data-hello="world"]',
|
||||
extra_trigger: '#oe_snippets.o_loaded',
|
||||
content: 'Check that the editor DOM matches its website-specific features',
|
||||
run: function () {}, // Simple check
|
||||
}]);
|
||||
});
|
||||
@@ -112,3 +112,21 @@ class TestUi(odoo.tests.HttpCase):
|
||||
|
||||
def test_04_backend_dashboard(self):
|
||||
self.start_tour("/", 'backend_dashboard', login='admin')
|
||||
|
||||
def test_05_specific_website_editor(self):
|
||||
website_default = self.env['website'].search([], limit=1)
|
||||
new_website = self.env['website'].create({'name': 'New Website'})
|
||||
website_editor_assets_view = self.env.ref('website.assets_wysiwyg')
|
||||
self.env['ir.ui.view'].create({
|
||||
'name': 'Editor Extension',
|
||||
'type': 'qweb',
|
||||
'inherit_id': website_editor_assets_view.id,
|
||||
'website_id': new_website.id,
|
||||
'arch': """
|
||||
<xpath expr="." position="inside">
|
||||
<script type="text/javascript">document.body.dataset.hello = 'world';</script>
|
||||
</xpath>
|
||||
""",
|
||||
})
|
||||
self.start_tour("/?fw=%s" % website_default.id, "generic_website_editor", login='admin')
|
||||
self.start_tour("/?fw=%s" % new_website.id, "specific_website_editor", login='admin')
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
<script type="text/javascript" src="/website/static/tests/tours/html_editor.js"/>
|
||||
<script type="text/javascript" src="/website/static/tests/tours/restricted_editor.js"/>
|
||||
<script type="text/javascript" src="/website/static/tests/tours/dashboard_tour.js"/>
|
||||
<script type="text/javascript" src="/website/static/tests/tours/specific_website_editor.js"/>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user