diff options
| author | Martin Geubelle <mge@odoo.com> | 2019-03-20 14:13:01 +0000 |
|---|---|---|
| committer | Aaron Bohy <aab@odoo.com> | 2019-04-02 11:55:57 +0000 |
| commit | a75fa7e377829ac22f85eab3bfefd79705458236 (patch) | |
| tree | badb103e14fdaf92a9a5fe559d397fb6695e60ff /addons/web/static/src/js | |
| parent | 015958dc1730296e216a035f3b12b92df2dbd6c8 (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/js')
| -rw-r--r-- | addons/web/static/src/js/views/list/list_controller.js | 87 | ||||
| -rw-r--r-- | addons/web/static/src/js/views/list/list_model.js | 46 |
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 |
