summaryrefslogtreecommitdiff
path: root/addons/web/static/src
diff options
context:
space:
mode:
Diffstat (limited to 'addons/web/static/src')
-rw-r--r--addons/web/static/src/js/component_extension.js21
-rw-r--r--addons/web/static/src/js/core/session.js8
-rw-r--r--addons/web/static/src/js/core/utils.js75
-rw-r--r--addons/web/static/src/js/env.js86
-rw-r--r--addons/web/static/src/js/main.js27
-rw-r--r--addons/web/static/src/js/public/public_env.js24
6 files changed, 240 insertions, 1 deletions
diff --git a/addons/web/static/src/js/component_extension.js b/addons/web/static/src/js/component_extension.js
new file mode 100644
index 00000000000..39568bd0594
--- /dev/null
+++ b/addons/web/static/src/js/component_extension.js
@@ -0,0 +1,21 @@
+/**
+ * Add a new method to owl Components to ensure that no performed RPC is
+ * resolved/rejected when the component is destroyed.
+ */
+(function () {
+ owl.Component.prototype.rpc = function () {
+ return new Promise((resolve, reject) => {
+ return this.env.services.rpc(...arguments)
+ .then(result => {
+ if (!this.__owl__.isDestroyed) {
+ resolve(result);
+ }
+ })
+ .catch(reason => {
+ if (!this.__owl__.isDestroyed) {
+ reject(reason);
+ }
+ });
+ });
+ };
+})();
diff --git a/addons/web/static/src/js/core/session.js b/addons/web/static/src/js/core/session.js
index 4c8a63dbdb5..a8159469145 100644
--- a/addons/web/static/src/js/core/session.js
+++ b/addons/web/static/src/js/core/session.js
@@ -4,7 +4,6 @@ odoo.define('web.Session', function (require) {
var ajax = require('web.ajax');
var concurrency = require('web.concurrency');
var core = require('web.core');
-var local_storage = require('web.local_storage');
var mixins = require('web.mixins');
var utils = require('web.utils');
@@ -239,7 +238,14 @@ var Session = core.Class.extend(mixins.EventDispatcherMixin, {
var route = '/web/webclient/qweb/' + (cacheId ? cacheId : Date.now()) + '?mods=' + mods;
return $.get(route).then(function (doc) {
if (!doc) { return; }
+ const owlTemplates = [];
+ for (let child of doc.querySelectorAll("templates > [owl]")) {
+ child.removeAttribute('owl');
+ owlTemplates.push(child.outerHTML);
+ child.remove();
+ }
qweb.add_template(doc);
+ self.owlTemplates = `<templates> ${owlTemplates.join('\n')} </templates>`;
});
});
return lock;
diff --git a/addons/web/static/src/js/core/utils.js b/addons/web/static/src/js/core/utils.js
index 29c2ff04c40..4fe1740d6eb 100644
--- a/addons/web/static/src/js/core/utils.js
+++ b/addons/web/static/src/js/core/utils.js
@@ -203,7 +203,10 @@ var diacriticsMap = {
'\u0225': 'z','\u0240': 'z','\u2C6C': 'z','\uA763': 'z',
};
+const patchMap = new WeakMap();
+
var utils = {
+
/**
* Throws an error if the given condition is not true
*
@@ -511,6 +514,51 @@ var utils = {
return new Array(size - str.length + 1).join('0') + str;
},
/**
+ * Patch a class and return a function that remove the patch
+ * when called.
+ *
+ * @param {Class} C Class to patch
+ * @param {string} patchName
+ * @param {Object} patch
+ * @returns {Function}
+ */
+ patch: function(C, patchName, patch) {
+ let metadata = patchMap.get(C.prototype);
+ if (!metadata) {
+ metadata = {
+ origMethods: {},
+ patches: {},
+ current: []
+ };
+ patchMap.set(C.prototype, metadata);
+ }
+ const proto = C.prototype;
+ if (metadata.patches[patchName]) {
+ throw new Error(`Patch [${patchName}] already exists`);
+ }
+ metadata.patches[patchName] = patch;
+ applyPatch(proto, patch);
+ metadata.current.push(patchName);
+
+ function applyPatch(proto, patch) {
+ Object.keys(patch).forEach(function (methodName) {
+ const method = patch[methodName];
+ if (typeof method === "function") {
+ const original = proto[methodName];
+ if (!(methodName in metadata.origMethods)) {
+ metadata.origMethods[methodName] = original;
+ }
+ proto[methodName] = function (...args) {
+ this._super = original;
+ return method.call(this, ...args);
+ };
+ }
+ });
+ }
+
+ return this.unpatch.bind(null, C, patchName);
+ },
+ /**
* performs a half up rounding with a fixed amount of decimals, correcting for float loss of precision
* See the corresponding float_round() in server/tools/float_utils.py for more info
* @param {Number} value the value to be rounded
@@ -662,6 +710,33 @@ var utils = {
return casesensetive ? str : str.toLowerCase();
},
/**
+ * We define here an unpatch function. This is mostly useful if we want to
+ * remove a patch. For example, for testing purposes
+ *
+ * @param {Class} C
+ * @param {string} patchName
+ */
+ unpatch: function(C, patchName) {
+ const proto = C.prototype;
+ let metadata = patchMap.get(proto);
+ if (!metdata) {
+ return;
+ }
+ patchMap.delete(proto);
+
+ // reset to original
+ for (let k in metadata.origMethods) {
+ proto[k] = metadata.origMethods[k];
+ }
+
+ // apply other patches
+ for (let name of metadata.current) {
+ if (name !== patchName) {
+ this.patch(C, name, metadata.patches[name]);
+ }
+ }
+ },
+ /**
* @param {any} node
* @param {any} strip_whitespace
* @returns
diff --git a/addons/web/static/src/js/env.js b/addons/web/static/src/js/env.js
new file mode 100644
index 00000000000..c223fcc91ee
--- /dev/null
+++ b/addons/web/static/src/js/env.js
@@ -0,0 +1,86 @@
+odoo.define("web.env", function (require) {
+ "use strict";
+
+ const { _lt, _t, bus } = require("web.core");
+ const { blockUI, unblockUI } = require("web.framework");
+ const { device, isDebug } = require("web.config");
+ const { jsonRpc } = require('web.ajax');
+ const rpc = require("web.rpc");
+ const session = require("web.session");
+ const utils = require("web.utils");
+
+
+ const qweb = new owl.QWeb({ translateFn: _t });
+
+ function ajaxJsonRPC() {
+ return jsonRpc(...arguments);
+ }
+
+ function getCookie() {
+ return utils.get_cookie(...arguments);
+ }
+
+ function httpRequest(route, params = {}, readMethod = 'json') {
+ 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);
+ }
+ }
+
+ return fetch(route, {
+ method: params.method || 'POST',
+ body: formData,
+ }).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);
+ }
+
+ // 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 {
+ _lt,
+ _t,
+ bus,
+ device,
+ isDebug,
+ qweb,
+ services: {
+ ajaxJsonRPC,
+ blockUI,
+ getCookie,
+ httpRequest,
+ navigate,
+ reloadPage,
+ rpc: performRPC,
+ setCookie,
+ unblockUI,
+ },
+ session,
+ };
+});
diff --git a/addons/web/static/src/js/main.js b/addons/web/static/src/js/main.js
new file mode 100644
index 00000000000..35f00254ba8
--- /dev/null
+++ b/addons/web/static/src/js/main.js
@@ -0,0 +1,27 @@
+odoo.define('web.web_client', function (require) {
+
+ const env = require('web.env');
+ const session = require("web.session");
+ const WebClient = require('web.WebClient');
+
+ owl.config.mode = env.isDebug() ? "dev" : "prod";
+ owl.Component.env = env;
+
+ const webClient = new WebClient();
+
+ /**
+ * Add the owl templates to the environment and start the web client.
+ */
+ async function startWebClient() {
+ await session.is_bound;
+ env.qweb.addTemplates(session.owlTemplates);
+
+ await owl.utils.whenReady();
+ webClient.setElement($(document.body));
+ webClient.start();
+ }
+
+ startWebClient();
+
+ return webClient;
+});
diff --git a/addons/web/static/src/js/public/public_env.js b/addons/web/static/src/js/public/public_env.js
new file mode 100644
index 00000000000..373c7b512b8
--- /dev/null
+++ b/addons/web/static/src/js/public/public_env.js
@@ -0,0 +1,24 @@
+odoo.define("web.public_env", function (require) {
+ "use strict";
+
+ const { _t } = require("web.core");
+ const rpc = require("web.rpc");
+
+ const qweb = new owl.QWeb({ translateFn: _t });
+
+ 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,
+ },
+ };
+});