[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:
co-authored by
Lucas Perais
parent
86e85ad5fd
commit
baf1d5b6d0
@@ -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);
|
||||
+218
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user