diff --git a/superset-frontend/plugins/plugin-chart-ag-grid-table/src/utils/useColDefs.ts b/superset-frontend/plugins/plugin-chart-ag-grid-table/src/utils/useColDefs.ts index e6b4cc48199..ea47c967af7 100644 --- a/superset-frontend/plugins/plugin-chart-ag-grid-table/src/utils/useColDefs.ts +++ b/superset-frontend/plugins/plugin-chart-ag-grid-table/src/utils/useColDefs.ts @@ -66,11 +66,22 @@ function getValueRange( alignPositiveNegative: boolean, data: InputData[], ) { - if (typeof data?.[0]?.[key] === 'number') { - const nums = data.map(row => row[key]) as number[]; - return ( - alignPositiveNegative ? [0, d3Max(nums.map(Math.abs))] : d3Extent(nums) - ) as ValueRange; + const nums = data + .map(row => { + const raw = row[key]; + return raw instanceof Number ? raw.valueOf() : raw; + }) + .filter( + (value): value is number => + typeof value === 'number' && Number.isFinite(value), + ) as number[]; + if (nums.length > 0) { + const maxAbs = d3Max(nums.map(Math.abs)); + if (alignPositiveNegative) { + return [0, maxAbs ?? 0] as ValueRange; + } + const extent = d3Extent(nums) as ValueRange | undefined; + return extent ?? [0, 0]; } return null; } diff --git a/superset-frontend/plugins/plugin-chart-table/src/TableChart.tsx b/superset-frontend/plugins/plugin-chart-table/src/TableChart.tsx index 7548e62dabd..ed3da07ab18 100644 --- a/superset-frontend/plugins/plugin-chart-table/src/TableChart.tsx +++ b/superset-frontend/plugins/plugin-chart-table/src/TableChart.tsx @@ -381,7 +381,7 @@ export default function TableChart( const nums = data ?.map(row => row?.[key]) .filter(value => typeof value === 'number') as number[]; - if (data && nums.length === data.length) { + if (nums.length > 0) { return ( alignPositiveNegative ? [0, d3Max(nums.map(Math.abs))] @@ -943,6 +943,7 @@ export default function TableChart( display: block; top: 0; ${valueRange && + typeof value === 'number' && ` width: ${`${cellWidth({ value: value as number, diff --git a/superset-frontend/plugins/plugin-chart-table/test/TableChart.test.tsx b/superset-frontend/plugins/plugin-chart-table/test/TableChart.test.tsx index f1bfd10ebb2..b1c56a71266 100644 --- a/superset-frontend/plugins/plugin-chart-table/test/TableChart.test.tsx +++ b/superset-frontend/plugins/plugin-chart-table/test/TableChart.test.tsx @@ -19,6 +19,7 @@ import '@testing-library/jest-dom'; import { render, screen } from '@superset-ui/core/spec'; import { cloneDeep } from 'lodash'; +import { GenericDataType } from '@superset-ui/core'; import TableChart, { sanitizeHeaderId } from '../src/TableChart'; import transformProps from '../src/transformProps'; import DateWithFormatter from '../src/utils/DateWithFormatter'; @@ -781,6 +782,77 @@ describe('plugin-chart-table', () => { ); cells = document.querySelectorAll('td'); }); + + test('render cell bars even when column contains NULL values', () => { + const props = transformProps({ + ...testData.raw, + queriesData: [ + { + ...testData.raw.queriesData[0], + colnames: ['category', 'value1', 'value2', 'value3', 'value4'], + coltypes: [ + GenericDataType.String, + GenericDataType.Numeric, + GenericDataType.Numeric, + GenericDataType.Numeric, + GenericDataType.Numeric, + ], + data: [ + { + category: 'Category A', + value1: 10, + value2: 20, + value3: 30, + value4: null, + }, + { + category: 'Category B', + value1: 15, + value2: 25, + value3: 35, + value4: 100, + }, + { + category: 'Category C', + value1: 18, + value2: 28, + value3: 38, + value4: null, + }, + ], + }, + ], + rawFormData: { + ...testData.raw.rawFormData, + show_cell_bars: true, + metrics: ['value1', 'value2', 'value3', 'value4'], + }, + }); + + const { container } = render( + ProviderWrapper({ + children: , + }), + ); + + // Get all cell bars - should exist for both columns with and without NULL values + const cellBars = container.querySelectorAll('div.cell-bar'); + + // Should have cell bars in all numeric columns, even those with NULL values + // value1, value2, value3 all have 3 values, value4 has 1 non-NULL value + // Total: 3 + 3 + 3 + 1 = 10 cell bars + expect(cellBars.length).toBeGreaterThan(0); + + // Specifically check that value4 column (which has NULLs) still renders bars for non-NULL cells + const rows = container.querySelectorAll('tbody tr'); + expect(rows.length).toBe(3); + + // Row 2 should have a cell bar in value4 column (value: 100) + const row2Cells = rows[1].querySelectorAll('td'); + const value4Cell = row2Cells[4]; // 5th column (0-indexed) + const value4Bar = value4Cell.querySelector('div.cell-bar'); + expect(value4Bar).toBeTruthy(); + }); }); }); });