From d5a3a29489b0c535acdace200d1ed31b902b7381 Mon Sep 17 00:00:00 2001 From: Yaroslav Kuznietsov Date: Wed, 19 Oct 2022 13:25:39 +0300 Subject: [PATCH 01/26] Added base code for converting heatmap to lens. --- src/plugins/vis_types/heatmap/kibana.json | 39 ++++++--- .../convert_to_lens/configurations/index.ts | 11 +++ .../heatmap/public/convert_to_lens/index.ts | 81 +++++++++++++++++++ .../heatmap/public/convert_to_lens/types.ts | 17 ++++ .../vis_types/heatmap/public/plugin.ts | 13 ++- .../vis_types/heatmap/public/services.ts | 13 +++ src/plugins/vis_types/pie/kibana.json | 39 ++++++--- .../convert_to_lens/types/configurations.ts | 52 +++++++++++- 8 files changed, 236 insertions(+), 29 deletions(-) create mode 100644 src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.ts create mode 100644 src/plugins/vis_types/heatmap/public/convert_to_lens/index.ts create mode 100644 src/plugins/vis_types/heatmap/public/convert_to_lens/types.ts create mode 100644 src/plugins/vis_types/heatmap/public/services.ts diff --git a/src/plugins/vis_types/heatmap/kibana.json b/src/plugins/vis_types/heatmap/kibana.json index c8df98e2b343a..b7f4a3bacbb90 100644 --- a/src/plugins/vis_types/heatmap/kibana.json +++ b/src/plugins/vis_types/heatmap/kibana.json @@ -1,14 +1,27 @@ { - "id": "visTypeHeatmap", - "version": "kibana", - "ui": true, - "server": true, - "requiredPlugins": ["charts", "data", "expressions", "visualizations", "usageCollection", "fieldFormats"], - "requiredBundles": ["visDefaultEditor"], - "extraPublicDirs": ["common/index"], - "owner": { - "name": "Vis Editors", - "githubTeam": "kibana-vis-editors" - }, - "description": "Contains the heatmap implementation using the elastic-charts library. The goal is to eventually deprecate the old implementation and keep only this. Until then, the library used is defined by the Legacy heatmap charts library advanced setting." - } + "id": "visTypeHeatmap", + "version": "kibana", + "ui": true, + "server": true, + "requiredPlugins": [ + "charts", + "data", + "expressions", + "visualizations", + "usageCollection", + "fieldFormats", + "dataViews" + ], + "requiredBundles": [ + "visDefaultEditor", + "kibanaUtils" + ], + "extraPublicDirs": [ + "common/index" + ], + "owner": { + "name": "Vis Editors", + "githubTeam": "kibana-vis-editors" + }, + "description": "Contains the heatmap implementation using the elastic-charts library. The goal is to eventually deprecate the old implementation and keep only this. Until then, the library used is defined by the Legacy heatmap charts library advanced setting." +} \ No newline at end of file diff --git a/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.ts b/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.ts new file mode 100644 index 0000000000000..f784073c543b9 --- /dev/null +++ b/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.ts @@ -0,0 +1,11 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export const getConfiguration = () => { + return {} as any; +}; diff --git a/src/plugins/vis_types/heatmap/public/convert_to_lens/index.ts b/src/plugins/vis_types/heatmap/public/convert_to_lens/index.ts new file mode 100644 index 0000000000000..a1612f692dacb --- /dev/null +++ b/src/plugins/vis_types/heatmap/public/convert_to_lens/index.ts @@ -0,0 +1,81 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { Column, ColumnWithMeta } from '@kbn/visualizations-plugin/common'; +import { + convertToLensModule, + getDataViewByIndexPatternId, +} from '@kbn/visualizations-plugin/public'; +import uuid from 'uuid'; +import { getDataViewsStart } from '../services'; +import { getConfiguration } from './configurations'; +import { ConvertHeatmapToLensVisualization } from './types'; + +export const isColumnWithMeta = (column: Column): column is ColumnWithMeta => { + if ((column as ColumnWithMeta).meta) { + return true; + } + return false; +}; + +export const excludeMetaFromColumn = (column: Column) => { + if (isColumnWithMeta(column)) { + const { meta, ...rest } = column; + return rest; + } + return column; +}; + +export const convertToLens: ConvertHeatmapToLensVisualization = async (vis, timefilter) => { + if (!timefilter) { + return null; + } + + const dataViews = getDataViewsStart(); + const dataView = await getDataViewByIndexPatternId(vis.data.indexPattern?.id, dataViews); + + if (!dataView) { + return null; + } + + const { getColumnsFromVis } = await convertToLensModule; + const layers = getColumnsFromVis(vis, timefilter, dataView, { + buckets: ['segment', 'group'], + splits: [], + unsupported: ['split_row', 'split_column'], + }); + + if (layers === null) { + return null; + } + + const [layerConfig] = layers; + + // doesn't support more than three split slice levels + // doesn't support pie without at least one split slice + if (layerConfig.buckets.all.length > 3 || !layerConfig.buckets.all.length) { + return null; + } + + const layerId = uuid(); + + const indexPatternId = dataView.id!; + return { + type: 'lnsPie', + layers: [ + { + indexPatternId, + layerId, + columns: layerConfig.columns.map(excludeMetaFromColumn), + columnOrder: [], + }, + ], + configuration: getConfiguration(), + indexPatternIds: [indexPatternId], + }; +}; diff --git a/src/plugins/vis_types/heatmap/public/convert_to_lens/types.ts b/src/plugins/vis_types/heatmap/public/convert_to_lens/types.ts new file mode 100644 index 0000000000000..732b977dd7b59 --- /dev/null +++ b/src/plugins/vis_types/heatmap/public/convert_to_lens/types.ts @@ -0,0 +1,17 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { TimefilterContract } from '@kbn/data-plugin/public'; +import { NavigateToLensContext, HeatmapConfiguration } from '@kbn/visualizations-plugin/common'; +import { Vis } from '@kbn/visualizations-plugin/public'; +import { HeatmapVisParams } from '../types'; + +export type ConvertHeatmapToLensVisualization = ( + vis: Vis, + timefilter?: TimefilterContract +) => Promise | null>; diff --git a/src/plugins/vis_types/heatmap/public/plugin.ts b/src/plugins/vis_types/heatmap/public/plugin.ts index 44357cceaa86b..ee7349145e7c6 100644 --- a/src/plugins/vis_types/heatmap/public/plugin.ts +++ b/src/plugins/vis_types/heatmap/public/plugin.ts @@ -6,14 +6,16 @@ * Side Public License, v 1. */ -import { CoreSetup } from '@kbn/core/public'; +import { CoreSetup, CoreStart } from '@kbn/core/public'; import type { VisualizationsSetup } from '@kbn/visualizations-plugin/public'; import type { ChartsPluginSetup } from '@kbn/charts-plugin/public'; +import { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public'; import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; import { LEGACY_HEATMAP_CHARTS_LIBRARY } from '../common'; import { heatmapVisType } from './vis_type'; +import { setDataViewsStart } from './services'; /** @internal */ export interface VisTypeHeatmapSetupDependencies { @@ -28,6 +30,11 @@ export interface VisTypeHeatmapPluginStartDependencies { fieldFormats: FieldFormatsStart; } +/** @internal */ +export interface VisTypeHeatmapStartDependencies { + dataViews: DataViewsPublicPluginStart; +} + export class VisTypeHeatmapPlugin { setup( core: CoreSetup, @@ -44,5 +51,7 @@ export class VisTypeHeatmapPlugin { return {}; } - start() {} + start(core: CoreStart, { dataViews }: VisTypeHeatmapStartDependencies) { + setDataViewsStart(dataViews); + } } diff --git a/src/plugins/vis_types/heatmap/public/services.ts b/src/plugins/vis_types/heatmap/public/services.ts new file mode 100644 index 0000000000000..736ad70d49419 --- /dev/null +++ b/src/plugins/vis_types/heatmap/public/services.ts @@ -0,0 +1,13 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { createGetterSetter } from '@kbn/kibana-utils-plugin/public'; +import { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; + +export const [getDataViewsStart, setDataViewsStart] = + createGetterSetter('dataViews'); diff --git a/src/plugins/vis_types/pie/kibana.json b/src/plugins/vis_types/pie/kibana.json index 4c5ee6b50579e..d9dca861e33be 100644 --- a/src/plugins/vis_types/pie/kibana.json +++ b/src/plugins/vis_types/pie/kibana.json @@ -1,14 +1,27 @@ { - "id": "visTypePie", - "version": "kibana", - "ui": true, - "server": true, - "requiredPlugins": ["charts", "data", "expressions", "visualizations", "usageCollection", "expressionPartitionVis", "dataViews"], - "requiredBundles": ["visDefaultEditor", "kibanaUtils"], - "extraPublicDirs": ["common/index"], - "owner": { - "name": "Vis Editors", - "githubTeam": "kibana-vis-editors" - }, - "description": "Contains the pie chart implementation using the elastic-charts library. The goal is to eventually deprecate the old implementation and keep only this. Until then, the library used is defined by the Legacy charts library advanced setting." - } + "id": "visTypePie", + "version": "kibana", + "ui": true, + "server": true, + "requiredPlugins": [ + "charts", + "data", + "expressions", + "visualizations", + "usageCollection", + "expressionPartitionVis", + "dataViews" + ], + "requiredBundles": [ + "visDefaultEditor", + "kibanaUtils" + ], + "extraPublicDirs": [ + "common/index" + ], + "owner": { + "name": "Vis Editors", + "githubTeam": "kibana-vis-editors" + }, + "description": "Contains the pie chart implementation using the elastic-charts library. The goal is to eventually deprecate the old implementation and keep only this. Until then, the library used is defined by the Legacy charts library advanced setting." +} \ No newline at end of file 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 4f7a5ad715215..b91d2dfd04d3e 100644 --- a/src/plugins/visualizations/common/convert_to_lens/types/configurations.ts +++ b/src/plugins/visualizations/common/convert_to_lens/types/configurations.ts @@ -10,6 +10,7 @@ import { HorizontalAlignment, LayoutDirection, Position, VerticalAlignment } fro import { $Values } from '@kbn/utility-types'; import type { CustomPaletteParams, PaletteOutput } from '@kbn/coloring'; import { KibanaQueryOutput } from '@kbn/data-plugin/common'; +import { CustomPaletteState } from '@kbn/charts-plugin/common'; import { LegendSize } from '../../constants'; import { CategoryDisplayTypes, @@ -28,6 +29,9 @@ import { GaugeCentralMajorModes, CollapseFunctions, } from '../constants'; +import { ExpressionValueVisDimension } from '../../expression_functions'; + +export type ChartShapes = 'heatmap'; export type CollapseFunction = typeof CollapseFunctions[number]; @@ -276,9 +280,55 @@ export type GaugeVisConfiguration = GaugeState & { layerType: typeof LayerTypes.DATA; }; +export interface HeatmapLegendConfig { + isVisible: boolean; + position: Position; + maxLines?: number; + shouldTruncate?: boolean; + legendSize?: LegendSize; +} +export interface HeatmapArguments { + percentageMode?: boolean; + lastRangeIsRightOpen?: boolean; + showTooltip?: boolean; + highlightInHover?: boolean; + palette?: PaletteOutput; + xAccessor?: string | ExpressionValueVisDimension; + yAccessor?: string | ExpressionValueVisDimension; + valueAccessor?: string | ExpressionValueVisDimension; + splitRowAccessor?: string | ExpressionValueVisDimension; + splitColumnAccessor?: string | ExpressionValueVisDimension; + legend: HeatmapLegendConfig; + gridConfig: HeatmapLegendConfig; + ariaLabel?: string; +} + +export type HeatmapLayerState = HeatmapArguments & { + layerId: string; + layerType: LayerType; + valueAccessor?: string; + xAccessor?: string; + yAccessor?: string; + shape: ChartShapes; +}; + +export type Palette = PaletteOutput & { accessor: string }; + +export type HeatmapVisualizationState = HeatmapLayerState & { + // need to store the current accessor to reset the color stops at accessor change + palette?: Palette; +}; + +export interface HeatmapConfiguration { + shape: PartitionChartType; + layers: PartitionLayerState[]; + palette?: PaletteOutput; +} + export type Configuration = | XYConfiguration | TableVisConfiguration | PartitionVisConfiguration | MetricVisConfiguration - | GaugeVisConfiguration; + | GaugeVisConfiguration + | HeatmapConfiguration; From d86314fe363b731a4e5ed409c68a292f78e2f99d Mon Sep 17 00:00:00 2001 From: Yaroslav Kuznietsov Date: Wed, 19 Oct 2022 16:21:55 +0300 Subject: [PATCH 02/26] Added navigateToLens to visType. --- src/plugins/vis_types/heatmap/public/vis_type/heatmap.tsx | 7 +++++++ .../common/convert_to_lens/types/configurations.ts | 8 +------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/plugins/vis_types/heatmap/public/vis_type/heatmap.tsx b/src/plugins/vis_types/heatmap/public/vis_type/heatmap.tsx index e5a92ca03f5cc..336da6e2d8041 100644 --- a/src/plugins/vis_types/heatmap/public/vis_type/heatmap.tsx +++ b/src/plugins/vis_types/heatmap/public/vis_type/heatmap.tsx @@ -16,6 +16,7 @@ import { HeatmapTypeProps, HeatmapVisParams, AxisType, ScaleType } from '../type import { toExpressionAst } from '../to_ast'; import { getHeatmapOptions } from '../editor/components'; import { SplitTooltip } from './split_tooltip'; +import { convertToLens } from '../convert_to_lens'; export const getHeatmapVisTypeDefinition = ({ showElasticChartsOptions = false, @@ -154,4 +155,10 @@ export const getHeatmapVisTypeDefinition = ({ ], }, requiresSearch: true, + navigateToLens: async (vis, timefilter) => (vis ? convertToLens(vis, timefilter) : null), + getExpressionVariables: async (vis, timeFilter) => { + return { + canNavigateToLens: Boolean(vis?.params ? await convertToLens(vis, timeFilter) : null), + }; + }, }); 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 b91d2dfd04d3e..37f0fa9a394dc 100644 --- a/src/plugins/visualizations/common/convert_to_lens/types/configurations.ts +++ b/src/plugins/visualizations/common/convert_to_lens/types/configurations.ts @@ -314,17 +314,11 @@ export type HeatmapLayerState = HeatmapArguments & { export type Palette = PaletteOutput & { accessor: string }; -export type HeatmapVisualizationState = HeatmapLayerState & { +export type HeatmapConfiguration = HeatmapLayerState & { // need to store the current accessor to reset the color stops at accessor change palette?: Palette; }; -export interface HeatmapConfiguration { - shape: PartitionChartType; - layers: PartitionLayerState[]; - palette?: PaletteOutput; -} - export type Configuration = | XYConfiguration | TableVisConfiguration From d3338d33e3e70218c65735cc759c5961b1a40b0c Mon Sep 17 00:00:00 2001 From: Yaroslav Kuznietsov Date: Wed, 19 Oct 2022 16:33:31 +0300 Subject: [PATCH 03/26] Added canNavigateToLens event. --- .../common/expression_functions/heatmap_function.ts | 1 + .../common/types/expression_functions.ts | 1 + .../public/expression_renderers/heatmap_renderer.tsx | 9 +++++++-- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/plugins/chart_expressions/expression_heatmap/common/expression_functions/heatmap_function.ts b/src/plugins/chart_expressions/expression_heatmap/common/expression_functions/heatmap_function.ts index 548d4ec0ab49e..f0c309de19236 100644 --- a/src/plugins/chart_expressions/expression_heatmap/common/expression_functions/heatmap_function.ts +++ b/src/plugins/chart_expressions/expression_heatmap/common/expression_functions/heatmap_function.ts @@ -232,6 +232,7 @@ export const heatmapFunction = (): HeatmapExpressionFunctionDefinition => ({ }, syncTooltips: handlers?.isSyncTooltipsEnabled?.() ?? false, syncCursor: handlers?.isSyncCursorEnabled?.() ?? true, + canNavigateToLens: Boolean(handlers?.variables?.canNavigateToLens), }, }; }, diff --git a/src/plugins/chart_expressions/expression_heatmap/common/types/expression_functions.ts b/src/plugins/chart_expressions/expression_heatmap/common/types/expression_functions.ts index 5aa1507f30b03..1bf5fe3bbb36b 100644 --- a/src/plugins/chart_expressions/expression_heatmap/common/types/expression_functions.ts +++ b/src/plugins/chart_expressions/expression_heatmap/common/types/expression_functions.ts @@ -94,6 +94,7 @@ export interface HeatmapExpressionProps { args: HeatmapArguments; syncTooltips: boolean; syncCursor: boolean; + canNavigateToLens?: boolean; } export interface HeatmapRender { diff --git a/src/plugins/chart_expressions/expression_heatmap/public/expression_renderers/heatmap_renderer.tsx b/src/plugins/chart_expressions/expression_heatmap/public/expression_renderers/heatmap_renderer.tsx index 4b813fb93416f..b14ee1382deb2 100644 --- a/src/plugins/chart_expressions/expression_heatmap/public/expression_renderers/heatmap_renderer.tsx +++ b/src/plugins/chart_expressions/expression_heatmap/public/expression_renderers/heatmap_renderer.tsx @@ -61,9 +61,14 @@ export const heatmapRenderer: ( const visualizationType = extractVisualizationType(executionContext); if (containerType && visualizationType) { - plugins.usageCollection?.reportUiCounter(containerType, METRIC_TYPE.COUNT, [ + const events = [ `render_${visualizationType}_${EXPRESSION_HEATMAP_NAME}`, - ]); + config.canNavigateToLens + ? `render_${visualizationType}_${EXPRESSION_HEATMAP_NAME}_convertable` + : undefined, + ].filter((event): event is string => Boolean(event)); + + plugins.usageCollection?.reportUiCounter(containerType, METRIC_TYPE.COUNT, events); } handlers.done(); From cbcf5aabbc42c5f5856278ecfacfd0fee3dfa95c Mon Sep 17 00:00:00 2001 From: Yaroslav Kuznietsov Date: Wed, 19 Oct 2022 16:49:10 +0300 Subject: [PATCH 04/26] Fixed type. --- src/plugins/vis_types/heatmap/public/convert_to_lens/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/vis_types/heatmap/public/convert_to_lens/index.ts b/src/plugins/vis_types/heatmap/public/convert_to_lens/index.ts index a1612f692dacb..175e12041b3cf 100644 --- a/src/plugins/vis_types/heatmap/public/convert_to_lens/index.ts +++ b/src/plugins/vis_types/heatmap/public/convert_to_lens/index.ts @@ -66,7 +66,7 @@ export const convertToLens: ConvertHeatmapToLensVisualization = async (vis, time const indexPatternId = dataView.id!; return { - type: 'lnsPie', + type: 'lnsHeatmap', layers: [ { indexPatternId, From 9e7e382c72153cc88b1381351f7610acafe8ee01 Mon Sep 17 00:00:00 2001 From: Yaroslav Kuznietsov Date: Wed, 19 Oct 2022 20:03:09 +0300 Subject: [PATCH 05/26] Added basic support of heatmap converting to lens. --- .../convert_to_lens/configurations/index.ts | 43 ++++++++++++++++++- .../heatmap/public/convert_to_lens/index.ts | 10 ++--- .../convert_to_lens/types/configurations.ts | 1 + .../visualizations/heatmap/visualization.tsx | 27 +++++++++++- 4 files changed, 72 insertions(+), 9 deletions(-) diff --git a/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.ts b/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.ts index f784073c543b9..c135ee0651251 100644 --- a/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.ts +++ b/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.ts @@ -6,6 +6,45 @@ * Side Public License, v 1. */ -export const getConfiguration = () => { - return {} as any; +import { Column, HeatmapConfiguration } from '@kbn/visualizations-plugin/common'; +import { Vis } from '@kbn/visualizations-plugin/public'; +import { HeatmapVisParams } from '../../types'; + +export const getConfiguration = ( + layerId: string, + vis: Vis, + { + metrics, + buckets, + columns, + }: { + metrics: string[]; + buckets: { + all: string[]; + customBuckets: Record; + }; + columns: Column[]; + } +): HeatmapConfiguration => { + const [valueAccessor] = metrics; + const xColumn = columns.find(({ isBucketed, isSplit }) => isBucketed && !isSplit); + const yColumn = columns.find(({ isBucketed, isSplit }) => isBucketed && isSplit); + return { + layerId, + layerType: 'data', + shape: 'heatmap', + legend: { + type: 'heatmap_legend', + isVisible: true, + position: 'bottom', + }, + gridConfig: { + type: 'heatmap_legend', + isVisible: true, + position: 'bottom', + }, + valueAccessor, + xAccessor: xColumn?.columnId, + yAccessor: yColumn?.columnId, + }; }; diff --git a/src/plugins/vis_types/heatmap/public/convert_to_lens/index.ts b/src/plugins/vis_types/heatmap/public/convert_to_lens/index.ts index 175e12041b3cf..874663e651fd7 100644 --- a/src/plugins/vis_types/heatmap/public/convert_to_lens/index.ts +++ b/src/plugins/vis_types/heatmap/public/convert_to_lens/index.ts @@ -45,8 +45,8 @@ export const convertToLens: ConvertHeatmapToLensVisualization = async (vis, time const { getColumnsFromVis } = await convertToLensModule; const layers = getColumnsFromVis(vis, timefilter, dataView, { - buckets: ['segment', 'group'], - splits: [], + buckets: ['segment'], + splits: ['group'], unsupported: ['split_row', 'split_column'], }); @@ -56,9 +56,7 @@ export const convertToLens: ConvertHeatmapToLensVisualization = async (vis, time const [layerConfig] = layers; - // doesn't support more than three split slice levels - // doesn't support pie without at least one split slice - if (layerConfig.buckets.all.length > 3 || !layerConfig.buckets.all.length) { + if (!layerConfig.buckets.all.length) { return null; } @@ -75,7 +73,7 @@ export const convertToLens: ConvertHeatmapToLensVisualization = async (vis, time columnOrder: [], }, ], - configuration: getConfiguration(), + configuration: getConfiguration(layerId, vis, layerConfig), indexPatternIds: [indexPatternId], }; }; 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 37f0fa9a394dc..6c2e4b449d0d2 100644 --- a/src/plugins/visualizations/common/convert_to_lens/types/configurations.ts +++ b/src/plugins/visualizations/common/convert_to_lens/types/configurations.ts @@ -286,6 +286,7 @@ export interface HeatmapLegendConfig { maxLines?: number; shouldTruncate?: boolean; legendSize?: LegendSize; + type: 'heatmap_legend'; } export interface HeatmapArguments { percentageMode?: boolean; diff --git a/x-pack/plugins/lens/public/visualizations/heatmap/visualization.tsx b/x-pack/plugins/lens/public/visualizations/heatmap/visualization.tsx index b8e98d03843a9..89833c007b35e 100644 --- a/x-pack/plugins/lens/public/visualizations/heatmap/visualization.tsx +++ b/x-pack/plugins/lens/public/visualizations/heatmap/visualization.tsx @@ -17,7 +17,7 @@ import { ThemeServiceStart } from '@kbn/core/public'; import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; import { VIS_EVENT_TO_TRIGGER } from '@kbn/visualizations-plugin/public'; import { LayerTypes } from '@kbn/expression-xy-plugin/public'; -import type { OperationMetadata, Visualization } from '../../types'; +import type { OperationMetadata, Suggestion, Visualization } from '../../types'; import type { HeatmapVisualizationState } from './types'; import { getSuggestions } from './suggestions'; import { @@ -33,6 +33,7 @@ import { import { HeatmapToolbar } from './toolbar_component'; import { HeatmapDimensionEditor } from './dimension_editor'; import { getSafePaletteParams } from './utils'; +import { FormBasedPersistedState } from '../..'; const groupLabelForHeatmap = i18n.translate('xpack.lens.heatmapVisualization.heatmapGroupLabel', { defaultMessage: 'Magnitude', @@ -525,4 +526,28 @@ export const getHeatmapVisualization = ({ ] : undefined; }, + + getSuggestionFromConvertToLensContext({ suggestions, context }) { + const allSuggestions = suggestions as Array< + Suggestion + >; + const suggestion: Suggestion = { + ...allSuggestions[0], + datasourceState: { + ...allSuggestions[0].datasourceState, + layers: allSuggestions.reduce( + (acc, s) => ({ + ...acc, + ...s.datasourceState?.layers, + }), + {} + ), + }, + visualizationState: { + ...allSuggestions[0].visualizationState, + ...context.configuration, + }, + }; + return suggestion; + }, }); From 0aefb591c9b37e0819815d314a4068bbcb75870a Mon Sep 17 00:00:00 2001 From: Yaroslav Kuznietsov Date: Fri, 21 Oct 2022 17:28:21 +0300 Subject: [PATCH 06/26] Added visType as arg. --- .../convert_to_lens/configurations/index.ts | 15 +- .../heatmap/public/convert_to_lens/index.ts | 7 +- .../table/public/convert_to_lens/index.ts | 1 + .../convert_to_lens/lib/buckets/index.test.ts | 20 +- .../convert_to_lens/lib/buckets/index.ts | 12 +- .../lib/convert/last_value.test.ts | 16 +- .../lib/convert/metric.test.ts | 5 + .../lib/convert/parent_pipeline.test.ts | 17 + .../lib/convert/parent_pipeline.ts | 12 +- .../lib/convert/percentage_mode.test.ts | 7 +- .../lib/convert/percentile.test.ts | 27 +- .../lib/convert/percentile_rank.test.ts | 29 +- .../lib/convert/sibling_pipeline.test.ts | 13 +- .../lib/convert/sibling_pipeline.ts | 11 +- .../lib/convert/std_deviation.test.ts | 44 +- .../convert_to_lens/lib/convert/terms.test.ts | 8 + .../convert_to_lens/lib/convert/terms.ts | 17 +- .../convert_to_lens/lib/convert/types.ts | 2 + .../lib/metrics/formula.test.ts | 29 +- .../convert_to_lens/lib/metrics/formula.ts | 8 +- .../lib/metrics/metrics.test.ts | 438 ++++++++++++------ .../convert_to_lens/lib/metrics/metrics.ts | 20 +- .../lib/metrics/percentage_formula.test.ts | 7 +- .../lib/metrics/percentage_formula.ts | 3 +- .../convert_to_lens/types/configurations.ts | 15 +- .../public/convert_to_lens/schemas.ts | 8 +- .../public/convert_to_lens/utils.test.ts | 12 +- .../public/convert_to_lens/utils.ts | 5 +- .../visualizations/heatmap/visualization.tsx | 3 +- 29 files changed, 550 insertions(+), 261 deletions(-) diff --git a/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.ts b/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.ts index c135ee0651251..3a4a6639bdcd6 100644 --- a/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.ts +++ b/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.ts @@ -25,10 +25,14 @@ export const getConfiguration = ( }; columns: Column[]; } -): HeatmapConfiguration => { +): HeatmapConfiguration | null => { const [valueAccessor] = metrics; const xColumn = columns.find(({ isBucketed, isSplit }) => isBucketed && !isSplit); const yColumn = columns.find(({ isBucketed, isSplit }) => isBucketed && isSplit); + if (yColumn && !xColumn) { + return null; + } + return { layerId, layerType: 'data', @@ -39,9 +43,12 @@ export const getConfiguration = ( position: 'bottom', }, gridConfig: { - type: 'heatmap_legend', - isVisible: true, - position: 'bottom', + type: 'heatmap_grid', + isCellLabelVisible: false, + isYAxisLabelVisible: false, + isYAxisTitleVisible: false, + isXAxisLabelVisible: false, + isXAxisTitleVisible: false, }, valueAccessor, xAccessor: xColumn?.columnId, diff --git a/src/plugins/vis_types/heatmap/public/convert_to_lens/index.ts b/src/plugins/vis_types/heatmap/public/convert_to_lens/index.ts index 874663e651fd7..645deb4d34d82 100644 --- a/src/plugins/vis_types/heatmap/public/convert_to_lens/index.ts +++ b/src/plugins/vis_types/heatmap/public/convert_to_lens/index.ts @@ -63,6 +63,11 @@ export const convertToLens: ConvertHeatmapToLensVisualization = async (vis, time const layerId = uuid(); const indexPatternId = dataView.id!; + const configuration = getConfiguration(layerId, vis, layerConfig); + if (configuration === null) { + return null; + } + return { type: 'lnsHeatmap', layers: [ @@ -73,7 +78,7 @@ export const convertToLens: ConvertHeatmapToLensVisualization = async (vis, time columnOrder: [], }, ], - configuration: getConfiguration(layerId, vis, layerConfig), + configuration, indexPatternIds: [indexPatternId], }; }; diff --git a/src/plugins/vis_types/table/public/convert_to_lens/index.ts b/src/plugins/vis_types/table/public/convert_to_lens/index.ts index e69faccbfd7ec..ed23d612cb68c 100644 --- a/src/plugins/vis_types/table/public/convert_to_lens/index.ts +++ b/src/plugins/vis_types/table/public/convert_to_lens/index.ts @@ -73,6 +73,7 @@ export const convertToLens: ConvertTableToLensVisualization = async (vis, timefi return null; } const percentageColumn = getPercentageColumnFormulaColumn({ + visType: vis.type.name, agg: metricAgg as SchemaConfig, dataView, aggs: visSchemas.metric as Array>, diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/buckets/index.test.ts b/src/plugins/visualizations/common/convert_to_lens/lib/buckets/index.test.ts index f0a8e4d32f7c3..02a6140625c07 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/buckets/index.test.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/buckets/index.test.ts @@ -8,7 +8,7 @@ import { stubLogstashDataView } from '@kbn/data-views-plugin/common/data_view.stub'; import { BUCKET_TYPES, METRIC_TYPES } from '@kbn/data-plugin/common'; -import { convertBucketToColumns } from '.'; +import { BucketAggs, convertBucketToColumns } from '.'; import { DateHistogramColumn, FiltersColumn, RangeColumn, TermsColumn } from '../../types'; import { AggBasedColumn, SchemaConfig } from '../../..'; @@ -27,7 +27,7 @@ jest.mock('../convert', () => ({ describe('convertBucketToColumns', () => { const field = stubLogstashDataView.fields[0].name; const dateField = stubLogstashDataView.fields.find((f) => f.type === 'date')!.name; - const bucketAggs: SchemaConfig[] = [ + const bucketAggs: Array> = [ { accessor: 0, label: '', @@ -152,6 +152,7 @@ describe('convertBucketToColumns', () => { }, }, ]; + const visType = 'heatmap'; afterEach(() => { jest.clearAllMocks(); @@ -167,7 +168,7 @@ describe('convertBucketToColumns', () => { >([ [ 'null if bucket agg type is not supported', - [{ dataView: stubLogstashDataView, agg: bucketAggs[6], aggs, metricColumns }], + [{ dataView: stubLogstashDataView, agg: bucketAggs[6], aggs, metricColumns, visType }], () => {}, null, ], @@ -179,6 +180,7 @@ describe('convertBucketToColumns', () => { agg: { ...bucketAggs[0], aggParams: undefined }, aggs, metricColumns, + visType, }, ], () => {}, @@ -186,7 +188,7 @@ describe('convertBucketToColumns', () => { ], [ 'filters column if bucket agg is valid filters agg', - [{ dataView: stubLogstashDataView, agg: bucketAggs[0], aggs, metricColumns }], + [{ dataView: stubLogstashDataView, agg: bucketAggs[0], aggs, metricColumns, visType }], () => { mockConvertToFiltersColumn.mockReturnValue({ operationType: 'filters', @@ -198,7 +200,7 @@ describe('convertBucketToColumns', () => { ], [ 'date histogram column if bucket agg is valid date histogram agg', - [{ dataView: stubLogstashDataView, agg: bucketAggs[1], aggs, metricColumns }], + [{ dataView: stubLogstashDataView, agg: bucketAggs[1], aggs, metricColumns, visType }], () => { mockConvertToDateHistogramColumn.mockReturnValue({ operationType: 'date_histogram', @@ -210,7 +212,7 @@ describe('convertBucketToColumns', () => { ], [ 'date histogram column if bucket agg is valid terms agg with date field', - [{ dataView: stubLogstashDataView, agg: bucketAggs[3], aggs, metricColumns }], + [{ dataView: stubLogstashDataView, agg: bucketAggs[3], aggs, metricColumns, visType }], () => { mockConvertToDateHistogramColumn.mockReturnValue({ operationType: 'date_histogram', @@ -222,7 +224,7 @@ describe('convertBucketToColumns', () => { ], [ 'terms column if bucket agg is valid terms agg with no date field', - [{ dataView: stubLogstashDataView, agg: bucketAggs[2], aggs, metricColumns }], + [{ dataView: stubLogstashDataView, agg: bucketAggs[2], aggs, metricColumns, visType }], () => { mockConvertToTermsColumn.mockReturnValue({ operationType: 'terms', @@ -234,7 +236,7 @@ describe('convertBucketToColumns', () => { ], [ 'range column if bucket agg is valid histogram agg', - [{ dataView: stubLogstashDataView, agg: bucketAggs[4], aggs, metricColumns }], + [{ dataView: stubLogstashDataView, agg: bucketAggs[4], aggs, metricColumns, visType }], () => { mockConvertToRangeColumn.mockReturnValue({ operationType: 'range', @@ -246,7 +248,7 @@ describe('convertBucketToColumns', () => { ], [ 'range column if bucket agg is valid range agg', - [{ dataView: stubLogstashDataView, agg: bucketAggs[5], aggs, metricColumns }], + [{ dataView: stubLogstashDataView, agg: bucketAggs[5], aggs, metricColumns, visType }], () => { mockConvertToRangeColumn.mockReturnValue({ operationType: 'range', diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/buckets/index.ts b/src/plugins/visualizations/common/convert_to_lens/lib/buckets/index.ts index 0f929189f3369..db02b1e09fdce 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/buckets/index.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/buckets/index.ts @@ -9,9 +9,8 @@ import { BUCKET_TYPES, IAggConfig, METRIC_TYPES } from '@kbn/data-plugin/common'; import type { DataView } from '@kbn/data-views-plugin/common'; import { convertToSchemaConfig } from '../../../vis_schemas'; -import { SchemaConfig } from '../../..'; +import { AggBasedColumn, SchemaConfig } from '../../..'; import { - AggBasedColumn, CommonBucketConverterArgs, convertToDateHistogramColumn, convertToFiltersColumn, @@ -26,6 +25,7 @@ export type BucketAggs = | BUCKET_TYPES.FILTERS | BUCKET_TYPES.RANGE | BUCKET_TYPES.HISTOGRAM; + const SUPPORTED_BUCKETS: string[] = [ BUCKET_TYPES.TERMS, BUCKET_TYPES.DATE_HISTOGRAM, @@ -39,7 +39,7 @@ const isSupportedBucketAgg = (agg: SchemaConfig): agg is SchemaConfig, + { agg, dataView, metricColumns, aggs, visType }: CommonBucketConverterArgs, { label, isSplit = false, @@ -76,7 +76,7 @@ export const getBucketColumns = ( if (field.type !== 'date') { return convertToTermsColumn( agg.aggId ?? '', - { agg, dataView, metricColumns, aggs }, + { agg, dataView, metricColumns, aggs, visType }, label, isSplit ); @@ -102,7 +102,9 @@ export const convertBucketToColumns = ( dataView, metricColumns, aggs, + visType, }: { + visType: string; agg: SchemaConfig | IAggConfig; dataView: DataView; metricColumns: AggBasedColumn[]; @@ -116,7 +118,7 @@ export const convertBucketToColumns = ( return null; } return getBucketColumns( - { agg: currentAgg, dataView, metricColumns, aggs }, + { agg: currentAgg, dataView, metricColumns, aggs, visType }, { label: getLabel(currentAgg), isSplit, diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/convert/last_value.test.ts b/src/plugins/visualizations/common/convert_to_lens/lib/convert/last_value.test.ts index 55ba1e8b5e09d..c46055ca6a9ab 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/convert/last_value.test.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/convert/last_value.test.ts @@ -22,6 +22,7 @@ jest.mock('../utils', () => ({ })); describe('convertToLastValueColumn', () => { + const visType = 'heatmap'; const dataView = stubLogstashDataView; const sortField = dataView.fields[0]; @@ -59,7 +60,13 @@ describe('convertToLastValueColumn', () => { test.each<[string, Parameters, Partial | null]>([ [ 'null if top hits size is more than 1', - [{ agg: { ...topHitAgg, aggParams: { ...topHitAgg.aggParams!, size: 2 } }, dataView }], + [ + { + agg: { ...topHitAgg, aggParams: { ...topHitAgg.aggParams!, size: 2 } }, + dataView, + visType, + }, + ], null, ], [ @@ -74,6 +81,7 @@ describe('convertToLastValueColumn', () => { }, }, dataView, + visType, }, ], null, @@ -88,7 +96,7 @@ describe('convertToLastValueColumn', () => { test('should skip if top hit field is not specified', () => { mockGetFieldNameFromField.mockReturnValue(null); - expect(convertToLastValueColumn({ agg: topHitAgg, dataView })).toBeNull(); + expect(convertToLastValueColumn({ agg: topHitAgg, dataView, visType })).toBeNull(); expect(mockGetFieldNameFromField).toBeCalledTimes(1); expect(dataView.getFieldByName).toBeCalledTimes(0); }); @@ -97,14 +105,14 @@ describe('convertToLastValueColumn', () => { mockGetFieldByName.mockReturnValue(null); dataView.getFieldByName = mockGetFieldByName; - expect(convertToLastValueColumn({ agg: topHitAgg, dataView })).toBeNull(); + expect(convertToLastValueColumn({ agg: topHitAgg, dataView, visType })).toBeNull(); expect(mockGetFieldNameFromField).toBeCalledTimes(1); expect(dataView.getFieldByName).toBeCalledTimes(1); expect(mockGetLabel).toBeCalledTimes(0); }); test('should return top hit column if top hit field is not present in index pattern', () => { - expect(convertToLastValueColumn({ agg: topHitAgg, dataView })).toEqual( + expect(convertToLastValueColumn({ agg: topHitAgg, dataView, visType })).toEqual( expect.objectContaining({ dataType: 'number', label: 'someLabel', diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/convert/metric.test.ts b/src/plugins/visualizations/common/convert_to_lens/lib/convert/metric.test.ts index 3be17abc46ac1..a0419d46df6b5 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/convert/metric.test.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/convert/metric.test.ts @@ -16,6 +16,7 @@ const mockGetFieldByName = jest.fn(); describe('convertToLastValueColumn', () => { const dataView = stubLogstashDataView; + const visType = 'heatmap'; const agg: SchemaConfig = { accessor: 0, @@ -42,6 +43,7 @@ describe('convertToLastValueColumn', () => { convertMetricAggregationColumnWithoutSpecialParams(SUPPORTED_METRICS[METRIC_TYPES.TOP_HITS], { agg, dataView, + visType, }) ).toBeNull(); }); @@ -54,6 +56,7 @@ describe('convertToLastValueColumn', () => { convertMetricAggregationColumnWithoutSpecialParams(SUPPORTED_METRICS[METRIC_TYPES.AVG], { agg, dataView, + visType, }) ).toBeNull(); expect(dataView.getFieldByName).toBeCalledTimes(1); @@ -67,6 +70,7 @@ describe('convertToLastValueColumn', () => { convertMetricAggregationColumnWithoutSpecialParams(SUPPORTED_METRICS[METRIC_TYPES.COUNT], { agg, dataView, + visType, }) ).toEqual(expect.objectContaining({ operationType: 'count' })); expect(dataView.getFieldByName).toBeCalledTimes(1); @@ -80,6 +84,7 @@ describe('convertToLastValueColumn', () => { convertMetricAggregationColumnWithoutSpecialParams(SUPPORTED_METRICS[METRIC_TYPES.AVG], { agg, dataView, + visType, }) ).toEqual( expect.objectContaining({ diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/convert/parent_pipeline.test.ts b/src/plugins/visualizations/common/convert_to_lens/lib/convert/parent_pipeline.test.ts index c28324533c837..65dd1cf40aaef 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/convert/parent_pipeline.test.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/convert/parent_pipeline.test.ts @@ -40,6 +40,7 @@ jest.mock('../metrics', () => ({ })); describe('convertToOtherParentPipelineAggColumns', () => { + const visType = 'heatmap'; const field = stubLogstashDataView.fields[0].name; const aggs: Array> = [ { @@ -81,6 +82,7 @@ describe('convertToOtherParentPipelineAggColumns', () => { dataView: stubLogstashDataView, aggs, agg: aggs[1] as SchemaConfig, + visType, }, ], () => { @@ -95,6 +97,7 @@ describe('convertToOtherParentPipelineAggColumns', () => { dataView: stubLogstashDataView, aggs, agg: aggs[1] as SchemaConfig, + visType, }, ], () => { @@ -112,6 +115,7 @@ describe('convertToOtherParentPipelineAggColumns', () => { dataView: stubLogstashDataView, aggs, agg: aggs[1] as SchemaConfig, + visType, }, ], () => { @@ -129,6 +133,7 @@ describe('convertToOtherParentPipelineAggColumns', () => { dataView: stubLogstashDataView, aggs, agg: aggs[1] as SchemaConfig, + visType, }, ], () => { @@ -147,6 +152,7 @@ describe('convertToOtherParentPipelineAggColumns', () => { dataView: stubLogstashDataView, aggs, agg: aggs[1] as SchemaConfig, + visType, }, ], () => { @@ -170,6 +176,7 @@ describe('convertToOtherParentPipelineAggColumns', () => { dataView: stubLogstashDataView, aggs, agg: aggs[1] as SchemaConfig, + visType, }, ], () => { @@ -188,6 +195,7 @@ describe('convertToOtherParentPipelineAggColumns', () => { dataView: stubLogstashDataView, aggs, agg: aggs[1] as SchemaConfig, + visType, }, ], () => { @@ -229,6 +237,7 @@ describe('convertToOtherParentPipelineAggColumns', () => { }); describe('convertToCumulativeSumAggColumn', () => { + const visType = 'heatmap'; const field = stubLogstashDataView.fields[0].name; const aggs: Array> = [ { @@ -280,6 +289,7 @@ describe('convertToCumulativeSumAggColumn', () => { dataView: stubLogstashDataView, aggs, agg: { ...aggs[1], aggParams: undefined } as SchemaConfig, + visType, }, ], () => { @@ -294,6 +304,7 @@ describe('convertToCumulativeSumAggColumn', () => { dataView: stubLogstashDataView, aggs, agg: aggs[1] as SchemaConfig, + visType, }, ], () => { @@ -308,6 +319,7 @@ describe('convertToCumulativeSumAggColumn', () => { dataView: stubLogstashDataView, aggs, agg: aggs[1] as SchemaConfig, + visType, }, ], () => { @@ -325,6 +337,7 @@ describe('convertToCumulativeSumAggColumn', () => { dataView: stubLogstashDataView, aggs, agg: aggs[1] as SchemaConfig, + visType, }, ], () => { @@ -342,6 +355,7 @@ describe('convertToCumulativeSumAggColumn', () => { dataView: stubLogstashDataView, aggs, agg: aggs[1] as SchemaConfig, + visType, }, ], () => { @@ -360,6 +374,7 @@ describe('convertToCumulativeSumAggColumn', () => { dataView: stubLogstashDataView, aggs, agg: aggs[1] as SchemaConfig, + visType, }, ], () => { @@ -383,6 +398,7 @@ describe('convertToCumulativeSumAggColumn', () => { dataView: stubLogstashDataView, aggs, agg: aggs[1] as SchemaConfig, + visType, }, ], () => { @@ -401,6 +417,7 @@ describe('convertToCumulativeSumAggColumn', () => { dataView: stubLogstashDataView, aggs, agg: aggs[1] as SchemaConfig, + visType, }, ], () => { diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/convert/parent_pipeline.ts b/src/plugins/visualizations/common/convert_to_lens/lib/convert/parent_pipeline.ts index ab41ceb259adb..0e0aef11316b2 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/convert/parent_pipeline.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/convert/parent_pipeline.ts @@ -38,7 +38,7 @@ export const convertToMovingAverageParams = ( }); export const convertToOtherParentPipelineAggColumns = ( - { agg, dataView, aggs }: ExtendedColumnConverterArgs, + { agg, dataView, aggs, visType }: ExtendedColumnConverterArgs, reducedTimeRange?: string ): FormulaColumn | [ParentPipelineAggColumn, AggBasedColumn] | null => { const { aggType } = agg; @@ -63,7 +63,7 @@ export const convertToOtherParentPipelineAggColumns = ( } if (PIPELINE_AGGS.includes(metric.aggType)) { - const formula = getFormulaForPipelineAgg({ agg, aggs, dataView }); + const formula = getFormulaForPipelineAgg({ agg, aggs, dataView, visType }); if (!formula) { return null; } @@ -71,7 +71,7 @@ export const convertToOtherParentPipelineAggColumns = ( return createFormulaColumn(formula, agg); } - const subMetric = convertMetricToColumns(metric, dataView, aggs); + const subMetric = convertMetricToColumns({ agg: metric, dataView, aggs, visType }); if (subMetric === null) { return null; @@ -90,7 +90,7 @@ export const convertToOtherParentPipelineAggColumns = ( }; export const convertToCumulativeSumAggColumn = ( - { agg, dataView, aggs }: ExtendedColumnConverterArgs, + { agg, dataView, aggs, visType }: ExtendedColumnConverterArgs, reducedTimeRange?: string ): | FormulaColumn @@ -119,7 +119,7 @@ export const convertToCumulativeSumAggColumn = ( // create column for sum or count const subMetric = convertMetricAggregationColumnWithoutSpecialParams( subAgg, - { agg: metric as SchemaConfig, dataView }, + { agg: metric as SchemaConfig, dataView, visType }, reducedTimeRange ); @@ -144,7 +144,7 @@ export const convertToCumulativeSumAggColumn = ( subMetric, ]; } else { - const formula = getFormulaForPipelineAgg({ agg, aggs, dataView }); + const formula = getFormulaForPipelineAgg({ agg, aggs, dataView, visType }); if (!formula) { return null; } diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/convert/percentage_mode.test.ts b/src/plugins/visualizations/common/convert_to_lens/lib/convert/percentage_mode.test.ts index 3b7e8ad7e797f..0ef5d07236d60 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/convert/percentage_mode.test.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/convert/percentage_mode.test.ts @@ -18,6 +18,7 @@ jest.mock('../metrics/formula', () => ({ })); describe('convertToColumnInPercentageMode', () => { + const visType = 'heatmap'; const formula = 'average(some_field)'; const dataView = stubLogstashDataView; @@ -42,7 +43,7 @@ describe('convertToColumnInPercentageMode', () => { test('should return null if it is not possible to build the valid formula', () => { mockGetFormulaForAgg.mockReturnValue(null); - expect(convertToColumnInPercentageMode({ agg, dataView, aggs: [agg] }, {})).toBeNull(); + expect(convertToColumnInPercentageMode({ agg, dataView, aggs: [agg], visType }, {})).toBeNull(); }); test('should return percentage mode over range formula if min and max was passed', () => { @@ -51,7 +52,7 @@ describe('convertToColumnInPercentageMode', () => { params: { format: { id: 'percent' }, formula: `((${formula}) - 0) / (100 - 0)` }, }; expect( - convertToColumnInPercentageMode({ agg, dataView, aggs: [agg] }, { min: 0, max: 100 }) + convertToColumnInPercentageMode({ agg, dataView, aggs: [agg], visType }, { min: 0, max: 100 }) ).toEqual(expect.objectContaining(formulaColumn)); }); @@ -60,7 +61,7 @@ describe('convertToColumnInPercentageMode', () => { operationType: 'formula', params: { format: { id: 'percent' }, formula: `(${formula}) / 10000` }, }; - expect(convertToColumnInPercentageMode({ agg, dataView, aggs: [agg] }, {})).toEqual( + expect(convertToColumnInPercentageMode({ agg, dataView, aggs: [agg], visType }, {})).toEqual( expect.objectContaining(formulaColumn) ); }); diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/convert/percentile.test.ts b/src/plugins/visualizations/common/convert_to_lens/lib/convert/percentile.test.ts index b4cf7f141e928..adfab7f55d1c4 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/convert/percentile.test.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/convert/percentile.test.ts @@ -24,6 +24,7 @@ jest.mock('../utils', () => ({ })); describe('convertToPercentileColumn', () => { + const visType = 'heatmap'; const dataView = stubLogstashDataView; const field = dataView.fields[0].displayName; const aggId = 'pr.10'; @@ -67,23 +68,27 @@ describe('convertToPercentileColumn', () => { test.each< [string, Parameters, Partial | null] >([ - ['null if no percents', [{ agg: { ...agg, aggId: 'pr' }, dataView }], null], + ['null if no percents', [{ agg: { ...agg, aggId: 'pr' }, dataView, visType }], null], [ 'null if no value', - [{ agg: { ...singlePercentileRankAgg, aggParams: undefined }, dataView }], + [{ agg: { ...singlePercentileRankAgg, aggParams: undefined }, dataView, visType }], + null, + ], + ['null if no aggId', [{ agg: { ...agg, aggId: undefined }, dataView, visType }], null], + ['null if no aggParams', [{ agg: { ...agg, aggParams: undefined }, dataView, visType }], null], + [ + 'null if aggId is invalid', + [{ agg: { ...agg, aggId: 'pr.invalid' }, dataView, visType }], null, ], - ['null if no aggId', [{ agg: { ...agg, aggId: undefined }, dataView }], null], - ['null if no aggParams', [{ agg: { ...agg, aggParams: undefined }, dataView }], null], - ['null if aggId is invalid', [{ agg: { ...agg, aggId: 'pr.invalid' }, dataView }], null], [ 'null if values are undefined', - [{ agg: { ...agg, aggParams: { percents: undefined, field } }, dataView }], + [{ agg: { ...agg, aggParams: { percents: undefined, field } }, dataView, visType }], null, ], [ 'null if values are empty', - [{ agg: { ...agg, aggParams: { percents: [], field } }, dataView }], + [{ agg: { ...agg, aggParams: { percents: [], field } }, dataView, visType }], null, ], ])('should return %s', (_, input, expected) => { @@ -96,7 +101,7 @@ describe('convertToPercentileColumn', () => { test('should return null if field is not specified', () => { mockGetFieldNameFromField.mockReturnValue(null); - expect(convertToPercentileColumn({ agg, dataView })).toBeNull(); + expect(convertToPercentileColumn({ agg, dataView, visType })).toBeNull(); expect(mockGetFieldNameFromField).toBeCalledTimes(1); expect(dataView.getFieldByName).toBeCalledTimes(0); }); @@ -105,13 +110,13 @@ describe('convertToPercentileColumn', () => { mockGetFieldByName.mockReturnValueOnce(null); dataView.getFieldByName = mockGetFieldByName; - expect(convertToPercentileColumn({ agg, dataView })).toBeNull(); + expect(convertToPercentileColumn({ agg, dataView, visType })).toBeNull(); expect(mockGetFieldNameFromField).toBeCalledTimes(1); expect(dataView.getFieldByName).toBeCalledTimes(1); }); test('should return percentile rank column for percentiles', () => { - expect(convertToPercentileColumn({ agg, dataView })).toEqual( + expect(convertToPercentileColumn({ agg, dataView, visType })).toEqual( expect.objectContaining({ dataType: 'number', label: 'someOtherLabel', @@ -126,7 +131,7 @@ describe('convertToPercentileColumn', () => { }); test('should return percentile rank column for single percentile', () => { - expect(convertToPercentileColumn({ agg: singlePercentileRankAgg, dataView })).toEqual( + expect(convertToPercentileColumn({ agg: singlePercentileRankAgg, dataView, visType })).toEqual( expect.objectContaining({ dataType: 'number', label: 'someOtherLabel', diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/convert/percentile_rank.test.ts b/src/plugins/visualizations/common/convert_to_lens/lib/convert/percentile_rank.test.ts index 8a696d51d871b..afeaa9899d107 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/convert/percentile_rank.test.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/convert/percentile_rank.test.ts @@ -24,6 +24,7 @@ jest.mock('../utils', () => ({ })); describe('convertToPercentileRankColumn', () => { + const visType = 'heatmap'; const dataView = stubLogstashDataView; const field = dataView.fields[0].displayName; const aggId = 'pr.10'; @@ -71,23 +72,27 @@ describe('convertToPercentileRankColumn', () => { Partial | null ] >([ - ['null if no percents', [{ agg: { ...agg, aggId: 'pr' }, dataView }], null], + ['null if no percents', [{ agg: { ...agg, aggId: 'pr' }, dataView, visType }], null], [ 'null if no value', - [{ agg: { ...singlePercentileRankAgg, aggParams: undefined }, dataView }], + [{ agg: { ...singlePercentileRankAgg, aggParams: undefined }, dataView, visType }], + null, + ], + ['null if no aggId', [{ agg: { ...agg, aggId: undefined }, dataView, visType }], null], + ['null if no aggParams', [{ agg: { ...agg, aggParams: undefined }, dataView, visType }], null], + [ + 'null if aggId is invalid', + [{ agg: { ...agg, aggId: 'pr.invalid' }, dataView, visType }], null, ], - ['null if no aggId', [{ agg: { ...agg, aggId: undefined }, dataView }], null], - ['null if no aggParams', [{ agg: { ...agg, aggParams: undefined }, dataView }], null], - ['null if aggId is invalid', [{ agg: { ...agg, aggId: 'pr.invalid' }, dataView }], null], [ 'null if values are undefined', - [{ agg: { ...agg, aggParams: { values: undefined, field } }, dataView }], + [{ agg: { ...agg, aggParams: { values: undefined, field } }, dataView, visType }], null, ], [ 'null if values are empty', - [{ agg: { ...agg, aggParams: { values: [], field } }, dataView }], + [{ agg: { ...agg, aggParams: { values: [], field } }, dataView, visType }], null, ], ])('should return %s', (_, input, expected) => { @@ -100,7 +105,7 @@ describe('convertToPercentileRankColumn', () => { test('should return null if field is not specified', () => { mockGetFieldNameFromField.mockReturnValue(null); - expect(convertToPercentileRankColumn({ agg, dataView })).toBeNull(); + expect(convertToPercentileRankColumn({ agg, dataView, visType })).toBeNull(); expect(mockGetFieldNameFromField).toBeCalledTimes(1); expect(dataView.getFieldByName).toBeCalledTimes(0); }); @@ -109,13 +114,13 @@ describe('convertToPercentileRankColumn', () => { mockGetFieldByName.mockReturnValueOnce(null); dataView.getFieldByName = mockGetFieldByName; - expect(convertToPercentileRankColumn({ agg, dataView })).toBeNull(); + expect(convertToPercentileRankColumn({ agg, dataView, visType })).toBeNull(); expect(mockGetFieldNameFromField).toBeCalledTimes(1); expect(dataView.getFieldByName).toBeCalledTimes(1); }); test('should return percentile rank column for percentile ranks', () => { - expect(convertToPercentileRankColumn({ agg, dataView })).toEqual( + expect(convertToPercentileRankColumn({ agg, dataView, visType })).toEqual( expect.objectContaining({ dataType: 'number', label: 'someOtherLabel', @@ -130,7 +135,9 @@ describe('convertToPercentileRankColumn', () => { }); test('should return percentile rank column for single percentile rank', () => { - expect(convertToPercentileRankColumn({ agg: singlePercentileRankAgg, dataView })).toEqual( + expect( + convertToPercentileRankColumn({ agg: singlePercentileRankAgg, dataView, visType }) + ).toEqual( expect.objectContaining({ dataType: 'number', label: 'someOtherLabel', diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/convert/sibling_pipeline.test.ts b/src/plugins/visualizations/common/convert_to_lens/lib/convert/sibling_pipeline.test.ts index 759620650b8a6..6adde7004b69a 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/convert/sibling_pipeline.test.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/convert/sibling_pipeline.test.ts @@ -23,6 +23,7 @@ jest.mock('../../../vis_schemas', () => ({ })); describe('convertToSiblingPipelineColumns', () => { + const visType = 'heatmap'; const dataView = stubLogstashDataView; const aggId = 'agg-id-1'; const agg: SchemaConfig = { @@ -46,7 +47,12 @@ describe('convertToSiblingPipelineColumns', () => { test('should return null if aggParams are not defined', () => { expect( - convertToSiblingPipelineColumns({ agg: { ...agg, aggParams: undefined }, aggs: [], dataView }) + convertToSiblingPipelineColumns({ + agg: { ...agg, aggParams: undefined }, + aggs: [], + dataView, + visType, + }) ).toBeNull(); expect(mockConvertMetricToColumns).toBeCalledTimes(0); }); @@ -57,6 +63,7 @@ describe('convertToSiblingPipelineColumns', () => { agg: { ...agg, aggParams: { customMetric: undefined } }, aggs: [], dataView, + visType, }) ).toBeNull(); expect(mockConvertMetricToColumns).toBeCalledTimes(0); @@ -64,7 +71,7 @@ describe('convertToSiblingPipelineColumns', () => { test('should return null if sibling agg is not supported', () => { mockConvertMetricToColumns.mockReturnValue(null); - expect(convertToSiblingPipelineColumns({ agg, aggs: [], dataView })).toBeNull(); + expect(convertToSiblingPipelineColumns({ agg, aggs: [], dataView, visType })).toBeNull(); expect(mockConvertToSchemaConfig).toBeCalledTimes(1); expect(mockConvertMetricToColumns).toBeCalledTimes(1); }); @@ -72,7 +79,7 @@ describe('convertToSiblingPipelineColumns', () => { test('should return column', () => { const column = { operationType: 'formula' }; mockConvertMetricToColumns.mockReturnValue([column]); - expect(convertToSiblingPipelineColumns({ agg, aggs: [], dataView })).toEqual(column); + expect(convertToSiblingPipelineColumns({ agg, aggs: [], dataView, visType })).toEqual(column); expect(mockConvertToSchemaConfig).toBeCalledTimes(1); expect(mockConvertMetricToColumns).toBeCalledTimes(1); }); diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/convert/sibling_pipeline.ts b/src/plugins/visualizations/common/convert_to_lens/lib/convert/sibling_pipeline.ts index a8389cb8601e4..c77500a55d5d1 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/convert/sibling_pipeline.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/convert/sibling_pipeline.ts @@ -22,11 +22,12 @@ export const convertToSiblingPipelineColumns = ( return null; } - const customMetricColumn = convertMetricToColumns( - { ...convertToSchemaConfig(aggParams.customMetric), label, aggId }, - columnConverterArgs.dataView, - columnConverterArgs.aggs - ); + const customMetricColumn = convertMetricToColumns({ + agg: { ...convertToSchemaConfig(aggParams.customMetric), label, aggId }, + dataView: columnConverterArgs.dataView, + aggs: columnConverterArgs.aggs, + visType: columnConverterArgs.visType, + }); if (!customMetricColumn) { return null; diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/convert/std_deviation.test.ts b/src/plugins/visualizations/common/convert_to_lens/lib/convert/std_deviation.test.ts index cbb1f03a6dc2e..c786d6b8c3a6f 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/convert/std_deviation.test.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/convert/std_deviation.test.ts @@ -22,6 +22,7 @@ jest.mock('../utils', () => ({ })); describe('convertToStdDeviationFormulaColumns', () => { + const visType = 'heatmap'; const dataView = stubLogstashDataView; const stdLowerAggId = 'agg-id.std_lower'; const stdUpperAggId = 'agg-id.std_upper'; @@ -51,22 +52,25 @@ describe('convertToStdDeviationFormulaColumns', () => { test.each< [string, Parameters, Partial | null] - >([['null if no aggId is passed', [{ agg: { ...agg, aggId: undefined }, dataView }], null]])( - 'should return %s', - (_, input, expected) => { - if (expected === null) { - expect(convertToStdDeviationFormulaColumns(...input)).toBeNull(); - } else { - expect(convertToStdDeviationFormulaColumns(...input)).toEqual( - expect.objectContaining(expected) - ); - } + >([ + [ + 'null if no aggId is passed', + [{ agg: { ...agg, aggId: undefined }, dataView, visType }], + null, + ], + ])('should return %s', (_, input, expected) => { + if (expected === null) { + expect(convertToStdDeviationFormulaColumns(...input)).toBeNull(); + } else { + expect(convertToStdDeviationFormulaColumns(...input)).toEqual( + expect.objectContaining(expected) + ); } - ); + }); test('should return null if field is not present', () => { mockGetFieldNameFromField.mockReturnValue(null); - expect(convertToStdDeviationFormulaColumns({ agg, dataView })).toBeNull(); + expect(convertToStdDeviationFormulaColumns({ agg, dataView, visType })).toBeNull(); expect(mockGetFieldNameFromField).toBeCalledTimes(1); expect(dataView.getFieldByName).toBeCalledTimes(0); }); @@ -74,14 +78,14 @@ describe('convertToStdDeviationFormulaColumns', () => { test("should return null if field doesn't exist in dataView", () => { mockGetFieldByName.mockReturnValue(null); dataView.getFieldByName = mockGetFieldByName; - expect(convertToStdDeviationFormulaColumns({ agg, dataView })).toBeNull(); + expect(convertToStdDeviationFormulaColumns({ agg, dataView, visType })).toBeNull(); expect(mockGetFieldNameFromField).toBeCalledTimes(1); expect(dataView.getFieldByName).toBeCalledTimes(1); }); test('should return null if agg id is invalid', () => { expect( - convertToStdDeviationFormulaColumns({ agg: { ...agg, aggId: 'some-id' }, dataView }) + convertToStdDeviationFormulaColumns({ agg: { ...agg, aggId: 'some-id' }, dataView, visType }) ).toBeNull(); expect(mockGetFieldNameFromField).toBeCalledTimes(1); expect(dataView.getFieldByName).toBeCalledTimes(1); @@ -89,7 +93,11 @@ describe('convertToStdDeviationFormulaColumns', () => { test('should return formula column for lower std deviation', () => { expect( - convertToStdDeviationFormulaColumns({ agg: { ...agg, aggId: stdLowerAggId }, dataView }) + convertToStdDeviationFormulaColumns({ + agg: { ...agg, aggId: stdLowerAggId }, + dataView, + visType, + }) ).toEqual( expect.objectContaining({ label, @@ -102,7 +110,11 @@ describe('convertToStdDeviationFormulaColumns', () => { test('should return formula column for upper std deviation', () => { expect( - convertToStdDeviationFormulaColumns({ agg: { ...agg, aggId: stdUpperAggId }, dataView }) + convertToStdDeviationFormulaColumns({ + agg: { ...agg, aggId: stdUpperAggId }, + dataView, + visType, + }) ).toEqual( expect.objectContaining({ label, diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/convert/terms.test.ts b/src/plugins/visualizations/common/convert_to_lens/lib/convert/terms.test.ts index d214ec74b09b1..c8bb23b35742c 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/convert/terms.test.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/convert/terms.test.ts @@ -23,6 +23,7 @@ jest.mock('../../../vis_schemas', () => ({ })); describe('convertToDateHistogramColumn', () => { + const visType = 'heatmap'; const aggId = `some-id`; const aggParams: AggParamsTerms = { field: stubLogstashDataView.fields[0].name, @@ -79,6 +80,7 @@ describe('convertToDateHistogramColumn', () => { dataView: stubLogstashDataView, aggs, metricColumns, + visType, }, '', false, @@ -95,6 +97,7 @@ describe('convertToDateHistogramColumn', () => { dataView: stubLogstashDataView, aggs, metricColumns, + visType, }, '', false, @@ -123,6 +126,7 @@ describe('convertToDateHistogramColumn', () => { dataView: stubLogstashDataView, aggs, metricColumns, + visType, }, '', false, @@ -152,6 +156,7 @@ describe('convertToDateHistogramColumn', () => { dataView: stubLogstashDataView, aggs, metricColumns, + visType, }, '', false, @@ -170,6 +175,7 @@ describe('convertToDateHistogramColumn', () => { dataView: stubLogstashDataView, aggs, metricColumns, + visType, }, '', false, @@ -188,6 +194,7 @@ describe('convertToDateHistogramColumn', () => { dataView: stubLogstashDataView, aggs, metricColumns, + visType, }, '', false, @@ -208,6 +215,7 @@ describe('convertToDateHistogramColumn', () => { dataView: stubLogstashDataView, aggs, metricColumns, + visType, }, '', false, diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/convert/terms.ts b/src/plugins/visualizations/common/convert_to_lens/lib/convert/terms.ts index 0a50390ec469e..44cc46c101d54 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/convert/terms.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/convert/terms.ts @@ -23,6 +23,7 @@ const getOrderByWithAgg = ({ agg, dataView, aggs, + visType, metricColumns, }: CommonBucketConverterArgs): OrderByWithAgg | null => { if (!agg.aggParams) { @@ -37,11 +38,12 @@ const getOrderByWithAgg = ({ if (!agg.aggParams.orderAgg) { return null; } - const orderMetricColumn = convertMetricToColumns( - convertToSchemaConfig(agg.aggParams.orderAgg), + const orderMetricColumn = convertMetricToColumns({ + agg: convertToSchemaConfig(agg.aggParams.orderAgg), dataView, - aggs - ); + aggs, + visType, + }); if (!orderMetricColumn) { return null; } @@ -73,12 +75,13 @@ export const convertToTermsParams = ({ dataView, aggs, metricColumns, + visType, }: CommonBucketConverterArgs): TermsParams | null => { if (!agg.aggParams) { return null; } - const orderByWithAgg = getOrderByWithAgg({ agg, dataView, aggs, metricColumns }); + const orderByWithAgg = getOrderByWithAgg({ agg, dataView, aggs, metricColumns, visType }); if (orderByWithAgg === null) { return null; } @@ -107,7 +110,7 @@ export const convertToTermsParams = ({ export const convertToTermsColumn = ( aggId: string, - { agg, dataView, aggs, metricColumns }: CommonBucketConverterArgs, + { agg, dataView, aggs, metricColumns, visType }: CommonBucketConverterArgs, label: string, isSplit: boolean ): TermsColumn | null => { @@ -121,7 +124,7 @@ export const convertToTermsColumn = ( return null; } - const params = convertToTermsParams({ agg, dataView, aggs, metricColumns }); + const params = convertToTermsParams({ agg, dataView, aggs, metricColumns, visType }); if (!params) { return null; } diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/convert/types.ts b/src/plugins/visualizations/common/convert_to_lens/lib/convert/types.ts index 8e6f9ec9443bb..97ccba39303fc 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/convert/types.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/convert/types.ts @@ -64,6 +64,7 @@ export interface CommonColumnConverterArgs< > { agg: SchemaConfig; dataView: DataView; + visType: string; } export interface ExtendedColumnConverterArgs< @@ -75,6 +76,7 @@ export interface ExtendedColumnConverterArgs< export interface CommonBucketConverterArgs< Agg extends SupportedAggregation = SupportedAggregation > { + visType: string; agg: SchemaConfig; dataView: DataView; metricColumns: AggBasedColumn[]; diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/metrics/formula.test.ts b/src/plugins/visualizations/common/convert_to_lens/lib/metrics/formula.test.ts index 95e128e22b092..72cd07ba03f7c 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/metrics/formula.test.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/metrics/formula.test.ts @@ -29,7 +29,7 @@ jest.mock('../utils', () => ({ })); const dataView = stubLogstashDataView; - +const visType = 'heatmap'; const field = stubLogstashDataView.fields[0].name; const aggs: Array> = [ { @@ -97,7 +97,7 @@ describe('getFormulaForPipelineAgg', () => { test.each<[string, Parameters, () => void, string | null]>([ [ 'null if custom metric is invalid', - [{ agg: aggs[0] as SchemaConfig, aggs, dataView }], + [{ agg: aggs[0] as SchemaConfig, aggs, dataView, visType }], () => { mockGetMetricFromParentPipelineAgg.mockReturnValue(null); }, @@ -105,7 +105,7 @@ describe('getFormulaForPipelineAgg', () => { ], [ 'null if custom metric type is not supported', - [{ agg: aggs[0] as SchemaConfig, aggs, dataView }], + [{ agg: aggs[0] as SchemaConfig, aggs, dataView, visType }], () => { mockGetMetricFromParentPipelineAgg.mockReturnValue({ aggType: METRIC_TYPES.GEO_BOUNDS, @@ -115,7 +115,7 @@ describe('getFormulaForPipelineAgg', () => { ], [ 'correct formula if agg is parent pipeline agg and custom metric is valid and supported pipeline agg', - [{ agg: aggs[0] as SchemaConfig, aggs, dataView }], + [{ agg: aggs[0] as SchemaConfig, aggs, dataView, visType }], () => { mockGetMetricFromParentPipelineAgg .mockReturnValueOnce({ @@ -135,7 +135,7 @@ describe('getFormulaForPipelineAgg', () => { ], [ 'correct formula if agg is parent pipeline agg and custom metric is valid and supported not pipeline agg', - [{ agg: aggs[0] as SchemaConfig, aggs, dataView }], + [{ agg: aggs[0] as SchemaConfig, aggs, dataView, visType }], () => { mockGetMetricFromParentPipelineAgg.mockReturnValueOnce({ aggType: METRIC_TYPES.AVG, @@ -149,7 +149,7 @@ describe('getFormulaForPipelineAgg', () => { ], [ 'correct formula if agg is parent pipeline agg and custom metric is valid and supported percentile rank agg', - [{ agg: aggs[0] as SchemaConfig, aggs, dataView }], + [{ agg: aggs[0] as SchemaConfig, aggs, dataView, visType }], () => { mockGetMetricFromParentPipelineAgg.mockReturnValueOnce({ aggType: METRIC_TYPES.PERCENTILE_RANKS, @@ -163,7 +163,7 @@ describe('getFormulaForPipelineAgg', () => { ], [ 'correct formula if agg is sibling pipeline agg and custom metric is valid and supported agg', - [{ agg: aggs[1] as SchemaConfig, aggs, dataView }], + [{ agg: aggs[1] as SchemaConfig, aggs, dataView, visType }], () => { mockGetMetricFromParentPipelineAgg.mockReturnValueOnce({ aggType: METRIC_TYPES.AVG, @@ -212,6 +212,7 @@ describe('getFormulaForPipelineAgg', () => { agg: aggs[1] as SchemaConfig, aggs, dataView, + visType, }); expect(agg).toBeNull(); }); @@ -244,6 +245,7 @@ describe('getFormulaForPipelineAgg', () => { agg: aggs[1] as SchemaConfig, aggs, dataView, + visType, }); expect(agg).toBeNull(); }); @@ -270,6 +272,7 @@ describe('getFormulaForAgg', () => { agg: { ...aggs[0], aggType: METRIC_TYPES.GEO_BOUNDS, aggParams: { field } }, aggs, dataView, + visType, }, ], () => {}, @@ -277,7 +280,7 @@ describe('getFormulaForAgg', () => { ], [ 'correct pipeline formula if agg is valid pipeline agg', - [{ agg: aggs[0], aggs, dataView }], + [{ agg: aggs[0], aggs, dataView, visType }], () => { mockIsPipeline.mockReturnValue(true); mockGetMetricFromParentPipelineAgg.mockReturnValueOnce({ @@ -292,7 +295,7 @@ describe('getFormulaForAgg', () => { ], [ 'correct percentile formula if agg is valid percentile agg', - [{ agg: aggs[2], aggs, dataView }], + [{ agg: aggs[2], aggs, dataView, visType }], () => { mockIsPercentileAgg.mockReturnValue(true); }, @@ -300,7 +303,7 @@ describe('getFormulaForAgg', () => { ], [ 'correct percentile rank formula if agg is valid percentile rank agg', - [{ agg: aggs[3], aggs, dataView }], + [{ agg: aggs[3], aggs, dataView, visType }], () => { mockIsPercentileRankAgg.mockReturnValue(true); }, @@ -308,7 +311,7 @@ describe('getFormulaForAgg', () => { ], [ 'correct standart deviation formula if agg is valid standart deviation agg', - [{ agg: aggs[4], aggs, dataView }], + [{ agg: aggs[4], aggs, dataView, visType }], () => { mockIsStdDevAgg.mockReturnValue(true); }, @@ -316,7 +319,7 @@ describe('getFormulaForAgg', () => { ], [ 'correct metric formula if agg is valid other metric agg', - [{ agg: aggs[5], aggs, dataView }], + [{ agg: aggs[5], aggs, dataView, visType }], () => {}, 'average(bytes)', ], @@ -395,6 +398,7 @@ describe('getFormulaForAgg', () => { >, aggs, dataView, + visType, }); expect(result).toBeNull(); }); @@ -467,6 +471,7 @@ describe('getFormulaForAgg', () => { >, aggs, dataView, + visType, }); expect(result).toBeNull(); } diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/metrics/formula.ts b/src/plugins/visualizations/common/convert_to_lens/lib/metrics/formula.ts index 276ac54e2fc3d..2356fe5163457 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/metrics/formula.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/metrics/formula.ts @@ -138,6 +138,7 @@ const getFormulaForSubMetric = ({ agg, dataView, aggs, + visType, }: ExtendedColumnConverterArgs): string | null => { const op = SUPPORTED_METRICS[agg.aggType]; if (!op) { @@ -148,7 +149,7 @@ const getFormulaForSubMetric = ({ PARENT_PIPELINE_OPS.includes(op.name) || SIBLING_PIPELINE_AGGS.includes(agg.aggType as METRIC_TYPES) ) { - return getFormulaForPipelineAgg({ agg: agg as PipelineAggs, aggs, dataView }); + return getFormulaForPipelineAgg({ agg: agg as PipelineAggs, aggs, dataView, visType }); } if (METRIC_OPS_WITHOUT_PARAMS.includes(op.name)) { @@ -181,6 +182,7 @@ export const getFormulaForPipelineAgg = ({ agg, dataView, aggs, + visType, }: ExtendedColumnConverterArgs< | METRIC_TYPES.CUMULATIVE_SUM | METRIC_TYPES.DERIVATIVE @@ -205,6 +207,7 @@ export const getFormulaForPipelineAgg = ({ agg: metricAgg, aggs, dataView, + visType, }); if (subFormula === null) { return null; @@ -222,9 +225,10 @@ export const getFormulaForAgg = ({ agg, aggs, dataView, + visType, }: ExtendedColumnConverterArgs) => { if (isPipeline(agg)) { - return getFormulaForPipelineAgg({ agg, aggs, dataView }); + return getFormulaForPipelineAgg({ agg, aggs, dataView, visType }); } if (isPercentileAgg(agg)) { diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/metrics/metrics.test.ts b/src/plugins/visualizations/common/convert_to_lens/lib/metrics/metrics.test.ts index 1cf3ff0b84064..c7674bf6603c0 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/metrics/metrics.test.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/metrics/metrics.test.ts @@ -9,6 +9,7 @@ import { METRIC_TYPES } from '@kbn/data-plugin/common'; import { stubLogstashDataView } from '@kbn/data-views-plugin/common/data_view.stub'; import { SchemaConfig } from '../../..'; +import { ExtendedColumnConverterArgs } from '../convert'; import { convertMetricToColumns } from './metrics'; const mockConvertMetricAggregationColumnWithoutSpecialParams = jest.fn(); @@ -37,6 +38,8 @@ jest.mock('../convert', () => ({ convertToColumnInPercentageMode: jest.fn(() => mockConvertToColumnInPercentageMode()), })); +const visType = 'heatmap'; + describe('convertMetricToColumns invalid cases', () => { const dataView = stubLogstashDataView; @@ -55,13 +58,18 @@ describe('convertMetricToColumns invalid cases', () => { mockConvertToCumulativeSumAggColumn.mockReturnValue(null); }); + const aggs: ExtendedColumnConverterArgs['aggs'] = []; + test.each<[string, Parameters, null, jest.Mock | undefined]>([ [ 'null if agg is not supported', [ - { aggType: METRIC_TYPES.GEO_BOUNDS } as unknown as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.GEO_BOUNDS } as unknown as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], null, @@ -70,9 +78,12 @@ describe('convertMetricToColumns invalid cases', () => { [ 'null if supported agg AVG is not valid', [ - { aggType: METRIC_TYPES.AVG } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.AVG } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], null, @@ -81,9 +92,12 @@ describe('convertMetricToColumns invalid cases', () => { [ 'null if supported agg MIN is not valid', [ - { aggType: METRIC_TYPES.MIN } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.MIN } as SchemaConfig, + dataView, + aggs: [], + visType, + }, { isPercentageMode: false }, ], null, @@ -92,9 +106,12 @@ describe('convertMetricToColumns invalid cases', () => { [ 'null if supported agg MAX is not valid', [ - { aggType: METRIC_TYPES.MAX } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.MAX } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], null, @@ -103,9 +120,12 @@ describe('convertMetricToColumns invalid cases', () => { [ 'null if supported agg SUM is not valid', [ - { aggType: METRIC_TYPES.SUM } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.SUM } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], null, @@ -114,9 +134,12 @@ describe('convertMetricToColumns invalid cases', () => { [ 'null if supported agg COUNT is not valid', [ - { aggType: METRIC_TYPES.COUNT } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.COUNT } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], null, @@ -125,9 +148,12 @@ describe('convertMetricToColumns invalid cases', () => { [ 'null if supported agg CARDINALITY is not valid', [ - { aggType: METRIC_TYPES.CARDINALITY } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.CARDINALITY } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], null, @@ -136,9 +162,12 @@ describe('convertMetricToColumns invalid cases', () => { [ 'null if supported agg VALUE_COUNT is not valid', [ - { aggType: METRIC_TYPES.VALUE_COUNT } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.VALUE_COUNT } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], null, @@ -147,9 +176,12 @@ describe('convertMetricToColumns invalid cases', () => { [ 'null if supported agg MEDIAN is not valid', [ - { aggType: METRIC_TYPES.MEDIAN } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.MEDIAN } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], null, @@ -158,9 +190,12 @@ describe('convertMetricToColumns invalid cases', () => { [ 'null if supported agg STD_DEV is not valid', [ - { aggType: METRIC_TYPES.STD_DEV } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.STD_DEV } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], null, @@ -169,9 +204,12 @@ describe('convertMetricToColumns invalid cases', () => { [ 'null if supported agg PERCENTILES is not valid', [ - { aggType: METRIC_TYPES.PERCENTILES } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.PERCENTILES } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], null, @@ -180,9 +218,12 @@ describe('convertMetricToColumns invalid cases', () => { [ 'null if supported agg SINGLE_PERCENTILE is not valid', [ - { aggType: METRIC_TYPES.SINGLE_PERCENTILE } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.SINGLE_PERCENTILE } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], null, @@ -191,9 +232,12 @@ describe('convertMetricToColumns invalid cases', () => { [ 'null if supported agg PERCENTILE_RANKS is not valid', [ - { aggType: METRIC_TYPES.PERCENTILE_RANKS } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.PERCENTILE_RANKS } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], null, @@ -202,9 +246,12 @@ describe('convertMetricToColumns invalid cases', () => { [ 'null if supported agg SINGLE_PERCENTILE_RANK is not valid', [ - { aggType: METRIC_TYPES.SINGLE_PERCENTILE_RANK } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.SINGLE_PERCENTILE_RANK } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], null, @@ -213,9 +260,12 @@ describe('convertMetricToColumns invalid cases', () => { [ 'null if supported agg TOP_HITS is not valid', [ - { aggType: METRIC_TYPES.TOP_HITS } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.TOP_HITS } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], null, @@ -224,9 +274,12 @@ describe('convertMetricToColumns invalid cases', () => { [ 'null if supported agg TOP_METRICS is not valid', [ - { aggType: METRIC_TYPES.TOP_METRICS } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.TOP_METRICS } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], null, @@ -235,9 +288,12 @@ describe('convertMetricToColumns invalid cases', () => { [ 'null if supported agg CUMULATIVE_SUM is not valid', [ - { aggType: METRIC_TYPES.CUMULATIVE_SUM } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.CUMULATIVE_SUM } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], null, @@ -246,9 +302,12 @@ describe('convertMetricToColumns invalid cases', () => { [ 'null if supported agg DERIVATIVE is not valid', [ - { aggType: METRIC_TYPES.DERIVATIVE } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.DERIVATIVE } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], null, @@ -257,9 +316,12 @@ describe('convertMetricToColumns invalid cases', () => { [ 'null if supported agg MOVING_FN is not valid', [ - { aggType: METRIC_TYPES.MOVING_FN } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.MOVING_FN } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], null, @@ -268,9 +330,12 @@ describe('convertMetricToColumns invalid cases', () => { [ 'null if supported agg SUM_BUCKET is not valid', [ - { aggType: METRIC_TYPES.SUM_BUCKET } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.SUM_BUCKET } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], null, @@ -279,9 +344,12 @@ describe('convertMetricToColumns invalid cases', () => { [ 'null if supported agg MIN_BUCKET is not valid', [ - { aggType: METRIC_TYPES.MIN_BUCKET } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.MIN_BUCKET } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], null, @@ -290,9 +358,12 @@ describe('convertMetricToColumns invalid cases', () => { [ 'null if supported agg MAX_BUCKET is not valid', [ - { aggType: METRIC_TYPES.MAX_BUCKET } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.MAX_BUCKET } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], null, @@ -301,9 +372,12 @@ describe('convertMetricToColumns invalid cases', () => { [ 'null if supported agg AVG_BUCKET is not valid', [ - { aggType: METRIC_TYPES.AVG_BUCKET } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.AVG_BUCKET } as SchemaConfig, + dataView, + aggs: [], + visType, + }, { isPercentageMode: false }, ], null, @@ -312,9 +386,12 @@ describe('convertMetricToColumns invalid cases', () => { [ 'null if supported agg SERIAL_DIFF is not valid', [ - { aggType: METRIC_TYPES.SERIAL_DIFF } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.SERIAL_DIFF } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], null, @@ -330,6 +407,7 @@ describe('convertMetricToColumns invalid cases', () => { }); describe('convertMetricToColumns valid cases', () => { const dataView = stubLogstashDataView; + const aggs: ExtendedColumnConverterArgs['aggs'] = []; beforeEach(() => { jest.clearAllMocks(); @@ -353,9 +431,12 @@ describe('convertMetricToColumns valid cases', () => { [ 'array of columns if supported agg AVG is valid', [ - { aggType: METRIC_TYPES.AVG } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.AVG } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], result, @@ -364,9 +445,12 @@ describe('convertMetricToColumns valid cases', () => { [ 'array of columns if supported agg MIN is valid', [ - { aggType: METRIC_TYPES.MIN } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.MIN } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], result, @@ -375,9 +459,12 @@ describe('convertMetricToColumns valid cases', () => { [ 'array of columns if supported agg MAX is valid', [ - { aggType: METRIC_TYPES.MAX } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.MAX } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], result, @@ -386,9 +473,12 @@ describe('convertMetricToColumns valid cases', () => { [ 'array of columns if supported agg SUM is valid', [ - { aggType: METRIC_TYPES.SUM } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.SUM } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], result, @@ -397,9 +487,12 @@ describe('convertMetricToColumns valid cases', () => { [ 'array of columns if supported agg COUNT is valid', [ - { aggType: METRIC_TYPES.COUNT } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.COUNT } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], result, @@ -408,9 +501,12 @@ describe('convertMetricToColumns valid cases', () => { [ 'array of columns if supported agg CARDINALITY is valid', [ - { aggType: METRIC_TYPES.CARDINALITY } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.CARDINALITY } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], result, @@ -419,9 +515,12 @@ describe('convertMetricToColumns valid cases', () => { [ 'array of columns if supported agg VALUE_COUNT is valid', [ - { aggType: METRIC_TYPES.VALUE_COUNT } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.VALUE_COUNT } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], result, @@ -430,9 +529,12 @@ describe('convertMetricToColumns valid cases', () => { [ 'array of columns if supported agg MEDIAN is valid', [ - { aggType: METRIC_TYPES.MEDIAN } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.MEDIAN } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], result, @@ -441,9 +543,12 @@ describe('convertMetricToColumns valid cases', () => { [ 'array of columns if supported agg STD_DEV is valid', [ - { aggType: METRIC_TYPES.STD_DEV } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.STD_DEV } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], result, @@ -452,9 +557,12 @@ describe('convertMetricToColumns valid cases', () => { [ 'array of columns if supported agg PERCENTILES is valid', [ - { aggType: METRIC_TYPES.PERCENTILES } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.PERCENTILES } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], result, @@ -463,9 +571,12 @@ describe('convertMetricToColumns valid cases', () => { [ 'array of columns if supported agg SINGLE_PERCENTILE is valid', [ - { aggType: METRIC_TYPES.SINGLE_PERCENTILE } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.SINGLE_PERCENTILE } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], result, @@ -474,9 +585,12 @@ describe('convertMetricToColumns valid cases', () => { [ 'array of columns if supported agg PERCENTILE_RANKS is valid', [ - { aggType: METRIC_TYPES.PERCENTILE_RANKS } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.PERCENTILE_RANKS } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], result, @@ -485,9 +599,12 @@ describe('convertMetricToColumns valid cases', () => { [ 'array of columns if supported agg SINGLE_PERCENTILE_RANK is valid', [ - { aggType: METRIC_TYPES.SINGLE_PERCENTILE_RANK } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.SINGLE_PERCENTILE_RANK } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], result, @@ -496,9 +613,12 @@ describe('convertMetricToColumns valid cases', () => { [ 'array of columns if supported agg TOP_HITS is valid', [ - { aggType: METRIC_TYPES.TOP_HITS } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.TOP_HITS } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], result, @@ -507,9 +627,12 @@ describe('convertMetricToColumns valid cases', () => { [ 'array of columns if supported agg TOP_METRICS is valid', [ - { aggType: METRIC_TYPES.TOP_METRICS } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.TOP_METRICS } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], result, @@ -518,9 +641,12 @@ describe('convertMetricToColumns valid cases', () => { [ 'array of columns if supported agg CUMULATIVE_SUM is valid', [ - { aggType: METRIC_TYPES.CUMULATIVE_SUM } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.CUMULATIVE_SUM } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], result, @@ -529,9 +655,12 @@ describe('convertMetricToColumns valid cases', () => { [ 'array of columns if supported agg DERIVATIVE is valid', [ - { aggType: METRIC_TYPES.DERIVATIVE } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.DERIVATIVE } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], result, @@ -540,9 +669,12 @@ describe('convertMetricToColumns valid cases', () => { [ 'array of columns if supported agg MOVING_FN is valid', [ - { aggType: METRIC_TYPES.MOVING_FN } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.MOVING_FN } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], result, @@ -551,9 +683,12 @@ describe('convertMetricToColumns valid cases', () => { [ 'array of columns if supported agg SUM_BUCKET is valid', [ - { aggType: METRIC_TYPES.SUM_BUCKET } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.SUM_BUCKET } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], result, @@ -562,9 +697,12 @@ describe('convertMetricToColumns valid cases', () => { [ 'array of columns if supported agg MIN_BUCKET is valid', [ - { aggType: METRIC_TYPES.MIN_BUCKET } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.MIN_BUCKET } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], result, @@ -573,9 +711,12 @@ describe('convertMetricToColumns valid cases', () => { [ 'array of columns if supported agg MAX_BUCKET is valid', [ - { aggType: METRIC_TYPES.MAX_BUCKET } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.MAX_BUCKET } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], result, @@ -584,9 +725,12 @@ describe('convertMetricToColumns valid cases', () => { [ 'array of columns if supported agg AVG_BUCKET is valid', [ - { aggType: METRIC_TYPES.AVG_BUCKET } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.AVG_BUCKET } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: false }, ], result, @@ -595,9 +739,12 @@ describe('convertMetricToColumns valid cases', () => { [ 'column in percentage mode without range if percentageMode is enabled ', [ - { aggType: METRIC_TYPES.AVG_BUCKET } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.AVG_BUCKET } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: true, min: 0, max: 100 }, ], result, @@ -606,9 +753,12 @@ describe('convertMetricToColumns valid cases', () => { [ 'column in percentage mode with range if percentageMode is enabled ', [ - { aggType: METRIC_TYPES.AVG_BUCKET } as SchemaConfig, - dataView, - [], + { + agg: { aggType: METRIC_TYPES.AVG_BUCKET } as SchemaConfig, + dataView, + aggs, + visType, + }, { isPercentageMode: true, min: 0, max: 100 }, ], result, diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/metrics/metrics.ts b/src/plugins/visualizations/common/convert_to_lens/lib/metrics/metrics.ts index be4c92cd4ec7f..5d765a6f286ba 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/metrics/metrics.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/metrics/metrics.ts @@ -7,8 +7,7 @@ */ import { METRIC_TYPES } from '@kbn/data-plugin/common'; -import type { DataView } from '@kbn/data-views-plugin/common'; -import { PercentageModeConfig, SchemaConfig } from '../../..'; +import { PercentageModeConfig } from '../../..'; import { convertMetricAggregationColumnWithoutSpecialParams, convertToOtherParentPipelineAggColumns, @@ -20,14 +19,13 @@ import { convertToCumulativeSumAggColumn, AggBasedColumn, convertToColumnInPercentageMode, + ExtendedColumnConverterArgs, } from '../convert'; import { SUPPORTED_METRICS } from '../convert/supported_metrics'; import { getValidColumns } from '../utils'; export const convertMetricToColumns = ( - agg: SchemaConfig, - dataView: DataView, - aggs: Array>, + { agg, dataView, aggs, visType }: ExtendedColumnConverterArgs, percentageModeConfig: PercentageModeConfig = { isPercentageMode: false } ): AggBasedColumn[] | null => { const supportedAgg = SUPPORTED_METRICS[agg.aggType]; @@ -38,7 +36,7 @@ export const convertMetricToColumns = ( if (percentageModeConfig.isPercentageMode) { const { isPercentageMode, ...minMax } = percentageModeConfig; - const formulaColumn = convertToColumnInPercentageMode({ agg, dataView, aggs }, minMax); + const formulaColumn = convertToColumnInPercentageMode({ agg, dataView, aggs, visType }, minMax); return getValidColumns(formulaColumn); } @@ -54,6 +52,7 @@ export const convertMetricToColumns = ( const columns = convertMetricAggregationColumnWithoutSpecialParams(supportedAgg, { agg, dataView, + visType, }); return getValidColumns(columns); } @@ -61,6 +60,7 @@ export const convertMetricToColumns = ( const columns = convertToStdDeviationFormulaColumns({ agg, dataView, + visType, }); return getValidColumns(columns); } @@ -68,6 +68,7 @@ export const convertMetricToColumns = ( const columns = convertToPercentileColumn({ agg, dataView, + visType, }); return getValidColumns(columns); } @@ -75,6 +76,7 @@ export const convertMetricToColumns = ( const columns = convertToPercentileColumn({ agg, dataView, + visType, }); return getValidColumns(columns); } @@ -82,6 +84,7 @@ export const convertMetricToColumns = ( const columns = convertToPercentileRankColumn({ agg, dataView, + visType, }); return getValidColumns(columns); } @@ -89,6 +92,7 @@ export const convertMetricToColumns = ( const columns = convertToPercentileRankColumn({ agg, dataView, + visType, }); return getValidColumns(columns); } @@ -97,6 +101,7 @@ export const convertMetricToColumns = ( const columns = convertToLastValueColumn({ agg, dataView, + visType, }); return getValidColumns(columns); } @@ -105,6 +110,7 @@ export const convertMetricToColumns = ( agg, dataView, aggs, + visType, }); return getValidColumns(columns); } @@ -114,6 +120,7 @@ export const convertMetricToColumns = ( agg, dataView, aggs, + visType, }); return getValidColumns(columns); } @@ -125,6 +132,7 @@ export const convertMetricToColumns = ( agg, dataView, aggs, + visType, }); return getValidColumns(columns); } diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/metrics/percentage_formula.test.ts b/src/plugins/visualizations/common/convert_to_lens/lib/metrics/percentage_formula.test.ts index 9855ce44b6602..fe6204d1fb2a1 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/metrics/percentage_formula.test.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/metrics/percentage_formula.test.ts @@ -24,6 +24,7 @@ jest.mock('../convert', () => ({ })); describe('getPercentageColumnFormulaColumn', () => { + const visType = 'heatmap'; const dataView = stubLogstashDataView; const field = stubLogstashDataView.fields[0].name; const aggs: Array> = [ @@ -52,7 +53,7 @@ describe('getPercentageColumnFormulaColumn', () => { >([ [ 'null if cannot build formula for provided agg', - [{ agg: aggs[0], aggs, dataView }], + [{ agg: aggs[0], aggs, dataView, visType }], () => { mockGetFormulaForAgg.mockReturnValue(null); }, @@ -60,7 +61,7 @@ describe('getPercentageColumnFormulaColumn', () => { ], [ 'null if cannot create formula column for provided arguments', - [{ agg: aggs[0], aggs, dataView }], + [{ agg: aggs[0], aggs, dataView, visType }], () => { mockGetFormulaForAgg.mockReturnValue('test-formula'); mockCreateFormulaColumn.mockReturnValue(null); @@ -69,7 +70,7 @@ describe('getPercentageColumnFormulaColumn', () => { ], [ 'formula column if provided arguments are valid', - [{ agg: aggs[0], aggs, dataView }], + [{ agg: aggs[0], aggs, dataView, visType }], () => { mockGetFormulaForAgg.mockReturnValue('test-formula'); mockCreateFormulaColumn.mockImplementation((formula) => ({ diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/metrics/percentage_formula.ts b/src/plugins/visualizations/common/convert_to_lens/lib/metrics/percentage_formula.ts index 773851a770db4..8d7194d5c25df 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/metrics/percentage_formula.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/metrics/percentage_formula.ts @@ -14,8 +14,9 @@ export const getPercentageColumnFormulaColumn = ({ agg, aggs, dataView, + visType, }: ExtendedColumnConverterArgs): FormulaColumn | null => { - const metricFormula = getFormulaForAgg({ agg, aggs, dataView }); + const metricFormula = getFormulaForAgg({ agg, aggs, dataView, visType }); if (!metricFormula) { return null; } 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 6c2e4b449d0d2..27854a3d01f04 100644 --- a/src/plugins/visualizations/common/convert_to_lens/types/configurations.ts +++ b/src/plugins/visualizations/common/convert_to_lens/types/configurations.ts @@ -288,6 +288,19 @@ export interface HeatmapLegendConfig { legendSize?: LegendSize; type: 'heatmap_legend'; } + +export interface HeatmapGridConfig { + strokeWidth?: number; + strokeColor?: string; + isCellLabelVisible: boolean; + isYAxisLabelVisible: boolean; + isYAxisTitleVisible: boolean; + yTitle?: string; + isXAxisLabelVisible: boolean; + isXAxisTitleVisible: boolean; + xTitle?: string; + type: 'heatmap_grid'; +} export interface HeatmapArguments { percentageMode?: boolean; lastRangeIsRightOpen?: boolean; @@ -300,7 +313,7 @@ export interface HeatmapArguments { splitRowAccessor?: string | ExpressionValueVisDimension; splitColumnAccessor?: string | ExpressionValueVisDimension; legend: HeatmapLegendConfig; - gridConfig: HeatmapLegendConfig; + gridConfig: HeatmapGridConfig; ariaLabel?: string; } diff --git a/src/plugins/visualizations/public/convert_to_lens/schemas.ts b/src/plugins/visualizations/public/convert_to_lens/schemas.ts index 3a225e540faae..1b44f7cdffda1 100644 --- a/src/plugins/visualizations/public/convert_to_lens/schemas.ts +++ b/src/plugins/visualizations/public/convert_to_lens/schemas.ts @@ -33,6 +33,7 @@ const areVisSchemasValid = (visSchemas: Schemas, unsupported: Array>, metricsForLayer: Array>, @@ -52,7 +53,7 @@ const createLayer = ( dropEmptyRowsInDateHistogram?: boolean ) => { const metricColumns = metricsForLayer.flatMap((m) => - convertMetricToColumns(m, dataView, allMetrics, percentageModeConfig) + convertMetricToColumns({ agg: m, dataView, aggs: allMetrics, visType }, percentageModeConfig) ); if (metricColumns.includes(null)) { return null; @@ -60,6 +61,7 @@ const createLayer = ( const metricColumnsWithoutNull = metricColumns as AggBasedColumn[]; const { customBucketColumns, customBucketsMap } = getCustomBucketColumns( + visType, customBucketsWithMetricIds, metricColumnsWithoutNull, dataView, @@ -72,6 +74,7 @@ const createLayer = ( } const bucketColumns = getBucketColumns( + visType, visSchemas, buckets, dataView, @@ -84,6 +87,7 @@ const createLayer = ( } const splitBucketColumns = getBucketColumns( + visType, visSchemas, splits, dataView, @@ -181,6 +185,7 @@ export const getColumnsFromVis = ( c.metricIds.some((m) => metricAggIds.includes(m)) ); const layer = createLayer( + vis.type.name, visSchemas, aggs, metrics, @@ -197,6 +202,7 @@ export const getColumnsFromVis = ( } } else { const layer = createLayer( + vis.type.name, visSchemas, aggs, aggs, diff --git a/src/plugins/visualizations/public/convert_to_lens/utils.test.ts b/src/plugins/visualizations/public/convert_to_lens/utils.test.ts index 50f667430a8cb..8c36b28452271 100644 --- a/src/plugins/visualizations/public/convert_to_lens/utils.test.ts +++ b/src/plugins/visualizations/public/convert_to_lens/utils.test.ts @@ -213,6 +213,7 @@ describe('getBucketCollapseFn', () => { describe('getBucketColumns', () => { const dataView = stubLogstashDataView; + const visType = 'heatmap'; beforeEach(() => { jest.clearAllMocks(); @@ -228,7 +229,7 @@ describe('getBucketColumns', () => { [bucketKey]: [], }; - expect(getBucketColumns(visSchemas, keys, dataView, false, [])).toEqual([]); + expect(getBucketColumns(visType, visSchemas, keys, dataView, false, [])).toEqual([]); expect(mockConvertBucketToColumns).toBeCalledTimes(0); }); @@ -254,7 +255,7 @@ describe('getBucketColumns', () => { }; mockConvertBucketToColumns.mockReturnValueOnce(null); - expect(getBucketColumns(visSchemas, keys, dataView, false, [])).toBeNull(); + expect(getBucketColumns(visType, visSchemas, keys, dataView, false, [])).toBeNull(); expect(mockConvertBucketToColumns).toBeCalledTimes(1); }); @@ -280,7 +281,7 @@ describe('getBucketColumns', () => { }; mockConvertBucketToColumns.mockReturnValueOnce([null]); - expect(getBucketColumns(visSchemas, keys, dataView, false, [])).toBeNull(); + expect(getBucketColumns(visType, visSchemas, keys, dataView, false, [])).toBeNull(); expect(mockConvertBucketToColumns).toBeCalledTimes(1); }); test('should return columns', () => { @@ -319,7 +320,7 @@ describe('getBucketColumns', () => { mockConvertBucketToColumns.mockReturnValue(returnValue); - expect(getBucketColumns(visSchemas, keys, dataView, false, [])).toEqual([ + expect(getBucketColumns(visType, visSchemas, keys, dataView, false, [])).toEqual([ ...returnValue, ...returnValue, ]); @@ -592,6 +593,8 @@ describe('sortColumns', () => { }); describe('getColumnIds', () => { + const visType = 'heatmap'; + const colId1 = '0_agg_id'; const colId2 = '1_agg_id'; const colId3 = '2_agg_id'; @@ -694,6 +697,7 @@ describe('getColumnIds', () => { }); expect( getCustomBucketColumns( + visType, customBucketsWithMetricIds, [ { columnId: 'col-3', meta: { aggId: '3' } }, diff --git a/src/plugins/visualizations/public/convert_to_lens/utils.ts b/src/plugins/visualizations/public/convert_to_lens/utils.ts index ba05d29cdeea9..531746ff86d87 100644 --- a/src/plugins/visualizations/public/convert_to_lens/utils.ts +++ b/src/plugins/visualizations/public/convert_to_lens/utils.ts @@ -63,6 +63,7 @@ export const getBucketCollapseFn = ( }; export const getBucketColumns = ( + visType: string, visSchemas: Schemas, keys: Array, dataView: DataView, @@ -78,6 +79,7 @@ export const getBucketColumns = ( { agg: m, dataView, + visType, metricColumns, aggs: visSchemas.metric as Array>, }, @@ -154,6 +156,7 @@ export const sortColumns = ( export const getColumnIds = (columns: AggBasedColumn[]) => columns.map(({ columnId }) => columnId); export const getCustomBucketColumns = ( + visType: string, customBucketsWithMetricIds: Array<{ customBucket: IAggConfig; metricIds: string[]; @@ -167,7 +170,7 @@ export const getCustomBucketColumns = ( const customBucketsMap: Record = {}; customBucketsWithMetricIds.forEach((customBucketWithMetricIds) => { const customBucketColumn = convertBucketToColumns( - { agg: customBucketWithMetricIds.customBucket, dataView, metricColumns, aggs }, + { agg: customBucketWithMetricIds.customBucket, dataView, metricColumns, aggs, visType }, true, dropEmptyRowsInDateHistogram ); diff --git a/x-pack/plugins/lens/public/visualizations/heatmap/visualization.tsx b/x-pack/plugins/lens/public/visualizations/heatmap/visualization.tsx index 89833c007b35e..fc8ef976548b4 100644 --- a/x-pack/plugins/lens/public/visualizations/heatmap/visualization.tsx +++ b/x-pack/plugins/lens/public/visualizations/heatmap/visualization.tsx @@ -17,6 +17,7 @@ import { ThemeServiceStart } from '@kbn/core/public'; import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; import { VIS_EVENT_TO_TRIGGER } from '@kbn/visualizations-plugin/public'; import { LayerTypes } from '@kbn/expression-xy-plugin/public'; +import { HeatmapConfiguration } from '@kbn/visualizations-plugin/common'; import type { OperationMetadata, Suggestion, Visualization } from '../../types'; import type { HeatmapVisualizationState } from './types'; import { getSuggestions } from './suggestions'; @@ -545,7 +546,7 @@ export const getHeatmapVisualization = ({ }, visualizationState: { ...allSuggestions[0].visualizationState, - ...context.configuration, + ...(context.configuration as HeatmapConfiguration), }, }; return suggestion; From fd2de53e333dc0eb1ea728b56f0d2c3dade84221 Mon Sep 17 00:00:00 2001 From: Yaroslav Kuznietsov Date: Fri, 21 Oct 2022 17:59:36 +0300 Subject: [PATCH 07/26] Added validation according to the --- .../convert_to_lens/lib/convert/last_value.ts | 8 ++- .../convert_to_lens/lib/convert/metric.ts | 4 +- .../convert_to_lens/lib/convert/percentile.ts | 3 +- .../lib/convert/percentile_rank.ts | 3 +- .../lib/convert/std_deviation.ts | 4 +- .../lib/convert/supported_metrics.ts | 62 +++++++++++-------- .../convert_to_lens/lib/metrics/formula.ts | 20 ++++-- .../common/convert_to_lens/utils.ts | 12 +++- 8 files changed, 74 insertions(+), 42 deletions(-) diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/convert/last_value.ts b/src/plugins/visualizations/common/convert_to_lens/lib/convert/last_value.ts index 3162cf14e71c3..9525f4b41b7eb 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/convert/last_value.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/convert/last_value.ts @@ -25,7 +25,11 @@ const convertToLastValueParams = ( }; export const convertToLastValueColumn = ( - { agg, dataView }: CommonColumnConverterArgs, + { + visType, + agg, + dataView, + }: CommonColumnConverterArgs, reducedTimeRange?: string ): LastValueColumn | null => { const { aggParams } = agg; @@ -43,7 +47,7 @@ export const convertToLastValueColumn = ( } const field = dataView.getFieldByName(fieldName); - if (!isFieldValid(field, SUPPORTED_METRICS[agg.aggType])) { + if (!isFieldValid(visType, field, SUPPORTED_METRICS[agg.aggType])) { return null; } diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/convert/metric.ts b/src/plugins/visualizations/common/convert_to_lens/lib/convert/metric.ts index eb21b9f0fe91d..dd6c8b02687b0 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/convert/metric.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/convert/metric.ts @@ -78,7 +78,7 @@ export const isMetricWithField = ( export const convertMetricAggregationColumnWithoutSpecialParams = ( aggregation: SupportedMetric, - { agg, dataView }: CommonColumnConverterArgs, + { visType, agg, dataView }: CommonColumnConverterArgs, reducedTimeRange?: string ): MetricAggregationColumnWithoutSpecialParams | null => { if (!isSupportedAggregationWithoutParams(aggregation.name)) { @@ -94,7 +94,7 @@ export const convertMetricAggregationColumnWithoutSpecialParams = ( } const field = dataView.getFieldByName(sourceField); - if (!isFieldValid(field, aggregation)) { + if (!isFieldValid(visType, field, aggregation)) { return null; } diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/convert/percentile.ts b/src/plugins/visualizations/common/convert_to_lens/lib/convert/percentile.ts index de9d4e088b636..9989db1c5dda7 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/convert/percentile.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/convert/percentile.ts @@ -51,6 +51,7 @@ const getPercent = ( export const convertToPercentileColumn = ( { + visType, agg, dataView, }: CommonColumnConverterArgs, @@ -74,7 +75,7 @@ export const convertToPercentileColumn = ( } const field = dataView.getFieldByName(fieldName); - if (!isFieldValid(field, SUPPORTED_METRICS[agg.aggType])) { + if (!isFieldValid(visType, field, SUPPORTED_METRICS[agg.aggType])) { return null; } diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/convert/percentile_rank.ts b/src/plugins/visualizations/common/convert_to_lens/lib/convert/percentile_rank.ts index 5124a26543552..8fb55789dd6a7 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/convert/percentile_rank.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/convert/percentile_rank.ts @@ -50,6 +50,7 @@ const getPercent = ( export const convertToPercentileRankColumn = ( { + visType, agg, dataView, }: CommonColumnConverterArgs, @@ -69,7 +70,7 @@ export const convertToPercentileRankColumn = ( } const field = dataView.getFieldByName(fieldName); - if (!isFieldValid(field, SUPPORTED_METRICS[agg.aggType])) { + if (!isFieldValid(visType, field, SUPPORTED_METRICS[agg.aggType])) { return null; } diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/convert/std_deviation.ts b/src/plugins/visualizations/common/convert_to_lens/lib/convert/std_deviation.ts index f2c218d429bdf..fe4e854759d8f 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/convert/std_deviation.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/convert/std_deviation.ts @@ -50,7 +50,7 @@ export const getStdDeviationFormula = ( }; export const convertToStdDeviationFormulaColumns = ( - { agg, dataView }: CommonColumnConverterArgs, + { visType, agg, dataView }: CommonColumnConverterArgs, reducedTimeRange?: string ) => { const { aggId } = agg; @@ -64,7 +64,7 @@ export const convertToStdDeviationFormulaColumns = ( return null; } const field = dataView.getFieldByName(fieldName); - if (!isFieldValid(field, SUPPORTED_METRICS[agg.aggType])) { + if (!isFieldValid(visType, field, SUPPORTED_METRICS[agg.aggType])) { return null; } diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/convert/supported_metrics.ts b/src/plugins/visualizations/common/convert_to_lens/lib/convert/supported_metrics.ts index 17a8ccf26c369..13492b4c74258 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/convert/supported_metrics.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/convert/supported_metrics.ts @@ -18,10 +18,12 @@ interface AggWithFormula { formula: string; } +type SupportedDataTypes = { [key: string]: readonly string[] } & { default: readonly string[] }; + export type AggOptions = { isFullReference: boolean; isFieldRequired: boolean; - supportedDataTypes: readonly string[]; + supportedDataTypes: SupportedDataTypes; } & (T extends Exclude ? Agg : AggWithFormula); // list of supported TSVB aggregation types in Lens @@ -62,9 +64,9 @@ export type SupportedMetrics = LocalSupportedMetrics & { [Key in UnsupportedSupportedMetrics]?: null; }; -const supportedDataTypesWithDate = ['number', 'date', 'histogram'] as const; -const supportedDataTypes = ['number', 'histogram'] as const; -const extendedSupportedDataTypes = [ +const supportedDataTypesWithDate: readonly string[] = ['number', 'date', 'histogram']; +const supportedDataTypes: readonly string[] = ['number', 'histogram']; +const extendedSupportedDataTypes: readonly string[] = [ 'string', 'boolean', 'number', @@ -74,44 +76,44 @@ const extendedSupportedDataTypes = [ 'date', 'date_range', 'murmur3', -] as const; +]; export const SUPPORTED_METRICS: SupportedMetrics = { avg: { name: 'average', isFullReference: false, isFieldRequired: true, - supportedDataTypes: ['number'], + supportedDataTypes: { default: ['number'] }, }, cardinality: { name: 'unique_count', isFullReference: false, isFieldRequired: true, - supportedDataTypes: extendedSupportedDataTypes, + supportedDataTypes: { default: extendedSupportedDataTypes }, }, count: { name: 'count', isFullReference: false, isFieldRequired: false, - supportedDataTypes: [], + supportedDataTypes: { default: ['number'] }, }, moving_avg: { name: 'moving_average', isFullReference: true, isFieldRequired: true, - supportedDataTypes: ['number'], + supportedDataTypes: { default: ['number'] }, }, derivative: { name: 'differences', isFullReference: true, isFieldRequired: true, - supportedDataTypes: ['number'], + supportedDataTypes: { default: ['number'] }, }, cumulative_sum: { name: 'cumulative_sum', isFullReference: true, isFieldRequired: true, - supportedDataTypes: ['number'], + supportedDataTypes: { default: ['number'] }, }, avg_bucket: { name: 'formula', @@ -119,7 +121,7 @@ export const SUPPORTED_METRICS: SupportedMetrics = { isFieldRequired: true, isFormula: true, formula: 'overall_average', - supportedDataTypes: ['number'], + supportedDataTypes: { default: ['number'] }, }, max_bucket: { name: 'formula', @@ -127,7 +129,7 @@ export const SUPPORTED_METRICS: SupportedMetrics = { isFieldRequired: true, isFormula: true, formula: 'overall_max', - supportedDataTypes: ['number'], + supportedDataTypes: { default: ['number'] }, }, min_bucket: { name: 'formula', @@ -135,7 +137,7 @@ export const SUPPORTED_METRICS: SupportedMetrics = { isFieldRequired: true, isFormula: true, formula: 'overall_min', - supportedDataTypes: ['number'], + supportedDataTypes: { default: ['number'] }, }, sum_bucket: { name: 'formula', @@ -143,79 +145,85 @@ export const SUPPORTED_METRICS: SupportedMetrics = { isFieldRequired: true, isFormula: true, formula: 'overall_sum', - supportedDataTypes: ['number'], + supportedDataTypes: { default: ['number'] }, }, max: { name: 'max', isFullReference: false, isFieldRequired: true, - supportedDataTypes: supportedDataTypesWithDate, + supportedDataTypes: { + default: ['number'], + heatmap: ['number'], + }, }, min: { name: 'min', isFullReference: false, isFieldRequired: true, - supportedDataTypes: supportedDataTypesWithDate, + supportedDataTypes: { + default: supportedDataTypesWithDate, + heatmap: ['number'], + }, }, percentiles: { name: 'percentile', isFullReference: false, isFieldRequired: true, - supportedDataTypes, + supportedDataTypes: { default: supportedDataTypes }, }, single_percentile: { name: 'percentile', isFullReference: false, isFieldRequired: true, - supportedDataTypes, + supportedDataTypes: { default: supportedDataTypes }, }, percentile_ranks: { name: 'percentile_rank', isFullReference: false, isFieldRequired: true, - supportedDataTypes, + supportedDataTypes: { default: supportedDataTypes }, }, single_percentile_rank: { name: 'percentile_rank', isFullReference: false, isFieldRequired: true, - supportedDataTypes, + supportedDataTypes: { default: supportedDataTypes }, }, sum: { name: 'sum', isFullReference: false, isFieldRequired: true, - supportedDataTypes, + supportedDataTypes: { default: supportedDataTypes }, }, top_hits: { name: 'last_value', isFullReference: false, isFieldRequired: true, - supportedDataTypes: extendedSupportedDataTypes, + supportedDataTypes: { default: extendedSupportedDataTypes }, }, top_metrics: { name: 'last_value', isFullReference: false, isFieldRequired: true, - supportedDataTypes: extendedSupportedDataTypes, + supportedDataTypes: { default: extendedSupportedDataTypes }, }, value_count: { name: 'count', isFullReference: false, isFieldRequired: true, - supportedDataTypes: extendedSupportedDataTypes, + supportedDataTypes: { default: extendedSupportedDataTypes }, }, std_dev: { name: 'standard_deviation', isFullReference: false, isFieldRequired: true, - supportedDataTypes, + supportedDataTypes: { default: supportedDataTypes }, }, median: { name: 'median', isFullReference: false, isFieldRequired: true, - supportedDataTypes, + supportedDataTypes: { default: supportedDataTypes }, }, } as const; diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/metrics/formula.ts b/src/plugins/visualizations/common/convert_to_lens/lib/metrics/formula.ts index 2356fe5163457..4492cd58ac230 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/metrics/formula.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/metrics/formula.ts @@ -66,7 +66,7 @@ const isDataViewField = (field: string | DataViewField): field is DataViewField return false; }; -const isValidAgg = (agg: SchemaConfig, dataView: DataView) => { +const isValidAgg = (visType: string, agg: SchemaConfig, dataView: DataView) => { const aggregation = SUPPORTED_METRICS[agg.aggType]; if (!aggregation) { return false; @@ -77,7 +77,7 @@ const isValidAgg = (agg: SchemaConfig, dataView: DataView) => { } const sourceField = getFieldNameFromField(agg.aggParams?.field); const field = dataView.getFieldByName(sourceField!); - if (!isFieldValid(field, aggregation)) { + if (!isFieldValid(visType, field, aggregation)) { return false; } } @@ -86,13 +86,14 @@ const isValidAgg = (agg: SchemaConfig, dataView: DataView) => { }; const getFormulaForAggsWithoutParams = ( + visType: string, agg: SchemaConfig, dataView: DataView, selector: string | undefined, reducedTimeRange?: string ) => { const op = SUPPORTED_METRICS[agg.aggType]; - if (!isValidAgg(agg, dataView) || !op) { + if (!isValidAgg(visType, agg, dataView) || !op) { return null; } @@ -101,6 +102,7 @@ const getFormulaForAggsWithoutParams = ( }; const getFormulaForPercentileRanks = ( + visType: string, agg: SchemaConfig, dataView: DataView, selector: string | undefined, @@ -108,7 +110,7 @@ const getFormulaForPercentileRanks = ( ) => { const value = Number(agg.aggId?.split('.')[1]); const op = SUPPORTED_METRICS[agg.aggType]; - if (!isValidAgg(agg, dataView) || !op) { + if (!isValidAgg(visType, agg, dataView) || !op) { return null; } @@ -117,6 +119,7 @@ const getFormulaForPercentileRanks = ( }; const getFormulaForPercentile = ( + visType: string, agg: SchemaConfig, dataView: DataView, selector: string, @@ -124,7 +127,7 @@ const getFormulaForPercentile = ( ) => { const percentile = Number(agg.aggId?.split('.')[1]); const op = SUPPORTED_METRICS[agg.aggType]; - if (!isValidAgg(agg, dataView) || !op) { + if (!isValidAgg(visType, agg, dataView) || !op) { return null; } @@ -155,6 +158,7 @@ const getFormulaForSubMetric = ({ if (METRIC_OPS_WITHOUT_PARAMS.includes(op.name)) { const metricAgg = agg as MetricAggsWithoutParams; return getFormulaForAggsWithoutParams( + visType, metricAgg, dataView, metricAgg.aggParams && 'field' in metricAgg.aggParams @@ -169,6 +173,7 @@ const getFormulaForSubMetric = ({ const percentileRanksAgg = agg as SchemaConfig; return getFormulaForPercentileRanks( + visType, percentileRanksAgg, dataView, percentileRanksAgg.aggParams?.field @@ -233,6 +238,7 @@ export const getFormulaForAgg = ({ if (isPercentileAgg(agg)) { return getFormulaForPercentile( + visType, agg, dataView, getFieldNameFromField(agg.aggParams?.field) ?? '' @@ -241,6 +247,7 @@ export const getFormulaForAgg = ({ if (isPercentileRankAgg(agg)) { return getFormulaForPercentileRanks( + visType, agg, dataView, getFieldNameFromField(agg.aggParams?.field) ?? '' @@ -248,13 +255,14 @@ export const getFormulaForAgg = ({ } if (isStdDevAgg(agg) && agg.aggId) { - if (!isValidAgg(agg, dataView)) { + if (!isValidAgg(visType, agg, dataView)) { return null; } return getStdDeviationFormula(agg.aggId, getFieldNameFromField(agg.aggParams?.field) ?? ''); } return getFormulaForAggsWithoutParams( + visType, agg, dataView, isMetricWithField(agg) ? getFieldNameFromField(agg.aggParams?.field) ?? '' : '' diff --git a/src/plugins/visualizations/common/convert_to_lens/utils.ts b/src/plugins/visualizations/common/convert_to_lens/utils.ts index 6a875bf63bea4..88c2802c421ec 100644 --- a/src/plugins/visualizations/common/convert_to_lens/utils.ts +++ b/src/plugins/visualizations/common/convert_to_lens/utils.ts @@ -18,7 +18,17 @@ export const isAnnotationsLayer = ( export const getIndexPatternIds = (layers: Layer[]) => layers.map(({ indexPatternId }) => indexPatternId); +const isValidFieldType = ( + visType: string, + { supportedDataTypes }: SupportedMetric, + field: DataViewField +) => { + const availableDataTypes = supportedDataTypes[visType] ?? supportedDataTypes.default; + return availableDataTypes.includes(field.type); +}; + export const isFieldValid = ( + visType: string, field: DataViewField | undefined, aggregation: SupportedMetric ): field is DataViewField => { @@ -26,7 +36,7 @@ export const isFieldValid = ( return false; } - if (field && (!field.aggregatable || !aggregation.supportedDataTypes.includes(field.type))) { + if (field && (!field.aggregatable || !isValidFieldType(visType, aggregation, field))) { return false; } From 962bde41c446c0f805c5f9f28ca5d2b9cca1c84a Mon Sep 17 00:00:00 2001 From: Yaroslav Kuznietsov Date: Fri, 21 Oct 2022 18:34:36 +0300 Subject: [PATCH 08/26] Fixed heatmap std_dev. --- src/plugins/vis_types/heatmap/public/convert_to_lens/index.ts | 2 +- .../common/convert_to_lens/lib/convert/formula.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/vis_types/heatmap/public/convert_to_lens/index.ts b/src/plugins/vis_types/heatmap/public/convert_to_lens/index.ts index 645deb4d34d82..715447b30d377 100644 --- a/src/plugins/vis_types/heatmap/public/convert_to_lens/index.ts +++ b/src/plugins/vis_types/heatmap/public/convert_to_lens/index.ts @@ -56,7 +56,7 @@ export const convertToLens: ConvertHeatmapToLensVisualization = async (vis, time const [layerConfig] = layers; - if (!layerConfig.buckets.all.length) { + if (!layerConfig.buckets.all.length || layerConfig.metrics.length > 1) { return null; } diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/convert/formula.ts b/src/plugins/visualizations/common/convert_to_lens/lib/convert/formula.ts index 0ad2a4072e19d..e79be2ba51516 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/convert/formula.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/convert/formula.ts @@ -21,6 +21,7 @@ export const createFormulaColumn = (formula: string, agg: SchemaConfig): Formula operationType: 'formula', ...createColumn(agg), references: [], + dataType: 'number', params: { ...params, ...getFormat() }, timeShift: agg.aggParams?.timeShift, meta: { aggId: createAggregationId(agg) }, From b27d502233df89c9bd3bbcb261844f27c3a4c122 Mon Sep 17 00:00:00 2001 From: Yaroslav Kuznietsov Date: Fri, 21 Oct 2022 18:45:20 +0300 Subject: [PATCH 09/26] Fixed failing xy. --- .../common/convert_to_lens/lib/convert/supported_metrics.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/convert/supported_metrics.ts b/src/plugins/visualizations/common/convert_to_lens/lib/convert/supported_metrics.ts index 13492b4c74258..61f3f3961b6dc 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/convert/supported_metrics.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/convert/supported_metrics.ts @@ -154,6 +154,9 @@ export const SUPPORTED_METRICS: SupportedMetrics = { supportedDataTypes: { default: ['number'], heatmap: ['number'], + line: ['number'], + area: ['number'], + histogram: ['number'], }, }, min: { @@ -163,6 +166,9 @@ export const SUPPORTED_METRICS: SupportedMetrics = { supportedDataTypes: { default: supportedDataTypesWithDate, heatmap: ['number'], + line: ['number'], + area: ['number'], + histogram: ['number'], }, }, percentiles: { From 17940ba449732fb33243eb7a640ceb0b7683b99b Mon Sep 17 00:00:00 2001 From: Yaroslav Kuznietsov Date: Mon, 24 Oct 2022 10:31:23 +0300 Subject: [PATCH 10/26] Fixed tests. --- .../__snapshots__/heatmap_function.test.ts.snap | 1 + .../visualizations/public/convert_to_lens/schemas.test.ts | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/plugins/chart_expressions/expression_heatmap/common/expression_functions/__snapshots__/heatmap_function.test.ts.snap b/src/plugins/chart_expressions/expression_heatmap/common/expression_functions/__snapshots__/heatmap_function.test.ts.snap index 96b70e33021f4..1b644ef0a4938 100644 --- a/src/plugins/chart_expressions/expression_heatmap/common/expression_functions/__snapshots__/heatmap_function.test.ts.snap +++ b/src/plugins/chart_expressions/expression_heatmap/common/expression_functions/__snapshots__/heatmap_function.test.ts.snap @@ -77,6 +77,7 @@ Object { "xAccessor": "col-1-2", "yAccessor": undefined, }, + "canNavigateToLens": false, "data": Object { "columns": Array [ Object { diff --git a/src/plugins/visualizations/public/convert_to_lens/schemas.test.ts b/src/plugins/visualizations/public/convert_to_lens/schemas.test.ts index 54975d08b8486..aa338db367988 100644 --- a/src/plugins/visualizations/public/convert_to_lens/schemas.test.ts +++ b/src/plugins/visualizations/public/convert_to_lens/schemas.test.ts @@ -70,7 +70,9 @@ describe('getColumnsFromVis', () => { ); const aggConfig = new AggConfig(aggConfigs, {} as AggConfigOptions); - const vis = {} as Vis; + const vis = { + type: { name: 'heatmap' }, + } as Vis; beforeEach(() => { jest.clearAllMocks(); mockGetVisSchemas.mockReturnValue({}); From f1c156ad1471cbd83d7b04c44ec553ecc49eb526 Mon Sep 17 00:00:00 2001 From: Yaroslav Kuznietsov Date: Mon, 24 Oct 2022 11:25:49 +0300 Subject: [PATCH 11/26] Added config for legend. --- .../heatmap/public/convert_to_lens/configurations/index.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.ts b/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.ts index 3a4a6639bdcd6..9f3f80cbdaca8 100644 --- a/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.ts +++ b/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.ts @@ -32,6 +32,8 @@ export const getConfiguration = ( if (yColumn && !xColumn) { return null; } + const { params, uiState } = vis; + const state = uiState.get('vis'); return { layerId, @@ -39,8 +41,8 @@ export const getConfiguration = ( shape: 'heatmap', legend: { type: 'heatmap_legend', - isVisible: true, - position: 'bottom', + isVisible: state.legendOpen, + position: params.legendPosition, }, gridConfig: { type: 'heatmap_grid', From e2bdbc94eead47e142a5c52cd66b80f523a12184 Mon Sep 17 00:00:00 2001 From: Yaroslav Kuznietsov Date: Mon, 24 Oct 2022 13:18:07 +0300 Subject: [PATCH 12/26] Added support of converting color ranges. --- .../convert_to_lens/configurations/index.ts | 9 ++-- .../convert_to_lens/configurations/palette.ts | 52 +++++++++++++++++++ .../heatmap/public/convert_to_lens/index.ts | 2 +- .../lib/configurations/index.ts | 2 +- .../lib/configurations/palette.ts | 25 ++++++--- .../convert_to_lens/types/configurations.ts | 3 +- .../public/convert_to_lens/index.ts | 1 + .../public/visualizations/heatmap/types.ts | 2 +- 8 files changed, 82 insertions(+), 14 deletions(-) create mode 100644 src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/palette.ts diff --git a/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.ts b/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.ts index 9f3f80cbdaca8..b4076e187c66c 100644 --- a/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.ts +++ b/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.ts @@ -9,8 +9,9 @@ import { Column, HeatmapConfiguration } from '@kbn/visualizations-plugin/common'; import { Vis } from '@kbn/visualizations-plugin/public'; import { HeatmapVisParams } from '../../types'; +import { getPaletteForHeatmap } from './palette'; -export const getConfiguration = ( +export const getConfiguration = async ( layerId: string, vis: Vis, { @@ -25,7 +26,7 @@ export const getConfiguration = ( }; columns: Column[]; } -): HeatmapConfiguration | null => { +): Promise => { const [valueAccessor] = metrics; const xColumn = columns.find(({ isBucketed, isSplit }) => isBucketed && !isSplit); const yColumn = columns.find(({ isBucketed, isSplit }) => isBucketed && isSplit); @@ -33,8 +34,9 @@ export const getConfiguration = ( return null; } const { params, uiState } = vis; - const state = uiState.get('vis'); + const state = uiState.get('vis', {}); + const palette = await getPaletteForHeatmap(params); return { layerId, layerType: 'data', @@ -55,5 +57,6 @@ export const getConfiguration = ( valueAccessor, xAccessor: xColumn?.columnId, yAccessor: yColumn?.columnId, + palette: palette ? { ...palette, accessor: valueAccessor } : undefined, }; }; diff --git a/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/palette.ts b/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/palette.ts new file mode 100644 index 0000000000000..3756fe7034e5a --- /dev/null +++ b/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/palette.ts @@ -0,0 +1,52 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { Range } from '@kbn/expressions-plugin/common'; +import { convertToLensModule } from '@kbn/visualizations-plugin/public'; +import { HeatmapVisParams } from '../../types'; +import { getStopsWithColorsFromColorsNumber } from '../../utils/palette'; + +type HeatmapVisParamsWithRanges = Omit & { + colorsRange: Exclude; +}; + +const isHeatmapVisParamsWithRanges = ( + params: HeatmapVisParams | HeatmapVisParamsWithRanges +): params is HeatmapVisParamsWithRanges => { + return Boolean(params.setColorRange && params.colorsRange && params.colorsRange.length); +}; + +export const getPaletteForHeatmap = async (params: HeatmapVisParams) => { + const { getPalette, getPaletteFromStopsWithColors, getPercentageModeConfig } = + await convertToLensModule; + + if (isHeatmapVisParamsWithRanges(params)) { + const percentageModeConfig = getPercentageModeConfig(params, false); + + return getPalette(params, percentageModeConfig, params.percentageMode); + } + // palette is type of percent, if user wants dynamic calulated ranges + const { color, stop = [] } = getStopsWithColorsFromColorsNumber( + params.colorsNumber, + params.colorSchema, + params.invertColors + ); + const colorsRange: Range[] = [{ from: stop[0], to: stop[stop.length - 1], type: 'range' }]; + const { colorSchema, invertColors, percentageMode } = params; + const percentageModeConfig = getPercentageModeConfig( + { + colorsRange, + colorSchema, + invertColors, + percentageMode, + }, + false + ); + + return getPaletteFromStopsWithColors({ color, stop: stop ?? [] }, percentageModeConfig, true); +}; diff --git a/src/plugins/vis_types/heatmap/public/convert_to_lens/index.ts b/src/plugins/vis_types/heatmap/public/convert_to_lens/index.ts index 715447b30d377..c07abe88e0976 100644 --- a/src/plugins/vis_types/heatmap/public/convert_to_lens/index.ts +++ b/src/plugins/vis_types/heatmap/public/convert_to_lens/index.ts @@ -63,7 +63,7 @@ export const convertToLens: ConvertHeatmapToLensVisualization = async (vis, time const layerId = uuid(); const indexPatternId = dataView.id!; - const configuration = getConfiguration(layerId, vis, layerConfig); + const configuration = await getConfiguration(layerId, vis, layerConfig); if (configuration === null) { return null; } diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/configurations/index.ts b/src/plugins/visualizations/common/convert_to_lens/lib/configurations/index.ts index c4592f50836c5..b4934d0bb0c85 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/configurations/index.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/configurations/index.ts @@ -6,5 +6,5 @@ * Side Public License, v 1. */ -export { getPalette } from './palette'; +export { getPalette, getPaletteFromStopsWithColors } from './palette'; export { getPercentageModeConfig } from './percentage_mode'; diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/configurations/palette.ts b/src/plugins/visualizations/common/convert_to_lens/lib/configurations/palette.ts index a89177c914996..3f81291fab201 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/configurations/palette.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/configurations/palette.ts @@ -74,6 +74,21 @@ const convertToPercentColorStops = ( return { ...colorStops, stop }; }; +export const getPaletteFromStopsWithColors = ( + config: PaletteConfig, + percentageModeConfig: PercentageModeConfig, + isPercentPaletteSupported: boolean = false +) => { + const percentStopsWithColors = percentageModeConfig.isPercentageMode + ? convertToPercentColorStops(config, percentageModeConfig, isPercentPaletteSupported) + : config; + + return buildCustomPalette( + buildPaletteParams(percentStopsWithColors), + isPercentPaletteSupported && percentageModeConfig.isPercentageMode + ); +}; + export const getPalette = ( params: PaletteParams, percentageModeConfig: PercentageModeConfig, @@ -86,12 +101,10 @@ export const getPalette = ( } const stopsWithColors = getStopsWithColorsFromRanges(colorsRange, colorSchema, invertColors); - const percentStopsWithColors = percentageModeConfig.isPercentageMode - ? convertToPercentColorStops(stopsWithColors, percentageModeConfig, isPercentPaletteSupported) - : stopsWithColors; - return buildCustomPalette( - buildPaletteParams(percentStopsWithColors), - isPercentPaletteSupported && percentageModeConfig.isPercentageMode + return getPaletteFromStopsWithColors( + stopsWithColors, + percentageModeConfig, + isPercentPaletteSupported ); }; 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 27854a3d01f04..a41155df3c0b9 100644 --- a/src/plugins/visualizations/common/convert_to_lens/types/configurations.ts +++ b/src/plugins/visualizations/common/convert_to_lens/types/configurations.ts @@ -10,7 +10,6 @@ import { HorizontalAlignment, LayoutDirection, Position, VerticalAlignment } fro import { $Values } from '@kbn/utility-types'; import type { CustomPaletteParams, PaletteOutput } from '@kbn/coloring'; import { KibanaQueryOutput } from '@kbn/data-plugin/common'; -import { CustomPaletteState } from '@kbn/charts-plugin/common'; import { LegendSize } from '../../constants'; import { CategoryDisplayTypes, @@ -306,7 +305,7 @@ export interface HeatmapArguments { lastRangeIsRightOpen?: boolean; showTooltip?: boolean; highlightInHover?: boolean; - palette?: PaletteOutput; + palette?: PaletteOutput; xAccessor?: string | ExpressionValueVisDimension; yAccessor?: string | ExpressionValueVisDimension; valueAccessor?: string | ExpressionValueVisDimension; diff --git a/src/plugins/visualizations/public/convert_to_lens/index.ts b/src/plugins/visualizations/public/convert_to_lens/index.ts index 73509d49157ae..862bf847b0953 100644 --- a/src/plugins/visualizations/public/convert_to_lens/index.ts +++ b/src/plugins/visualizations/public/convert_to_lens/index.ts @@ -10,6 +10,7 @@ export { getColumnsFromVis } from './schemas'; export { getPercentageColumnFormulaColumn, getPalette, + getPaletteFromStopsWithColors, getPercentageModeConfig, createStaticValueColumn, } from '../../common/convert_to_lens/lib'; diff --git a/x-pack/plugins/lens/public/visualizations/heatmap/types.ts b/x-pack/plugins/lens/public/visualizations/heatmap/types.ts index 08913ad25a7d3..6be8d3b6e8d95 100644 --- a/x-pack/plugins/lens/public/visualizations/heatmap/types.ts +++ b/x-pack/plugins/lens/public/visualizations/heatmap/types.ts @@ -10,7 +10,7 @@ import type { HeatmapArguments } from '@kbn/expression-heatmap-plugin/common'; import type { LayerType } from '../../../common'; export type ChartShapes = 'heatmap'; -export type HeatmapLayerState = HeatmapArguments & { +export type HeatmapLayerState = Omit & { layerId: string; layerType: LayerType; valueAccessor?: string; From ebc58479760fd5e840aa464c1f3c709086150981 Mon Sep 17 00:00:00 2001 From: Yaroslav Kuznietsov Date: Mon, 24 Oct 2022 14:03:32 +0300 Subject: [PATCH 13/26] Fixed palette for default ranges. --- .../public/convert_to_lens/configurations/index.ts | 10 +++++----- .../public/convert_to_lens/configurations/palette.ts | 3 ++- src/plugins/vis_types/heatmap/public/utils/palette.ts | 9 ++++++++- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.ts b/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.ts index b4076e187c66c..e54b41cb3a049 100644 --- a/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.ts +++ b/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.ts @@ -48,11 +48,11 @@ export const getConfiguration = async ( }, gridConfig: { type: 'heatmap_grid', - isCellLabelVisible: false, - isYAxisLabelVisible: false, - isYAxisTitleVisible: false, - isXAxisLabelVisible: false, - isXAxisTitleVisible: false, + isCellLabelVisible: params.valueAxes?.[0].labels.show ?? false, + isXAxisLabelVisible: true, + isYAxisLabelVisible: true, + isYAxisTitleVisible: true, + isXAxisTitleVisible: true, }, valueAccessor, xAccessor: xColumn?.columnId, diff --git a/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/palette.ts b/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/palette.ts index 3756fe7034e5a..a643f372f52fe 100644 --- a/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/palette.ts +++ b/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/palette.ts @@ -34,7 +34,8 @@ export const getPaletteForHeatmap = async (params: HeatmapVisParams) => { const { color, stop = [] } = getStopsWithColorsFromColorsNumber( params.colorsNumber, params.colorSchema, - params.invertColors + params.invertColors, + true ); const colorsRange: Range[] = [{ from: stop[0], to: stop[stop.length - 1], type: 'range' }]; const { colorSchema, invertColors, percentageMode } = params; diff --git a/src/plugins/vis_types/heatmap/public/utils/palette.ts b/src/plugins/vis_types/heatmap/public/utils/palette.ts index aa978a2954e90..29109a55fd1e7 100644 --- a/src/plugins/vis_types/heatmap/public/utils/palette.ts +++ b/src/plugins/vis_types/heatmap/public/utils/palette.ts @@ -27,13 +27,20 @@ const getColor = ( export const getStopsWithColorsFromColorsNumber = ( colorsNumber: number | '', colorSchema: ColorSchemas, - invertColors: boolean = false + invertColors: boolean = false, + includeZeroElement: boolean = false ) => { const colors = []; const stops = []; if (!colorsNumber) { return { color: [] }; } + + if (includeZeroElement) { + colors.push(TRANSPARENT); + stops.push(0); + } + const step = 100 / colorsNumber; for (let i = 0; i < colorsNumber; i++) { colors.push(getColor(i, colorsNumber, colorSchema, invertColors)); From 0068ec3490f46535166c42b0501889c8fcf2f8bd Mon Sep 17 00:00:00 2001 From: Yaroslav Kuznietsov Date: Mon, 24 Oct 2022 15:20:57 +0300 Subject: [PATCH 14/26] Refactored. --- .../heatmap/public/convert_to_lens/configurations/palette.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/palette.ts b/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/palette.ts index a643f372f52fe..32187e184d4ef 100644 --- a/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/palette.ts +++ b/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/palette.ts @@ -27,10 +27,9 @@ export const getPaletteForHeatmap = async (params: HeatmapVisParams) => { if (isHeatmapVisParamsWithRanges(params)) { const percentageModeConfig = getPercentageModeConfig(params, false); - return getPalette(params, percentageModeConfig, params.percentageMode); } - // palette is type of percent, if user wants dynamic calulated ranges + const { color, stop = [] } = getStopsWithColorsFromColorsNumber( params.colorsNumber, params.colorSchema, From 0caf3ba9957e955e487d1e7662f185959e05b51c Mon Sep 17 00:00:00 2001 From: Yaroslav Kuznietsov Date: Mon, 24 Oct 2022 15:55:19 +0300 Subject: [PATCH 15/26] Added tests for convertToLens. --- .../public/convert_to_lens/index.test.ts | 163 ++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 src/plugins/vis_types/heatmap/public/convert_to_lens/index.test.ts diff --git a/src/plugins/vis_types/heatmap/public/convert_to_lens/index.test.ts b/src/plugins/vis_types/heatmap/public/convert_to_lens/index.test.ts new file mode 100644 index 0000000000000..de1cfecacca89 --- /dev/null +++ b/src/plugins/vis_types/heatmap/public/convert_to_lens/index.test.ts @@ -0,0 +1,163 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { ColorSchemas } from '@kbn/charts-plugin/common'; +import { Vis } from '@kbn/visualizations-plugin/public'; +import { convertToLens } from '.'; +import { HeatmapVisParams } from '../types'; + +const mockGetColumnsFromVis = jest.fn(); +const mockGetConfiguration = jest.fn().mockReturnValue({}); +const mockGetDataViewByIndexPatternId = jest.fn(); + +jest.mock('../services', () => ({ + getDataViewsStart: jest.fn(() => ({ get: () => ({}), getDefault: () => ({}) })), +})); + +jest.mock('@kbn/visualizations-plugin/public', () => ({ + convertToLensModule: Promise.resolve({ + getColumnsFromVis: jest.fn(() => mockGetColumnsFromVis()), + }), + getDataViewByIndexPatternId: jest.fn(() => mockGetDataViewByIndexPatternId()), +})); + +jest.mock('./configurations', () => ({ + getConfiguration: jest.fn(() => mockGetConfiguration()), +})); + +const params: HeatmapVisParams = { + addTooltip: false, + addLegend: false, + enableHover: true, + legendPosition: 'bottom', + lastRangeIsRightOpen: false, + percentageMode: false, + valueAxes: [], + colorSchema: ColorSchemas.Blues, + invertColors: false, + colorsNumber: 4, + setColorRange: true, +}; + +const vis = { + isHierarchical: () => false, + type: {}, + params, + data: {}, +} as unknown as Vis; + +const timefilter = { + getAbsoluteTime: () => {}, +} as any; + +describe('convertToLens', () => { + beforeEach(() => { + mockGetDataViewByIndexPatternId.mockReturnValue({ id: 'index-pattern' }); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + test('should return null if timefilter is undefined', async () => { + const result = await convertToLens(vis); + expect(result).toBeNull(); + }); + + test('should return null if mockGetDataViewByIndexPatternId returns null', async () => { + mockGetDataViewByIndexPatternId.mockReturnValue(null); + const result = await convertToLens(vis, timefilter); + expect(mockGetDataViewByIndexPatternId).toBeCalledTimes(1); + expect(mockGetColumnsFromVis).toBeCalledTimes(0); + expect(result).toBeNull(); + }); + + test('should return null if getColumnsFromVis returns null', async () => { + mockGetColumnsFromVis.mockReturnValue(null); + const result = await convertToLens(vis, timefilter); + expect(mockGetColumnsFromVis).toBeCalledTimes(1); + expect(result).toBeNull(); + }); + + test('should return null if metrics count is more than 1', async () => { + mockGetColumnsFromVis.mockReturnValue([ + { + metrics: ['1', '2'], + buckets: { all: [] }, + columns: [{ columnId: '2' }, { columnId: '1' }], + }, + ]); + const result = await convertToLens(vis, timefilter); + expect(mockGetColumnsFromVis).toBeCalledTimes(1); + expect(result).toBeNull(); + }); + + test('should return null if getConfiguration returns null', async () => { + mockGetColumnsFromVis.mockReturnValue([ + { + metrics: ['1'], + buckets: { all: ['2'] }, + columns: [{ columnId: '2' }, { columnId: '1' }], + }, + ]); + mockGetConfiguration.mockReturnValue(Promise.resolve(null)); + const result = await convertToLens(vis, timefilter); + expect(mockGetConfiguration).toBeCalledTimes(1); + expect(result).toBeNull(); + }); + + test('should return null if no buckets are specified', async () => { + mockGetColumnsFromVis.mockReturnValue([ + { + metrics: ['1'], + buckets: { all: [] }, + columns: [{ columnId: '1', dataType: 'number' }], + columnsWithoutReferenced: [ + { columnId: '1', meta: { aggId: 'agg-1' } }, + { columnId: '2', meta: { aggId: 'agg-2' } }, + ], + }, + ]); + const result = await convertToLens(vis, timefilter); + expect(mockGetColumnsFromVis).toBeCalledTimes(1); + expect(result).toBeNull(); + }); + + test('should return correct state for valid vis', async () => { + const config = { + layerType: 'data', + }; + + mockGetColumnsFromVis.mockReturnValue([ + { + metrics: ['1'], + buckets: { all: ['2'] }, + columns: [{ columnId: '1', dataType: 'number' }], + columnsWithoutReferenced: [ + { columnId: '1', meta: { aggId: 'agg-1' } }, + { columnId: '2', meta: { aggId: 'agg-2' } }, + ], + }, + ]); + mockGetConfiguration.mockReturnValue(config); + + const result = await convertToLens(vis, timefilter); + expect(mockGetColumnsFromVis).toBeCalledTimes(1); + expect(mockGetConfiguration).toBeCalledTimes(1); + expect(result?.type).toEqual('lnsHeatmap'); + expect(result?.layers.length).toEqual(1); + expect(result?.layers[0]).toEqual( + expect.objectContaining({ + columnOrder: [], + columns: [{ columnId: '1', dataType: 'number' }], + indexPatternId: 'index-pattern', + }) + ); + expect(result?.configuration).toEqual(config); + }); +}); From 31bc49494ae4be5eccdbcc721197e4668c4b3b23 Mon Sep 17 00:00:00 2001 From: Yaroslav Kuznietsov Date: Mon, 24 Oct 2022 16:37:34 +0300 Subject: [PATCH 16/26] Added tests for getConfiguration. --- .../configurations/index.test.ts | 125 ++++++++++++++++++ .../heatmap/public/sample_vis.test.mocks.ts | 11 +- .../vis_types/heatmap/public/to_ast.test.ts | 4 +- 3 files changed, 136 insertions(+), 4 deletions(-) create mode 100644 src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.test.ts diff --git a/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.test.ts b/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.test.ts new file mode 100644 index 0000000000000..6a811d9c291fb --- /dev/null +++ b/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.test.ts @@ -0,0 +1,125 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { AvgColumn, DateHistogramColumn } from '@kbn/visualizations-plugin/common/convert_to_lens'; +import { Vis } from '@kbn/visualizations-plugin/public'; +import { getConfiguration } from '.'; +import { sampleHeatmapVis } from '../../sample_vis.test.mocks'; +import { HeatmapVisParams } from '../../types'; + +describe('getConfiguration', () => { + const layerId = 'layer-id'; + let vis: Vis; + + const metric: AvgColumn = { + sourceField: 'price', + columnId: 'column-1', + operationType: 'average', + isBucketed: false, + isSplit: false, + dataType: 'string', + params: {}, + }; + const xColumn: DateHistogramColumn = { + sourceField: 'price', + columnId: 'column-2', + operationType: 'date_histogram', + isBucketed: true, + isSplit: false, + dataType: 'string', + params: { + interval: '1h', + }, + }; + + const yColumn: DateHistogramColumn = { + sourceField: 'price', + columnId: 'column-3', + operationType: 'date_histogram', + isBucketed: true, + isSplit: true, + dataType: 'string', + params: { + interval: '1h', + }, + }; + + beforeEach(() => { + vis = sampleHeatmapVis as unknown as Vis; + }); + + test('should return null if yColumn is defined, but xColumn is not', async () => { + const result = await getConfiguration(layerId, vis, { + metrics: [metric.columnId], + buckets: { all: [xColumn.columnId, yColumn.columnId], customBuckets: {} }, + columns: [metric, { ...xColumn, isBucketed: false }, yColumn], + }); + + expect(result).toBeNull(); + }); + + test('should return valid configuration', async () => { + const result = await getConfiguration(layerId, vis, { + metrics: [metric.columnId], + buckets: { all: [xColumn.columnId, yColumn.columnId], customBuckets: {} }, + columns: [metric, xColumn, yColumn], + }); + expect(result).toEqual({ + gridConfig: { + isCellLabelVisible: true, + isXAxisLabelVisible: true, + isXAxisTitleVisible: true, + isYAxisLabelVisible: true, + isYAxisTitleVisible: true, + type: 'heatmap_grid', + }, + layerId, + layerType: 'data', + legend: { isVisible: undefined, position: 'right', type: 'heatmap_legend' }, + palette: { + accessor: 'column-1', + name: 'custom', + params: { + colorStops: [ + { color: '#F7FBFF', stop: 0 }, + { color: '#DEEBF7', stop: 12.5 }, + { color: '#C3DBEE', stop: 25 }, + { color: '#9CC8E2', stop: 37.5 }, + { color: '#6DAED5', stop: 50 }, + { color: '#4391C6', stop: 62.5 }, + { color: '#2271B3', stop: 75 }, + { color: '#0D5097', stop: 87.5 }, + ], + continuity: 'none', + maxSteps: 5, + name: 'custom', + progression: 'fixed', + rangeMax: 100, + rangeMin: 0, + rangeType: 'number', + reverse: false, + stops: [ + { color: '#F7FBFF', stop: 12.5 }, + { color: '#DEEBF7', stop: 25 }, + { color: '#C3DBEE', stop: 37.5 }, + { color: '#9CC8E2', stop: 50 }, + { color: '#6DAED5', stop: 62.5 }, + { color: '#4391C6', stop: 75 }, + { color: '#2271B3', stop: 87.5 }, + { color: '#0D5097', stop: 100 }, + ], + }, + type: 'palette', + }, + shape: 'heatmap', + valueAccessor: metric.columnId, + xAccessor: xColumn.columnId, + yAccessor: yColumn.columnId, + }); + }); +}); diff --git a/src/plugins/vis_types/heatmap/public/sample_vis.test.mocks.ts b/src/plugins/vis_types/heatmap/public/sample_vis.test.mocks.ts index 6a33feb853221..89ede55b951ef 100644 --- a/src/plugins/vis_types/heatmap/public/sample_vis.test.mocks.ts +++ b/src/plugins/vis_types/heatmap/public/sample_vis.test.mocks.ts @@ -5,7 +5,9 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -export const sampleAreaVis = { + +const mockUiStateGet = jest.fn().mockReturnValue(() => {}); +export const sampleHeatmapVis = { type: { name: 'heatmap', title: 'Heatmap', @@ -1788,5 +1790,10 @@ export const sampleAreaVis = { }, }, isHierarchical: () => false, - uiState: {}, + uiState: { + vis: { + legendOpen: false, + }, + get: mockUiStateGet, + }, }; diff --git a/src/plugins/vis_types/heatmap/public/to_ast.test.ts b/src/plugins/vis_types/heatmap/public/to_ast.test.ts index d1e312755cf49..07585d9f2332f 100644 --- a/src/plugins/vis_types/heatmap/public/to_ast.test.ts +++ b/src/plugins/vis_types/heatmap/public/to_ast.test.ts @@ -7,7 +7,7 @@ */ import { Vis } from '@kbn/visualizations-plugin/public'; -import { sampleAreaVis } from './sample_vis.test.mocks'; +import { sampleHeatmapVis } from './sample_vis.test.mocks'; import { buildExpression } from '@kbn/expressions-plugin/public'; import { toExpressionAst } from './to_ast'; @@ -33,7 +33,7 @@ describe('heatmap vis toExpressionAst function', () => { } as any; beforeEach(() => { - vis = sampleAreaVis as any; + vis = sampleHeatmapVis as any; }); it('should match basic snapshot', () => { From 3de1107c64727531fe2e089a7401f0bc79ecdfec Mon Sep 17 00:00:00 2001 From: Yaroslav Kuznietsov Date: Wed, 26 Oct 2022 11:25:33 +0300 Subject: [PATCH 17/26] Fixed problem --- .../heatmap/public/convert_to_lens/configurations/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.ts b/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.ts index e54b41cb3a049..8fee8381c5f5e 100644 --- a/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.ts +++ b/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.ts @@ -34,7 +34,7 @@ export const getConfiguration = async ( return null; } const { params, uiState } = vis; - const state = uiState.get('vis', {}); + const state = uiState.get('vis', {}) ?? {}; const palette = await getPaletteForHeatmap(params); return { From 23ce3eb2e71db60bda5e488b7e8910f4e65e4b84 Mon Sep 17 00:00:00 2001 From: Yaroslav Kuznietsov Date: Wed, 26 Oct 2022 12:44:12 +0300 Subject: [PATCH 18/26] Added basic functional tests for heatmap. --- .../lens/open_in_lens/agg_based/heatmap.ts | 79 +++++++++++++++++++ .../apps/lens/open_in_lens/agg_based/index.ts | 1 + 2 files changed, 80 insertions(+) create mode 100644 x-pack/test/functional/apps/lens/open_in_lens/agg_based/heatmap.ts diff --git a/x-pack/test/functional/apps/lens/open_in_lens/agg_based/heatmap.ts b/x-pack/test/functional/apps/lens/open_in_lens/agg_based/heatmap.ts new file mode 100644 index 0000000000000..8e1fff2aaa570 --- /dev/null +++ b/x-pack/test/functional/apps/lens/open_in_lens/agg_based/heatmap.ts @@ -0,0 +1,79 @@ +/* + * 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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; + +export default function ({ getPageObjects, getService }: FtrProviderContext) { + const { visualize, lens, timePicker, visEditor } = getPageObjects([ + 'visualize', + 'lens', + 'timePicker', + 'visEditor', + ]); + + describe('Heatmap', function describeIndexTests() { + const isNewChartsLibraryEnabled = true; + + before(async () => { + await visualize.initTests(isNewChartsLibraryEnabled); + }); + + beforeEach(async () => { + await visualize.navigateToNewAggBasedVisualization(); + await visualize.clickHeatmapChart(); + await visualize.clickNewSearch(); + await timePicker.setDefaultAbsoluteRange(); + }); + + it('should show the "Edit Visualization in Lens" menu item', async () => { + await visEditor.clickBucket('X-axis'); + await visEditor.selectAggregation('Terms'); + await visEditor.selectField('machine.os.raw'); + + expect(await visualize.hasNavigateToLensButton()).to.eql(true); + }); + + it('should convert to Lens', async () => { + await visEditor.clickBucket('X-axis'); + await visEditor.selectAggregation('Terms'); + await visEditor.selectField('machine.os.raw'); + await visEditor.clickGo(); + + await visualize.navigateToLensFromAnotherVisulization(); + await lens.waitForVisualization('heatmapChart'); + const debugState = await lens.getCurrentChartDebugState('heatmapChart'); + + if (!debugState) { + throw new Error('Debug state is not available'); + } + + // assert axes + expect(debugState.axes!.x[0].labels).to.eql(['win 8', 'win xp', 'win 7', 'ios', 'osx']); + expect(debugState.axes!.y[0].labels).to.eql(['']); + expect(debugState.heatmap!.cells.length).to.eql(5); + expect(debugState.legend!.items).to.eql([ + { + color: '#006837', + key: '0 - 25', + name: '0 - 25', + }, + { color: '#86CB66', key: '25 - 50', name: '25 - 50' }, + { + color: '#FEFEBD', + key: '50 - 75', + name: '50 - 75', + }, + { + color: '#F88D52', + key: '75 - 100', + name: '75 - 100', + }, + ]); + }); + }); +} diff --git a/x-pack/test/functional/apps/lens/open_in_lens/agg_based/index.ts b/x-pack/test/functional/apps/lens/open_in_lens/agg_based/index.ts index 87c9d025893a1..52ef856d53ef6 100644 --- a/x-pack/test/functional/apps/lens/open_in_lens/agg_based/index.ts +++ b/x-pack/test/functional/apps/lens/open_in_lens/agg_based/index.ts @@ -15,5 +15,6 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./gauge')); loadTestFile(require.resolve('./goal')); loadTestFile(require.resolve('./table')); + loadTestFile(require.resolve('./heatmap')); }); } From a4df52a6795800024bad4df1e410e71ea2b07478 Mon Sep 17 00:00:00 2001 From: Yaroslav Kuznietsov Date: Wed, 26 Oct 2022 12:53:56 +0300 Subject: [PATCH 19/26] Added functional test for not convertable case. --- .../apps/lens/open_in_lens/agg_based/heatmap.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/x-pack/test/functional/apps/lens/open_in_lens/agg_based/heatmap.ts b/x-pack/test/functional/apps/lens/open_in_lens/agg_based/heatmap.ts index 8e1fff2aaa570..4186eb7e23940 100644 --- a/x-pack/test/functional/apps/lens/open_in_lens/agg_based/heatmap.ts +++ b/x-pack/test/functional/apps/lens/open_in_lens/agg_based/heatmap.ts @@ -75,5 +75,14 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }, ]); }); + + it('should not convert to Lens if Y-axis is defined, but X-axis is not', async () => { + await visEditor.clickBucket('Y-axis'); + await visEditor.selectAggregation('Terms'); + await visEditor.selectField('machine.os.raw'); + await visEditor.clickGo(); + + expect(await visualize.hasNavigateToLensButton()).to.eql(false); + }); }); } From 504546e6e9abb3b37feca56b2e29bda76b5e38d0 Mon Sep 17 00:00:00 2001 From: Yaroslav Kuznietsov Date: Wed, 26 Oct 2022 13:07:23 +0300 Subject: [PATCH 20/26] Added tests for not valid config and fixed one with valid. --- .../functional/apps/lens/open_in_lens/agg_based/heatmap.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/x-pack/test/functional/apps/lens/open_in_lens/agg_based/heatmap.ts b/x-pack/test/functional/apps/lens/open_in_lens/agg_based/heatmap.ts index 4186eb7e23940..86ca494adc755 100644 --- a/x-pack/test/functional/apps/lens/open_in_lens/agg_based/heatmap.ts +++ b/x-pack/test/functional/apps/lens/open_in_lens/agg_based/heatmap.ts @@ -30,10 +30,15 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await timePicker.setDefaultAbsoluteRange(); }); + it('should not show the "Edit Visualization in Lens" menu item if no X-axis was specified', async () => { + expect(await visualize.hasNavigateToLensButton()).to.eql(false); + }); + it('should show the "Edit Visualization in Lens" menu item', async () => { await visEditor.clickBucket('X-axis'); await visEditor.selectAggregation('Terms'); await visEditor.selectField('machine.os.raw'); + await visEditor.clickGo(); expect(await visualize.hasNavigateToLensButton()).to.eql(true); }); From f782daf2255edb4970729a1a2a62fcfc8f617126 Mon Sep 17 00:00:00 2001 From: Yaroslav Kuznietsov Date: Wed, 26 Oct 2022 14:00:37 +0300 Subject: [PATCH 21/26] Added test for custom ranges. --- .../lens/open_in_lens/agg_based/heatmap.ts | 116 +++++++++++++++++- 1 file changed, 115 insertions(+), 1 deletion(-) diff --git a/x-pack/test/functional/apps/lens/open_in_lens/agg_based/heatmap.ts b/x-pack/test/functional/apps/lens/open_in_lens/agg_based/heatmap.ts index 86ca494adc755..ab92f3fb441df 100644 --- a/x-pack/test/functional/apps/lens/open_in_lens/agg_based/heatmap.ts +++ b/x-pack/test/functional/apps/lens/open_in_lens/agg_based/heatmap.ts @@ -9,9 +9,10 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ getPageObjects, getService }: FtrProviderContext) { - const { visualize, lens, timePicker, visEditor } = getPageObjects([ + const { visualize, lens, visChart, timePicker, visEditor } = getPageObjects([ 'visualize', 'lens', + 'visChart', 'timePicker', 'visEditor', ]); @@ -89,5 +90,118 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { expect(await visualize.hasNavigateToLensButton()).to.eql(false); }); + + it('should respect heatmap colors number', async () => { + await visEditor.clickBucket('X-axis'); + await visEditor.selectAggregation('Terms'); + await visEditor.selectField('machine.os.raw'); + await visEditor.clickGo(); + + await visEditor.clickOptionsTab(); + await visEditor.changeHeatmapColorNumbers(6); + await visEditor.clickGo(); + await visChart.waitForVisualizationRenderingStabilized(); + + await visualize.navigateToLensFromAnotherVisulization(); + await lens.waitForVisualization('heatmapChart'); + const debugState = await lens.getCurrentChartDebugState('heatmapChart'); + + if (!debugState) { + throw new Error('Debug state is not available'); + } + + expect(debugState.legend!.items).to.eql([ + { + color: '#006837', + key: '0 - 16.67', + name: '0 - 16.67', + }, + { + color: '#4CB15D', + key: '16.67 - 33.33', + name: '16.67 - 33.33', + }, + { + color: '#B7E075', + key: '33.33 - 50', + name: '33.33 - 50', + }, + { + color: '#FEFEBD', + key: '50 - 66.67', + name: '50 - 66.67', + }, + { + color: '#FDBF6F', + key: '66.67 - 83.33', + name: '66.67 - 83.33', + }, + { + color: '#EA5839', + key: '83.33 - 100', + name: '83.33 - 100', + }, + ]); + }); + + it('should show respect heatmap custom color ranges', async () => { + await visEditor.clickBucket('X-axis'); + await visEditor.selectAggregation('Terms'); + await visEditor.selectField('machine.os.raw'); + await visEditor.clickGo(); + + await visEditor.clickOptionsTab(); + await visEditor.clickOptionsTab(); + await visEditor.clickEnableCustomRanges(); + await visEditor.clickAddRange(); + await visEditor.clickAddRange(); + await visEditor.clickAddRange(); + await visEditor.clickAddRange(); + await visEditor.clickAddRange(); + + await visEditor.clickGo(); + await visChart.waitForVisualizationRenderingStabilized(); + + await visualize.navigateToLensFromAnotherVisulization(); + await lens.waitForVisualization('heatmapChart'); + const debugState = await lens.getCurrentChartDebugState('heatmapChart'); + + if (!debugState) { + throw new Error('Debug state is not available'); + } + + expect(debugState.legend!.items).to.eql([ + { + color: '#006837', + key: '0 - 100', + name: '0 - 100', + }, + { + color: '#65BC62', + key: '100 - 200', + name: '100 - 200', + }, + { + color: '#D8EF8C', + key: '200 - 300', + name: '200 - 300', + }, + { + color: '#FEDF8B', + key: '300 - 400', + name: '300 - 400', + }, + { + color: '#F36D43', + key: '400 - 500', + name: '400 - 500', + }, + { + color: '#A50026', + key: '500 - 600', + name: '500 - 600', + }, + ]); + }); }); } From e975faa5f90fafd4c16b76477f28bc6332500043 Mon Sep 17 00:00:00 2001 From: Yaroslav Kuznietsov Date: Thu, 27 Oct 2022 13:22:29 +0300 Subject: [PATCH 22/26] Added empty filters if x-axis is not defined. - Added empty filters if y-axis is defined, but x-axis is not and if no x/y-axis was defined. - Added/fixed tests. --- .../configurations/index.test.ts | 13 +------ .../convert_to_lens/configurations/index.ts | 22 ++++------- .../public/convert_to_lens/index.test.ts | 37 ++++++++++--------- .../heatmap/public/convert_to_lens/index.ts | 23 +++++++++--- .../public/convert_to_lens/index.ts | 1 + .../lens/open_in_lens/agg_based/heatmap.ts | 21 +++++++++-- 6 files changed, 64 insertions(+), 53 deletions(-) diff --git a/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.test.ts b/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.test.ts index 6a811d9c291fb..3f60b6fde0a94 100644 --- a/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.test.ts +++ b/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.test.ts @@ -53,21 +53,10 @@ describe('getConfiguration', () => { vis = sampleHeatmapVis as unknown as Vis; }); - test('should return null if yColumn is defined, but xColumn is not', async () => { - const result = await getConfiguration(layerId, vis, { - metrics: [metric.columnId], - buckets: { all: [xColumn.columnId, yColumn.columnId], customBuckets: {} }, - columns: [metric, { ...xColumn, isBucketed: false }, yColumn], - }); - - expect(result).toBeNull(); - }); - test('should return valid configuration', async () => { const result = await getConfiguration(layerId, vis, { metrics: [metric.columnId], - buckets: { all: [xColumn.columnId, yColumn.columnId], customBuckets: {} }, - columns: [metric, xColumn, yColumn], + buckets: [xColumn.columnId, yColumn.columnId], }); expect(result).toEqual({ gridConfig: { diff --git a/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.ts b/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.ts index 8fee8381c5f5e..2e7a3f161514a 100644 --- a/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.ts +++ b/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { Column, HeatmapConfiguration } from '@kbn/visualizations-plugin/common'; +import { HeatmapConfiguration } from '@kbn/visualizations-plugin/common'; import { Vis } from '@kbn/visualizations-plugin/public'; import { HeatmapVisParams } from '../../types'; import { getPaletteForHeatmap } from './palette'; @@ -17,22 +17,14 @@ export const getConfiguration = async ( { metrics, buckets, - columns, }: { metrics: string[]; - buckets: { - all: string[]; - customBuckets: Record; - }; - columns: Column[]; + buckets: string[]; } -): Promise => { +): Promise => { const [valueAccessor] = metrics; - const xColumn = columns.find(({ isBucketed, isSplit }) => isBucketed && !isSplit); - const yColumn = columns.find(({ isBucketed, isSplit }) => isBucketed && isSplit); - if (yColumn && !xColumn) { - return null; - } + const [xAccessor, yAccessor] = buckets; + const { params, uiState } = vis; const state = uiState.get('vis', {}) ?? {}; @@ -55,8 +47,8 @@ export const getConfiguration = async ( isXAxisTitleVisible: true, }, valueAccessor, - xAccessor: xColumn?.columnId, - yAccessor: yColumn?.columnId, + xAccessor, + yAccessor, palette: palette ? { ...palette, accessor: valueAccessor } : undefined, }; }; diff --git a/src/plugins/vis_types/heatmap/public/convert_to_lens/index.test.ts b/src/plugins/vis_types/heatmap/public/convert_to_lens/index.test.ts index de1cfecacca89..ef86b3829c248 100644 --- a/src/plugins/vis_types/heatmap/public/convert_to_lens/index.test.ts +++ b/src/plugins/vis_types/heatmap/public/convert_to_lens/index.test.ts @@ -14,6 +14,7 @@ import { HeatmapVisParams } from '../types'; const mockGetColumnsFromVis = jest.fn(); const mockGetConfiguration = jest.fn().mockReturnValue({}); const mockGetDataViewByIndexPatternId = jest.fn(); +const mockConvertToFiltersColumn = jest.fn(); jest.mock('../services', () => ({ getDataViewsStart: jest.fn(() => ({ get: () => ({}), getDefault: () => ({}) })), @@ -22,6 +23,7 @@ jest.mock('../services', () => ({ jest.mock('@kbn/visualizations-plugin/public', () => ({ convertToLensModule: Promise.resolve({ getColumnsFromVis: jest.fn(() => mockGetColumnsFromVis()), + convertToFiltersColumn: jest.fn(() => mockConvertToFiltersColumn()), }), getDataViewByIndexPatternId: jest.fn(() => mockGetDataViewByIndexPatternId()), })); @@ -58,6 +60,7 @@ const timefilter = { describe('convertToLens', () => { beforeEach(() => { mockGetDataViewByIndexPatternId.mockReturnValue({ id: 'index-pattern' }); + mockConvertToFiltersColumn.mockReturnValue({ columnId: 'column-id-1' }); }); afterEach(() => { @@ -97,21 +100,7 @@ describe('convertToLens', () => { expect(result).toBeNull(); }); - test('should return null if getConfiguration returns null', async () => { - mockGetColumnsFromVis.mockReturnValue([ - { - metrics: ['1'], - buckets: { all: ['2'] }, - columns: [{ columnId: '2' }, { columnId: '1' }], - }, - ]); - mockGetConfiguration.mockReturnValue(Promise.resolve(null)); - const result = await convertToLens(vis, timefilter); - expect(mockGetConfiguration).toBeCalledTimes(1); - expect(result).toBeNull(); - }); - - test('should return null if no buckets are specified', async () => { + test('should return empty filters for x-axis if no buckets are specified', async () => { mockGetColumnsFromVis.mockReturnValue([ { metrics: ['1'], @@ -120,12 +109,26 @@ describe('convertToLens', () => { columnsWithoutReferenced: [ { columnId: '1', meta: { aggId: 'agg-1' } }, { columnId: '2', meta: { aggId: 'agg-2' } }, + { columnId: 'column-id-1' }, ], }, ]); const result = await convertToLens(vis, timefilter); expect(mockGetColumnsFromVis).toBeCalledTimes(1); - expect(result).toBeNull(); + expect(result).toEqual( + expect.objectContaining({ + configuration: {}, + indexPatternIds: ['index-pattern'], + layers: [ + expect.objectContaining({ + columnOrder: [], + columns: [{ columnId: '1', dataType: 'number' }, { columnId: 'column-id-1' }], + indexPatternId: 'index-pattern', + }), + ], + type: 'lnsHeatmap', + }) + ); }); test('should return correct state for valid vis', async () => { @@ -154,7 +157,7 @@ describe('convertToLens', () => { expect(result?.layers[0]).toEqual( expect.objectContaining({ columnOrder: [], - columns: [{ columnId: '1', dataType: 'number' }], + columns: [{ columnId: '1', dataType: 'number' }, { columnId: 'column-id-1' }], indexPatternId: 'index-pattern', }) ); diff --git a/src/plugins/vis_types/heatmap/public/convert_to_lens/index.ts b/src/plugins/vis_types/heatmap/public/convert_to_lens/index.ts index c07abe88e0976..546d497e80560 100644 --- a/src/plugins/vis_types/heatmap/public/convert_to_lens/index.ts +++ b/src/plugins/vis_types/heatmap/public/convert_to_lens/index.ts @@ -43,7 +43,7 @@ export const convertToLens: ConvertHeatmapToLensVisualization = async (vis, time return null; } - const { getColumnsFromVis } = await convertToLensModule; + const { getColumnsFromVis, convertToFiltersColumn } = await convertToLensModule; const layers = getColumnsFromVis(vis, timefilter, dataView, { buckets: ['segment'], splits: ['group'], @@ -56,6 +56,17 @@ export const convertToLens: ConvertHeatmapToLensVisualization = async (vis, time const [layerConfig] = layers; + const xColumn = layerConfig.columns.find(({ isBucketed, isSplit }) => isBucketed && !isSplit); + const xAxisColumn = + xColumn ?? + convertToFiltersColumn(uuid(), { filters: [{ input: { language: 'lucene', query: '*' } }] })!; + + if (xColumn?.columnId !== xAxisColumn?.columnId) { + layerConfig.buckets.all.push(xAxisColumn.columnId); + layerConfig.columns.push(xAxisColumn); + } + const yColumn = layerConfig.columns.find(({ isBucketed, isSplit }) => isBucketed && isSplit); + if (!layerConfig.buckets.all.length || layerConfig.metrics.length > 1) { return null; } @@ -63,10 +74,12 @@ export const convertToLens: ConvertHeatmapToLensVisualization = async (vis, time const layerId = uuid(); const indexPatternId = dataView.id!; - const configuration = await getConfiguration(layerId, vis, layerConfig); - if (configuration === null) { - return null; - } + const configuration = await getConfiguration(layerId, vis, { + metrics: layerConfig.metrics, + buckets: [xAxisColumn.columnId, yColumn?.columnId].filter((c): c is string => + Boolean(c) + ), + }); return { type: 'lnsHeatmap', diff --git a/src/plugins/visualizations/public/convert_to_lens/index.ts b/src/plugins/visualizations/public/convert_to_lens/index.ts index 862bf847b0953..46fca64199ae1 100644 --- a/src/plugins/visualizations/public/convert_to_lens/index.ts +++ b/src/plugins/visualizations/public/convert_to_lens/index.ts @@ -8,6 +8,7 @@ export { getColumnsFromVis } from './schemas'; export { + convertToFiltersColumn, getPercentageColumnFormulaColumn, getPalette, getPaletteFromStopsWithColors, diff --git a/x-pack/test/functional/apps/lens/open_in_lens/agg_based/heatmap.ts b/x-pack/test/functional/apps/lens/open_in_lens/agg_based/heatmap.ts index ab92f3fb441df..60a958e7796b6 100644 --- a/x-pack/test/functional/apps/lens/open_in_lens/agg_based/heatmap.ts +++ b/x-pack/test/functional/apps/lens/open_in_lens/agg_based/heatmap.ts @@ -16,6 +16,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { 'timePicker', 'visEditor', ]); + const log = getService('log'); describe('Heatmap', function describeIndexTests() { const isNewChartsLibraryEnabled = true; @@ -31,8 +32,10 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await timePicker.setDefaultAbsoluteRange(); }); - it('should not show the "Edit Visualization in Lens" menu item if no X-axis was specified', async () => { - expect(await visualize.hasNavigateToLensButton()).to.eql(false); + it('should show the "Edit Visualization in Lens" menu item if no X-axis was specified', async () => { + await visChart.waitForVisualizationRenderingStabilized(); + + expect(await visualize.hasNavigateToLensButton()).to.eql(true); }); it('should show the "Edit Visualization in Lens" menu item', async () => { @@ -82,13 +85,23 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { ]); }); - it('should not convert to Lens if Y-axis is defined, but X-axis is not', async () => { + it('should convert to Lens if Y-axis is defined, but X-axis is not', async () => { await visEditor.clickBucket('Y-axis'); await visEditor.selectAggregation('Terms'); await visEditor.selectField('machine.os.raw'); await visEditor.clickGo(); - expect(await visualize.hasNavigateToLensButton()).to.eql(false); + await visualize.navigateToLensFromAnotherVisulization(); + await lens.waitForVisualization('heatmapChart'); + const debugState = await lens.getCurrentChartDebugState('heatmapChart'); + + if (!debugState) { + throw new Error('Debug state is not available'); + } + + expect(debugState.axes!.x[0].labels).to.eql(['*']); + expect(debugState.axes!.y[0].labels).to.eql(['win 8', 'win xp', 'win 7', 'ios', 'osx']); + expect(debugState.heatmap!.cells.length).to.eql(5); }); it('should respect heatmap colors number', async () => { From 70f0fd0f476068a2c66b2838303129babd69f16b Mon Sep 17 00:00:00 2001 From: Yaroslav Kuznietsov Date: Thu, 27 Oct 2022 13:45:00 +0300 Subject: [PATCH 23/26] Removed unused service. --- .../test/functional/apps/lens/open_in_lens/agg_based/heatmap.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/test/functional/apps/lens/open_in_lens/agg_based/heatmap.ts b/x-pack/test/functional/apps/lens/open_in_lens/agg_based/heatmap.ts index 60a958e7796b6..8556ae601daf9 100644 --- a/x-pack/test/functional/apps/lens/open_in_lens/agg_based/heatmap.ts +++ b/x-pack/test/functional/apps/lens/open_in_lens/agg_based/heatmap.ts @@ -16,7 +16,6 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { 'timePicker', 'visEditor', ]); - const log = getService('log'); describe('Heatmap', function describeIndexTests() { const isNewChartsLibraryEnabled = true; From 87042ff90cb30b599d8b37d530f477dcb0b92630 Mon Sep 17 00:00:00 2001 From: Yaroslav Kuznietsov Date: Thu, 27 Oct 2022 15:14:05 +0300 Subject: [PATCH 24/26] Histogram problems fixed. --- .../common/convert_to_lens/lib/convert/range.ts | 13 ++++++------- .../common/convert_to_lens/types/params.ts | 2 +- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/convert/range.ts b/src/plugins/visualizations/common/convert_to_lens/lib/convert/range.ts index 6a9f96fd5ad1e..98200c321935c 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/convert/range.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/convert/range.ts @@ -27,18 +27,17 @@ export const convertToRangeParams = ( return { type: RANGE_MODES.Histogram, maxBars: aggParams.maxBars ?? 'auto', - ranges: [], + includeEmptyRows: aggParams.min_doc_count, }; } else { return { type: RANGE_MODES.Range, maxBars: 'auto', - ranges: - aggParams.ranges?.map((range) => ({ - label: range.label, - from: range.from ?? null, - to: range.to ?? null, - })) ?? [], + ranges: aggParams.ranges?.map((range) => ({ + label: range.label, + from: range.from ?? null, + to: range.to ?? null, + })), }; } }; diff --git a/src/plugins/visualizations/common/convert_to_lens/types/params.ts b/src/plugins/visualizations/common/convert_to_lens/types/params.ts index d66822921fb19..4623506496382 100644 --- a/src/plugins/visualizations/common/convert_to_lens/types/params.ts +++ b/src/plugins/visualizations/common/convert_to_lens/types/params.ts @@ -55,7 +55,7 @@ interface Range { export interface RangeParams extends FormatParams { type: RangeMode; maxBars: 'auto' | number; - ranges: Range[]; + ranges?: Range[]; includeEmptyRows?: boolean; parentFormat?: { id: string; From 7eb90010777a1fe98c8f45765a780734d3763904 Mon Sep 17 00:00:00 2001 From: Yaroslav Kuznietsov Date: Thu, 27 Oct 2022 15:27:03 +0300 Subject: [PATCH 25/26] Fixed include/exclude regexp. --- .../convert_to_lens/lib/convert/terms.ts | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/convert/terms.ts b/src/plugins/visualizations/common/convert_to_lens/lib/convert/terms.ts index 44cc46c101d54..53004fdafec94 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/convert/terms.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/convert/terms.ts @@ -70,6 +70,19 @@ const getOrderByWithAgg = ({ }; }; +const filterOutEmptyValues = (values: string | Array): number[] | string[] => { + if (typeof values === 'string') { + return Boolean(values) ? [] : [values]; + } + + return values.filter((v): v is string | number => { + if (typeof v === 'string') { + return Boolean(v); + } + return true; + }) as string[] | number[]; +}; + export const convertToTermsParams = ({ agg, dataView, @@ -88,17 +101,9 @@ export const convertToTermsParams = ({ return { size: agg.aggParams.size ?? 10, - include: agg.aggParams.include - ? Array.isArray(agg.aggParams.include) - ? agg.aggParams.include - : [agg.aggParams.include] - : [], + include: agg.aggParams.include ? filterOutEmptyValues(agg.aggParams.include) : [], includeIsRegex: agg.aggParams.includeIsRegex, - exclude: agg.aggParams.exclude - ? Array.isArray(agg.aggParams.exclude) - ? agg.aggParams.exclude - : [agg.aggParams.exclude] - : [], + exclude: agg.aggParams.exclude ? filterOutEmptyValues(agg.aggParams.exclude) : [], excludeIsRegex: agg.aggParams.excludeIsRegex, otherBucket: agg.aggParams.otherBucket, orderDirection: agg.aggParams.order?.value ?? 'desc', From a53dd456627710638e8fca352252e98f2b834da6 Mon Sep 17 00:00:00 2001 From: Yaroslav Kuznietsov Date: Thu, 27 Oct 2022 16:40:45 +0300 Subject: [PATCH 26/26] Fixed terms. --- .../common/convert_to_lens/lib/convert/range.test.ts | 1 - .../common/convert_to_lens/lib/convert/terms.test.ts | 6 ++++++ .../common/convert_to_lens/lib/convert/terms.ts | 12 +++++++----- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/convert/range.test.ts b/src/plugins/visualizations/common/convert_to_lens/lib/convert/range.test.ts index 8f535c28c8264..5a754fd1c9466 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/convert/range.test.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/convert/range.test.ts @@ -60,7 +60,6 @@ describe('convertToRangeColumn', () => { params: { type: RANGE_MODES.Histogram, maxBars: 'auto', - ranges: [], }, }, ], diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/convert/terms.test.ts b/src/plugins/visualizations/common/convert_to_lens/lib/convert/terms.test.ts index c8bb23b35742c..516ad6b196095 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/convert/terms.test.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/convert/terms.test.ts @@ -110,6 +110,8 @@ describe('convertToDateHistogramColumn', () => { size: 5, include: [], exclude: [], + includeIsRegex: false, + excludeIsRegex: false, parentFormat: { id: 'terms' }, orderBy: { type: 'alphabetical' }, orderDirection: 'asc', @@ -139,6 +141,8 @@ describe('convertToDateHistogramColumn', () => { size: 5, include: [], exclude: [], + includeIsRegex: false, + excludeIsRegex: false, parentFormat: { id: 'terms' }, orderBy: { type: 'column', columnId: metricColumns[0].columnId }, orderAgg: metricColumns[0], @@ -228,6 +232,8 @@ describe('convertToDateHistogramColumn', () => { size: 5, include: [], exclude: [], + includeIsRegex: false, + excludeIsRegex: false, parentFormat: { id: 'terms' }, orderBy: { type: 'custom' }, orderAgg: metricColumns[0], diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/convert/terms.ts b/src/plugins/visualizations/common/convert_to_lens/lib/convert/terms.ts index 53004fdafec94..a54a3857e20f6 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/convert/terms.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/convert/terms.ts @@ -72,7 +72,7 @@ const getOrderByWithAgg = ({ const filterOutEmptyValues = (values: string | Array): number[] | string[] => { if (typeof values === 'string') { - return Boolean(values) ? [] : [values]; + return Boolean(values) ? [values] : []; } return values.filter((v): v is string | number => { @@ -99,12 +99,14 @@ export const convertToTermsParams = ({ return null; } + const exclude = agg.aggParams.exclude ? filterOutEmptyValues(agg.aggParams.exclude) : []; + const include = agg.aggParams.include ? filterOutEmptyValues(agg.aggParams.include) : []; return { size: agg.aggParams.size ?? 10, - include: agg.aggParams.include ? filterOutEmptyValues(agg.aggParams.include) : [], - includeIsRegex: agg.aggParams.includeIsRegex, - exclude: agg.aggParams.exclude ? filterOutEmptyValues(agg.aggParams.exclude) : [], - excludeIsRegex: agg.aggParams.excludeIsRegex, + include, + exclude, + includeIsRegex: Boolean(include.length && agg.aggParams.includeIsRegex), + excludeIsRegex: Boolean(exclude.length && agg.aggParams.excludeIsRegex), otherBucket: agg.aggParams.otherBucket, orderDirection: agg.aggParams.order?.value ?? 'desc', parentFormat: { id: 'terms' },