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 @@ -5,6 +5,8 @@
* 2.0.
*/

import 'jest-canvas-mock';

// @ts-ignore
import { compile } from 'vega-lite/build/vega-lite';

Expand Down Expand Up @@ -100,8 +102,8 @@ describe('getScatterplotMatrixVegaLiteSpec()', () => {
});
expect(vegaLiteSpec.spec.encoding.color).toEqual({
condition: {
// Note the alternative UTF-8 dot character
test: "(datum['mloutlier_score'] >= mlOutlierScoreThreshold.cutoff)",
// Note the escaped dot character
test: "(datum['ml\\.outlier_score'] >= mlOutlierScoreThreshold.cutoff)",
value: COLOR_OUTLIER,
},
value: euiThemeLight.euiColorMediumShade,
Expand All @@ -110,8 +112,8 @@ describe('getScatterplotMatrixVegaLiteSpec()', () => {
{ field: 'x', type: 'quantitative' },
{ field: 'y', type: 'quantitative' },
{
// Note the alternative UTF-8 dot character
field: 'mloutlier_score',
// Note the escaped dot character
field: 'ml\\.outlier_score',
format: '.3f',
type: 'quantitative',
},
Expand Down Expand Up @@ -156,4 +158,25 @@ describe('getScatterplotMatrixVegaLiteSpec()', () => {
{ field: 'y', type: 'quantitative' },
]);
});

it('should escape special characters', () => {
const data = [{ ['x.a']: 1, ['y[a]']: 1 }];

const vegaLiteSpec = getScatterplotMatrixVegaLiteSpec(
data,
['x.a', 'y[a]'],
euiThemeLight,
undefined,
'the-color-field',
LEGEND_TYPES.NOMINAL
);

// column values should be escaped
expect(vegaLiteSpec.repeat).toEqual({
column: ['x\\.a', 'y\\[a\\]'],
row: ['y\\[a\\]', 'x\\.a'],
});
// raw data should not be escaped
expect(vegaLiteSpec.spec.data.values).toEqual(data);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -59,26 +59,11 @@ export const getColorSpec = (
return { value: DEFAULT_COLOR };
};

// Replace dots in field names with an alternative UTF-8 character
// since VEGA treats dots in field names as nested values and escaping
// in columns/rows for repeated charts isn't working as expected.
// Escapes the characters .[] in field names with double backslashes
// since VEGA treats dots/brackets in field names as nested values.
// See https://vega.github.io/vega-lite/docs/field.html for details.
function getEscapedVegaFieldName(fieldName: string) {
return fieldName.replace(/\./g, '․');
}

// Replace dots for all keys of all data items with an alternative UTF-8 character
// since VEGA treats dots in field names as nested values and escaping
// in columns/rows for repeated charts isn't working as expected.
function getEscapedVegaValues(values: VegaValue[]): VegaValue[] {
return values.map((d) =>
Object.keys(d).reduce(
(p, c) => ({
...p,
[getEscapedVegaFieldName(c)]: d[c],
}),
{} as VegaValue
)
);
return fieldName.replace(/([\.|\[|\]])/g, '\\$1');
}

type VegaValue = Record<string, string | number>;
Expand All @@ -92,13 +77,11 @@ export const getScatterplotMatrixVegaLiteSpec = (
legendType?: LegendType,
dynamicSize?: boolean
): TopLevelSpec => {
const vegaValues = getEscapedVegaValues(values);
const vegaValues = values;
const vegaColumns = columns.map(getEscapedVegaFieldName);
const outliers = resultsField !== undefined;

// Use an alternative UTF-8 character for the dot
// since VEGA treats dots in field names as nested values.
const escapedOutlierScoreField = `${resultsField}․${OUTLIER_SCORE_FIELD}`;
const escapedOutlierScoreField = `${resultsField}\\.${OUTLIER_SCORE_FIELD}`;

const colorSpec = getColorSpec(
euiTheme,
Expand Down Expand Up @@ -193,7 +176,10 @@ export const getScatterplotMatrixVegaLiteSpec = (
...(color !== undefined
? [{ type: colorSpec.type, field: getEscapedVegaFieldName(color) }]
: []),
...vegaColumns.map((d) => ({ type: LEGEND_TYPES.QUANTITATIVE, field: d })),
...vegaColumns.map((d) => ({
type: LEGEND_TYPES.QUANTITATIVE,
field: d,
})),
...(outliers
? [{ type: LEGEND_TYPES.QUANTITATIVE, field: escapedOutlierScoreField, format: '.3f' }]
: []),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,17 @@

import React, { FC, Suspense } from 'react';

import { EuiErrorBoundary } from '@elastic/eui';

import { VegaChartLoading } from './vega_chart_loading';
import type { VegaChartViewProps } from './vega_chart_view';

const VegaChartView = React.lazy(() => import('./vega_chart_view'));

export const VegaChart: FC<VegaChartViewProps> = (props) => (
<Suspense fallback={<VegaChartLoading />}>
<VegaChartView {...props} />
</Suspense>
<EuiErrorBoundary>
<Suspense fallback={<VegaChartLoading />}>
<VegaChartView {...props} />
</Suspense>
</EuiErrorBoundary>
);