[FIX] web: editable list: correctly edit in readonly

Some widgets allow the edition in readonly (e.g. boolean_toggle,
priority...). In this case, the changed value is saved directly.
Before this commit, this didn't work in (main) list views: the
widget was updated with the new value, but it wasn't saved in db,
so the change was lost at reload.

This was due to the list controller not being correctly aware of
its mode ('edit' or 'readonly'), on which the basic controller
relies to determine whether a change must be saved directly or
not.

With this commit, a list is always in 'readonly', except when a
row is being edited, in which case it is in 'edit'.

Issue reported on task 2288963

closes odoo/odoo#54075

X-original-commit: 64e55cb42163643386740fbd23d710f64033b2ae
Signed-off-by: Julien Mougenot (jum) <jum@odoo.com>
Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
This commit is contained in:
Aaron Bohy
2020-07-03 16:41:56 +00:00
parent 5aa9765131
commit 2e6ec66022
3 changed files with 48 additions and 5 deletions
@@ -61,10 +61,6 @@ var ListController = BasicController.extend({
session.user_has_group('base.group_allow_export').then(has_group => {
this.isExportEnable = has_group;
});
Object.defineProperty(this, 'mode', {
get: () => this.renderer.isEditable() ? 'edit' : 'readonly',
set: () => {},
});
},
//--------------------------------------------------------------------------
@@ -519,6 +515,7 @@ var ListController = BasicController.extend({
*/
_setMode: function (mode, recordID) {
if ((recordID || this.handle) !== this.handle) {
this.mode = mode;
this.updateButtons(mode);
return this.renderer.setRowMode(recordID, mode);
} else {
@@ -60,7 +60,7 @@ var ListView = BasicView.extend({
this.controllerParams.editable = editable;
this.controllerParams.hasActionMenus = params.hasActionMenus;
this.controllerParams.toolbarActions = viewInfo.toolbar;
this.controllerParams.mode = editable ? 'edit' : 'readonly';
this.controllerParams.mode = 'readonly';
this.controllerParams.selectedRecords = selectedRecords;
this.rendererParams.arch = this.arch;
@@ -1229,6 +1229,52 @@ QUnit.module('Views', {
form.destroy();
});
QUnit.test('edit field in editable field without editing the row', async function (assert) {
// some widgets are editable in readonly (e.g. priority, boolean_toggle...) and they
// thus don't require the row to be switched in edition to be edited
assert.expect(13);
const list = await createView({
View: ListView,
model: 'foo',
data: this.data,
arch: `
<tree editable="top">
<field name="foo"/>
<field name="bar" widget="boolean_toggle"/>
</tree>`,
mockRPC(route, args) {
if (args.method === 'write') {
assert.step('write: ' + args.args[1].bar);
}
return this._super(...arguments);
},
});
// toggle the boolean value of the first row without editing the row
assert.ok(list.$('.o_data_row:first .o_boolean_toggle input')[0].checked);
assert.containsNone(list, '.o_selected_row');
await testUtils.dom.click(list.$('.o_data_row:first .o_boolean_toggle'));
assert.notOk(list.$('.o_data_row:first .o_boolean_toggle input')[0].checked);
assert.containsNone(list, '.o_selected_row');
assert.verifySteps(['write: false']);
// toggle the boolean value after switching the row in edition
assert.containsNone(list, '.o_selected_row');
await testUtils.dom.click(list.$('.o_data_row .o_data_cell:first'));
assert.containsOnce(list, '.o_selected_row');
await testUtils.dom.click(list.$('.o_selected_row .o_boolean_toggle'));
assert.containsOnce(list, '.o_selected_row');
assert.verifySteps([]);
// save
await testUtils.dom.click(list.$('.o_list_button_save'));
assert.containsNone(list, '.o_selected_row');
assert.verifySteps(['write: true']);
list.destroy();
});
QUnit.test('basic operations for editable list renderer', async function (assert) {
assert.expect(2);