diff --git a/x-pack/plugins/lens/common/expressions/xy_chart/xy_args.ts b/x-pack/plugins/lens/common/expressions/xy_chart/xy_args.ts index fb794eda22dbe..f00608135820a 100644 --- a/x-pack/plugins/lens/common/expressions/xy_chart/xy_args.ts +++ b/x-pack/plugins/lens/common/expressions/xy_chart/xy_args.ts @@ -12,8 +12,7 @@ import type { LayerArgs } from './layer_config'; import type { LegendConfigResult } from './legend_config'; import type { TickLabelsConfigResult } from './tick_labels_config'; import type { LabelsOrientationConfigResult } from './labels_orientation_config'; - -export type ValueLabelConfig = 'hide' | 'inside' | 'outside'; +import type { ValueLabelConfig } from '../../types'; export type XYCurveType = 'LINEAR' | 'CURVE_MONOTONE_X'; diff --git a/x-pack/plugins/lens/common/types.ts b/x-pack/plugins/lens/common/types.ts index 38e198c01e730..307ed856c7c66 100644 --- a/x-pack/plugins/lens/common/types.ts +++ b/x-pack/plugins/lens/common/types.ts @@ -62,3 +62,6 @@ export interface CustomPaletteParams { export type RequiredPaletteParamTypes = Required; export type LayerType = 'data' | 'referenceLine'; + +// Shared by XY Chart and Heatmap as for now +export type ValueLabelConfig = 'hide' | 'inside' | 'outside'; diff --git a/x-pack/plugins/lens/public/heatmap_visualization/chart_component.tsx b/x-pack/plugins/lens/public/heatmap_visualization/chart_component.tsx index 677cb9d20c25b..c999656071ef4 100644 --- a/x-pack/plugins/lens/public/heatmap_visualization/chart_component.tsx +++ b/x-pack/plugins/lens/public/heatmap_visualization/chart_component.tsx @@ -288,6 +288,9 @@ export const HeatmapComponent: FC = ({ maxHeight: 'fill', label: { visible: args.gridConfig.isCellLabelVisible ?? false, + minFontSize: 8, + maxFontSize: 18, + useGlobalMinFontSize: true, // override the min if there's a different directive upstream }, border: { strokeWidth: 0, diff --git a/x-pack/plugins/lens/public/heatmap_visualization/toolbar_component.tsx b/x-pack/plugins/lens/public/heatmap_visualization/toolbar_component.tsx index 80954516f0418..88966acd22691 100644 --- a/x-pack/plugins/lens/public/heatmap_visualization/toolbar_component.tsx +++ b/x-pack/plugins/lens/public/heatmap_visualization/toolbar_component.tsx @@ -10,7 +10,7 @@ import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { Position } from '@elastic/charts'; import { i18n } from '@kbn/i18n'; import type { VisualizationToolbarProps } from '../types'; -import { LegendSettingsPopover } from '../shared_components'; +import { LegendSettingsPopover, ToolbarPopover, ValueLabelsSettings } from '../shared_components'; import type { HeatmapVisualizationState } from './types'; const legendOptions: Array<{ id: string; value: 'auto' | 'show' | 'hide'; label: string }> = [ @@ -37,11 +37,29 @@ export const HeatmapToolbar = memo( const legendMode = state.legend.isVisible ? 'show' : 'hide'; return ( - + + + { + setState({ + ...state, + gridConfig: { ...state.gridConfig, isCellLabelVisible: newMode === 'inside' }, + }); + }} + /> + { diff --git a/x-pack/plugins/lens/public/index.ts b/x-pack/plugins/lens/public/index.ts index 84302f25d0a02..9be07a4f44dcd 100644 --- a/x-pack/plugins/lens/public/index.ts +++ b/x-pack/plugins/lens/public/index.ts @@ -22,11 +22,11 @@ export type { XYLayerConfig, LegendConfig, SeriesType, - ValueLabelConfig, YAxisMode, XYCurveType, YConfig, } from '../common/expressions'; +export type { ValueLabelConfig } from '../common/types'; export type { DatatableVisualizationState } from './datatable_visualization/visualization'; export type { IndexPatternPersistedState, diff --git a/x-pack/plugins/lens/public/shared_components/index.ts b/x-pack/plugins/lens/public/shared_components/index.ts index f947ce699dce4..f268d6816910e 100644 --- a/x-pack/plugins/lens/public/shared_components/index.ts +++ b/x-pack/plugins/lens/public/shared_components/index.ts @@ -14,4 +14,5 @@ export * from './coloring'; export { useDebouncedValue } from './debounced_value'; export * from './helpers'; export { LegendActionPopover } from './legend_action_popover'; +export { ValueLabelsSettings } from './value_labels_settings'; export * from './static_header'; diff --git a/x-pack/plugins/lens/public/shared_components/value_labels_settings.test.tsx b/x-pack/plugins/lens/public/shared_components/value_labels_settings.test.tsx new file mode 100644 index 0000000000000..ae68a40d8cea6 --- /dev/null +++ b/x-pack/plugins/lens/public/shared_components/value_labels_settings.test.tsx @@ -0,0 +1,46 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { shallowWithIntl as shallow } from '@kbn/test/jest'; +import { ValueLabelsSettings, VisualOptionsProps } from './value_labels_settings'; + +describe('Value labels Settings', () => { + let props: VisualOptionsProps; + beforeEach(() => { + props = { + onValueLabelChange: jest.fn(), + }; + }); + + it('should not render the component if not enabled', () => { + const component = shallow(); + expect(component.find('[data-test-subj="lens-value-labels-visibility-btn"]').length).toEqual(0); + }); + + it('should set hide as default value', () => { + const component = shallow(); + expect( + component.find('[data-test-subj="lens-value-labels-visibility-btn"]').prop('idSelected') + ).toEqual(`value_labels_hide`); + }); + + it('should have called onValueLabelChange function on ButtonGroup change', () => { + const component = shallow(); + component + .find('[data-test-subj="lens-value-labels-visibility-btn"]') + .simulate('change', 'value_labels_inside'); + expect(props.onValueLabelChange).toHaveBeenCalled(); + }); + + it('should render the passed value if given', () => { + const component = shallow(); + expect( + component.find('[data-test-subj="lens-value-labels-visibility-btn"]').prop('idSelected') + ).toEqual(`value_labels_inside`); + }); +}); diff --git a/x-pack/plugins/lens/public/shared_components/value_labels_settings.tsx b/x-pack/plugins/lens/public/shared_components/value_labels_settings.tsx new file mode 100644 index 0000000000000..64d9f5475379a --- /dev/null +++ b/x-pack/plugins/lens/public/shared_components/value_labels_settings.tsx @@ -0,0 +1,75 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { FC } from 'react'; +import { i18n } from '@kbn/i18n'; +import { EuiButtonGroup, EuiFormRow } from '@elastic/eui'; +import { ValueLabelConfig } from '../../common/types'; + +const valueLabelsOptions: Array<{ + id: string; + value: ValueLabelConfig; + label: string; + 'data-test-subj': string; +}> = [ + { + id: `value_labels_hide`, + value: 'hide', + label: i18n.translate('xpack.lens.shared.valueLabelsVisibility.auto', { + defaultMessage: 'Hide', + }), + 'data-test-subj': 'lns_valueLabels_hide', + }, + { + id: `value_labels_inside`, + value: 'inside', + label: i18n.translate('xpack.lens.shared.valueLabelsVisibility.inside', { + defaultMessage: 'Show', + }), + 'data-test-subj': 'lns_valueLabels_inside', + }, +]; + +export interface VisualOptionsProps { + isVisible?: boolean; + valueLabels?: ValueLabelConfig; + onValueLabelChange: (newMode: ValueLabelConfig) => void; +} + +export const ValueLabelsSettings: FC = ({ + isVisible = true, + valueLabels = 'hide', + onValueLabelChange, +}) => { + if (!isVisible) { + return null; + } + const label = i18n.translate('xpack.lens.shared.chartValueLabelVisibilityLabel', { + defaultMessage: 'Labels', + }); + const isSelected = + valueLabelsOptions.find(({ value }) => value === valueLabels)?.id || 'value_labels_hide'; + return ( + {label}}> + { + const newMode = valueLabelsOptions.find(({ id }) => id === modeId); + if (newMode) { + onValueLabelChange(newMode.value); + } + }} + /> + + ); +}; diff --git a/x-pack/plugins/lens/public/xy_visualization/types.ts b/x-pack/plugins/lens/public/xy_visualization/types.ts index 4729cfb96f324..475571b2965f6 100644 --- a/x-pack/plugins/lens/public/xy_visualization/types.ts +++ b/x-pack/plugins/lens/public/xy_visualization/types.ts @@ -20,7 +20,6 @@ import { LensIconChartLine } from '../assets/chart_line'; import type { VisualizationType } from '../types'; import type { SeriesType, - ValueLabelConfig, LegendConfig, AxisExtentConfig, XYLayerConfig, @@ -29,6 +28,7 @@ import type { FittingFunction, LabelsOrientationConfig, } from '../../common/expressions'; +import type { ValueLabelConfig } from '../../common/types'; // Persisted parts of the state export interface XYState { diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_config_panel/visual_options_popover/index.tsx b/x-pack/plugins/lens/public/xy_visualization/xy_config_panel/visual_options_popover/index.tsx index 2a19897445e63..8ea6f9ace6320 100644 --- a/x-pack/plugins/lens/public/xy_visualization/xy_config_panel/visual_options_popover/index.tsx +++ b/x-pack/plugins/lens/public/xy_visualization/xy_config_panel/visual_options_popover/index.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; -import { ToolbarPopover, TooltipWrapper } from '../../../shared_components'; +import { ToolbarPopover, TooltipWrapper, ValueLabelsSettings } from '../../../shared_components'; import { MissingValuesOptions } from './missing_values_option'; import { LineCurveOption } from './line_curve_option'; import { FillOpacityOption } from './fill_opacity_option'; @@ -102,14 +102,17 @@ export const VisualOptionsPopover: React.FC = ({ }} /> - { setState({ ...state, valueLabels: newMode }); }} + /> + + { setState({ ...state, fittingFunction: newVal }); }} diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_config_panel/visual_options_popover/missing_value_option.test.tsx b/x-pack/plugins/lens/public/xy_visualization/xy_config_panel/visual_options_popover/missing_value_option.test.tsx index 851b14839d7f7..ce4e05223b5a3 100644 --- a/x-pack/plugins/lens/public/xy_visualization/xy_config_panel/visual_options_popover/missing_value_option.test.tsx +++ b/x-pack/plugins/lens/public/xy_visualization/xy_config_panel/visual_options_popover/missing_value_option.test.tsx @@ -7,70 +7,23 @@ import React from 'react'; import { shallowWithIntl as shallow, mountWithIntl as mount } from '@kbn/test/jest'; -import { EuiSuperSelect, EuiButtonGroup } from '@elastic/eui'; +import { EuiSuperSelect } from '@elastic/eui'; import { MissingValuesOptions } from './missing_values_option'; describe('Missing values option', () => { it('should show currently selected fitting function', () => { const component = shallow( - + ); expect(component.find(EuiSuperSelect).prop('valueOfSelected')).toEqual('Carry'); }); - it('should show currently selected value labels display setting', () => { - const component = mount( - - ); - - expect(component.find(EuiButtonGroup).prop('idSelected')).toEqual('value_labels_inside'); - }); - - it('should show display field when enabled', () => { - const component = mount( - - ); - - expect(component.exists('[data-test-subj="lnsValueLabelsDisplay"]')).toEqual(true); - }); - - it('should hide in display value label option when disabled', () => { - const component = mount( - - ); - - expect(component.exists('[data-test-subj="lnsValueLabelsDisplay"]')).toEqual(false); - }); - it('should show the fitting option when enabled', () => { const component = mount( ); @@ -82,9 +35,7 @@ describe('Missing values option', () => { const component = mount( ); diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_config_panel/visual_options_popover/missing_values_option.tsx b/x-pack/plugins/lens/public/xy_visualization/xy_config_panel/visual_options_popover/missing_values_option.tsx index b12e2d2f57112..a858d1c879efe 100644 --- a/x-pack/plugins/lens/public/xy_visualization/xy_config_panel/visual_options_popover/missing_values_option.tsx +++ b/x-pack/plugins/lens/public/xy_visualization/xy_config_panel/visual_options_popover/missing_values_option.tsx @@ -7,85 +7,23 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; -import { EuiButtonGroup, EuiFormRow, EuiIconTip, EuiSuperSelect, EuiText } from '@elastic/eui'; +import { EuiFormRow, EuiIconTip, EuiSuperSelect, EuiText } from '@elastic/eui'; import { fittingFunctionDefinitions } from '../../../../common/expressions'; -import type { FittingFunction, ValueLabelConfig } from '../../../../common/expressions'; +import type { FittingFunction } from '../../../../common/expressions'; export interface MissingValuesOptionProps { - valueLabels?: ValueLabelConfig; fittingFunction?: FittingFunction; - onValueLabelChange: (newMode: ValueLabelConfig) => void; onFittingFnChange: (newMode: FittingFunction) => void; - isValueLabelsEnabled?: boolean; isFittingEnabled?: boolean; } -const valueLabelsOptions: Array<{ - id: string; - value: 'hide' | 'inside' | 'outside'; - label: string; - 'data-test-subj': string; -}> = [ - { - id: `value_labels_hide`, - value: 'hide', - label: i18n.translate('xpack.lens.xyChart.valueLabelsVisibility.auto', { - defaultMessage: 'Hide', - }), - 'data-test-subj': 'lnsXY_valueLabels_hide', - }, - { - id: `value_labels_inside`, - value: 'inside', - label: i18n.translate('xpack.lens.xyChart.valueLabelsVisibility.inside', { - defaultMessage: 'Show', - }), - 'data-test-subj': 'lnsXY_valueLabels_inside', - }, -]; - export const MissingValuesOptions: React.FC = ({ - onValueLabelChange, onFittingFnChange, - valueLabels, fittingFunction, - isValueLabelsEnabled = true, isFittingEnabled = true, }) => { - const valueLabelsVisibilityMode = valueLabels || 'hide'; - return ( <> - {isValueLabelsEnabled && ( - - {i18n.translate('xpack.lens.shared.chartValueLabelVisibilityLabel', { - defaultMessage: 'Labels', - })} - - } - > - value === valueLabelsVisibilityMode)!.id - } - onChange={(modeId) => { - const newMode = valueLabelsOptions.find(({ id }) => id === modeId)!.value; - onValueLabelChange(newMode); - }} - /> - - )} {isFittingEnabled && ( { /> ); - expect(component.find(MissingValuesOptions).prop('isValueLabelsEnabled')).toEqual(false); + expect(component.find(ValueLabelsSettings).prop('isVisible')).toEqual(false); expect(component.find(MissingValuesOptions).prop('isFittingEnabled')).toEqual(false); }); @@ -196,7 +196,7 @@ describe('Visual options popover', () => { /> ); - expect(component.find(MissingValuesOptions).prop('isValueLabelsEnabled')).toEqual(true); + expect(component.find(ValueLabelsSettings).prop('isVisible')).toEqual(true); }); it('should hide in the popover the display option for area and line series', () => { @@ -213,7 +213,7 @@ describe('Visual options popover', () => { /> ); - expect(component.find(MissingValuesOptions).prop('isValueLabelsEnabled')).toEqual(false); + expect(component.find(ValueLabelsSettings).prop('isVisible')).toEqual(false); }); it('should keep the display option for bar series with multiple layers', () => { @@ -245,6 +245,6 @@ describe('Visual options popover', () => { /> ); - expect(component.find(MissingValuesOptions).prop('isValueLabelsEnabled')).toEqual(true); + expect(component.find(ValueLabelsSettings).prop('isVisible')).toEqual(true); }); }); diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 7291e94615477..a8d3b4a5f3e27 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -807,8 +807,6 @@ "xpack.lens.xyChart.topAxisDisabledHelpText": "この設定は、上の軸が有効であるときにのみ適用されます。", "xpack.lens.xyChart.topAxisLabel": "上の軸", "xpack.lens.xyChart.upperBoundLabel": "上界", - "xpack.lens.xyChart.valueLabelsVisibility.auto": "非表示", - "xpack.lens.xyChart.valueLabelsVisibility.inside": "表示", "xpack.lens.xyChart.valuesHistogramDisabledHelpText": "この設定はヒストグラムで変更できません。", "xpack.lens.xyChart.valuesInLegend.help": "凡例に値を表示", "xpack.lens.xyChart.valuesPercentageDisabledHelpText": "この設定は割合エリアグラフで変更できません。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 2aa9cabb7866b..4bd2a5907abf3 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -817,8 +817,6 @@ "xpack.lens.xyChart.topAxisDisabledHelpText": "此设置仅在启用顶轴时应用。", "xpack.lens.xyChart.topAxisLabel": "顶轴", "xpack.lens.xyChart.upperBoundLabel": "上边界", - "xpack.lens.xyChart.valueLabelsVisibility.auto": "隐藏", - "xpack.lens.xyChart.valueLabelsVisibility.inside": "显示", "xpack.lens.xyChart.valuesHistogramDisabledHelpText": "不能在直方图上更改此设置。", "xpack.lens.xyChart.valuesInLegend.help": "在图例中显示值", "xpack.lens.xyChart.valuesPercentageDisabledHelpText": "不能在百分比面积图上更改此设置。", diff --git a/x-pack/test/functional/apps/lens/smokescreen.ts b/x-pack/test/functional/apps/lens/smokescreen.ts index ff5bae8aa7e61..7cacee6446723 100644 --- a/x-pack/test/functional/apps/lens/smokescreen.ts +++ b/x-pack/test/functional/apps/lens/smokescreen.ts @@ -256,7 +256,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('should show value labels on bar charts when enabled', async () => { // enable value labels await PageObjects.lens.openVisualOptions(); - await testSubjects.click('lnsXY_valueLabels_inside'); + await testSubjects.click('lns_valueLabels_inside'); await PageObjects.lens.waitForVisualization();