[REF] website_slides: convert slide_category_one2many

This commit converts the old "slide_category_one2many" field to the new
WOWL field API.

Part-of: odoo/odoo#97984
Co-authored-by: Lucas Perais (lpe) <lpe@odoo.com>
This commit is contained in:
Mathieu Duckerts-Antoine
2022-08-29 13:49:10 +02:00
co-authored by Lucas Perais
parent 86e85ad5fd
commit baf1d5b6d0
5 changed files with 319 additions and 1 deletions
+2
View File
@@ -71,6 +71,8 @@ Featuring
'website_slides/static/src/models/*.js',
],
'web.assets_backend': [
'website_slides/static/src/slide_category_one2many_field.js',
'website_slides/static/src/slide_category_list_renderer.js',
'website_slides/static/src/scss/slide_views.scss',
'website_slides/static/src/js/slide_category_one2many.js',
'website_slides/static/src/js/rating_field_backend.js',
@@ -0,0 +1,81 @@
/** @odoo-module */
import { makeContext } from "@web/core/context";
import { ListRenderer } from "@web/views/list/list_renderer";
const { useEffect } = owl;
export class SlideCategoryListRenderer extends ListRenderer {
setup() {
super.setup();
this.discriminant = "is_category";
this.titleField = "name";
useEffect(
(table) => {
if (table) {
table.classList.add("o_section_list_view");
}
},
() => [this.tableRef.el]
);
}
add(params) {
let editable = false;
if (params.context && !this.env.isSmall) {
const evaluatedContext = makeContext([params.context]);
if (evaluatedContext[`default_${this.discriminant}`]) {
editable = this.props.editable;
}
}
super.add({ ...params, editable });
}
getColumns(record) {
const columns = super.getColumns(record);
if (this.isSection(record)) {
return this.getSectionColumns(columns);
}
return columns;
}
getRowClass(record) {
const classNames = super.getRowClass(record).split(" ");
if (this.isSection(record)) {
classNames.push(`o_is_section`, `fw-bold`);
}
return classNames.join(" ");
}
getSectionColumns(columns) {
const sectionColumns = columns.filter((col) => col.widget === "handle");
const colspan = columns.length - sectionColumns.length;
const titleCol = columns.find(
(col) => col.type === "field" && col.name === this.titleField
);
sectionColumns.push({ ...titleCol, colspan });
return sectionColumns;
}
isInlineEditable(record) {
return this.isSection(record) && this.props.editable;
}
isSection(record) {
return record.data[this.discriminant];
}
onCellKeydownEditMode(hotkey) {
switch (hotkey) {
case "enter":
case "tab":
case "shift+tab": {
this.props.list.unselectRecord(true);
return true;
}
}
return super.onCellKeydownEditMode(...arguments);
}
}
@@ -0,0 +1,17 @@
/** @odoo-module */
import { registry } from "@web/core/registry";
import { SlideCategoryListRenderer } from "./slide_category_list_renderer";
import { X2ManyField } from "@web/views/fields/x2many/x2many_field";
class SlideCategoryOneToManyField extends X2ManyField {}
SlideCategoryOneToManyField.components = {
...X2ManyField.components,
ListRenderer: SlideCategoryListRenderer,
};
SlideCategoryOneToManyField.defaultProps = {
...X2ManyField.defaultProps,
editable: "bottom",
};
registry.category("fields").add("slide_category_one2many", SlideCategoryOneToManyField);
@@ -0,0 +1,218 @@
/** @odoo-module */
import { click, clickEdit, getFixture } from "@web/../tests/helpers/utils";
import { makeView, setupViewRegistries } from "@web/../tests/views/helpers";
QUnit.module("SlideCategoryOneToManyField", (hooks) => {
let serverData;
let target;
hooks.beforeEach(() => {
target = getFixture();
serverData = {
models: {
partner: {
fields: { lines: { type: "one2many", relation: "lines_sections" } },
records: [
{
id: 1,
lines: [1, 2],
},
],
},
lines_sections: {
fields: {
is_category: { type: "boolean" },
name: { type: "char", string: "Name" },
int: { type: "number", string: "Integer" },
},
records: [
{
id: 1,
is_category: true,
display_name: "firstSectionName",
name: "firstSectionTitle",
int: 4,
},
{
id: 2,
is_category: false,
display_name: "recordName",
name: "recordTitle",
int: 5,
},
],
},
},
views: {
"lines_sections,false,form": `
<form>
<field name="display_name" />
</form>
`,
},
};
setupViewRegistries();
});
QUnit.test("basic rendering", async (assert) => {
await makeView({
type: "form",
resModel: "partner",
resId: 1,
serverData,
arch: `
<form>
<field name="lines" widget="slide_category_one2many">
<tree>
<field name="is_category" invisible="1" />
<field name="name" />
<field name="display_name" />
<field name="int" />
</tree>
</field>
</form>
`,
});
assert.containsOnce(target, ".o_field_x2many .o_list_renderer table.o_section_list_view");
assert.containsN(target, ".o_data_row", 2);
assert.hasClass(target.querySelectorAll(".o_data_row")[0], "o_is_section fw-bold");
const rows = target.querySelectorAll(".o_data_row");
assert.strictEqual(rows[0].textContent, "firstSectionTitle");
assert.strictEqual(rows[1].textContent, "recordTitlerecordName5");
assert.strictEqual(rows[0].querySelector("td[name=name]").getAttribute("colspan"), "3");
assert.strictEqual(rows[1].querySelector("td[name=name]").getAttribute("colspan"), null);
});
QUnit.test("click on section behaves as usual in readonly mode", async (assert) => {
await makeView({
type: "form",
resModel: "partner",
resId: 1,
serverData,
arch: `
<form>
<field name="lines" widget="slide_category_one2many">
<tree>
<field name="is_category" invisible="1" />
<field name="name" />
<field name="int" />
</tree>
</field>
</form>
`,
});
await click(target.querySelector(".o_data_cell"));
assert.containsNone(target, ".o_selected_row");
assert.containsOnce(target, ".modal .o_form_view_dialog");
});
QUnit.test("click on section edit the section in place", async (assert) => {
await makeView({
type: "form",
resModel: "partner",
resId: 1,
serverData,
arch: `
<form>
<field name="lines" widget="slide_category_one2many">
<tree>
<field name="is_category" invisible="1" />
<field name="name" />
<field name="int" />
</tree>
</field>
</form>`,
});
await clickEdit(target);
await click(target.querySelector(".o_data_cell"));
assert.hasClass(target.querySelector(".o_is_section"), "o_selected_row");
assert.containsNone(target, ".modal .o_form_view_dialog");
});
QUnit.test("click on real line opens a dialog", async (assert) => {
await makeView({
type: "form",
resModel: "partner",
resId: 1,
serverData,
arch: `
<form>
<field name="lines" widget="slide_category_one2many">
<tree>
<field name="is_category" invisible="1" />
<field name="name" />
<field name="int" />
</tree>
</field>
</form>
`,
});
await clickEdit(target);
await click(target.querySelector(".o_data_row:nth-child(2) .o_data_cell"));
assert.containsNone(target, ".o_selected_row");
assert.containsOnce(target, ".modal .o_form_view_dialog");
});
QUnit.test("can create section inline", async (assert) => {
await makeView({
type: "form",
resModel: "partner",
resId: 1,
serverData,
arch: `
<form>
<field name="lines" widget="slide_category_one2many">
<tree>
<field name="is_category" invisible="1" />
<field name="name" />
<field name="int" />
<control>
<create string="add line" />
<create string="add section" context="{'default_is_category': true}" />
</control>
</tree>
</field>
</form>
`,
});
await clickEdit(target);
assert.containsNone(target, ".o_selected_row.o_is_section");
await click(target.querySelectorAll(".o_field_x2many_list_row_add a")[1]);
assert.containsOnce(target, ".o_selected_row.o_is_section");
assert.containsNone(target, ".modal .o_form_view_dialog");
});
QUnit.test("creates real record in form dialog", async (assert) => {
await makeView({
type: "form",
resModel: "partner",
resId: 1,
serverData,
arch: `
<form>
<field name="lines" widget="slide_category_one2many">
<tree>
<field name="is_category" invisible="1" />
<field name="name" />
<field name="int" />
<control>
<create string="add line" />
<create string="add section" context="{'default_is_category': true}" />
</control>
</tree>
</field>
</form>
`,
});
await clickEdit(target);
await click(target.querySelector(".o_field_x2many_list_row_add a"));
assert.containsNone(target, ".o_selected_row");
assert.containsOnce(target, ".modal .o_form_view_dialog");
});
});
@@ -6,7 +6,7 @@
<field name="name">slide.channel.view.form</field>
<field name="model">slide.channel</field>
<field name="arch" type="xml">
<form string="Channels" js_class="legacy_form">
<form string="Channels">
<header>
<button name="action_channel_invite" string="Invite" type="object" class="oe_highlight" attrs="{'invisible': [('enroll', '!=', 'invite')]}"/>
</header>