Skip to content

Commit

Permalink
feat(bar_chart): Stacked Bar chart with Time comparison in separated …
Browse files Browse the repository at this point in the history
…stacks (#27589)
  • Loading branch information
Antonio-RiveroMartnez authored and pull[bot] committed May 16, 2024
1 parent fcd5ce2 commit c9416f5
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,7 @@ export default function transformProps(
sliceId,
isHorizontal,
lineStyle,
timeCompare: array,
},
);
if (transformedSeries) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ import {
formatAnnotationLabel,
parseAnnotationOpacity,
} from '../utils/annotation';
import { getChartPadding } from '../utils/series';
import { getChartPadding, getTimeCompareStackId } from '../utils/series';
import {
OpacityEnum,
StackControlsValue,
Expand Down Expand Up @@ -164,6 +164,7 @@ export function transformSeries(
isHorizontal?: boolean;
lineStyle?: LineStyleOption;
queryIndex?: number;
timeCompare?: string[];
},
): SeriesOption | undefined {
const { name } = series;
Expand All @@ -188,6 +189,7 @@ export function transformSeries(
sliceId,
isHorizontal = false,
queryIndex = 0,
timeCompare = [],
} = opts;
const contexts = seriesContexts[name || ''] || [];
const hasForecast =
Expand Down Expand Up @@ -217,9 +219,9 @@ export function transformSeries(
} else if (stack && isObservation) {
// the suffix of the observation series is '' (falsy), which disables
// stacking. Therefore we need to set something that is truthy.
stackId = 'obs';
stackId = getTimeCompareStackId('obs', timeCompare, name);
} else if (stack && isTrend) {
stackId = forecastSeries.type;
stackId = getTimeCompareStackId(forecastSeries.type, timeCompare, name);
}
let plotType;
if (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import {
} from '@superset-ui/core';
import { SortSeriesType } from '@superset-ui/chart-controls';
import { format, LegendComponentOption, SeriesOption } from 'echarts';
import { maxBy, meanBy, minBy, orderBy, sumBy } from 'lodash';
import { isEmpty, maxBy, meanBy, minBy, orderBy, sumBy } from 'lodash';
import {
NULL_STRING,
StackControlsValue,
Expand Down Expand Up @@ -604,3 +604,39 @@ export function getMinAndMaxFromBounds(
}
return {};
}

/**
* Returns the stackId used in stacked series.
* It will return the defaultId if the chart is not using time comparison.
* If time comparison is used, it will return the time comparison value as the stackId
* if the name includes the time comparison value.
*
* @param {string} defaultId The default stackId.
* @param {string[]} timeCompare The time comparison values.
* @param {string | number} name The name of the serie.
*
* @returns {string} The stackId.
*/
export function getTimeCompareStackId(
defaultId: string,
timeCompare: string[],
name?: string | number,
): string {
if (isEmpty(timeCompare)) {
return defaultId;
}
// Each timeCompare is its own stack so it doesn't stack on top of original ones
return (
timeCompare.find(value => {
if (typeof name === 'string') {
// offset is represented as <offset>, group by list
return (
name.includes(`${value},`) ||
// offset is represented as <metric>__<offset>
name.includes(`__${value}`)
);
}
return name?.toString().includes(value);
}) || defaultId
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import {
sanitizeHtml,
sortAndFilterSeries,
sortRows,
getTimeCompareStackId,
} from '../../src/utils/series';
import {
EchartsTimeseriesSeriesType,
Expand Down Expand Up @@ -1041,3 +1042,33 @@ test('getMinAndMaxFromBounds returns automatic lower bound when truncating', ()
scale: true,
});
});

describe('getTimeCompareStackId', () => {
it('returns the defaultId when timeCompare is empty', () => {
const result = getTimeCompareStackId('default', []);
expect(result).toEqual('default');
});

it('returns the defaultId when no value in timeCompare is included in name', () => {
const result = getTimeCompareStackId(
'default',
['compare1', 'compare2'],
'test__name',
);
expect(result).toEqual('default');
});

it('returns the first value in timeCompare that is included in name', () => {
const result = getTimeCompareStackId(
'default',
['compare1', 'compare2'],
'test__compare1',
);
expect(result).toEqual('compare1');
});

it('handles name being a number', () => {
const result = getTimeCompareStackId('default', ['123', '456'], 123);
expect(result).toEqual('123');
});
});

0 comments on commit c9416f5

Please sign in to comment.