diff --git a/addons/web/static/src/js/fields/relational_fields.js b/addons/web/static/src/js/fields/relational_fields.js index 432961bc0bf..53a942bdd70 100644 --- a/addons/web/static/src/js/fields/relational_fields.js +++ b/addons/web/static/src/js/fields/relational_fields.js @@ -27,7 +27,7 @@ var KanbanRecord = require('web.KanbanRecord'); var KanbanRenderer = require('web.KanbanRenderer'); var ListRenderer = require('web.ListRenderer'); const { ComponentWrapper, WidgetAdapterMixin } = require('web.OwlCompatibility'); -const { sprintf } = require("web.utils"); +const { sprintf, toBoolElse } = require("web.utils"); const { escape } = owl.utils; var _t = core._t; @@ -1365,6 +1365,7 @@ var FieldX2Many = AbstractField.extend(WidgetAdapterMixin, { addCreateLine: this._hasCreateLine(), addTrashIcon: this._hasTrashIcon(), isMany2Many: this.isMany2Many, + no_open: this.isReadonly && toBoolElse(arch.attrs.no_open || '', false), columnInvisibleFields: this.currentColInvisibleFields, }); } diff --git a/addons/web/static/src/js/views/list/list_renderer.js b/addons/web/static/src/js/views/list/list_renderer.js index 4571b1275a4..dc53bd16108 100644 --- a/addons/web/static/src/js/views/list/list_renderer.js +++ b/addons/web/static/src/js/views/list/list_renderer.js @@ -78,6 +78,7 @@ var ListRenderer = BasicRenderer.extend({ this.pagers = []; // instantiated pagers (only for grouped lists) this.isGrouped = this.state.groupedBy.length > 0; this.groupbys = params.groupbys; + this.no_open = params.no_open; }, /** * Compute columns visilibity. This can't be done earlier as we need the @@ -952,6 +953,9 @@ var ListRenderer = BasicRenderer.extend({ if (this.hasSelectors) { $tr.prepend(this._renderSelector('td', !record.res_id)); } + if (this.no_open && this.mode === "readonly") { + $tr.addClass('o_list_no_open'); + } this._setDecorationClasses($tr, this.rowDecorations, record); return $tr; }, @@ -1377,7 +1381,7 @@ var ListRenderer = BasicRenderer.extend({ _onRowClicked: function (ev) { // The special_click property explicitely allow events to bubble all // the way up to bootstrap's level rather than being stopped earlier. - if (!ev.target.closest('.o_list_record_selector') && !$(ev.target).prop('special_click')) { + if (!ev.target.closest('.o_list_record_selector') && !$(ev.target).prop('special_click') && !this.no_open) { var id = $(ev.currentTarget).data('id'); if (id) { this.trigger_up('open_record', { id: id, target: ev.target }); diff --git a/addons/web/static/src/scss/list_view.scss b/addons/web/static/src/scss/list_view.scss index 476d89b46dc..bbdff95b817 100644 --- a/addons/web/static/src/scss/list_view.scss +++ b/addons/web/static/src/scss/list_view.scss @@ -229,6 +229,10 @@ width: 32px; } + .o_data_row.o_list_no_open { + cursor: default; + } + .o_data_row:not(.o_selected_row) .o_data_cell { // Boolean fields in non-selected rows completely disabled. diff --git a/addons/web/static/tests/fields/relational_fields_tests.js b/addons/web/static/tests/fields/relational_fields_tests.js index 487e953003f..a1e9c1a7d43 100644 --- a/addons/web/static/tests/fields/relational_fields_tests.js +++ b/addons/web/static/tests/fields/relational_fields_tests.js @@ -441,6 +441,29 @@ QUnit.module('relational_fields', { form.destroy(); }); + QUnit.test('prevent the dialog in readonly x2many tree view with option no_open True', async function (assert) { + assert.expect(2); + var form = await createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '
', + res_id: 1, + }); + assert.containsOnce(form, '.o_data_row:contains("blip")', "There should be one record in x2many list view") + await testUtils.dom.click(form.$('.o_data_row:first')); + assert.strictEqual($('.modal-dialog').length, 0, "There is should be no dialog open on click of readonly list row"); + form.destroy(); + }); + QUnit.test('delete a record while adding another one in a multipage', async function (assert) { // in a many2one with at least 2 pages, add a new line. Delete the line above it. // (the onchange makes it so that the virtualID is inserted in the middle of the currentResIDs.)