Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ export const getTimeOffset = (
// offset is represented as <offset>, group by list
series.name.includes(`${timeOffset},`) ||
// offset is represented as <metric>__<offset>
series.name.includes(`__${timeOffset}`),
series.name.includes(`__${timeOffset}`) ||
// offset is represented as <metric>, <offset>
series.name.includes(`, ${timeOffset}`),
);

export const hasTimeOffset = (
Expand All @@ -45,10 +47,14 @@ export const getOriginalSeries = (
): string => {
let result = seriesName;
timeCompare.forEach(compare => {
// offset is represented as <offset>, group by list
// offset in the middle: <metric>, <offset>, <dimension>
result = result.replace(`, ${compare},`, ',');
// offset at start: <offset>, <dimension>
result = result.replace(`${compare},`, '');
// offset is represented as <metric>__<offset>
// offset with double underscore: <metric>__<offset>
result = result.replace(`__${compare}`, '');
// offset at end: <metric>, <offset>
result = result.replace(`, ${compare}`, '');
});
return result.trim();
};
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,101 @@
* specific language governing permissions and limitations
* under the License.
*/
import { getOriginalSeries } from '@superset-ui/chart-controls';
import {
getOriginalSeries,
getTimeOffset,
hasTimeOffset,
} from '@superset-ui/chart-controls';

test('returns the series name when time compare is empty', () => {
test('getOriginalSeries returns the series name when time compare is empty', () => {
const seriesName = 'sum';
expect(getOriginalSeries(seriesName, [])).toEqual(seriesName);
});

test('returns the original series name', () => {
test('getOriginalSeries returns the original series name with __ pattern', () => {
const seriesName = 'sum__1_month_ago';
const timeCompare = ['1_month_ago'];
expect(getOriginalSeries(seriesName, timeCompare)).toEqual('sum');
});

test('getOriginalSeries returns the original series name with <offset>, pattern', () => {
const seriesName = '1 year ago, groupby_value';
const timeCompare = ['1 year ago'];
expect(getOriginalSeries(seriesName, timeCompare)).toEqual('groupby_value');
});

test('getOriginalSeries returns the original series name with , <offset> pattern', () => {
const seriesName = 'AVG(price_each), 1 year ago';
const timeCompare = ['1 year ago'];
expect(getOriginalSeries(seriesName, timeCompare)).toEqual('AVG(price_each)');
});

test('getOriginalSeries handles multiple time compares', () => {
const seriesName = 'count, 1 year ago';
const timeCompare = ['1 month ago', '1 year ago'];
expect(getOriginalSeries(seriesName, timeCompare)).toEqual('count');
});

test('getOriginalSeries strips offset in the middle with dimension', () => {
const seriesName = 'SUM(sales), 28 days ago, Medium';
const timeCompare = ['28 days ago'];
expect(getOriginalSeries(seriesName, timeCompare)).toEqual(
'SUM(sales), Medium',
);
});

test('getOriginalSeries strips offset in the middle with multiple dimensions', () => {
const seriesName = 'SUM(sales), 1 year ago, Medium, 11';
const timeCompare = ['1 year ago'];
expect(getOriginalSeries(seriesName, timeCompare)).toEqual(
'SUM(sales), Medium, 11',
);
});

test('getTimeOffset returns undefined when no time offset pattern matches', () => {
const series = { name: 'count' };
const timeCompare = ['1 year ago'];
expect(getTimeOffset(series, timeCompare)).toBeUndefined();
});

test('getTimeOffset detects __ pattern', () => {
const series = { name: 'count__1 year ago' };
const timeCompare = ['1 year ago'];
expect(getTimeOffset(series, timeCompare)).toEqual('1 year ago');
});

test('getTimeOffset detects <offset>, pattern', () => {
const series = { name: '1 year ago, groupby_value' };
const timeCompare = ['1 year ago'];
expect(getTimeOffset(series, timeCompare)).toEqual('1 year ago');
});

test('getTimeOffset detects , <offset> pattern', () => {
const series = { name: 'AVG(price_each), 1 year ago' };
const timeCompare = ['1 year ago'];
expect(getTimeOffset(series, timeCompare)).toEqual('1 year ago');
});

test('getTimeOffset detects , <offset>, pattern (offset in middle)', () => {
const series = { name: 'SUM(sales), 28 days ago, Medium' };
const timeCompare = ['28 days ago'];
expect(getTimeOffset(series, timeCompare)).toEqual('28 days ago');
});

test('hasTimeOffset returns false for original series', () => {
const series = { name: 'count' };
const timeCompare = ['1 year ago'];
expect(hasTimeOffset(series, timeCompare)).toBe(false);
});

test('hasTimeOffset returns true for derived series with , <offset> pattern', () => {
const series = { name: 'AVG(price_each), 1 year ago' };
const timeCompare = ['1 year ago'];
expect(hasTimeOffset(series, timeCompare)).toBe(true);
});

test('hasTimeOffset returns false when series name is not a string', () => {
const series = { name: 123 };
const timeCompare = ['1 year ago'];
expect(hasTimeOffset(series, timeCompare)).toBe(false);
});
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,7 @@ export default function transformProps(
chartProps.rawFormData,
seriesName,
);

const lineStyle: LineStyleOption = {};
if (derivedSeries) {
// Get the time offset for this series to assign different dash patterns
Expand Down Expand Up @@ -370,7 +371,21 @@ export default function transformProps(

let colorScaleKey = getOriginalSeries(seriesName, array);

// If series name exactly matches a time offset (single metric case),
// When there's a single metric with dimensions, the backend replaces the metric
// with the time offset in derived series (e.g., "28 days ago, Medium" instead of
// "SUM(sales), 28 days ago, Medium"). To match colors, strip the metric label
// from original series so both produce the same key (e.g., "Medium").
if (
groupby &&
groupby.length > 0 &&
array.length > 0 &&
metrics?.length === 1
) {
const metricLabel = getMetricLabel(metrics[0]);
colorScaleKey = colorScaleKey.replace(`${metricLabel}, `, '');
}

// If series name exactly matches a time offset (single metric case, no dimensions),
// find the original series for color matching
if (derivedSeries && array.includes(seriesName)) {
const originalSeries = rawSeries.find(
Expand Down
Loading