summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohammed Shekha <msh@odoo.com>2020-12-01 06:04:15 +0000
committerAaron Bohy <aab@odoo.com>2021-02-17 07:31:31 +0000
commitd37648944f9d9eeec470f7102c51ae56ba99dac6 (patch)
treeb0963c5bfce771650e0e9bfd2fd840ddedd97020
parentfa7a185663f21c1c4060765c8c137b296df3a350 (diff)
[IMP] web: list multi-edit: discard, cancel then save
In a list view that allows the multi edition, select several records, edit a field, and 'click' on Discard. In the confirm dialog, click on 'Cancel'. The row is still in edition and the changes are still there. However, before this commit, clicking on 'Save' did nothing. The reason is that the 'Save' button is fake. Typically, clicking on it triggers a 'field_changed' event, thus saving the selected records. In this above scenario, the changes have already been notified, so nothing happens when the user clicks on 'Save'. This commit fixes the issue by storing the last 'field_changed' event, and re-triggering it when necessary. This isn't the cleaner way to handle that scenario, but it is the simpler, so we go for it in stable. In master, it would be nice to rework the multi edition feature with this scenario in mind. task-2376233 closes odoo/odoo#66045 X-original-commit: 18ed619baeda06f071779da00177beee01f8a896 Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
-rw-r--r--addons/web/static/src/js/views/list/list_controller.js10
-rw-r--r--addons/web/static/tests/views/list_tests.js44
2 files changed, 53 insertions, 1 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 0e1921883ff..d157e9e0ab7 100644
--- a/addons/web/static/src/js/views/list/list_controller.js
+++ b/addons/web/static/src/js/views/list/list_controller.js
@@ -60,6 +60,7 @@ var ListController = BasicController.extend({
this.selectedRecords = params.selectedRecords || [];
this.multipleRecordsSavingPromise = null;
this.fieldChangedPrevented = false;
+ this.lastFieldChangedEvent = null;
this.isPageSelected = false; // true iff all records of the page are selected
this.isDomainSelected = false; // true iff the user selected all records matching the domain
this.isExportEnable = false;
@@ -536,6 +537,10 @@ var ListController = BasicController.extend({
_saveRecord: function (recordId) {
var record = this.model.get(recordId, { raw: true });
if (record.isDirty() && this.renderer.isInMultipleRecordEdition(recordId)) {
+ if (!this.multipleRecordsSavingPromise && this.lastFieldChangedEvent) {
+ this._onFieldChanged(this.lastFieldChangedEvent);
+ this.lastFieldChangedEvent = null;
+ }
// do not save the record (see _saveMultipleRecords)
const prom = this.multipleRecordsSavingPromise || Promise.reject();
this.multipleRecordsSavingPromise = null;
@@ -728,7 +733,9 @@ var ListController = BasicController.extend({
*/
_onDiscard: function (ev) {
ev.stopPropagation(); // So that it is not considered as a row leaving
- this._discardChanges();
+ this._discardChanges().then(() => {
+ this.lastFieldChangedEvent = null;
+ });
},
/**
* Used to detect if the discard button is about to be clicked.
@@ -818,6 +825,7 @@ var ListController = BasicController.extend({
_onFieldChanged: function (ev) {
ev.stopPropagation();
const recordId = ev.data.dataPointID;
+ this.lastFieldChangedEvent = ev;
if (this.fieldChangedPrevented) {
this.fieldChangedPrevented = ev;
diff --git a/addons/web/static/tests/views/list_tests.js b/addons/web/static/tests/views/list_tests.js
index b33028f5b44..60044cae0d5 100644
--- a/addons/web/static/tests/views/list_tests.js
+++ b/addons/web/static/tests/views/list_tests.js
@@ -7856,6 +7856,50 @@ QUnit.module('Views', {
list.destroy();
});
+ QUnit.test('editable list view: click Discard, Cancel discard dialog and then Save in multi edition', async function (assert) {
+ assert.expect(5);
+
+ const list = await createView({
+ arch: `
+ <tree editable="top" multi_edit="1">
+ <field name="foo"/>
+ </tree>`,
+ data: this.data,
+ model: 'foo',
+ View: ListView,
+ });
+
+ // select two records
+ await testUtils.dom.click(list.$('.o_data_row:eq(0) .o_list_record_selector input'));
+ await testUtils.dom.click(list.$('.o_data_row:eq(1) .o_list_record_selector input'));
+
+ await testUtils.dom.click(list.$('.o_data_row:first() .o_data_cell:first()'));
+ list.$('.o_data_row:first() .o_data_cell:first() input').val("oof");
+
+ const $discardButton = list.$buttons.find('.o_list_button_discard');
+
+ // Simulates an actual click (event chain is: mousedown > change > blur > focus > mouseup > click)
+ await testUtils.dom.triggerEvents($discardButton, ['mousedown']);
+ await testUtils.dom.triggerEvents(list.$('.o_data_row:first() .o_data_cell:first() input'),
+ ['change', 'blur', 'focusout']);
+ await testUtils.dom.triggerEvents($discardButton, ['focus']);
+ $discardButton[0].dispatchEvent(new MouseEvent('mouseup'));
+ await testUtils.dom.click($discardButton);
+
+ assert.ok($('.modal').text().includes("Warning"), "Modal should ask to discard changes");
+ await testUtils.dom.click($('.modal .btn:contains(Cancel)'));
+ assert.hasClass(list.$('.o_data_row:first'), 'o_selected_row',
+ "the first row should still be selected");
+
+ await testUtils.dom.click($('.o_list_button_save'));
+ assert.containsOnce(document.body, '.modal');
+ await testUtils.dom.click($('.modal .btn-primary'));
+ assert.containsNone(list, '.o_selected_row');
+ assert.strictEqual(list.$('.o_data_row .o_data_cell').text(), "oofoofgnapblip");
+
+ list.destroy();
+ });
+
QUnit.test('editable list view: multi edition with readonly modifiers', async function (assert) {
assert.expect(5);