diff --git a/src/plugins/chart_expressions/expression_partition_vis/common/index.ts b/src/plugins/chart_expressions/expression_partition_vis/common/index.ts index 559d597caf90c..d51838b334a09 100755 --- a/src/plugins/chart_expressions/expression_partition_vis/common/index.ts +++ b/src/plugins/chart_expressions/expression_partition_vis/common/index.ts @@ -31,6 +31,7 @@ export type { TreemapVisExpressionFunctionDefinition, MosaicVisExpressionFunctionDefinition, WaffleVisExpressionFunctionDefinition, + PartitionLabelsExpressionFunctionDefinition, } from './types/expression_functions'; export type { diff --git a/src/plugins/chart_expressions/expression_partition_vis/common/types/expression_functions.ts b/src/plugins/chart_expressions/expression_partition_vis/common/types/expression_functions.ts index fe5910990d62a..30c5aba33ebf1 100644 --- a/src/plugins/chart_expressions/expression_partition_vis/common/types/expression_functions.ts +++ b/src/plugins/chart_expressions/expression_partition_vis/common/types/expression_functions.ts @@ -18,6 +18,7 @@ import { TREEMAP_VIS_EXPRESSION_NAME, MOSAIC_VIS_EXPRESSION_NAME, WAFFLE_VIS_EXPRESSION_NAME, + PARTITION_LABELS_FUNCTION, } from '../constants'; import { RenderValue, @@ -91,3 +92,10 @@ export enum ChartTypes { MOSAIC = 'mosaic', WAFFLE = 'waffle', } + +export type PartitionLabelsExpressionFunctionDefinition = ExpressionFunctionDefinition< + typeof PARTITION_LABELS_FUNCTION, + Datatable | null, + PartitionLabelsArguments, + ExpressionValuePartitionLabels +>; diff --git a/x-pack/plugins/lens/kibana.json b/x-pack/plugins/lens/kibana.json index 6921d2afa5082..ad4475ed9faa8 100644 --- a/x-pack/plugins/lens/kibana.json +++ b/x-pack/plugins/lens/kibana.json @@ -32,6 +32,7 @@ ], "optionalPlugins": [ "expressionLegacyMetricVis", + "expressionPartitionVis", "usageCollection", "taskManager", "globalSearch", diff --git a/x-pack/plugins/lens/public/visualizations/partition/to_expression.ts b/x-pack/plugins/lens/public/visualizations/partition/to_expression.ts index 3f66965dc98b6..42371f85e5984 100644 --- a/x-pack/plugins/lens/public/visualizations/partition/to_expression.ts +++ b/x-pack/plugins/lens/public/visualizations/partition/to_expression.ts @@ -5,11 +5,24 @@ * 2.0. */ -import type { Ast, AstFunction } from '@kbn/interpreter'; +import type { Ast } from '@kbn/interpreter'; import { Position } from '@elastic/charts'; import type { PaletteOutput, PaletteRegistry } from '@kbn/coloring'; import { buildExpression, buildExpressionFunction } from '@kbn/expressions-plugin/public'; +import type { + LabelPositions, + MosaicVisExpressionFunctionDefinition, + PartitionLabelsExpressionFunctionDefinition, + PieVisExpressionFunctionDefinition, + TreemapVisExpressionFunctionDefinition, + ValueFormats, + LegendDisplay as PartitionVisLegendDisplay, + WaffleVisExpressionFunctionDefinition, +} from '@kbn/expression-partition-vis-plugin/common'; +import { ExpressionFunctionTheme } from '@kbn/expressions-plugin/common'; +import { ExpressionFunctionVisDimension } from '@kbn/visualizations-plugin/common'; +import type { CollapseExpressionFunction } from '../../../common/expressions'; import type { Operation, DatasourcePublicAPI, DatasourceLayers } from '../../types'; import { DEFAULT_PERCENT_DECIMALS } from './constants'; import { shouldShowValuesInLegend } from './render_helpers'; @@ -45,15 +58,6 @@ type GenerateExpressionAstFunction = ( paletteService: PaletteRegistry ) => Ast | null; -type GenerateExpressionAstArguments = ( - state: PieVisualizationState, - attributes: Attributes, - operations: OperationColumnId[], - layer: PieLayerState, - datasourceLayers: DatasourceLayers, - paletteService: PaletteRegistry -) => Ast['chain'][number]['arguments']; - type GenerateLabelsAstArguments = ( state: PieVisualizationState, attributes: Attributes, @@ -74,30 +78,25 @@ export const getSortedGroups = ( return Array.from(new Set(originalOrder?.concat(layer[accessor] ?? []))); }; -const prepareDimension = (accessor: string) => { - const visdimension = buildExpressionFunction('visdimension', { accessor }); - return buildExpression([visdimension]).toAst(); -}; +const prepareDimension = (accessor: string) => + buildExpression([ + buildExpressionFunction('visdimension', { accessor }), + ]).toAst(); const generateCommonLabelsAstArgs: GenerateLabelsAstArguments = (state, attributes, layer) => { - const show = [!attributes.isPreview && layer.categoryDisplay !== CategoryDisplay.HIDE]; - const position = layer.categoryDisplay !== CategoryDisplay.HIDE ? [layer.categoryDisplay] : []; - const values = [layer.numberDisplay !== NumberDisplay.HIDDEN]; - const valuesFormat = layer.numberDisplay !== NumberDisplay.HIDDEN ? [layer.numberDisplay] : []; - const percentDecimals = [layer.percentDecimals ?? DEFAULT_PERCENT_DECIMALS]; + const show = !attributes.isPreview && layer.categoryDisplay !== CategoryDisplay.HIDE; + const position = + layer.categoryDisplay !== CategoryDisplay.HIDE ? (layer.categoryDisplay as LabelPositions) : []; + const values = layer.numberDisplay !== NumberDisplay.HIDDEN; + const valuesFormat = + layer.numberDisplay !== NumberDisplay.HIDDEN ? (layer.numberDisplay as ValueFormats) : []; + const percentDecimals = layer.percentDecimals ?? DEFAULT_PERCENT_DECIMALS; + const partitionLabelsFn = buildExpressionFunction( + 'partitionLabels', + { show, position, values, valuesFormat, percentDecimals } + ); - return [ - { - type: 'expression', - chain: [ - { - type: 'function', - function: 'partitionLabels', - arguments: { show, position, values, valuesFormat, percentDecimals }, - }, - ], - }, - ]; + return [buildExpression([partitionLabelsFn]).toAst()]; }; const generateWaffleLabelsAstArguments: GenerateLabelsAstArguments = (...args) => { @@ -117,29 +116,22 @@ const generatePaletteAstArguments = ( ): [Ast] => palette ? [ - { - type: 'expression', - chain: [ - { - type: 'function', - function: 'theme', - arguments: { - variable: ['palette'], - default: [paletteService.get(palette.name).toExpression(palette.params)], - }, - }, - ], - }, + buildExpression([ + buildExpressionFunction('theme', { + variable: 'palette', + default: paletteService.get(palette.name).toExpression(palette.params), + }), + ]).toAst(), ] : [paletteService.get('default').toExpression()]; -const generateCommonArguments: GenerateExpressionAstArguments = ( - state, - attributes, - operations, - layer, - datasourceLayers, - paletteService +const generateCommonArguments = ( + state: PieVisualizationState, + attributes: Attributes, + operations: OperationColumnId[], + layer: PieLayerState, + datasourceLayers: DatasourceLayers, + paletteService: PaletteRegistry ) => { return { labels: generateCommonLabelsAstArgs(state, attributes, layer), @@ -147,108 +139,81 @@ const generateCommonArguments: GenerateExpressionAstArguments = ( .filter(({ columnId }) => !isCollapsed(columnId, layer)) .map(({ columnId }) => columnId) .map(prepareDimension), - metric: layer.metric ? [prepareDimension(layer.metric)] : [], - legendDisplay: [attributes.isPreview ? LegendDisplay.HIDE : layer.legendDisplay], - legendPosition: [layer.legendPosition || Position.Right], - maxLegendLines: [layer.legendMaxLines ?? 1], - legendSize: layer.legendSize ? [layer.legendSize] : [], - nestedLegend: [!!layer.nestedLegend], - truncateLegend: [ + metric: layer.metric ? prepareDimension(layer.metric) : '', + legendDisplay: (attributes.isPreview + ? LegendDisplay.HIDE + : layer.legendDisplay) as PartitionVisLegendDisplay, + legendPosition: layer.legendPosition || Position.Right, + maxLegendLines: layer.legendMaxLines ?? 1, + legendSize: layer.legendSize, + nestedLegend: !!layer.nestedLegend, + truncateLegend: layer.truncateLegend ?? getDefaultVisualValuesForLayer(state, datasourceLayers).truncateText, - ], palette: generatePaletteAstArguments(paletteService, state.palette), + addTooltip: false, }; }; -const generatePieVisAst: GenerateExpressionAstFunction = (...rest) => ({ - type: 'expression', - chain: [ - { - type: 'function', - function: 'pieVis', - arguments: { - ...generateCommonArguments(...rest), - respectSourceOrder: [false], - startFromSecondLargestSlice: [true], - }, - }, - ], -}); +const generatePieVisAst: GenerateExpressionAstFunction = (...rest) => + buildExpression([ + buildExpressionFunction('pieVis', { + ...generateCommonArguments(...rest), + respectSourceOrder: false, + startFromSecondLargestSlice: true, + isDonut: false, + }), + ]).toAst(); const generateDonutVisAst: GenerateExpressionAstFunction = (...rest) => { const [, , , layer] = rest; - return { - type: 'expression', - chain: [ - { - type: 'function', - function: 'pieVis', - arguments: { - ...generateCommonArguments(...rest), - respectSourceOrder: [false], - isDonut: [true], - startFromSecondLargestSlice: [true], - emptySizeRatio: [layer.emptySizeRatio ?? EmptySizeRatios.SMALL], - }, - }, - ], - }; + + return buildExpression([ + buildExpressionFunction('pieVis', { + ...generateCommonArguments(...rest), + respectSourceOrder: false, + isDonut: true, + startFromSecondLargestSlice: true, + emptySizeRatio: layer.emptySizeRatio ?? EmptySizeRatios.SMALL, + }), + ]).toAst(); }; const generateTreemapVisAst: GenerateExpressionAstFunction = (...rest) => { const [, , , layer] = rest; - return { - type: 'expression', - chain: [ - { - type: 'function', - function: 'treemapVis', - arguments: { - ...generateCommonArguments(...rest), - nestedLegend: [!!layer.nestedLegend], - }, - }, - ], - }; + + return buildExpression([ + buildExpressionFunction('treemapVis', { + ...generateCommonArguments(...rest), + nestedLegend: !!layer.nestedLegend, + }), + ]).toAst(); }; -const generateMosaicVisAst: GenerateExpressionAstFunction = (...rest) => ({ - type: 'expression', - chain: [ - { - type: 'function', - function: 'mosaicVis', - arguments: { - ...generateCommonArguments(...rest), - // flip order of bucket dimensions so the rows are fetched before the columns to keep them stable - buckets: rest[2] - .filter(({ columnId }) => !isCollapsed(columnId, rest[3])) - .reverse() - .map((o) => o.columnId) - .map(prepareDimension), - }, - }, - ], -}); +const generateMosaicVisAst: GenerateExpressionAstFunction = (...rest) => + buildExpression([ + buildExpressionFunction('mosaicVis', { + ...generateCommonArguments(...rest), + // flip order of bucket dimensions so the rows are fetched before the columns to keep them stable + buckets: rest[2] + .filter(({ columnId }) => !isCollapsed(columnId, rest[3])) + .reverse() + .map((o) => o.columnId) + .map(prepareDimension), + }), + ]).toAst(); const generateWaffleVisAst: GenerateExpressionAstFunction = (...rest) => { const { buckets, nestedLegend, ...args } = generateCommonArguments(...rest); const [state, attributes, , layer] = rest; - return { - type: 'expression', - chain: [ - { - type: 'function', - function: 'waffleVis', - arguments: { - ...args, - bucket: buckets, - labels: generateWaffleLabelsAstArguments(state, attributes, layer), - showValuesInLegend: [shouldShowValuesInLegend(layer, state.shape)], - }, - }, - ], - }; + + return buildExpression([ + buildExpressionFunction('waffleVis', { + ...args, + bucket: buckets, + labels: generateWaffleLabelsAstArguments(state, attributes, layer), + showValuesInLegend: shouldShowValuesInLegend(layer, state.shape), + }), + ]).toAst(); }; const generateExprAst: GenerateExpressionAstFunction = (state, ...restArgs) => @@ -306,15 +271,11 @@ function expressionHelper( ...groups .filter((columnId) => layer.collapseFns?.[columnId]) .map((columnId) => { - return { - type: 'function', - function: 'lens_collapse', - arguments: { - by: groups.filter((chk) => chk !== columnId), - metric: [layer.metric], - fn: [layer.collapseFns![columnId]!], - }, - } as AstFunction; + return buildExpressionFunction('lens_collapse', { + by: groups.filter((chk) => chk !== columnId), + metric: layer.metric ? [layer.metric] : [], + fn: [layer.collapseFns![columnId]!], + }).toAst(); }), ...(visualizationAst ? visualizationAst.chain : []), ], diff --git a/x-pack/plugins/lens/tsconfig.json b/x-pack/plugins/lens/tsconfig.json index f4f343bbb4e5b..0cb74b2b1a87a 100644 --- a/x-pack/plugins/lens/tsconfig.json +++ b/x-pack/plugins/lens/tsconfig.json @@ -31,6 +31,7 @@ { "path": "../../../src/plugins/embeddable/tsconfig.json"}, { "path": "../../../src/plugins/presentation_util/tsconfig.json"}, { "path": "../../../src/plugins/field_formats/tsconfig.json"}, + { "path": "../../../src/plugins/chart_expressions/expression_partition_vis/tsconfig.json"}, { "path": "../../../src/plugins/chart_expressions/expression_heatmap/tsconfig.json"}, { "path": "../../../src/plugins/chart_expressions/expression_gauge/tsconfig.json"}, { "path": "../../../src/plugins/chart_expressions/expression_legacy_metric/tsconfig.json"},