[FIX] web: touch a record in a x2m

Before this commit, if a touchstart event is performed on a row in an
x2many, then a crash is displayed.

We also use this commit to rename the hasSelector props to allowSelector.
allowSelector is true if checkboxes can be present.

How to reproduce:
- go to a form view in mobile mode with an x2many field
- touch a row in the x2many (trigger an event touchstart)

Before this commit:
    An error is displayed

After this commit:
    Nothing happens.

closes odoo/odoo#98893

Related: odoo/enterprise#30773
Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
This commit is contained in:
FrancoisGe
2022-08-30 03:44:56 +02:00
parent 75cb824902
commit e50bee88c4
8 changed files with 41 additions and 15 deletions
+1 -1
View File
@@ -50,7 +50,7 @@ export class BoardAction extends Component {
this.viewProps.domain = action.domain;
}
if (viewMode === "list") {
this.viewProps.hasSelectors = false;
this.viewProps.allowSelectors = false;
}
});
}
@@ -112,7 +112,6 @@ KanbanController.props = {
defaultGroupBy: { validate: (dgb) => !dgb || typeof dgb === "string", optional: true },
editable: { type: Boolean, optional: true },
forceGlobalClick: { type: Boolean, optional: true },
hasSelectors: { type: Boolean, optional: true },
onSelectionChanged: { type: Function, optional: true },
showButtons: { type: Boolean, optional: true },
Model: Function,
@@ -439,8 +439,8 @@ ListController.template = `web.ListView`;
ListController.components = { ActionMenus, ListViewHeaderButton, Layout, ViewButton };
ListController.props = {
...standardViewProps,
allowSelectors: { type: Boolean, optional: true },
editable: { type: Boolean, optional: true },
hasSelectors: { type: Boolean, optional: true },
onSelectionChanged: { type: Function, optional: true },
showButtons: { type: Boolean, optional: true },
Model: Function,
@@ -449,9 +449,9 @@ ListController.props = {
archInfo: Object,
};
ListController.defaultProps = {
allowSelectors: true,
createRecord: () => {},
editable: true,
hasSelectors: true,
selectRecord: () => {},
showButtons: true,
};
@@ -25,7 +25,7 @@
resModel="model.root.resModel"/>
</t>
</t>
<t t-component="props.Renderer" list="model.root" activeActions="activeActions" archInfo="archInfo" hasSelectors="props.hasSelectors" editable="editable" openRecord.bind="openRecord" noContentHelp="props.info.noContentHelp" onAdd.bind="createRecord"/>
<t t-component="props.Renderer" list="model.root" activeActions="activeActions" archInfo="archInfo" allowSelectors="props.allowSelectors" editable="editable" openRecord.bind="openRecord" noContentHelp="props.info.noContentHelp" onAdd.bind="createRecord"/>
</Layout>
</div>
</t>
@@ -189,7 +189,7 @@ export class ListRenderer extends Component {
}
get hasSelectors() {
return this.props.hasSelectors && !this.env.isSmall;
return this.props.allowSelectors && !this.env.isSmall;
}
add(params) {
@@ -1680,6 +1680,9 @@ export class ListRenderer extends Component {
}
onRowTouchStart(record, ev) {
if (!this.props.allowSelectors) {
return;
}
if (this.props.list.selection.length) {
// in selection mode, only selection is allowed.
ev.preventDefault();
@@ -1719,7 +1722,7 @@ ListRenderer.props = [
"openRecord",
"onAdd?",
"cycleOnTab?",
"hasSelectors?",
"allowSelectors?",
"editable?",
"noContentHelp?",
"nestedKeyOptionalFieldsData?",
@@ -25,16 +25,20 @@ export class SelectCreateDialog extends Component {
}
get viewProps() {
return {
const type = this.env.isSmall ? "kanban" : "list";
const props = {
...this.baseViewProps,
context: this.props.context,
domain: this.props.domain,
dynamicFilters: this.props.dynamicFilters,
hasSelectors: this.props.multiSelect,
resModel: this.props.resModel,
searchViewId: this.props.searchViewId,
type: this.env.isSmall ? "kanban" : "list",
type,
};
if (type === "list") {
props.allowSelectors = this.props.multiSelect;
}
return props;
}
async select(resIds) {
@@ -12542,4 +12542,24 @@ QUnit.module("Fields", (hooks) => {
await clickSave(target);
assert.verifySteps(["write partner", "read partner"]);
});
QUnit.test("can't select a record in a one2many", async function (assert) {
await makeView({
type: "form",
resModel: "partner",
serverData,
arch: `
<form>
<field name="turtles">
<tree>
<field name="display_name"/>
</tree>
</field>
</form>`,
resId: 1,
});
await triggerEvents(target, ".o_data_row", ["touchstart", "touchend"]);
assert.containsNone(target, ".o_data_row_selected");
});
});
@@ -1276,7 +1276,7 @@ QUnit.module("Views", (hooks) => {
serverData,
arch: '<tree><field name="foo"/></tree>',
groupBy: ["bar"],
hasSelectors: false,
allowSelectors: false,
});
assert.containsOnce(target.querySelector(".o_group_header"), "th");
@@ -1303,7 +1303,7 @@ QUnit.module("Views", (hooks) => {
serverData,
arch: '<tree ><field name="foo"/><field name="bar"/></tree>',
groupBy: ["bar"],
hasSelectors: false,
allowSelectors: false,
});
assert.containsN(target.querySelector(".o_group_header"), "th", 2);
@@ -1317,7 +1317,7 @@ QUnit.module("Views", (hooks) => {
serverData,
arch: '<tree ><field name="foo"/><field name="bar"/><field name="text"/></tree>',
groupBy: ["bar"],
hasSelectors: false,
allowSelectors: false,
});
assert.containsN(target.querySelector(".o_group_header"), "th", 2);
@@ -1331,7 +1331,7 @@ QUnit.module("Views", (hooks) => {
serverData,
arch: '<tree ><field name="foo"/><field name="bar"/></tree>',
groupBy: ["bar"],
hasSelectors: true,
allowSelectors: true,
});
assert.containsN(target.querySelector(".o_group_header"), "th", 2);
@@ -1345,7 +1345,7 @@ QUnit.module("Views", (hooks) => {
serverData,
arch: '<tree><field name="foo"/><field name="bar"/><field name="text"/></tree>',
groupBy: ["bar"],
hasSelectors: true,
allowSelectors: true,
});
assert.containsN(target.querySelector(".o_group_header"), "th", 2);