summaryrefslogtreecommitdiff
path: root/addons/web/static/src/js/framework/data_manager.js
diff options
context:
space:
mode:
authorGéry Debongnie <ged@odoo.com>2017-03-05 10:05:56 +0100
committerAaron Bohy <aab@odoo.com>2017-04-11 19:44:38 +0200
commit905e01921f3c3ef43ace6fc537d1d8c0d280002c (patch)
tree265c43ab21c5401a5d9f0f3d64d86f1ac417451c /addons/web/static/src/js/framework/data_manager.js
parent54d4c73af4ad05c7640d28c1892247c9538b8017 (diff)
[REF] web, *: redesign all JS views
This commit introduce a full redesign of all JS views. We started basically from scratch. The goal was to unify all the various views under a common framework, to make them testable, to make then usable in different conditions (in studio, or in the frontend), and to make our lives easier. Some important points are: - we introduced new coding guidelines (camelCase, 80 chars width, ...) - we have a brand new testing framework (still QUnit based) - kanban view moved to the web addon - calendar view (formerly web_calender) moved to web as well - the tree view was removed - all new code should be documented We hope that this code is the start of a new era for the Odoo web client, we want to have a high quality codebase, well documented, well tested, well designed. Work done by the framework team: mostly aab, ged, chm, dmo, qsm
Diffstat (limited to 'addons/web/static/src/js/framework/data_manager.js')
-rw-r--r--addons/web/static/src/js/framework/data_manager.js280
1 files changed, 0 insertions, 280 deletions
diff --git a/addons/web/static/src/js/framework/data_manager.js b/addons/web/static/src/js/framework/data_manager.js
deleted file mode 100644
index 55a4b4da15b..00000000000
--- a/addons/web/static/src/js/framework/data_manager.js
+++ /dev/null
@@ -1,280 +0,0 @@
-odoo.define('web.DataManager', function (require) {
-"use strict";
-
-var core = require('web.core');
-var Model = require('web.DataModel');
-var session = require('web.session');
-var utils = require('web.utils');
-
-function traverse(tree, f) {
- if (f(tree)) {
- _.each(tree.children, function(c) { traverse(c, f); });
- }
-}
-
-return core.Class.extend({
- init: function () {
- this.Filters = new Model('ir.filters');
- this._init_cache();
- },
-
- _init_cache: function () {
- this._cache = {
- actions: {},
- fields_views: {},
- fields: {},
- filters: {},
- views: {},
- };
- },
-
- /**
- * Invalidates the whole cache
- * Suggestion: could be refined to invalidate some part of the cache
- */
- invalidate: function () {
- this._init_cache();
- },
-
- /**
- * Loads an action from its id or xmlid.
- *
- * @param {int|string} [action_id] the action id or xmlid
- * @param {Object} [additional_context] used to load the action
- * @return {Deferred} resolved with the action whose id or xmlid is action_id
- */
- load_action: function (action_id, additional_context) {
- var self = this;
- var key = this._gen_key(action_id, additional_context || {});
-
- if (!this._cache.actions[key]) {
- this._cache.actions[key] = session.rpc("/web/action/load", {
- action_id: action_id,
- additional_context : additional_context,
- }).then(function (action) {
- self._cache.actions[key] = action.no_cache ? null : self._cache.actions[key];
- return action;
- }, this._invalidate.bind(this, this._cache.actions, key));
- }
-
- return this._cache.actions[key].then(function (action) {
- return $.extend(true, {}, action);
- });
- },
-
- /**
- * Loads various information concerning views: fields_view for each view,
- * and optionally filters and fields.
- *
- * @param {Object} [dataset] the dataset for which the views are loaded
- * @param {Array} [views_descr] array of [view_id, view_type]
- * @param {Object} [options] dictionnary of various options:
- * - options.load_filters: whether or not to load the filters,
- * - options.action_id: the action_id (required to load filters),
- * - options.load_fields: whether or not to load the fields,
- * - options.toolbar: whether or not a toolbar will be displayed,
- * @return {Deferred} resolved with the requested views information
- */
- load_views: function (dataset, views_descr, options) {
- var self = this;
- var model = dataset.model;
- var context = dataset.get_context();
- var key = this._gen_key(model, views_descr, options || {}, context);
-
- if (!this._cache.views[key]) {
- // Don't load fields or filters if already in cache
- options.load_fields = options.load_fields && !this._cache.fields[model];
- var filters_key;
- if (options.load_filters) {
- filters_key = this._gen_key(model, options.action_id);
- options.load_filters = !this._cache.filters[filters_key];
- }
-
- this._cache.views[key] = dataset.call('load_views', {
- views: views_descr,
- options: options,
- context: context,
- }).then(function (result) {
- // Postprocess fields_views and insert them into the fields_views cache
- result.fields_views = _.mapObject(result.fields_views, self._postprocess_fvg.bind(self)); // FIXME: lazy postprocess?
- _.each(views_descr, function (view_descr) {
- var toolbar = options.toolbar && view_descr[1] !== 'search';
- var fv_key = self._gen_key(model, view_descr[0], view_descr[1], toolbar, context);
- self._cache.fields_views[fv_key] = $.when(result.fields_views[view_descr[1]]);
- });
-
- // Insert filters, if any, into the filters cache
- if (result.filters) {
- self._cache.filters[filters_key] = $.when(result.filters);
- }
-
- // Insert fields, if any, into the fields cache
- if (result.fields) {
- self._cache.fields[model] = $.when(result.fields);
- }
-
- return result.fields_views;
- }, this._invalidate.bind(this, this._cache.views, key));
- }
-
- return this._cache.views[key];
- },
-
- /**
- * Loads the fields_view of a given model, view_type and optional view_id.
- *
- * @param {Object} [dataset] the dataset for which the fields_view is loaded
- * @param {int} [view_id] the id of the view (optional)
- * @param {string} [view_type] the type of the view
- * @param {Boolean} [toolbar] whether or not a toolbar will be displayed
- * @return {Deferred} resolved with the requested fields_view
- */
- load_fields_view: function (dataset, view_id, view_type, toolbar) {
- var key = this._gen_key(dataset.model, view_id, view_type, toolbar, dataset.get_context());
- if (!this._cache.fields_views[key]) {
- this._cache.fields_views[key] = dataset.call('fields_view_get', {
- view_id: view_id,
- view_type: view_type,
- toolbar: toolbar,
- context: dataset.get_context(),
- }).then(this._postprocess_fvg.bind(this), this._invalidate.bind(this, this._cache.fields_views, key));
- }
- return this._cache.fields_views[key];
- },
-
- /**
- * Loads the fields of a given model.
- *
- * @param {Object} [dataset] the dataset for which the fields are loaded
- * @return {Deferred} resolved with the requested fields
- */
- load_fields: function (dataset) {
- if (!this._cache.fields[dataset.model]) {
- this._cache.fields[dataset.model] = dataset.call('fields_get', {
- context: dataset.get_context(),
- }).fail(this._invalidate.bind(this, this._cache.fields, dataset.model));
- }
- return this._cache.fields[dataset.model];
- },
-
- /**
- * Loads the filters of a given model and optional action id.
- *
- * @param {Object} [dataset] the dataset for which the filters are loaded
- * @param {int} [action_id] the id of the action (optional)
- * @return {Deferred} resolved with the requested filters
- */
- load_filters: function (dataset, action_id) {
- var key = this._gen_key(dataset.model, action_id);
- if (!this._cache.filters[key]) {
- this._cache.filters[key] = this.Filters.call('get_filters', [dataset.model, action_id], {
- context: dataset.get_context(),
- }).fail(this._invalidate.bind(this, this._cache.filters, key));
- }
- return this._cache.filters[key];
- },
-
- /**
- * Calls 'create_or_replace' on 'ir_filters'.
- *
- * @param {Object} [filter] the filter description
- * @return {Deferred} resolved with the id of the created or replaced filter
- */
- create_filter: function (filter) {
- var self = this;
- return this.Filters
- .call('create_or_replace', [filter])
- .then(function (filter_id) {
- var key = [
- filter.model_id,
- filter.action_id || false,
- ].join(',');
- self._invalidate(self._cache.filters, key);
- return filter_id;
- });
- },
-
- /**
- * Calls 'unlink' on 'ir_filters'.
- *
- * @param {Object} [filter] the description of the filter to remove
- * @return {Deferred}
- */
- delete_filter: function (filter) {
- var self = this;
- return this.Filters
- .call('unlink', [filter.id])
- .then(function () {
- self._cache.filters = {}; // invalidate cache
- });
- },
-
- /**
- * Private function that postprocesses fields_view (mainly parses the arch attribute)
- */
- _postprocess_fvg: function (fields_view) {
- var self = this;
-
- // Parse and process arch
- var doc = $.parseXML(fields_view.arch).documentElement;
- var fields = fields_view.fields;
- fields_view.arch = utils.xml_to_json(doc, (doc.nodeName.toLowerCase() !== 'kanban'));
- traverse(fields_view.arch, function(node) {
- if (typeof node === 'string') {
- return false;
- }
- if (node.tag === 'field') {
- fields[node.attrs.name].__attrs = node.attrs;
- if (fields[node.attrs.name].type === 'many2one') { // FIXME: this shouldn't be done here
- if (node.attrs.widget === 'statusbar' || node.attrs.widget === 'radio') {
- fields[node.attrs.name].__fetch_status = true;
- } else if (node.attrs.widget === 'selection') {
- fields[node.attrs.name].__fetch_selection = true;
- }
- }
- if (node.attrs.widget === 'many2many_checkboxes') {
- fields[node.attrs.name].__fetch_many2manys = true;
- }
- return false;
- }
- return node.tag !== 'arch';
- });
-
- // Special case for id's
- if ('id' in fields_view.fields) {
- var id_field = fields_view.fields.id;
- id_field.original_type = id_field.type;
- id_field.type = 'id';
- }
-
- // Process inner views (one2manys)
- _.each(fields_view.fields, function(field) {
- _.each(field.views || {}, function(view) {
- self._postprocess_fvg(view);
- });
- });
-
- return fields_view;
- },
-
- /**
- * Private function that generates a cache key from its arguments
- */
- _gen_key: function () {
- return _.map(Array.prototype.slice.call(arguments), function (arg) {
- if (!arg) {
- return false;
- }
- return _.isObject(arg) ? JSON.stringify(arg) : arg;
- }).join(',');
- },
-
- /**
- * Private function that invalidates a cache entry
- */
- _invalidate: function (cache, key) {
- delete cache[key];
- },
-});
-
-});