[Lens] Allow value labels on histogram and stacked charts (#143635)

* allow value labels on histogram and stacked charts

* fix tests

* fix test

Co-authored-by: Stratoula Kalafateli <efstratia.kalafateli@elastic.co>
This commit is contained in:
Joe Reuter 2022-10-20 14:25:54 +02:00 committed by GitHub
parent c1175f971a
commit 719d680c9d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 38 additions and 83 deletions

View file

@ -77,14 +77,10 @@ export const errors = {
i18n.translate('expressionXY.reusable.function.xyVis.errors.notUsedFillOpacityError', {
defaultMessage: '`fillOpacity` argument is applicable only for area charts.',
}),
valueLabelsForNotBarsOrHistogramBarsChartsError: () =>
i18n.translate(
'expressionXY.reusable.function.xyVis.errors.valueLabelsForNotBarsOrHistogramBarsChartsError',
{
defaultMessage:
'`valueLabels` argument is applicable only for bar charts, which are not histograms.',
}
),
valueLabelsForNotBarsChartsError: () =>
i18n.translate('expressionXY.reusable.function.xyVis.errors.valueLabelsForNotBarChartsError', {
defaultMessage: '`valueLabels` argument is applicable only for bar charts.',
}),
dataBoundsForNotLineChartError: () =>
i18n.translate('expressionXY.reusable.function.xyVis.errors.dataBoundsForNotLineChartError', {
defaultMessage: 'Only line charts can be fit to the data bounds',
@ -127,10 +123,6 @@ export const hasBarLayer = (layers: Array<DataLayerConfigResult | CommonXYDataLa
export const hasAreaLayer = (layers: Array<DataLayerConfigResult | CommonXYDataLayerConfig>) =>
layers.some(({ seriesType }) => seriesType === SeriesTypes.AREA);
export const hasHistogramBarLayer = (
layers: Array<DataLayerConfigResult | CommonXYDataLayerConfig>
) => layers.some(({ seriesType, isHistogram }) => seriesType === SeriesTypes.BAR && isHistogram);
export const isValidExtentWithCustomMode = (extent: AxisExtentConfigResult) => {
const isValidLowerBound =
extent.lowerBound === undefined || (extent.lowerBound !== undefined && extent.lowerBound <= 0);
@ -212,13 +204,9 @@ export const validateFillOpacity = (fillOpacity: number | undefined, hasArea: bo
}
};
export const validateValueLabels = (
valueLabels: ValueLabelMode,
hasBar: boolean,
hasNotHistogramBars: boolean
) => {
if ((!hasBar || !hasNotHistogramBars) && valueLabels !== ValueLabelModes.HIDE) {
throw new Error(errors.valueLabelsForNotBarsOrHistogramBarsChartsError());
export const validateValueLabels = (valueLabels: ValueLabelMode, hasBar: boolean) => {
if (!hasBar && valueLabels !== ValueLabelModes.HIDE) {
throw new Error(errors.valueLabelsForNotBarsChartsError());
}
};

View file

@ -15,7 +15,6 @@ import { DataLayerConfigResult, XYLayerConfig, XyVisFn, XYArgs } from '../types'
import {
hasAreaLayer,
hasBarLayer,
hasHistogramBarLayer,
validateExtents,
validateFillOpacity,
validateMarkSizeRatioLimits,
@ -112,9 +111,7 @@ export const xyVisFn: XyVisFn['fn'] = async (data, args, handlers) => {
validateAddTimeMarker(dataLayers, args.addTimeMarker);
validateMinTimeBarInterval(dataLayers, hasBar, args.minTimeBarInterval);
const hasNotHistogramBars = !hasHistogramBarLayer(dataLayers);
validateValueLabels(args.valueLabels, hasBar, hasNotHistogramBars);
validateValueLabels(args.valueLabels, hasBar);
validateMarkSizeRatioWithAccessor(args.markSizeRatio, dataLayers[0].markSizeAccessor);
validateMarkSizeRatioLimits(args.markSizeRatio);
validateLineWidthForChartType(lineWidth, args.seriesType);

View file

@ -5119,7 +5119,7 @@ exports[`XYChart component it renders stacked area 1`] = `
"getAll": [Function],
}
}
shouldShowValueLabels={false}
shouldShowValueLabels={true}
syncColors={false}
timeZone="UTC"
titles={
@ -6101,7 +6101,7 @@ exports[`XYChart component it renders stacked bar 1`] = `
"getAll": [Function],
}
}
shouldShowValueLabels={false}
shouldShowValueLabels={true}
syncColors={false}
timeZone="UTC"
titles={
@ -7083,7 +7083,7 @@ exports[`XYChart component it renders stacked horizontal bar 1`] = `
"getAll": [Function],
}
}
shouldShowValueLabels={false}
shouldShowValueLabels={true}
syncColors={false}
timeZone="UTC"
titles={

View file

@ -523,12 +523,7 @@ export function XYChart({
};
};
const shouldShowValueLabels = uiState
? valueLabels !== ValueLabelModes.HIDE
: // No stacked bar charts
dataLayers.every((layer) => !layer.isStacked) &&
// No histogram charts
!isHistogramViz;
const shouldShowValueLabels = !uiState || valueLabels !== ValueLabelModes.HIDE;
const valueLabelsStyling =
shouldShowValueLabels &&

View file

@ -7,7 +7,7 @@
import React, { FC } from 'react';
import { i18n } from '@kbn/i18n';
import { EuiButtonGroup, EuiFormRow } from '@elastic/eui';
import { EuiButtonGroup, EuiFormRow, EuiIconTip } from '@elastic/eui';
import { ValueLabelConfig } from '../../common/types';
const valueLabelsOptions: Array<{
@ -54,7 +54,26 @@ export const ValueLabelsSettings: FC<VisualOptionsProps> = ({
const isSelected =
valueLabelsOptions.find(({ value }) => value === valueLabels)?.id || 'value_labels_hide';
return (
<EuiFormRow display="columnCompressed" label={<span>{label}</span>}>
<EuiFormRow
display="columnCompressed"
label={
<span>
{label}{' '}
<EuiIconTip
color="subdued"
content={i18n.translate('xpack.lens.shared.chartValueLabelVisibilityTooltip', {
defaultMessage: 'If there is not enough space, value labels might be hidden',
})}
iconProps={{
className: 'eui-alignTop',
}}
position="top"
size="s"
type="questionInCircle"
/>
</span>
}
>
<EuiButtonGroup
isFullWidth
legend={label}

View file

@ -55,11 +55,7 @@ export const VisualOptionsPopover: React.FC<VisualOptionsPopoverProps> = ({
);
const hasNonBarSeries = dataLayers.some(({ seriesType }) =>
['area_stacked', 'area', 'line'].includes(seriesType)
);
const hasBarNotStacked = dataLayers.some(({ seriesType }) =>
['bar', 'bar_horizontal'].includes(seriesType)
['area_stacked', 'area', 'line', 'area_percentage_stacked'].includes(seriesType)
);
const hasAreaSeries = dataLayers.some(({ seriesType }) =>
@ -68,8 +64,8 @@ export const VisualOptionsPopover: React.FC<VisualOptionsPopoverProps> = ({
const isHistogramSeries = Boolean(hasHistogramSeries(dataLayers, datasourceLayers));
const isValueLabelsEnabled = !hasNonBarSeries && hasBarNotStacked && !isHistogramSeries;
const isFittingEnabled = hasNonBarSeries;
const isValueLabelsEnabled = !hasNonBarSeries;
const isFittingEnabled = hasNonBarSeries && !isAreaPercentage;
const isCurveTypeEnabled = hasNonBarSeries || isAreaPercentage;
const valueLabelsDisabledReason = getValueLabelDisableReason({

View file

@ -8,7 +8,7 @@
import React from 'react';
import { shallowWithIntl as shallow } from '@kbn/test-jest-helpers';
import { Position } from '@elastic/charts';
import type { FramePublicAPI, DatasourcePublicAPI } from '../../../../types';
import type { FramePublicAPI } from '../../../../types';
import { createMockDatasource, createMockFramePublicAPI } from '../../../../mocks';
import { State, XYLayerConfig } from '../../types';
import { VisualOptionsPopover } from '.';
@ -44,21 +44,6 @@ describe('Visual options popover', () => {
first: createMockDatasource('test').publicAPIMock,
};
});
it('should disable the visual options for stacked bar charts', () => {
const state = testState();
const component = shallow(
<VisualOptionsPopover
datasourceLayers={frame.datasourceLayers}
setState={jest.fn()}
state={{
...state,
layers: [{ ...state.layers[0], seriesType: 'bar_stacked' } as XYLayerConfig],
}}
/>
);
expect(component.find(ToolbarPopover).prop('isDisabled')).toEqual(true);
});
it('should disable the values and fitting for percentage area charts', () => {
const state = testState();
@ -109,28 +94,6 @@ describe('Visual options popover', () => {
expect(component.find(ToolbarPopover).prop('isDisabled')).toEqual(false);
});
it('should disabled the popover if there is histogram series', () => {
// make it detect an histogram series
const datasourceLayers = frame.datasourceLayers as Record<string, DatasourcePublicAPI>;
datasourceLayers.first.getOperationForColumnId = jest.fn().mockReturnValueOnce({
isBucketed: true,
scale: 'interval',
});
const state = testState();
const component = shallow(
<VisualOptionsPopover
datasourceLayers={frame.datasourceLayers}
setState={jest.fn()}
state={{
...state,
layers: [{ ...state.layers[0] }],
}}
/>
);
expect(component.find(ToolbarPopover).prop('isDisabled')).toEqual(true);
});
it('should hide the fitting option for bar series', () => {
const state = testState();
const component = shallow(

View file

@ -2729,7 +2729,6 @@
"expressionXY.reusable.function.xyVis.errors.pointsRadiusForNonLineOrAreaChartError": "\"pointsRadius\" peut être appliqué uniquement aux graphiques linéaires ou aux graphiques en aires",
"expressionXY.reusable.function.xyVis.errors.showPointsForNonLineOrAreaChartError": "\"showPoints\" peut être appliqué uniquement aux graphiques linéaires ou aux graphiques en aires",
"expressionXY.reusable.function.xyVis.errors.timeMarkerForNotTimeChartsError": "Seuls les graphiques temporels peuvent avoir un repère de temps actuel",
"expressionXY.reusable.function.xyVis.errors.valueLabelsForNotBarsOrHistogramBarsChartsError": "L'argument \"valueLabels\" s'applique uniquement aux graphiques à barres qui ne sont pas des histogrammes.",
"expressionXY.xAxisConfigFn.help": "Configurer la config de l'axe x du graphique xy",
"expressionXY.xyChart.emptyXLabel": "(vide)",
"expressionXY.xyChart.iconSelect.alertIconLabel": "Alerte",

View file

@ -2725,7 +2725,6 @@
"expressionXY.reusable.function.xyVis.errors.pointsRadiusForNonLineOrAreaChartError": "pointsRadiusは折れ線グラフまたは面グラフでのみ適用できます。",
"expressionXY.reusable.function.xyVis.errors.showPointsForNonLineOrAreaChartError": "showPointsは折れ線グラフまたは面グラフでのみ適用できます。",
"expressionXY.reusable.function.xyVis.errors.timeMarkerForNotTimeChartsError": "現在時刻マーカーを設定できるのは、時系列グラフのみです",
"expressionXY.reusable.function.xyVis.errors.valueLabelsForNotBarsOrHistogramBarsChartsError": "valueLabels引数は棒グラフでのみ適用できます。これはヒストグラフではありません。",
"expressionXY.xAxisConfigFn.help": "xyグラフのx軸設定を構成",
"expressionXY.xyChart.emptyXLabel": "(空)",
"expressionXY.xyChart.iconSelect.alertIconLabel": "アラート",

View file

@ -2729,7 +2729,6 @@
"expressionXY.reusable.function.xyVis.errors.pointsRadiusForNonLineOrAreaChartError": "`pointsRadius` 仅适用于折线图或面积图",
"expressionXY.reusable.function.xyVis.errors.showPointsForNonLineOrAreaChartError": "`showPoints` 仅适用于折线图或面积图",
"expressionXY.reusable.function.xyVis.errors.timeMarkerForNotTimeChartsError": "仅时间图表可以具有当前时间标记",
"expressionXY.reusable.function.xyVis.errors.valueLabelsForNotBarsOrHistogramBarsChartsError": "`valueLabels` 参数仅适用于条形图,它们并非直方图。",
"expressionXY.xAxisConfigFn.help": "配置 xy 图表的 x 轴配置",
"expressionXY.xyChart.emptyXLabel": "(空)",
"expressionXY.xyChart.iconSelect.alertIconLabel": "告警",

View file

@ -263,7 +263,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
// check for value labels
data = await PageObjects.lens.getCurrentChartDebugState('xyVisChart');
expect(data?.bars?.[0].labels.length).to.eql(0);
expect(data?.bars?.[0].labels).not.to.eql(0);
});
it('should override axis title', async () => {