diff --git a/addons/web/static/src/js/fields/relational_fields.js b/addons/web/static/src/js/fields/relational_fields.js index 5aecf7b592f..f3125c72f29 100644 --- a/addons/web/static/src/js/fields/relational_fields.js +++ b/addons/web/static/src/js/fields/relational_fields.js @@ -1833,6 +1833,7 @@ var FieldMany2ManyTags = AbstractField.extend({ * @param {MouseEvent} event */ _onDeleteTag: function (event) { + event.stopPropagation(); this._removeTag($(event.target).parent().data('id')); }, /** @@ -1907,8 +1908,8 @@ var FormFieldMany2ManyTags = FieldMany2ManyTags.extend({ 'tag_id': tagID, })); - $(ev.currentTarget).append(this.$color_picker); - this.$color_picker.dropdown('toggle'); + $(ev.currentTarget).after(this.$color_picker); + this.$color_picker.dropdown(); this.$color_picker.attr("tabindex", 1).focus(); if (!tagColor) { this.$('.custom-checkbox input').prop('checked', true); diff --git a/addons/web/static/src/scss/fields.scss b/addons/web/static/src/scss/fields.scss index 9a1e904fdc2..1c6fdf3abb1 100644 --- a/addons/web/static/src/scss/fields.scss +++ b/addons/web/static/src/scss/fields.scss @@ -95,7 +95,7 @@ max-width: 100%; } - > .badge { + .badge { flex: 0 0 auto; border: 0; font-size: 12px; @@ -107,53 +107,53 @@ max-width: 200px; } - // o-kanban-colorpicker without customizing - // '&:first-child > a::before' (transparent red-crossed colorpick) - @mixin o-tag-colorpicker { - $o-tag-colorpicker-padding-right: $o-dropdown-hpadding - 2 * 5px; // FIXME was $o-kanban-inner-hmargin before scss convertion - - max-width: 100%; - padding: 3px $o-tag-colorpicker-padding-right 3px $o-dropdown-hpadding; - - > li { - display: inline-block; - margin: 5px 5px 0 0; // FIXME was $o-kanban-inner-hmargin before scss convertion - border: 1px solid white; - box-shadow: 0 0 0 1px gray('300'); - - > a { - display: block; - - &::after { - content: ""; - display: block; - width: 20px; - height: 15px; - } - } - - &:last-of-type { - box-shadow: 0 0 0 0px white; // remove grey border on hide in kanban - color: $o-main-text-color; - } - } - } - - > .tagcolor_dropdown_menu { - min-width: 150px; // down from 160px of .dropdown-menu - margin-right: 0px; // cancel right margin of .dropdown-menu - } - - > .o_colorpicker > ul { - @include o-tag-colorpicker; - white-space: normal; - } - .o_delete { cursor: pointer; } } + // o-kanban-colorpicker without customizing + // '&:first-child > a::before' (transparent red-crossed colorpick) + @mixin o-tag-colorpicker { + $o-tag-colorpicker-padding-right: $o-dropdown-hpadding - 2 * 5px; // FIXME was $o-kanban-inner-hmargin before scss convertion + + max-width: 100%; + padding: 3px $o-tag-colorpicker-padding-right 3px $o-dropdown-hpadding; + + > li { + display: inline-block; + margin: 5px 5px 0 0; // FIXME was $o-kanban-inner-hmargin before scss convertion + border: 1px solid white; + box-shadow: 0 0 0 1px gray('300'); + + > a { + display: block; + + &::after { + content: ""; + display: block; + width: 20px; + height: 15px; + } + } + + &:last-of-type { + box-shadow: 0 0 0 0px white; // remove grey border on hide in kanban + color: $o-main-text-color; + } + } + } + + .tagcolor_dropdown_menu { + min-width: 150px; // down from 160px of .dropdown-menu + margin-right: 0px; // cancel right margin of .dropdown-menu + } + + .o_colorpicker > ul { + @include o-tag-colorpicker; + white-space: normal; + } + @for $size from 1 through length($o-colors) { .o_tag_color_#{$size - 1} { @if $size == 1 { diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml index 5f6f8253bdf..9b6ef0099d5 100644 --- a/addons/web/static/src/xml/base.xml +++ b/addons/web/static/src/xml/base.xml @@ -833,10 +833,12 @@ - + diff --git a/addons/web/static/tests/fields/relational_fields_tests.js b/addons/web/static/tests/fields/relational_fields_tests.js index f0e71ca5316..bb7b4a446e6 100644 --- a/addons/web/static/tests/fields/relational_fields_tests.js +++ b/addons/web/static/tests/fields/relational_fields_tests.js @@ -11740,9 +11740,9 @@ QUnit.module('relational_fields', { assert.strictEqual($input.autocomplete('widget').find('li').length, 3, "autocomplete dropdown should have 3 entries (2 values + 'Search and Edit...')"); $input.autocomplete('widget').find('li:first()').click(); // adds a tag - assert.strictEqual(form.$('.o_field_many2manytags[name="timmy"] > button').length, 1, + assert.strictEqual(form.$('.o_field_many2manytags[name="timmy"] > .dropdown > button').length, 1, "should contain 1 tag"); - assert.ok(form.$('.o_field_many2manytags[name="timmy"] > button:contains("gold")').length, + assert.ok(form.$('.o_field_many2manytags[name="timmy"] > .dropdown > button:contains("gold")').length, "should contain newly added tag 'gold'"); form.destroy(); @@ -11775,7 +11775,7 @@ QUnit.module('relational_fields', { return this._super.apply(this, arguments); }, }); - assert.strictEqual(form.$('.o_field_many2manytags > button').length, 2, + assert.strictEqual(form.$('.o_field_many2manytags > .dropdown > button').length, 2, "should contain 2 tags"); assert.ok(form.$('button:contains(gold)').length, 'should have fetched and rendered gold partner tag'); @@ -11786,7 +11786,7 @@ QUnit.module('relational_fields', { form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('.o_field_many2manytags > button').length, 2, + assert.strictEqual(form.$('.o_field_many2manytags > .dropdown > button').length, 2, "should still contain 2 tags in edit mode"); assert.ok(form.$('.o_tag_color_2 .o_badge_text:contains(gold)').length, 'first tag should still contain "gold" and be color 2 in edit mode'); @@ -11801,18 +11801,18 @@ QUnit.module('relational_fields', { assert.strictEqual($input.autocomplete('widget').find('li a:contains("red")').length, 1, "autocomplete dropdown should contain 'red'"); $input.autocomplete('widget').find('li').click(); // add 'red' - assert.strictEqual(form.$('.o_field_many2manytags > button').length, 3, + assert.strictEqual(form.$('.o_field_many2manytags > .dropdown > button').length, 3, "should contain 3 tags"); - assert.ok(form.$('.o_field_many2manytags > button:contains("red")').length, + assert.ok(form.$('.o_field_many2manytags > .dropdown > button:contains("red")').length, "should contain newly added tag 'red'"); - assert.ok(form.$('.o_field_many2manytags > button[data-color=8]:contains("red")').length, + assert.ok(form.$('.o_field_many2manytags > .dropdown > button[data-color=8]:contains("red")').length, "should have fetched the color of added tag"); // remove tag with id 14 form.$('.o_field_many2manytags button[data-id=14] .o_delete').click(); - assert.strictEqual(form.$('.o_field_many2manytags > button').length, 2, + assert.strictEqual(form.$('.o_field_many2manytags > .dropdown > button').length, 2, "should contain 2 tags"); - assert.ok(!form.$('.o_field_many2manytags > button:contains("silver")').length, + assert.ok(!form.$('.o_field_many2manytags > .dropdown > button:contains("silver")').length, "should not contain tag 'silver' anymore"); // save the record (should do the write RPC with the correct commands) @@ -11824,7 +11824,7 @@ QUnit.module('relational_fields', { assert.ok(form.$('.o_field_many2manytags button[data-id=13] .o_colorpicker .custom-checkbox'), "should have a checkbox in the colorpicker dropdown menu"); $input.click(); - var $checkBox = form.$('.o_field_many2manytags button[data-id=13] .o_colorpicker .custom-checkbox input'); + var $checkBox = form.$('.o_field_many2manytags button[data-id=13]').next().find('.custom-checkbox input'); assert.notOk($checkBox.is(':checked'), "should have unticked checkbox in colorpicker dropdown menu"); $checkBox.mousedown(); @@ -11832,7 +11832,7 @@ QUnit.module('relational_fields', { assert.equal($input.data('color'), "0", "should become transparent when toggling on checkbox"); $input.click(); - $checkBox = form.$('.o_field_many2manytags button[data-id=13] .o_colorpicker .custom-checkbox input'); // refresh + $checkBox = form.$('.o_field_many2manytags button[data-id=13]').next().find('.custom-checkbox input'); // refresh assert.ok($checkBox.is(':checked'), "should have a ticked checkbox in colorpicker dropdown menu after mousedown"); $checkBox.mousedown(); @@ -11840,7 +11840,7 @@ QUnit.module('relational_fields', { assert.equal($input.data('color'), "8", "should revert to old color when toggling off checkbox"); $input.click(); - $checkBox = form.$('.o_field_many2manytags button[data-id=13] .o_colorpicker .custom-checkbox input'); // refresh + $checkBox = form.$('.o_field_many2manytags button[data-id=13]').next().find('.custom-checkbox input'); // refresh assert.notOk($checkBox.is(':checked'), "should have an unticked checkbox in colorpicker dropdown menu after 2nd click"); // TODO: it would be nice to test the behaviors of the autocomplete dropdown @@ -11873,7 +11873,7 @@ QUnit.module('relational_fields', { return this._super.apply(this, arguments); } }); - assert.strictEqual(form.$('.o_field_many2manytags > button').length, 1, + assert.strictEqual(form.$('.o_field_many2manytags > .dropdown > button').length, 1, "should contain 1 tag"); assert.ok(form.$('button:contains(gold)').length, 'should have fetched and rendered gold partner tag'); @@ -11888,9 +11888,9 @@ QUnit.module('relational_fields', { assert.strictEqual($input.autocomplete('widget').find('li a:contains("silver")').length, 1, "autocomplete dropdown should contain 'silver'"); $input.autocomplete('widget').find('li').click(); // add 'silver' - assert.strictEqual(form.$('.o_field_many2manytags > button').length, 2, + assert.strictEqual(form.$('.o_field_many2manytags > .dropdown > button').length, 2, "should contain 2 tags"); - assert.ok(form.$('.o_field_many2manytags > button:contains("silver")').length, + assert.ok(form.$('.o_field_many2manytags > .dropdown > button:contains("silver")').length, "should contain newly added tag 'silver'"); form.destroy(); @@ -11923,9 +11923,9 @@ QUnit.module('relational_fields', { assert.strictEqual($input.autocomplete('widget').find('li').length, 3, "autocomplete dropdown should have 3 entries (2 values + 'Search and Edit...')"); $input.autocomplete('widget').find('li:first()').click(); // adds a tag - assert.strictEqual(form.$('.o_field_many2manytags > button').length, 1, + assert.strictEqual(form.$('.o_field_many2manytags > .dropdown > button').length, 1, "should contain 1 tag"); - assert.ok(form.$('.o_field_many2manytags > button:contains("gold")').length, + assert.ok(form.$('.o_field_many2manytags > .dropdown > button:contains("gold")').length, "should contain newly added tag 'gold'"); // save the record (should do the write RPC with the correct commands) @@ -12101,7 +12101,7 @@ QUnit.module('relational_fields', { '', res_id: 1, }); - assert.strictEqual(form.$('.o_field_widget[name="partner_ids"] > button').length, 100, + assert.strictEqual(form.$('.o_field_widget[name="partner_ids"] > .dropdown > button').length, 100, 'should have rendered 100 tags'); form.destroy(); }); @@ -12126,14 +12126,14 @@ QUnit.module('relational_fields', { }); form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('.o_field_many2manytags > button').length, 1, + assert.strictEqual(form.$('.o_field_many2manytags > .dropdown > button').length, 1, "should contain one tag"); // update foo, which will trigger an onchange and update timmy // -> m2mtags input should not have taken the focus form.$('input:first').focus(); form.$('input:first').val('trigger onchange').trigger('input'); - assert.strictEqual(form.$('.o_field_many2manytags > button').length, 0, + assert.strictEqual(form.$('.o_field_many2manytags > .dropdown > button').length, 0, "should contain no tags"); assert.strictEqual(form.$('input:first').get(0), document.activeElement, "foo input should have kept the focus"); @@ -12141,14 +12141,14 @@ QUnit.module('relational_fields', { // add a tag -> m2mtags input should still have the focus form.$('.o_field_many2manytags input').click(); // opens the dropdown form.$('.o_field_many2manytags input').autocomplete('widget').find('li:first').click(); - assert.strictEqual(form.$('.o_field_many2manytags > button').length, 1, + assert.strictEqual(form.$('.o_field_many2manytags > .dropdown > button').length, 1, "should contain a tag"); assert.strictEqual(form.$('.o_field_many2manytags input').get(0), document.activeElement, "m2m tags input should have kept the focus"); // remove a tag -> m2mtags input should still have the focus form.$('.o_field_many2manytags .o_delete').click(); - assert.strictEqual(form.$('.o_field_many2manytags > button').length, 0, + assert.strictEqual(form.$('.o_field_many2manytags > .dropdown > button').length, 0, "should contain no tags"); assert.strictEqual(form.$('.o_field_many2manytags input').get(0), document.activeElement, "m2m tags input should have kept the focus");