diff --git a/addons/web/static/src/views/graph/graph_search_model.js b/addons/web/static/src/views/graph/graph_search_model.js new file mode 100644 index 00000000000..ab76cf1831c --- /dev/null +++ b/addons/web/static/src/views/graph/graph_search_model.js @@ -0,0 +1,21 @@ +/** @odoo-module **/ + +import { SearchModel } from "@web/search/search_model"; + +export class GraphSearchModel extends SearchModel { + _getIrFilterDescription() { + this.preparingIrFilterDescription = true; + const result = super._getIrFilterDescription(...arguments); + this.preparingIrFilterDescription = false; + return result; + } + + _getSearchItemGroupBys(activeItem) { + const { searchItemId } = activeItem; + const { context, type } = this.searchItems[searchItemId]; + if (!this.preparingIrFilterDescription && type === "favorite" && context.graph_groupbys) { + return context.graph_groupbys; + } + return super._getSearchItemGroupBys(...arguments); + } +} diff --git a/addons/web/static/src/views/graph/graph_view.js b/addons/web/static/src/views/graph/graph_view.js index 088ae71a40f..9d93e085ab8 100644 --- a/addons/web/static/src/views/graph/graph_view.js +++ b/addons/web/static/src/views/graph/graph_view.js @@ -6,6 +6,7 @@ import { GraphArchParser } from "./graph_arch_parser"; import { GraphModel } from "./graph_model"; import { GraphController } from "./graph_controller"; import { GraphRenderer } from "./graph_renderer"; +import { GraphSearchModel } from "./graph_search_model"; const viewRegistry = registry.category("views"); @@ -18,6 +19,7 @@ export const graphView = { Renderer: GraphRenderer, Model: GraphModel, ArchParser: GraphArchParser, + SearchModel: GraphSearchModel, searchMenuTypes: ["filter", "groupBy", "comparison", "favorite"], buttonTemplate: "web.GraphView.Buttons", diff --git a/addons/web/static/src/views/pivot/pivot_search_model.js b/addons/web/static/src/views/pivot/pivot_search_model.js new file mode 100644 index 00000000000..ffe46a6bb6b --- /dev/null +++ b/addons/web/static/src/views/pivot/pivot_search_model.js @@ -0,0 +1,25 @@ +/** @odoo-module **/ + +import { SearchModel } from "@web/search/search_model"; + +export class PivotSearchModel extends SearchModel { + _getIrFilterDescription() { + this.preparingIrFilterDescription = true; + const result = super._getIrFilterDescription(...arguments); + this.preparingIrFilterDescription = false; + return result; + } + + _getSearchItemGroupBys(activeItem) { + const { searchItemId } = activeItem; + const { context, type } = this.searchItems[searchItemId]; + if ( + !this.preparingIrFilterDescription && + type === "favorite" && + context.pivot_row_groupby + ) { + return context.pivot_row_groupby; + } + return super._getSearchItemGroupBys(...arguments); + } +} diff --git a/addons/web/static/src/views/pivot/pivot_view.js b/addons/web/static/src/views/pivot/pivot_view.js index d8ea9e95521..0bf46ca0a18 100644 --- a/addons/web/static/src/views/pivot/pivot_view.js +++ b/addons/web/static/src/views/pivot/pivot_view.js @@ -6,6 +6,7 @@ import { PivotArchParser } from "@web/views/pivot/pivot_arch_parser"; import { PivotController } from "./pivot_controller"; import { PivotModel } from "@web/views/pivot/pivot_model"; import { PivotRenderer } from "@web/views/pivot/pivot_renderer"; +import { PivotSearchModel } from "./pivot_search_model"; const viewRegistry = registry.category("views"); @@ -18,6 +19,7 @@ export const pivotView = { Renderer: PivotRenderer, Model: PivotModel, ArchParser: PivotArchParser, + SearchModel: PivotSearchModel, searchMenuTypes: ["filter", "groupBy", "comparison", "favorite"], buttonTemplate: "web.PivotView.Buttons", diff --git a/addons/web/static/tests/views/graph_view_tests.js b/addons/web/static/tests/views/graph_view_tests.js index a472dd8cf64..0ea43c26c76 100644 --- a/addons/web/static/tests/views/graph_view_tests.js +++ b/addons/web/static/tests/views/graph_view_tests.js @@ -3676,4 +3676,43 @@ QUnit.module("Views", (hooks) => { }); checkLabels(assert, graph, ["January 2016", "March 2016", "May 2016", "April 2016"]); }); + + QUnit.test("graph_groupbys should be also used after first load", async function (assert) { + const graph = await makeView({ + serverData, + type: "graph", + resModel: "foo", + groupBy: ["date:quarter"], + arch: ``, + irFilters: [ + { + user_id: [2, "Mitchell Admin"], + name: "Favorite", + id: 1, + context: `{ + "group_by": [], + "graph_measure": "revenue", + "graph_mode": "bar", + "graph_groupbys": ["color_id"], + }`, + sort: "[]", + domain: "", + is_default: false, + model_id: "foo", + action_id: false, + }, + ], + }); + + checkModeIs(assert, graph, "bar"); + checkLabels(assert, graph, ["Q1 2016", "Q2 2016", "Undefined"]); + checkLegend(assert, graph, "Count"); + + await toggleFavoriteMenu(target); + await toggleMenuItem(target, "Favorite"); + + checkModeIs(assert, graph, "bar"); + checkLabels(assert, graph, ["Undefined", "red"]); + checkLegend(assert, graph, "Revenue"); + }); }); diff --git a/addons/web/static/tests/views/pivot_view_tests.js b/addons/web/static/tests/views/pivot_view_tests.js index 870ec97919b..e2dea0351e7 100644 --- a/addons/web/static/tests/views/pivot_view_tests.js +++ b/addons/web/static/tests/views/pivot_view_tests.js @@ -5383,4 +5383,164 @@ QUnit.module("Views", (hooks) => { assert.strictEqual(getCurrentValues(target), values.join()); } ); + + QUnit.test("pivot_row_groupby should be also used after first load", async function (assert) { + const ids = [1, 2]; + const expectedContexts = [ + { + group_by: ["bar"], + pivot_column_groupby: [], + pivot_measures: ["__count"], + pivot_row_groupby: ["product_id"], + }, + { + group_by: ["bar", "customer"], + pivot_column_groupby: [], + pivot_measures: ["__count"], + pivot_row_groupby: ["customer"], + }, + ]; + + await makeView({ + type: "pivot", + resModel: "partner", + serverData, + arch: ``, + searchViewArch: ` + + + + + `, + groupBy: ["bar"], + mockRPC(route, args) { + if (args.method === "create_or_replace") { + assert.deepEqual(args.args[0].context, expectedContexts.shift()); + return ids.shift(); + } + }, + }); + + assert.deepEqual( + [...target.querySelectorAll("th")].slice(3).map((el) => el.innerText), + ["Total", "No", "Yes"], + "The row headers should be as expected" + ); + + await click(target.querySelector("tbody th")); // click on row header "Total" + await click(target.querySelector("tbody th")); // click on row header "Total" + await click(target.querySelector("tbody .o_group_by_menu .o_menu_item")); // select "Product" + + assert.deepEqual( + [...target.querySelectorAll("th")].slice(3).map((el) => el.innerText), + ["Total", "xphone", "xpad"], + "The row headers should be as expected" + ); + + await toggleFavoriteMenu(target); + await toggleSaveFavorite(target); + await editFavoriteName(target, "Favorite"); + await saveFavorite(target); + + assert.deepEqual( + [...target.querySelectorAll("th")].slice(3).map((el) => el.innerText), + ["Total", "xphone", "xpad"], + "The row headers should be as expected" + ); + + await removeFacet(target); + + assert.deepEqual( + [...target.querySelectorAll("th")].slice(3).map((el) => el.innerText), + ["Total", "No", "Yes"], + "The row headers should be as expected" + ); + + await toggleFavoriteMenu(target); + await toggleMenuItem(target, "Favorite"); + + assert.deepEqual( + [...target.querySelectorAll("th")].slice(3).map((el) => el.innerText), + ["Total", "xphone", "xpad"], + "The row headers should be as expected" + ); + + await toggleGroupByMenu(target); + await toggleMenuItem(target, "Customer"); + + assert.deepEqual( + [...target.querySelectorAll("th")].slice(3).map((el) => el.innerText), + ["Total", "xphone", "First", "xpad", "First", "Second"], + "The row headers should be as expected" + ); + + await click(target.querySelector("tbody th")); // click on row header "Total" + await click(target.querySelector("tbody th")); // click on row header "Total" + await click(target.querySelectorAll("tbody .o_group_by_menu .o_menu_item")[1]); // select "Customer" + + assert.deepEqual( + [...target.querySelectorAll("th")].slice(3).map((el) => el.innerText), + ["Total", "First", "Second"], + "The row headers should be as expected" + ); + + await toggleFavoriteMenu(target); + await toggleSaveFavorite(target); + await editFavoriteName(target, "Favorite 2"); + await saveFavorite(target); + + assert.deepEqual( + [...target.querySelectorAll("th")].slice(3).map((el) => el.innerText), + ["Total", "First", "Second"], + "The row headers should be as expected" + ); + }); + + QUnit.test( + "pivot_row_groupby should be also used after first load (2)", + async function (assert) { + await makeView({ + serverData, + type: "pivot", + resModel: "partner", + groupBy: ["product_id"], + arch: ``, + irFilters: [ + { + user_id: [2, "Mitchell Admin"], + name: "Favorite", + id: 1, + context: ` + { + "group_by": [], + "pivot_row_groupby": ["customer"], + "pivot_col_groupby": [], + "pivot_measures": ["foo"], + } + `, + sort: "[]", + domain: "", + is_default: false, + model_id: "foo", + action_id: false, + }, + ], + }); + + assert.deepEqual( + [...target.querySelectorAll("th")].slice(3).map((el) => el.innerText), + ["Total", "xphone", "xpad"], + "The row headers should be as expected" + ); + + await toggleFavoriteMenu(target); + await toggleMenuItem(target, "Favorite"); + + assert.deepEqual( + [...target.querySelectorAll("th")].slice(3).map((el) => el.innerText), + ["Total", "First", "Second"], + "The row headers should be as expected" + ); + } + ); });