diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Bubble/transformProps.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Bubble/transformProps.ts index 2ffeaebf2ab7..3456034e77f6 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/Bubble/transformProps.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/src/Bubble/transformProps.ts @@ -145,7 +145,7 @@ export default function transformProps(chartProps: EchartsBubbleChartProps) { data.forEach(datum => { const dataName = bubbleSeries ? datum[bubbleSeries] : datum[entity]; - const name = dataName ? String(dataName) : NULL_STRING; + const name = dataName ? String(dataName) : NULL_STRING(); const bubbleSeriesValue = bubbleSeries ? datum[bubbleSeries] : null; series.push({ diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Sunburst/transformProps.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Sunburst/transformProps.ts index 8ffde2656ac9..c7352185ac32 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/Sunburst/transformProps.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/src/Sunburst/transformProps.ts @@ -130,7 +130,7 @@ export function formatTooltip({ const parentNode = treePathInfo.length > 2 ? treePathInfo[treePathInfo.length - 2] : undefined; - const title = (node.name || NULL_STRING) + const title = (node.name || NULL_STRING()) .toString() .replaceAll('<', '<') .replaceAll('>', '>'); @@ -144,8 +144,8 @@ export function formatTooltip({ rows.push([metricLabel, formattedValue]); if (!colorByCategory) { rows.push([ - secondaryMetricLabel || NULL_STRING, - formattedSecondaryValue || NULL_STRING, + secondaryMetricLabel || NULL_STRING(), + formattedSecondaryValue || NULL_STRING(), ]); rows.push([ `${metricLabel}/${secondaryMetricLabel}`, diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Treemap/EchartsTreemap.tsx b/superset-frontend/plugins/plugin-chart-echarts/src/Treemap/EchartsTreemap.tsx index 57fdef6aaae0..83d3fa91ae0d 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/Treemap/EchartsTreemap.tsx +++ b/superset-frontend/plugins/plugin-chart-echarts/src/Treemap/EchartsTreemap.tsx @@ -124,7 +124,7 @@ export default function EchartsTreemap({ const drillToDetailFilters: BinaryQueryObjectFilterClause[] = []; const drillByFilters: BinaryQueryObjectFilterClause[] = []; treePath.forEach((path, i) => { - const val = path === 'null' ? NULL_STRING : path; + const val = path === 'null' ? NULL_STRING() : path; drillToDetailFilters.push({ col: groupby[i], op: '==', diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Waterfall/transformProps.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Waterfall/transformProps.ts index 4a82498fd594..adb0c7fe16b6 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/Waterfall/transformProps.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/src/Waterfall/transformProps.ts @@ -70,7 +70,7 @@ function formatTooltip({ const isTotal = series?.seriesName === totalMark; if (!series) { - return NULL_STRING; + return NULL_STRING(); } const title = @@ -329,7 +329,7 @@ export default function transformProps( value = row[breakdownName]; } if (!value) { - value = NULL_STRING; + value = NULL_STRING(); } if (typeof value !== 'string' && typeof value !== 'number') { value = String(value); diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/constants.ts b/superset-frontend/plugins/plugin-chart-echarts/src/constants.ts index f496b7e2af81..193543d0aa83 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/constants.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/src/constants.ts @@ -27,8 +27,12 @@ import { TitleFormData, } from './types'; -// eslint-disable-next-line import/prefer-default-export -export const NULL_STRING = ''; +// ATTENTION: If you change any constants, make sure to also change constants.py + +export const EMPTY_STRING = () => t(''); +export const NULL_STRING = () => t(''); +export const TRUE_STRING = () => t('TRUE'); +export const FALSE_STRING = () => t('FALSE'); export const TIMESERIES_CONSTANTS = { gridOffsetRight: 20, diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/utils/series.ts b/superset-frontend/plugins/plugin-chart-echarts/src/utils/series.ts index a8c80303ced0..15a620a4e6eb 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/src/utils/series.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/src/utils/series.ts @@ -652,7 +652,7 @@ export function extractSeries( ...datum, [xAxis]: datum[xAxis] === null && xAxisType === AxisType.Category - ? NULL_STRING + ? NULL_STRING() : datum[xAxis], })); const sortedSeries = sortAndFilterSeries( @@ -730,7 +730,7 @@ export function formatSeriesName( } = {}, ): string { if (name === undefined || name === null) { - return NULL_STRING; + return NULL_STRING(); } if (typeof name === 'boolean' || typeof name === 'bigint') { return name.toString(); diff --git a/superset-frontend/plugins/plugin-chart-echarts/test/utils/series.test.ts b/superset-frontend/plugins/plugin-chart-echarts/test/utils/series.test.ts index 0817e2896b28..66981a844309 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/test/utils/series.test.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/test/utils/series.test.ts @@ -558,7 +558,7 @@ describe('extractSeries', () => { ]); }); - test('should convert NULL x-values to NULL_STRING for categorical axis', () => { + test('should convert NULL x-values to NULL_STRING() for categorical axis', () => { const data = [ { browser: 'Firefox', @@ -585,7 +585,7 @@ describe('extractSeries', () => { name: 'count', data: [ ['Firefox', 5], - [NULL_STRING, 10], + [NULL_STRING(), 10], ['Chrome', 8], ], }, @@ -1351,7 +1351,7 @@ describe('dedupSeries', () => { describe('sanitizeHtml', () => { test('should remove html tags from series name', () => { - expect(sanitizeHtml(NULL_STRING)).toEqual('<NULL>'); + expect(sanitizeHtml('')).toEqual('<NULL>'); }); }); diff --git a/superset-frontend/src/components/FilterableTable/useCellContentParser.test.ts b/superset-frontend/src/components/FilterableTable/useCellContentParser.test.ts index eeff225ef29f..d5ab069d0f11 100644 --- a/superset-frontend/src/components/FilterableTable/useCellContentParser.test.ts +++ b/superset-frontend/src/components/FilterableTable/useCellContentParser.test.ts @@ -18,14 +18,14 @@ */ import { renderHook } from '@testing-library/react'; -import { useCellContentParser } from './useCellContentParser'; +import { NULL_STRING, useCellContentParser } from './useCellContentParser'; -test('should return NULL for null cell data', () => { +test('should return NULL_STRING() for null cell data', () => { const { result } = renderHook(() => useCellContentParser({ columnKeys: [], expandedColumns: [] }), ); const parser = result.current; - expect(parser({ cellData: null, columnKey: '' })).toBe('NULL'); + expect(parser({ cellData: null, columnKey: '' })).toBe(NULL_STRING()); }); test('should return truncated string for complex columns', () => { diff --git a/superset-frontend/src/components/FilterableTable/useCellContentParser.ts b/superset-frontend/src/components/FilterableTable/useCellContentParser.ts index 3724691c7cde..a3579aac2a8e 100644 --- a/superset-frontend/src/components/FilterableTable/useCellContentParser.ts +++ b/superset-frontend/src/components/FilterableTable/useCellContentParser.ts @@ -17,10 +17,11 @@ * under the License. */ import { useCallback, useMemo } from 'react'; +import { t } from '@apache-superset/core/translation'; export type CellDataType = string | number | null; -export const NULL_STRING = 'NULL'; +export const NULL_STRING = () => t('NULL'); type Params = { columnKeys: string[]; @@ -50,7 +51,7 @@ export function useCellContentParser({ columnKeys, expandedColumns }: Params) { columnKey: string; }) => { if (cellData === null) { - return NULL_STRING; + return NULL_STRING(); } const content = String(cellData); const firstCharacter = content.substring(0, 1); diff --git a/superset-frontend/src/components/FilterableTable/utils.tsx b/superset-frontend/src/components/FilterableTable/utils.tsx index e388c373d6ef..61d4d35175b9 100644 --- a/superset-frontend/src/components/FilterableTable/utils.tsx +++ b/superset-frontend/src/components/FilterableTable/utils.tsx @@ -41,7 +41,7 @@ export const renderResultCell = ({ const cellNode = getCellContent?.({ cellData, columnKey }) ?? String(cellData); if (cellData === null) { - return {NULL_STRING}; + return {NULL_STRING()}; } const jsonObject = safeJsonObjectParse(cellData); if (jsonObject) { diff --git a/superset-frontend/src/explore/components/controls/CollectionControl/CollectionControl.test.tsx b/superset-frontend/src/explore/components/controls/CollectionControl/CollectionControl.test.tsx index 1bd518e95114..9ee34add1bab 100644 --- a/superset-frontend/src/explore/components/controls/CollectionControl/CollectionControl.test.tsx +++ b/superset-frontend/src/explore/components/controls/CollectionControl/CollectionControl.test.tsx @@ -20,6 +20,7 @@ import { render, screen, userEvent } from 'spec/helpers/testing-library'; import CollectionControl from '.'; jest.mock('@superset-ui/chart-controls', () => ({ + ...jest.requireActual('@superset-ui/chart-controls'), InfoTooltip: (props: any) => (