From c0809dd41d9866c072822b36eae6b57cbc918cc9 Mon Sep 17 00:00:00 2001 From: Martin Geubelle Date: Wed, 25 Apr 2018 13:53:37 +0200 Subject: [FIX] web: reload progressbar values after archiving records Before this, the progressbar values were not updated (both count and progress) after archiving all the records of a column. Multiple things have been done here to update it. Firstly, a optimization had been done to avoid reloading the progressbar when updating a column ; this optimization was not correct due to this precise use case. This will update the progressbar. Secondly, the `aggregateValues` are reset when putting empty groups back in the datapoint. This attribute is used to compute the counter if a `sum_field` is set on the progressbar widget. It needs to be reset because the loop that computes it won't iterate on empty groups. Eventually, the mockRPC of the progressbar route was not taking the `group_by` argument into account (probably a typo). --- addons/web/static/src/js/views/basic/basic_model.js | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'addons/web/static/src/js/views/basic/basic_model.js') diff --git a/addons/web/static/src/js/views/basic/basic_model.js b/addons/web/static/src/js/views/basic/basic_model.js index e311378eee4..9d4dc877473 100644 --- a/addons/web/static/src/js/views/basic/basic_model.js +++ b/addons/web/static/src/js/views/basic/basic_model.js @@ -3842,6 +3842,10 @@ var BasicModel = AbstractModel.extend({ var emptyGroupsIDs = _.difference(_.pluck(previousGroups, 'id'), list.data); _.each(emptyGroupsIDs, function (groupID) { list.data.push(groupID); + var emptyGroup = self.localData[groupID]; + // this attribute hasn't been updated in the previous + // loop for empty groups + emptyGroup.aggregateValues = {}; }); } return $.when.apply($, defs).then(function () { -- cgit v1.2.3 From 27c9f838d35f36f6fe8d68068ed96c5c58d9d186 Mon Sep 17 00:00:00 2001 From: "Lucas Perais (lpe)" Date: Fri, 20 Apr 2018 14:43:19 +0200 Subject: [FIX] web: inline views should share their fields Have a One2Many The views of that o2m define two inline views: the list and the form in the list view, put a field that isn't in the form and used in a domain Try to add an item to the list The form pops up Fill in the data and save & close Before this commit: It crashed when evaluating the domain on a field using the field that is not in the form After this commit: Subviews share their fields in a special object on the parent record In our case, the form view checks in that shared resource if the fields it is supposed to initialize are there. Hence, this flow doesn't crash anymore OPW 1837511 closes #24350 --- .../web/static/src/js/views/basic/basic_model.js | 38 +++++++++++++++------- 1 file changed, 26 insertions(+), 12 deletions(-) (limited to 'addons/web/static/src/js/views/basic/basic_model.js') diff --git a/addons/web/static/src/js/views/basic/basic_model.js b/addons/web/static/src/js/views/basic/basic_model.js index 9d4dc877473..9d95f893bc7 100644 --- a/addons/web/static/src/js/views/basic/basic_model.js +++ b/addons/web/static/src/js/views/basic/basic_model.js @@ -208,6 +208,8 @@ var BasicModel = AbstractModel.extend({ * assume main viewType from the record * @param {Array} [options.fieldNames] list of field names for which a * default value must be generated (used to complete the values dict) + * @param {record} [options.parentRecord] The parent record of the current one + * usefull to get all the fields from all the views the model can be displayed on. * @returns {Deferred} */ applyDefaultValues: function (recordID, values, options) { @@ -219,6 +221,20 @@ var BasicModel = AbstractModel.extend({ var fieldName; record._changes = record._changes || {}; + /* Get the field's definition in the parent record if it is + * not present in the current one. + * + * @param {string} fieldName The name of the field we try to get the definition for + * in the parent record + * @returns {Object} the field's definition + */ + function getFieldsFromOtherViews(fieldName) { + return options.parentRecord + && options.parentRecord.mergedViewsFields[viewType] + && options.parentRecord.mergedViewsFields[viewType][fieldName] + || {}; + } + // ignore values for non requested fields (for instance, fields that are // not in the view) values = _.pick(values, fieldNames); @@ -227,7 +243,7 @@ var BasicModel = AbstractModel.extend({ for (var i = 0; i < fieldNames.length; i++) { fieldName = fieldNames[i]; if (!(fieldName in values) && !(fieldName in record._changes)) { - field = record.fields[fieldName]; + field = record.fields[fieldName] || getFieldsFromOtherViews(fieldName); if (field.type === 'float' || field.type === 'integer' || field.type === 'monetary') { @@ -243,7 +259,7 @@ var BasicModel = AbstractModel.extend({ // parse each value and create dataPoints for relational fields var defs = []; for (fieldName in values) { - field = record.fields[fieldName]; + field = record.fields[fieldName] || getFieldsFromOtherViews(fieldName); record.data[fieldName] = null; var dp; if (field.type === 'many2one' && values[fieldName]) { @@ -2495,6 +2511,7 @@ var BasicModel = AbstractModel.extend({ var fieldNames = options && options.fieldNames || record.getFieldNames(); var viewType = options && options.viewType || record.viewType; _.each(fieldNames, function (fieldName) { + var mergedViewsFields = record.fieldsInfo[viewType] && record.fieldsInfo[viewType][fieldName].mergeViewsFields || {}; var field = record.fields[fieldName]; if (field.type === 'one2many' || field.type === 'many2many') { var fieldInfo = record.fieldsInfo[viewType][fieldName]; @@ -2517,6 +2534,7 @@ var BasicModel = AbstractModel.extend({ rawContext: rawContext, relationField: field.relation_field, viewType: view ? view.type : fieldInfo.viewType, + mergedViewsFields: mergedViewsFields, }); record.data[fieldName] = list.id; if (!fieldInfo.__no_fetch) { @@ -3221,6 +3239,8 @@ var BasicModel = AbstractModel.extend({ * @param {string} [params.type='record'|'list'] * @param {[type]} [params.value] * @param {string} [params.viewType] the type of the view, e.g. 'list' or 'form' + * @param {Object} [params.mergedViewsFields] Contains for each viewType + * all the other viewTypes' fields plus its own to allow switching views more smoothly * @returns {Object} the resource created */ _makeDataPoint: function (params) { @@ -3280,6 +3300,7 @@ var BasicModel = AbstractModel.extend({ type: type, // 'record' | 'list' value: value, viewType: params.viewType, + mergedViewsFields: params.mergedViewsFields || {}, }; // _editionViewType is a dict whose keys are field names and which is populated when a field @@ -3323,22 +3344,15 @@ var BasicModel = AbstractModel.extend({ */ _makeDefaultRecord: function (modelName, params) { var self = this; - + var parentRecord = self.localData[params.parentID]; var determineExtraFields = function() { // Fields that are present in the originating view, that need to be initialized // Hence preventing their value to crash when getting back to the originating view - var parentRecord = self.localData[params.parentID]; - var originView = parentRecord && parentRecord.fieldsInfo; if (!originView || !originView[parentRecord.viewType]) return []; - var fieldsFromOrigin = _.filter(Object.keys(originView[parentRecord.viewType]), - function(fieldname) { - return params.fields[fieldname] !== undefined; - }); - - return fieldsFromOrigin; + return Object.keys(originView[parentRecord.viewType]); } var fieldNames = Object.keys(params.fieldsInfo[params.viewType]); @@ -3363,7 +3377,7 @@ var BasicModel = AbstractModel.extend({ viewType: params.viewType, }); - return self.applyDefaultValues(record.id, result, {fieldNames: _.union(fieldNames, extraFields)}) + return self.applyDefaultValues(record.id, result, {fieldNames: _.union(fieldNames, extraFields), parentRecord: parentRecord}) .then(function () { var def = $.Deferred(); self._performOnChange(record, fields_key).always(function () { -- cgit v1.2.3 From f53659269164a2ddc9c15736c438c5111eab98cb Mon Sep 17 00:00:00 2001 From: Nicolas Martinelli Date: Thu, 3 May 2018 08:30:55 +0200 Subject: [FIX] web: inline views should share their fields This causes issues (already 3, and counting...) This reverts commit 27c9f838d35f36f6fe8d68068ed96c5c58d9d186. opw-1840984 opw-1841041 opw-1841000 --- .../web/static/src/js/views/basic/basic_model.js | 38 +++++++--------------- 1 file changed, 12 insertions(+), 26 deletions(-) (limited to 'addons/web/static/src/js/views/basic/basic_model.js') diff --git a/addons/web/static/src/js/views/basic/basic_model.js b/addons/web/static/src/js/views/basic/basic_model.js index 9d95f893bc7..9d4dc877473 100644 --- a/addons/web/static/src/js/views/basic/basic_model.js +++ b/addons/web/static/src/js/views/basic/basic_model.js @@ -208,8 +208,6 @@ var BasicModel = AbstractModel.extend({ * assume main viewType from the record * @param {Array} [options.fieldNames] list of field names for which a * default value must be generated (used to complete the values dict) - * @param {record} [options.parentRecord] The parent record of the current one - * usefull to get all the fields from all the views the model can be displayed on. * @returns {Deferred} */ applyDefaultValues: function (recordID, values, options) { @@ -221,20 +219,6 @@ var BasicModel = AbstractModel.extend({ var fieldName; record._changes = record._changes || {}; - /* Get the field's definition in the parent record if it is - * not present in the current one. - * - * @param {string} fieldName The name of the field we try to get the definition for - * in the parent record - * @returns {Object} the field's definition - */ - function getFieldsFromOtherViews(fieldName) { - return options.parentRecord - && options.parentRecord.mergedViewsFields[viewType] - && options.parentRecord.mergedViewsFields[viewType][fieldName] - || {}; - } - // ignore values for non requested fields (for instance, fields that are // not in the view) values = _.pick(values, fieldNames); @@ -243,7 +227,7 @@ var BasicModel = AbstractModel.extend({ for (var i = 0; i < fieldNames.length; i++) { fieldName = fieldNames[i]; if (!(fieldName in values) && !(fieldName in record._changes)) { - field = record.fields[fieldName] || getFieldsFromOtherViews(fieldName); + field = record.fields[fieldName]; if (field.type === 'float' || field.type === 'integer' || field.type === 'monetary') { @@ -259,7 +243,7 @@ var BasicModel = AbstractModel.extend({ // parse each value and create dataPoints for relational fields var defs = []; for (fieldName in values) { - field = record.fields[fieldName] || getFieldsFromOtherViews(fieldName); + field = record.fields[fieldName]; record.data[fieldName] = null; var dp; if (field.type === 'many2one' && values[fieldName]) { @@ -2511,7 +2495,6 @@ var BasicModel = AbstractModel.extend({ var fieldNames = options && options.fieldNames || record.getFieldNames(); var viewType = options && options.viewType || record.viewType; _.each(fieldNames, function (fieldName) { - var mergedViewsFields = record.fieldsInfo[viewType] && record.fieldsInfo[viewType][fieldName].mergeViewsFields || {}; var field = record.fields[fieldName]; if (field.type === 'one2many' || field.type === 'many2many') { var fieldInfo = record.fieldsInfo[viewType][fieldName]; @@ -2534,7 +2517,6 @@ var BasicModel = AbstractModel.extend({ rawContext: rawContext, relationField: field.relation_field, viewType: view ? view.type : fieldInfo.viewType, - mergedViewsFields: mergedViewsFields, }); record.data[fieldName] = list.id; if (!fieldInfo.__no_fetch) { @@ -3239,8 +3221,6 @@ var BasicModel = AbstractModel.extend({ * @param {string} [params.type='record'|'list'] * @param {[type]} [params.value] * @param {string} [params.viewType] the type of the view, e.g. 'list' or 'form' - * @param {Object} [params.mergedViewsFields] Contains for each viewType - * all the other viewTypes' fields plus its own to allow switching views more smoothly * @returns {Object} the resource created */ _makeDataPoint: function (params) { @@ -3300,7 +3280,6 @@ var BasicModel = AbstractModel.extend({ type: type, // 'record' | 'list' value: value, viewType: params.viewType, - mergedViewsFields: params.mergedViewsFields || {}, }; // _editionViewType is a dict whose keys are field names and which is populated when a field @@ -3344,15 +3323,22 @@ var BasicModel = AbstractModel.extend({ */ _makeDefaultRecord: function (modelName, params) { var self = this; - var parentRecord = self.localData[params.parentID]; + var determineExtraFields = function() { // Fields that are present in the originating view, that need to be initialized // Hence preventing their value to crash when getting back to the originating view + var parentRecord = self.localData[params.parentID]; + var originView = parentRecord && parentRecord.fieldsInfo; if (!originView || !originView[parentRecord.viewType]) return []; - return Object.keys(originView[parentRecord.viewType]); + var fieldsFromOrigin = _.filter(Object.keys(originView[parentRecord.viewType]), + function(fieldname) { + return params.fields[fieldname] !== undefined; + }); + + return fieldsFromOrigin; } var fieldNames = Object.keys(params.fieldsInfo[params.viewType]); @@ -3377,7 +3363,7 @@ var BasicModel = AbstractModel.extend({ viewType: params.viewType, }); - return self.applyDefaultValues(record.id, result, {fieldNames: _.union(fieldNames, extraFields), parentRecord: parentRecord}) + return self.applyDefaultValues(record.id, result, {fieldNames: _.union(fieldNames, extraFields)}) .then(function () { var def = $.Deferred(); self._performOnChange(record, fields_key).always(function () { -- cgit v1.2.3 From 6e15a9cd24eb5825ea615512a4ee834f131a60f7 Mon Sep 17 00:00:00 2001 From: Aaron Bohy Date: Tue, 24 Apr 2018 10:32:45 +0200 Subject: [FIX] web: one2many form view with action button Assume a one2many field inside a form, displaying field A in its list view, and a field B in its (dialog) form view. Moreover, there is an action button in the dialog, which updates the value of B. Before this rev., B wasn't correctly reloaded when the button was clicked, because the BasicModel reloaded the fields on the list view (i.e. field A), whereas it should reload the fields in both views. This fix is twofold. First, we force the viewType to 'form' when the record is reloaded, instead of the default ('list'), so that fields in the form view are correctly reloaded. Second, when we open the form view in the dialog, we add the fields of the list view to the dict of fields of the form view, so that the form is aware of those fields and can ask the model to reload them (still without displaying them). Fixes #24189 --- .../web/static/src/js/views/basic/basic_model.js | 31 ++++++++++++++++------ 1 file changed, 23 insertions(+), 8 deletions(-) (limited to 'addons/web/static/src/js/views/basic/basic_model.js') diff --git a/addons/web/static/src/js/views/basic/basic_model.js b/addons/web/static/src/js/views/basic/basic_model.js index 9d4dc877473..d325d558b96 100644 --- a/addons/web/static/src/js/views/basic/basic_model.js +++ b/addons/web/static/src/js/views/basic/basic_model.js @@ -1054,7 +1054,13 @@ var BasicModel = AbstractModel.extend({ addFieldsInfo: function (recordID, viewInfo) { var record = this.localData[recordID]; record.fields = _.extend({}, record.fields, viewInfo.fields); - record.fieldsInfo = _.extend({}, record.fieldsInfo, viewInfo.fieldsInfo); + // complete the given fieldsInfo with the fields of the main view, so + // that those field will be reloaded if a reload is triggered by the + // secondary view + var fieldsInfo = _.mapObject(viewInfo.fieldsInfo, function (fieldsInfo) { + return _.defaults({}, fieldsInfo, record.fieldsInfo[record.viewType]); + }); + record.fieldsInfo = _.extend({}, record.fieldsInfo, fieldsInfo); }, /** * For list resources, this freezes the current records order. @@ -1992,7 +1998,8 @@ var BasicModel = AbstractModel.extend({ */ _fetchRecord: function (record, options) { var self = this; - var fieldNames = options && options.fieldNames || record.getFieldNames(); + options = options || {}; + var fieldNames = options.fieldNames || record.getFieldNames(options); fieldNames = _.uniq(fieldNames.concat(['display_name'])); return this._rpc({ model: record.model, @@ -2492,8 +2499,9 @@ var BasicModel = AbstractModel.extend({ _fetchX2Manys: function (record, options) { var self = this; var defs = []; - var fieldNames = options && options.fieldNames || record.getFieldNames(); - var viewType = options && options.viewType || record.viewType; + options = options || {}; + var fieldNames = options.fieldNames || record.getFieldNames(options); + var viewType = options.viewType || record.viewType; _.each(fieldNames, function (fieldName) { var field = record.fields[fieldName]; if (field.type === 'one2many' || field.type === 'many2many') { @@ -3016,11 +3024,15 @@ var BasicModel = AbstractModel.extend({ * default view type. * * @param {Object} element an element from the localData + * @param {Object} [options] + * @param {Object} [options.viewType] current viewType. If not set, we will + * assume main viewType from the record * @returns {string[]} the list of field names */ - _getFieldNames: function (element) { + _getFieldNames: function (element, options) { var fieldsInfo = element.fieldsInfo; - return Object.keys(fieldsInfo && fieldsInfo[element.viewType] || {}); + var viewType = options && options.viewType || element.viewType; + return Object.keys(fieldsInfo && fieldsInfo[viewType] || {}); }, /** * Evaluate the record evaluation context. This method is supposed to be @@ -3500,13 +3512,16 @@ var BasicModel = AbstractModel.extend({ * @see _fetchRecord @see _makeDefaultRecord * * @param {Object} record - * @param {Object} record + * @param {Object} [options] + * @param {Object} [options.viewType] current viewType. If not set, we will + * assume main viewType from the record * @returns {Deferred} resolves to the finished resource */ _postprocess: function (record, options) { var self = this; var defs = []; - _.each(record.getFieldNames(), function (name) { + + _.each(record.getFieldNames(options), function (name) { var field = record.fields[name]; var fieldInfo = record.fieldsInfo[record.viewType][name] || {}; var options = fieldInfo.options || {}; -- cgit v1.2.3 From 013baed41376f3b5b84bfa4a29cacb3774af6e28 Mon Sep 17 00:00:00 2001 From: Aaron Bohy Date: Mon, 7 May 2018 15:19:08 +0200 Subject: [FIX] web: navigate through records in Kanban with progressbar Recently, rev. c0809dd41 removed a protection in the reload of Kanban views with progressbars. This protection ensured that the manual reload of the progressbars was only done when one of the records of the Kanban view was updated (and not when a column, or the whole view was). However, removing it highlighted a bug linked to the manual reload of progressbars, which messed up the list of ids in the environment. As a consequence, for instance, if the user archived the records of a column, and then opendc a record in form view, it couldn't use the pager anymore. Besides fixing this bug, this rev. re-introduces the protection, and refines it to prevent 2 useless RPCs when the whole Kanban view was reloaded. opw~1841276 opw~1841342 --- addons/web/static/src/js/views/basic/basic_model.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'addons/web/static/src/js/views/basic/basic_model.js') diff --git a/addons/web/static/src/js/views/basic/basic_model.js b/addons/web/static/src/js/views/basic/basic_model.js index d325d558b96..9e8afe1629f 100644 --- a/addons/web/static/src/js/views/basic/basic_model.js +++ b/addons/web/static/src/js/views/basic/basic_model.js @@ -3864,11 +3864,13 @@ var BasicModel = AbstractModel.extend({ }); } return $.when.apply($, defs).then(function () { - // generate the res_ids of the main list, being the concatenation - // of the fetched res_ids in each group - list.res_ids = _.flatten(_.map(arguments, function (group) { - return group ? group.res_ids : []; - })); + if (!options || !options.onlyGroups) { + // generate the res_ids of the main list, being the concatenation + // of the fetched res_ids in each group + list.res_ids = _.flatten(_.map(arguments, function (group) { + return group ? group.res_ids : []; + })); + } return list; }); }); -- cgit v1.2.3 From 25548eb7e963632668438f939401403431201904 Mon Sep 17 00:00:00 2001 From: len-odoo Date: Fri, 11 May 2018 16:59:10 +0200 Subject: [FIX] web: sort relational fields by their names When sorting records according to a many2one field in a list view embedded in a form view, the js would sort according to their ids, in a seemingly arbitrary order. Thus sorting records according to a field with values in ("a", "b", "c") could be sorted as "a", "a", "c", "b" instead of "a", "a", "b", "c". We make the comparison on the name of the field instead. opw 1838860 --- addons/web/static/src/js/views/basic/basic_model.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'addons/web/static/src/js/views/basic/basic_model.js') diff --git a/addons/web/static/src/js/views/basic/basic_model.js b/addons/web/static/src/js/views/basic/basic_model.js index 9e8afe1629f..d0eed4dc524 100644 --- a/addons/web/static/src/js/views/basic/basic_model.js +++ b/addons/web/static/src/js/views/basic/basic_model.js @@ -4100,10 +4100,20 @@ var BasicModel = AbstractModel.extend({ var r2 = self.localData[record2ID]; var data1 = _.extend({}, r1.data, r1._changes); var data2 = _.extend({}, r2.data, r2._changes); - if (data1[order.name] < data2[order.name]) { + + // Default value to sort against: the value of the field + var orderData1 = data1[order.name]; + var orderData2 = data2[order.name]; + + // If the field is a relation, sort on the display_name of those records + if (list.fields[order.name].type === 'many2one') { + orderData1 = orderData1 ? self.localData[orderData1].data.display_name : ""; + orderData2 = orderData2 ? self.localData[orderData2].data.display_name : ""; + } + if (orderData1 < orderData2) { return order.asc ? -1 : 1; } - if (data1[order.name] > data2[order.name]) { + if (orderData1 > orderData2) { return order.asc ? 1 : -1; } return compareRecords(record1ID, record2ID, level + 1); -- cgit v1.2.3 From 6f7031e9fb74561aa0d4630caf47987675b49a65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20K=C3=BChn?= Date: Mon, 14 May 2018 21:18:22 +0200 Subject: [FIX] web: pass unique ids on `name_get` rpc Before this commit, when a list contains records with many2one fields that contain the same values, duplicate ids were passed to the server on rpc `name_get`. For instance, if 40 records in a list refer to a Unit of Measure with id "1" whose displayed_name is "unit(s)", the server receives a long list of ids with simply the value "1". Also, the server responds with a list of displayed_name, in this case a list of 40 strings "unit(s)". With this commit, we always pass unique ids to the server on rpc `name_get`. --- addons/web/static/src/js/views/basic/basic_model.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'addons/web/static/src/js/views/basic/basic_model.js') diff --git a/addons/web/static/src/js/views/basic/basic_model.js b/addons/web/static/src/js/views/basic/basic_model.js index d0eed4dc524..a90cc1075c9 100644 --- a/addons/web/static/src/js/views/basic/basic_model.js +++ b/addons/web/static/src/js/views/basic/basic_model.js @@ -1974,13 +1974,16 @@ var BasicModel = AbstractModel.extend({ return this._rpc({ model: model, method: 'name_get', - args: [ids], + args: [_.uniq(ids)], context: list.context, }) .then(function (name_gets) { - for (var i = 0; i < name_gets.length; i++) { - records[i].data.display_name = name_gets[i][1]; - } + _.each(records, function (record) { + var nameGet = _.find(name_gets, function (nameGet) { + return nameGet[0] === record.data.id; + }); + record.data.display_name = nameGet[1]; + }); }); }, /** -- cgit v1.2.3 From 8ac98fc78a3794e06481b02a431bcdc386a5a6ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20K=C3=BChn?= Date: Mon, 14 May 2018 21:18:32 +0200 Subject: [FIX] web: show names of many2one on default_get Before this commit, some records in a list did not show the name of their many2one fields. This case occurs when the records in the list are created from a default_get, and the records do not fit in a single page. In that case, the records in the first page correctly display the names of their many2one fields, but not the records in the other pages. Fixes #24547 --- .../web/static/src/js/views/basic/basic_model.js | 28 +++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) (limited to 'addons/web/static/src/js/views/basic/basic_model.js') diff --git a/addons/web/static/src/js/views/basic/basic_model.js b/addons/web/static/src/js/views/basic/basic_model.js index a90cc1075c9..60c167ddfd1 100644 --- a/addons/web/static/src/js/views/basic/basic_model.js +++ b/addons/web/static/src/js/views/basic/basic_model.js @@ -2469,7 +2469,16 @@ var BasicModel = AbstractModel.extend({ var self = this; var def; if (list.static) { - def = this._readUngroupedList(list); + def = this._readUngroupedList(list).then(function () { + if (list.parentID && self.isNew(list.parentID)) { + // list from a default_get, so fetch display_name for many2one fields + var many2ones = self._getMany2OneFieldNames(list); + var defs = _.map(many2ones, function (name) { + return self._fetchNameGets(list, name); + }); + return $.when.apply($, defs); + } + }); } else { def = this._searchReadUngroupedList(list); } @@ -3037,6 +3046,23 @@ var BasicModel = AbstractModel.extend({ var viewType = options && options.viewType || element.viewType; return Object.keys(fieldsInfo && fieldsInfo[viewType] || {}); }, + /** + * Get many2one fields names in a datapoint. This is useful in order to + * fetch their names in the case of a default_get. + * + * @private + * @param {Object} datapoint a valid resource object + * @returns {string[]} list of field names that are many2one + */ + _getMany2OneFieldNames: function (datapoint) { + var many2ones = []; + _.each(datapoint.fields, function (field, name) { + if (field.type === 'many2one') { + many2ones.push(name); + } + }); + return many2ones; + }, /** * Evaluate the record evaluation context. This method is supposed to be * called by _getEvalContext. It basically only generates a dictionary of -- cgit v1.2.3 From c587c0029b3211708f371b13c20b3efc7b6c9b43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20K=C3=BChn?= Date: Fri, 18 May 2018 15:18:24 +0200 Subject: [FIX] web: only abandon records on discard without savepoint Revision on https://github.com/odoo/odoo/commit/9a9da5763b38a3bce54e9c4870af0032e38cacc3 The intent of the commit above was to no abandon records in a list on discard when these records have been created from a `default_get`. Also, the `default_get` may also perform an `onchange` that could create more records. The records from this `onchange` must also be included in the "do not abandon" rule. However, the rule was too relax, so that any following `onchanges` from a user interaction was also considered into this rule. As a result, it was not possible to abandon such records. With this fix, we restrict the rule to `default_get` (already the case) and only the `onchange` right after a `default_get`. Any record created on an `onchange` from a user interaction after a `default_get` should be abandoned on discard. Representation of creating the list: savepoint |----------|-----------|-------||--------|-------> create default_get onchange1 onchange2 record in the list is created by default_get or onchange1 => do not abandon on discard record in the list is created by onchange2 => abandon on discard --- addons/web/static/src/js/views/basic/basic_model.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'addons/web/static/src/js/views/basic/basic_model.js') diff --git a/addons/web/static/src/js/views/basic/basic_model.js b/addons/web/static/src/js/views/basic/basic_model.js index 60c167ddfd1..36e9652dd9b 100644 --- a/addons/web/static/src/js/views/basic/basic_model.js +++ b/addons/web/static/src/js/views/basic/basic_model.js @@ -1542,8 +1542,10 @@ var BasicModel = AbstractModel.extend({ rec = self._makeDataPoint(params); list._cache[rec.res_id] = rec.id; } - - rec._noAbandon = true; + // Do not abandon the record if it has been created + // from `default_get`. The list has a savepoint only + // after having fully executed `default_get`. + rec._noAbandon = !list._savePoint; list._changes.push({operation: 'ADD', id: rec.id}); if (command[0] === 1) { list._changes.push({operation: 'UPDATE', id: rec.id}); -- cgit v1.2.3 From 8dbebe02429363b88c4beeed7e24c806d9d9560d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20K=C3=BChn?= Date: Tue, 22 May 2018 09:57:00 +0200 Subject: [FIX] web: fetch name_gets on list only when there are data Revision on 8ac98fc78a3794e06481b02a431bcdc386a5a6ee The commit above does not check whether the list contains data or not. As a result, if there are no data in the list, there is no reason to fetch `name_gets`. In fact, there could be a traceback because some parameters of this rpc are computed from data in the list. So if there are no data in the list, the parameters of the rpc are undefined. This was the case for a test in enterprise. --- addons/web/static/src/js/views/basic/basic_model.js | 3 +++ 1 file changed, 3 insertions(+) (limited to 'addons/web/static/src/js/views/basic/basic_model.js') diff --git a/addons/web/static/src/js/views/basic/basic_model.js b/addons/web/static/src/js/views/basic/basic_model.js index 36e9652dd9b..ea3b8f17a09 100644 --- a/addons/web/static/src/js/views/basic/basic_model.js +++ b/addons/web/static/src/js/views/basic/basic_model.js @@ -1963,6 +1963,9 @@ var BasicModel = AbstractModel.extend({ var records = []; var ids = []; list = this._applyX2ManyOperations(list); + if (_.isEmpty(list.data)) { + return $.when(); + } _.each(list.data, function (localId) { var record = self.localData[localId]; var data = record._changes || record.data; -- cgit v1.2.3