summaryrefslogtreecommitdiff
path: root/addons/web/static/src/js/views/basic
diff options
context:
space:
mode:
Diffstat (limited to 'addons/web/static/src/js/views/basic')
-rw-r--r--addons/web/static/src/js/views/basic/basic_model.js64
-rw-r--r--addons/web/static/src/js/views/basic/basic_view.js80
2 files changed, 89 insertions, 55 deletions
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 9112756aaed..033d0f670ae 100644
--- a/addons/web/static/src/js/views/basic/basic_model.js
+++ b/addons/web/static/src/js/views/basic/basic_model.js
@@ -214,21 +214,63 @@ var BasicModel = AbstractModel.extend({
* It is useful for the cases where a record element is shared between
* various views, such as a one2many with a tree and a form view.
*
- * @param {string} recordID a valid element ID
+ * @param {string} datapointID a valid element ID (of type 'list' or 'record')
* @param {Object} viewInfo
* @param {Object} viewInfo.fields
- * @param {Object} viewInfo.fieldsInfo
+ * @param {Object} viewInfo.fieldInfo
+ * @param {string} viewInfo.viewType
+ * @returns {Promise} resolved when the fieldInfo have been set on the given
+ * datapoint and all its children, and all rawChanges have been applied
*/
- addFieldsInfo: function (recordID, viewInfo) {
- var record = this.localData[recordID];
- record.fields = _.extend({}, record.fields, viewInfo.fields);
- // complete the given fieldsInfo with the fields of the main view, so
+ addFieldsInfo: function (dataPointID, viewInfo) {
+ var dataPoint = this.localData[dataPointID];
+ dataPoint.fields = _.extend({}, dataPoint.fields, viewInfo.fields);
+ // complete the given fieldInfo 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]);
+ dataPoint.fieldsInfo = dataPoint.fieldsInfo || {};
+ const mainFieldInfo = dataPoint.fieldsInfo[dataPoint[viewInfo.viewType]];
+ dataPoint.fieldsInfo[viewInfo.viewType] = _.defaults({}, viewInfo.fieldInfo, mainFieldInfo);
+
+ // Some fields in the new fields info might not be in the previous one,
+ // so we might have stored changes for them (e.g. coming from onchange
+ // RPCs), that we haven't been able to process earlier (because those
+ // fields were unknown at that time). So we now try to process them.
+ return this.applyRawChanges(dataPointID, viewInfo.viewType).then(() => {
+ const proms = [];
+ const fieldInfo = dataPoint.fieldsInfo[viewInfo.viewType];
+ // recursively apply the new field info on sub datapoints
+ if (dataPoint.type === 'list') {
+ // case 'list': on all datapoints in the list
+ Object.values(dataPoint._cache).forEach(subDataPointID => {
+ proms.push(this.addFieldsInfo(subDataPointID, {
+ fields: dataPoint.fields,
+ fieldInfo: dataPoint.fieldsInfo[viewInfo.viewType],
+ viewType: viewInfo.viewType,
+ }));
+ });
+ } else {
+ // case 'record': on datapoints of all x2many fields
+ const values = _.extend({}, dataPoint.data, dataPoint._changes);
+ Object.keys(fieldInfo).forEach(fieldName => {
+ const fieldType = dataPoint.fields[fieldName].type;
+ if (fieldType === 'one2many' || fieldType === 'many2many') {
+ const mode = fieldInfo[fieldName].mode;
+ const views = fieldInfo[fieldName].views;
+ const x2mDataPointID = values[fieldName];
+ if (views[mode] && x2mDataPointID) {
+ proms.push(this.addFieldsInfo(x2mDataPointID, {
+ fields: views[mode].fields,
+ fieldInfo: views[mode].fieldsInfo[mode],
+ viewType: mode,
+ }));
+ }
+ }
+ });
+ }
+ return Promise.all(proms);
});
- record.fieldsInfo = _.extend({}, record.fieldsInfo, fieldsInfo);
+
},
/**
* Add and process default values for a given record. Those values are
@@ -3735,8 +3777,8 @@ var BasicModel = AbstractModel.extend({
* @returns {boolean}
*/
_isFieldProtected: function (record, fieldName, viewType) {
- var fieldInfo = record.fieldsInfo &&
- (record.fieldsInfo[viewType || record.viewType][fieldName]);
+ viewType = viewType || record.viewType;
+ var fieldInfo = viewType && record.fieldsInfo && record.fieldsInfo[viewType][fieldName];
if (fieldInfo) {
var rawModifiers = fieldInfo.modifiers || {};
var modifiers = this._evalModifiers(record, _.pick(rawModifiers, 'readonly'));
diff --git a/addons/web/static/src/js/views/basic/basic_view.js b/addons/web/static/src/js/views/basic/basic_view.js
index 4566d0b9471..6668392b823 100644
--- a/addons/web/static/src/js/views/basic/basic_view.js
+++ b/addons/web/static/src/js/views/basic/basic_view.js
@@ -96,14 +96,15 @@ var BasicView = AbstractView.extend({
* @private
* @returns {Promise}
*/
- _loadData: function (model) {
+ _loadData: async function (model) {
if (this.recordID) {
// Add the fieldsInfo of the current view to the given recordID,
// as it will be shared between two views, and it must be able to
// handle changes on fields that are only on this view.
- model.addFieldsInfo(this.recordID, {
+ await model.addFieldsInfo(this.recordID, {
fields: this.fields,
- fieldsInfo: this.fieldsInfo,
+ fieldInfo: this.fieldsInfo[this.viewType],
+ viewType: this.viewType,
});
var record = model.get(this.recordID);
@@ -119,7 +120,7 @@ var BasicView = AbstractView.extend({
// in the form view (e.g. if field is a many2many list in the form
// view, or if it is displayed by a widget requiring specialData).
// So when this happens, F is added to the list of fieldNames to fetch.
- _.each(viewFields, function (name) {
+ _.each(viewFields, (name) => {
if (!_.contains(fieldNames, name)) {
var fieldType = record.fields[name].type;
var fieldInfo = fieldsInfo[name];
@@ -137,30 +138,28 @@ var BasicView = AbstractView.extend({
// X2Many case: field is an x2many displayed as a list or
// kanban view, but the related fields haven't been loaded yet.
if ((fieldType === 'one2many' || fieldType === 'many2many')) {
- if (!('fieldsInfo' in record.data[name])) {
+ var x2mFieldInfo = record.fieldsInfo[this.viewType][name];
+ var viewType = x2mFieldInfo.viewType || x2mFieldInfo.mode;
+ var knownFields = Object.keys(record.data[name].fieldsInfo[record.data[name].viewType] || {});
+ var newFields = Object.keys(record.data[name].fieldsInfo[viewType]);
+ if (_.difference(newFields, knownFields).length) {
fieldNames.push(name);
- } else {
+ }
+
+ if (record.data[name].viewType === 'default') {
+ // Use case: x2many (tags) in x2many list views
+ // When opening the x2many record form view, the
+ // x2many will be reloaded but it may not have
+ // the same fields (ex: tags in list and list in
+ // form) so we need to merge the fieldsInfo to
+ // avoid losing the initial fields (display_name)
var fieldViews = fieldInfo.views || fieldInfo.fieldsInfo || {};
- var fieldViewTypes = Object.keys(fieldViews);
- var recordViewTypes = Object.keys(record.data[name].fieldsInfo);
- if (_.difference(fieldViewTypes, recordViewTypes).length) {
- fieldNames.push(name);
- }
-
- if (record.data[name].viewType === 'default') {
- // Use case: x2many (tags) in x2many list views
- // When opening the x2many record form view, the
- // x2many will be reloaded but it may not have
- // the same fields (ex: tags in list and list in
- // form) so we need to merge the fieldsInfo to
- // avoid losing the initial fields (display_name)
- var defaultFieldInfo = record.data[name].fieldsInfo.default;
- _.each(fieldViews, function (fieldView) {
- _.each(fieldView.fieldsInfo, function (x2mFieldInfo) {
- _.defaults(x2mFieldInfo, defaultFieldInfo);
- });
+ var defaultFieldInfo = record.data[name].fieldsInfo.default;
+ _.each(fieldViews, function (fieldView) {
+ _.each(fieldView.fieldsInfo, function (x2mFieldInfo) {
+ _.defaults(x2mFieldInfo, defaultFieldInfo);
});
- }
+ });
}
}
// Many2one: context is not the same between the different views
@@ -176,25 +175,18 @@ var BasicView = AbstractView.extend({
var def;
if (fieldNames.length) {
- // Some fields in the new view weren't in the previous one, so
- // we might have stored changes for them (e.g. coming from
- // onchange RPCs), that we haven't been able to process earlier
- // (because those fields were unknow at that time). So we ask
- // the model to process them.
- def = model.applyRawChanges(record.id, viewType).then(function () {
- if (model.isNew(record.id)) {
- return model.applyDefaultValues(record.id, {}, {
- fieldNames: fieldNames,
- viewType: viewType,
- });
- } else {
- return model.reload(record.id, {
- fieldNames: fieldNames,
- keepChanges: true,
- viewType: viewType,
- });
- }
- });
+ if (model.isNew(record.id)) {
+ def = model.applyDefaultValues(record.id, {}, {
+ fieldNames: fieldNames,
+ viewType: viewType,
+ });
+ } else {
+ def = model.reload(record.id, {
+ fieldNames: fieldNames,
+ keepChanges: true,
+ viewType: viewType,
+ });
+ }
}
return Promise.resolve(def).then(function () {
return model.get(record.id);