diff options
Diffstat (limited to 'addons/web/static/src')
| -rw-r--r-- | addons/web/static/src/js/core/abstract_service.js | 9 | ||||
| -rw-r--r-- | addons/web/static/src/js/core/registry.js | 14 | ||||
| -rw-r--r-- | addons/web/static/src/js/core/service_mixins.js | 98 | ||||
| -rw-r--r-- | addons/web/static/src/js/core/utils.js | 31 | ||||
| -rw-r--r-- | addons/web/static/src/js/services/ajax_service.js | 3 | ||||
| -rw-r--r-- | addons/web/static/src/js/services/core.js | 1 | ||||
| -rw-r--r-- | addons/web/static/src/js/services/local_storage_service.js | 3 | ||||
| -rw-r--r-- | addons/web/static/src/js/services/report_service.js | 3 |
8 files changed, 87 insertions, 75 deletions
diff --git a/addons/web/static/src/js/core/abstract_service.js b/addons/web/static/src/js/core/abstract_service.js index cbd6c1322ca..14efef09b39 100644 --- a/addons/web/static/src/js/core/abstract_service.js +++ b/addons/web/static/src/js/core/abstract_service.js @@ -6,7 +6,6 @@ var Mixins = require('web.mixins'); var ServicesMixin = require('web.ServicesMixin'); var AbstractService = Class.extend(Mixins.EventDispatcherMixin, ServicesMixin, { - Services: [], dependencies: [], name: null, init: function (parent) { @@ -15,13 +14,5 @@ var AbstractService = Class.extend(Mixins.EventDispatcherMixin, ServicesMixin, { }, }); -var realExtend = AbstractService.extend; - -AbstractService.extend = function () { - var Service = realExtend.apply(this, arguments); - AbstractService.prototype.Services.push(Service); - return Service; -}; - return AbstractService; }); diff --git a/addons/web/static/src/js/core/registry.js b/addons/web/static/src/js/core/registry.js index d70c09e4ae0..f925b0ea30a 100644 --- a/addons/web/static/src/js/core/registry.js +++ b/addons/web/static/src/js/core/registry.js @@ -25,6 +25,7 @@ var Registry = Class.extend({ */ init: function (mapping) { this.map = Object.create(mapping || null); + this.listeners = []; // listening callbacks on newly added items. }, //-------------------------------------------------------------------------- @@ -34,12 +35,17 @@ var Registry = Class.extend({ /** * Add a key (and a value) to the registry. * + * Notify the listeners on newly added item in the registry. + * * @param {string} key * @param {any} value * @returns {Registry} can be used to chain add calls. */ add: function (key, value) { this.map[key] = value; + _.each(this.listeners, function (callback) { + callback(key, value); + }); return this; }, /** @@ -89,6 +95,14 @@ var Registry = Class.extend({ } return null; }, + /** + * Register a callback to execute when items are added to the registry. + * + * @param {function} callback function with parameters (key, value). + */ + onAdd: function (callback) { + this.listeners.push(callback); + }, }); return Registry; diff --git a/addons/web/static/src/js/core/service_mixins.js b/addons/web/static/src/js/core/service_mixins.js index d5abf727704..052e2a6a3d9 100644 --- a/addons/web/static/src/js/core/service_mixins.js +++ b/addons/web/static/src/js/core/service_mixins.js @@ -1,58 +1,86 @@ odoo.define('web.ServiceProviderMixin', function (require) { "use strict"; -var AbstractService = require('web.AbstractService'); -var utils = require('web.utils'); +var core = require('web.core'); var ServiceProviderMixin = { - services: {}, - init: function () { + services: {}, // dict containing deployed service instances + UndeployedServices: {}, // dict containing classes of undeployed services + /** + * @override + */ + init: function (parent) { + var self = this; // to properly instantiate services with this as parent, this mixin // assumes that it is used along the EventDispatcherMixin, and that // EventDispatchedMixin's init is called first - var self = this; - // as EventDispatcherMixin's init is already called, this handler has to - // be bound manually + // as EventDispatcherMixin's init is already called, this handler has + // to be bound manually this.on('call_service', this, this._call_service.bind(this)); - var sortedServices = this._sortServices(AbstractService.prototype.Services); - _.each(sortedServices, function (Service) { - var service = new Service(self); - self.services[service.name] = service; + // add already registered services from the service registry + _.each(core.serviceRegistry.map, function (Service, serviceName) { + self.UndeployedServices[serviceName] = Service; }); + this._deployServices(); + + // listen on newly added services + core.serviceRegistry.onAdd(function (serviceName, Service) { + self.UndeployedServices[serviceName] = Service; + self._deployServices(); + }); + }, + + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + /** + * @private + */ + _deployServices: function () { + var self = this; + var done = false; + while (!done) { + var Service = _.find(this.UndeployedServices, function (Service) { + // no missing dependency + return !_.some(Service.prototype.dependencies, function (depName) { + return !self.services[depName]; + }); + }); + if (Service) { + this.services[Service.prototype.name] = new Service(this); + delete this.UndeployedServices[Service.prototype.name]; + } else { + done = true; + } + } }, + + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + + /** + * Call the 'service', using data from the 'event' that + * has triggered the service call. + * + * For the ajax service, the arguments are extended with + * the target so that it can call back the caller. + * + * @private + * @param {OdooEvent} event + */ _call_service: function (event) { - var service = this.services[event.data.service]; var args = event.data.args || []; - // ajax service uses an extra 'target' argument for rpc if (event.data.service === 'ajax' && event.data.method === 'rpc') { + // ajax service uses an extra 'target' argument for rpc args = args.concat(event.target); } + var service = this.services[event.data.service]; var result = service[event.data.method].apply(service, args); event.data.callback(result); }, - _sortServices: function (services) { - var nodes = {}; - // Create nodes (services) - _.each(services, function (Service) { - nodes[Service.prototype.name] = Service.prototype.dependencies; - }); - var sorted; - try { - sorted = utils.topologicalSort(nodes); - } catch (err) { - console.warn('topologicalSort Error:', err.message); - sorted = nodes; - } - // Sort services based on sorted - // Note: we convert sorted to an object key=>index for efficiency - var sortedObj = _.invert(_.object(_.pairs(sorted))); - sorted = _.sortBy(services, function (Service) { - return sortedObj[Service.prototype.name]; - }); - - return sorted; - }, }; return ServiceProviderMixin; diff --git a/addons/web/static/src/js/core/utils.js b/addons/web/static/src/js/core/utils.js index 0b4af722203..1bdd9e70a69 100644 --- a/addons/web/static/src/js/core/utils.js +++ b/addons/web/static/src/js/core/utils.js @@ -301,37 +301,6 @@ var utils = { return fn(mod, Math.floor(x)); }, /** - * Topological sort of nodes - * - * @param {Object} nodes where key is name of node, and value is list of - * names of dependent nodes. - * @param {string[]} nodes[name] list of named dependencies of node having - * 'name' as its name. - * @return {string[]} topological sort of nodes by their names. - * @throws {Error} if there is at least one circular - * dependency between nodes - */ - topologicalSort: function (nodes) { - var sorted = []; - var unresolved = nodes; - while (!_.isEmpty(unresolved)) { - // Get all nodes that have no dependency - var resolvable = _.pick(unresolved, function (dependencies, name) { - return _.isEmpty(_.difference(dependencies, sorted)); - }); - if (_.isEmpty(resolvable)) { - throw new Error("Circular dependency detected"); - } - // Append them to sorted - sorted = _.union(sorted, _.keys(resolvable)); - // Remove these nodes from unresolved - _.each(resolvable, function (dependencies, name) { - unresolved = _.omit(unresolved, name); - }); - } - return sorted; - }, - /** * 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 diff --git a/addons/web/static/src/js/services/ajax_service.js b/addons/web/static/src/js/services/ajax_service.js index 480549347d4..3446f651a59 100644 --- a/addons/web/static/src/js/services/ajax_service.js +++ b/addons/web/static/src/js/services/ajax_service.js @@ -2,6 +2,7 @@ odoo.define('web.AjaxService', function (require) { "use strict"; var AbstractService = require('web.AbstractService'); +var core = require('web.core'); var session = require('web.session'); var AjaxService = AbstractService.extend({ @@ -21,6 +22,8 @@ var AjaxService = AbstractService.extend({ }, }); +core.serviceRegistry.add('ajax', AjaxService); + return AjaxService; }); diff --git a/addons/web/static/src/js/services/core.js b/addons/web/static/src/js/services/core.js index 73071a2a65d..522d6b07302 100644 --- a/addons/web/static/src/js/services/core.js +++ b/addons/web/static/src/js/services/core.js @@ -41,6 +41,7 @@ return { crash_registry: new Registry(), search_filters_registry: new Registry(), search_widgets_registry: new Registry(), + serviceRegistry: new Registry(), /** * @type {String} */ diff --git a/addons/web/static/src/js/services/local_storage_service.js b/addons/web/static/src/js/services/local_storage_service.js index a4527026238..7a8c803a0f9 100644 --- a/addons/web/static/src/js/services/local_storage_service.js +++ b/addons/web/static/src/js/services/local_storage_service.js @@ -2,6 +2,7 @@ odoo.define('web.LocalStorageService', function (require) { 'use strict'; var AbstractService = require('web.AbstractService'); +var core = require('web.core'); var localStorage = require('web.local_storage'); var LocalStorageService = AbstractService.extend({ @@ -20,6 +21,8 @@ var LocalStorageService = AbstractService.extend({ } }); +core.serviceRegistry.add('local_storage', LocalStorageService); + return LocalStorageService; }); diff --git a/addons/web/static/src/js/services/report_service.js b/addons/web/static/src/js/services/report_service.js index a2bb8759a24..cfd62c0499f 100644 --- a/addons/web/static/src/js/services/report_service.js +++ b/addons/web/static/src/js/services/report_service.js @@ -6,6 +6,7 @@ odoo.define('web.ReportService', function (require) { */ var AbstractService = require('web.AbstractService'); +var core = require('web.core'); var ReportService = AbstractService.extend({ name: 'report', @@ -28,6 +29,8 @@ var ReportService = AbstractService.extend({ }, }); +core.serviceRegistry.add('report', ReportService); + return ReportService; }); |
