From 3f620428b3a81b2eaaef2a0374dd9e0e4da815a9 Mon Sep 17 00:00:00 2001 From: Yaroslav Kuznietsov Date: Wed, 2 Nov 2022 12:39:30 +0200 Subject: [PATCH] [Lens] Heatmap expression types improvement. (#144174) * Added expression function builder for heatmap * Fixed heatmap preview. * Fixed tests. Co-authored-by: Stratoula Kalafateli --- .../expression_functions/heatmap_legend.ts | 10 +- .../expression_heatmap/common/index.ts | 3 + .../common/types/expression_functions.ts | 14 ++ .../heatmap/visualization.test.ts | 11 +- .../visualizations/heatmap/visualization.tsx | 229 +++++++----------- 5 files changed, 114 insertions(+), 153 deletions(-) diff --git a/src/plugins/chart_expressions/expression_heatmap/common/expression_functions/heatmap_legend.ts b/src/plugins/chart_expressions/expression_heatmap/common/expression_functions/heatmap_legend.ts index 79a356ddad934e..9aa489a031eeb3 100644 --- a/src/plugins/chart_expressions/expression_heatmap/common/expression_functions/heatmap_legend.ts +++ b/src/plugins/chart_expressions/expression_heatmap/common/expression_functions/heatmap_legend.ts @@ -7,17 +7,11 @@ */ import { Position } from '@elastic/charts'; import { i18n } from '@kbn/i18n'; -import type { ExpressionFunctionDefinition } from '@kbn/expressions-plugin/common'; import { DEFAULT_LEGEND_SIZE, LegendSize } from '@kbn/visualizations-plugin/common/constants'; import { EXPRESSION_HEATMAP_LEGEND_NAME } from '../constants'; -import { HeatmapLegendConfig, HeatmapLegendConfigResult } from '../types'; +import { HeatmapLegendExpressionFunctionDefinition } from '../types'; -export const heatmapLegendConfig: ExpressionFunctionDefinition< - typeof EXPRESSION_HEATMAP_LEGEND_NAME, - null, - HeatmapLegendConfig, - HeatmapLegendConfigResult -> = { +export const heatmapLegendConfig: HeatmapLegendExpressionFunctionDefinition = { name: EXPRESSION_HEATMAP_LEGEND_NAME, aliases: [], type: EXPRESSION_HEATMAP_LEGEND_NAME, diff --git a/src/plugins/chart_expressions/expression_heatmap/common/index.ts b/src/plugins/chart_expressions/expression_heatmap/common/index.ts index 484dee11c300b7..1fa096cc6fe8a4 100755 --- a/src/plugins/chart_expressions/expression_heatmap/common/index.ts +++ b/src/plugins/chart_expressions/expression_heatmap/common/index.ts @@ -18,6 +18,9 @@ export type { HeatmapLegendConfigResult, HeatmapGridConfigResult, HeatmapArguments, + HeatmapExpressionFunctionDefinition, + HeatmapLegendExpressionFunctionDefinition, + HeatmapGridExpressionFunctionDefinition, } from './types'; export { heatmapFunction, heatmapLegendConfig, heatmapGridConfig } from './expression_functions'; 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 1bf5fe3bbb36bf..2537d4c7f5105c 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 @@ -109,3 +109,17 @@ export type HeatmapExpressionFunctionDefinition = ExpressionFunctionDefinition< HeatmapArguments, ExpressionValueRender >; + +export type HeatmapLegendExpressionFunctionDefinition = ExpressionFunctionDefinition< + typeof EXPRESSION_HEATMAP_LEGEND_NAME, + null, + HeatmapLegendConfig, + HeatmapLegendConfigResult +>; + +export type HeatmapGridExpressionFunctionDefinition = ExpressionFunctionDefinition< + typeof EXPRESSION_HEATMAP_GRID_NAME, + null, + HeatmapGridConfig, + HeatmapGridConfigResult +>; diff --git a/x-pack/plugins/lens/public/visualizations/heatmap/visualization.test.ts b/x-pack/plugins/lens/public/visualizations/heatmap/visualization.test.ts index 8f958b8fa75ce3..bbebf37ff4b5cb 100644 --- a/x-pack/plugins/lens/public/visualizations/heatmap/visualization.test.ts +++ b/x-pack/plugins/lens/public/visualizations/heatmap/visualization.test.ts @@ -427,7 +427,6 @@ describe('heatmap', () => { arguments: { isVisible: [true], position: [Position.Right], - legendSize: [], }, }, ], @@ -441,11 +440,6 @@ describe('heatmap', () => { type: 'function', function: HEATMAP_GRID_FUNCTION, arguments: { - // grid - strokeWidth: [], - strokeColor: [], - xTitle: [], - yTitle: [], // cells isCellLabelVisible: [false], // Y-axis @@ -505,6 +499,7 @@ describe('heatmap', () => { ...exampleState(), layerId: 'first', xAccessor: 'x-accessor', + valueAccessor: 'value-accessor', }; expect( @@ -521,7 +516,7 @@ describe('heatmap', () => { arguments: { xAccessor: ['x-accessor'], yAccessor: [''], - valueAccessor: [''], + valueAccessor: ['value-accessor'], palette: [ { type: 'expression', @@ -545,7 +540,7 @@ describe('heatmap', () => { function: LEGEND_FUNCTION, arguments: { isVisible: [false], - position: [], + position: ['right'], }, }, ], diff --git a/x-pack/plugins/lens/public/visualizations/heatmap/visualization.tsx b/x-pack/plugins/lens/public/visualizations/heatmap/visualization.tsx index fc8ef976548b47..dfa37ba75f38ca 100644 --- a/x-pack/plugins/lens/public/visualizations/heatmap/visualization.tsx +++ b/x-pack/plugins/lens/public/visualizations/heatmap/visualization.tsx @@ -18,6 +18,12 @@ 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 { + HeatmapExpressionFunctionDefinition, + HeatmapGridExpressionFunctionDefinition, + HeatmapLegendExpressionFunctionDefinition, +} from '@kbn/expression-heatmap-plugin/common'; +import { buildExpression, buildExpressionFunction } from '@kbn/expressions-plugin/common'; import type { OperationMetadata, Suggestion, Visualization } from '../../types'; import type { HeatmapVisualizationState } from './types'; import { getSuggestions } from './suggestions'; @@ -25,7 +31,6 @@ import { CHART_NAMES, CHART_SHAPES, DEFAULT_PALETTE_NAME, - FUNCTION_NAME, GROUP_ID, HEATMAP_GRID_FUNCTION, LEGEND_FUNCTION, @@ -321,82 +326,53 @@ export const getHeatmapVisualization = ({ return null; } + const legendFn = buildExpressionFunction( + 'heatmap_legend', + { + isVisible: state.legend.isVisible, + position: state.legend.position, + legendSize: state.legend.legendSize, + } + ); + + const gridConfigFn = buildExpressionFunction( + 'heatmap_grid', + { + // grid + strokeWidth: state.gridConfig.strokeWidth, + strokeColor: state.gridConfig.strokeColor, + // cells + isCellLabelVisible: state.gridConfig.isCellLabelVisible, + // Y-axis + isYAxisLabelVisible: state.gridConfig.isYAxisLabelVisible, + isYAxisTitleVisible: state.gridConfig.isYAxisTitleVisible ?? false, + yTitle: state.gridConfig.yTitle, + // X-axis + isXAxisLabelVisible: state.gridConfig.isXAxisLabelVisible, + isXAxisTitleVisible: state.gridConfig.isXAxisTitleVisible ?? false, + xTitle: state.gridConfig.xTitle, + } + ); + + const heatmapFn = buildExpressionFunction('heatmap', { + xAccessor: state.xAccessor ?? '', + yAccessor: state.yAccessor ?? '', + valueAccessor: state.valueAccessor ?? '', + lastRangeIsRightOpen: state.palette?.params?.continuity + ? ['above', 'all'].includes(state.palette.params.continuity) + : true, + palette: state.palette?.params + ? paletteService + .get(CUSTOM_PALETTE) + .toExpression(computePaletteParams(state.palette?.params)) + : paletteService.get(DEFAULT_PALETTE_NAME).toExpression(), + legend: buildExpression([legendFn]), + gridConfig: buildExpression([gridConfigFn]), + }); + return { type: 'expression', - chain: [ - ...(datasourceExpression?.chain ?? []), - { - type: 'function', - function: FUNCTION_NAME, - arguments: { - xAccessor: [state.xAccessor ?? ''], - yAccessor: [state.yAccessor ?? ''], - valueAccessor: [state.valueAccessor ?? ''], - lastRangeIsRightOpen: [ - state.palette?.params?.continuity - ? ['above', 'all'].includes(state.palette.params.continuity) - : true, - ], - palette: state.palette?.params - ? [ - paletteService - .get(CUSTOM_PALETTE) - .toExpression( - computePaletteParams((state.palette?.params || {}) as CustomPaletteParams) - ), - ] - : [paletteService.get(DEFAULT_PALETTE_NAME).toExpression()], - legend: [ - { - type: 'expression', - chain: [ - { - type: 'function', - function: LEGEND_FUNCTION, - arguments: { - isVisible: [state.legend.isVisible], - position: [state.legend.position], - legendSize: state.legend.legendSize ? [state.legend.legendSize] : [], - }, - }, - ], - }, - ], - gridConfig: [ - { - type: 'expression', - chain: [ - { - type: 'function', - function: HEATMAP_GRID_FUNCTION, - arguments: { - // grid - strokeWidth: state.gridConfig.strokeWidth - ? [state.gridConfig.strokeWidth] - : [], - strokeColor: state.gridConfig.strokeColor - ? [state.gridConfig.strokeColor] - : [], - // cells - isCellLabelVisible: [state.gridConfig.isCellLabelVisible], - // Y-axis - isYAxisLabelVisible: [state.gridConfig.isYAxisLabelVisible], - isYAxisTitleVisible: [state.gridConfig.isYAxisTitleVisible ?? false], - yTitle: state.gridConfig.yTitle ? [state.gridConfig.yTitle] : [], - // X-axis - isXAxisLabelVisible: state.gridConfig.isXAxisLabelVisible - ? [state.gridConfig.isXAxisLabelVisible] - : [], - isXAxisTitleVisible: [state.gridConfig.isXAxisTitleVisible ?? false], - xTitle: state.gridConfig.xTitle ? [state.gridConfig.xTitle] : [], - }, - }, - ], - }, - ], - }, - }, - ], + chain: [...(datasourceExpression?.chain ?? []), heatmapFn.toAst()], }; }, @@ -407,73 +383,52 @@ export const getHeatmapVisualization = ({ const originalOrder = datasource?.getTableSpec().map(({ columnId }) => columnId); // When we add a column it could be empty, and therefore have no order - if (!originalOrder) { + if (!originalOrder || !state.valueAccessor) { return null; } + const legendFn = buildExpressionFunction( + 'heatmap_legend', + { + isVisible: false, + position: 'right', + } + ); + + const gridConfigFn = buildExpressionFunction( + 'heatmap_grid', + { + // grid + strokeWidth: 1, + // cells + isCellLabelVisible: false, + // Y-axis + isYAxisLabelVisible: false, + isYAxisTitleVisible: state.gridConfig.isYAxisTitleVisible, + yTitle: state.gridConfig.yTitle ?? '', + // X-axis + isXAxisLabelVisible: false, + isXAxisTitleVisible: state.gridConfig.isXAxisTitleVisible, + xTitle: state.gridConfig.xTitle ?? '', + } + ); + + const heatmapFn = buildExpressionFunction('heatmap', { + xAccessor: state.xAccessor ?? '', + yAccessor: state.yAccessor ?? '', + valueAccessor: state.valueAccessor ?? '', + legend: buildExpression([legendFn]), + gridConfig: buildExpression([gridConfigFn]), + palette: state.palette?.params + ? paletteService + .get(CUSTOM_PALETTE) + .toExpression(computePaletteParams(state.palette?.params)) + : paletteService.get(DEFAULT_PALETTE_NAME).toExpression(), + }); + return { type: 'expression', - chain: [ - ...(datasourceExpression?.chain ?? []), - { - type: 'function', - function: FUNCTION_NAME, - arguments: { - xAccessor: [state.xAccessor ?? ''], - yAccessor: [state.yAccessor ?? ''], - valueAccessor: [state.valueAccessor ?? ''], - legend: [ - { - type: 'expression', - chain: [ - { - type: 'function', - function: LEGEND_FUNCTION, - arguments: { - isVisible: [false], - position: [], - }, - }, - ], - }, - ], - palette: state.palette?.params - ? [ - paletteService - .get(CUSTOM_PALETTE) - .toExpression( - computePaletteParams((state.palette?.params || {}) as CustomPaletteParams) - ), - ] - : [paletteService.get(DEFAULT_PALETTE_NAME).toExpression()], - gridConfig: [ - { - type: 'expression', - chain: [ - { - type: 'function', - function: HEATMAP_GRID_FUNCTION, - arguments: { - // grid - strokeWidth: [1], - // cells - isCellLabelVisible: [false], - // Y-axis - isYAxisLabelVisible: [false], - isYAxisTitleVisible: [state.gridConfig.isYAxisTitleVisible], - yTitle: [state.gridConfig.yTitle ?? ''], - // X-axis - isXAxisLabelVisible: [false], - isXAxisTitleVisible: [state.gridConfig.isXAxisTitleVisible], - xTitle: [state.gridConfig.xTitle ?? ''], - }, - }, - ], - }, - ], - }, - }, - ], + chain: [...(datasourceExpression?.chain ?? []), heatmapFn.toAst()], }; },