mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[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:
parent
c1175f971a
commit
719d680c9d
11 changed files with 38 additions and 83 deletions
|
@ -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());
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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={
|
||||
|
|
|
@ -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 &&
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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({
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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": "アラート",
|
||||
|
|
|
@ -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": "告警",
|
||||
|
|
|
@ -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 () => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue