Small multiples in vis_type_xy plugin (#86880) (#89127)

* Small multiples in vis_type_xy plugin

* Fix tooltip and formatted split chart values

* update advanced settings wording

* Remove React import in files with no JSX and change the extension to .ts

* Simplify conditions

* fix bar interval on split charts in vislib

* Fix charts not splitting for terms boolean fields

* fix filtering for small multiples

* Change tests interval values from 100 to 1000000

* Revert "Change tests interval values from 100 to 1000000"

This reverts commit 92f9d1b4b9.

* Fix tests for interval issue in vislib

(cherry picked from commit ef45b63c47da403399f76f00b49329531d445f31)

* Revert axis_scale changes related to interval

* Enable _line_chart_split_chart test for new charts library

* Move chart splitter id to const

Co-authored-by: nickofthyme <nick.ryan.partridge@gmail.com>
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>

Co-authored-by: nickofthyme <nick.ryan.partridge@gmail.com>
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Diana Derevyankina 2021-01-25 18:00:04 +03:00 committed by GitHub
parent acea647b56
commit f7b288bd8f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 213 additions and 162 deletions

View file

@ -459,7 +459,7 @@ of buckets to try to represent.
[horizontal]
[[visualization-visualize-chartslibrary]]`visualization:visualize:legacyChartsLibrary`::
Enables legacy charts library for area, line and bar charts in visualize. Currently, only legacy charts library supports split chart aggregation.
Enables legacy charts library for area, line and bar charts in visualize.
[[visualization-colormapping]]`visualization:colorMapping`::
**This setting is deprecated and will not be supported as of 8.0.**

View file

@ -30,6 +30,9 @@ export interface BrushTriggerEvent {
type AllSeriesAccessors = Array<[accessor: Accessor | AccessorFn, value: string | number]>;
// TODO: replace when exported from elastic/charts
const DEFAULT_SINGLE_PANEL_SM_VALUE = '__ECH_DEFAULT_SINGLE_PANEL_SM_VALUE__';
/**
* returns accessor value from string or function accessor
* @param datum
@ -82,6 +85,29 @@ const getAllSplitAccessors = (
value,
]);
/**
* Gets value from small multiple accessors
*
* Only handles single small multiple accessor
*/
function getSplitChartValue({
smHorizontalAccessorValue,
smVerticalAccessorValue,
}: Pick<XYChartSeriesIdentifier, 'smHorizontalAccessorValue' | 'smVerticalAccessorValue'>):
| string
| number
| undefined {
if (smHorizontalAccessorValue !== DEFAULT_SINGLE_PANEL_SM_VALUE) {
return smHorizontalAccessorValue;
}
if (smVerticalAccessorValue !== DEFAULT_SINGLE_PANEL_SM_VALUE) {
return smVerticalAccessorValue;
}
return;
}
/**
* Reduces matching column indexes
*
@ -92,7 +118,8 @@ const getAllSplitAccessors = (
const columnReducer = (
xAccessor: Accessor | AccessorFn | null,
yAccessor: Accessor | AccessorFn | null,
splitAccessors: AllSeriesAccessors
splitAccessors: AllSeriesAccessors,
splitChartAccessor?: Accessor | AccessorFn
) => (
acc: Array<[index: number, id: string]>,
{ id }: Datatable['columns'][number],
@ -101,6 +128,7 @@ const columnReducer = (
if (
(xAccessor !== null && validateAccessorId(id, xAccessor)) ||
(yAccessor !== null && validateAccessorId(id, yAccessor)) ||
(splitChartAccessor !== undefined && validateAccessorId(id, splitChartAccessor)) ||
splitAccessors.some(([accessor]) => validateAccessorId(id, accessor))
) {
acc.push([index, id]);
@ -121,13 +149,18 @@ const rowFindPredicate = (
geometry: GeometryValue | null,
xAccessor: Accessor | AccessorFn | null,
yAccessor: Accessor | AccessorFn | null,
splitAccessors: AllSeriesAccessors
splitAccessors: AllSeriesAccessors,
splitChartAccessor?: Accessor | AccessorFn,
splitChartValue?: string | number
) => (row: Datatable['rows'][number]): boolean =>
(geometry === null ||
(xAccessor !== null &&
getAccessorValue(row, xAccessor) === geometry.x &&
yAccessor !== null &&
getAccessorValue(row, yAccessor) === geometry.y)) &&
getAccessorValue(row, yAccessor) === geometry.y &&
(splitChartAccessor === undefined ||
(splitChartValue !== undefined &&
getAccessorValue(row, splitChartAccessor) === splitChartValue)))) &&
[...splitAccessors].every(([accessor, value]) => getAccessorValue(row, accessor) === value);
/**
@ -142,19 +175,28 @@ export const getFilterFromChartClickEventFn = (
table: Datatable,
xAccessor: Accessor | AccessorFn,
splitSeriesAccessorFnMap?: Map<string | number, AccessorFn>,
splitChartAccessor?: Accessor | AccessorFn,
negate: boolean = false
) => (points: Array<[GeometryValue, XYChartSeriesIdentifier]>): ClickTriggerEvent => {
const data: ValueClickContext['data']['data'] = [];
points.forEach((point) => {
const [geometry, { yAccessor, splitAccessors }] = point;
const splitChartValue = getSplitChartValue(point[1]);
const allSplitAccessors = getAllSplitAccessors(splitAccessors, splitSeriesAccessorFnMap);
const columns = table.columns.reduce<Array<[index: number, id: string]>>(
columnReducer(xAccessor, yAccessor, allSplitAccessors),
columnReducer(xAccessor, yAccessor, allSplitAccessors, splitChartAccessor),
[]
);
const row = table.rows.findIndex(
rowFindPredicate(geometry, xAccessor, yAccessor, allSplitAccessors)
rowFindPredicate(
geometry,
xAccessor,
yAccessor,
allSplitAccessors,
splitChartAccessor,
splitChartValue
)
);
const newData = columns.map(([column, id]) => ({
table,
@ -179,16 +221,20 @@ export const getFilterFromChartClickEventFn = (
* Helper function to get filter action event from series
*/
export const getFilterFromSeriesFn = (table: Datatable) => (
{ splitAccessors }: XYChartSeriesIdentifier,
{ splitAccessors, ...rest }: XYChartSeriesIdentifier,
splitSeriesAccessorFnMap?: Map<string | number, AccessorFn>,
splitChartAccessor?: Accessor | AccessorFn,
negate = false
): ClickTriggerEvent => {
const splitChartValue = getSplitChartValue(rest);
const allSplitAccessors = getAllSplitAccessors(splitAccessors, splitSeriesAccessorFnMap);
const columns = table.columns.reduce<Array<[index: number, id: string]>>(
columnReducer(null, null, allSplitAccessors),
columnReducer(null, null, allSplitAccessors, splitChartAccessor),
[]
);
const row = table.rows.findIndex(rowFindPredicate(null, null, null, allSplitAccessors));
const row = table.rows.findIndex(
rowFindPredicate(null, null, null, allSplitAccessors, splitChartAccessor, splitChartValue)
);
const data: ValueClickContext['data']['data'] = columns.map(([column, id]) => ({
table,
column,

View file

@ -7,7 +7,7 @@
*/
import d3 from 'd3';
import _ from 'lodash';
import { isNumber, reduce, times } from 'lodash';
import moment from 'moment';
import { InvalidLogScaleValues } from '../../errors';
@ -62,7 +62,7 @@ export class AxisScale {
return d3[extent](
opts.reduce(function (opts, v) {
if (!_.isNumber(v)) v = +v;
if (!isNumber(v)) v = +v;
if (!isNaN(v)) opts.push(v);
return opts;
}, [])
@ -90,7 +90,7 @@ export class AxisScale {
const y = moment(x);
const method = n > 0 ? 'add' : 'subtract';
_.times(Math.abs(n), function () {
times(Math.abs(n), function () {
y[method](interval);
});
@ -100,7 +100,7 @@ export class AxisScale {
getAllPoints() {
const config = this.axisConfig;
const data = this.visConfig.data.chartData();
const chartPoints = _.reduce(
const chartPoints = reduce(
data,
(chartPoints, chart, chartIndex) => {
const points = chart.series.reduce((points, seri, seriIndex) => {
@ -254,6 +254,6 @@ export class AxisScale {
}
validateScale(scale) {
if (!scale || _.isNaN(scale)) throw new Error('scale is ' + scale);
if (!scale || Number.isNaN(scale)) throw new Error('scale is ' + scale);
}
}

View file

@ -0,0 +1,45 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* and the Server Side Public License, v 1; you may not use this file except in
* compliance with, at your election, the Elastic License or the Server Side
* Public License, v 1.
*/
import React from 'react';
import { Accessor, AccessorFn, GroupBy, GroupBySort, SmallMultiples } from '@elastic/charts';
interface ChartSplitterProps {
splitColumnAccessor?: Accessor | AccessorFn;
splitRowAccessor?: Accessor | AccessorFn;
sort?: GroupBySort;
}
const CHART_SPLITTER_ID = '__chart_splitter__';
export const ChartSplitter = ({
splitColumnAccessor,
splitRowAccessor,
sort,
}: ChartSplitterProps) =>
splitColumnAccessor || splitRowAccessor ? (
<>
<GroupBy
id={CHART_SPLITTER_ID}
by={(spec, datum) => {
const splitTypeAccessor = splitColumnAccessor || splitRowAccessor;
if (splitTypeAccessor) {
return typeof splitTypeAccessor === 'function'
? splitTypeAccessor(datum)
: datum[splitTypeAccessor];
}
return spec.id;
}}
sort={sort || 'dataIndex'}
/>
<SmallMultiples
splitVertically={splitRowAccessor ? CHART_SPLITTER_ID : undefined}
splitHorizontally={splitColumnAccessor ? CHART_SPLITTER_ID : undefined}
/>
</>
) : null;

View file

@ -16,19 +16,20 @@ import {
XYChartSeriesIdentifier,
} from '@elastic/charts';
import { BUCKET_TYPES } from '../../../data/public';
import { Aspects } from '../types';
import './_detailed_tooltip.scss';
import { fillEmptyValue } from '../utils/get_series_name_fn';
import { COMPLEX_SPLIT_ACCESSOR } from '../utils/accessors';
import { COMPLEX_SPLIT_ACCESSOR, isRangeAggType } from '../utils/accessors';
interface TooltipData {
label: string;
value: string;
}
// TODO: replace when exported from elastic/charts
const DEFAULT_SINGLE_PANEL_SM_VALUE = '__ECH_DEFAULT_SINGLE_PANEL_SM_VALUE__';
const getTooltipData = (
aspects: Aspects,
header: TooltipValue | null,
@ -37,10 +38,7 @@ const getTooltipData = (
const data: TooltipData[] = [];
if (header) {
const xFormatter =
aspects.x.aggType === BUCKET_TYPES.DATE_RANGE || aspects.x.aggType === BUCKET_TYPES.RANGE
? null
: aspects.x.formatter;
const xFormatter = isRangeAggType(aspects.x.aggType) ? null : aspects.x.formatter;
data.push({
label: aspects.x.title,
value: xFormatter ? xFormatter(header.value) : `${header.value}`,
@ -80,6 +78,28 @@ const getTooltipData = (
}
});
if (
aspects.splitColumn &&
valueSeries.smHorizontalAccessorValue !== undefined &&
valueSeries.smHorizontalAccessorValue !== DEFAULT_SINGLE_PANEL_SM_VALUE
) {
data.push({
label: aspects.splitColumn.title,
value: `${valueSeries.smHorizontalAccessorValue}`,
});
}
if (
aspects.splitRow &&
valueSeries.smVerticalAccessorValue !== undefined &&
valueSeries.smVerticalAccessorValue !== DEFAULT_SINGLE_PANEL_SM_VALUE
) {
data.push({
label: aspects.splitRow.title,
value: `${valueSeries.smVerticalAccessorValue}`,
});
}
return data;
};

View file

@ -11,4 +11,3 @@ export { XYEndzones } from './xy_endzones';
export { XYCurrentTime } from './xy_current_time';
export { XYSettings } from './xy_settings';
export { XYThresholdLine } from './xy_threshold_line';
export { SplitChartWarning } from './split_chart_warning';

View file

@ -1,44 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* and the Server Side Public License, v 1; you may not use this file except in
* compliance with, at your election, the Elastic License or the Server Side
* Public License, v 1.
*/
import React, { FC } from 'react';
import { EuiLink, EuiCallOut } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import { getDocLinks } from '../services';
export const SplitChartWarning: FC = () => {
const advancedSettingsLink = getDocLinks().links.management.visualizationSettings;
return (
<EuiCallOut
title={i18n.translate('visTypeXy.splitChartWarning.title', {
defaultMessage: 'Warning',
})}
color="warning"
iconType="help"
>
<FormattedMessage
id="visTypeXy.splitChartWarning.content"
defaultMessage="The new charts library does not support split chart aggregation. Please enable the {link} advanced setting to use split chart aggregation."
values={{
link: (
<EuiLink href={advancedSettingsLink} target="_blank" external>
<FormattedMessage
id="visTypeXy.splitChartWarning.link"
defaultMessage="Legacy charts library"
/>
</EuiLink>
),
}}
/>
</EuiCallOut>
);
};

View file

@ -29,7 +29,10 @@ export function getEmptyAspect(): Aspect {
},
};
}
export function getAspects(columns: DatatableColumn[], { x, y, z, series }: Dimensions): Aspects {
export function getAspects(
columns: DatatableColumn[],
{ x, y, z, series, splitColumn, splitRow }: Dimensions
): Aspects {
const seriesDimensions = Array.isArray(series) || series === undefined ? series : [series];
return {
@ -37,6 +40,8 @@ export function getAspects(columns: DatatableColumn[], { x, y, z, series }: Dime
y: getAspectsFromDimension(columns, y) ?? [],
z: z && z?.length > 0 ? getAspectsFromDimension(columns, z[0]) : undefined,
series: getAspectsFromDimension(columns, seriesDimensions),
splitColumn: splitColumn?.length ? getAspectsFromDimension(columns, splitColumn[0]) : undefined,
splitRow: splitRow?.length ? getAspectsFromDimension(columns, splitRow[0]) : undefined,
};
}

View file

@ -43,6 +43,8 @@ export interface Aspects {
y: Aspect[];
z?: Aspect;
series?: Aspect[];
splitColumn?: Aspect;
splitRow?: Aspect;
}
export interface AxisGrid {

View file

@ -26,11 +26,15 @@ const getFieldName = (fieldName: string, index?: number) => {
return `${fieldName}${indexStr}`;
};
export const isRangeAggType = (type: string | null) =>
type === BUCKET_TYPES.DATE_RANGE || type === BUCKET_TYPES.RANGE;
/**
* Returns accessor function for complex accessor types
* @param aspect
* @param isComplex - forces to be functional/complex accessor
*/
export const getComplexAccessor = (fieldName: string) => (
export const getComplexAccessor = (fieldName: string, isComplex: boolean = false) => (
aspect: Aspect,
index?: number
): Accessor | AccessorFn | undefined => {
@ -38,12 +42,7 @@ export const getComplexAccessor = (fieldName: string) => (
return;
}
if (
!(
(aspect.aggType === BUCKET_TYPES.DATE_RANGE || aspect.aggType === BUCKET_TYPES.RANGE) &&
aspect.formatter
)
) {
if (!((isComplex || isRangeAggType(aspect.aggType)) && aspect.formatter)) {
return aspect.accessor;
}
@ -51,7 +50,7 @@ export const getComplexAccessor = (fieldName: string) => (
const accessor = aspect.accessor;
const fn: AccessorFn = (d) => {
const v = d[accessor];
if (!v) {
if (v === undefined) {
return;
}
const f = formatter(v);

View file

@ -65,6 +65,7 @@ import {
getComplexAccessor,
getSplitSeriesAccessorFnMap,
} from './utils/accessors';
import { ChartSplitter } from './chart_splitter';
export interface VisComponentProps {
visParams: VisParams;
@ -117,7 +118,8 @@ const VisComponent = (props: VisComponentProps) => {
(
visData: Datatable,
xAccessor: Accessor | AccessorFn,
splitSeriesAccessors: Array<Accessor | AccessorFn>
splitSeriesAccessors: Array<Accessor | AccessorFn>,
splitChartAccessor?: Accessor | AccessorFn
): ElementClickListener => {
const splitSeriesAccessorFnMap = getSplitSeriesAccessorFnMap(splitSeriesAccessors);
return (elements) => {
@ -125,7 +127,8 @@ const VisComponent = (props: VisComponentProps) => {
const event = getFilterFromChartClickEventFn(
visData,
xAccessor,
splitSeriesAccessorFnMap
splitSeriesAccessorFnMap,
splitChartAccessor
)(elements as XYChartElementEvent[]);
props.fireEvent(event);
}
@ -154,12 +157,17 @@ const VisComponent = (props: VisComponentProps) => {
(
visData: Datatable,
xAccessor: Accessor | AccessorFn,
splitSeriesAccessors: Array<Accessor | AccessorFn>
splitSeriesAccessors: Array<Accessor | AccessorFn>,
splitChartAccessor?: Accessor | AccessorFn
) => {
const splitSeriesAccessorFnMap = getSplitSeriesAccessorFnMap(splitSeriesAccessors);
return (series: XYChartSeriesIdentifier): ClickTriggerEvent | null => {
if (xAccessor !== null) {
return getFilterFromSeriesFn(visData)(series, splitSeriesAccessorFnMap);
return getFilterFromSeriesFn(visData)(
series,
splitSeriesAccessorFnMap,
splitChartAccessor
);
}
return null;
@ -304,6 +312,12 @@ const VisComponent = (props: VisComponentProps) => {
: [],
[config.aspects.series]
);
const splitChartColumnAccessor = config.aspects.splitColumn
? getComplexAccessor(COMPLEX_SPLIT_ACCESSOR, true)(config.aspects.splitColumn)
: undefined;
const splitChartRowAccessor = config.aspects.splitRow
? getComplexAccessor(COMPLEX_SPLIT_ACCESSOR, true)(config.aspects.splitRow)
: undefined;
const renderSeries = useMemo(
() =>
@ -336,6 +350,10 @@ const VisComponent = (props: VisComponentProps) => {
legendPosition={legendPosition}
/>
<Chart size="100%">
<ChartSplitter
splitColumnAccessor={splitChartColumnAccessor}
splitRowAccessor={splitChartRowAccessor}
/>
<XYSettings
{...config}
showLegend={showLegend}
@ -343,14 +361,24 @@ const VisComponent = (props: VisComponentProps) => {
xDomain={xDomain}
adjustedXDomain={adjustedXDomain}
legendColorPicker={useColorPicker(legendPosition, setColor, getSeriesName)}
onElementClick={handleFilterClick(visData, xAccessor, splitSeriesAccessors)}
onElementClick={handleFilterClick(
visData,
xAccessor,
splitSeriesAccessors,
splitChartColumnAccessor ?? splitChartRowAccessor
)}
onBrushEnd={handleBrush(visData, xAccessor, 'interval' in config.aspects.x.params)}
onRenderChange={onRenderChange}
legendAction={
config.aspects.series && (config.aspects.series?.length ?? 0) > 0
? getLegendActions(
canFilter,
getFilterEventData(visData, xAccessor, splitSeriesAccessors),
getFilterEventData(
visData,
xAccessor,
splitSeriesAccessors,
splitChartColumnAccessor ?? splitChartRowAccessor
),
handleFilterAction,
getSeriesName
)

View file

@ -16,7 +16,6 @@ import { VisualizationContainer } from '../../visualizations/public';
import type { PersistedState } from '../../visualizations/public';
import { XyVisType } from '../common';
import { SplitChartWarning } from './components/split_chart_warning';
import { VisComponentType } from './vis_component';
import { RenderValue, visName } from './xy_vis_fn';
@ -36,24 +35,20 @@ export const xyVisRenderer: ExpressionRenderDefinition<RenderValue> = {
reuseDomNode: true,
render: async (domNode, { visData, visConfig, visType, syncColors }, handlers) => {
const showNoResult = shouldShowNoResultsMessage(visData, visType);
const isSplitChart = Boolean(visConfig.dimensions.splitRow);
handlers.onDestroy(() => unmountComponentAtNode(domNode));
render(
<I18nProvider>
<>
{isSplitChart && <SplitChartWarning />}
<VisualizationContainer handlers={handlers} showNoResult={showNoResult || isSplitChart}>
<VisComponent
visParams={visConfig}
visData={visData}
renderComplete={handlers.done}
fireEvent={handlers.event}
uiState={handlers.uiState as PersistedState}
syncColors={syncColors}
/>
</VisualizationContainer>
</>
<VisualizationContainer handlers={handlers} showNoResult={showNoResult}>
<VisComponent
visParams={visConfig}
visData={visData}
renderComplete={handlers.done}
fireEvent={handlers.event}
uiState={handlers.uiState as PersistedState}
syncColors={syncColors}
/>
</VisualizationContainer>
</I18nProvider>,
domNode
);

View file

@ -6,8 +6,6 @@
* Public License, v 1.
*/
import React from 'react';
import { i18n } from '@kbn/i18n';
// @ts-ignore
import { euiPaletteColorBlind } from '@elastic/eui/lib/services';
@ -30,7 +28,6 @@ import { toExpressionAst } from '../to_ast';
import { ChartType } from '../../common';
import { getConfigCollections } from '../editor/collections';
import { getOptionTabs } from '../editor/common_config';
import { SplitTooltip } from './split_tooltip';
export const getAreaVisTypeDefinition = (
showElasticChartsOptions = false
@ -181,12 +178,6 @@ export const getAreaVisTypeDefinition = (
min: 0,
max: 1,
aggFilter: ['!geohash_grid', '!geotile_grid', '!filter'],
// TODO: Remove when split chart aggs are supported
// https://github.com/elastic/kibana/issues/82496
...(showElasticChartsOptions && {
disabled: true,
tooltip: <SplitTooltip />,
}),
},
],
},

View file

@ -6,8 +6,6 @@
* Public License, v 1.
*/
import React from 'react';
import { i18n } from '@kbn/i18n';
// @ts-ignore
import { euiPaletteColorBlind } from '@elastic/eui/lib/services';
@ -30,7 +28,6 @@ import { ChartType } from '../../common';
import { getConfigCollections } from '../editor/collections';
import { getOptionTabs } from '../editor/common_config';
import { defaultCountLabel, LabelRotation } from '../../../charts/public';
import { SplitTooltip } from './split_tooltip';
export const getHistogramVisTypeDefinition = (
showElasticChartsOptions = false
@ -184,12 +181,6 @@ export const getHistogramVisTypeDefinition = (
min: 0,
max: 1,
aggFilter: ['!geohash_grid', '!geotile_grid', '!filter'],
// TODO: Remove when split chart aggs are supported
// https://github.com/elastic/kibana/issues/82496
...(showElasticChartsOptions && {
disabled: true,
tooltip: <SplitTooltip />,
}),
},
],
},

View file

@ -6,8 +6,6 @@
* Public License, v 1.
*/
import React from 'react';
import { i18n } from '@kbn/i18n';
// @ts-ignore
import { euiPaletteColorBlind } from '@elastic/eui/lib/services';
@ -30,7 +28,6 @@ import { ChartType } from '../../common';
import { getConfigCollections } from '../editor/collections';
import { getOptionTabs } from '../editor/common_config';
import { defaultCountLabel, LabelRotation } from '../../../charts/public';
import { SplitTooltip } from './split_tooltip';
export const getHorizontalBarVisTypeDefinition = (
showElasticChartsOptions = false
@ -183,12 +180,6 @@ export const getHorizontalBarVisTypeDefinition = (
min: 0,
max: 1,
aggFilter: ['!geohash_grid', '!geotile_grid', '!filter'],
// TODO: Remove when split chart aggs are supported
// https://github.com/elastic/kibana/issues/82496
...(showElasticChartsOptions && {
disabled: true,
tooltip: <SplitTooltip />,
}),
},
],
},

View file

@ -6,8 +6,6 @@
* Public License, v 1.
*/
import React from 'react';
import { i18n } from '@kbn/i18n';
// @ts-ignore
import { euiPaletteColorBlind } from '@elastic/eui/lib/services';
@ -30,7 +28,6 @@ import { toExpressionAst } from '../to_ast';
import { ChartType } from '../../common';
import { getConfigCollections } from '../editor/collections';
import { getOptionTabs } from '../editor/common_config';
import { SplitTooltip } from './split_tooltip';
export const getLineVisTypeDefinition = (
showElasticChartsOptions = false
@ -175,12 +172,6 @@ export const getLineVisTypeDefinition = (
min: 0,
max: 1,
aggFilter: ['!geohash_grid', '!geotile_grid', '!filter'],
// TODO: Remove when split chart aggs are supported
// https://github.com/elastic/kibana/issues/82496
...(showElasticChartsOptions && {
disabled: true,
tooltip: <SplitTooltip />,
}),
},
],
},

View file

@ -1,20 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* and the Server Side Public License, v 1; you may not use this file except in
* compliance with, at your election, the Elastic License or the Server Side
* Public License, v 1.
*/
import React from 'react';
import { FormattedMessage } from '@kbn/i18n/react';
export function SplitTooltip() {
return (
<FormattedMessage
id="visTypeXy.splitTitle.tooltip"
defaultMessage="Split chart aggregation is not supported with the new charts library. Please enable the legacy charts library advanced setting to use split chart aggregation."
/>
);
}

View file

@ -24,8 +24,7 @@ export const uiSettingsConfig: Record<string, UiSettingsParams<boolean>> = {
description: i18n.translate(
'visTypeXy.advancedSettings.visualization.legacyChartsLibrary.description',
{
defaultMessage:
'Enables legacy charts library for area, line and bar charts in visualize. Currently, only legacy charts library supports split chart aggregation.',
defaultMessage: 'Enables legacy charts library for area, line and bar charts in visualize.',
}
),
category: ['visualization'],

View file

@ -176,8 +176,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
await PageObjects.visEditor.changeYAxisFilterLabelsCheckbox(axisId, false);
await PageObjects.visEditor.clickGo();
const labels = await PageObjects.visChart.getYAxisLabelsAsNumbers();
const minLabel = 2;
const maxLabel = 5000;
const minLabel = await PageObjects.visChart.getExpectedValue(2, 1);
const maxLabel = await PageObjects.visChart.getExpectedValue(5000, 7000);
const numberOfLabels = 10;
expect(labels.length).to.be.greaterThan(numberOfLabels);
expect(labels[0]).to.eql(minLabel);
@ -188,8 +188,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
await PageObjects.visEditor.changeYAxisFilterLabelsCheckbox(axisId, true);
await PageObjects.visEditor.clickGo();
const labels = await PageObjects.visChart.getYAxisLabelsAsNumbers();
const minLabel = 2;
const maxLabel = 5000;
const minLabel = await PageObjects.visChart.getExpectedValue(2, 1);
const maxLabel = await PageObjects.visChart.getExpectedValue(5000, 7000);
const numberOfLabels = 10;
expect(labels.length).to.be.greaterThan(numberOfLabels);
expect(labels[0]).to.eql(minLabel);
@ -201,7 +201,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
await PageObjects.visEditor.changeYAxisFilterLabelsCheckbox(axisId, false);
await PageObjects.visEditor.clickGo();
const labels = await PageObjects.visChart.getYAxisLabels();
const expectedLabels = ['0', '2,000', '4,000', '6,000', '8,000', '10,000'];
const expectedLabels = await PageObjects.visChart.getExpectedValue(
['0', '2,000', '4,000', '6,000', '8,000', '10,000'],
['0', '1,000', '2,000', '3,000', '4,000', '5,000', '6,000', '7,000', '8,000', '9,000']
);
expect(labels).to.eql(expectedLabels);
});
@ -210,7 +213,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
await PageObjects.visEditor.changeYAxisFilterLabelsCheckbox(axisId, true);
await PageObjects.visEditor.clickGo();
const labels = await PageObjects.visChart.getYAxisLabels();
const expectedLabels = ['2,000', '4,000', '6,000', '8,000'];
const expectedLabels = await PageObjects.visChart.getExpectedValue(
['2,000', '4,000', '6,000', '8,000'],
['0', '1,000', '2,000', '3,000', '4,000', '5,000', '6,000', '7,000', '8,000', '9,000']
);
expect(labels).to.eql(expectedLabels);
});
@ -220,7 +226,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
await PageObjects.visEditor.clickGo();
const labels = await PageObjects.visChart.getYAxisLabels();
log.debug(labels);
const expectedLabels = ['0', '2,000', '4,000', '6,000', '8,000', '10,000'];
const expectedLabels = await PageObjects.visChart.getExpectedValue(
['0', '2,000', '4,000', '6,000', '8,000', '10,000'],
['0', '1,000', '2,000', '3,000', '4,000', '5,000', '6,000', '7,000', '8,000', '9,000']
);
expect(labels).to.eql(expectedLabels);
});
@ -228,7 +237,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
await PageObjects.visEditor.changeYAxisFilterLabelsCheckbox(axisId, true);
await PageObjects.visEditor.clickGo();
const labels = await PageObjects.visChart.getYAxisLabels();
const expectedLabels = ['2,000', '4,000', '6,000', '8,000'];
const expectedLabels = await PageObjects.visChart.getExpectedValue(
['2,000', '4,000', '6,000', '8,000'],
['0', '1,000', '2,000', '3,000', '4,000', '5,000', '6,000', '7,000', '8,000', '9,000']
);
expect(labels).to.eql(expectedLabels);
});
});

View file

@ -52,6 +52,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) {
// Test replaced vislib chart types
loadTestFile(require.resolve('./_area_chart'));
loadTestFile(require.resolve('./_line_chart_split_series'));
loadTestFile(require.resolve('./_line_chart_split_chart'));
loadTestFile(require.resolve('./_point_series_options'));
loadTestFile(require.resolve('./_vertical_bar_chart'));
loadTestFile(require.resolve('./_vertical_bar_chart_nontimeindex'));