diff --git a/src/plugins/chart_expressions/expression_xy/common/__mocks__/index.ts b/src/plugins/chart_expressions/expression_xy/common/__mocks__/index.ts index 8b468c7196fab..3c71b238d64b2 100644 --- a/src/plugins/chart_expressions/expression_xy/common/__mocks__/index.ts +++ b/src/plugins/chart_expressions/expression_xy/common/__mocks__/index.ts @@ -87,6 +87,7 @@ export const createArgsWithLayers = ( layers: DataLayerConfig | DataLayerConfig[] = sampleLayer ): XYProps => ({ showTooltip: true, + minBarHeight: 1, legend: { type: 'legendConfig', isVisible: false, diff --git a/src/plugins/chart_expressions/expression_xy/common/expression_functions/common_xy_args.ts b/src/plugins/chart_expressions/expression_xy/common/expression_functions/common_xy_args.ts index 799dc12b1ea5b..6f2d8addc8f79 100644 --- a/src/plugins/chart_expressions/expression_xy/common/expression_functions/common_xy_args.ts +++ b/src/plugins/chart_expressions/expression_xy/common/expression_functions/common_xy_args.ts @@ -103,4 +103,8 @@ export const commonXYArgs: CommonXYFn['args'] = { types: ['string'], help: strings.getMinTimeBarIntervalHelp(), }, + minBarHeight: { + types: ['number'], + help: strings.getMinBarHeightHelp(), + }, }; diff --git a/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis_fn.ts b/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis_fn.ts index cf1325f09bf22..cef6b837acc17 100644 --- a/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis_fn.ts +++ b/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis_fn.ts @@ -55,6 +55,7 @@ export const layeredXyVisFn: LayeredXyVisFn['fn'] = async (data, args, handlers) args: { ...args, layers, + minBarHeight: args.minBarHeight ?? 1, markSizeRatio: hasMarkSizeAccessors && !args.markSizeRatio ? 10 : args.markSizeRatio, ariaLabel: args.ariaLabel ?? diff --git a/src/plugins/chart_expressions/expression_xy/common/expression_functions/validate.ts b/src/plugins/chart_expressions/expression_xy/common/expression_functions/validate.ts index efdbe7e2d0088..9f072c6ca4592 100644 --- a/src/plugins/chart_expressions/expression_xy/common/expression_functions/validate.ts +++ b/src/plugins/chart_expressions/expression_xy/common/expression_functions/validate.ts @@ -109,6 +109,11 @@ export const errors = { defaultMessage: '`minTimeBarInterval` argument is applicable only for time bar charts.', } ), + invalidMinBarHeightError: () => + i18n.translate('expressionXY.reusable.function.xyVis.errors.invalidMinBarHeightError', { + defaultMessage: + 'The min bar height should be a positive integer, representing pixel height of the bar.', + }), axisIsNotAssignedError: (axisId: string) => i18n.translate('expressionXY.reusable.function.xyVis.errors.axisIsNotAssignedError', { defaultMessage: @@ -297,3 +302,9 @@ export const validateMinTimeBarInterval = ( } } }; + +export const validateMinBarHeight = (minBarHeight?: number) => { + if (minBarHeight !== undefined && minBarHeight < 0) { + throw new Error(errors.invalidMinBarHeightError()); + } +}; diff --git a/src/plugins/chart_expressions/expression_xy/common/expression_functions/xy_vis_fn.ts b/src/plugins/chart_expressions/expression_xy/common/expression_functions/xy_vis_fn.ts index 03df575b3c653..47705a3fd7c12 100644 --- a/src/plugins/chart_expressions/expression_xy/common/expression_functions/xy_vis_fn.ts +++ b/src/plugins/chart_expressions/expression_xy/common/expression_functions/xy_vis_fn.ts @@ -28,6 +28,7 @@ import { validatePointsRadiusForChartType, validateLinesVisibilityForChartType, validateAxes, + validateMinBarHeight, } from './validate'; import { logDatatable } from '../utils'; @@ -111,6 +112,7 @@ export const xyVisFn: XyVisFn['fn'] = async (data, args, handlers) => { validateFillOpacity(args.fillOpacity, hasArea); validateAddTimeMarker(dataLayers, args.addTimeMarker); validateMinTimeBarInterval(dataLayers, hasBar, args.minTimeBarInterval); + validateMinBarHeight(args.minBarHeight); validateValueLabels(args.valueLabels, hasBar); validateMarkSizeRatioWithAccessor(args.markSizeRatio, dataLayers[0].markSizeAccessor); @@ -127,6 +129,7 @@ export const xyVisFn: XyVisFn['fn'] = async (data, args, handlers) => { args: { ...restArgs, layers, + minBarHeight: args.minBarHeight ?? 1, markSizeRatio: dataLayers[0].markSizeAccessor && !args.markSizeRatio ? 10 : args.markSizeRatio, ariaLabel: diff --git a/src/plugins/chart_expressions/expression_xy/common/i18n/index.tsx b/src/plugins/chart_expressions/expression_xy/common/i18n/index.tsx index 2446a27e718ce..8eecd2cb1a421 100644 --- a/src/plugins/chart_expressions/expression_xy/common/i18n/index.tsx +++ b/src/plugins/chart_expressions/expression_xy/common/i18n/index.tsx @@ -121,6 +121,10 @@ export const strings = { i18n.translate('expressionXY.xyVis.xAxisInterval.help', { defaultMessage: 'Specifies the min interval for time bar chart', }), + getMinBarHeightHelp: () => + i18n.translate('expressionXY.xyVis.minBarHeight.help', { + defaultMessage: 'Specifies the min bar height in pixels for bar chart', + }), getSplitColumnAccessorHelp: () => i18n.translate('expressionXY.xyVis.splitColumnAccessor.help', { defaultMessage: 'Specifies split column of the xy chart', diff --git a/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts b/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts index a81128f6e74a7..95f75d1d820b2 100644 --- a/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts +++ b/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts @@ -233,6 +233,7 @@ export interface XYArgs extends DataLayerArgs { addTimeMarker?: boolean; markSizeRatio?: number; minTimeBarInterval?: string; + minBarHeight?: number; splitRowAccessor?: ExpressionValueVisDimension | string; splitColumnAccessor?: ExpressionValueVisDimension | string; detailedTooltip?: boolean; @@ -284,6 +285,7 @@ export interface LayeredXYArgs { addTimeMarker?: boolean; markSizeRatio?: number; minTimeBarInterval?: string; + minBarHeight?: number; orderBucketsBySum?: boolean; showTooltip: boolean; splitRowAccessor?: ExpressionValueVisDimension | string; @@ -307,6 +309,7 @@ export interface XYProps { addTimeMarker?: boolean; markSizeRatio?: number; minTimeBarInterval?: string; + minBarHeight: number; splitRowAccessor?: ExpressionValueVisDimension | string; splitColumnAccessor?: ExpressionValueVisDimension | string; detailedTooltip?: boolean; diff --git a/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap b/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap index 0bbb116f29f23..24f630df2ff45 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap +++ b/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap @@ -1200,6 +1200,7 @@ exports[`XYChart component it renders area 1`] = ` }, ] } + minBarHeight={1} paletteService={ Object { "get": [Function], @@ -2210,6 +2211,7 @@ exports[`XYChart component it renders bar 1`] = ` }, ] } + minBarHeight={1} paletteService={ Object { "get": [Function], @@ -3220,6 +3222,7 @@ exports[`XYChart component it renders horizontal bar 1`] = ` }, ] } + minBarHeight={1} paletteService={ Object { "get": [Function], @@ -4230,6 +4233,7 @@ exports[`XYChart component it renders line 1`] = ` }, ] } + minBarHeight={1} paletteService={ Object { "get": [Function], @@ -5240,6 +5244,7 @@ exports[`XYChart component it renders stacked area 1`] = ` }, ] } + minBarHeight={1} paletteService={ Object { "get": [Function], @@ -6250,6 +6255,7 @@ exports[`XYChart component it renders stacked bar 1`] = ` }, ] } + minBarHeight={1} paletteService={ Object { "get": [Function], @@ -7260,6 +7266,7 @@ exports[`XYChart component it renders stacked horizontal bar 1`] = ` }, ] } + minBarHeight={1} paletteService={ Object { "get": [Function], @@ -8496,6 +8503,7 @@ exports[`XYChart component split chart should render split chart if both, splitR }, ] } + minBarHeight={1} paletteService={ Object { "get": [Function], @@ -9739,6 +9747,7 @@ exports[`XYChart component split chart should render split chart if splitColumnA }, ] } + minBarHeight={1} paletteService={ Object { "get": [Function], @@ -10980,6 +10989,7 @@ exports[`XYChart component split chart should render split chart if splitRowAcce }, ] } + minBarHeight={1} paletteService={ Object { "get": [Function], diff --git a/src/plugins/chart_expressions/expression_xy/public/components/data_layers.tsx b/src/plugins/chart_expressions/expression_xy/public/components/data_layers.tsx index cc6e969a10af9..c5223a270eadd 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/data_layers.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/data_layers.tsx @@ -8,6 +8,7 @@ import { AreaSeries, BarSeries, + BarSeriesProps, CurveType, LabelOverflowConstraint, LineSeries, @@ -51,6 +52,7 @@ interface Props { timeZone?: string; emphasizeFitting?: boolean; fillOpacity?: number; + minBarHeight: number; shouldShowValueLabels?: boolean; valueLabels: ValueLabelMode; defaultXScaleType: XScaleType; @@ -68,6 +70,7 @@ export const DataLayers: FC = ({ syncColors, valueLabels, fillOpacity, + minBarHeight, formatFactory, paletteService, fittingFunction, @@ -189,14 +192,13 @@ export const DataLayers: FC = ({ /> ); case SeriesTypes.BAR: - const valueLabelsSettings = { + const valueLabelsSettings: Pick = { displayValueSettings: { // This format double fixes two issues in elastic-chart // * when rotating the chart, the formatter is not correctly picked // * in some scenarios value labels are not strings, and this breaks the elastic-chart lib valueFormatter: (d: unknown) => yAxis?.formatter?.convert(d) || '', showValueLabel: shouldShowValueLabels && valueLabels !== ValueLabelModes.HIDE, - isValueContainedInElement: false, isAlternatingValueLabel: false, overflowConstraints: [ LabelOverflowConstraint.ChartEdges, @@ -204,7 +206,14 @@ export const DataLayers: FC = ({ ], }, }; - return ; + return ( + + ); case SeriesTypes.AREA: return ( { const args: XYProps = { showTooltip: true, + minBarHeight: 1, legend: { type: 'legendConfig', isVisible: false, position: Position.Top }, valueLabels: 'hide', yAxisConfigs: [ @@ -2618,6 +2619,7 @@ describe('XYChart component', () => { const args: XYProps = { legend: { type: 'legendConfig', isVisible: false, position: Position.Top }, valueLabels: 'hide', + minBarHeight: 1, yAxisConfigs: [ { type: 'yAxisConfig', @@ -2706,6 +2708,7 @@ describe('XYChart component', () => { const args: XYProps = { showTooltip: true, + minBarHeight: 1, legend: { type: 'legendConfig', isVisible: true, position: Position.Top }, valueLabels: 'hide', yAxisConfigs: [ diff --git a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx index 1a10643f099d4..ec466bab82b1e 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx @@ -948,6 +948,7 @@ export function XYChart({ syncColors={syncColors} valueLabels={valueLabels} fillOpacity={args.fillOpacity} + minBarHeight={args.minBarHeight} formatFactory={formatFactory} paletteService={paletteService} fittingFunction={fittingFunction} diff --git a/src/plugins/unified_histogram/public/chart/utils/get_lens_attributes.test.ts b/src/plugins/unified_histogram/public/chart/utils/get_lens_attributes.test.ts index 2a4523d152066..53ec7350401b7 100644 --- a/src/plugins/unified_histogram/public/chart/utils/get_lens_attributes.test.ts +++ b/src/plugins/unified_histogram/public/chart/utils/get_lens_attributes.test.ts @@ -176,6 +176,7 @@ describe('getLensAttributes', () => { "position": "right", "shouldTruncate": false, }, + "minBarHeight": 2, "preferredSeriesType": "bar_stacked", "showCurrentTimeMarker": true, "tickLabelsVisibilitySettings": Object { @@ -352,6 +353,7 @@ describe('getLensAttributes', () => { "position": "right", "shouldTruncate": false, }, + "minBarHeight": 2, "preferredSeriesType": "bar_stacked", "showCurrentTimeMarker": true, "tickLabelsVisibilitySettings": Object { @@ -510,6 +512,7 @@ describe('getLensAttributes', () => { "position": "right", "shouldTruncate": false, }, + "minBarHeight": 2, "preferredSeriesType": "bar_stacked", "showCurrentTimeMarker": true, "tickLabelsVisibilitySettings": Object { diff --git a/src/plugins/unified_histogram/public/chart/utils/get_lens_attributes.ts b/src/plugins/unified_histogram/public/chart/utils/get_lens_attributes.ts index 53fb29ac925ed..b5c9bca754ac5 100644 --- a/src/plugins/unified_histogram/public/chart/utils/get_lens_attributes.ts +++ b/src/plugins/unified_histogram/public/chart/utils/get_lens_attributes.ts @@ -18,6 +18,7 @@ import type { Suggestion, } from '@kbn/lens-plugin/public'; import { LegendSize } from '@kbn/visualizations-plugin/public'; +import { XYConfiguration } from '@kbn/visualizations-plugin/common'; import { fieldSupportsBreakdown } from './field_supports_breakdown'; export interface LensRequestData { @@ -139,7 +140,7 @@ export const getLensAttributes = ({ ? { ...suggestionVisualizationState, } - : { + : ({ layers: [ { accessors: ['count_column'], @@ -167,6 +168,7 @@ export const getLensAttributes = ({ preferredSeriesType: 'bar_stacked', valueLabels: 'hide', fittingFunction: 'None', + minBarHeight: 2, showCurrentTimeMarker: true, axisTitlesVisibilitySettings: { x: false, @@ -183,7 +185,7 @@ export const getLensAttributes = ({ yLeft: true, yRight: false, }, - }; + } as XYConfiguration); const attributes = { title: title ?? diff --git a/src/plugins/visualizations/common/convert_to_lens/types/configurations.ts b/src/plugins/visualizations/common/convert_to_lens/types/configurations.ts index 9949644aa1e24..61b7ea3789837 100644 --- a/src/plugins/visualizations/common/convert_to_lens/types/configurations.ts +++ b/src/plugins/visualizations/common/convert_to_lens/types/configurations.ts @@ -166,6 +166,7 @@ export interface XYConfiguration { labelsOrientation?: LabelsOrientationConfig; curveType?: XYCurveType; fillOpacity?: number; + minBarHeight?: number; hideEndzones?: boolean; valuesInLegend?: boolean; showCurrentTimeMarker?: boolean; diff --git a/x-pack/plugins/lens/public/visualizations/xy/__snapshots__/to_expression.test.ts.snap b/x-pack/plugins/lens/public/visualizations/xy/__snapshots__/to_expression.test.ts.snap index 7dfe39667fd22..6c1818c0f94ae 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/__snapshots__/to_expression.test.ts.snap +++ b/x-pack/plugins/lens/public/visualizations/xy/__snapshots__/to_expression.test.ts.snap @@ -124,6 +124,9 @@ Object { "type": "expression", }, ], + "minBarHeight": Array [ + 1, + ], "showTooltip": Array [], "valueLabels": Array [ "hide", diff --git a/x-pack/plugins/lens/public/visualizations/xy/to_expression.ts b/x-pack/plugins/lens/public/visualizations/xy/to_expression.ts index 2b80a39fc3b53..ffa803fa643db 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/to_expression.ts +++ b/x-pack/plugins/lens/public/visualizations/xy/to_expression.ts @@ -331,14 +331,15 @@ export const buildXYExpression = ( const layeredXyVisFn = buildExpressionFunction('layeredXyVis', { legend: buildExpression([legendConfigFn]).toAst(), - fittingFunction: state.fittingFunction || 'None', - endValue: state.endValue || 'None', - emphasizeFitting: state.emphasizeFitting || false, - fillOpacity: state.fillOpacity || 0.3, - valueLabels: state?.valueLabels || 'hide', - hideEndzones: state?.hideEndzones || false, - addTimeMarker: state?.showCurrentTimeMarker || false, - valuesInLegend: state?.valuesInLegend || false, + fittingFunction: state.fittingFunction ?? 'None', + endValue: state.endValue ?? 'None', + emphasizeFitting: state.emphasizeFitting ?? false, + minBarHeight: state.minBarHeight ?? 1, + fillOpacity: state.fillOpacity ?? 0.3, + valueLabels: state.valueLabels ?? 'hide', + hideEndzones: state.hideEndzones ?? false, + addTimeMarker: state.showCurrentTimeMarker ?? false, + valuesInLegend: state.valuesInLegend ?? false, yAxisConfigs: [...yAxisConfigsToExpression(yAxisConfigs)], xAxisConfig: buildExpression([xAxisConfigFn]).toAst(), showTooltip: [], diff --git a/x-pack/plugins/lens/public/visualizations/xy/types.ts b/x-pack/plugins/lens/public/visualizations/xy/types.ts index 9ffb59ec0a4d5..f0bf714093961 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/types.ts +++ b/x-pack/plugins/lens/public/visualizations/xy/types.ts @@ -215,6 +215,7 @@ export interface XYState { labelsOrientation?: LabelsOrientationConfig; curveType?: XYCurveType; fillOpacity?: number; + minBarHeight?: number; hideEndzones?: boolean; showCurrentTimeMarker?: boolean; valuesInLegend?: boolean;