diff options
9 files changed, 124 insertions, 36 deletions
diff --git a/addons/sale_expense/static/tests/sale_order_many2one_tests.js b/addons/sale_expense/static/tests/sale_order_many2one_tests.js index 62a8bb735c2..00c7eed7b0c 100644 --- a/addons/sale_expense/static/tests/sale_order_many2one_tests.js +++ b/addons/sale_expense/static/tests/sale_order_many2one_tests.js @@ -70,8 +70,8 @@ QUnit.module('sale_expense', { }); var $dropdown = form.$('.o_field_many2one input').autocomplete('widget'); await testUtils.fields.many2one.clickOpenDropdown('sale_order_id'); - assert.containsN($dropdown, 'li:not(.o_m2o_dropdown_option)', 8, 'autocomplete should contains 8 suggestions'); - assert.containsN($dropdown, 'li.o_m2o_dropdown_option', 1, 'autocomplete should contain only one option'); + assert.containsN($dropdown, 'li:not(.o_m2o_dropdown_option)', 9); + assert.containsNone($dropdown, 'li.o_m2o_dropdown_option'); assert.containsNone($dropdown, 'li.o_m2o_dropdown_option:contains("Search More...")', "Should not display the 'Search More... option'"); form.destroy(); }); diff --git a/addons/web/static/src/js/fields/relational_fields.js b/addons/web/static/src/js/fields/relational_fields.js index 944a7c30ebb..f9a220c6b8f 100644 --- a/addons/web/static/src/js/fields/relational_fields.js +++ b/addons/web/static/src/js/fields/relational_fields.js @@ -600,7 +600,7 @@ var FieldMany2One = AbstractField.extend({ }); } // create and edit ... - if (self.can_create && !self.nodeOptions.no_create_edit) { + if (self.can_create && !self.nodeOptions.no_create_edit && search_val.length > 0) { var createAndEditAction = function () { // Clear the value in case the user clicks on discard self.$('input').val(''); @@ -616,7 +616,13 @@ var FieldMany2One = AbstractField.extend({ label: _t("No results to show..."), }); } - + if (!self.value && !search_val.length && self.can_create + && (!self.nodeOptions.no_quick_create || !self.nodeOptions.no_create_edit)) { + values.push({ + label: _t("Start typing..."), + classname: 'o_m2o_start_typing', + }); + } resolve(values); }); }); diff --git a/addons/web/static/src/scss/dropdown.scss b/addons/web/static/src/scss/dropdown.scss index 82f053a535e..e94bc3e0203 100644 --- a/addons/web/static/src/scss/dropdown.scss +++ b/addons/web/static/src/scss/dropdown.scss @@ -24,9 +24,17 @@ margin: 0; } } - &.o_m2o_dropdown_option { + &.o_m2o_dropdown_option, &.o_m2o_start_typing { text-indent: 20px } + &.o_m2o_start_typing { + font-style: italic; + cursor: default; + a.ui-menu-item-wrapper, a.ui-state-active, a.ui-state-active:hover { + background: none; + color: #adb5bd; + } + } } } diff --git a/addons/web/static/tests/fields/relational_fields/field_many2many_tests.js b/addons/web/static/tests/fields/relational_fields/field_many2many_tests.js index 47fe687d773..d7d18dfb86b 100644 --- a/addons/web/static/tests/fields/relational_fields/field_many2many_tests.js +++ b/addons/web/static/tests/fields/relational_fields/field_many2many_tests.js @@ -1314,8 +1314,7 @@ QUnit.module('fields', {}, function () { }); await testUtils.form.clickEdit(form); - await testUtils.fields.many2one.clickOpenDropdown('timmy'); - await testUtils.fields.many2one.clickItem('timmy','Create and Edit'); + await testUtils.fields.many2one.createAndEdit('timmy',"Ralts"); assert.containsOnce($(document), '.modal .o_form_view', "should have opened the modal"); // Create multiple records with save & new @@ -1454,8 +1453,8 @@ QUnit.module('fields', {}, function () { await testUtils.fields.many2one.clickOpenDropdown('partner_ids'); const $dropdown1 = form.$('.o_field_many2one input').autocomplete('widget'); - assert.containsOnce($dropdown1, 'li.o_m2o_dropdown_option:contains(Create and Edit...)', - 'autocomplete should contain Create and Edit...'); + assert.containsOnce($dropdown1, 'li.o_m2o_start_typing:contains(Start typing...)', + 'autocomplete should contain Start typing...'); await testUtils.fields.many2one.clickItem('partner_ids', 'Search More'); @@ -1468,7 +1467,7 @@ QUnit.module('fields', {}, function () { await testUtils.fields.editAndTrigger(form.$('.o_field_many2one input'), 'Something that does not exist', 'keydown'); // await testUtils.nextTick(); - assert.containsN($dropdown1, 'li.o_m2o_dropdown_option', 2, + assert.containsN(form.$('.o_field_many2one input').autocomplete('widget'), 'li.o_m2o_dropdown_option', 2, 'autocomplete should contain Create and Create and Edit... options'); // set turtle_bar false -> create and delete actions are no longer available diff --git a/addons/web/static/tests/fields/relational_fields/field_many2one_tests.js b/addons/web/static/tests/fields/relational_fields/field_many2one_tests.js index b43e2e102a1..856019092fe 100644 --- a/addons/web/static/tests/fields/relational_fields/field_many2one_tests.js +++ b/addons/web/static/tests/fields/relational_fields/field_many2one_tests.js @@ -625,8 +625,7 @@ QUnit.module('fields', {}, function () { assert.strictEqual(document.activeElement, input, "Input should be focused when activated"); - await testUtils.fields.many2one.clickOpenDropdown('trululu'); - await testUtils.fields.many2one.clickItem('trululu', 'Create'); + await testUtils.fields.many2one.createAndEdit('trululu', "ABC"); // At this point, if the focus is correctly registered by the m2o, there // should be only one modal (the "Create" one) and none for saving changes. @@ -667,8 +666,78 @@ QUnit.module('fields', {}, function () { form.destroy(); }); + QUnit.test('empty many2one field', async function (assert) { + assert.expect(4); + + const form = await createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: `<form string="Partners"> + <sheet> + <group> + <field name="trululu"/> + </group> + </sheet> + </form>`, + viewOptions: { + mode: 'edit', + }, + }); + + const $dropdown = form.$('.o_field_many2one input').autocomplete('widget'); + await testUtils.fields.many2one.clickOpenDropdown('trululu'); + assert.containsNone($dropdown, 'li.o_m2o_dropdown_option', + 'autocomplete should not contains dropdown options'); + assert.containsOnce($dropdown, 'li.o_m2o_start_typing', + 'autocomplete should contains start typing option'); + + await testUtils.fields.editAndTrigger(form.$('.o_field_many2one[name="trululu"] input'), + 'abc', 'keydown'); + await testUtils.nextTick(); + assert.containsN($dropdown, 'li.o_m2o_dropdown_option', 2, + 'autocomplete should contains 2 dropdown options'); + assert.containsNone($dropdown, 'li.o_m2o_start_typing', + 'autocomplete should not contains start typing option'); + + form.destroy(); + }); + + QUnit.test('empty many2one field with node options', async function (assert) { + assert.expect(2); + + const form = await createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: `<form string="Partners"> + <sheet> + <group> + <field name="trululu" options="{'no_create_edit': 1}"/> + <field name="product_id" options="{'no_create_edit': 1, 'no_quick_create': 1}"/> + </group> + </sheet> + </form>`, + viewOptions: { + mode: 'edit', + }, + }); + + const $dropdownTrululu = form.$('.o_field_many2one[name="trululu"] input').autocomplete('widget'); + const $dropdownProduct = form.$('.o_field_many2one[name="product_id"] input').autocomplete('widget'); + await testUtils.fields.many2one.clickOpenDropdown('trululu'); + assert.containsOnce($dropdownTrululu, 'li.o_m2o_start_typing', + 'autocomplete should contains start typing option'); + + await testUtils.fields.many2one.clickOpenDropdown('product_id'); + assert.containsNone($dropdownProduct, 'li.o_m2o_start_typing', + 'autocomplete should contains start typing option'); + + form.destroy(); + }); + QUnit.test('many2one in edit mode', async function (assert) { - assert.expect(16); + assert.expect(17); // create 10 partners to have the 'Search More' option in the autocomplete dropdown for (var i = 0; i < 10; i++) { @@ -716,9 +785,11 @@ QUnit.module('fields', {}, function () { assert.ok($dropdown.is(':visible'), 'clicking on the m2o input should open the dropdown if it is not open yet'); assert.strictEqual($dropdown.find('li:not(.o_m2o_dropdown_option)').length, 7, - 'autocomplete should contains 7 suggestions'); - assert.strictEqual($dropdown.find('li.o_m2o_dropdown_option').length, 2, - 'autocomplete should contain "Search More" and Create and Edit..."'); + 'autocomplete should contains 8 suggestions'); + assert.strictEqual($dropdown.find('li.o_m2o_dropdown_option').length, 1, + 'autocomplete should contain "Search More"'); + assert.containsNone($dropdown, 'li.o_m2o_start_typing', + 'autocomplete should not contains start typing option if value is available'); await testUtils.fields.many2one.clickOpenDropdown('trululu'); assert.ok(!$dropdown.is(':visible'), @@ -808,9 +879,7 @@ QUnit.module('fields', {}, function () { }, }); - // click on 'Create and Edit' in m2o dropdown - await testUtils.fields.many2one.clickOpenDropdown('product_id'); - await testUtils.fields.many2one.clickItem('product_id', 'Create and Edit'); + await testUtils.fields.many2one.createAndEdit('product_id', "ABC"); assert.containsOnce(document.body, '.modal .o_form_view'); // quick create 'new value' @@ -891,8 +960,8 @@ QUnit.module('fields', {}, function () { await testUtils.fields.many2one.clickOpenDropdown('trululu'); assert.isVisible($dropdown); - assert.containsN($dropdown, 'li:not(.o_m2o_dropdown_option)', 3, - 'autocomplete should contains 3 suggestions'); + assert.containsN($dropdown, 'li:not(.o_m2o_dropdown_option)', 4, + 'autocomplete should contains 4 suggestions'); // search with leading spaces form.$('.o_field_many2one input').val(' first').trigger('keydown').trigger('keyup'); diff --git a/addons/web/static/tests/fields/relational_fields/field_one2many_tests.js b/addons/web/static/tests/fields/relational_fields/field_one2many_tests.js index c2801eb9ac1..f3e5b036fb5 100644 --- a/addons/web/static/tests/fields/relational_fields/field_one2many_tests.js +++ b/addons/web/static/tests/fields/relational_fields/field_one2many_tests.js @@ -264,7 +264,7 @@ QUnit.module('fields', {}, function () { }); QUnit.test('O2M with parented m2o and domain on parent.m2o', async function (assert) { - assert.expect(3); + assert.expect(4); /* records in an o2m can have a m2o pointing to themselves * in that case, a domain evaluation on that field followed by name_search @@ -299,8 +299,7 @@ QUnit.module('fields', {}, function () { await testUtils.dom.click(form.$('.o_field_x2many_list[name=turtles] .o_field_x2many_list_row_add a')); - await testUtils.fields.many2one.clickOpenDropdown('parent_id'); - await testUtils.fields.many2one.clickHighlightedItem('parent_id'); + await testUtils.fields.many2one.createAndEdit('parent_id'); var $modal = $('.modal-content'); @@ -8131,8 +8130,7 @@ QUnit.module('fields', {}, function () { assert.containsOnce(form, '.o_selected_row', "should have create a new row in edition"); - await testUtils.fields.many2one.clickOpenDropdown('turtle_trululu'); - await testUtils.fields.many2one.clickItem('turtle_trululu','Create and Edit...'); + await testUtils.fields.many2one.createAndEdit('turtle_trululu', "ABC"); assert.strictEqual($('.modal .o_form_view').length, 1, "should have opened a form view in a dialog"); diff --git a/addons/web/static/tests/fields/relational_fields_tests.js b/addons/web/static/tests/fields/relational_fields_tests.js index c5a1e5765e4..bbbf74f5b7b 100644 --- a/addons/web/static/tests/fields/relational_fields_tests.js +++ b/addons/web/static/tests/fields/relational_fields_tests.js @@ -1370,8 +1370,8 @@ QUnit.module('relational_fields', { // add an other existing tag var $input = form.$('.o_field_many2manytags input'); await testUtils.fields.many2one.clickOpenDropdown('timmy'); - assert.strictEqual($input.autocomplete('widget').find('li').length, 1, - "autocomplete dropdown should have 1 entry"); + assert.strictEqual($input.autocomplete('widget').find('li').length, 2, + "autocomplete dropdown should have 2 entry"); assert.strictEqual($input.autocomplete('widget').find('li a:contains("red")').length, 1, "autocomplete dropdown should contain 'red'"); await testUtils.fields.many2one.clickHighlightedItem('timmy'); @@ -1479,8 +1479,8 @@ QUnit.module('relational_fields', { // add an other existing tag var $input = form.$('.o_field_many2manytags input'); await testUtils.fields.many2one.clickOpenDropdown('timmy'); - assert.strictEqual($input.autocomplete('widget').find('li').length, 1, - "autocomplete dropdown should have 1 entry"); + assert.strictEqual($input.autocomplete('widget').find('li').length, 2, + "autocomplete dropdown should have 2 entry"); assert.strictEqual($input.autocomplete('widget').find('li a:contains("silver")').length, 1, "autocomplete dropdown should contain 'silver'"); await testUtils.fields.many2one.clickHighlightedItem('timmy'); @@ -3452,6 +3452,7 @@ QUnit.module('relational_fields', { relationalFields.FieldMany2One.prototype.AUTOCOMPLETE_DELAY = 0; await testUtils.dom.click(form.$el.find('.o_input_dropdown>input')); + await testUtils.fields.editInput(form.$('.o_field_many2one input'), 'ABC'); // click create and edit await testUtils.dom.click($('.ui-autocomplete .ui-menu-item a:contains(Create and)').trigger('mouseenter')); diff --git a/addons/web/static/tests/views/view_dialogs_tests.js b/addons/web/static/tests/views/view_dialogs_tests.js index e86d0f53297..26fc002605a 100644 --- a/addons/web/static/tests/views/view_dialogs_tests.js +++ b/addons/web/static/tests/views/view_dialogs_tests.js @@ -324,7 +324,7 @@ QUnit.module('Views', { return Promise.resolve(false); } if (route === '/web/dataset/call_kw/instrument/create') { - assert.deepEqual(args.args, [{badassery: [[6, false, [1]]], name: false}], + assert.deepEqual(args.args, [{badassery: [[6, false, [1]]], name: "ABC"}], 'The method create should have been called with the right arguments'); return Promise.resolve(false); } @@ -334,8 +334,7 @@ QUnit.module('Views', { await testUtils.form.clickEdit(form); await testUtils.dom.click(form.$('.o_field_x2many_list_row_add a')); - await testUtils.dom.click(form.$('.o_field_widget .o_field_many2one[name=instrument] input')); - await testUtils.dom.click($('ul.ui-autocomplete.ui-front.ui-menu.ui-widget.ui-widget-content li.o_m2o_dropdown_option').first()); + await testUtils.fields.many2one.createAndEdit("instrument"); var $modal = $('.modal-lg'); @@ -495,7 +494,7 @@ QUnit.module('Views', { }); QUnit.test('propagate can_create onto the search popup o2m', async function (assert) { - assert.expect(3); + assert.expect(4); this.data.instrument.records = [ {id: 1, name: 'Tromblon1'}, @@ -539,9 +538,13 @@ QUnit.module('Views', { await testUtils.fields.many2one.clickOpenDropdown('instrument'); - assert.notOk($('.ui-autocomplete a:contains(Create and Edit)').length, - 'Create and edit not present in dropdown'); + assert.containsNone(form, '.ui-autocomplete a:contains(Start typing...)'); + + await testUtils.fields.editInput(form.el.querySelector(".o_field_many2one[name=instrument] input"), "a"); + + assert.containsNone(form, '.ui-autocomplete a:contains(Create and Edit)'); + await testUtils.fields.editInput(form.el.querySelector(".o_field_many2one[name=instrument] input"), ""); await testUtils.fields.many2one.clickItem('instrument', 'Search More...'); var $modal = $('.modal-dialog.modal-lg'); diff --git a/odoo/addons/test_new_api/static/tests/tours/x2many.js b/odoo/addons/test_new_api/static/tests/tours/x2many.js index 1eeb10e6977..a8f207fff6d 100644 --- a/odoo/addons/test_new_api/static/tests/tours/x2many.js +++ b/odoo/addons/test_new_api/static/tests/tours/x2many.js @@ -26,6 +26,10 @@ odoo.define('web.test.x2many', function (require) { trigger: 'tr:contains(Moderator) .o_input_dropdown > input', run: 'click', }, { + content: "insert value in moderator", + trigger: 'input.ui-autocomplete-input', + run: 'text test', + }, { content: "click on 'Create and Edit...'", trigger: '.ui-autocomplete .o_m2o_dropdown_option:last', }, { |
