summaryrefslogtreecommitdiff
path: root/addons/web/static/src/js
diff options
context:
space:
mode:
authorJulien Mougenot <jum@odoo.com>2020-03-23 13:03:47 +0000
committerJulien Mougenot <jum@odoo.com>2020-03-24 09:57:00 +0000
commit70d426b948e180850ad436708728d6bb127c5d86 (patch)
tree37a411cf78ce9f19edcda2bc74b6a6462fa72464 /addons/web/static/src/js
parent0ebbd1848f1c6fbf56cf3df7e4b5ac0baa6e63b3 (diff)
[FIX] web: fix dataManager loading caches
Before this commit, coming back on a view when in 'debug=assets' would erase the previously loaded favorites with an 'undefined' value. This was due to an incorrect cache invalidation mechanism in the DataManager's load_views' method. Now the views and filters caches are properly loaded if any of them has been invalidated. closes odoo/odoo#48085 Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
Diffstat (limited to 'addons/web/static/src/js')
-rw-r--r--addons/web/static/src/js/services/data_manager.js119
1 files changed, 58 insertions, 61 deletions
diff --git a/addons/web/static/src/js/services/data_manager.js b/addons/web/static/src/js/services/data_manager.js
index 12d7ce24f8d..f5bb482a66d 100644
--- a/addons/web/static/src/js/services/data_manager.js
+++ b/addons/web/static/src/js/services/data_manager.js
@@ -16,7 +16,6 @@ return core.Class.extend({
_init_cache: function () {
this._cache = {
actions: {},
- fields_views: {},
filters: {},
views: {},
};
@@ -52,7 +51,7 @@ return core.Class.extend({
}).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));
+ }).guardedCatch(() => this._invalidate('actions', key));
}
return this._cache.actions[key].then(function (action) {
@@ -68,78 +67,74 @@ return core.Class.extend({
* @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:
+ * @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: function (params, options) {
- var self = this;
-
- var model = params.model;
- var context = params.context;
- var views_descr = params.views_descr;
- var key = this._gen_key(model, views_descr, options || {}, context);
-
- if (config.isDebug('assets') || !this._cache.views[key]) {
- // Don't load filters if already in cache
- 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] = rpc.query({
+ 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: {
- views: views_descr,
- options: options,
- context: context,
- },
- model: model,
+ kwargs: { context, options, views: views_descr },
+ model,
method: 'load_views',
- }).then(async result => {
+ }).then(result => {
// Freeze the fields dict as it will be shared between views and
// no one should edit it
utils.deepFreeze(result.fields);
-
- // Insert views into the fields_views cache
- for (const view_descr of views_descr) {
- var toolbar = options.toolbar && view_descr[1] !== 'search';
- var fv_key = self._gen_key(model, view_descr[0], view_descr[1], toolbar, context);
- var fvg = result.fields_views[view_descr[1]];
- if (view_descr[1] === 'search') {
- fvg.favoriteFilters = result.filters;
- }
+ for (const [viewId, viewType] of views_descr) {
+ const fvg = result.fields_views[viewType];
fvg.viewFields = fvg.fields;
fvg.fields = result.fields;
- self._cache.fields_views[fv_key] = Promise.resolve(fvg);
}
// Insert filters, if any, into the filters cache
- if (result.filters) {
- self._cache.filters[filters_key] = Promise.resolve(result.filters);
+ if (shouldLoadFilters) {
+ this._cache.filters[filtersKey] = Promise.resolve(result.filters);
}
return result.fields_views;
- }, this._invalidate.bind(this, this._cache.views, key));
+ }).guardedCatch(() => this._invalidate('views', viewsKey));
}
-
- return this._cache.views[key];
+ 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 {string} params.modelName
+ * @param {number} params.actionId
* @param {Object} params.context
- * @param {integer} params.actionId
+ * @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) {
- var key = this._gen_key(params.modelName, params.actionId);
- if (config.isDebug('assets') || !this._cache.filters[key]) {
+ 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: {
@@ -148,7 +143,7 @@ return core.Class.extend({
},
model: 'ir.filters',
method: 'get_filters',
- }).guardedCatch(this._invalidate.bind(this, this._cache.filters, key));
+ }).guardedCatch(() => this._invalidate('filters', key));
}
return this._cache.filters[key];
},
@@ -160,18 +155,14 @@ return core.Class.extend({
* @return {Promise} resolved with the id of the created or replaced filter
*/
create_filter: function (filter) {
- var self = this;
return rpc.query({
args: [filter],
model: 'ir.filters',
method: 'create_or_replace',
})
- .then(function (filterId) {
- var key = [
- filter.model_id,
- filter.action_id || false,
- ].join(',');
- self._invalidate(self._cache.filters, key);
+ .then(filterId => {
+ const filtersKey = this._gen_key(filter.model_id, filter.action_id);
+ this._invalidate('filters', filtersKey);
return filterId;
});
},
@@ -183,15 +174,13 @@ return core.Class.extend({
* @return {Promise}
*/
delete_filter: function (filterId) {
- var self = this;
return rpc.query({
args: [filterId],
model: 'ir.filters',
method: 'unlink',
})
- .then(function () {
- self._cache.filters = {}; // invalidate cache
- });
+ // Invalidate the whole cache since we have no idea where the filter came from.
+ .then(() => this._invalidate('filters'));
},
/**
@@ -207,10 +196,18 @@ return core.Class.extend({
},
/**
- * Private function that invalidates a cache entry
+ * Invalidate a cache entry or a whole cache section.
+ *
+ * @private
+ * @param {string} section
+ * @param {string} key
*/
- _invalidate: function (cache, key) {
- delete cache[key];
+ _invalidate(section, key) {
+ if (key) {
+ delete this._cache[section][key];
+ } else {
+ this._cache[section] = {};
+ }
},
});