[IMP] web_pwa_oca: Add support for require system

Service workers need to load "Odoo Bootstrap" to be able to use
"require". The problem is that "Odoo Bootstrap" does operations
on the DOM (by using jQuery) and to avoid errors a minimal
compatibility layer "jquery-sw-compat.js" has been created to
allow using "require" in the service worker.

Moved Service Worker (js) code from the xml to python.
This commit is contained in:
Alexandre D. Díaz
2021-03-11 15:08:42 +01:00
parent 54b074a50e
commit dfe4e8ae6c
11 changed files with 187 additions and 518 deletions

View File

@@ -0,0 +1,62 @@
/* Copyright 2020 Tecnativa - Alexandre D. Díaz
* License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). */
// Compatibility layer to load some Odoo modules
// This is a very simple implementation!!!
function JQuery (selector, context) {
return new JQuery.prototype.init(selector, context);
};
JQuery.prototype = {
init: function (selector, context) {
if (typeof selector === "function") {
selector();
}
},
// This is a hack, not a complete implementation!
// only expected to be used by boot.js
deparam: function (data) {
const params = data.split(',');
const res = [];
for (let param of params) {
res.push(param.split('='));
}
return _.object(res);
},
param: {
querystring: function () {
return "debug=1";
}
},
when: function (tasks) {
if (!(tasks instanceof Array)) {
tasks = [tasks];
}
return Promise.all(tasks).then((results) => {
return results.length === 1 ? results[0] : results;
});
},
};
class Deferred {
constructor() {
this.promise = new Promise((resolve, reject)=> {
this.reject = reject;
this.resolve = resolve;
})
}
};
JQuery.prototype.Deferred = () => new Deferred();
self.$ = JQuery;
self.$.deparam = JQuery.prototype.deparam;
self.$.param = JQuery.prototype.param;
self.$.Deferred = JQuery.prototype.Deferred;
self.$.when = JQuery.prototype.when;
self.window = self;

View File

@@ -1,150 +0,0 @@
/**
* Improved John Resig's inheritance, based on:
*
* Simple JavaScript Inheritance
* By John Resig http://ejohn.org/
* MIT Licensed.
*
* Adds "include()"
*
* Defines The Class object. That object can be used to define and inherit classes using
* the extend() method.
*
* Example::
*
* var Person = Class.extend({
* init: function(isDancing){
* this.dancing = isDancing;
* },
* dance: function(){
* return this.dancing;
* }
* });
*
* The init() method act as a constructor. This class can be instanced this way::
*
* var person = new Person(true);
* person.dance();
*
* The Person class can also be extended again:
*
* var Ninja = Person.extend({
* init: function(){
* this._super( false );
* },
* dance: function(){
* // Call the inherited version of dance()
* return this._super();
* },
* swingSword: function(){
* return true;
* }
* });
*
* When extending a class, each re-defined method can use this._super() to call the previous
* implementation of that method.
*
* @class Class
*/
function OdooClass(){}
var initializing = false;
var fnTest = /xyz/.test(function(){xyz();}) ? /\b_super\b/ : /.*/;
/**
* Subclass an existing class
*
* @param {Object} prop class-level properties (class attributes and instance methods) to set on the new class
*/
OdooClass.extend = function() {
var _super = this.prototype;
// Support mixins arguments
var args = _.toArray(arguments);
args.unshift({});
var prop = _.extend.apply(_,args);
// Instantiate a web class (but only create the instance,
// don't run the init constructor)
initializing = true;
var This = this;
var prototype = new This();
initializing = false;
// Copy the properties over onto the new prototype
_.each(prop, function(val, name) {
// Check if we're overwriting an existing function
prototype[name] = typeof prop[name] == "function" &&
fnTest.test(prop[name]) ?
(function(name, fn) {
return function() {
var tmp = this._super;
// Add a new ._super() method that is the same
// method but on the super-class
this._super = _super[name];
// The method only need to be bound temporarily, so
// we remove it when we're done executing
var ret = fn.apply(this, arguments);
this._super = tmp;
return ret;
};
})(name, prop[name]) :
prop[name];
});
// The dummy class constructor
function Class() {
if(this.constructor !== OdooClass){
throw new Error("You can only instanciate objects with the 'new' operator");
}
// All construction is actually done in the init method
this._super = null;
if (!initializing && this.init) {
var ret = this.init.apply(this, arguments);
if (ret) { return ret; }
}
return this;
}
Class.include = function (properties) {
_.each(properties, function(val, name) {
if (typeof properties[name] !== 'function'
|| !fnTest.test(properties[name])) {
prototype[name] = properties[name];
} else if (typeof prototype[name] === 'function'
&& prototype.hasOwnProperty(name)) {
prototype[name] = (function (name, fn, previous) {
return function () {
var tmp = this._super;
this._super = previous;
var ret = fn.apply(this, arguments);
this._super = tmp;
return ret;
};
})(name, properties[name], prototype[name]);
} else if (typeof _super[name] === 'function') {
prototype[name] = (function (name, fn) {
return function () {
var tmp = this._super;
this._super = _super[name];
var ret = fn.apply(this, arguments);
this._super = tmp;
return ret;
};
})(name, properties[name]);
}
});
};
// Populate our constructed prototype object
Class.prototype = prototype;
// Enforce the constructor to be what we expect
Class.constructor = Class;
// And make this class extendable
Class.extend = this.extend;
return Class;
};

View File

@@ -1,7 +1,3 @@
"use strict";
/* eslint strict: ["error", "global"] */
/* eslint-disable no-undef, no-empty-function, no-implicit-globals,
no-unused-vars */
/* Copyright 2020 Tecnativa - Alexandre D. Díaz
* License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). */
@@ -11,25 +7,36 @@ no-unused-vars */
* When the service worker is called to be installed from the "pwa_manager"
* this class is instantiated.
*/
var PWA = OdooClass.extend({
// eslint-disable-next-line
init: function (params) {
// To be overridden
},
/**
* @returns {Promise}
*/
installWorker: function () {
return Promise.resolve();
},
odoo.define("web_pwa_oca.PWA", function (require) {
"use strict";
/**
* @returns {Promise}
*/
activateWorker: function () {
return Promise.resolve();
},
const OdooClass = require("web.Class");
const PWA = OdooClass.extend({
// eslint-disable-next-line
init: function (params) {
// To be overridden
},
/**
* @returns {Promise}
*/
installWorker: function () {
// To be overridden
return Promise.resolve();
},
/**
* @returns {Promise}
*/
activateWorker: function () {
// To be overridden
return Promise.resolve();
},
});
return PWA;
});