summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDhruv Patel <dhp@odoo.com>2020-06-03 10:35:33 +0000
committerJulien Mougenot <jum@odoo.com>2020-06-10 13:08:33 +0000
commiteacbec1e03b1f25e71875fb7caed646a53af67ed (patch)
tree0945bb57b0c438bc8af7ee3b21f1cc49567bf28f
parenta392da16015c69161814e83f1cde5ddf40782505 (diff)
[IMP] web,*: highlight quick create feature to user
Generally, Users are not necessarily aware that they can quick create a most records by simply typing in their name+enter in the many2xxx field input. The exact purpose of this commit is to make sure the user discovers the quick create feature of our many2xxx fields. For that, when the input is empty, display 'Start typing to create a record...' at the bottom of the dropdown when can_create is set and no_create_edit option not set. So the user can easily understand that by typing and pressing enter will create the new record. Also "Search and Create" options in the dropdown only been shown to the user when it type anything in the input box as the same case in the "Create" option. Task : 2266557 Co-authored-by: Mohammed Shekha <msh@openerp.com> Co-authored-by: Julien Mougenot <jum@odoo.com>
-rw-r--r--addons/sale_expense/static/tests/sale_order_many2one_tests.js4
-rw-r--r--addons/web/static/src/js/fields/relational_fields.js10
-rw-r--r--addons/web/static/src/scss/dropdown.scss10
-rw-r--r--addons/web/static/tests/fields/relational_fields/field_many2many_tests.js9
-rw-r--r--addons/web/static/tests/fields/relational_fields/field_many2one_tests.js91
-rw-r--r--addons/web/static/tests/fields/relational_fields/field_one2many_tests.js8
-rw-r--r--addons/web/static/tests/fields/relational_fields_tests.js9
-rw-r--r--addons/web/static/tests/views/view_dialogs_tests.js15
-rw-r--r--odoo/addons/test_new_api/static/tests/tours/x2many.js4
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',
}, {