diff --git a/addons/web/static/src/views/list/list_arch_parser.js b/addons/web/static/src/views/list/list_arch_parser.js index 6884358f558..192532bf165 100644 --- a/addons/web/static/src/views/list/list_arch_parser.js +++ b/addons/web/static/src/views/list/list_arch_parser.js @@ -68,7 +68,6 @@ export class ListArchParser extends XMLParser { const groupListArchParser = new GroupListArchParser(); let buttonGroup; let handleField = null; - let defaultOrder = stringToOrderBy(xmlDoc.getAttribute("default_order") || null); const treeAttr = {}; let nextId = 0; const activeFields = {}; @@ -207,6 +206,9 @@ export class ListArchParser extends XMLParser { treeAttr.expand = archParseBoolean(xmlDoc.getAttribute("expand") || ""); treeAttr.decorations = getDecoration(xmlDoc); + treeAttr.defaultGroupBy = xmlDoc.getAttribute("default_group_by"); + treeAttr.defaultOrder = stringToOrderBy(xmlDoc.getAttribute("default_order") || null); + // custom open action when clicking on record row const action = xmlDoc.getAttribute("action"); const type = xmlDoc.getAttribute("type"); @@ -214,8 +216,8 @@ export class ListArchParser extends XMLParser { } }); - if (!defaultOrder.length && handleField) { - defaultOrder = stringToOrderBy(handleField); + if (!treeAttr.defaultOrder.length && handleField) { + treeAttr.defaultOrder = stringToOrderBy(handleField); } for (const [key, field] of Object.entries(fieldNodes)) { @@ -230,7 +232,6 @@ export class ListArchParser extends XMLParser { activeFields, columns, groupBy, - defaultOrder, __rawArch: arch, ...treeAttr, }; diff --git a/addons/web/static/src/views/list/list_controller.js b/addons/web/static/src/views/list/list_controller.js index 06bd880e714..15a90fb1194 100644 --- a/addons/web/static/src/views/list/list_controller.js +++ b/addons/web/static/src/views/list/list_controller.js @@ -70,6 +70,7 @@ export class ListController extends Component { groupByInfo: this.archInfo.groupBy.fields, limit: this.archInfo.limit || this.props.limit, defaultOrder: this.archInfo.defaultOrder, + defaultGroupBy: this.props.searchMenuTypes.includes("groupBy") && this.props.archInfo.defaultGroupBy, expand: this.archInfo.expand, groupsLimit: this.archInfo.groupsLimit, multiEdit: this.multiEdit, diff --git a/addons/web/static/tests/views/list_view_tests.js b/addons/web/static/tests/views/list_view_tests.js index 8d8c2ed3efb..fb01f8d6879 100644 --- a/addons/web/static/tests/views/list_view_tests.js +++ b/addons/web/static/tests/views/list_view_tests.js @@ -16634,4 +16634,43 @@ QUnit.module("Views", (hooks) => { await click(target, ".o_field_many2one_selection .o-autocomplete--input"); assert.verifySteps(["name_search"]); }); + + QUnit.test("list view with default_group_by", async (assert) => { + serverData.models.foo.fields.m2m.store = true; + + let readGroupCount = 0; + await makeView({ + type: "list", + resModel: "foo", + serverData, + arch: ` + + + + `, + async mockRPC(route, { kwargs }) { + if (route === "/web/dataset/call_kw/partner/web_read_group") { + readGroupCount++; + switch (readGroupCount) { + case 1: + return assert.deepEqual(kwargs.groupby, ["bar"]); + case 2: + return assert.deepEqual(kwargs.groupby, ["m2m"]); + case 3: + return assert.deepEqual(kwargs.groupby, ["bar"]); + } + } + }, + }); + + assert.hasClass(target.querySelector(".o_list_renderer table"), "o_list_table_grouped"); + assert.containsN(target, ".o_group_header", 2); + + await groupByMenu(target, "m2m"); + assert.containsN(target, ".o_group_header", 4); + + await toggleMenuItem(target, "M2M field"); + assert.containsN(target, ".o_group_header", 2); + }); + }); diff --git a/odoo/addons/base/rng/tree_view.rng b/odoo/addons/base/rng/tree_view.rng index ed194bbda6e..a02c3223503 100644 --- a/odoo/addons/base/rng/tree_view.rng +++ b/odoo/addons/base/rng/tree_view.rng @@ -36,6 +36,7 @@ +