summaryrefslogtreecommitdiff
path: root/addons/web/static/src
diff options
context:
space:
mode:
authorMartin Geubelle <mge@odoo.com>2019-03-20 14:13:01 +0000
committerAaron Bohy <aab@odoo.com>2019-04-02 11:55:57 +0000
commita75fa7e377829ac22f85eab3bfefd79705458236 (patch)
treebadb103e14fdaf92a9a5fe559d397fb6695e60ff /addons/web/static/src
parent015958dc1730296e216a035f3b12b92df2dbd6c8 (diff)
[IMP] web: allow mass update in editable lists
From an editable list view, if you select several lines then change a field, you are now asked if you want to apply the same change on all selected lines. If you accept, a write is directly performed (without applying onchange, as the records are reloaded and the view re-rendered). If you decline, the classic behavior still occurs. Part of task 1915702
Diffstat (limited to 'addons/web/static/src')
-rw-r--r--addons/web/static/src/js/views/list/list_controller.js87
-rw-r--r--addons/web/static/src/js/views/list/list_model.js46
2 files changed, 131 insertions, 2 deletions
diff --git a/addons/web/static/src/js/views/list/list_controller.js b/addons/web/static/src/js/views/list/list_controller.js
index c96b677e2ea..c4d1ca8959f 100644
--- a/addons/web/static/src/js/views/list/list_controller.js
+++ b/addons/web/static/src/js/views/list/list_controller.js
@@ -343,6 +343,15 @@ var ListController = BasicController.extend({
return _.extend(env, {domain: record.getDomain()});
},
/**
+ * @private
+ * @returns {boolean}
+ */
+ _inMultipleRecordEdition: function (recordId) {
+ var record = this.model.get(recordId, { raw: true });
+ var recordIds = _.union([recordId], this.selectedRecords);
+ return recordIds.length > 1 && record.res_id;
+ },
+ /**
* Only display the pager when there are data to display.
*
* @override
@@ -353,6 +362,57 @@ var ListController = BasicController.extend({
return !!state.count;
},
/**
+ * @private
+ * @param {string} recordId
+ * @param {Object} node
+ * @param {Object} changes
+ */
+ _saveMultipleRecords: function (recordId, node, changes) {
+ var self = this;
+ var value = Object.values(changes)[0];
+ var recordIds = _.union([recordId], this.selectedRecords);
+ var validRecordIds = recordIds.reduce(function (result, recordId) {
+ var record = self.model.get(recordId);
+ var modifiers = self.renderer._registerModifiers(node, record);
+ if (!modifiers.readonly && (!modifiers.required || value)) {
+ result.push(recordId);
+ }
+ return result;
+ }, []);
+ var message = _.str.sprintf(
+ _t('Do you want to set the value on the %d valid selected records?'),
+ validRecordIds.length);
+ if (recordIds.length !== validRecordIds.length) {
+ var nbInvalid = recordIds.length - validRecordIds.length;
+ message += ' ' + _.str.sprintf(_t('(%d invalid)'), nbInvalid);
+ }
+ Dialog.confirm(this, message, {
+ confirm_callback: function () {
+ self.model.saveRecords(recordId, validRecordIds)
+ .then(function () {
+ self._updateButtons('readonly');
+ var state = self.model.get(self.handle);
+ self.renderer.updateState(state, {});
+ });
+ },
+ });
+ },
+ /**
+ * Overridden to deal with edition of multiple line.
+ *
+ * @override
+ * @param {string} recordId
+ */
+ _saveRecord: function (recordId) {
+ var record = this.model.get(recordId, { raw: true });
+ if (record.isDirty() && this._inMultipleRecordEdition(recordId)) {
+ // do not save the record (see _saveMultipleRecords)
+ return Promise.resolve();
+
+ }
+ return this._super.apply(this, arguments);
+ },
+ /**
* Allows to change the mode of a single row.
*
* @override
@@ -546,6 +606,30 @@ var ListController = BasicController.extend({
});
},
/**
+ * Overridden to deal with the edition of multiple records.
+ *
+ * Note that we don't manage saving multiple records on saveLine
+ * because we don't want the onchanges to be applied.
+ *
+ * @private
+ * @override
+ */
+ _onFieldChanged: function (ev) {
+ ev.stopPropagation();
+ var self = this;
+
+ if (this._inMultipleRecordEdition(ev.data.dataPointID)) {
+ // deal with edition of multiple lines
+ var _onSuccess = ev.data.onSuccess;
+ ev.data.onSuccess = function () {
+ Promise.resolve(_onSuccess()).then(function () {
+ self._saveMultipleRecords(ev.data.dataPointID, ev.target.__node, ev.data.changes);
+ });
+ };
+ }
+ this._super.apply(this, arguments);
+ },
+ /**
* Force a resequence of the records curently on this page.
*
* @private
@@ -579,8 +663,7 @@ var ListController = BasicController.extend({
* @param {OdooEvent} ev
*/
_onSaveLine: function (ev) {
- var recordID = ev.data.recordID;
- this.saveRecord(recordID)
+ this.saveRecord(ev.data.recordID)
.then(ev.data.onSuccess)
.guardedCatch(ev.data.onFailure);
},
diff --git a/addons/web/static/src/js/views/list/list_model.js b/addons/web/static/src/js/views/list/list_model.js
index 0be8f54e4f1..73c2d86864d 100644
--- a/addons/web/static/src/js/views/list/list_model.js
+++ b/addons/web/static/src/js/views/list/list_model.js
@@ -33,6 +33,52 @@ odoo.define('web.ListModel', function (require) {
}
return result;
},
+ /**
+ * For a list of records, performs a write with all changes and fetches
+ * all data.
+ *
+ * @param {string} referenceRecordId the record datapoint used to
+ * generate the changes to apply to recordIds
+ * @param {string[]} recordIds a list of record datapoint ids
+ */
+ saveRecords: function (referenceRecordId, recordIds) {
+ var self = this;
+ var referenceRecord = this.localData[referenceRecordId];
+ var list = this.localData[referenceRecord.parentID];
+ var changes = this._generateChanges(referenceRecord, {});
+ var records = recordIds.map(function (recordId) {
+ return self.localData[recordId];
+ });
+ var model = records[0].model;
+ var recordResIds = _.pluck(records, 'res_id');
+ var fieldNames = records[0].getFieldNames();
+
+ return this._rpc({
+ model: model,
+ method: 'write',
+ args: [recordResIds, changes],
+ context: records[0].getContext(),
+ }).then(function () {
+ return self._rpc({
+ model: model,
+ method: 'read',
+ args: [recordResIds, fieldNames],
+ });
+ }).then(function (results) {
+ results.forEach(function (data) {
+ var record = _.findWhere(records, {res_id: data.id});
+ record.data = _.extend({}, record.data, data);
+ record._changes = {};
+ record._isDirty = false;
+ self._parseServerData(fieldNames, record, record.data);
+ });
+ }).then(function () {
+ return Promise.all([
+ self._fetchX2ManysBatched(list),
+ self._fetchReferencesBatched(list)
+ ]);
+ });
+ },
//--------------------------------------------------------------------------
// Private