diff --git a/addons/project/static/src/scss/project_widgets.scss b/addons/project/static/src/scss/project_widgets.scss index 815534ae13b..01fe49f302a 100644 --- a/addons/project/static/src/scss/project_widgets.scss +++ b/addons/project/static/src/scss/project_widgets.scss @@ -37,7 +37,7 @@ cursor: pointer; } -.o_kanban_project_tasks .o_kanban_renderer .o_field_many2manytags, .o_kanban_tags{ +.o_kanban_project_tasks .o_kanban_renderer .o_field_many2manytags{ margin: 0px; } diff --git a/addons/web/static/src/core/tags_list/tags_list.js b/addons/web/static/src/core/tags_list/tags_list.js index 77690758d22..b939fa8b7d2 100644 --- a/addons/web/static/src/core/tags_list/tags_list.js +++ b/addons/web/static/src/core/tags_list/tags_list.js @@ -5,17 +5,14 @@ import { Component } from "@odoo/owl"; export class TagsList extends Component { static template = "web.TagsList"; static defaultProps = { - className: "", displayBadge: true, displayText: true, }; static props = { - className: { type: String, optional: true }, displayBadge: { type: Boolean, optional: true }, displayText: { type: Boolean, optional: true }, - name: { type: String, optional: true }, itemsVisible: { type: Number, optional: true }, - tags: { type: Object, optional: true }, + tags: { type: Object }, }; get visibleTagsCount() { return this.props.itemsVisible - 1; diff --git a/addons/web/static/src/core/tags_list/tags_list.xml b/addons/web/static/src/core/tags_list/tags_list.xml index 6e6b4bbd913..8bf06810bb6 100644 --- a/addons/web/static/src/core/tags_list/tags_list.xml +++ b/addons/web/static/src/core/tags_list/tags_list.xml @@ -3,7 +3,7 @@ - +
diff --git a/addons/web/static/src/views/fields/many2many_tags/kanban_many2many_tags_field.xml b/addons/web/static/src/views/fields/many2many_tags/kanban_many2many_tags_field.xml index 2fae728ff61..c1a1c8faa96 100644 --- a/addons/web/static/src/views/fields/many2many_tags/kanban_many2many_tags_field.xml +++ b/addons/web/static/src/views/fields/many2many_tags/kanban_many2many_tags_field.xml @@ -2,6 +2,6 @@ - + diff --git a/addons/web/static/src/views/fields/properties/property_tags.js b/addons/web/static/src/views/fields/properties/property_tags.js index 3d5ed930b7d..37102c7c1f4 100644 --- a/addons/web/static/src/views/fields/properties/property_tags.js +++ b/addons/web/static/src/views/fields/properties/property_tags.js @@ -68,6 +68,7 @@ export class PropertyTags extends Component { return { id: tagId, text: tagLabel, + className: this.props.canChangeTags ? "" : "pe-none", colorIndex: tagColorIndex || 0, onClick: (event) => this.onTagClick(event, tagId, tagColorIndex), onDelete: canDeleteTag && (() => this.onTagDelete(tagId)), diff --git a/addons/web/static/src/views/fields/properties/property_tags.scss b/addons/web/static/src/views/fields/properties/property_tags.scss index f9d64d257ae..a6b80c13193 100644 --- a/addons/web/static/src/views/fields/properties/property_tags.scss +++ b/addons/web/static/src/views/fields/properties/property_tags.scss @@ -1,9 +1,3 @@ -.o_field_property_tag_readonly { - // deactivate all click interactions with tags - // if we can't change their definition - pointer-events: none; -} - .o_field_property_tag { .o_tag { margin: 1px 2px 1px 0; diff --git a/addons/web/static/src/views/fields/properties/property_tags.xml b/addons/web/static/src/views/fields/properties/property_tags.xml index bbf733babc7..dfe6456c5ec 100644 --- a/addons/web/static/src/views/fields/properties/property_tags.xml +++ b/addons/web/static/src/views/fields/properties/property_tags.xml @@ -5,8 +5,7 @@
+ displayBadge="displayBadge"/>
diff --git a/addons/web/static/src/views/kanban/kanban_controller.scss b/addons/web/static/src/views/kanban/kanban_controller.scss index f186a63aa87..dd66ac9da9f 100644 --- a/addons/web/static/src/views/kanban/kanban_controller.scss +++ b/addons/web/static/src/views/kanban/kanban_controller.scss @@ -281,8 +281,7 @@ } // Kanban Record - Inner elements - .o_field_many2many_tags, - .o_kanban_tags { + .o_field_many2many_tags { display: block; margin-bottom: var(--KanbanRecord-gap-v); line-height: 1.2; diff --git a/addons/web/static/tests/core/tags_list_tests.js b/addons/web/static/tests/core/tags_list_tests.js new file mode 100644 index 00000000000..d08dd518cdc --- /dev/null +++ b/addons/web/static/tests/core/tags_list_tests.js @@ -0,0 +1,155 @@ +/** @odoo-module **/ + +import { browser } from "@web/core/browser/browser"; +import { TagsList } from "@web/core/tags_list/tags_list"; +import { makeTestEnv } from "../helpers/mock_env"; +import { getFixture, patchWithCleanup, mount, click } from "../helpers/utils"; + +import { Component, xml } from "@odoo/owl"; + +QUnit.module("Web Components", (hooks) => { + QUnit.module("TagsList"); + + let env; + let target; + + hooks.beforeEach(async () => { + env = await makeTestEnv(); + target = getFixture(); + patchWithCleanup(browser, { + setTimeout: (fn) => Promise.resolve().then(fn), + }); + }); + + QUnit.test("Can be rendered with different tags", async (assert) => { + class Parent extends Component { + setup() { + this.tags = [ + { + id: "tag1", + text: "Earth", + }, + { + colorIndex: 1, + id: "tag2", + text: "Wind", + onDelete: () => { + assert.step(`tag2 delete button has been clicked`); + }, + }, + { + colorIndex: 2, + id: "tag3", + text: "Fire", + onClick: () => { + assert.step(`tag3 has been clicked`); + }, + onDelete: () => { + assert.step(`tag3 delete button has been clicked`); + }, + }, + ]; + } + } + Parent.components = { TagsList }; + Parent.template = xml` + `; + + await mount(Parent, target, { env }); + assert.containsN(target, ".o_tag", 3); + + await click(target.querySelector(".o_tag:nth-of-type(2) .o_delete")); + assert.verifySteps(["tag2 delete button has been clicked"]); + + await click(target.querySelector(".o_tag:nth-of-type(3)")); + assert.verifySteps(["tag3 has been clicked"]); + }); + + QUnit.test("Tags can be displayed with an image", async (assert) => { + class Parent extends Component { + setup() { + this.tags = [ + { + img: "fake/url", + id: "tag1", + text: "Earth", + }, + { + img: "fake/url/2", + id: "tag2", + text: "Wind", + }, + ]; + } + } + Parent.components = { TagsList }; + Parent.template = xml` + `; + + await mount(Parent, target, { env }); + assert.containsN(target, ".o_tag", 2); + assert.strictEqual( + target.querySelector(".o_tag:nth-of-type(1) img").dataset.src, + "fake/url" + ); + assert.strictEqual( + target.querySelector(".o_tag:nth-of-type(2) img").dataset.src, + "fake/url/2" + ); + }); + + QUnit.test("Limiting the visible tags displays a counter", async (assert) => { + class Parent extends Component { + setup() { + this.tags = [ + { + id: "tag1", + text: "Water", + onDelete: () => {}, + }, + { + id: "tag2", + text: "Grass", + }, + { + id: "tag3", + text: "Fire", + }, + { + id: "tag4", + text: "Earth", + }, + { + id: "tag5", + text: "Wind", + }, + { + id: "tag6", + text: "Dust", + }, + ]; + } + } + Parent.components = { TagsList }; + Parent.template = xml` + `; + + await mount(Parent, target, { env }); + assert.containsN(target, ".o_tag", 2); + + const counter = target.querySelector(".rounded-circle"); + assert.strictEqual(counter.textContent, "+4", "the counter displays 4 more items"); + assert.deepEqual( + JSON.parse(counter.dataset.tooltipInfo), + { + tags: [ + { text: "Fire", id: "tag3" }, + { text: "Earth", id: "tag4" }, + { text: "Wind", id: "tag5" }, + { text: "Dust", id: "tag6" }, + ], + }, + "the counter has a tooltip displaying other items" + ); + }); +});