From f909d1a16acd15be467b293be682fa4e2808f03d Mon Sep 17 00:00:00 2001 From: Aleksandr Lesnenko <alxnddr@users.noreply.github.com> Date: Thu, 8 Dec 2022 23:15:45 -0300 Subject: [PATCH] allow to hide column and row totals on pivot tables (#27023) --- frontend/src/metabase/lib/data_grid.js | 19 ++++--- .../visualizations/PivotTable.jsx | 14 ++++++ .../test/metabase/lib/data_grid.unit.spec.js | 49 +++++++++++++++++-- 3 files changed, 73 insertions(+), 9 deletions(-) diff --git a/frontend/src/metabase/lib/data_grid.js b/frontend/src/metabase/lib/data_grid.js index 1cd177fe217..31f1bb2c282 100644 --- a/frontend/src/metabase/lib/data_grid.js +++ b/frontend/src/metabase/lib/data_grid.js @@ -130,7 +130,10 @@ export function multiLevelPivot(data, settings) { topIndexFormatters, topIndexColumns, ); - if (formattedColumnTreeWithoutValues.length > 1) { + if ( + formattedColumnTreeWithoutValues.length > 1 && + settings["pivot.show_row_totals"] + ) { // if there are multiple columns, we should add another for row totals formattedColumnTreeWithoutValues.push({ value: t`Row totals`, @@ -161,11 +164,15 @@ export function multiLevelPivot(data, settings) { const showSubtotalsByColumn = rowColumnIndexes.map( index => getIn(columnSettings, [index, COLUMN_SHOW_TOTALS]) !== false, ); - const formattedRowTree = addSubtotals( - formattedRowTreeWithoutSubtotals, - showSubtotalsByColumn, - ); - if (formattedRowTreeWithoutSubtotals.length > 1) { + + const formattedRowTree = settings["pivot.show_column_totals"] + ? addSubtotals(formattedRowTreeWithoutSubtotals, showSubtotalsByColumn) + : formattedRowTreeWithoutSubtotals; + + if ( + formattedRowTreeWithoutSubtotals.length > 1 && + settings["pivot.show_column_totals"] + ) { // if there are multiple columns, we should add another for row totals formattedRowTree.push({ value: t`Grand totals`, diff --git a/frontend/src/metabase/visualizations/visualizations/PivotTable.jsx b/frontend/src/metabase/visualizations/visualizations/PivotTable.jsx index f7554570ac8..0d1c85cb827 100644 --- a/frontend/src/metabase/visualizations/visualizations/PivotTable.jsx +++ b/frontend/src/metabase/visualizations/visualizations/PivotTable.jsx @@ -185,6 +185,20 @@ class PivotTable extends Component { return addMissingCardBreakouts(setting, card); }, }, + "pivot.show_row_totals": { + section: t`Columns`, + title: t`Show row totals`, + widget: "toggle", + default: true, + inline: true, + }, + "pivot.show_column_totals": { + section: t`Columns`, + title: t`Show column totals`, + widget: "toggle", + default: true, + inline: true, + }, [COLUMN_FORMATTING_SETTING]: { section: t`Conditional Formatting`, widget: ChartSettingsTableFormatting, diff --git a/frontend/test/metabase/lib/data_grid.unit.spec.js b/frontend/test/metabase/lib/data_grid.unit.spec.js index 6631c3ea1d4..8745dcbd4ce 100644 --- a/frontend/test/metabase/lib/data_grid.unit.spec.js +++ b/frontend/test/metabase/lib/data_grid.unit.spec.js @@ -169,7 +169,13 @@ describe("data_grid", () => { columns, rows, values, - { collapsedRows = [], columnSorts = [], columnShowTotals = [] } = {}, + { + collapsedRows = [], + columnSorts = [], + columnShowTotals = [], + showColumnTotals = true, + showRowTotals = true, + } = {}, ) => { const settings = { column: column => { @@ -185,6 +191,8 @@ describe("data_grid", () => { indexes => indexes.map(index => ["fake field ref", index]), ), [COLLAPSED_ROWS_SETTING]: { value: collapsedRows }, + "pivot.show_row_totals": showRowTotals, + "pivot.show_column_totals": showColumnTotals, }; data = { ...data, @@ -204,7 +212,7 @@ describe("data_grid", () => { ["b", "y", 5], ["b", "z", 6], ]); - it("should produce multi-level top header", () => { + it("should produce multi-level top header with row totals", () => { const { topHeaderItems, leftHeaderItems, rowCount, columnCount } = multiLevelPivotForIndexes(data, [0, 1], [], [2]); expect(getPathsAndValues(topHeaderItems)).toEqual([ @@ -222,7 +230,22 @@ describe("data_grid", () => { expect(rowCount).toEqual(1); expect(columnCount).toEqual(7); }); - it("should produce multi-level left header", () => { + + it("should produce multi-level top header without row totals", () => { + const { topHeaderItems } = multiLevelPivotForIndexes( + data, + [0, 1], + [], + [2], + { showColumnTotals: true, showRowTotals: false }, + ); + const pathsAndValues = getPathsAndValues(topHeaderItems); + expect(pathsAndValues[pathsAndValues.length - 1].value).not.toEqual( + "Row totals", + ); + }); + + it("should produce multi-level left header with totals", () => { const { topHeaderItems, leftHeaderItems, rowCount, columnCount } = multiLevelPivotForIndexes(data, [], [0, 1], [2]); expect(getPathsAndValues(leftHeaderItems)).toEqual([ @@ -242,6 +265,26 @@ describe("data_grid", () => { expect(rowCount).toEqual(9); expect(columnCount).toEqual(1); }); + + it("should produce multi-level left header without totals", () => { + const { topHeaderItems, leftHeaderItems, rowCount, columnCount } = + multiLevelPivotForIndexes(data, [], [0, 1], [2], { + showColumnTotals: false, + }); + expect(getPathsAndValues(leftHeaderItems)).toEqual([ + { value: "a", path: ["a"] }, + { value: "x", path: ["a", "x"] }, + { value: "y", path: ["a", "y"] }, + { value: "z", path: ["a", "z"] }, + { value: "b", path: ["b"] }, + { value: "x", path: ["b", "x"] }, + { value: "y", path: ["b", "y"] }, + { value: "z", path: ["b", "z"] }, + ]); + expect(getValues(topHeaderItems)).toEqual(["Metric"]); + expect(rowCount).toEqual(6); + expect(columnCount).toEqual(1); + }); it("should allow unspecified values", () => { const data = makePivotData([ ["a", "x", 1], -- GitLab