mirror of
https://github.com/apache/superset.git
synced 2026-04-19 08:04:53 +00:00
feat: Implement currencies formatter for saved metrics (#24517)
This commit is contained in:
committed by
GitHub
parent
e402c94a9f
commit
83ff4cd86a
@@ -19,9 +19,9 @@
|
||||
import {
|
||||
ColorFormatters,
|
||||
getColorFormatters,
|
||||
Metric,
|
||||
} from '@superset-ui/chart-controls';
|
||||
import {
|
||||
getNumberFormatter,
|
||||
GenericDataType,
|
||||
getMetricLabel,
|
||||
extractTimegrain,
|
||||
@@ -30,12 +30,20 @@ import {
|
||||
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,
|
||||
): BigNumberVizProps {
|
||||
const { width, height, queriesData, formData, rawFormData, hooks } =
|
||||
chartProps;
|
||||
const {
|
||||
width,
|
||||
height,
|
||||
queriesData,
|
||||
formData,
|
||||
rawFormData,
|
||||
hooks,
|
||||
datasource: { currencyFormats = {}, columnFormats = {} },
|
||||
} = chartProps;
|
||||
const {
|
||||
headerFontSize,
|
||||
metric = 'value',
|
||||
@@ -54,7 +62,7 @@ export default function transformProps(
|
||||
const bigNumber =
|
||||
data.length === 0 ? null : parseMetricValue(data[0][metricName]);
|
||||
|
||||
let metricEntry;
|
||||
let metricEntry: Metric | undefined;
|
||||
if (chartProps.datasource?.metrics) {
|
||||
metricEntry = chartProps.datasource.metrics.find(
|
||||
metricItem => metricItem.metric_name === metric,
|
||||
@@ -67,12 +75,19 @@ export default function transformProps(
|
||||
metricEntry?.d3format,
|
||||
);
|
||||
|
||||
const numberFormatter = getValueFormatter(
|
||||
metric,
|
||||
currencyFormats,
|
||||
columnFormats,
|
||||
yAxisFormat,
|
||||
);
|
||||
|
||||
const headerFormatter =
|
||||
coltypes[0] === GenericDataType.TEMPORAL ||
|
||||
coltypes[0] === GenericDataType.STRING ||
|
||||
forceTimestampFormatting
|
||||
? formatTime
|
||||
: getNumberFormatter(yAxisFormat ?? metricEntry?.d3format ?? undefined);
|
||||
: numberFormatter;
|
||||
|
||||
const { onContextMenu } = hooks;
|
||||
|
||||
|
||||
@@ -24,9 +24,10 @@ import {
|
||||
getMetricLabel,
|
||||
t,
|
||||
smartDateVerboseFormatter,
|
||||
NumberFormatter,
|
||||
TimeFormatter,
|
||||
getXAxisLabel,
|
||||
Metric,
|
||||
ValueFormatter,
|
||||
} from '@superset-ui/core';
|
||||
import { EChartsCoreOption, graphic } from 'echarts';
|
||||
import {
|
||||
@@ -38,11 +39,12 @@ 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(
|
||||
formatDate: TimeFormatter = smartDateVerboseFormatter,
|
||||
formatValue: NumberFormatter | TimeFormatter = defaultNumberFormatter,
|
||||
formatValue: ValueFormatter | TimeFormatter = defaultNumberFormatter,
|
||||
) {
|
||||
return function renderTooltip(params: { data: TimeSeriesDatum }[]) {
|
||||
return `
|
||||
@@ -73,6 +75,7 @@ export default function transformProps(
|
||||
theme,
|
||||
hooks,
|
||||
inContextMenu,
|
||||
datasource: { currencyFormats = {}, columnFormats = {} },
|
||||
} = chartProps;
|
||||
const {
|
||||
colorPicker,
|
||||
@@ -159,7 +162,7 @@ export default function transformProps(
|
||||
className = 'negative';
|
||||
}
|
||||
|
||||
let metricEntry;
|
||||
let metricEntry: Metric | undefined;
|
||||
if (chartProps.datasource?.metrics) {
|
||||
metricEntry = chartProps.datasource.metrics.find(
|
||||
metricEntry => metricEntry.metric_name === metric,
|
||||
@@ -172,12 +175,19 @@ export default function transformProps(
|
||||
metricEntry?.d3format,
|
||||
);
|
||||
|
||||
const numberFormatter = getValueFormatter(
|
||||
metric,
|
||||
currencyFormats,
|
||||
columnFormats,
|
||||
yAxisFormat,
|
||||
);
|
||||
|
||||
const headerFormatter =
|
||||
metricColtype === GenericDataType.TEMPORAL ||
|
||||
metricColtype === GenericDataType.STRING ||
|
||||
forceTimestampFormatting
|
||||
? formatTime
|
||||
: getNumberFormatter(yAxisFormat ?? metricEntry?.d3format ?? undefined);
|
||||
: numberFormatter;
|
||||
|
||||
if (trendLineData && timeRangeFixed && fromDatetime) {
|
||||
const toDatetimeOrToday = toDatetime ?? Date.now();
|
||||
|
||||
@@ -22,10 +22,10 @@ import {
|
||||
ChartDataResponseResult,
|
||||
ContextMenuFilters,
|
||||
DataRecordValue,
|
||||
NumberFormatter,
|
||||
QueryFormData,
|
||||
QueryFormMetric,
|
||||
TimeFormatter,
|
||||
ValueFormatter,
|
||||
} from '@superset-ui/core';
|
||||
import { ColorFormatters } from '@superset-ui/chart-controls';
|
||||
import { BaseChartProps, Refs } from '../types';
|
||||
@@ -73,7 +73,7 @@ export type BigNumberVizProps = {
|
||||
height: number;
|
||||
bigNumber?: DataRecordValue;
|
||||
bigNumberFallback?: TimeSeriesDatum;
|
||||
headerFormatter: NumberFormatter | TimeFormatter;
|
||||
headerFormatter: ValueFormatter | TimeFormatter;
|
||||
formatTime?: TimeFormatter;
|
||||
headerFontSize: number;
|
||||
kickerFontSize?: number;
|
||||
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
getMetricLabel,
|
||||
getNumberFormatter,
|
||||
NumberFormats,
|
||||
NumberFormatter,
|
||||
ValueFormatter,
|
||||
getColumnLabel,
|
||||
} from '@superset-ui/core';
|
||||
import { CallbackDataParams } from 'echarts/types/src/util/types';
|
||||
@@ -45,6 +45,7 @@ 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);
|
||||
|
||||
@@ -56,7 +57,7 @@ export function formatFunnelLabel({
|
||||
}: {
|
||||
params: Pick<CallbackDataParams, 'name' | 'value' | 'percent'>;
|
||||
labelType: EchartsFunnelLabelTypeType;
|
||||
numberFormatter: NumberFormatter;
|
||||
numberFormatter: ValueFormatter;
|
||||
sanitizeName?: boolean;
|
||||
}): string {
|
||||
const { name: rawName = '', value, percent } = params;
|
||||
@@ -94,6 +95,7 @@ export default function transformProps(
|
||||
theme,
|
||||
inContextMenu,
|
||||
emitCrossFilters,
|
||||
datasource,
|
||||
} = chartProps;
|
||||
const data: DataRecord[] = queriesData[0].data || [];
|
||||
const coltypeMapping = getColtypesMapping(queriesData[0]);
|
||||
@@ -118,6 +120,7 @@ export default function transformProps(
|
||||
...DEFAULT_FUNNEL_FORM_DATA,
|
||||
...formData,
|
||||
};
|
||||
const { currencyFormats = {}, columnFormats = {} } = datasource;
|
||||
const refs: Refs = {};
|
||||
const metricLabel = getMetricLabel(metric);
|
||||
const groupbyLabels = groupby.map(getColumnLabel);
|
||||
@@ -139,7 +142,12 @@ export default function transformProps(
|
||||
const { setDataMask = () => {}, onContextMenu } = hooks;
|
||||
|
||||
const colorFn = CategoricalColorNamespace.getScale(colorScheme as string);
|
||||
const numberFormatter = getNumberFormatter(numberFormat);
|
||||
const numberFormatter = getValueFormatter(
|
||||
metric,
|
||||
currencyFormats,
|
||||
columnFormats,
|
||||
numberFormat,
|
||||
);
|
||||
|
||||
const transformedData: FunnelSeriesOption[] = data.map(datum => {
|
||||
const name = extractGroupbyLabel({
|
||||
|
||||
@@ -21,7 +21,6 @@ import {
|
||||
CategoricalColorNamespace,
|
||||
CategoricalColorScale,
|
||||
DataRecord,
|
||||
getNumberFormatter,
|
||||
getMetricLabel,
|
||||
getColumnLabel,
|
||||
} from '@superset-ui/core';
|
||||
@@ -47,6 +46,7 @@ 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,
|
||||
@@ -105,7 +105,11 @@ export default function transformProps(
|
||||
} = chartProps;
|
||||
|
||||
const gaugeSeriesOptions = defaultGaugeSeriesOption(theme);
|
||||
const { verboseMap = {} } = datasource;
|
||||
const {
|
||||
verboseMap = {},
|
||||
currencyFormats = {},
|
||||
columnFormats = {},
|
||||
} = datasource;
|
||||
const {
|
||||
groupby,
|
||||
metric,
|
||||
@@ -132,7 +136,12 @@ export default function transformProps(
|
||||
const refs: Refs = {};
|
||||
const data = (queriesData[0]?.data || []) as DataRecord[];
|
||||
const coltypeMapping = getColtypesMapping(queriesData[0]);
|
||||
const numberFormatter = getNumberFormatter(numberFormat);
|
||||
const numberFormatter = getValueFormatter(
|
||||
metric,
|
||||
currencyFormats,
|
||||
columnFormats,
|
||||
numberFormat,
|
||||
);
|
||||
const colorFn = CategoricalColorNamespace.getScale(colorScheme as string);
|
||||
const axisLineWidth = calculateAxisLineWidth(data, fontSize, overlap);
|
||||
const groupbyLabels = groupby.map(getColumnLabel);
|
||||
|
||||
@@ -23,8 +23,8 @@ import {
|
||||
getNumberFormatter,
|
||||
getTimeFormatter,
|
||||
NumberFormats,
|
||||
NumberFormatter,
|
||||
t,
|
||||
ValueFormatter,
|
||||
} from '@superset-ui/core';
|
||||
import { CallbackDataParams } from 'echarts/types/src/util/types';
|
||||
import { EChartsCoreOption, PieSeriesOption } from 'echarts';
|
||||
@@ -47,6 +47,7 @@ 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);
|
||||
|
||||
@@ -58,7 +59,7 @@ export function formatPieLabel({
|
||||
}: {
|
||||
params: Pick<CallbackDataParams, 'name' | 'value' | 'percent'>;
|
||||
labelType: EchartsPieLabelType;
|
||||
numberFormatter: NumberFormatter;
|
||||
numberFormatter: ValueFormatter;
|
||||
sanitizeName?: boolean;
|
||||
}): string {
|
||||
const { name: rawName = '', value, percent } = params;
|
||||
@@ -145,7 +146,9 @@ export default function transformProps(
|
||||
theme,
|
||||
inContextMenu,
|
||||
emitCrossFilters,
|
||||
datasource,
|
||||
} = chartProps;
|
||||
const { columnFormats = {}, currencyFormats = {} } = datasource;
|
||||
const { data = [] } = queriesData[0];
|
||||
const coltypeMapping = getColtypesMapping(queriesData[0]);
|
||||
|
||||
@@ -203,7 +206,13 @@ export default function transformProps(
|
||||
const { setDataMask = () => {}, onContextMenu } = hooks;
|
||||
|
||||
const colorFn = CategoricalColorNamespace.getScale(colorScheme as string);
|
||||
const numberFormatter = getNumberFormatter(numberFormat);
|
||||
const numberFormatter = getValueFormatter(
|
||||
metric,
|
||||
currencyFormats,
|
||||
columnFormats,
|
||||
numberFormat,
|
||||
);
|
||||
|
||||
let totalValue = 0;
|
||||
|
||||
const transformedData: PieSeriesOption[] = data.map(datum => {
|
||||
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
AnnotationLayer,
|
||||
AxisType,
|
||||
CategoricalColorNamespace,
|
||||
CurrencyFormatter,
|
||||
ensureIsArray,
|
||||
GenericDataType,
|
||||
getMetricLabel,
|
||||
@@ -32,9 +33,13 @@ import {
|
||||
isFormulaAnnotationLayer,
|
||||
isIntervalAnnotationLayer,
|
||||
isPhysicalColumn,
|
||||
isSavedMetric,
|
||||
isTimeseriesAnnotationLayer,
|
||||
NumberFormats,
|
||||
QueryFormMetric,
|
||||
t,
|
||||
TimeseriesChartDataResponseResult,
|
||||
ValueFormatter,
|
||||
} from '@superset-ui/core';
|
||||
import {
|
||||
extractExtraMetrics,
|
||||
@@ -92,6 +97,36 @@ 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);
|
||||
};
|
||||
|
||||
export default function transformProps(
|
||||
chartProps: EchartsTimeseriesChartProps,
|
||||
@@ -109,7 +144,11 @@ export default function transformProps(
|
||||
inContextMenu,
|
||||
emitCrossFilters,
|
||||
} = chartProps;
|
||||
const { verboseMap = {} } = datasource;
|
||||
const {
|
||||
verboseMap = {},
|
||||
columnFormats = {},
|
||||
currencyFormats = {},
|
||||
} = datasource;
|
||||
const [queryData] = queriesData;
|
||||
const { data = [], label_map = {} } =
|
||||
queryData as TimeseriesChartDataResponseResult;
|
||||
@@ -232,8 +271,15 @@ export default function transformProps(
|
||||
|
||||
const xAxisType = getAxisType(xAxisDataType);
|
||||
const series: SeriesOption[] = [];
|
||||
const formatter = getNumberFormatter(
|
||||
contributionMode || isAreaExpand ? ',.0%' : yAxisFormat,
|
||||
|
||||
const forcePercentFormatter = Boolean(contributionMode || isAreaExpand);
|
||||
const percentFormatter = getNumberFormatter(',.0%');
|
||||
const defaultFormatter = getNumberFormatter(yAxisFormat);
|
||||
const customFormatters = buildCustomFormatters(
|
||||
metrics,
|
||||
currencyFormats,
|
||||
columnFormats,
|
||||
yAxisFormat,
|
||||
);
|
||||
|
||||
const array = ensureIsArray(chartProps.rawFormData?.time_compare);
|
||||
@@ -262,7 +308,13 @@ export default function transformProps(
|
||||
seriesType,
|
||||
legendState,
|
||||
stack,
|
||||
formatter,
|
||||
formatter: forcePercentFormatter
|
||||
? percentFormatter
|
||||
: getCustomFormatter(
|
||||
customFormatters,
|
||||
metrics,
|
||||
labelMap[seriesName]?.[0],
|
||||
) ?? defaultFormatter,
|
||||
showValue,
|
||||
onlyTotal,
|
||||
totalStackedValues: sortedTotalValues,
|
||||
@@ -440,7 +492,14 @@ export default function transformProps(
|
||||
max,
|
||||
minorTick: { show: true },
|
||||
minorSplitLine: { show: minorSplitLine },
|
||||
axisLabel: { formatter },
|
||||
axisLabel: {
|
||||
formatter: getYAxisFormatter(
|
||||
metrics,
|
||||
forcePercentFormatter,
|
||||
customFormatters,
|
||||
yAxisFormat,
|
||||
),
|
||||
},
|
||||
scale: truncateYAxis,
|
||||
name: yAxisTitle,
|
||||
nameGap: convertInteger(yAxisTitleMargin),
|
||||
@@ -485,10 +544,17 @@ export default function transformProps(
|
||||
if (value.observation === 0 && stack) {
|
||||
return;
|
||||
}
|
||||
// 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
|
||||
const formatterKey =
|
||||
groupby.length === 0 ? inverted[key] : labelMap[key]?.[0];
|
||||
const content = formatForecastTooltipSeries({
|
||||
...value,
|
||||
seriesName: key,
|
||||
formatter,
|
||||
formatter: forcePercentFormatter
|
||||
? percentFormatter
|
||||
: getCustomFormatter(customFormatters, metrics, formatterKey) ??
|
||||
defaultFormatter,
|
||||
});
|
||||
if (!legendState || legendState[key]) {
|
||||
rows.push(`<span style="font-weight: 700">${content}</span>`);
|
||||
|
||||
@@ -28,13 +28,13 @@ import {
|
||||
IntervalAnnotationLayer,
|
||||
isTimeseriesAnnotationResult,
|
||||
LegendState,
|
||||
NumberFormatter,
|
||||
smartDateDetailedFormatter,
|
||||
smartDateFormatter,
|
||||
SupersetTheme,
|
||||
TimeFormatter,
|
||||
TimeseriesAnnotationLayer,
|
||||
TimeseriesDataRecord,
|
||||
ValueFormatter,
|
||||
} from '@superset-ui/core';
|
||||
import { SeriesOption } from 'echarts';
|
||||
import {
|
||||
@@ -158,7 +158,7 @@ export function transformSeries(
|
||||
showValue?: boolean;
|
||||
onlyTotal?: boolean;
|
||||
legendState?: LegendState;
|
||||
formatter?: NumberFormatter;
|
||||
formatter?: ValueFormatter;
|
||||
totalStackedValues?: number[];
|
||||
showValueIndexes?: number[];
|
||||
thresholdValues?: number[];
|
||||
|
||||
@@ -23,7 +23,7 @@ import {
|
||||
getNumberFormatter,
|
||||
getTimeFormatter,
|
||||
NumberFormats,
|
||||
NumberFormatter,
|
||||
ValueFormatter,
|
||||
} from '@superset-ui/core';
|
||||
import { TreemapSeriesNodeItemOption } from 'echarts/types/src/chart/treemap/TreemapSeries';
|
||||
import { EChartsCoreOption, TreemapSeriesOption } from 'echarts';
|
||||
@@ -48,6 +48,7 @@ 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,
|
||||
@@ -56,7 +57,7 @@ export function formatLabel({
|
||||
}: {
|
||||
params: TreemapSeriesCallbackDataParams;
|
||||
labelType: EchartsTreemapLabelType;
|
||||
numberFormatter: NumberFormatter;
|
||||
numberFormatter: ValueFormatter;
|
||||
}): string {
|
||||
const { name = '', value } = params;
|
||||
const formattedValue = numberFormatter(value as number);
|
||||
@@ -78,7 +79,7 @@ export function formatTooltip({
|
||||
numberFormatter,
|
||||
}: {
|
||||
params: TreemapSeriesCallbackDataParams;
|
||||
numberFormatter: NumberFormatter;
|
||||
numberFormatter: ValueFormatter;
|
||||
}): string {
|
||||
const { value, treePathInfo = [] } = params;
|
||||
const formattedValue = numberFormatter(value as number);
|
||||
@@ -118,8 +119,10 @@ export default function transformProps(
|
||||
theme,
|
||||
inContextMenu,
|
||||
emitCrossFilters,
|
||||
datasource,
|
||||
} = chartProps;
|
||||
const { data = [] } = queriesData[0];
|
||||
const { columnFormats = {}, currencyFormats = {} } = datasource;
|
||||
const { setDataMask = () => {}, onContextMenu } = hooks;
|
||||
const coltypeMapping = getColtypesMapping(queriesData[0]);
|
||||
|
||||
@@ -141,7 +144,13 @@ export default function transformProps(
|
||||
};
|
||||
const refs: Refs = {};
|
||||
const colorFn = CategoricalColorNamespace.getScale(colorScheme as string);
|
||||
const numberFormatter = getNumberFormatter(numberFormat);
|
||||
const numberFormatter = getValueFormatter(
|
||||
metric,
|
||||
currencyFormats,
|
||||
columnFormats,
|
||||
numberFormat,
|
||||
);
|
||||
|
||||
const formatter = (params: TreemapSeriesCallbackDataParams) =>
|
||||
formatLabel({
|
||||
params,
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* under the License.
|
||||
*/
|
||||
import { isNumber } from 'lodash';
|
||||
import { DataRecord, DTTM_ALIAS, NumberFormatter } from '@superset-ui/core';
|
||||
import { DataRecord, DTTM_ALIAS, ValueFormatter } from '@superset-ui/core';
|
||||
import { OptionName } from 'echarts/types/src/util/types';
|
||||
import { TooltipMarker } from 'echarts/types/src/util/format';
|
||||
import {
|
||||
@@ -91,7 +91,7 @@ export const formatForecastTooltipSeries = ({
|
||||
}: ForecastValue & {
|
||||
seriesName: string;
|
||||
marker: TooltipMarker;
|
||||
formatter: NumberFormatter;
|
||||
formatter: ValueFormatter;
|
||||
}): string => {
|
||||
let row = `${marker}${sanitizeHtml(seriesName)}: `;
|
||||
let isObservation = false;
|
||||
|
||||
@@ -31,6 +31,7 @@ import {
|
||||
SupersetTheme,
|
||||
normalizeTimestamp,
|
||||
LegendState,
|
||||
ValueFormatter,
|
||||
} from '@superset-ui/core';
|
||||
import { SortSeriesType } from '@superset-ui/chart-controls';
|
||||
import { format, LegendComponentOption, SeriesOption } from 'echarts';
|
||||
@@ -345,7 +346,7 @@ export function formatSeriesName(
|
||||
timeFormatter,
|
||||
coltype,
|
||||
}: {
|
||||
numberFormatter?: NumberFormatter;
|
||||
numberFormatter?: ValueFormatter;
|
||||
timeFormatter?: TimeFormatter;
|
||||
coltype?: GenericDataType;
|
||||
} = {},
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
import {
|
||||
Currency,
|
||||
CurrencyFormatter,
|
||||
ensureIsArray,
|
||||
getNumberFormatter,
|
||||
isSavedMetric,
|
||||
QueryFormMetric,
|
||||
ValueFormatter,
|
||||
} from '@superset-ui/core';
|
||||
|
||||
export const buildCustomFormatters = (
|
||||
metrics: QueryFormMetric | QueryFormMetric[] | undefined,
|
||||
currencyFormats: Record<string, Currency>,
|
||||
columnFormats: Record<string, string>,
|
||||
d3Format: string | undefined,
|
||||
) => {
|
||||
const metricsArray = ensureIsArray(metrics);
|
||||
return metricsArray.reduce((acc, metric) => {
|
||||
const actualD3Format = isSavedMetric(metric)
|
||||
? columnFormats[metric] ?? d3Format
|
||||
: d3Format;
|
||||
if (isSavedMetric(metric)) {
|
||||
return currencyFormats[metric]
|
||||
? {
|
||||
...acc,
|
||||
[metric]: new CurrencyFormatter({
|
||||
d3Format: actualD3Format,
|
||||
currency: currencyFormats[metric],
|
||||
}),
|
||||
}
|
||||
: {
|
||||
...acc,
|
||||
[metric]: getNumberFormatter(actualD3Format),
|
||||
};
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
};
|
||||
|
||||
export const getCustomFormatter = (
|
||||
customFormatters: Record<string, ValueFormatter>,
|
||||
metrics: QueryFormMetric | QueryFormMetric[] | undefined,
|
||||
key?: string,
|
||||
) => {
|
||||
const metricsArray = ensureIsArray(metrics);
|
||||
if (metricsArray.length === 1 && isSavedMetric(metricsArray[0])) {
|
||||
return customFormatters[metricsArray[0]];
|
||||
}
|
||||
return key ? customFormatters[key] : undefined;
|
||||
};
|
||||
|
||||
export const getValueFormatter = (
|
||||
metrics: QueryFormMetric | QueryFormMetric[] | undefined,
|
||||
currencyFormats: Record<string, Currency>,
|
||||
columnFormats: Record<string, string>,
|
||||
d3Format: string | undefined,
|
||||
key?: string,
|
||||
) =>
|
||||
getCustomFormatter(
|
||||
buildCustomFormatters(metrics, currencyFormats, columnFormats, d3Format),
|
||||
metrics,
|
||||
key,
|
||||
) ?? getNumberFormatter(d3Format);
|
||||
@@ -158,5 +158,30 @@ describe('BigNumberWithTrendline', () => {
|
||||
'1.23',
|
||||
);
|
||||
});
|
||||
|
||||
it('should format with datasource currency', () => {
|
||||
const propsWithDatasource = {
|
||||
...props,
|
||||
datasource: {
|
||||
...props.datasource,
|
||||
currencyFormats: {
|
||||
value: { symbol: 'USD', symbolPosition: 'prefix' },
|
||||
},
|
||||
metrics: [
|
||||
{
|
||||
label: 'value',
|
||||
metric_name: 'value',
|
||||
d3format: '.2f',
|
||||
currency: `{symbol: 'USD', symbolPosition: 'prefix' }`,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
const transformed = transformProps(propsWithDatasource);
|
||||
// @ts-ignore
|
||||
expect(transformed.headerFormatter(transformed.bigNumber)).toStrictEqual(
|
||||
'$ 1.23',
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user