diff --git a/addons/web/static/src/js/views/abstract_view.js b/addons/web/static/src/js/views/abstract_view.js index a8e4ebbd8f0..9b6e5a5d192 100644 --- a/addons/web/static/src/js/views/abstract_view.js +++ b/addons/web/static/src/js/views/abstract_view.js @@ -282,6 +282,26 @@ odoo.define('web.viewUtils', function () { */ var utils = { + /** + * Returns the value of a group dataPoint, i.e. the value of the groupBy + * field for the records in that group. + * + * @param {Object} group dataPoint of type list, corresponding to a group + * @param {string} groupByField the name of the groupBy field + * @returns {string | integer | false} + */ + getGroupValue: function (group, groupByField) { + var groupedByField = group.fields[groupByField]; + switch (groupedByField.type) { + case 'many2one': + return group.res_id || false; + case 'selection': + var descriptor = _.findWhere(groupedByField.selection, group.value); + return descriptor && descriptor[0]; + default: + return group.value; + } + }, /** * States whether or not the quick create feature is available for the given * datapoint, depending on its groupBy field. @@ -294,7 +314,7 @@ var utils = { if (!groupByField) { return false; } - var availableTypes = ['char', 'boolean', 'many2one']; + var availableTypes = ['char', 'boolean', 'many2one', 'selection']; if (!_.contains(availableTypes, list.fields[groupByField].type)) { return false; } 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 15f37551188..8cc33aa32d0 100644 --- a/addons/web/static/src/js/views/kanban/kanban_column.js +++ b/addons/web/static/src/js/views/kanban/kanban_column.js @@ -7,6 +7,7 @@ var Dialog = require('web.Dialog'); var KanbanRecord = require('web.KanbanRecord'); var RecordQuickCreate = require('web.kanban_record_quick_create'); var view_dialogs = require('web.view_dialogs'); +var viewUtils = require('web.viewUtils'); var Widget = require('web.Widget'); var KanbanColumnProgressBar = require('web.KanbanColumnProgressBar'); @@ -194,7 +195,7 @@ var KanbanColumn = Widget.extend({ this.trigger_up('close_quick_create'); // close other quick create widgets this.trigger_up('start_quick_create'); var context = this.data.getContext(); - context['default_' + this.groupedBy] = this.grouped_by_m2o ? this.id : this.data.value; + context['default_' + this.groupedBy] = viewUtils.getGroupValue(this.data, this.groupedBy); this.quickCreateWidget = new RecordQuickCreate(this, { context: context, formViewRef: this.quickCreateView, diff --git a/addons/web/static/src/js/views/kanban/kanban_controller.js b/addons/web/static/src/js/views/kanban/kanban_controller.js index 025cbc79247..7f44dceb2ef 100644 --- a/addons/web/static/src/js/views/kanban/kanban_controller.js +++ b/addons/web/static/src/js/views/kanban/kanban_controller.js @@ -389,8 +389,7 @@ var KanbanController = BasicController.extend({ var context = columnState.getContext(); var state = self.model.get(self.handle, {raw: true}); var groupedBy = state.groupedBy[0]; - var groupedByM2O = state.fields[groupedBy].type === 'many2one'; - context['default_' + groupedBy] = groupedByM2O ? columnState.res_id : columnState.value; + context['default_' + groupedBy] = viewUtils.getGroupValue(columnState, groupedBy); new view_dialogs.FormViewDialog(self, { res_model: state.model, context: _.extend({default_name: values.name || values.display_name}, context), diff --git a/addons/web/static/src/js/views/kanban/kanban_model.js b/addons/web/static/src/js/views/kanban/kanban_model.js index b71a11f08ec..5dfa0b8a75d 100644 --- a/addons/web/static/src/js/views/kanban/kanban_model.js +++ b/addons/web/static/src/js/views/kanban/kanban_model.js @@ -7,6 +7,7 @@ odoo.define('web.KanbanModel', function (require) { */ var BasicModel = require('web.BasicModel'); +var viewUtils = require('web.viewUtils'); var KanbanModel = BasicModel.extend({ @@ -105,8 +106,8 @@ var KanbanModel = BasicModel.extend({ var group = this.localData[groupID]; var context = this._getContext(group); var parent = this.localData[group.parentID]; - var groupedByM2O = parent.fields[parent.groupedBy].type === 'many2one'; - context['default_' + parent.groupedBy[0]] = groupedByM2O ? group.res_id : group.value; + var groupedBy = parent.groupedBy; + context['default_' + groupedBy] = viewUtils.getGroupValue(group, groupedBy); var def; if (Object.keys(values).length === 1 && 'display_name' in values) { // only 'display_name is given, perform a 'name_create' @@ -133,7 +134,7 @@ var KanbanModel = BasicModel.extend({ }, /** * Add the following (kanban specific) keys when performing a `get`: - * + * * - tooltipData * - progressBarValues * - isGroupedByM2ONoColumn diff --git a/addons/web/static/tests/views/kanban_tests.js b/addons/web/static/tests/views/kanban_tests.js index 3b0a48f9445..f50d1cd18b2 100644 --- a/addons/web/static/tests/views/kanban_tests.js +++ b/addons/web/static/tests/views/kanban_tests.js @@ -1233,6 +1233,63 @@ QUnit.module('Views', { kanban.destroy(); }); + QUnit.test('quick create record fails in grouped by selection', function (assert) { + assert.expect(7); + + var kanban = createView({ + View: KanbanView, + model: 'partner', + data: this.data, + arch: '' + + '' + + '
' + + '
' + + '
', + archs: { + 'partner,false,form': '
' + + '' + + '', + }, + mockRPC: function (route, args) { + if (args.method === 'name_create') { + return $.Deferred().reject({ + code: 200, + data: {}, + message: "Odoo server error", + }, $.Event()); + } + if (args.method === 'create') { + assert.deepEqual(args.args[0], {state: 'abc'}, + "should write the correct value for state"); + assert.deepEqual(args.kwargs.context, {default_state: 'abc', default_name: 'test'}, + "should send the correct default value for state"); + } + return this._super.apply(this, arguments); + }, + groupBy: ['state'], + }); + + assert.strictEqual(kanban.$('.o_kanban_group:first .o_kanban_record').length, 1, + "there should be 1 record in first column"); + + kanban.$('.o_kanban_header:first .o_kanban_quick_add i').click(); + kanban.$('.o_kanban_quick_create input').val('test').trigger('input'); + kanban.$('.o_kanban_add').click(); + + assert.strictEqual($('.modal .o_form_view.o_form_editable').length, 1, + "a form view dialog should have been opened (in edit)"); + assert.strictEqual($('.modal .o_field_widget[name=state]').val(), '"abc"', + "the correct default value for state should already be set"); + + $('.modal-footer .btn-primary').click(); + + assert.strictEqual($('.modal').length, 0, "the modal should be closed"); + assert.strictEqual(kanban.$('.o_kanban_group:first .o_kanban_record').length, 2, + "there should be 2 records in first column"); + + kanban.destroy(); + }); + QUnit.test('quick create record in empty grouped kanban', function (assert) { assert.expect(3); @@ -1424,6 +1481,43 @@ QUnit.module('Views', { kanban.destroy(); }); + QUnit.test('quick create record in grouped on selection field', function (assert) { + assert.expect(4); + + var kanban = createView({ + View: KanbanView, + model: 'partner', + data: this.data, + arch: '' + + '' + + '
' + + '
' + + '
', + mockRPC: function (route, args) { + if (args.method === 'name_create') { + assert.deepEqual(args.kwargs.context, {default_state: 'abc'}, + "should send the correct default value for bar"); + } + return this._super.apply(this, arguments); + }, + groupBy: ['state'], + }); + + assert.strictEqual(kanban.$('.o_kanban_header .o_kanban_quick_add i').length, 3, + "quick create should be enabled when grouped on a selection field"); + assert.strictEqual(kanban.$('.o_kanban_group:first .o_kanban_record').length, 1, + "first column (abc) should contain 1 record"); + + kanban.$('.o_kanban_header:first .o_kanban_quick_add i').click(); + kanban.$('.o_kanban_quick_create input').val('new record').trigger('input'); + kanban.$('.o_kanban_add').click(); + + assert.strictEqual(kanban.$('.o_kanban_group:first .o_kanban_record').length, 2, + "first column (abc) should contain 2 records"); + + kanban.destroy(); + }); + QUnit.test('quick create record in grouped by char field (within quick_create_view)', function (assert) { assert.expect(6); @@ -1514,6 +1608,51 @@ QUnit.module('Views', { kanban.destroy(); }); + QUnit.test('quick create record in grouped by selection field (within quick_create_view)', function (assert) { + assert.expect(6); + + var kanban = createView({ + View: KanbanView, + model: 'partner', + data: this.data, + arch: '' + + '' + + '
' + + '
' + + '
', + archs: { + 'partner,some_view_ref,form': '
' + + '' + + '', + }, + groupBy: ['state'], + mockRPC: function (route, args) { + if (args.method === 'create') { + assert.deepEqual(args.args[0], {state: 'abc'}, + "should write the correct value for state"); + assert.deepEqual(args.kwargs.context, {default_state: 'abc'}, + "should send the correct default value for state"); + } + return this._super.apply(this, arguments); + }, + }); + + assert.strictEqual(kanban.$('.o_kanban_header .o_kanban_quick_add i').length, 3, + "quick create should be enabled when grouped on a selection field"); + assert.strictEqual(kanban.$('.o_kanban_group:first .o_kanban_record').length, 1, + "first column (abc) should contain 1 record"); + + kanban.$('.o_kanban_header:first .o_kanban_quick_add i').click(); + assert.strictEqual(kanban.$('.o_kanban_quick_create select').val(), '"abc"', + "should have set the correct state value by default"); + kanban.$('.o_kanban_add').click(); + + assert.strictEqual(kanban.$('.o_kanban_group:first .o_kanban_record').length, 2, + "first column (abc) should now contain 2 records"); + + kanban.destroy(); + }); + QUnit.test('many2many_tags in kanban views', function (assert) { assert.expect(12); diff --git a/doc/reference/views.rst b/doc/reference/views.rst index d35af9b7b36..42fcc86d047 100644 --- a/doc/reference/views.rst +++ b/doc/reference/views.rst @@ -852,7 +852,7 @@ attributes: ``quick_create`` whether it should be possible to create records without switching to the form view. By default, ``quick_create`` is enabled when the Kanban view is - grouped by many2one, char or boolean fields, and disabled when not. + grouped by many2one, selection, char or boolean fields, and disabled when not. Set to ``true`` to always enable it, and to ``false`` to always disable it.