diff --git a/superset-frontend/src/dashboard/components/SliceHeaderControls/index.tsx b/superset-frontend/src/dashboard/components/SliceHeaderControls/index.tsx index 142e7f8e65b..6e73bec6f2b 100644 --- a/superset-frontend/src/dashboard/components/SliceHeaderControls/index.tsx +++ b/superset-frontend/src/dashboard/components/SliceHeaderControls/index.tsx @@ -457,6 +457,7 @@ const SliceHeaderControls = ( isRequest isVisible canDownload={!!props.supersetCanCSV} + columnDisplayNames={datasetWithVerboseMap?.verbose_map} /> } /> diff --git a/superset-frontend/src/explore/components/DataTableControl/index.tsx b/superset-frontend/src/explore/components/DataTableControl/index.tsx index 3cb98afe41a..7f010de6176 100644 --- a/superset-frontend/src/explore/components/DataTableControl/index.tsx +++ b/superset-frontend/src/explore/components/DataTableControl/index.tsx @@ -164,6 +164,7 @@ const DataTableTemporalHeaderCell = ({ onTimeColumnChange, datasourceId, isOriginalTimeColumn, + displayLabel, }: { columnName: string; onTimeColumnChange: ( @@ -172,6 +173,7 @@ const DataTableTemporalHeaderCell = ({ ) => void; datasourceId?: string; isOriginalTimeColumn: boolean; + displayLabel?: string; }) => { const theme = useTheme(); @@ -215,10 +217,10 @@ const DataTableTemporalHeaderCell = ({ onClick={(e: React.MouseEvent) => e.stopPropagation()} /> - {columnName} + {displayLabel ?? columnName} ) : ( - {columnName} + {displayLabel ?? columnName} ); }; @@ -258,6 +260,7 @@ export const useTableColumns = ( isVisible?: boolean, moreConfigs?: { [key: string]: Partial }, allowHTML?: boolean, + columnDisplayNames?: Record, ) => { const [originalFormattedTimeColumns, setOriginalFormattedTimeColumns] = useState(getTimeColumns(datasourceId)); @@ -302,6 +305,7 @@ export const useTableColumns = ( .map((key, index) => { const colType = coltypes?.[index]; const firstValue = data[0][key]; + const headerLabel = columnDisplayNames?.[key] ?? key; const originalFormattedTimeColumnIndex = colType === GenericDataType.Temporal ? originalFormattedTimeColumns.indexOf(key) @@ -320,9 +324,10 @@ export const useTableColumns = ( datasourceId={datasourceId} onTimeColumnChange={onTimeColumnChange} isOriginalTimeColumn={isOriginalTimeColumn} + displayLabel={headerLabel} /> ) : ( - key + headerLabel ), Cell: ({ value }) => { if (value === true) { @@ -357,6 +362,7 @@ export const useTableColumns = ( datasourceId, moreConfigs, originalFormattedTimeColumns, + columnDisplayNames, ], ); }; diff --git a/superset-frontend/src/explore/components/DataTableControl/useTableColumns.test.ts b/superset-frontend/src/explore/components/DataTableControl/useTableColumns.test.ts index b9defabc28f..acfb4987879 100644 --- a/superset-frontend/src/explore/components/DataTableControl/useTableColumns.test.ts +++ b/superset-frontend/src/explore/components/DataTableControl/useTableColumns.test.ts @@ -105,6 +105,7 @@ test('useTableColumns with no options', () => { "Cell": [Function], "Header": , @@ -168,6 +169,7 @@ test('useTableColumns with options', () => { "Cell": [Function], "Header": , @@ -194,3 +196,29 @@ test('useTableColumns with options', () => { }); }); }); + +test('useTableColumns applies columnDisplayNames to headers', () => { + const columnDisplayNames = { + col01: 'Column One', + [NUMTIME_KEY]: 'Verbose Numtime', + } as Record; + const hook = renderHook(() => + useTableColumns( + colnames, + coltypes, + data, + undefined, + true, + undefined, + undefined, + columnDisplayNames, + ), + ); + const cols = hook.result.current as JsonObject[]; + const col01 = cols.find(c => c.id === 'col01'); + const numtime = cols.find(c => c.id === NUMTIME_KEY); + expect(col01?.Header).toBe('Column One'); + // Temporal header is a component; ensure it received the displayLabel prop + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + expect(numtime?.Header.props.displayLabel).toBe('Verbose Numtime'); +}); diff --git a/superset-frontend/src/explore/components/DataTablesPane/components/ResultsPaneOnDashboard.tsx b/superset-frontend/src/explore/components/DataTablesPane/components/ResultsPaneOnDashboard.tsx index 0883505b193..196bed0b1d9 100644 --- a/superset-frontend/src/explore/components/DataTablesPane/components/ResultsPaneOnDashboard.tsx +++ b/superset-frontend/src/explore/components/DataTablesPane/components/ResultsPaneOnDashboard.tsx @@ -55,6 +55,7 @@ export const ResultsPaneOnDashboard = ({ isVisible, dataSize = 50, canDownload, + columnDisplayNames, }: ResultsPaneProps) => { const resultsPanes = useResultsPane({ errorMessage, @@ -66,6 +67,7 @@ export const ResultsPaneOnDashboard = ({ dataSize, isVisible, canDownload, + columnDisplayNames, }); if (resultsPanes.length === 1) { diff --git a/superset-frontend/src/explore/components/DataTablesPane/components/SingleQueryResultPane.tsx b/superset-frontend/src/explore/components/DataTablesPane/components/SingleQueryResultPane.tsx index 73fa093bec5..562f5cc9eb7 100644 --- a/superset-frontend/src/explore/components/DataTablesPane/components/SingleQueryResultPane.tsx +++ b/superset-frontend/src/explore/components/DataTablesPane/components/SingleQueryResultPane.tsx @@ -39,6 +39,7 @@ export const SingleQueryResultPane = ({ dataSize = 50, isVisible, canDownload, + columnDisplayNames, }: SingleQueryResultPaneProp) => { const [filterText, setFilterText] = useState(''); @@ -52,6 +53,7 @@ export const SingleQueryResultPane = ({ isVisible, {}, // moreConfig true, // allowHTML + columnDisplayNames, ); const filteredData = useFilteredTableData(filterText, data); diff --git a/superset-frontend/src/explore/components/DataTablesPane/components/useResultsPane.tsx b/superset-frontend/src/explore/components/DataTablesPane/components/useResultsPane.tsx index 143a07e0148..5372fd11852 100644 --- a/superset-frontend/src/explore/components/DataTablesPane/components/useResultsPane.tsx +++ b/superset-frontend/src/explore/components/DataTablesPane/components/useResultsPane.tsx @@ -55,6 +55,7 @@ export const useResultsPane = ({ isVisible, dataSize = 50, canDownload, + columnDisplayNames, }: ResultsPaneProps): ReactElement[] => { const metadata = getChartMetadataRegistry().get( queryFormData?.viz_type || queryFormData?.vizType, @@ -164,6 +165,7 @@ export const useResultsPane = ({ datasourceId={queryFormData.datasource} isVisible={isVisible} canDownload={canDownload} + columnDisplayNames={columnDisplayNames} /> )); diff --git a/superset-frontend/src/explore/components/DataTablesPane/types.ts b/superset-frontend/src/explore/components/DataTablesPane/types.ts index 7a4764974b5..d5b6891ec99 100644 --- a/superset-frontend/src/explore/components/DataTablesPane/types.ts +++ b/superset-frontend/src/explore/components/DataTablesPane/types.ts @@ -49,6 +49,8 @@ export interface ResultsPaneProps { // reload OriginalFormattedTimeColumns from localStorage when isVisible is true isVisible: boolean; canDownload: boolean; + // Optional map of column/metric name -> verbose label + columnDisplayNames?: Record; } export interface SamplesPaneProps { @@ -88,4 +90,6 @@ export interface SingleQueryResultPaneProp extends QueryResultInterface { // reload OriginalFormattedTimeColumns from localStorage when isVisible is true isVisible: boolean; canDownload: boolean; + // Optional map of column/metric name -> verbose label + columnDisplayNames?: Record; }