From 63f0cc051980530b7ab29ebc1324debedf34fe8a Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Tue, 15 Sep 2020 11:24:02 +0200 Subject: [PATCH] [Lens] Stack as percentage (#70703) --- .../plugins/lens/public/app_plugin/_app.scss | 14 ++ .../plugins/lens/public/assets/chart_area.svg | 6 - .../plugins/lens/public/assets/chart_area.tsx | 30 +++ .../public/assets/chart_area_percentage.tsx | 34 +++ .../lens/public/assets/chart_area_stacked.svg | 6 - .../lens/public/assets/chart_area_stacked.tsx | 34 +++ .../plugins/lens/public/assets/chart_bar.svg | 6 - .../plugins/lens/public/assets/chart_bar.tsx | 30 +++ .../public/assets/chart_bar_horizontal.svg | 6 - .../public/assets/chart_bar_horizontal.tsx | 34 +++ .../chart_bar_horizontal_percentage.tsx | 34 +++ .../assets/chart_bar_horizontal_stacked.svg | 6 - .../assets/chart_bar_horizontal_stacked.tsx | 34 +++ .../public/assets/chart_bar_percentage.tsx | 34 +++ .../lens/public/assets/chart_bar_stacked.svg | 6 - .../lens/public/assets/chart_bar_stacked.tsx | 34 +++ .../lens/public/assets/chart_datatable.svg | 6 - .../lens/public/assets/chart_datatable.tsx | 34 +++ .../lens/public/assets/chart_donut.svg | 4 - .../lens/public/assets/chart_donut.tsx | 30 +++ .../plugins/lens/public/assets/chart_line.svg | 6 - .../plugins/lens/public/assets/chart_line.tsx | 30 +++ .../lens/public/assets/chart_metric.svg | 4 - .../lens/public/assets/chart_metric.tsx | 30 +++ .../lens/public/assets/chart_mixed_xy.svg | 7 - .../lens/public/assets/chart_mixed_xy.tsx | 34 +++ .../plugins/lens/public/assets/chart_pie.svg | 4 - .../plugins/lens/public/assets/chart_pie.tsx | 30 +++ .../lens/public/assets/chart_treemap.svg | 5 - .../lens/public/assets/chart_treemap.tsx | 34 +++ .../expression.test.tsx | 3 +- .../datatable_visualization/expression.tsx | 4 +- .../datatable_visualization/visualization.tsx | 9 +- .../editor_frame/_suggestion_panel.scss | 5 +- .../config_panel/layer_panel.scss | 8 + .../editor_frame/config_panel/layer_panel.tsx | 2 +- .../editor_frame/suggestion_panel.test.tsx | 6 +- .../workspace_panel/chart_switch.scss | 1 + .../workspace_panel/chart_switch.tsx | 4 +- .../metric_suggestions.test.ts | 2 +- .../metric_suggestions.ts | 4 +- .../metric_visualization.tsx | 7 +- .../public/pie_visualization/constants.ts | 14 +- .../pie_visualization/pie_visualization.tsx | 6 +- .../render_function.test.tsx | 3 +- .../pie_visualization/render_function.tsx | 5 +- .../lens/public/pie_visualization/toolbar.tsx | 4 +- x-pack/plugins/lens/public/types.ts | 3 +- .../__snapshots__/xy_expression.test.tsx.snap | 231 ++++++++++++++++++ .../xy_visualization/axes_configuration.ts | 13 +- .../public/xy_visualization/state_helpers.ts | 6 +- .../xy_visualization/to_expression.test.ts | 39 +-- .../public/xy_visualization/to_expression.ts | 4 +- .../lens/public/xy_visualization/types.ts | 80 ++++-- .../xy_visualization/xy_config_panel.test.tsx | 10 +- .../xy_visualization/xy_config_panel.tsx | 1 - .../public/xy_visualization/xy_expression.tsx | 37 ++- .../xy_visualization/xy_suggestions.test.ts | 77 +++++- .../public/xy_visualization/xy_suggestions.ts | 133 ++++++++-- .../xy_visualization/xy_visualization.test.ts | 5 +- .../xy_visualization/xy_visualization.tsx | 44 ++-- .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - 63 files changed, 1149 insertions(+), 229 deletions(-) delete mode 100644 x-pack/plugins/lens/public/assets/chart_area.svg create mode 100644 x-pack/plugins/lens/public/assets/chart_area.tsx create mode 100644 x-pack/plugins/lens/public/assets/chart_area_percentage.tsx delete mode 100644 x-pack/plugins/lens/public/assets/chart_area_stacked.svg create mode 100644 x-pack/plugins/lens/public/assets/chart_area_stacked.tsx delete mode 100644 x-pack/plugins/lens/public/assets/chart_bar.svg create mode 100644 x-pack/plugins/lens/public/assets/chart_bar.tsx delete mode 100644 x-pack/plugins/lens/public/assets/chart_bar_horizontal.svg create mode 100644 x-pack/plugins/lens/public/assets/chart_bar_horizontal.tsx create mode 100644 x-pack/plugins/lens/public/assets/chart_bar_horizontal_percentage.tsx delete mode 100644 x-pack/plugins/lens/public/assets/chart_bar_horizontal_stacked.svg create mode 100644 x-pack/plugins/lens/public/assets/chart_bar_horizontal_stacked.tsx create mode 100644 x-pack/plugins/lens/public/assets/chart_bar_percentage.tsx delete mode 100644 x-pack/plugins/lens/public/assets/chart_bar_stacked.svg create mode 100644 x-pack/plugins/lens/public/assets/chart_bar_stacked.tsx delete mode 100644 x-pack/plugins/lens/public/assets/chart_datatable.svg create mode 100644 x-pack/plugins/lens/public/assets/chart_datatable.tsx delete mode 100644 x-pack/plugins/lens/public/assets/chart_donut.svg create mode 100644 x-pack/plugins/lens/public/assets/chart_donut.tsx delete mode 100644 x-pack/plugins/lens/public/assets/chart_line.svg create mode 100644 x-pack/plugins/lens/public/assets/chart_line.tsx delete mode 100644 x-pack/plugins/lens/public/assets/chart_metric.svg create mode 100644 x-pack/plugins/lens/public/assets/chart_metric.tsx delete mode 100644 x-pack/plugins/lens/public/assets/chart_mixed_xy.svg create mode 100644 x-pack/plugins/lens/public/assets/chart_mixed_xy.tsx delete mode 100644 x-pack/plugins/lens/public/assets/chart_pie.svg create mode 100644 x-pack/plugins/lens/public/assets/chart_pie.tsx delete mode 100644 x-pack/plugins/lens/public/assets/chart_treemap.svg create mode 100644 x-pack/plugins/lens/public/assets/chart_treemap.tsx diff --git a/x-pack/plugins/lens/public/app_plugin/_app.scss b/x-pack/plugins/lens/public/app_plugin/_app.scss index 4ad8dd360bac6..8416577a60421 100644 --- a/x-pack/plugins/lens/public/app_plugin/_app.scss +++ b/x-pack/plugins/lens/public/app_plugin/_app.scss @@ -26,3 +26,17 @@ flex-direction: column; flex-grow: 1; } + +.lensChartIcon__subdued { + fill: $euiTextSubduedColor; + + // Not great, but the easiest way to fix the gray fill when stuck in a button with a fill + // Like when selected in a button group + .euiButton--fill & { + fill: currentColor; + } +} + +.lensChartIcon__accent { + fill: $euiColorVis0; +} diff --git a/x-pack/plugins/lens/public/assets/chart_area.svg b/x-pack/plugins/lens/public/assets/chart_area.svg deleted file mode 100644 index d291a084028db..0000000000000 --- a/x-pack/plugins/lens/public/assets/chart_area.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/x-pack/plugins/lens/public/assets/chart_area.tsx b/x-pack/plugins/lens/public/assets/chart_area.tsx new file mode 100644 index 0000000000000..ae817e9794dc5 --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_area.tsx @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartArea = ({ title, titleId, ...props }: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_area_percentage.tsx b/x-pack/plugins/lens/public/assets/chart_area_percentage.tsx new file mode 100644 index 0000000000000..45c208d5d634b --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_area_percentage.tsx @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartAreaPercentage = ({ + title, + titleId, + ...props +}: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_area_stacked.svg b/x-pack/plugins/lens/public/assets/chart_area_stacked.svg deleted file mode 100644 index 6ae48bf6a640b..0000000000000 --- a/x-pack/plugins/lens/public/assets/chart_area_stacked.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/x-pack/plugins/lens/public/assets/chart_area_stacked.tsx b/x-pack/plugins/lens/public/assets/chart_area_stacked.tsx new file mode 100644 index 0000000000000..0320ad7e9afa5 --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_area_stacked.tsx @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartAreaStacked = ({ + title, + titleId, + ...props +}: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_bar.svg b/x-pack/plugins/lens/public/assets/chart_bar.svg deleted file mode 100644 index 44553960a5cce..0000000000000 --- a/x-pack/plugins/lens/public/assets/chart_bar.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/x-pack/plugins/lens/public/assets/chart_bar.tsx b/x-pack/plugins/lens/public/assets/chart_bar.tsx new file mode 100644 index 0000000000000..9408f77bd4237 --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_bar.tsx @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartBar = ({ title, titleId, ...props }: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_bar_horizontal.svg b/x-pack/plugins/lens/public/assets/chart_bar_horizontal.svg deleted file mode 100644 index e0d9dc8385971..0000000000000 --- a/x-pack/plugins/lens/public/assets/chart_bar_horizontal.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/x-pack/plugins/lens/public/assets/chart_bar_horizontal.tsx b/x-pack/plugins/lens/public/assets/chart_bar_horizontal.tsx new file mode 100644 index 0000000000000..7ec48b107e2fb --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_bar_horizontal.tsx @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartBarHorizontal = ({ + title, + titleId, + ...props +}: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_bar_horizontal_percentage.tsx b/x-pack/plugins/lens/public/assets/chart_bar_horizontal_percentage.tsx new file mode 100644 index 0000000000000..6ce09265d4894 --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_bar_horizontal_percentage.tsx @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartBarHorizontalPercentage = ({ + title, + titleId, + ...props +}: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_bar_horizontal_stacked.svg b/x-pack/plugins/lens/public/assets/chart_bar_horizontal_stacked.svg deleted file mode 100644 index 602a06e696ecd..0000000000000 --- a/x-pack/plugins/lens/public/assets/chart_bar_horizontal_stacked.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/x-pack/plugins/lens/public/assets/chart_bar_horizontal_stacked.tsx b/x-pack/plugins/lens/public/assets/chart_bar_horizontal_stacked.tsx new file mode 100644 index 0000000000000..c862121fd04f2 --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_bar_horizontal_stacked.tsx @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartBarHorizontalStacked = ({ + title, + titleId, + ...props +}: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_bar_percentage.tsx b/x-pack/plugins/lens/public/assets/chart_bar_percentage.tsx new file mode 100644 index 0000000000000..b7d6a0ed604af --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_bar_percentage.tsx @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartBarPercentage = ({ + title, + titleId, + ...props +}: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_bar_stacked.svg b/x-pack/plugins/lens/public/assets/chart_bar_stacked.svg deleted file mode 100644 index a954cce83873d..0000000000000 --- a/x-pack/plugins/lens/public/assets/chart_bar_stacked.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/x-pack/plugins/lens/public/assets/chart_bar_stacked.tsx b/x-pack/plugins/lens/public/assets/chart_bar_stacked.tsx new file mode 100644 index 0000000000000..edf8e675178f0 --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_bar_stacked.tsx @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartBarStacked = ({ + title, + titleId, + ...props +}: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_datatable.svg b/x-pack/plugins/lens/public/assets/chart_datatable.svg deleted file mode 100644 index aba1f104264cb..0000000000000 --- a/x-pack/plugins/lens/public/assets/chart_datatable.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/x-pack/plugins/lens/public/assets/chart_datatable.tsx b/x-pack/plugins/lens/public/assets/chart_datatable.tsx new file mode 100644 index 0000000000000..48cc844ea2805 --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_datatable.tsx @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartDatatable = ({ + title, + titleId, + ...props +}: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_donut.svg b/x-pack/plugins/lens/public/assets/chart_donut.svg deleted file mode 100644 index 5e0d8b7ea83bf..0000000000000 --- a/x-pack/plugins/lens/public/assets/chart_donut.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/x-pack/plugins/lens/public/assets/chart_donut.tsx b/x-pack/plugins/lens/public/assets/chart_donut.tsx new file mode 100644 index 0000000000000..9482161de9d9e --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_donut.tsx @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartDonut = ({ title, titleId, ...props }: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_line.svg b/x-pack/plugins/lens/public/assets/chart_line.svg deleted file mode 100644 index 412c9f88f652b..0000000000000 --- a/x-pack/plugins/lens/public/assets/chart_line.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/x-pack/plugins/lens/public/assets/chart_line.tsx b/x-pack/plugins/lens/public/assets/chart_line.tsx new file mode 100644 index 0000000000000..5b57e1fe28c16 --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_line.tsx @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartLine = ({ title, titleId, ...props }: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_metric.svg b/x-pack/plugins/lens/public/assets/chart_metric.svg deleted file mode 100644 index 84f0dc181587b..0000000000000 --- a/x-pack/plugins/lens/public/assets/chart_metric.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/x-pack/plugins/lens/public/assets/chart_metric.tsx b/x-pack/plugins/lens/public/assets/chart_metric.tsx new file mode 100644 index 0000000000000..9faa4d6584258 --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_metric.tsx @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartMetric = ({ title, titleId, ...props }: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_mixed_xy.svg b/x-pack/plugins/lens/public/assets/chart_mixed_xy.svg deleted file mode 100644 index 943d5a08bcc0b..0000000000000 --- a/x-pack/plugins/lens/public/assets/chart_mixed_xy.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/x-pack/plugins/lens/public/assets/chart_mixed_xy.tsx b/x-pack/plugins/lens/public/assets/chart_mixed_xy.tsx new file mode 100644 index 0000000000000..08eac8eb1605d --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_mixed_xy.tsx @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartMixedXy = ({ title, titleId, ...props }: Omit) => ( + + {title ? {title} : null} + + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_pie.svg b/x-pack/plugins/lens/public/assets/chart_pie.svg deleted file mode 100644 index 22faaf5d97661..0000000000000 --- a/x-pack/plugins/lens/public/assets/chart_pie.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/x-pack/plugins/lens/public/assets/chart_pie.tsx b/x-pack/plugins/lens/public/assets/chart_pie.tsx new file mode 100644 index 0000000000000..cc26df4419caf --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_pie.tsx @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartPie = ({ title, titleId, ...props }: Omit) => ( + + {title ? {title} : null} + + + +); diff --git a/x-pack/plugins/lens/public/assets/chart_treemap.svg b/x-pack/plugins/lens/public/assets/chart_treemap.svg deleted file mode 100644 index b0ee04d02b2a6..0000000000000 --- a/x-pack/plugins/lens/public/assets/chart_treemap.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/x-pack/plugins/lens/public/assets/chart_treemap.tsx b/x-pack/plugins/lens/public/assets/chart_treemap.tsx new file mode 100644 index 0000000000000..57205e94137a8 --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_treemap.tsx @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiIconProps } from '@elastic/eui'; + +export const LensIconChartTreemap = ({ title, titleId, ...props }: Omit) => ( + + {title ? {title} : null} + + + + +); diff --git a/x-pack/plugins/lens/public/datatable_visualization/expression.test.tsx b/x-pack/plugins/lens/public/datatable_visualization/expression.test.tsx index b9bdea5522f32..eb00cf93ccd34 100644 --- a/x-pack/plugins/lens/public/datatable_visualization/expression.test.tsx +++ b/x-pack/plugins/lens/public/datatable_visualization/expression.test.tsx @@ -15,6 +15,7 @@ import { IFieldFormat } from '../../../../../src/plugins/data/public'; import { IAggType } from 'src/plugins/data/public'; const onClickValue = jest.fn(); import { EmptyPlaceholder } from '../shared_components'; +import { LensIconChartDatatable } from '../assets/chart_datatable'; function sampleArgs() { const data: LensMultiTable = { @@ -219,7 +220,7 @@ describe('datatable_expression', () => { )} /> ); - expect(component.find(EmptyPlaceholder).prop('icon')).toEqual('visTable'); + expect(component.find(EmptyPlaceholder).prop('icon')).toEqual(LensIconChartDatatable); }); }); }); diff --git a/x-pack/plugins/lens/public/datatable_visualization/expression.tsx b/x-pack/plugins/lens/public/datatable_visualization/expression.tsx index 87ac2d1710b19..dac3b23b98e3b 100644 --- a/x-pack/plugins/lens/public/datatable_visualization/expression.tsx +++ b/x-pack/plugins/lens/public/datatable_visualization/expression.tsx @@ -23,6 +23,8 @@ import { import { VisualizationContainer } from '../visualization_container'; import { EmptyPlaceholder } from '../shared_components'; import { desanitizeFilterContext } from '../utils'; +import { LensIconChartDatatable } from '../assets/chart_datatable'; + export interface DatatableColumns { columnIds: string[]; } @@ -199,7 +201,7 @@ export function DatatableComponent(props: DatatableRenderProps) { )); if (isEmpty) { - return ; + return ; } return ( diff --git a/x-pack/plugins/lens/public/datatable_visualization/visualization.tsx b/x-pack/plugins/lens/public/datatable_visualization/visualization.tsx index 836ffcb15cfa1..5b462f44b3dd5 100644 --- a/x-pack/plugins/lens/public/datatable_visualization/visualization.tsx +++ b/x-pack/plugins/lens/public/datatable_visualization/visualization.tsx @@ -7,7 +7,7 @@ import { Ast } from '@kbn/interpreter/common'; import { i18n } from '@kbn/i18n'; import { SuggestionRequest, Visualization, VisualizationSuggestion, Operation } from '../types'; -import chartTableSVG from '../assets/chart_datatable.svg'; +import { LensIconChartDatatable } from '../assets/chart_datatable'; export interface LayerState { layerId: string; @@ -31,8 +31,7 @@ export const datatableVisualization: Visualization visualizationTypes: [ { id: 'lnsDatatable', - icon: 'visTable', - largeIcon: chartTableSVG, + icon: LensIconChartDatatable, label: i18n.translate('xpack.lens.datatable.label', { defaultMessage: 'Data table', }), @@ -55,7 +54,7 @@ export const datatableVisualization: Visualization getDescription() { return { - icon: chartTableSVG, + icon: LensIconChartDatatable, label: i18n.translate('xpack.lens.datatable.label', { defaultMessage: 'Data table', }), @@ -121,7 +120,7 @@ export const datatableVisualization: Visualization }, ], }, - previewIcon: chartTableSVG, + previewIcon: LensIconChartDatatable, // tables are hidden from suggestion bar, but used for drag & drop and chart switching hide: true, }, diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/_suggestion_panel.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/_suggestion_panel.scss index 1d088e2ec86f9..9d018076dc320 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/_suggestion_panel.scss +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/_suggestion_panel.scss @@ -42,9 +42,8 @@ justify-content: center; padding: $euiSizeS; - // Targeting img as this won't target normal EuiIcon's only the custom svgs's - > img { - @include size($euiSize * 4); + &:not(:only-child) { + height: calc(100% - #{$euiSizeL}); } } diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.scss index 34cefd7d1b101..b85c3e843613d 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.scss +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.scss @@ -6,6 +6,14 @@ max-width: calc(100% - #{$euiSize * 3.625}); } +.lnsLayerPanel__settingsFlexItem:empty + .lnsLayerPanel__sourceFlexItem { + max-width: calc(100% - #{$euiSizeS}); +} + +.lnsLayerPanel__settingsFlexItem:empty { + margin: 0; +} + .lnsLayerPanel__row { background: $euiColorLightestShade; padding: $euiSizeS; diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx index 258aadc82fbf2..46cd0292f2459 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx @@ -101,7 +101,7 @@ export function LayerPanel( - + { getSuggestionsMock.mockReturnValue([ { datasourceState: {}, - previewIcon: chartTableSVG, + previewIcon: LensIconChartDatatable, score: 0.5, visualizationState: suggestion1State, visualizationId: 'vis', @@ -288,6 +288,6 @@ describe('suggestion_panel', () => { const wrapper = mount(); expect(wrapper.find(EuiIcon)).toHaveLength(1); - expect(wrapper.find(EuiIcon).prop('type')).toEqual(chartTableSVG); + expect(wrapper.find(EuiIcon).prop('type')).toEqual(LensIconChartDatatable); }); }); diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.scss index 8a44d59ff1c0d..f84191e1bfb1a 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.scss +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.scss @@ -8,6 +8,7 @@ .lnsChartSwitch__summaryIcon { margin-right: $euiSizeS; transform: translateY(-1px); + color: $euiTextSubduedColor; } // Targeting img as this won't target normal EuiIcon's only the custom svgs's diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.tsx index 5640c52ac4325..82983862e7c03 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.tsx @@ -66,7 +66,7 @@ function VisualizationSummary(props: Props) { return ( <> {description.icon && ( - + )} {description.label} @@ -181,7 +181,7 @@ export function ChartSwitch(props: Props) { v.visualizationTypes.map((t) => ({ visualizationId: v.id, ...t, - icon: t.largeIcon || t.icon, + icon: t.icon, })) ) ).map((visualizationType) => ({ diff --git a/x-pack/plugins/lens/public/metric_visualization/metric_suggestions.test.ts b/x-pack/plugins/lens/public/metric_visualization/metric_suggestions.test.ts index ecb1f07214ac6..2a659e5fe10c4 100644 --- a/x-pack/plugins/lens/public/metric_visualization/metric_suggestions.test.ts +++ b/x-pack/plugins/lens/public/metric_visualization/metric_suggestions.test.ts @@ -100,7 +100,7 @@ describe('metric_suggestions', () => { expect(rest).toHaveLength(0); expect(suggestion).toMatchInlineSnapshot(` Object { - "previewIcon": "test-file-stub", + "previewIcon": [Function], "score": 0.1, "state": Object { "accessor": "bytes", diff --git a/x-pack/plugins/lens/public/metric_visualization/metric_suggestions.ts b/x-pack/plugins/lens/public/metric_visualization/metric_suggestions.ts index 0caac7dd0d092..c95467ab04e11 100644 --- a/x-pack/plugins/lens/public/metric_visualization/metric_suggestions.ts +++ b/x-pack/plugins/lens/public/metric_visualization/metric_suggestions.ts @@ -6,7 +6,7 @@ import { SuggestionRequest, VisualizationSuggestion, TableSuggestion } from '../types'; import { State } from './types'; -import chartMetricSVG from '../assets/chart_metric.svg'; +import { LensIconChartMetric } from '../assets/chart_metric'; /** * Generate suggestions for the metric chart. @@ -44,7 +44,7 @@ function getSuggestion(table: TableSuggestion): VisualizationSuggestion { return { title, score: 0.1, - previewIcon: chartMetricSVG, + previewIcon: LensIconChartMetric, state: { layerId: table.layerId, accessor: col.columnId, diff --git a/x-pack/plugins/lens/public/metric_visualization/metric_visualization.tsx b/x-pack/plugins/lens/public/metric_visualization/metric_visualization.tsx index 5f1ce5334dd36..72c07bed1acb2 100644 --- a/x-pack/plugins/lens/public/metric_visualization/metric_visualization.tsx +++ b/x-pack/plugins/lens/public/metric_visualization/metric_visualization.tsx @@ -7,9 +7,9 @@ import { i18n } from '@kbn/i18n'; import { Ast } from '@kbn/interpreter/target/common'; import { getSuggestions } from './metric_suggestions'; +import { LensIconChartMetric } from '../assets/chart_metric'; import { Visualization, OperationMetadata, DatasourcePublicAPI } from '../types'; import { State } from './types'; -import chartMetricSVG from '../assets/chart_metric.svg'; const toExpression = ( state: State, @@ -45,8 +45,7 @@ export const metricVisualization: Visualization = { visualizationTypes: [ { id: 'lnsMetric', - icon: 'visMetric', - largeIcon: chartMetricSVG, + icon: LensIconChartMetric, label: i18n.translate('xpack.lens.metric.label', { defaultMessage: 'Metric', }), @@ -70,7 +69,7 @@ export const metricVisualization: Visualization = { getDescription() { return { - icon: chartMetricSVG, + icon: LensIconChartMetric, label: i18n.translate('xpack.lens.metric.label', { defaultMessage: 'Metric', }), diff --git a/x-pack/plugins/lens/public/pie_visualization/constants.ts b/x-pack/plugins/lens/public/pie_visualization/constants.ts index 10672f91a81c7..ab5e64ea84029 100644 --- a/x-pack/plugins/lens/public/pie_visualization/constants.ts +++ b/x-pack/plugins/lens/public/pie_visualization/constants.ts @@ -5,25 +5,25 @@ */ import { i18n } from '@kbn/i18n'; -import chartDonutSVG from '../assets/chart_donut.svg'; -import chartPieSVG from '../assets/chart_pie.svg'; -import chartTreemapSVG from '../assets/chart_treemap.svg'; +import { LensIconChartDonut } from '../assets/chart_donut'; +import { LensIconChartPie } from '../assets/chart_pie'; +import { LensIconChartTreemap } from '../assets/chart_treemap'; export const CHART_NAMES = { donut: { - icon: chartDonutSVG, + icon: LensIconChartDonut, label: i18n.translate('xpack.lens.pie.donutLabel', { defaultMessage: 'Donut', }), }, pie: { - icon: chartPieSVG, + icon: LensIconChartPie, label: i18n.translate('xpack.lens.pie.pielabel', { defaultMessage: 'Pie', }), }, treemap: { - icon: chartTreemapSVG, + icon: LensIconChartTreemap, label: i18n.translate('xpack.lens.pie.treemaplabel', { defaultMessage: 'Treemap', }), @@ -33,4 +33,4 @@ export const CHART_NAMES = { export const MAX_PIE_BUCKETS = 3; export const MAX_TREEMAP_BUCKETS = 2; -export const DEFAULT_PERCENT_DECIMALS = 3; +export const DEFAULT_PERCENT_DECIMALS = 2; diff --git a/x-pack/plugins/lens/public/pie_visualization/pie_visualization.tsx b/x-pack/plugins/lens/public/pie_visualization/pie_visualization.tsx index 855bacd4f794c..dd1b36e00ebb9 100644 --- a/x-pack/plugins/lens/public/pie_visualization/pie_visualization.tsx +++ b/x-pack/plugins/lens/public/pie_visualization/pie_visualization.tsx @@ -37,17 +37,17 @@ export const pieVisualization: Visualization = { visualizationTypes: [ { id: 'donut', - largeIcon: CHART_NAMES.donut.icon, + icon: CHART_NAMES.donut.icon, label: CHART_NAMES.donut.label, }, { id: 'pie', - largeIcon: CHART_NAMES.pie.icon, + icon: CHART_NAMES.pie.icon, label: CHART_NAMES.pie.label, }, { id: 'treemap', - largeIcon: CHART_NAMES.treemap.icon, + icon: CHART_NAMES.treemap.icon, label: CHART_NAMES.treemap.label, }, ], diff --git a/x-pack/plugins/lens/public/pie_visualization/render_function.test.tsx b/x-pack/plugins/lens/public/pie_visualization/render_function.test.tsx index 38ef44a2fef18..ac952e307758b 100644 --- a/x-pack/plugins/lens/public/pie_visualization/render_function.test.tsx +++ b/x-pack/plugins/lens/public/pie_visualization/render_function.test.tsx @@ -12,6 +12,7 @@ import { PieComponent } from './render_function'; import { PieExpressionArgs } from './types'; import { EmptyPlaceholder } from '../shared_components'; import { chartPluginMock } from '../../../../../src/plugins/charts/public/mocks'; +import { LensIconChartDonut } from '../assets/chart_donut'; const chartsThemeService = chartPluginMock.createSetupContract().theme; @@ -189,7 +190,7 @@ describe('PieVisualization component', () => { const component = shallow( ); - expect(component.find(EmptyPlaceholder).prop('icon')).toEqual('visPie'); + expect(component.find(EmptyPlaceholder).prop('icon')).toEqual(LensIconChartDonut); }); }); }); diff --git a/x-pack/plugins/lens/public/pie_visualization/render_function.tsx b/x-pack/plugins/lens/public/pie_visualization/render_function.tsx index 4e813494d7d32..d97ab146e000d 100644 --- a/x-pack/plugins/lens/public/pie_visualization/render_function.tsx +++ b/x-pack/plugins/lens/public/pie_visualization/render_function.tsx @@ -33,6 +33,7 @@ import { EmptyPlaceholder } from '../shared_components'; import './visualization.scss'; import { desanitizeFilterContext } from '../utils'; import { ChartsPluginSetup } from '../../../../../src/plugins/charts/public'; +import { LensIconChartDonut } from '../assets/chart_donut'; const EMPTY_SLICE = Symbol('empty_slice'); @@ -186,7 +187,7 @@ export function PieComponent( const percentFormatter = props.formatFactory({ id: 'percent', params: { - pattern: `0,0.${'0'.repeat(percentDecimals ?? DEFAULT_PERCENT_DECIMALS)}%`, + pattern: `0,0.[${'0'.repeat(percentDecimals ?? DEFAULT_PERCENT_DECIMALS)}]%`, }, }); @@ -210,7 +211,7 @@ export function PieComponent( ); if (isEmpty) { - return ; + return ; } if (hasNegative) { diff --git a/x-pack/plugins/lens/public/pie_visualization/toolbar.tsx b/x-pack/plugins/lens/public/pie_visualization/toolbar.tsx index 501a2de24d9ad..9ee37fdf53a92 100644 --- a/x-pack/plugins/lens/public/pie_visualization/toolbar.tsx +++ b/x-pack/plugins/lens/public/pie_visualization/toolbar.tsx @@ -188,10 +188,10 @@ export function PieToolbar(props: VisualizationToolbarProps yAxisConfig.forAccessor === accessor)?.axisMode || 'auto'; - const formatter: SerializedFieldFormat = table.columns.find( - (column) => column.id === accessor - )?.formatHint || { id: 'number' }; + let formatter: SerializedFieldFormat = table.columns.find((column) => column.id === accessor) + ?.formatHint || { id: 'number' }; + if (layer.seriesType.includes('percentage') && formatter.id !== 'percent') { + formatter = { + id: 'percent', + params: { + pattern: '0.[00]%', + }, + }; + } series[mode].push({ layer: layer.layerId, accessor, diff --git a/x-pack/plugins/lens/public/xy_visualization/state_helpers.ts b/x-pack/plugins/lens/public/xy_visualization/state_helpers.ts index 2ddb9418abad9..41d18e5199e4c 100644 --- a/x-pack/plugins/lens/public/xy_visualization/state_helpers.ts +++ b/x-pack/plugins/lens/public/xy_visualization/state_helpers.ts @@ -8,7 +8,11 @@ import { EuiIconType } from '@elastic/eui/src/components/icon/icon'; import { SeriesType, visualizationTypes, LayerConfig, YConfig } from './types'; export function isHorizontalSeries(seriesType: SeriesType) { - return seriesType === 'bar_horizontal' || seriesType === 'bar_horizontal_stacked'; + return ( + seriesType === 'bar_horizontal' || + seriesType === 'bar_horizontal_stacked' || + seriesType === 'bar_horizontal_percentage_stacked' + ); } export function isHorizontalChart(layers: Array<{ seriesType: SeriesType }>) { diff --git a/x-pack/plugins/lens/public/xy_visualization/to_expression.test.ts b/x-pack/plugins/lens/public/xy_visualization/to_expression.test.ts index f579085646f6f..825281d6d88c2 100644 --- a/x-pack/plugins/lens/public/xy_visualization/to_expression.test.ts +++ b/x-pack/plugins/lens/public/xy_visualization/to_expression.test.ts @@ -100,25 +100,26 @@ describe('#toExpression', () => { expect(expression.chain[0].arguments.showYAxisTitle[0]).toBe(true); }); - it('should not generate an expression when missing x', () => { - expect( - xyVisualization.toExpression( - { - legend: { position: Position.Bottom, isVisible: true }, - preferredSeriesType: 'bar', - layers: [ - { - layerId: 'first', - seriesType: 'area', - splitAccessor: undefined, - xAccessor: undefined, - accessors: ['a'], - }, - ], - }, - frame.datasourceLayers - ) - ).toBeNull(); + it('should generate an expression without x accessor', () => { + const expression = xyVisualization.toExpression( + { + legend: { position: Position.Bottom, isVisible: true }, + preferredSeriesType: 'bar', + layers: [ + { + layerId: 'first', + seriesType: 'area', + splitAccessor: undefined, + xAccessor: undefined, + accessors: ['a'], + }, + ], + }, + frame.datasourceLayers + ) as Ast; + expect((expression.chain[0].arguments.layers[0] as Ast).chain[0].arguments.xAccessor).toEqual( + [] + ); }); it('should not generate an expression when missing y', () => { diff --git a/x-pack/plugins/lens/public/xy_visualization/to_expression.ts b/x-pack/plugins/lens/public/xy_visualization/to_expression.ts index cd32d4f94c3e5..f64624776186d 100644 --- a/x-pack/plugins/lens/public/xy_visualization/to_expression.ts +++ b/x-pack/plugins/lens/public/xy_visualization/to_expression.ts @@ -84,7 +84,7 @@ export const buildExpression = ( datasourceLayers?: Record ): Ast | null => { const validLayers = state.layers.filter((layer): layer is ValidLayer => - Boolean(layer.xAccessor && layer.accessors.length) + Boolean(layer.accessors.length) ); if (!validLayers.length) { return null; @@ -187,7 +187,7 @@ export const buildExpression = ( hide: [Boolean(layer.hide)], - xAccessor: [layer.xAccessor], + xAccessor: layer.xAccessor ? [layer.xAccessor] : [], yScaleType: [ getScaleType(metadata[layer.layerId][layer.accessors[0]], ScaleType.Ordinal), ], diff --git a/x-pack/plugins/lens/public/xy_visualization/types.ts b/x-pack/plugins/lens/public/xy_visualization/types.ts index 2739ffe42f13f..8438b1f27dd0d 100644 --- a/x-pack/plugins/lens/public/xy_visualization/types.ts +++ b/x-pack/plugins/lens/public/xy_visualization/types.ts @@ -7,13 +7,16 @@ import { Position } from '@elastic/charts'; import { i18n } from '@kbn/i18n'; import { ArgumentType, ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; -import chartAreaSVG from '../assets/chart_area.svg'; -import chartAreaStackedSVG from '../assets/chart_area_stacked.svg'; -import chartBarSVG from '../assets/chart_bar.svg'; -import chartBarStackedSVG from '../assets/chart_bar_stacked.svg'; -import chartBarHorizontalSVG from '../assets/chart_bar_horizontal.svg'; -import chartBarHorizontalStackedSVG from '../assets/chart_bar_horizontal_stacked.svg'; -import chartLineSVG from '../assets/chart_line.svg'; +import { LensIconChartArea } from '../assets/chart_area'; +import { LensIconChartAreaStacked } from '../assets/chart_area_stacked'; +import { LensIconChartAreaPercentage } from '../assets/chart_area_percentage'; +import { LensIconChartBar } from '../assets/chart_bar'; +import { LensIconChartBarStacked } from '../assets/chart_bar_stacked'; +import { LensIconChartBarPercentage } from '../assets/chart_bar_percentage'; +import { LensIconChartBarHorizontal } from '../assets/chart_bar_horizontal'; +import { LensIconChartBarHorizontalStacked } from '../assets/chart_bar_horizontal_stacked'; +import { LensIconChartBarHorizontalPercentage } from '../assets/chart_bar_horizontal_percentage'; +import { LensIconChartLine } from '../assets/chart_line'; import { VisualizationType } from '../index'; import { FittingFunction } from './fitting_functions'; @@ -230,7 +233,15 @@ export const layerConfig: ExpressionFunctionDefinition< }, seriesType: { types: ['string'], - options: ['bar', 'line', 'area', 'bar_stacked', 'area_stacked'], + options: [ + 'bar', + 'line', + 'area', + 'bar_stacked', + 'area_stacked', + 'bar_percentage_stacked', + 'area_percentage_stacked', + ], help: 'The type of chart to display.', }, xScaleType: { @@ -283,8 +294,11 @@ export type SeriesType = | 'line' | 'area' | 'bar_stacked' + | 'bar_percentage_stacked' | 'bar_horizontal_stacked' - | 'area_stacked'; + | 'bar_horizontal_percentage_stacked' + | 'area_stacked' + | 'area_percentage_stacked'; export type YAxisMode = 'auto' | 'left' | 'right'; @@ -343,58 +357,72 @@ export type State = XYState; export const visualizationTypes: VisualizationType[] = [ { id: 'bar', - icon: 'visBarVertical', - largeIcon: chartBarSVG, + icon: LensIconChartBar, label: i18n.translate('xpack.lens.xyVisualization.barLabel', { defaultMessage: 'Bar', }), }, { id: 'bar_horizontal', - icon: 'visBarHorizontal', - largeIcon: chartBarHorizontalSVG, + icon: LensIconChartBarHorizontal, label: i18n.translate('xpack.lens.xyVisualization.barHorizontalLabel', { defaultMessage: 'Horizontal bar', }), }, { id: 'bar_stacked', - icon: 'visBarVerticalStacked', - largeIcon: chartBarStackedSVG, + icon: LensIconChartBarStacked, label: i18n.translate('xpack.lens.xyVisualization.stackedBarLabel', { defaultMessage: 'Stacked bar', }), }, + { + id: 'bar_percentage_stacked', + icon: LensIconChartBarPercentage, + label: i18n.translate('xpack.lens.xyVisualization.stackedPercentageBarLabel', { + defaultMessage: 'Bar percentage', + }), + }, { id: 'bar_horizontal_stacked', - icon: 'visBarHorizontalStacked', - largeIcon: chartBarHorizontalStackedSVG, + icon: LensIconChartBarHorizontalStacked, label: i18n.translate('xpack.lens.xyVisualization.stackedBarHorizontalLabel', { defaultMessage: 'Stacked horizontal bar', }), }, { - id: 'line', - icon: 'visLine', - largeIcon: chartLineSVG, - label: i18n.translate('xpack.lens.xyVisualization.lineLabel', { - defaultMessage: 'Line', + id: 'bar_horizontal_percentage_stacked', + icon: LensIconChartBarHorizontalPercentage, + label: i18n.translate('xpack.lens.xyVisualization.stackedPercentageBarHorizontalLabel', { + defaultMessage: 'Horizontal bar percentage', }), }, { id: 'area', - icon: 'visArea', - largeIcon: chartAreaSVG, + icon: LensIconChartArea, label: i18n.translate('xpack.lens.xyVisualization.areaLabel', { defaultMessage: 'Area', }), }, { id: 'area_stacked', - icon: 'visAreaStacked', - largeIcon: chartAreaStackedSVG, + icon: LensIconChartAreaStacked, label: i18n.translate('xpack.lens.xyVisualization.stackedAreaLabel', { defaultMessage: 'Stacked area', }), }, + { + id: 'area_percentage_stacked', + icon: LensIconChartAreaPercentage, + label: i18n.translate('xpack.lens.xyVisualization.stackedPercentageAreaLabel', { + defaultMessage: 'Area percentage', + }), + }, + { + id: 'line', + icon: LensIconChartLine, + label: i18n.translate('xpack.lens.xyVisualization.lineLabel', { + defaultMessage: 'Line', + }), + }, ]; diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_config_panel.test.tsx b/x-pack/plugins/lens/public/xy_visualization/xy_config_panel.test.tsx index e80bb22c04a69..89a2574026ced 100644 --- a/x-pack/plugins/lens/public/xy_visualization/xy_config_panel.test.tsx +++ b/x-pack/plugins/lens/public/xy_visualization/xy_config_panel.test.tsx @@ -59,9 +59,11 @@ describe('XY Config panels', () => { expect(options!.map(({ id }) => id)).toEqual([ 'bar', 'bar_stacked', - 'line', + 'bar_percentage_stacked', 'area', 'area_stacked', + 'area_percentage_stacked', + 'line', ]); expect(options!.filter(({ isDisabled }) => isDisabled).map(({ id }) => id)).toEqual([]); @@ -83,7 +85,11 @@ describe('XY Config panels', () => { .first() .prop('options') as EuiButtonGroupProps['options']; - expect(options!.map(({ id }) => id)).toEqual(['bar_horizontal', 'bar_horizontal_stacked']); + expect(options!.map(({ id }) => id)).toEqual([ + 'bar_horizontal', + 'bar_horizontal_stacked', + 'bar_horizontal_percentage_stacked', + ]); expect(options!.filter(({ isDisabled }) => isDisabled).map(({ id }) => id)).toEqual([]); }); }); diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_config_panel.tsx b/x-pack/plugins/lens/public/xy_visualization/xy_config_panel.tsx index a2488d123e13a..62fd6e013f20d 100644 --- a/x-pack/plugins/lens/public/xy_visualization/xy_config_panel.tsx +++ b/x-pack/plugins/lens/public/xy_visualization/xy_config_panel.tsx @@ -114,7 +114,6 @@ export function LayerContextMenu(props: VisualizationLayerWidgetProps) { ); }} isIconOnly - buttonSize="compressed" /> ); diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_expression.tsx b/x-pack/plugins/lens/public/xy_visualization/xy_expression.tsx index 31873228fb394..a8c7c8daaf58b 100644 --- a/x-pack/plugins/lens/public/xy_visualization/xy_expression.tsx +++ b/x-pack/plugins/lens/public/xy_visualization/xy_expression.tsx @@ -17,6 +17,7 @@ import { Position, GeometryValue, XYChartSeriesIdentifier, + StackMode, } from '@elastic/charts'; import { I18nProvider } from '@kbn/i18n/react'; import { @@ -229,11 +230,10 @@ export function XYChart({ const filteredLayers = layers.filter(({ layerId, xAccessor, accessors }) => { return !( - !xAccessor || !accessors.length || !data.tables[layerId] || data.tables[layerId].rows.length === 0 || - data.tables[layerId].rows.every((row) => typeof row[xAccessor] === 'undefined') + (xAccessor && data.tables[layerId].rows.every((row) => typeof row[xAccessor] === 'undefined')) ); }); @@ -425,7 +425,7 @@ export function XYChart({ visible: gridlinesVisibilitySettings?.x, strokeWidth: 2, }} - hide={filteredLayers[0].hide} + hide={filteredLayers[0].hide || !filteredLayers[0].xAccessor} tickFormat={(d) => xAxisFormatter.convert(d)} style={{ tickLabel: { @@ -483,8 +483,7 @@ export function XYChart({ // To not display them in the legend, they need to be filtered out. const rows = table.rows.filter( (row) => - xAccessor && - typeof row[xAccessor] !== 'undefined' && + !(xAccessor && typeof row[xAccessor] === 'undefined') && !( splitAccessor && typeof row[splitAccessor] === 'undefined' && @@ -492,21 +491,42 @@ export function XYChart({ ) ); + if (!xAccessor) { + rows.forEach((row) => { + row.unifiedX = i18n.translate('xpack.lens.xyChart.emptyXLabel', { + defaultMessage: '(empty)', + }); + }); + } + const seriesProps: SeriesSpec = { splitSeriesAccessors: splitAccessor ? [splitAccessor] : [], stackAccessors: seriesType.includes('stacked') ? [xAccessor as string] : [], id: `${splitAccessor}-${accessor}`, - xAccessor, + xAccessor: xAccessor || 'unifiedX', yAccessors: [accessor], data: rows, - xScaleType, + xScaleType: xAccessor ? xScaleType : 'ordinal', yScaleType, color: () => getSeriesColor(layer, accessor), groupId: yAxesConfiguration.find((axisConfiguration) => axisConfiguration.series.find((currentSeries) => currentSeries.accessor === accessor) )?.groupId, enableHistogramMode: isHistogram && (seriesType.includes('stacked') || !splitAccessor), + stackMode: seriesType.includes('percentage') ? StackMode.Percentage : undefined, timeZone, + areaSeriesStyle: { + point: { + visible: !xAccessor, + radius: 5, + }, + }, + lineSeriesStyle: { + point: { + visible: !xAccessor, + radius: 5, + }, + }, name(d) { const splitHint = table.columns.find((col) => col.id === splitAccessor)?.formatHint; @@ -545,10 +565,13 @@ export function XYChart({ ); case 'bar': case 'bar_stacked': + case 'bar_percentage_stacked': case 'bar_horizontal': case 'bar_horizontal_stacked': + case 'bar_horizontal_percentage_stacked': return ; case 'area_stacked': + case 'area_percentage_stacked': return ( ); diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.test.ts b/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.test.ts index 79e4ed6958193..ea5cff80695a3 100644 --- a/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.test.ts +++ b/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.test.ts @@ -119,6 +119,51 @@ describe('xy_suggestions', () => { ); }); + test('suggests all xy charts without changes to the state when switching among xy charts with malformed table', () => { + (generateId as jest.Mock).mockReturnValueOnce('aaa'); + const suggestions = getSuggestions({ + table: { + isMultiRow: false, + columns: [numCol('bytes')], + layerId: 'first', + changeType: 'unchanged', + }, + keptLayerIds: [], + state: { + legend: { isVisible: true, position: 'bottom' }, + preferredSeriesType: 'bar', + layers: [ + { + layerId: 'first', + seriesType: 'bar', + accessors: ['bytes'], + splitAccessor: undefined, + }, + { + layerId: 'second', + seriesType: 'bar', + accessors: ['bytes'], + splitAccessor: undefined, + }, + ], + }, + }); + + expect(suggestions).toHaveLength(visualizationTypes.length); + expect(suggestions.map(({ state }) => xyVisualization.getVisualizationTypeId(state))).toEqual([ + 'bar', + 'bar_horizontal', + 'bar_stacked', + 'bar_percentage_stacked', + 'bar_horizontal_stacked', + 'bar_horizontal_percentage_stacked', + 'area', + 'area_stacked', + 'area_percentage_stacked', + 'line', + ]); + }); + test('suggests all basic x y charts when switching from another vis', () => { (generateId as jest.Mock).mockReturnValueOnce('aaa'); const suggestions = getSuggestions({ @@ -134,10 +179,13 @@ describe('xy_suggestions', () => { expect(suggestions).toHaveLength(visualizationTypes.length); expect(suggestions.map(({ state }) => xyVisualization.getVisualizationTypeId(state))).toEqual([ 'bar_stacked', + 'line', + 'area_percentage_stacked', 'area_stacked', 'area', - 'line', + 'bar_horizontal_percentage_stacked', 'bar_horizontal_stacked', + 'bar_percentage_stacked', 'bar_horizontal', 'bar', ]); @@ -157,13 +205,27 @@ describe('xy_suggestions', () => { }); expect(suggestions).toHaveLength(visualizationTypes.length); - expect(suggestions.map(({ state }) => state.layers.length)).toEqual([1, 1, 1, 1, 1, 1, 1]); + expect(suggestions.map(({ state }) => state.layers.length)).toEqual([ + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + ]); expect(suggestions.map(({ state }) => xyVisualization.getVisualizationTypeId(state))).toEqual([ 'bar_stacked', + 'line', + 'area_percentage_stacked', 'area_stacked', 'area', - 'line', + 'bar_horizontal_percentage_stacked', 'bar_horizontal_stacked', + 'bar_percentage_stacked', 'bar_horizontal', 'bar', ]); @@ -200,9 +262,12 @@ describe('xy_suggestions', () => { 'bar', 'bar_horizontal', 'bar_stacked', + 'bar_percentage_stacked', 'bar_horizontal_stacked', + 'bar_horizontal_percentage_stacked', 'area', 'area_stacked', + 'area_percentage_stacked', ]); }); @@ -244,9 +309,12 @@ describe('xy_suggestions', () => { 'bar', 'bar_horizontal', 'bar_stacked', + 'bar_percentage_stacked', 'bar_horizontal_stacked', + 'bar_horizontal_percentage_stacked', 'area', 'area_stacked', + 'area_percentage_stacked', ]); expect(suggestions.map(({ state }) => state.layers.map((l) => l.layerId))).toEqual([ ['first', 'second'], @@ -256,6 +324,9 @@ describe('xy_suggestions', () => { ['first', 'second'], ['first', 'second'], ['first', 'second'], + ['first', 'second'], + ['first', 'second'], + ['first', 'second'], ]); }); diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.ts b/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.ts index 75dd5a7a579b8..42fc538874b93 100644 --- a/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.ts +++ b/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.ts @@ -45,6 +45,24 @@ export function getSuggestions({ table.columns.every((col) => col.operation.dataType !== 'number') || table.columns.some((col) => !columnSortOrder.hasOwnProperty(col.operation.dataType)) ) { + if (table.changeType === 'unchanged' && state) { + // this isn't a table we would switch to, but we have a state already. In this case, just use the current state for all series types + return visualizationTypes.map((visType) => { + const seriesType = visType.id as SeriesType; + return { + seriesType, + score: 0, + state: { + ...state, + preferredSeriesType: seriesType, + layers: state.layers.map((layer) => ({ ...layer, seriesType })), + }, + previewIcon: getIconForSeries(seriesType), + title: visType.label, + hide: true, + }; + }); + } return []; } @@ -91,6 +109,25 @@ function getSuggestionForColumns( } } +function flipSeriesType(seriesType: SeriesType) { + switch (seriesType) { + case 'bar_horizontal': + return 'bar'; + case 'bar_horizontal_stacked': + return 'bar_stacked'; + case 'bar': + return 'bar_horizontal'; + case 'bar_horizontal_stacked': + return 'bar_stacked'; + case 'bar_horizontal_percentage_stacked': + return 'bar_percentage_stacked'; + case 'bar_percentage_stacked': + return 'bar_horizontal_percentage_stacked'; + default: + return 'bar_horizontal'; + } +} + function getBucketMappings(table: TableSuggestion, currentState?: State) { const currentLayer = currentState && currentState.layers.find(({ layerId }) => layerId === table.layerId); @@ -156,7 +193,7 @@ function getSuggestionsForLayer({ }: { layerId: string; changeType: TableChangeType; - xValue: TableSuggestionColumn; + xValue?: TableSuggestionColumn; yValues: TableSuggestionColumn[]; splitBy?: TableSuggestionColumn; currentState?: State; @@ -164,7 +201,7 @@ function getSuggestionsForLayer({ keptLayerIds: string[]; }): VisualizationSuggestion | Array> { const title = getSuggestionTitle(yValues, xValue, tableLabel); - const seriesType: SeriesType = getSeriesType(currentState, layerId, xValue, changeType); + const seriesType: SeriesType = getSeriesType(currentState, layerId, xValue); const options = { currentState, @@ -182,11 +219,13 @@ function getSuggestionsForLayer({ if (!currentState && changeType === 'unchanged') { // Chart switcher needs to include every chart type return visualizationTypes - .map((visType) => ({ - ...buildSuggestion({ ...options, seriesType: visType.id as SeriesType }), - title: visType.label, - hide: visType.id !== 'bar_stacked', - })) + .map((visType) => { + return { + ...buildSuggestion({ ...options, seriesType: visType.id as SeriesType }), + title: visType.label, + hide: visType.id !== 'bar_stacked', + }; + }) .sort((a, b) => (a.state.preferredSeriesType === 'bar_stacked' ? -1 : 1)); } @@ -199,18 +238,13 @@ function getSuggestionsForLayer({ const sameStateSuggestions: Array> = []; // if current state is using the same data, suggest same chart with different presentational configuration - if (seriesType !== 'line' && xValue.operation.scale === 'ordinal') { + if (seriesType.includes('bar') && (!xValue || xValue.operation.scale === 'ordinal')) { // flip between horizontal/vertical for ordinal scales sameStateSuggestions.push( buildSuggestion({ ...options, title: i18n.translate('xpack.lens.xySuggestions.flipTitle', { defaultMessage: 'Flip' }), - seriesType: - seriesType === 'bar_horizontal' - ? 'bar' - : seriesType === 'bar_horizontal_stacked' - ? 'bar_stacked' - : 'bar_horizontal', + seriesType: flipSeriesType(seriesType), }) ); } else { @@ -231,7 +265,7 @@ function getSuggestionsForLayer({ ); } - if (seriesType !== 'line' && splitBy) { + if (seriesType !== 'line' && splitBy && !seriesType.includes('percentage')) { // flip between stacked/unstacked sameStateSuggestions.push( buildSuggestion({ @@ -248,6 +282,30 @@ function getSuggestionsForLayer({ ); } + if ( + seriesType !== 'line' && + seriesType.includes('stacked') && + !seriesType.includes('percentage') + ) { + const percentageOptions = { ...options }; + if (percentageOptions.xValue?.operation.scale === 'ordinal' && !percentageOptions.splitBy) { + percentageOptions.splitBy = percentageOptions.xValue; + delete percentageOptions.xValue; + } + // percentage suggestion + sameStateSuggestions.push( + buildSuggestion({ + ...options, + // hide the suggestion if split by is missing + hide: !percentageOptions.splitBy, + seriesType: asPercentageSeriesType(seriesType), + title: i18n.translate('xpack.lens.xySuggestions.asPercentageTitle', { + defaultMessage: 'Percentage', + }), + }) + ); + } + // Combine all pre-built suggestions with hidden suggestions for remaining chart types return sameStateSuggestions.concat( visualizationTypes @@ -280,6 +338,19 @@ function toggleStackSeriesType(oldSeriesType: SeriesType) { } } +function asPercentageSeriesType(oldSeriesType: SeriesType) { + switch (oldSeriesType) { + case 'area_stacked': + return 'area_percentage_stacked'; + case 'bar_stacked': + return 'bar_percentage_stacked'; + case 'bar_horizontal_stacked': + return 'bar_horizontal_percentage_stacked'; + default: + return oldSeriesType; + } +} + // Until the area chart rendering bug is fixed, avoid suggesting area charts // https://github.com/elastic/elastic-charts/issues/388 function altSeriesType(oldSeriesType: SeriesType) { @@ -301,8 +372,7 @@ function altSeriesType(oldSeriesType: SeriesType) { function getSeriesType( currentState: XYState | undefined, layerId: string, - xValue: TableSuggestionColumn, - changeType: TableChangeType + xValue?: TableSuggestionColumn ): SeriesType { const defaultType = 'bar_stacked'; @@ -314,7 +384,7 @@ function getSeriesType( // Attempt to keep the seriesType consistent on initial add of a layer // Ordinal scales should always use a bar because there is no interpolation between buckets - if (xValue.operation.scale && xValue.operation.scale === 'ordinal') { + if (xValue && xValue.operation.scale && xValue.operation.scale === 'ordinal') { return closestSeriesType.startsWith('bar') ? closestSeriesType : defaultType; } @@ -323,7 +393,7 @@ function getSeriesType( function getSuggestionTitle( yValues: TableSuggestionColumn[], - xValue: TableSuggestionColumn, + xValue: TableSuggestionColumn | undefined, tableLabel: string | undefined ) { const yTitle = yValues @@ -335,10 +405,14 @@ function getSuggestionTitle( 'A character that can be used for conjunction of multiple enumarated items. Make sure to include spaces around it if needed.', }) ); - const xTitle = xValue.operation.label; + const xTitle = + xValue?.operation.label || + i18n.translate('xpack.lens.xySuggestions.emptyAxisTitle', { + defaultMessage: '(empty)', + }); const title = tableLabel || - (xValue.operation.dataType === 'date' + (xValue?.operation.dataType === 'date' ? i18n.translate('xpack.lens.xySuggestions.dateSuggestion', { defaultMessage: '{yTitle} over {xTitle}', description: @@ -364,24 +438,30 @@ function buildSuggestion({ changeType, xValue, keptLayerIds, + hide, }: { currentState: XYState | undefined; seriesType: SeriesType; title: string; yValues: TableSuggestionColumn[]; - xValue: TableSuggestionColumn; + xValue?: TableSuggestionColumn; splitBy: TableSuggestionColumn | undefined; layerId: string; changeType: TableChangeType; keptLayerIds: string[]; + hide?: boolean; }) { + if (seriesType.includes('percentage') && xValue?.operation.scale === 'ordinal' && !splitBy) { + splitBy = xValue; + xValue = undefined; + } const existingLayer: LayerConfig | {} = getExistingLayer(currentState, layerId) || {}; const accessors = yValues.map((col) => col.columnId); const newLayer = { ...existingLayer, layerId, seriesType, - xAccessor: xValue.columnId, + xAccessor: xValue?.columnId, splitAccessor: splitBy?.columnId, accessors, yConfig: @@ -427,10 +507,11 @@ function buildSuggestion({ title, score: getScore(yValues, splitBy, changeType), hide: + hide ?? // Only advertise very clear changes when XY chart is not active - (!currentState && changeType !== 'unchanged' && changeType !== 'extended') || - // Don't advertise removing dimensions - (currentState && changeType === 'reduced'), + ((!currentState && changeType !== 'unchanged' && changeType !== 'extended') || + // Don't advertise removing dimensions + (currentState && changeType === 'reduced')), state, previewIcon: getIconForSeries(seriesType), }; diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_visualization.test.ts b/x-pack/plugins/lens/public/xy_visualization/xy_visualization.test.ts index 53f7a23dcae98..7cf1830cdc2fa 100644 --- a/x-pack/plugins/lens/public/xy_visualization/xy_visualization.test.ts +++ b/x-pack/plugins/lens/public/xy_visualization/xy_visualization.test.ts @@ -9,6 +9,7 @@ import { Position } from '@elastic/charts'; import { Operation } from '../types'; import { State, SeriesType } from './types'; import { createMockDatasource, createMockFramePublicAPI } from '../editor_frame_service/mocks'; +import { LensIconChartBar } from '../assets/chart_bar'; function exampleState(): State { return { @@ -49,9 +50,7 @@ describe('xy_visualization', () => { it('should show the preferredSeriesType if there are no layers', () => { const desc = xyVisualization.getDescription(mixedState()); - // 'test-file-stub' is a hack, but it at least means we aren't using - // a standard icon here. - expect(desc.icon).toEqual('test-file-stub'); + expect(desc.icon).toEqual(LensIconChartBar); expect(desc.label).toEqual('Bar chart'); }); diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_visualization.tsx b/x-pack/plugins/lens/public/xy_visualization/xy_visualization.tsx index 8c551c575764e..0b8f7e2ed0f11 100644 --- a/x-pack/plugins/lens/public/xy_visualization/xy_visualization.tsx +++ b/x-pack/plugins/lens/public/xy_visualization/xy_visualization.tsx @@ -14,12 +14,13 @@ import { getSuggestions } from './xy_suggestions'; import { LayerContextMenu, XyToolbar, DimensionEditor } from './xy_config_panel'; import { Visualization, OperationMetadata, VisualizationType } from '../types'; import { State, SeriesType, visualizationTypes, LayerConfig } from './types'; -import chartBarStackedSVG from '../assets/chart_bar_stacked.svg'; -import chartMixedSVG from '../assets/chart_mixed_xy.svg'; import { isHorizontalChart } from './state_helpers'; import { toExpression, toPreviewExpression } from './to_expression'; +import { LensIconChartBarStacked } from '../assets/chart_bar_stacked'; +import { LensIconChartMixedXy } from '../assets/chart_mixed_xy'; +import { LensIconChartBarHorizontal } from '../assets/chart_bar_horizontal'; -const defaultIcon = chartBarStackedSVG; +const defaultIcon = LensIconChartBarStacked; const defaultSeriesType = 'bar_stacked'; const isNumericMetric = (op: OperationMetadata) => !op.isBucketed && op.dataType === 'number'; const isBucketed = (op: OperationMetadata) => op.isBucketed; @@ -48,29 +49,27 @@ function getDescription(state?: State) { const visualizationType = getVisualizationType(state); - if (!state.layers.length) { - const preferredType = visualizationType as VisualizationType; + if (visualizationType === 'mixed' && isHorizontalChart(state.layers)) { + return { + icon: LensIconChartBarHorizontal, + label: i18n.translate('xpack.lens.xyVisualization.mixedBarHorizontalLabel', { + defaultMessage: 'Mixed horizontal bar', + }), + }; + } + + if (visualizationType === 'mixed') { return { - icon: preferredType.largeIcon || preferredType.icon, - label: preferredType.label, + icon: LensIconChartMixedXy, + label: i18n.translate('xpack.lens.xyVisualization.mixedLabel', { + defaultMessage: 'Mixed XY', + }), }; } return { - icon: - visualizationType === 'mixed' - ? chartMixedSVG - : visualizationType.largeIcon || visualizationType.icon, - label: - visualizationType === 'mixed' - ? isHorizontalChart(state.layers) - ? i18n.translate('xpack.lens.xyVisualization.mixedBarHorizontalLabel', { - defaultMessage: 'Mixed horizontal bar', - }) - : i18n.translate('xpack.lens.xyVisualization.mixedLabel', { - defaultMessage: 'Mixed XY', - }) - : visualizationType.label, + icon: visualizationType.icon, + label: visualizationType.label, }; } @@ -172,7 +171,7 @@ export const xyVisualization: Visualization = { filterOperations: isBucketed, suggestedPriority: 1, supportsMoreColumns: !layer.xAccessor, - required: true, + required: !layer.seriesType.includes('percentage'), dataTestSubj: 'lnsXY_xDimensionPanel', }, { @@ -197,6 +196,7 @@ export const xyVisualization: Visualization = { suggestedPriority: 0, supportsMoreColumns: !layer.splitAccessor, dataTestSubj: 'lnsXY_splitDimensionPanel', + required: layer.seriesType.includes('percentage'), }, ], }; diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index a0aa285b43848..0977e99fa0c3c 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -9691,7 +9691,6 @@ "xpack.lens.pieChart.legendDisplayLegend": "凡例表示", "xpack.lens.pieChart.nestedLegendLabel": "ネストされた凡例", "xpack.lens.pieChart.numberLabels": "ラベル値", - "xpack.lens.pieChart.percentDecimalsLabel": "割合の小数点桁数", "xpack.lens.pieChart.showCategoriesLabel": "内部または外部", "xpack.lens.pieChart.showFormatterValuesLabel": "値を表示", "xpack.lens.pieChart.showPercentValuesLabel": "割合を表示", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 01cd7f569d13b..7f8f2a98abae3 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -9697,7 +9697,6 @@ "xpack.lens.pieChart.legendDisplayLegend": "图例显示", "xpack.lens.pieChart.nestedLegendLabel": "嵌套图例", "xpack.lens.pieChart.numberLabels": "标签值", - "xpack.lens.pieChart.percentDecimalsLabel": "百分比的小数位数", "xpack.lens.pieChart.showCategoriesLabel": "内部或外部", "xpack.lens.pieChart.showFormatterValuesLabel": "显示值", "xpack.lens.pieChart.showPercentValuesLabel": "显示百分比",