diff options
| author | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
|---|---|---|
| committer | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
| commit | 3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch) | |
| tree | a44932296ef4a9b71d5f010906253d8c53727726 /addons/web/static/src/js/services/data_manager.js | |
| parent | 0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff) | |
initial commit 2
Diffstat (limited to 'addons/web/static/src/js/services/data_manager.js')
| -rw-r--r-- | addons/web/static/src/js/services/data_manager.js | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/addons/web/static/src/js/services/data_manager.js b/addons/web/static/src/js/services/data_manager.js new file mode 100644 index 00000000..f5bb482a --- /dev/null +++ b/addons/web/static/src/js/services/data_manager.js @@ -0,0 +1,225 @@ +odoo.define('web.DataManager', function (require) { +"use strict"; + +var config = require('web.config'); +var core = require('web.core'); +var rpc = require('web.rpc'); +var session = require('web.session'); +var utils = require('web.utils'); + +return core.Class.extend({ + init: function () { + this._init_cache(); + core.bus.on('clear_cache', this, this.invalidate.bind(this)); + }, + + _init_cache: function () { + this._cache = { + actions: {}, + filters: {}, + views: {}, + }; + }, + + /** + * Invalidates the whole cache + * Suggestion: could be refined to invalidate some part of the cache + */ + invalidate: function () { + session.invalidateCacheKey('load_menus'); + 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 {Promise} 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 (config.isDebug('assets') || !this._cache.actions[key]) { + this._cache.actions[key] = rpc.query({ + route: "/web/action/load", + params: { + 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; + }).guardedCatch(() => this._invalidate('actions', key)); + } + + return this._cache.actions[key].then(function (action) { + return $.extend(true, {}, action); + }); + }, + + /** + * Loads various information concerning views: fields_view for each view, + * the fields of the corresponding model, and optionally the filters. + * + * @param {Object} params + * @param {String} params.model + * @param {Object} params.context + * @param {Array} params.views_descr array of [view_id, view_type] + * @param {Object} [options={}] dictionary of various options: + * - options.load_filters: whether or not to load the filters, + * - options.action_id: the action_id (required to load filters), + * - options.toolbar: whether or not a toolbar will be displayed, + * @return {Promise} resolved with the requested views information + */ + load_views: async function ({ model, context, views_descr } , options = {}) { + const viewsKey = this._gen_key(model, views_descr, options, context); + const filtersKey = this._gen_key(model, options.action_id); + const withFilters = Boolean(options.load_filters); + const shouldLoadViews = config.isDebug('assets') || !this._cache.views[viewsKey]; + const shouldLoadFilters = config.isDebug('assets') || ( + withFilters && !this._cache.filters[filtersKey] + ); + if (shouldLoadViews) { + // Views info should be loaded + options.load_filters = shouldLoadFilters; + this._cache.views[viewsKey] = rpc.query({ + args: [], + kwargs: { context, options, views: views_descr }, + model, + method: 'load_views', + }).then(result => { + // Freeze the fields dict as it will be shared between views and + // no one should edit it + utils.deepFreeze(result.fields); + for (const [viewId, viewType] of views_descr) { + const fvg = result.fields_views[viewType]; + fvg.viewFields = fvg.fields; + fvg.fields = result.fields; + } + + // Insert filters, if any, into the filters cache + if (shouldLoadFilters) { + this._cache.filters[filtersKey] = Promise.resolve(result.filters); + } + return result.fields_views; + }).guardedCatch(() => this._invalidate('views', viewsKey)); + } + const result = await this._cache.views[viewsKey]; + if (withFilters && result.search) { + if (shouldLoadFilters) { + await this.load_filters({ + actionId: options.action_id, + context, + forceReload: false, + modelName: model, + }); + } + result.search.favoriteFilters = await this._cache.filters[filtersKey]; + } + return result; + }, + + /** + * Loads the filters of a given model and optional action id. + * + * @param {Object} params + * @param {number} params.actionId + * @param {Object} params.context + * @param {boolean} [params.forceReload=true] can be set to false to prevent forceReload + * @param {string} params.modelName + * @return {Promise} resolved with the requested filters + */ + load_filters: function (params) { + const key = this._gen_key(params.modelName, params.actionId); + const forceReload = params.forceReload !== false && config.isDebug('assets'); + if (forceReload || !this._cache.filters[key]) { + this._cache.filters[key] = rpc.query({ + args: [params.modelName, params.actionId], + kwargs: { + context: params.context || {}, + // get_context() de dataset + }, + model: 'ir.filters', + method: 'get_filters', + }).guardedCatch(() => this._invalidate('filters', key)); + } + return this._cache.filters[key]; + }, + + /** + * Calls 'create_or_replace' on 'ir_filters'. + * + * @param {Object} [filter] the filter description + * @return {Promise} resolved with the id of the created or replaced filter + */ + create_filter: function (filter) { + return rpc.query({ + args: [filter], + model: 'ir.filters', + method: 'create_or_replace', + }) + .then(filterId => { + const filtersKey = this._gen_key(filter.model_id, filter.action_id); + this._invalidate('filters', filtersKey); + return filterId; + }); + }, + + /** + * Calls 'unlink' on 'ir_filters'. + * + * @param {integer} filterId Id of the filter to remove + * @return {Promise} + */ + delete_filter: function (filterId) { + return rpc.query({ + args: [filterId], + model: 'ir.filters', + method: 'unlink', + }) + // Invalidate the whole cache since we have no idea where the filter came from. + .then(() => this._invalidate('filters')); + }, + + /** + * 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(','); + }, + + /** + * Invalidate a cache entry or a whole cache section. + * + * @private + * @param {string} section + * @param {string} key + */ + _invalidate(section, key) { + if (key) { + delete this._cache[section][key]; + } else { + this._cache[section] = {}; + } + }, +}); + +}); + +odoo.define('web.data_manager', function (require) { +"use strict"; + +var DataManager = require('web.DataManager'); + +var data_manager = new DataManager(); + +return data_manager; + +}); |
