diff --git a/addons/web/static/src/views/fields/formatters.js b/addons/web/static/src/views/fields/formatters.js index 033959e4b7e..8bd27f7cc68 100644 --- a/addons/web/static/src/views/fields/formatters.js +++ b/addons/web/static/src/views/fields/formatters.js @@ -8,6 +8,8 @@ import { escape, intersperse, nbsp, sprintf } from "@web/core/utils/strings"; import { isBinarySize } from "@web/core/utils/binary"; import { session } from "@web/session"; +const { markup } = owl; + // ----------------------------------------------------------------------------- // Helpers // ----------------------------------------------------------------------------- @@ -121,7 +123,13 @@ export function formatBinary(value) { * @returns {string} */ export function formatBoolean(value) { - return value ? _t("True") : _t("False"); + return markup(` +
+ +
`); } /** @@ -287,7 +295,7 @@ export function formatMany2one(value, options) { if (!value) { value = ""; } else { - value = value[1]; + value = value[1] || ""; } if (options && options.escape) { value = encodeURIComponent(value); diff --git a/addons/web/static/src/views/kanban/kanban_compiler.js b/addons/web/static/src/views/kanban/kanban_compiler.js index 1402e833071..570aac1dca7 100644 --- a/addons/web/static/src/views/kanban/kanban_compiler.js +++ b/addons/web/static/src/views/kanban/kanban_compiler.js @@ -234,7 +234,7 @@ export class KanbanCompiler extends ViewCompiler { if (!el.hasAttribute("widget")) { // fields without a specified widget are rendered as simple spans in kanban records const fieldName = el.getAttribute("name"); - compiled = createElement("span", { "t-esc": `record["${fieldName}"].value` }); + compiled = createElement("span", { "t-out": `record["${fieldName}"].value` }); } else { compiled = super.compileField(el, params); const fieldId = el.getAttribute("field_id") || el.getAttribute("name"); diff --git a/addons/web/static/src/views/list/list_renderer.js b/addons/web/static/src/views/list/list_renderer.js index 2244c7bc9d0..a64533673d4 100644 --- a/addons/web/static/src/views/list/list_renderer.js +++ b/addons/web/static/src/views/list/list_renderer.js @@ -348,9 +348,7 @@ export class ListRenderer extends Component { } canUseFormatter(column, record) { - return ( - !record.isInEdition && !column.widget && record.fields[column.name].type !== "boolean" - ); + return !record.isInEdition && !column.widget; } focusCell(column, forward = true) { diff --git a/addons/web/static/src/views/list/list_renderer.xml b/addons/web/static/src/views/list/list_renderer.xml index 408745aa0f6..69f3ac37425 100644 --- a/addons/web/static/src/views/list/list_renderer.xml +++ b/addons/web/static/src/views/list/list_renderer.xml @@ -225,7 +225,7 @@ data-tooltip-delay="1000" t-on-click="(ev) => this.onCellClicked(record, column, ev)" tabindex="-1"> - + diff --git a/addons/web/static/tests/views/fields/boolean_field_tests.js b/addons/web/static/tests/views/fields/boolean_field_tests.js index 5278b69d38c..08c2237359e 100644 --- a/addons/web/static/tests/views/fields/boolean_field_tests.js +++ b/addons/web/static/tests/views/fields/boolean_field_tests.js @@ -239,29 +239,6 @@ QUnit.module("Fields", (hooks) => { 3, "should still have only 3 checked input" ); - - // Re-Edit the line to check the checkbox back but this time click on - // the checkbox directly in readonly mode. - // This should not toggle the checkbox and only pass the record in edition. - cell = target.querySelector("tr.o_data_row td:not(.o_list_record_selector)"); - await click(cell, ".o_field_boolean"); - - assert.notOk( - cell.querySelector(".o-checkbox input").disabled, - "input should not have the disabled property in edit mode" - ); - assert.containsN( - target, - "tbody td:not(.o_list_record_selector) .o-checkbox", - 5, - "should still have 5 checkboxes" - ); - assert.containsN( - target, - "tbody td:not(.o_list_record_selector) .o-checkbox input:checked", - 3, - "should still have only 3 checked input" - ); }); QUnit.test("readonly boolean field", async function (assert) { diff --git a/addons/web/static/tests/views/fields/html_field_tests.js b/addons/web/static/tests/views/fields/html_field_tests.js index 2ef1afd4acc..207859674e9 100644 --- a/addons/web/static/tests/views/fields/html_field_tests.js +++ b/addons/web/static/tests/views/fields/html_field_tests.js @@ -1,6 +1,6 @@ /** @odoo-module **/ -import { editInput, getFixture } from "@web/../tests/helpers/utils"; +import { click, editInput, getFixture } from "@web/../tests/helpers/utils"; import { makeView, setupViewRegistries } from "@web/../tests/views/helpers"; import { registry } from "@web/core/registry"; import { HtmlField } from "@web/views/fields/html/html_field"; @@ -34,7 +34,7 @@ QUnit.module("Fields", ({ beforeEach }) => { QUnit.module("HtmlField"); - QUnit.test("html fields are correctly rendered (readonly)", async (assert) => { + QUnit.test("html fields are correctly rendered in form view (readonly)", async (assert) => { await makeView({ type: "form", resModel: "partner", @@ -68,4 +68,46 @@ QUnit.module("Fields", ({ beforeEach }) => { await editInput(textarea, null, BLUE_TEXT); assert.strictEqual(textarea.value, BLUE_TEXT); }); + + QUnit.test("html fields are correctly rendered in list view", async (assert) => { + await makeView({ + type: "list", + resModel: "partner", + serverData, + arch: ` + + + `, + }); + const txt = target.querySelector(".o_data_row [name='txt']"); + assert.strictEqual(txt.textContent, "some text"); + assert.strictEqual(txt.querySelector(".kek").style.color, "red"); + + await click(target.querySelector(".o_data_row [name='txt']")); + assert.strictEqual( + target.querySelector(".o_data_row [name='txt'] textarea").value, + '
some text
' + ); + }); + + QUnit.test("html fields are correctly rendered in kanban view", async (assert) => { + await makeView({ + type: "kanban", + resModel: "partner", + serverData, + arch: ` + + + +
+ +
+
+
+
`, + }); + const txt = target.querySelector(".kek"); + assert.strictEqual(txt.textContent, "some text"); + assert.strictEqual(txt.style.color, "red"); + }); }); diff --git a/addons/web/static/tests/views/fields/one2many_field_tests.js b/addons/web/static/tests/views/fields/one2many_field_tests.js index 437e2c8d767..6ad8ee73488 100644 --- a/addons/web/static/tests/views/fields/one2many_field_tests.js +++ b/addons/web/static/tests/views/fields/one2many_field_tests.js @@ -11103,7 +11103,7 @@ QUnit.module("Fields", (hooks) => { // the next line should be displayed below the newly added one assert.containsN(target, ".o_data_row", 2, "should have 2 records"); assert.deepEqual( - getNodesTextContent(target.querySelectorAll(".o_data_cell")), + [...target.querySelectorAll(".o_data_cell")].map(el => el.textContent.trim()), ["pi", "", "kawa", ""], "should display the correct records on page 1" ); diff --git a/addons/web/static/tests/views/kanban_view_tests.js b/addons/web/static/tests/views/kanban_view_tests.js index fe68f35a8c3..5b001c0000c 100644 --- a/addons/web/static/tests/views/kanban_view_tests.js +++ b/addons/web/static/tests/views/kanban_view_tests.js @@ -9800,8 +9800,9 @@ QUnit.module("Views", (hooks) => { `, }); - assert.containsN(target, ".o_kanban_record:contains(True)", 3); - assert.containsOnce(target, ".o_kanban_record:contains(False)"); + assert.containsN(target, ".o_kanban_record input:disabled", 4); + assert.containsN(target, ".o_kanban_record input:checked", 3); + assert.containsOnce(target, ".o_kanban_record input:not(:checked)"); }); QUnit.test("kanban view with boolean widget", async (assert) => { diff --git a/addons/web/static/tests/views/list_view_tests.js b/addons/web/static/tests/views/list_view_tests.js index 3198da57c75..3f95e530fdf 100644 --- a/addons/web/static/tests/views/list_view_tests.js +++ b/addons/web/static/tests/views/list_view_tests.js @@ -15125,6 +15125,7 @@ QUnit.module("Views", (hooks) => { assert.verifySteps(["create"]); }); + QUnit.test( "classNames given to a field are set on the right field directly", async function (assert) { @@ -15139,7 +15140,7 @@ QUnit.module("Views", (hooks) => { `, }); assert.doesNotHaveClass( - target.querySelector(".o_field_cell:nth-child(2)"), + target.querySelectorAll(".o_field_cell")[2], "d-flex align-items-center", "classnames are not set on the first cell" ); @@ -15148,15 +15149,10 @@ QUnit.module("Views", (hooks) => { "d-flex align-items-center", "classnames are set on the corresponding field div directly" ); - assert.doesNotHaveClass( - target.querySelector(".o_field_cell:nth-child(3)"), - "d-none", - "classnames are not set on the second cell" - ); assert.hasClass( - target.querySelector(".o_field_boolean"), + target.querySelectorAll(".o_field_cell")[3], "d-none", - "classnames are set on the second field div directly" + "classnames are set on the second cell" ); } );