diff --git a/addons/web/static/src/js/views/kanban/kanban_column.js b/addons/web/static/src/js/views/kanban/kanban_column.js index 269e37e7082..82fc5d168ff 100644 --- a/addons/web/static/src/js/views/kanban/kanban_column.js +++ b/addons/web/static/src/js/views/kanban/kanban_column.js @@ -50,7 +50,7 @@ var KanbanColumn = Widget.extend({ this.grouped_by_m2o = options.grouped_by_m2o; this.editable = options.editable; this.deletable = options.deletable; - this.draggable = recordOptions.draggable; + this.draggable = options.draggable; this.records_editable = options.records_editable; this.records_deletable = options.records_deletable; this.relation = options.relation; @@ -87,12 +87,13 @@ var KanbanColumn = Widget.extend({ } this.$header.tooltip(); - if (config.device.size_class > config.device.SIZES.XS && this.draggable !== false) { + if (config.device.size_class > config.device.SIZES.XS) { // deactivate sortable in mobile mode. It does not work anyway, // and it breaks horizontal scrolling in kanban views. Someday, we // should find a way to use the touch events to make sortable work. this.$el.sortable({ connectWith: '.o_kanban_group', + containment: this.draggable ? '.o_kanban_view' : 'parent', revert: 0, delay: 0, items: '> .o_kanban_record:not(.o_updating)', diff --git a/addons/web/static/src/js/views/kanban/kanban_record.js b/addons/web/static/src/js/views/kanban/kanban_record.js index e5846e55cf4..7eb8b126508 100644 --- a/addons/web/static/src/js/views/kanban/kanban_record.js +++ b/addons/web/static/src/js/views/kanban/kanban_record.js @@ -33,7 +33,6 @@ var KanbanRecord = Widget.extend({ this.options = options; this.editable = options.editable; this.deletable = options.deletable; - this.draggable = options.draggable; this.read_only_mode = options.read_only_mode; this.qweb = options.qweb; this.subWidgets = {}; diff --git a/addons/web/static/src/js/views/kanban/kanban_renderer.js b/addons/web/static/src/js/views/kanban/kanban_renderer.js index cd9572b0fc5..b8c2e3c0bcd 100644 --- a/addons/web/static/src/js/views/kanban/kanban_renderer.js +++ b/addons/web/static/src/js/views/kanban/kanban_renderer.js @@ -316,7 +316,7 @@ var KanbanRenderer = BasicRenderer.extend({ var groupByFieldInfo = state.fieldsInfo.kanban[state.groupedBy[0]]; // Deactivate the drag'n'drop if the groupedBy field: // - is a date or datetime since we group by month or - // - is readonly + // - is readonly (on the field attrs or in the view) var draggable = true; if (groupByFieldAttrs) { if (groupByFieldAttrs.type === "date" || groupByFieldAttrs.type === "datetime") { @@ -325,6 +325,11 @@ var KanbanRenderer = BasicRenderer.extend({ draggable = !(groupByFieldAttrs.readonly); } } + if (groupByFieldInfo) { + if (draggable && groupByFieldInfo.readonly !== undefined) { + draggable = !(groupByFieldInfo.readonly); + } + } this.groupedByM2O = groupByFieldAttrs && (groupByFieldAttrs.type === 'many2one'); var grouped_by_field = this.groupedByM2O && groupByFieldAttrs.relation; var groupByTooltip = groupByFieldInfo && groupByFieldInfo.options.group_by_tooltip; diff --git a/addons/web/static/tests/views/kanban_tests.js b/addons/web/static/tests/views/kanban_tests.js index 64decd5f657..ca6a2ce50d5 100644 --- a/addons/web/static/tests/views/kanban_tests.js +++ b/addons/web/static/tests/views/kanban_tests.js @@ -581,6 +581,79 @@ QUnit.module('Views', { kanban.destroy(); }); + QUnit.test('prevent drag and drop of record if grouped by readonly', function (assert) { + assert.expect(12); + + this.data.partner.fields.foo.readonly = true; + var kanban = createView({ + View: KanbanView, + model: 'partner', + data: this.data, + arch: '' + + '' + + '
' + + '' + + '' + + '
' + + '
' + + '
', + mockRPC: function (route, args) { + if (route === '/web/dataset/resequence') { + return $.when(); + } + if (args.model === 'partner' && args.method === 'write') { + throw new Error('should not be draggable'); + } + return this._super(route, args); + }, + }); + // simulate an update coming from the searchview, with another groupby given + kanban.update({groupBy: ['state']}); + assert.strictEqual(kanban.$('.o_kanban_group:nth-child(1) .o_kanban_record').length, 1, + "column should contain 1 record(s)"); + assert.strictEqual(kanban.$('.o_kanban_group:nth-child(2) .o_kanban_record').length, 1, + "column should contain 1 record(s)"); + // drag&drop a record in another column + var $record = kanban.$('.o_kanban_group:nth-child(1) .o_kanban_record:first'); + var $group = kanban.$('.o_kanban_group:nth-child(2)'); + testUtils.dragAndDrop($record, $group); + // should not be draggable + assert.strictEqual(kanban.$('.o_kanban_group:nth-child(1) .o_kanban_record').length, 1, + "column should now contain 1 record(s)"); + assert.strictEqual(kanban.$('.o_kanban_group:nth-child(2) .o_kanban_record').length, 1, + "column should contain 1 record(s)"); + + // simulate an update coming from the searchview, with another groupby given + kanban.update({groupBy: ['foo']}); + assert.strictEqual(kanban.$('.o_kanban_group:nth-child(1) .o_kanban_record').length, 1, + "column should contain 1 record(s)"); + assert.strictEqual(kanban.$('.o_kanban_group:nth-child(2) .o_kanban_record').length, 2, + "column should contain 2 record(s)"); + // drag&drop a record in another column + $record = kanban.$('.o_kanban_group:nth-child(1) .o_kanban_record:first'); + $group = kanban.$('.o_kanban_group:nth-child(2)'); + testUtils.dragAndDrop($record, $group); + // should not be draggable + assert.strictEqual(kanban.$('.o_kanban_group:nth-child(1) .o_kanban_record').length, 1, + "column should now contain 1 record(s)"); + assert.strictEqual(kanban.$('.o_kanban_group:nth-child(2) .o_kanban_record').length, 2, + "column should contain 2 record(s)"); + + // drag&drop a record in the same column + var $record1 = kanban.$('.o_kanban_group:nth-child(2) .o_kanban_record:eq(0)'); + var $record2 = kanban.$('.o_kanban_group:nth-child(2) .o_kanban_record:eq(1)'); + assert.strictEqual($record1.text(), "blipDEF", "first record should be DEF"); + assert.strictEqual($record2.text(), "blipGHI", "second record should be GHI"); + testUtils.dragAndDrop($record2, $record1, {position: 'top'}); + // should still be able to resequence + assert.strictEqual(kanban.$('.o_kanban_group:nth-child(2) .o_kanban_record:eq(0)').text(), "blipGHI", + "records should have been resequenced"); + assert.strictEqual(kanban.$('.o_kanban_group:nth-child(2) .o_kanban_record:eq(1)').text(), "blipDEF", + "records should have been resequenced"); + + kanban.destroy(); + }); + QUnit.test('kanban view with default_group_by', function (assert) { assert.expect(7); this.data.partner.records.product_id = 1;