You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by kg...@apache.org on 2023/07/07 17:28:20 UTC
[superset] branch master updated: feat: Implement support for currencies in more charts (#24594)
This is an automated email from the ASF dual-hosted git repository.
kgabryje pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git
The following commit(s) were added to refs/heads/master by this push:
new d74d7eca23 feat: Implement support for currencies in more charts (#24594)
d74d7eca23 is described below
commit d74d7eca23a3c94bc48af082c115d34c103e815d
Author: Kamil Gabryjelski <ka...@gmail.com>
AuthorDate: Fri Jul 7 19:28:13 2023 +0200
feat: Implement support for currencies in more charts (#24594)
---
.../superset-ui-core/src/currency-format/index.ts | 1 +
.../superset-ui-core/src/currency-format/utils.ts} | 22 ++-
.../test/currency-format/utils.test.ts | 151 +++++++++++++++++++++
.../legacy-plugin-chart-heatmap/src/Heatmap.js | 6 +-
.../src/transformProps.js | 14 +-
.../legacy-plugin-chart-world-map/src/WorldMap.js | 5 +-
.../src/transformProps.js | 12 ++
.../src/BigNumber/BigNumberTotal/transformProps.ts | 2 +-
.../BigNumberWithTrendline/transformProps.ts | 2 +-
.../src/Funnel/transformProps.ts | 2 +-
.../src/Gauge/transformProps.ts | 2 +-
.../src/MixedTimeseries/transformProps.ts | 124 +++++++++++++++--
.../plugin-chart-echarts/src/Pie/transformProps.ts | 2 +-
.../src/Sunburst/transformProps.ts | 41 ++++--
.../src/Timeseries/transformProps.ts | 38 +-----
.../src/Treemap/transformProps.ts | 2 +-
.../src/utils/getYAxisFormatter.ts | 54 ++++++++
.../plugin-chart-echarts/src/utils/series.ts | 2 +-
18 files changed, 404 insertions(+), 78 deletions(-)
diff --git a/superset-frontend/packages/superset-ui-core/src/currency-format/index.ts b/superset-frontend/packages/superset-ui-core/src/currency-format/index.ts
index c7fa5a0388..45fa851e88 100644
--- a/superset-frontend/packages/superset-ui-core/src/currency-format/index.ts
+++ b/superset-frontend/packages/superset-ui-core/src/currency-format/index.ts
@@ -19,3 +19,4 @@
export { default as CurrencyFormatter } from './CurrencyFormatter';
export * from './CurrencyFormatter';
+export * from './utils';
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/utils/valueFormatter.ts b/superset-frontend/packages/superset-ui-core/src/currency-format/utils.ts
similarity index 65%
rename from superset-frontend/plugins/plugin-chart-echarts/src/utils/valueFormatter.ts
rename to superset-frontend/packages/superset-ui-core/src/currency-format/utils.ts
index 5d995c9f00..014388b86d 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/utils/valueFormatter.ts
+++ b/superset-frontend/packages/superset-ui-core/src/currency-format/utils.ts
@@ -1,3 +1,21 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
import {
Currency,
CurrencyFormatter,
@@ -16,10 +34,8 @@ export const buildCustomFormatters = (
) => {
const metricsArray = ensureIsArray(metrics);
return metricsArray.reduce((acc, metric) => {
- const actualD3Format = isSavedMetric(metric)
- ? columnFormats[metric] ?? d3Format
- : d3Format;
if (isSavedMetric(metric)) {
+ const actualD3Format = d3Format ?? columnFormats[metric];
return currencyFormats[metric]
? {
...acc,
diff --git a/superset-frontend/packages/superset-ui-core/test/currency-format/utils.test.ts b/superset-frontend/packages/superset-ui-core/test/currency-format/utils.test.ts
new file mode 100644
index 0000000000..9e35ce8d99
--- /dev/null
+++ b/superset-frontend/packages/superset-ui-core/test/currency-format/utils.test.ts
@@ -0,0 +1,151 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import {
+ buildCustomFormatters,
+ CurrencyFormatter,
+ getCustomFormatter,
+ getNumberFormatter,
+ getValueFormatter,
+ NumberFormatter,
+ ValueFormatter,
+} from '@superset-ui/core';
+
+it('buildCustomFormatters without saved metrics returns empty object', () => {
+ expect(
+ buildCustomFormatters(
+ [
+ {
+ expressionType: 'SIMPLE',
+ aggregate: 'COUNT',
+ column: { column_name: 'test' },
+ },
+ ],
+ {
+ sum__num: { symbol: 'USD', symbolPosition: 'prefix' },
+ },
+ {},
+ ',.1f',
+ ),
+ ).toEqual({});
+
+ expect(
+ buildCustomFormatters(
+ undefined,
+ {
+ sum__num: { symbol: 'USD', symbolPosition: 'prefix' },
+ },
+ {},
+ ',.1f',
+ ),
+ ).toEqual({});
+});
+
+it('buildCustomFormatters with saved metrics returns custom formatters object', () => {
+ const customFormatters: Record<string, ValueFormatter> =
+ buildCustomFormatters(
+ [
+ {
+ expressionType: 'SIMPLE',
+ aggregate: 'COUNT',
+ column: { column_name: 'test' },
+ },
+ 'sum__num',
+ 'count',
+ ],
+ {
+ sum__num: { symbol: 'USD', symbolPosition: 'prefix' },
+ },
+ { sum__num: ',.2' },
+ ',.1f',
+ );
+
+ expect(customFormatters).toEqual({
+ sum__num: expect.any(Function),
+ count: expect.any(Function),
+ });
+
+ expect(customFormatters.sum__num).toBeInstanceOf(CurrencyFormatter);
+ expect(customFormatters.count).toBeInstanceOf(NumberFormatter);
+ expect((customFormatters.sum__num as CurrencyFormatter).d3Format).toEqual(
+ ',.1f',
+ );
+});
+
+it('buildCustomFormatters uses dataset d3 format if not provided in control panel', () => {
+ const customFormatters: Record<string, ValueFormatter> =
+ buildCustomFormatters(
+ [
+ {
+ expressionType: 'SIMPLE',
+ aggregate: 'COUNT',
+ column: { column_name: 'test' },
+ },
+ 'sum__num',
+ 'count',
+ ],
+ {
+ sum__num: { symbol: 'USD', symbolPosition: 'prefix' },
+ },
+ { sum__num: ',.2' },
+ undefined,
+ );
+
+ expect((customFormatters.sum__num as CurrencyFormatter).d3Format).toEqual(
+ ',.2',
+ );
+});
+
+it('getCustomFormatter', () => {
+ const customFormatters = {
+ sum__num: new CurrencyFormatter({
+ currency: { symbol: 'USD', symbolPosition: 'prefix' },
+ }),
+ count: getNumberFormatter(),
+ };
+ expect(getCustomFormatter(customFormatters, 'count')).toEqual(
+ customFormatters.count,
+ );
+ expect(
+ getCustomFormatter(customFormatters, ['count', 'sum__num'], 'count'),
+ ).toEqual(customFormatters.count);
+ expect(getCustomFormatter(customFormatters, ['count', 'sum__num'])).toEqual(
+ undefined,
+ );
+});
+
+it('getValueFormatter', () => {
+ expect(
+ getValueFormatter(['count', 'sum__num'], {}, {}, ',.1f'),
+ ).toBeInstanceOf(NumberFormatter);
+
+ expect(
+ getValueFormatter(['count', 'sum__num'], {}, {}, ',.1f', 'count'),
+ ).toBeInstanceOf(NumberFormatter);
+
+ expect(
+ getValueFormatter(
+ ['count', 'sum__num'],
+ { count: { symbol: 'USD', symbolPosition: 'prefix' } },
+ {},
+ ',.1f',
+ 'count',
+ ),
+ ).toBeInstanceOf(CurrencyFormatter);
+});
diff --git a/superset-frontend/plugins/legacy-plugin-chart-heatmap/src/Heatmap.js b/superset-frontend/plugins/legacy-plugin-chart-heatmap/src/Heatmap.js
index b377c71c57..7d62622313 100644
--- a/superset-frontend/plugins/legacy-plugin-chart-heatmap/src/Heatmap.js
+++ b/superset-frontend/plugins/legacy-plugin-chart-heatmap/src/Heatmap.js
@@ -51,7 +51,7 @@ const propTypes = {
leftMargin: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
metric: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
normalized: PropTypes.bool,
- numberFormat: PropTypes.string,
+ valueFormatter: PropTypes.object,
showLegend: PropTypes.bool,
showPercentage: PropTypes.bool,
showValues: PropTypes.bool,
@@ -90,7 +90,7 @@ function Heatmap(element, props) {
leftMargin,
metric,
normalized,
- numberFormat,
+ valueFormatter,
showLegend,
showPercentage,
showValues,
@@ -115,8 +115,6 @@ function Heatmap(element, props) {
const pixelsPerCharX = 4.5; // approx, depends on font size
let pixelsPerCharY = 6; // approx, depends on font size
- const valueFormatter = getNumberFormatter(numberFormat);
-
// Dynamically adjusts based on max x / y category lengths
function adjustMargins() {
let longestX = 1;
diff --git a/superset-frontend/plugins/legacy-plugin-chart-heatmap/src/transformProps.js b/superset-frontend/plugins/legacy-plugin-chart-heatmap/src/transformProps.js
index 9381250ac1..a6adf5f8b8 100644
--- a/superset-frontend/plugins/legacy-plugin-chart-heatmap/src/transformProps.js
+++ b/superset-frontend/plugins/legacy-plugin-chart-heatmap/src/transformProps.js
@@ -1,3 +1,5 @@
+import { getValueFormatter } from '@superset-ui/core';
+
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
@@ -17,7 +19,7 @@
* under the License.
*/
export default function transformProps(chartProps) {
- const { width, height, formData, queriesData } = chartProps;
+ const { width, height, formData, queriesData, datasource } = chartProps;
const {
bottomMargin,
canvasImageRendering,
@@ -37,7 +39,13 @@ export default function transformProps(chartProps) {
yAxisBounds,
yAxisFormat,
} = formData;
-
+ const { columnFormats = {}, currencyFormats = {} } = datasource;
+ const valueFormatter = getValueFormatter(
+ metric,
+ currencyFormats,
+ columnFormats,
+ yAxisFormat,
+ );
return {
width,
height,
@@ -50,7 +58,6 @@ export default function transformProps(chartProps) {
leftMargin,
metric,
normalized,
- numberFormat: yAxisFormat,
showLegend,
showPercentage: showPerc,
showValues,
@@ -59,5 +66,6 @@ export default function transformProps(chartProps) {
xScaleInterval: parseInt(xscaleInterval, 10),
yScaleInterval: parseInt(yscaleInterval, 10),
yAxisBounds,
+ valueFormatter,
};
}
diff --git a/superset-frontend/plugins/legacy-plugin-chart-world-map/src/WorldMap.js b/superset-frontend/plugins/legacy-plugin-chart-world-map/src/WorldMap.js
index c8aa2cdc2a..540097be24 100644
--- a/superset-frontend/plugins/legacy-plugin-chart-world-map/src/WorldMap.js
+++ b/superset-frontend/plugins/legacy-plugin-chart-world-map/src/WorldMap.js
@@ -21,7 +21,6 @@ import d3 from 'd3';
import PropTypes from 'prop-types';
import { extent as d3Extent } from 'd3-array';
import {
- getNumberFormatter,
getSequentialSchemeRegistry,
CategoricalColorNamespace,
} from '@superset-ui/core';
@@ -47,10 +46,9 @@ const propTypes = {
setDataMask: PropTypes.func,
onContextMenu: PropTypes.func,
emitCrossFilters: PropTypes.bool,
+ formatter: PropTypes.object,
};
-const formatter = getNumberFormatter();
-
function WorldMap(element, props) {
const {
countryFieldtype,
@@ -71,6 +69,7 @@ function WorldMap(element, props) {
inContextMenu,
filterState,
emitCrossFilters,
+ formatter,
} = props;
const div = d3.select(element);
div.classed('superset-legacy-chart-world-map', true);
diff --git a/superset-frontend/plugins/legacy-plugin-chart-world-map/src/transformProps.js b/superset-frontend/plugins/legacy-plugin-chart-world-map/src/transformProps.js
index 5f8c718449..182d1b0b11 100644
--- a/superset-frontend/plugins/legacy-plugin-chart-world-map/src/transformProps.js
+++ b/superset-frontend/plugins/legacy-plugin-chart-world-map/src/transformProps.js
@@ -17,6 +17,7 @@
* under the License.
*/
import { rgb } from 'd3-color';
+import { getValueFormatter } from '@superset-ui/core';
export default function transformProps(chartProps) {
const {
@@ -28,6 +29,7 @@ export default function transformProps(chartProps) {
inContextMenu,
filterState,
emitCrossFilters,
+ datasource,
} = chartProps;
const { onContextMenu, setDataMask } = hooks;
const {
@@ -40,8 +42,17 @@ export default function transformProps(chartProps) {
colorBy,
colorScheme,
sliceId,
+ metric,
} = formData;
const { r, g, b } = colorPicker;
+ const { currencyFormats = {}, columnFormats = {} } = datasource;
+
+ const formatter = getValueFormatter(
+ metric,
+ currencyFormats,
+ columnFormats,
+ undefined,
+ );
return {
countryFieldtype,
@@ -61,5 +72,6 @@ export default function transformProps(chartProps) {
inContextMenu,
filterState,
emitCrossFilters,
+ formatter,
};
}
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberTotal/transformProps.ts b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberTotal/transformProps.ts
index 5486030f46..bdef7852d1 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberTotal/transformProps.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberTotal/transformProps.ts
@@ -26,11 +26,11 @@ import {
getMetricLabel,
extractTimegrain,
QueryFormData,
+ getValueFormatter,
} from '@superset-ui/core';
import { BigNumberTotalChartProps, BigNumberVizProps } from '../types';
import { getDateFormatter, parseMetricValue } from '../utils';
import { Refs } from '../../types';
-import { getValueFormatter } from '../../utils/valueFormatter';
export default function transformProps(
chartProps: BigNumberTotalChartProps,
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberWithTrendline/transformProps.ts b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberWithTrendline/transformProps.ts
index c05a427f31..4daa8f4401 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberWithTrendline/transformProps.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberWithTrendline/transformProps.ts
@@ -28,6 +28,7 @@ import {
getXAxisLabel,
Metric,
ValueFormatter,
+ getValueFormatter,
} from '@superset-ui/core';
import { EChartsCoreOption, graphic } from 'echarts';
import {
@@ -39,7 +40,6 @@ import {
import { getDateFormatter, parseMetricValue } from '../utils';
import { getDefaultTooltip } from '../../utils/tooltip';
import { Refs } from '../../types';
-import { getValueFormatter } from '../../utils/valueFormatter';
const defaultNumberFormatter = getNumberFormatter();
export function renderTooltipFactory(
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Funnel/transformProps.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Funnel/transformProps.ts
index 796aa36e40..41319079dc 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Funnel/transformProps.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Funnel/transformProps.ts
@@ -24,6 +24,7 @@ import {
NumberFormats,
ValueFormatter,
getColumnLabel,
+ getValueFormatter,
} from '@superset-ui/core';
import { CallbackDataParams } from 'echarts/types/src/util/types';
import { EChartsCoreOption, FunnelSeriesOption } from 'echarts';
@@ -45,7 +46,6 @@ import { defaultGrid } from '../defaults';
import { OpacityEnum, DEFAULT_LEGEND_FORM_DATA } from '../constants';
import { getDefaultTooltip } from '../utils/tooltip';
import { Refs } from '../types';
-import { getValueFormatter } from '../utils/valueFormatter';
const percentFormatter = getNumberFormatter(NumberFormats.PERCENT_2_POINT);
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Gauge/transformProps.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Gauge/transformProps.ts
index ffbb746bf0..0fd41e88a0 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Gauge/transformProps.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Gauge/transformProps.ts
@@ -23,6 +23,7 @@ import {
DataRecord,
getMetricLabel,
getColumnLabel,
+ getValueFormatter,
} from '@superset-ui/core';
import { EChartsCoreOption, GaugeSeriesOption } from 'echarts';
import { GaugeDataItemOption } from 'echarts/types/src/chart/gauge/GaugeSeries';
@@ -46,7 +47,6 @@ import { OpacityEnum } from '../constants';
import { getDefaultTooltip } from '../utils/tooltip';
import { Refs } from '../types';
import { getColtypesMapping } from '../utils/series';
-import { getValueFormatter } from '../utils/valueFormatter';
const setIntervalBoundsAndColors = (
intervals: string,
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/transformProps.ts b/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/transformProps.ts
index 77e8550d09..a3028bfef8 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/transformProps.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/MixedTimeseries/transformProps.ts
@@ -34,6 +34,11 @@ import {
isPhysicalColumn,
isDefined,
ensureIsArray,
+ buildCustomFormatters,
+ ValueFormatter,
+ NumberFormatter,
+ QueryFormMetric,
+ getCustomFormatter,
} from '@superset-ui/core';
import { getOriginalSeries } from '@superset-ui/chart-controls';
import { EChartsCoreOption, SeriesOption } from 'echarts';
@@ -83,6 +88,23 @@ import {
} from '../Timeseries/transformers';
import { TIMESERIES_CONSTANTS, TIMEGRAIN_TO_TIMESTAMP } from '../constants';
import { getDefaultTooltip } from '../utils/tooltip';
+import { getYAxisFormatter } from '../utils/getYAxisFormatter';
+
+const getFormatter = (
+ customFormatters: Record<string, ValueFormatter>,
+ defaultFormatter: NumberFormatter,
+ metrics: QueryFormMetric[],
+ formatterKey: string,
+ forcePercentFormat: boolean,
+) => {
+ if (forcePercentFormat) {
+ return getNumberFormatter(',.0%');
+ }
+ return (
+ getCustomFormatter(customFormatters, metrics, formatterKey) ??
+ defaultFormatter
+ );
+};
export default function transformProps(
chartProps: EchartsMixedTimeseriesProps,
@@ -99,7 +121,11 @@ export default function transformProps(
inContextMenu,
emitCrossFilters,
} = chartProps;
- const { verboseMap = {} } = datasource;
+ const {
+ verboseMap = {},
+ currencyFormats = {},
+ columnFormats = {},
+ } = datasource;
const { label_map: labelMap } =
queriesData[0] as TimeseriesChartDataResponseResult;
const { label_map: labelMapB } =
@@ -160,6 +186,8 @@ export default function transformProps(
sliceId,
timeGrainSqla,
percentageThreshold,
+ metrics = [],
+ metricsB = [],
}: EchartsMixedTimeseriesFormData = { ...DEFAULT_FORM_DATA, ...formData };
const refs: Refs = {};
@@ -194,6 +222,18 @@ export default function transformProps(
const formatterSecondary = getNumberFormatter(
contributionMode ? ',.0%' : yAxisFormatSecondary,
);
+ const customFormatters = buildCustomFormatters(
+ [...metrics, ...metricsB],
+ currencyFormats,
+ columnFormats,
+ yAxisFormat,
+ );
+ const customFormattersSecondary = buildCustomFormatters(
+ [...metrics, ...metricsB],
+ currencyFormats,
+ columnFormats,
+ yAxisFormatSecondary,
+ );
const primarySeries = new Set<string>();
const secondarySeries = new Set<string>();
@@ -292,12 +332,6 @@ export default function transformProps(
parseYAxisBound,
);
- const maxLabelFormatter = getOverMaxHiddenFormatter({ max, formatter });
- const maxLabelFormatterSecondary = getOverMaxHiddenFormatter({
- max: maxSecondary,
- formatter: formatterSecondary,
- });
-
const array = ensureIsArray(chartProps.rawFormData?.time_compare);
const inverted = invert(verboseMap);
@@ -306,6 +340,14 @@ export default function transformProps(
const seriesName = inverted[entryName] || entryName;
const colorScaleKey = getOriginalSeries(seriesName, array);
+ const seriesFormatter = getFormatter(
+ customFormatters,
+ formatter,
+ metrics,
+ labelMap[seriesName]?.[0],
+ !!contributionMode,
+ );
+
const transformedSeries = transformSeries(
entry,
colorScale,
@@ -325,8 +367,11 @@ export default function transformProps(
queryIndex: 0,
formatter:
seriesType === EchartsTimeseriesSeriesType.Bar
- ? maxLabelFormatter
- : formatter,
+ ? getOverMaxHiddenFormatter({
+ max,
+ formatter: seriesFormatter,
+ })
+ : seriesFormatter,
showValueIndexes: showValueIndexesA,
totalStackedValues,
thresholdValues,
@@ -340,6 +385,14 @@ export default function transformProps(
const seriesName = `${inverted[entryName] || entryName} (1)`;
const colorScaleKey = getOriginalSeries(seriesName, array);
+ const seriesFormatter = getFormatter(
+ customFormattersSecondary,
+ formatterSecondary,
+ metricsB,
+ labelMapB[seriesName]?.[0],
+ !!contributionMode,
+ );
+
const transformedSeries = transformSeries(
entry,
colorScale,
@@ -361,8 +414,11 @@ export default function transformProps(
queryIndex: 1,
formatter:
seriesTypeB === EchartsTimeseriesSeriesType.Bar
- ? maxLabelFormatterSecondary
- : formatterSecondary,
+ ? getOverMaxHiddenFormatter({
+ max: maxSecondary,
+ formatter: seriesFormatter,
+ })
+ : seriesFormatter,
showValueIndexes: showValueIndexesB,
totalStackedValues: totalStackedValuesB,
thresholdValues: thresholdValuesB,
@@ -434,7 +490,14 @@ export default function transformProps(
max,
minorTick: { show: true },
minorSplitLine: { show: minorSplitLine },
- axisLabel: { formatter },
+ axisLabel: {
+ formatter: getYAxisFormatter(
+ metrics,
+ !!contributionMode,
+ customFormatters,
+ yAxisFormat,
+ ),
+ },
scale: truncateYAxis,
name: yAxisTitle,
nameGap: convertInteger(yAxisTitleMargin),
@@ -449,7 +512,14 @@ export default function transformProps(
minorTick: { show: true },
splitLine: { show: false },
minorSplitLine: { show: minorSplitLine },
- axisLabel: { formatter: formatterSecondary },
+ axisLabel: {
+ formatter: getYAxisFormatter(
+ metricsB,
+ !!contributionMode,
+ customFormattersSecondary,
+ yAxisFormatSecondary,
+ ),
+ },
scale: truncateYAxis,
name: yAxisTitleSecondary,
alignTicks,
@@ -475,10 +545,36 @@ export default function transformProps(
Object.keys(forecastValues).forEach(key => {
const value = forecastValues[key];
+ // if there are no dimensions, key is a verbose name of a metric,
+ // otherwise it is a comma separated string where the first part is metric name
+ let formatterKey;
+ if (primarySeries.has(key)) {
+ formatterKey =
+ groupby.length === 0 ? inverted[key] : labelMap[key]?.[0];
+ } else {
+ formatterKey =
+ groupbyB.length === 0 ? inverted[key] : labelMapB[key]?.[0];
+ }
+ const tooltipFormatter = getFormatter(
+ customFormatters,
+ formatter,
+ metrics,
+ formatterKey,
+ !!contributionMode,
+ );
+ const tooltipFormatterSecondary = getFormatter(
+ customFormattersSecondary,
+ formatterSecondary,
+ metricsB,
+ formatterKey,
+ !!contributionMode,
+ );
const content = formatForecastTooltipSeries({
...value,
seriesName: key,
- formatter: primarySeries.has(key) ? formatter : formatterSecondary,
+ formatter: primarySeries.has(key)
+ ? tooltipFormatter
+ : tooltipFormatterSecondary,
});
rows.push(`<span style="opacity: 0.7">${content}</span>`);
});
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Pie/transformProps.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Pie/transformProps.ts
index 7ea9cc1ffb..ea616cb201 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Pie/transformProps.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Pie/transformProps.ts
@@ -25,6 +25,7 @@ import {
NumberFormats,
t,
ValueFormatter,
+ getValueFormatter,
} from '@superset-ui/core';
import { CallbackDataParams } from 'echarts/types/src/util/types';
import { EChartsCoreOption, PieSeriesOption } from 'echarts';
@@ -47,7 +48,6 @@ import { defaultGrid } from '../defaults';
import { convertInteger } from '../utils/convertInteger';
import { getDefaultTooltip } from '../utils/tooltip';
import { Refs } from '../types';
-import { getValueFormatter } from '../utils/valueFormatter';
const percentFormatter = getNumberFormatter(NumberFormats.PERCENT_2_POINT);
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 a12a757e44..6af4c7f653 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Sunburst/transformProps.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Sunburst/transformProps.ts
@@ -24,10 +24,11 @@ import {
getNumberFormatter,
getSequentialSchemeRegistry,
getTimeFormatter,
+ getValueFormatter,
NumberFormats,
- NumberFormatter,
SupersetTheme,
t,
+ ValueFormatter,
} from '@superset-ui/core';
import { EChartsCoreOption } from 'echarts';
import { CallbackDataParams } from 'echarts/types/src/util/types';
@@ -74,7 +75,7 @@ export function formatLabel({
}: {
params: CallbackDataParams;
labelType: EchartsSunburstLabelType;
- numberFormatter: NumberFormatter;
+ numberFormatter: ValueFormatter;
}): string {
const { name = '', value } = params;
const formattedValue = numberFormatter(value as number);
@@ -93,7 +94,8 @@ export function formatLabel({
export function formatTooltip({
params,
- numberFormatter,
+ primaryValueFormatter,
+ secondaryValueFormatter,
colorByCategory,
totalValue,
metricLabel,
@@ -107,7 +109,8 @@ export function formatTooltip({
value: number;
}[];
};
- numberFormatter: NumberFormatter;
+ primaryValueFormatter: ValueFormatter;
+ secondaryValueFormatter: ValueFormatter | undefined;
colorByCategory: boolean;
totalValue: number;
metricLabel: string;
@@ -116,8 +119,10 @@ export function formatTooltip({
}): string {
const { data, treePathInfo = [] } = params;
const node = data as TreeNode;
- const formattedValue = numberFormatter(node.value);
- const formattedSecondaryValue = numberFormatter(node.secondaryValue);
+ const formattedValue = primaryValueFormatter(node.value);
+ const formattedSecondaryValue = secondaryValueFormatter?.(
+ node.secondaryValue,
+ );
const percentFormatter = getNumberFormatter(NumberFormats.PERCENT_2_POINT);
const compareValuePercentage = percentFormatter(
@@ -177,6 +182,7 @@ export default function transformProps(
theme,
inContextMenu,
emitCrossFilters,
+ datasource,
} = chartProps;
const { data = [] } = queriesData[0];
const coltypeMapping = getColtypesMapping(queriesData[0]);
@@ -195,12 +201,28 @@ export default function transformProps(
showTotal,
sliceId,
} = formData;
+ const { currencyFormats = {}, columnFormats = {} } = datasource;
const refs: Refs = {};
+ const primaryValueFormatter = getValueFormatter(
+ metric,
+ currencyFormats,
+ columnFormats,
+ numberFormat,
+ );
+ const secondaryValueFormatter = secondaryMetric
+ ? getValueFormatter(
+ secondaryMetric,
+ currencyFormats,
+ columnFormats,
+ numberFormat,
+ )
+ : undefined;
+
const numberFormatter = getNumberFormatter(numberFormat);
const formatter = (params: CallbackDataParams) =>
formatLabel({
params,
- numberFormatter,
+ numberFormatter: primaryValueFormatter,
labelType,
});
const minShowLabelAngle = (showLabelsThreshold || 0) * 3.6;
@@ -319,7 +341,8 @@ export default function transformProps(
formatter: (params: any) =>
formatTooltip({
params,
- numberFormatter,
+ primaryValueFormatter,
+ secondaryValueFormatter,
colorByCategory,
totalValue,
metricLabel,
@@ -356,7 +379,7 @@ export default function transformProps(
top: 'center',
left: 'center',
style: {
- text: t('Total: %s', numberFormatter(totalValue)),
+ text: t('Total: %s', primaryValueFormatter(totalValue)),
fontSize: 16,
fontWeight: 'bold',
},
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts
index 2066148c84..63b2b2f6f4 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts
@@ -22,7 +22,6 @@ import {
AnnotationLayer,
AxisType,
CategoricalColorNamespace,
- CurrencyFormatter,
ensureIsArray,
GenericDataType,
getMetricLabel,
@@ -33,13 +32,11 @@ import {
isFormulaAnnotationLayer,
isIntervalAnnotationLayer,
isPhysicalColumn,
- isSavedMetric,
isTimeseriesAnnotationLayer,
- NumberFormats,
- QueryFormMetric,
t,
TimeseriesChartDataResponseResult,
- ValueFormatter,
+ buildCustomFormatters,
+ getCustomFormatter,
} from '@superset-ui/core';
import {
extractExtraMetrics,
@@ -97,36 +94,7 @@ import {
TIMEGRAIN_TO_TIMESTAMP,
} from '../constants';
import { getDefaultTooltip } from '../utils/tooltip';
-import {
- buildCustomFormatters,
- getCustomFormatter,
-} from '../utils/valueFormatter';
-
-const getYAxisFormatter = (
- metrics: QueryFormMetric[],
- forcePercentFormatter: boolean,
- customFormatters: Record<string, ValueFormatter>,
- yAxisFormat: string = NumberFormats.SMART_NUMBER,
-) => {
- if (forcePercentFormatter) {
- return getNumberFormatter(',.0%');
- }
- const metricsArray = ensureIsArray(metrics);
- if (
- metricsArray.every(isSavedMetric) &&
- metricsArray
- .map(metric => customFormatters[metric])
- .every(
- (formatter, _, formatters) =>
- formatter instanceof CurrencyFormatter &&
- (formatter as CurrencyFormatter)?.currency?.symbol ===
- (formatters[0] as CurrencyFormatter)?.currency?.symbol,
- )
- ) {
- return customFormatters[metricsArray[0]];
- }
- return getNumberFormatter(yAxisFormat);
-};
+import { getYAxisFormatter } from '../utils/getYAxisFormatter';
export default function transformProps(
chartProps: EchartsTimeseriesChartProps,
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/Treemap/transformProps.ts b/superset-frontend/plugins/plugin-chart-echarts/src/Treemap/transformProps.ts
index 9e0454b386..a9e909abf8 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Treemap/transformProps.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Treemap/transformProps.ts
@@ -24,6 +24,7 @@ import {
getTimeFormatter,
NumberFormats,
ValueFormatter,
+ getValueFormatter,
} from '@superset-ui/core';
import { TreemapSeriesNodeItemOption } from 'echarts/types/src/chart/treemap/TreemapSeries';
import { EChartsCoreOption, TreemapSeriesOption } from 'echarts';
@@ -48,7 +49,6 @@ import { OpacityEnum } from '../constants';
import { getDefaultTooltip } from '../utils/tooltip';
import { Refs } from '../types';
import { treeBuilder, TreeNode } from '../utils/treeBuilder';
-import { getValueFormatter } from '../utils/valueFormatter';
export function formatLabel({
params,
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/utils/getYAxisFormatter.ts b/superset-frontend/plugins/plugin-chart-echarts/src/utils/getYAxisFormatter.ts
new file mode 100644
index 0000000000..8d52c44464
--- /dev/null
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/utils/getYAxisFormatter.ts
@@ -0,0 +1,54 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import {
+ CurrencyFormatter,
+ ensureIsArray,
+ getNumberFormatter,
+ isSavedMetric,
+ NumberFormats,
+ QueryFormMetric,
+ ValueFormatter,
+} from '@superset-ui/core';
+
+export const getYAxisFormatter = (
+ metrics: QueryFormMetric[],
+ forcePercentFormatter: boolean,
+ customFormatters: Record<string, ValueFormatter>,
+ yAxisFormat: string = NumberFormats.SMART_NUMBER,
+) => {
+ if (forcePercentFormatter) {
+ return getNumberFormatter(',.0%');
+ }
+ const metricsArray = ensureIsArray(metrics);
+ if (
+ metricsArray.every(isSavedMetric) &&
+ metricsArray
+ .map(metric => customFormatters[metric])
+ .every(
+ (formatter, _, formatters) =>
+ formatter instanceof CurrencyFormatter &&
+ (formatter as CurrencyFormatter)?.currency?.symbol ===
+ (formatters[0] as CurrencyFormatter)?.currency?.symbol,
+ )
+ ) {
+ return customFormatters[metricsArray[0]];
+ }
+ return getNumberFormatter(yAxisFormat);
+};
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 f9477ea25a..663548f25d 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/utils/series.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/utils/series.ts
@@ -518,7 +518,7 @@ export function getAxisType(dataType?: GenericDataType): AxisType {
export function getOverMaxHiddenFormatter(
config: {
max?: number;
- formatter?: NumberFormatter;
+ formatter?: ValueFormatter;
} = {},
) {
const { max, formatter } = config;