From 6d1ba64bc59e928393beb31510293846b41b821b Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Fri, 15 Jul 2022 13:25:40 +0300 Subject: [PATCH 01/27] Migrate vis type xy to new unified xy expression --- .../expression_xy/common/constants.ts | 3 + .../common_data_layer_args.ts | 8 +- .../expression_functions/common_xy_args.ts | 12 +- .../extended_data_layer.ts | 12 +- .../extended_data_layer_fn.ts | 8 +- .../expression_functions/layered_xy_vis.ts | 11 +- .../expression_xy/common/i18n/index.tsx | 4 + .../common/types/expression_functions.ts | 25 +- .../public/components/data_layers.tsx | 8 +- .../public/components/split_chart.tsx | 28 +- .../components/tooltip/tooltip.test.tsx | 2 +- .../public/components/tooltip/tooltip.tsx | 7 +- .../public/components/x_domain.tsx | 10 +- .../public/components/xy_chart.tsx | 31 +- .../xy_chart_renderer.tsx | 13 +- .../public/helpers/data_layers.tsx | 44 +- .../expression_xy/public/helpers/layers.ts | 26 +- src/plugins/vis_types/xy/public/to_ast.ts | 389 ++++++++++++++---- .../public/xy_visualization/to_expression.ts | 51 ++- 19 files changed, 480 insertions(+), 212 deletions(-) diff --git a/src/plugins/chart_expressions/expression_xy/common/constants.ts b/src/plugins/chart_expressions/expression_xy/common/constants.ts index 5d9d7fb70d478..7392bb9da43c2 100644 --- a/src/plugins/chart_expressions/expression_xy/common/constants.ts +++ b/src/plugins/chart_expressions/expression_xy/common/constants.ts @@ -35,6 +35,8 @@ export const FittingFunctions = { LINEAR: 'Linear', CARRY: 'Carry', LOOKAHEAD: 'Lookahead', + AVERAGE: 'Average', + NEAREST: 'Nearest', } as const; export const EndValues = { @@ -98,6 +100,7 @@ export const XScaleTypes = { export const XYCurveTypes = { LINEAR: 'LINEAR', CURVE_MONOTONE_X: 'CURVE_MONOTONE_X', + CURVE_STEP_AFTER: 'CURVE_STEP_AFTER', } as const; export const ValueLabelModes = { diff --git a/src/plugins/chart_expressions/expression_xy/common/expression_functions/common_data_layer_args.ts b/src/plugins/chart_expressions/expression_xy/common/expression_functions/common_data_layer_args.ts index 0c173ea0754f8..10f6d5d748b23 100644 --- a/src/plugins/chart_expressions/expression_xy/common/expression_functions/common_data_layer_args.ts +++ b/src/plugins/chart_expressions/expression_xy/common/expression_functions/common_data_layer_args.ts @@ -7,7 +7,7 @@ */ import { ArgumentType } from '@kbn/expressions-plugin/common'; -import { SeriesTypes, XScaleTypes, DATA_DECORATION_CONFIG } from '../constants'; +import { SeriesTypes, XScaleTypes, DATA_DECORATION_CONFIG, XYCurveTypes } from '../constants'; import { strings } from '../i18n'; import { DataLayerArgs, ExtendedDataLayerArgs } from '../types'; @@ -58,6 +58,12 @@ export const commonDataLayerArgs: Omit< default: false, help: strings.getIsHorizontalHelp(), }, + curveType: { + types: ['string'], + options: [...Object.values(XYCurveTypes)], + help: strings.getCurveTypeHelp(), + strict: true, + }, lineWidth: { types: ['number'], help: strings.getLineWidthHelp(), diff --git a/src/plugins/chart_expressions/expression_xy/common/expression_functions/common_xy_args.ts b/src/plugins/chart_expressions/expression_xy/common/expression_functions/common_xy_args.ts index df9c4abdfe22e..8fb32aa39b366 100644 --- a/src/plugins/chart_expressions/expression_xy/common/expression_functions/common_xy_args.ts +++ b/src/plugins/chart_expressions/expression_xy/common/expression_functions/common_xy_args.ts @@ -11,7 +11,6 @@ import { FittingFunctions, LEGEND_CONFIG, ValueLabelModes, - XYCurveTypes, X_AXIS_CONFIG, Y_AXIS_CONFIG, } from '../constants'; @@ -50,12 +49,6 @@ export const commonXYArgs: CommonXYFn['args'] = { strict: true, default: ValueLabelModes.HIDE, }, - curveType: { - types: ['string'], - options: [...Object.values(XYCurveTypes)], - help: strings.getCurveTypeHelp(), - strict: true, - }, fillOpacity: { types: ['number'], help: strings.getFillOpacityHelp(), @@ -110,4 +103,9 @@ export const commonXYArgs: CommonXYFn['args'] = { types: ['string'], help: strings.getMinTimeBarIntervalHelp(), }, + handleEmptyXAccessor: { + types: ['boolean'], + default: false, + help: strings.getHandleEmptyXAccessorHelp(), + }, }; diff --git a/src/plugins/chart_expressions/expression_xy/common/expression_functions/extended_data_layer.ts b/src/plugins/chart_expressions/expression_xy/common/expression_functions/extended_data_layer.ts index 17c6485c711da..d0d65cc72732d 100644 --- a/src/plugins/chart_expressions/expression_xy/common/expression_functions/extended_data_layer.ts +++ b/src/plugins/chart_expressions/expression_xy/common/expression_functions/extended_data_layer.ts @@ -20,27 +20,23 @@ export const extendedDataLayerFunction: ExtendedDataLayerFn = { args: { ...commonDataLayerArgs, xAccessor: { - types: ['string'], + types: ['vis_dimension', 'string'], help: strings.getXAccessorHelp(), }, splitAccessors: { - types: ['string'], + types: ['vis_dimension', 'string'], help: strings.getSplitAccessorHelp(), multi: true, }, accessors: { - types: ['string'], + types: ['vis_dimension', 'string'], help: strings.getAccessorsHelp(), multi: true, }, markSizeAccessor: { - types: ['string'], + types: ['vis_dimension', 'string'], help: strings.getMarkSizeAccessorHelp(), }, - table: { - types: ['datatable'], - help: strings.getTableHelp(), - }, layerId: { types: ['string'], help: strings.getLayerIdHelp(), diff --git a/src/plugins/chart_expressions/expression_xy/common/expression_functions/extended_data_layer_fn.ts b/src/plugins/chart_expressions/expression_xy/common/expression_functions/extended_data_layer_fn.ts index 16905f96f9c2f..79612971e841b 100644 --- a/src/plugins/chart_expressions/expression_xy/common/expression_functions/extended_data_layer_fn.ts +++ b/src/plugins/chart_expressions/expression_xy/common/expression_functions/extended_data_layer_fn.ts @@ -6,6 +6,7 @@ * Side Public License, v 1. */ +import { ExpressionValueVisDimension } from '@kbn/visualizations-plugin/common'; import { validateAccessor } from '@kbn/visualizations-plugin/common/utils'; import { ExtendedDataLayerArgs, ExtendedDataLayerFn } from '../types'; import { EXTENDED_DATA_LAYER, LayerTypes } from '../constants'; @@ -19,8 +20,11 @@ import { } from './validate'; export const extendedDataLayerFn: ExtendedDataLayerFn['fn'] = async (data, args, context) => { - const table = args.table ?? data; - const accessors = getAccessors(args, table); + const table = data; + const accessors = getAccessors( + args, + table + ); validateAccessor(accessors.xAccessor, table.columns); accessors.splitAccessors?.forEach((accessor) => validateAccessor(accessor, table.columns)); diff --git a/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis.ts b/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis.ts index f419891e079ea..2de0d1305df52 100644 --- a/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis.ts +++ b/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis.ts @@ -13,6 +13,7 @@ import { REFERENCE_LINE_LAYER, LAYERED_XY_VIS, EXTENDED_ANNOTATION_LAYER, + REFERENCE_LINE, } from '../constants'; import { commonXYArgs } from './common_xy_args'; import { strings } from '../i18n'; @@ -25,12 +26,20 @@ export const layeredXyVisFunction: LayeredXyVisFn = { args: { ...commonXYArgs, layers: { - types: [EXTENDED_DATA_LAYER, REFERENCE_LINE_LAYER, EXTENDED_ANNOTATION_LAYER], + types: [EXTENDED_DATA_LAYER, REFERENCE_LINE_LAYER, EXTENDED_ANNOTATION_LAYER, REFERENCE_LINE], help: i18n.translate('expressionXY.layeredXyVis.layers.help', { defaultMessage: 'Layers of visual series', }), multi: true, }, + splitColumnAccessor: { + types: ['vis_dimension', 'string'], + help: strings.getSplitColumnAccessorHelp(), + }, + splitRowAccessor: { + types: ['vis_dimension', 'string'], + help: strings.getSplitRowAccessorHelp(), + }, }, async fn(data, args, handlers) { const { layeredXyVisFn } = await import('./layered_xy_vis_fn'); diff --git a/src/plugins/chart_expressions/expression_xy/common/i18n/index.tsx b/src/plugins/chart_expressions/expression_xy/common/i18n/index.tsx index 75a523ab41d92..ac2b20f8bdf49 100644 --- a/src/plugins/chart_expressions/expression_xy/common/i18n/index.tsx +++ b/src/plugins/chart_expressions/expression_xy/common/i18n/index.tsx @@ -117,6 +117,10 @@ export const strings = { i18n.translate('expressionXY.xyVis.splitRowAccessor.help', { defaultMessage: 'Specifies split row of the xy chart', }), + getHandleEmptyXAccessorHelp: () => + i18n.translate('expressionXY.xyVis.splitRowAccessor.help', { + defaultMessage: 'Allow handling empty x accessor', + }), getLayersHelp: () => i18n.translate('expressionXY.layeredXyVis.layers.help', { defaultMessage: 'Layers of visual series', diff --git a/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts b/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts index 5d518c31513ae..83002c57e7514 100644 --- a/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts +++ b/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts @@ -130,6 +130,7 @@ export interface DataLayerArgs { isHorizontal: boolean; palette: PaletteOutput; decorations?: DataDecorationConfigResult[]; + curveType?: XYCurveType; } export interface ValidLayer extends DataLayerConfigResult { @@ -138,12 +139,12 @@ export interface ValidLayer extends DataLayerConfigResult { export interface ExtendedDataLayerArgs { layerId?: string; - accessors: string[]; + accessors: Array; seriesType: SeriesType; - xAccessor?: string; + xAccessor?: string | ExpressionValueVisDimension; simpleView?: boolean; - splitAccessors?: string[]; - markSizeAccessor?: string; + splitAccessors?: Array; + markSizeAccessor?: string | ExpressionValueVisDimension; lineWidth?: number; showPoints?: boolean; showLines?: boolean; @@ -157,7 +158,7 @@ export interface ExtendedDataLayerArgs { palette: PaletteOutput; // palette will always be set on the expression decorations?: DataDecorationConfigResult[]; - table?: Datatable; + curveType?: XYCurveType; } export interface LegendConfig { @@ -215,7 +216,6 @@ export interface XYArgs extends DataLayerArgs { referenceLines: ReferenceLineConfigResult[]; annotationLayers: AnnotationLayerConfigResult[]; fittingFunction?: FittingFunction; - curveType?: XYCurveType; fillOpacity?: number; hideEndzones?: boolean; valuesInLegend?: boolean; @@ -230,6 +230,7 @@ export interface XYArgs extends DataLayerArgs { detailedTooltip?: boolean; orderBucketsBySum?: boolean; showTooltip: boolean; + handleEmptyXAccessor?: boolean; } export interface LayeredXYArgs { @@ -239,7 +240,6 @@ export interface LayeredXYArgs { valueLabels: ValueLabelMode; layers?: XYExtendedLayerConfigResult[]; fittingFunction?: FittingFunction; - curveType?: XYCurveType; fillOpacity?: number; hideEndzones?: boolean; valuesInLegend?: boolean; @@ -252,6 +252,9 @@ export interface LayeredXYArgs { minTimeBarInterval?: string; orderBucketsBySum?: boolean; showTooltip: boolean; + splitRowAccessor?: ExpressionValueVisDimension | string; + splitColumnAccessor?: ExpressionValueVisDimension | string; + handleEmptyXAccessor?: boolean; } export interface XYProps { @@ -261,7 +264,6 @@ export interface XYProps { valueLabels: ValueLabelMode; layers: CommonXYLayerConfig[]; fittingFunction?: FittingFunction; - curveType?: XYCurveType; fillOpacity?: number; hideEndzones?: boolean; valuesInLegend?: boolean; @@ -276,6 +278,7 @@ export interface XYProps { detailedTooltip?: boolean; orderBucketsBySum?: boolean; showTooltip: boolean; + handleEmptyXAccessor?: boolean; } export interface AnnotationLayerArgs { @@ -317,12 +320,14 @@ export type XYLayerConfig = DataLayerConfig | ReferenceLineConfig | AnnotationLa export type XYExtendedLayerConfig = | ExtendedDataLayerConfig | ReferenceLineLayerConfig - | ExtendedAnnotationLayerConfig; + | ExtendedAnnotationLayerConfig + | ReferenceLineConfig; export type XYExtendedLayerConfigResult = | ExtendedDataLayerConfigResult | ReferenceLineLayerConfigResult - | ExtendedAnnotationLayerConfigResult; + | ExtendedAnnotationLayerConfigResult + | ReferenceLineConfigResult; export interface ExtendedReferenceLineDecorationConfig extends ReferenceLineArgs { type: typeof EXTENDED_REFERENCE_LINE_DECORATION_CONFIG; diff --git a/src/plugins/chart_expressions/expression_xy/public/components/data_layers.tsx b/src/plugins/chart_expressions/expression_xy/public/components/data_layers.tsx index 35e4c0c7f1abb..b8f2bca232c49 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/data_layers.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/data_layers.tsx @@ -22,7 +22,6 @@ import { EndValue, FittingFunction, ValueLabelMode, - XYCurveType, XScaleType, } from '../../common'; import { SeriesTypes, ValueLabelModes, AxisModes } from '../../common/constants'; @@ -42,7 +41,6 @@ interface Props { formatFactory: FormatFactory; chartHasMoreThanOneBarSeries?: boolean; yAxesConfiguration: GroupsConfiguration; - curveType?: XYCurveType; fittingFunction?: FittingFunction; endValue?: EndValue | undefined; paletteService: PaletteRegistry; @@ -55,6 +53,7 @@ interface Props { valueLabels: ValueLabelMode; defaultXScaleType: XScaleType; fieldFormats: LayersFieldFormats; + handleEmptyXAccessor?: boolean; } export const DataLayers: FC = ({ @@ -62,7 +61,6 @@ export const DataLayers: FC = ({ layers, endValue, timeZone, - curveType, syncColors, valueLabels, fillOpacity, @@ -76,6 +74,7 @@ export const DataLayers: FC = ({ chartHasMoreThanOneBarSeries, defaultXScaleType, fieldFormats, + handleEmptyXAccessor, }) => { const colorAssignments = getColorAssignments(layers, titles, fieldFormats, formattedDatatables); return ( @@ -118,11 +117,12 @@ export const DataLayers: FC = ({ fillOpacity, defaultXScaleType, fieldFormats, + handleEmptyXAccessor, }); const index = `${layer.layerId}-${accessorIndex}`; - const curve = curveType ? CurveType[curveType] : undefined; + const curve = layer.curveType ? CurveType[layer.curveType] : undefined; switch (seriesType) { case SeriesTypes.LINE: diff --git a/src/plugins/chart_expressions/expression_xy/public/components/split_chart.tsx b/src/plugins/chart_expressions/expression_xy/public/components/split_chart.tsx index 3f7d59e0473d5..6df2d10a777b3 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/split_chart.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/split_chart.tsx @@ -9,41 +9,19 @@ import React, { useCallback } from 'react'; import { GroupBy, SmallMultiples, Predicate } from '@elastic/charts'; import { ExpressionValueVisDimension } from '@kbn/visualizations-plugin/common'; -import { - getAccessorByDimension, - getColumnByAccessor, -} from '@kbn/visualizations-plugin/common/utils'; +import { getColumnByAccessor } from '@kbn/visualizations-plugin/common/utils'; import { Datatable } from '@kbn/expressions-plugin/public'; -import { SerializedFieldFormat } from '@kbn/field-formats-plugin/common'; -import { FormatFactory } from '../types'; interface SplitChartProps { splitColumnAccessor?: ExpressionValueVisDimension | string; splitRowAccessor?: ExpressionValueVisDimension | string; columns: Datatable['columns']; - formatFactory: FormatFactory; - fieldFormats: Record; } const SPLIT_COLUMN = '__split_column__'; const SPLIT_ROW = '__split_row__'; -export const SplitChart = ({ - splitColumnAccessor, - splitRowAccessor, - columns, - fieldFormats, - formatFactory, -}: SplitChartProps) => { - const format = useCallback( - (value: unknown, accessor: ExpressionValueVisDimension | string) => { - const formatParams = fieldFormats[getAccessorByDimension(accessor, columns)]; - const formatter = formatFactory(formatParams); - return formatter.convert(value); - }, - [columns, formatFactory, fieldFormats] - ); - +export const SplitChart = ({ splitColumnAccessor, splitRowAccessor, columns }: SplitChartProps) => { const getData = useCallback( (datum: Record, accessor: ExpressionValueVisDimension | string) => { const splitColumn = getColumnByAccessor(accessor, columns); @@ -59,7 +37,6 @@ export const SplitChart = ({ id={SPLIT_COLUMN} by={(spec, datum) => getData(datum, splitColumnAccessor)} sort={Predicate.DataIndex} - format={(value) => format(value, splitColumnAccessor)} /> )} {splitRowAccessor && ( @@ -67,7 +44,6 @@ export const SplitChart = ({ id={SPLIT_ROW} by={(spec, datum) => getData(datum, splitRowAccessor)} sort={Predicate.DataIndex} - format={(value) => format(value, splitRowAccessor)} /> )} ; }): XYChartSeriesIdentifier => ({ - specId: generateSeriesId({ layerId, xAccessor }, splitAccessors, yAccessor), + specId: generateSeriesId({ layerId }, splitAccessors, yAccessor, xAccessor), yAccessor: yAccessor ?? 'a', splitAccessors: seriesSplitAccessors, seriesKeys: [], diff --git a/src/plugins/chart_expressions/expression_xy/public/components/tooltip/tooltip.tsx b/src/plugins/chart_expressions/expression_xy/public/components/tooltip/tooltip.tsx index 7ab7c9f549e24..45cd2a87c1651 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/tooltip/tooltip.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/tooltip/tooltip.tsx @@ -32,6 +32,7 @@ type Props = TooltipInfo & { splitRowAccessor?: string; splitColumnAccessor?: string; }; + handleEmptyXAccessor?: boolean; }; export const Tooltip: FC = ({ @@ -43,6 +44,7 @@ export const Tooltip: FC = ({ formattedDatatables, splitAccessors, xDomain, + handleEmptyXAccessor, }) => { const pickedValue = values.find(({ isHighlighted }) => isHighlighted); @@ -52,7 +54,10 @@ export const Tooltip: FC = ({ const data: TooltipData[] = []; const seriesIdentifier = pickedValue.seriesIdentifier as XYChartSeriesIdentifier; - const { layerId, xAccessor, yAccessor } = getMetaFromSeriesId(seriesIdentifier.specId); + const { layerId, xAccessor, yAccessor } = getMetaFromSeriesId( + seriesIdentifier.specId, + handleEmptyXAccessor + ); const { formattedColumns } = formattedDatatables[layerId]; const layerTitles = titles[layerId]; const layerFormats = fieldFormats[layerId]; diff --git a/src/plugins/chart_expressions/expression_xy/public/components/x_domain.tsx b/src/plugins/chart_expressions/expression_xy/public/components/x_domain.tsx index e193eb9a91d3f..e1d873d5ad171 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/x_domain.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/x_domain.tsx @@ -47,6 +47,7 @@ export const getXDomain = ( minInterval: number | undefined, isTimeViz: boolean, isHistogram: boolean, + hasBars: boolean, xExtent?: AxisExtentConfigResult ) => { const appliedTimeRange = getAppliedTimeRange(datatableUtilitites, layers)?.timeRange; @@ -62,7 +63,7 @@ export const getXDomain = ( ? { minInterval, min: NaN, max: NaN } : undefined; - if (isHistogram && isFullyQualified(baseDomain)) { + if ((isHistogram || isTimeViz) && isFullyQualified(baseDomain)) { if (xExtent && !isTimeViz) { return { extendedDomain: { @@ -76,7 +77,8 @@ export const getXDomain = ( const xValues = uniq( layers .flatMap(({ table, xAccessor }) => { - const accessor = xAccessor && getAccessorByDimension(xAccessor, table.columns); + const accessor = + xAccessor !== undefined ? getAccessorByDimension(xAccessor, table.columns) : undefined; return table.rows.map((row) => accessor && row[accessor] && row[accessor].valueOf()); }) .filter((v) => !isUndefined(v)) @@ -86,8 +88,8 @@ export const getXDomain = ( const lastXValue = xValues[xValues.length - 1]; const domainMin = Math.min(firstXValue, baseDomain.min); - const domainMaxValue = baseDomain.max - baseDomain.minInterval; - const domainMax = Math.max(domainMaxValue, lastXValue); + const domainMaxValue = Math.max(baseDomain.max - baseDomain.minInterval, lastXValue); + const domainMax = hasBars ? domainMaxValue : domainMaxValue + baseDomain.minInterval; return { extendedDomain: { diff --git a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx index 5bb7f5d6f8c47..07f161e7a6080 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx @@ -27,6 +27,7 @@ import { Direction, XYChartElementEvent, } from '@elastic/charts'; +import { i18n } from '@kbn/i18n'; import { IconType } from '@elastic/eui'; import { PaletteRegistry } from '@kbn/coloring'; import { RenderMode } from '@kbn/expressions-plugin/common'; @@ -190,6 +191,7 @@ export function XYChart({ xAxisConfig, splitColumnAccessor, splitRowAccessor, + handleEmptyXAccessor, } = args; const chartRef = useRef(null); const chartTheme = chartsThemeService.useChartsTheme(); @@ -272,7 +274,14 @@ export function XYChart({ [...(yAxisConfigs ?? []), ...(xAxisConfig ? [xAxisConfig] : [])] ); - const xTitle = xAxisConfig?.title || (xAxisColumn && xAxisColumn.name); + const allDocs = i18n.translate('visTypeXy.aggResponse.allDocsTitle', { + defaultMessage: 'All docs', + }); + + const xTitle = + xAxisConfig?.title || + (xAxisColumn && xAxisColumn.name) || + (handleEmptyXAccessor ? allDocs : undefined); const yAxesMap = { left: yAxesConfiguration.find( ({ position }) => position === getAxisPosition(Position.Left, shouldRotate) @@ -286,7 +295,8 @@ export function XYChart({ dataLayers, { splitColumnAccessor, splitRowAccessor }, { xTitle }, - yAxesConfiguration + yAxesConfiguration, + handleEmptyXAccessor ); const filteredBarLayers = dataLayers.filter(({ seriesType }) => seriesType === SeriesTypes.BAR); @@ -303,6 +313,7 @@ export function XYChart({ const defaultXScaleType = isTimeViz ? XScaleTypes.TIME : XScaleTypes.ORDINAL; const isHistogramViz = dataLayers.every((l) => l.isHistogram); + const hasBars = dataLayers.some((l) => l.seriesType === SeriesTypes.BAR); const { baseDomain: rawXDomain, extendedDomain: xDomain } = getXDomain( data.datatableUtilities, @@ -310,6 +321,7 @@ export function XYChart({ minInterval, isTimeViz, isHistogramViz, + hasBars, xAxisConfig?.extent ); @@ -546,7 +558,9 @@ export function XYChart({ const { table } = dataLayers[0]; const xAccessor = - dataLayers[0].xAccessor && getAccessorByDimension(dataLayers[0].xAccessor, table.columns); + dataLayers[0].xAccessor !== undefined + ? getAccessorByDimension(dataLayers[0].xAccessor, table.columns) + : undefined; const xAxisColumnIndex = table.columns.findIndex((el) => el.id === xAccessor); const context: BrushEvent['data'] = { range: [min, max], table, column: xAxisColumnIndex }; @@ -699,6 +713,7 @@ export function XYChart({ splitRowAccessor: splitRowId, }} xDomain={isTimeViz ? rawXDomain : undefined} + handleEmptyXAccessor={handleEmptyXAccessor} /> ) : undefined, @@ -740,7 +755,11 @@ export function XYChart({ } title={xTitle} gridLine={gridLineStyle} - hide={xAxisConfig?.hide || dataLayers[0]?.simpleView || !dataLayers[0]?.xAccessor} + hide={ + xAxisConfig?.hide || + dataLayers[0]?.simpleView || + !(handleEmptyXAccessor || dataLayers[0]?.xAccessor) + } tickFormat={(d) => { let value = safeXAccessorLabelRenderer(d) || ''; if (xAxisConfig?.truncate && value.length > xAxisConfig.truncate) { @@ -757,9 +776,7 @@ export function XYChart({ )} {yAxesConfiguration.map((axis) => { @@ -812,7 +829,6 @@ export function XYChart({ layers={dataLayers} endValue={endValue} timeZone={timeZone} - curveType={args.curveType} syncColors={syncColors} valueLabels={valueLabels} fillOpacity={args.fillOpacity} @@ -826,6 +842,7 @@ export function XYChart({ chartHasMoreThanOneBarSeries={chartHasMoreThanOneBarSeries} defaultXScaleType={defaultXScaleType} fieldFormats={fieldFormats} + handleEmptyXAccessor={handleEmptyXAccessor} /> )} {referenceLineLayers.length ? ( diff --git a/src/plugins/chart_expressions/expression_xy/public/expression_renderers/xy_chart_renderer.tsx b/src/plugins/chart_expressions/expression_xy/public/expression_renderers/xy_chart_renderer.tsx index c5ca004e3c38c..df870934df159 100644 --- a/src/plugins/chart_expressions/expression_xy/public/expression_renderers/xy_chart_renderer.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/expression_renderers/xy_chart_renderer.tsx @@ -9,6 +9,7 @@ import { i18n } from '@kbn/i18n'; import { I18nProvider } from '@kbn/i18n-react'; import { ThemeServiceStart } from '@kbn/core/public'; +import { css } from '@emotion/react'; import React from 'react'; import ReactDOM from 'react-dom'; import type { PaletteRegistry } from '@kbn/coloring'; @@ -62,13 +63,17 @@ export const getXyChartRenderer = ({ import('../helpers/interval'), ]); + const chartContainerStyle = css({ + width: '100%', + height: '100%', + overflowX: 'hidden', + position: handlers.uiState ? 'absolute' : 'relative', + }); + ReactDOM.render( -
+
SeriesSpec; type GetSeriesNameFn = ( @@ -323,19 +324,21 @@ const EMPTY_ACCESSOR = '-'; const SPLIT_CHAR = '.'; export const generateSeriesId = ( - { layerId, xAccessor }: Pick, + { layerId }: Pick, splitColumnIds: string[], - accessor?: string + accessor?: string, + xColumnId?: string ) => - [layerId, xAccessor ?? EMPTY_ACCESSOR, accessor ?? EMPTY_ACCESSOR, ...splitColumnIds].join( + [layerId, xColumnId ?? EMPTY_ACCESSOR, accessor ?? EMPTY_ACCESSOR, ...splitColumnIds].join( SPLIT_CHAR ); -export const getMetaFromSeriesId = (seriesId: string) => { +export const getMetaFromSeriesId = (seriesId: string, handleEmptyXAccessor?: boolean) => { const [layerId, xAccessor, yAccessor, ...splitAccessors] = seriesId.split(SPLIT_CHAR); return { layerId, - xAccessor: xAccessor === EMPTY_ACCESSOR ? undefined : xAccessor, + xAccessor: + xAccessor === EMPTY_ACCESSOR ? (handleEmptyXAccessor ? 'all' : undefined) : xAccessor, yAccessor, splitAccessor: splitAccessors[0] === EMPTY_ACCESSOR ? undefined : splitAccessors, }; @@ -358,6 +361,7 @@ export const getSeriesProps: GetSeriesPropsFn = ({ formattedDatatableInfo, defaultXScaleType, fieldFormats, + handleEmptyXAccessor, }): SeriesSpec => { const { table, isStacked, markSizeAccessor } = layer; const isPercentage = layer.isPercentage; @@ -367,7 +371,10 @@ export const getSeriesProps: GetSeriesPropsFn = ({ } const scaleType = yAxis?.scaleType || ScaleType.Linear; const isBarChart = layer.seriesType === SeriesTypes.BAR; - const xColumnId = layer.xAccessor && getAccessorByDimension(layer.xAccessor, table.columns); + const xColumnId = + layer.xAccessor !== undefined + ? getAccessorByDimension(layer.xAccessor, table.columns) + : undefined; const splitColumnIds = layer.splitAccessors?.map((splitAccessor) => { return getAccessorByDimension(splitAccessor, table.columns); @@ -403,12 +410,24 @@ export const getSeriesProps: GetSeriesPropsFn = ({ ) ); + let emptyX: Record = { + unifiedX: i18n.translate('expressionXY.xyChart.emptyXLabel', { + defaultMessage: '(empty)', + }), + }; + + if (handleEmptyXAccessor) { + emptyX = { + all: i18n.translate('expressionXY.xyChart.handledEmptyXLabel', { + defaultMessage: '_all', + }), + }; + } + if (!xColumnId) { rows = rows.map((row) => ({ ...row, - unifiedX: i18n.translate('expressionXY.xyChart.emptyXLabel', { - defaultMessage: '(empty)', - }), + ...emptyX, })); } @@ -429,13 +448,14 @@ export const getSeriesProps: GetSeriesPropsFn = ({ return { splitSeriesAccessors: splitColumnIds.length ? splitColumnIds : [], - stackAccessors: isStacked ? [layer.xAccessor as string] : [], + stackAccessors: isStacked && xColumnId ? [xColumnId] : [], id: generateSeriesId( layer, splitColumnIds.length ? splitColumnIds : [EMPTY_ACCESSOR], - accessor + accessor, + xColumnId ), - xAccessor: xColumnId || 'unifiedX', + xAccessor: xColumnId || (handleEmptyXAccessor ? 'all' : 'unifiedX'), yAccessors: [accessor], markSizeAccessor: markSizeColumnId, markFormat: (value) => markFormatter.convert(value), diff --git a/src/plugins/chart_expressions/expression_xy/public/helpers/layers.ts b/src/plugins/chart_expressions/expression_xy/public/helpers/layers.ts index 359f1c27879a9..03a3f412b7af3 100644 --- a/src/plugins/chart_expressions/expression_xy/public/helpers/layers.ts +++ b/src/plugins/chart_expressions/expression_xy/public/helpers/layers.ts @@ -80,7 +80,9 @@ export function getFilteredLayers(layers: CommonXYLayerConfig[]) { if (isDataLayer(layer)) { xAccessor = - layer.xAccessor && table && getAccessorByDimension(layer.xAccessor, table.columns); + layer.xAccessor !== undefined && table + ? getAccessorByDimension(layer.xAccessor, table.columns) + : undefined; splitAccessors = table ? layer.splitAccessors?.map((splitAccessor) => getAccessorByDimension(splitAccessor, table!.columns) @@ -197,7 +199,8 @@ export const getLayerTitles = ( { xAccessor, accessors, splitAccessors = [], table, layerId }: CommonXYDataLayerConfig, { splitColumnAccessor, splitRowAccessor }: SplitAccessors, { xTitle }: CustomTitles, - groups: GroupsConfiguration + groups: GroupsConfiguration, + handleEmptyXAccessor?: boolean ): LayerAccessorsTitles => { const mapTitle = (dimension?: string | ExpressionValueVisDimension) => { if (!dimension) { @@ -212,8 +215,12 @@ export const getLayerTitles = ( [accessor]: getTitleForYAccessor(layerId, accessor, groups, table.columns), }); - const xColumnId = xAccessor && getAccessorByDimension(xAccessor, table.columns); - const yColumnIds = accessors.map((a) => a && getAccessorByDimension(a, table.columns)); + const xColumnId = xAccessor + ? getAccessorByDimension(xAccessor, table.columns) + : handleEmptyXAccessor + ? 'all' + : undefined; + const yColumnIds = accessors.map((a) => getAccessorByDimension(a, table.columns)); const splitColumnAccessors: Array = splitAccessors; return { @@ -238,12 +245,19 @@ export const getLayersTitles = ( layers: CommonXYDataLayerConfig[], splitAccessors: SplitAccessors, customTitles: CustomTitles, - groups: GroupsConfiguration + groups: GroupsConfiguration, + handleEmptyXAccessor?: boolean ): LayersAccessorsTitles => layers.reduce( (formatters, layer) => ({ ...formatters, - [layer.layerId]: getLayerTitles(layer, splitAccessors, customTitles, groups), + [layer.layerId]: getLayerTitles( + layer, + splitAccessors, + customTitles, + groups, + handleEmptyXAccessor + ), }), {} ); diff --git a/src/plugins/vis_types/xy/public/to_ast.ts b/src/plugins/vis_types/xy/public/to_ast.ts index e92ca8cda82d2..635489ba9299a 100644 --- a/src/plugins/vis_types/xy/public/to_ast.ts +++ b/src/plugins/vis_types/xy/public/to_ast.ts @@ -7,7 +7,7 @@ */ import moment from 'moment'; -import { Position } from '@elastic/charts'; +import { Position, ScaleType as ECScaleType } from '@elastic/charts'; import { VisToExpressionAst, getVisSchemas, @@ -17,9 +17,8 @@ import { } from '@kbn/visualizations-plugin/public'; import { buildExpression, buildExpressionFunction } from '@kbn/expressions-plugin/public'; import { BUCKET_TYPES } from '@kbn/data-plugin/public'; -import { Labels } from '@kbn/charts-plugin/public'; - import { TimeRangeBounds } from '@kbn/data-plugin/common'; +import { PaletteOutput } from '@kbn/charts-plugin/common/expressions/palette/types'; import { Dimensions, Dimension, @@ -29,86 +28,267 @@ import { ThresholdLine, ValueAxis, Scale, - TimeMarker, + ChartMode, + InterpolationMode, + ScaleType, } from './types'; -import { visName, VisTypeXyExpressionFunctionDefinition } from './expression_functions/xy_vis_fn'; -import { XyVisType } from '../common'; +import { ChartType } from '../common'; import { getSeriesParams } from './utils/get_series_params'; import { getSafeId } from './utils/accessors'; -const prepareLabel = (data: Labels) => { - const label = buildExpressionFunction('label', { - ...data, +interface Bounds { + min?: string | number; + max?: string | number; +} + +const getCurveType = (type?: InterpolationMode) => { + switch (type) { + case 'cardinal': + return 'CURVE_MONOTONE_X'; + case 'step-after': + return 'CURVE_STEP_AFTER'; + case 'linear': + default: + return 'LINEAR'; + } +}; + +const prepareLengend = (params: VisParams, legendSize?: LegendSize) => { + const legend = buildExpressionFunction('legendConfig', { + isVisible: params.addLegend, + maxLines: params.maxLegendLines, + position: params.legendPosition, + shouldTruncate: params.truncateLegend, + legendSize, }); - return buildExpression([label]); + return buildExpression([legend]); +}; + +const getCorrectAccessor = (yAccessor: Dimension, aggId: string) => { + return typeof yAccessor.accessor === 'number' + ? `col-${yAccessor.accessor}-${aggId}` + : yAccessor.accessor; }; -const prepareScale = (data: Scale) => { - const scale = buildExpressionFunction('visscale', { - ...data, +const prepareDecoration = (axisId: string, yAccessor: Dimension, aggId: string) => { + const dataDecorationConfig = buildExpressionFunction('dataDecorationConfig', { + forAccessor: getCorrectAccessor(yAccessor, aggId), + axisId, }); - return buildExpression([scale]); + return buildExpression([dataDecorationConfig]); }; -const prepareThresholdLine = (data: ThresholdLine) => { - const thresholdLine = buildExpressionFunction('thresholdline', { - ...data, +const preparePalette = (palette: PaletteOutput) => { + const paletteExp = buildExpressionFunction( + palette.name === 'custom' ? 'palette' : 'system_palette', + palette.name === 'custom' + ? { ...palette.params } + : { + name: palette.name, + } + ); + + return buildExpression([paletteExp]); +}; + +const prepareLayers = ( + seriesParam: SeriesParam, + isHistogram: boolean, + valueAxes: ValueAxis[], + yAccessors: Dimension[], + xAccessor: Dimension | null, + splitAccessors?: Dimension[], + markSizeAccessor?: Dimension, + palette?: PaletteOutput, + xScale?: Scale +) => { + // valueAxis.position !== Position.Left + const isHorizontal = valueAxes.some((valueAxis) => { + return ( + seriesParam.valueAxis === valueAxis.id && + valueAxis.position !== Position.Left && + valueAxis.position !== Position.Right + ); + }); + const isBar = seriesParam.type === ChartType.Histogram; + const dataLayer = buildExpressionFunction('extendedDataLayer', { + seriesType: isBar ? 'bar' : seriesParam.type, + isHistogram, + isHorizontal, + isStacked: seriesParam.mode === ChartMode.Stacked, + lineWidth: !isBar ? seriesParam.lineWidth : undefined, + showPoints: !isBar ? seriesParam.showCircles : undefined, + pointsRadius: !isBar ? seriesParam.circlesRadius : undefined, + showLines: !isBar ? seriesParam.drawLinesBetweenPoints : undefined, + curveType: getCurveType(seriesParam.interpolate), + decorations: yAccessors.map((accessor) => + prepareDecoration(seriesParam.valueAxis, accessor, seriesParam.data.id) + ), + hide: !seriesParam.show, + accessors: yAccessors.map((accessor) => prepareVisDimension(accessor)), + xAccessor: xAccessor ? prepareVisDimension(xAccessor) : undefined, + xScaleType: getScaleType( + xScale, + xAccessor?.format?.id === 'number' || + (xAccessor?.format?.params?.id === 'number' && + xAccessor?.format?.id !== BUCKET_TYPES.RANGE && + xAccessor?.format?.id !== BUCKET_TYPES.TERMS), + 'date' in (xAccessor?.params || {}), + 'interval' in (xAccessor?.params || {}) + ), + splitAccessors: splitAccessors ? splitAccessors.map(prepareVisDimension) : undefined, + markSizeAccessor: markSizeAccessor ? prepareVisDimension(markSizeAccessor) : undefined, + palette: palette ? preparePalette(palette) : undefined, + columnToLabel: JSON.stringify( + [...yAccessors, xAccessor, ...(splitAccessors ?? [])].reduce>( + (acc, dimension) => { + if (dimension) { + acc[getCorrectAccessor(dimension, seriesParam.data.id)] = dimension.label; + } + + return acc; + }, + {} + ) + ), }); - return buildExpression([thresholdLine]); + return buildExpression([dataLayer]); }; -const prepareTimeMarker = (data: TimeMarker) => { - const timeMarker = buildExpressionFunction('timemarker', { - ...data, +const getMode = (scale: Scale, bounds?: Bounds) => { + if (scale.defaultYExtents) { + return 'dataBounds'; + } + + if (scale.setYExtents || bounds) { + return 'custom'; + } +}; + +const getLabelArgs = (data: CategoryAxis, isTimeChart?: boolean) => { + return { + truncate: data.labels.truncate, + labelsOrientation: data.labels.rotate ?? (isTimeChart ? 0 : -90), + showOverlappingLabels: data.labels.filter === false, + showDuplicates: data.labels.filter === false, + labelColor: data.labels.color, + }; +}; + +const prepareAxisExtentConfig = (scale: Scale, bounds?: Bounds) => { + const axisExtentConfig = buildExpressionFunction('axisExtentConfig', { + mode: getMode(scale, bounds), + lowerBound: bounds?.min || scale.min, + upperBound: bounds?.max || scale.max, }); - return buildExpression([timeMarker]); + return buildExpression([axisExtentConfig]); }; -const prepareCategoryAxis = (data: CategoryAxis) => { - const categoryAxis = buildExpressionFunction('categoryaxis', { - id: data.id, - show: data.show, - position: data.position, - type: data.type, +function getScaleType( + scale?: Scale, + isNumber?: boolean, + isTime = false, + isHistogram = false +): ECScaleType | undefined { + if (isTime) return ECScaleType.Time; + if (isHistogram) return ECScaleType.Linear; + + if (!isNumber) { + return ECScaleType.Ordinal; + } + + const type = scale?.type; + if (type === ScaleType.SquareRoot) { + return ECScaleType.Sqrt; + } + + return type; +} + +function getYAxisPosition(position: Position) { + if (position === Position.Top) { + return Position.Right; + } + + if (position === Position.Bottom) { + return Position.Left; + } + + return position; +} + +function getXAxisPosition(position: Position) { + if (position === Position.Left) { + return Position.Bottom; + } + + if (position === Position.Right) { + return Position.Top; + } + + return position; +} + +const prepareXAxis = ( + data: CategoryAxis, + showGridLines?: boolean, + bounds?: Bounds, + isTimeChart?: boolean +) => { + const xAxisConfig = buildExpressionFunction('xAxisConfig', { + hide: !data.show, + position: getXAxisPosition(data.position), title: data.title.text, - scale: prepareScale(data.scale), - labels: prepareLabel(data.labels), + extent: prepareAxisExtentConfig(data.scale, bounds), + showGridLines, + ...getLabelArgs(data, isTimeChart), }); - return buildExpression([categoryAxis]); + return buildExpression([xAxisConfig]); }; -const prepareValueAxis = (data: ValueAxis) => { - const categoryAxis = buildExpressionFunction('valueaxis', { - name: data.name, - axisParams: prepareCategoryAxis({ - ...data, - }), +const prepareYAxis = (data: ValueAxis, showGridLines?: boolean) => { + const yAxisConfig = buildExpressionFunction('yAxisConfig', { + id: data.id, + hide: !data.show, + position: getYAxisPosition(data.position), + title: data.title.text, + extent: prepareAxisExtentConfig(data.scale), + boundsMargin: data.scale.boundsMargin, + scaleType: getScaleType(data.scale, true), + mode: data.scale.mode, + showGridLines, + ...getLabelArgs(data), }); - return buildExpression([categoryAxis]); + return buildExpression([yAxisConfig]); +}; + +const getLineStyle = (style: ThresholdLine['style']) => { + switch (style) { + case 'full': + return 'solid'; + case 'dashed': + return 'dashed'; + case 'dot-dashed': + return 'dotted'; + } }; -const prepareSeriesParam = (data: SeriesParam) => { - const seriesParam = buildExpressionFunction('seriesparam', { - label: data.data.label, - id: data.data.id, - drawLinesBetweenPoints: data.drawLinesBetweenPoints, - interpolate: data.interpolate, - lineWidth: data.lineWidth, - mode: data.mode, - show: data.show, - showCircles: data.showCircles, - circlesRadius: data.circlesRadius, - type: data.type, - valueAxis: data.valueAxis, +const prepareReferenceLine = (thresholdLine: ThresholdLine, axisId: string) => { + const referenceLine = buildExpressionFunction('referenceLine', { + value: thresholdLine.value, + color: thresholdLine.color, + lineWidth: thresholdLine.width, + lineStyle: getLineStyle(thresholdLine.style), + axisId, }); - return buildExpression([seriesParam]); + return buildExpression([referenceLine]); }; const prepareVisDimension = (data: Dimension) => { @@ -122,16 +302,8 @@ const prepareVisDimension = (data: Dimension) => { return buildExpression([visDimension]); }; -const prepareXYDimension = (data: Dimension) => { - const xyDimension = buildExpressionFunction('xydimension', { - params: JSON.stringify(data.params), - aggType: data.aggType, - label: data.label, - visDimension: prepareVisDimension(data), - }); - - return buildExpression([xyDimension]); -}; +export const isDateHistogramParams = (params: Dimension['params']): params is DateHistogramParams => + (params as DateHistogramParams).date; export const toExpressionAst: VisToExpressionAst = async (vis, params) => { const schemas = getVisSchemas(vis, params); @@ -158,9 +330,12 @@ export const toExpressionAst: VisToExpressionAst = async (vis, params const finalSeriesParams = updatedSeries ?? vis.params.seriesParams; + let isHistogram = false; + if (dimensions.x) { const xAgg = responseAggs[dimensions.x.accessor] as any; if (xAgg.type.name === BUCKET_TYPES.DATE_HISTOGRAM) { + isHistogram = true; (dimensions.x.params as DateHistogramParams).date = true; const { esUnit, esValue } = xAgg.buckets.getInterval(); (dimensions.x.params as DateHistogramParams).intervalESUnit = esUnit; @@ -178,6 +353,7 @@ export const toExpressionAst: VisToExpressionAst = async (vis, params }; } } else if (xAgg.type.name === BUCKET_TYPES.HISTOGRAM) { + isHistogram = true; const intervalParam = xAgg.type.paramByName('interval'); const output = { params: {} as any }; await intervalParam.modifyAggConfigOnSearchRequestStart(xAgg, vis.data.searchSource, { @@ -209,38 +385,71 @@ export const toExpressionAst: VisToExpressionAst = async (vis, params legendSize = LegendSize.AUTO; } - const visTypeXy = buildExpressionFunction(visName, { - type: vis.type.name as XyVisType, - chartType: vis.params.type, + const yAccessors = (dimensions.y || []).reduce>((acc, yDimension) => { + const yAgg = responseAggs[yDimension.accessor]; + const aggId = getSafeId(yAgg.id); + if (acc[aggId]) { + acc[aggId].push(yDimension); + } else { + acc[aggId] = [yDimension]; + } + return acc; + }, {}); + + const xScale = vis.params.categoryAxes[0].scale; + + const visTypeXy = buildExpressionFunction('layeredXyVis', { + layers: [ + ...finalSeriesParams.map((seriesParam) => + prepareLayers( + seriesParam, + isHistogram, + vis.params.valueAxes, + yAccessors[seriesParam.data.id], + dimensions.x, + dimensions.series, + dimensions.z ? dimensions.z[0] : undefined, + vis.params.palette, + xScale + ) + ), + ...(vis.params.thresholdLine.show + ? [prepareReferenceLine(vis.params.thresholdLine, vis.params.valueAxes[0].id)] + : []), + ], addTimeMarker: vis.params.addTimeMarker, - truncateLegend: vis.params.truncateLegend, - maxLegendLines: vis.params.maxLegendLines, - legendSize, - addLegend: vis.params.addLegend, - addTooltip: vis.params.addTooltip, - legendPosition: vis.params.legendPosition, orderBucketsBySum: vis.params.orderBucketsBySum, - categoryAxes: vis.params.categoryAxes.map(prepareCategoryAxis), - valueAxes: vis.params.valueAxes.map(prepareValueAxis), - seriesParams: finalSeriesParams.map(prepareSeriesParam), - labels: prepareLabel(vis.params.labels), - thresholdLine: prepareThresholdLine(vis.params.thresholdLine), - gridCategoryLines: vis.params.grid.categoryLines, - gridValueAxis: vis.params.grid.valueAxis, - radiusRatio: vis.params.radiusRatio, - isVislibVis: vis.params.isVislibVis, + fittingFunction: vis.params.fittingFunction + ? vis.params.fittingFunction.charAt(0).toUpperCase() + vis.params.fittingFunction.slice(1) + : undefined, detailedTooltip: vis.params.detailedTooltip, - fittingFunction: vis.params.fittingFunction, - times: vis.params.times.map(prepareTimeMarker), - palette: vis.params.palette.name, fillOpacity: vis.params.fillOpacity, - xDimension: dimensions.x ? prepareXYDimension(dimensions.x) : null, - yDimension: dimensions.y.map(prepareXYDimension), - zDimension: dimensions.z?.map(prepareXYDimension), - widthDimension: dimensions.width?.map(prepareXYDimension), - seriesDimension: dimensions.series?.map(prepareXYDimension), - splitRowDimension: dimensions.splitRow?.map(prepareXYDimension), - splitColumnDimension: dimensions.splitColumn?.map(prepareXYDimension), + showTooltip: vis.params.addTooltip, + markSizeRatio: dimensions.z ? vis.params.radiusRatio : undefined, + legend: prepareLengend(vis.params, legendSize), + xAxisConfig: prepareXAxis( + vis.params.categoryAxes[0], + vis.params.grid.categoryLines, + dimensions.x?.params && isDateHistogramParams(dimensions.x?.params) + ? dimensions.x?.params.bounds + : undefined, + dimensions.x?.params && isDateHistogramParams(dimensions.x?.params) + ? dimensions.x?.params.date + : undefined + ), // as we have only one x axis + yAxisConfigs: vis.params.valueAxes + .filter((axis) => finalSeriesParams.some((seriesParam) => seriesParam.valueAxis === axis.id)) + .map((valueAxis) => prepareYAxis(valueAxis, vis.params.grid.valueAxis === valueAxis.id)), + minTimeBarInterval: + dimensions.x?.params && + isDateHistogramParams(dimensions.x?.params) && + dimensions.x?.params.date && + finalSeriesParams.some((param) => param.type === ChartType.Histogram) + ? dimensions.x?.params.intervalESValue + dimensions.x?.params.intervalESUnit + : undefined, + splitColumnAccessor: dimensions.splitColumn?.map(prepareVisDimension), + splitRowAccessor: dimensions.splitRow?.map(prepareVisDimension), + handleEmptyXAccessor: true, }); const ast = buildExpression([visTypeXy]); diff --git a/x-pack/plugins/lens/public/xy_visualization/to_expression.ts b/x-pack/plugins/lens/public/xy_visualization/to_expression.ts index 6c06891f530e0..e2689ca49c324 100644 --- a/x-pack/plugins/lens/public/xy_visualization/to_expression.ts +++ b/x-pack/plugins/lens/public/xy_visualization/to_expression.ts @@ -295,7 +295,6 @@ export const buildExpression = ( fittingFunction: [state.fittingFunction || 'None'], endValue: [state.endValue || 'None'], emphasizeFitting: [state.emphasizeFitting || false], - curveType: [state.curveType || 'LINEAR'], fillOpacity: [state.fillOpacity || 0.3], valueLabels: [state?.valueLabels || 'hide'], hideEndzones: [state?.hideEndzones || false], @@ -330,7 +329,8 @@ export const buildExpression = ( datasourceLayers[layer.layerId], metadata, paletteService, - datasourceExpressionsByLayers[layer.layerId] + datasourceExpressionsByLayers[layer.layerId], + state.curveType || 'LINEAR' ) ), ...validReferenceLayers.map((layer) => @@ -428,7 +428,8 @@ const dataLayerToExpression = ( datasourceLayer: DatasourcePublicAPI, metadata: Record>, paletteService: PaletteRegistry, - datasourceExpression: Ast + datasourceExpression: Ast, + curveType: any ): Ast => { const columnToLabel = getColumnToLabelMap(layer, datasourceLayer); @@ -450,6 +451,24 @@ const dataLayerToExpression = ( return { type: 'expression', chain: [ + ...(datasourceExpression + ? [ + ...datasourceExpression.chain, + ...(layer.collapseFn + ? [ + { + type: 'function', + function: 'lens_collapse', + arguments: { + by: layer.xAccessor ? [layer.xAccessor] : [], + metric: layer.accessors, + fn: [layer.collapseFn!], + }, + } as AstFunction, + ] + : []), + ] + : []), { type: 'function', function: 'extendedDataLayer', @@ -468,34 +487,10 @@ const dataLayerToExpression = ( yConfigToDataDecorationConfigExpression(yConfig, yAxisConfigs) ) : [], + curveType: [curveType], seriesType: [seriesType], accessors: layer.accessors, columnToLabel: [JSON.stringify(columnToLabel)], - ...(datasourceExpression - ? { - table: [ - { - ...datasourceExpression, - chain: [ - ...datasourceExpression.chain, - ...(layer.collapseFn - ? [ - { - type: 'function', - function: 'lens_collapse', - arguments: { - by: layer.xAccessor ? [layer.xAccessor] : [], - metric: layer.accessors, - fn: [layer.collapseFn!], - }, - } as AstFunction, - ] - : []), - ], - }, - ], - } - : {}), palette: [ { type: 'expression', From ce23d344da957c5f7e5d18ab980ca6fe3f69beed Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Fri, 15 Jul 2022 17:42:44 +0300 Subject: [PATCH 02/27] Add legend toggle and color picker. Some fixes --- .../__snapshots__/xy_chart.test.tsx.snap | 13981 ++++++++-------- .../public/components/data_layers.tsx | 5 +- .../public/components/legend_color_picker.tsx | 103 + .../public/components/xy_chart.test.tsx | 4 +- .../public/components/xy_chart.tsx | 547 +- .../xy_chart_renderer.tsx | 5 +- .../public/helpers/data_layers.tsx | 35 +- src/plugins/vis_types/xy/public/to_ast.ts | 30 +- .../public/xy_visualization/to_expression.ts | 3 +- 9 files changed, 7104 insertions(+), 7609 deletions(-) create mode 100644 src/plugins/chart_expressions/expression_xy/public/components/legend_color_picker.tsx diff --git a/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap b/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap index 24c7d68cd6fda..f761b332562f3 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap +++ b/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap @@ -281,2299 +281,1409 @@ Array [ `; exports[`XYChart component it renders area 1`] = ` - - - } - onBrushEnd={[Function]} - onElementClick={[Function]} - onPointerUpdate={[Function]} - onRenderChange={[Function]} - rotation={0} - showLegend={false} - showLegendExtra={false} - theme={ - Object { - "background": Object { - "color": undefined, - }, - "barSeriesStyle": Object {}, - "chartMargins": Object {}, - "legend": Object { - "labelOptions": Object { - "maxLines": 0, - }, - }, - "markSizeRatio": undefined, - } - } - tooltip={ - Object { - "boundary": undefined, - "customTooltip": undefined, - "headerFormatter": [Function], - "type": "vertical", - } - } - /> - - - - - - -`; - -exports[`XYChart component it renders bar 1`] = ` - - - } - onBrushEnd={[Function]} - onElementClick={[Function]} - onPointerUpdate={[Function]} - onRenderChange={[Function]} - rotation={0} - showLegend={false} - showLegendExtra={false} - theme={ - Object { - "background": Object { - "color": undefined, - }, - "barSeriesStyle": Object {}, - "chartMargins": Object {}, - "legend": Object { - "labelOptions": Object { - "maxLines": 0, - }, - }, - "markSizeRatio": undefined, - } - } - tooltip={ - Object { - "boundary": undefined, - "customTooltip": undefined, - "headerFormatter": [Function], - "type": "vertical", - } - } - /> - - - - - + + + + } + onBrushEnd={[Function]} + onElementClick={[Function]} + onPointerUpdate={[Function]} + onRenderChange={[Function]} + rotation={0} + showLegend={false} + showLegendExtra={false} + theme={ + Object { + "background": Object { + "color": undefined, }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Object { - "convert": [MockFunction] { - "calls": Array [ - Array [ - 1652034840000, - ], - Array [ - 1652122440000, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": 1652034840000, - }, - Object { - "type": "return", - "value": 1652122440000, - }, - ], + "barSeriesStyle": Object {}, + "chartMargins": Object {}, + "legend": Object { + "labelOptions": Object { + "maxLines": 0, }, }, - }, + "markSizeRatio": undefined, + } + } + tooltip={ Object { - "type": "return", - "value": Object { - "convert": [MockFunction] { - "calls": Array [ - Array [ - 1652034840000, - ], - Array [ - 1652122440000, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": 1652034840000, - }, - Object { - "type": "return", - "value": 1652122440000, - }, - ], - }, - }, - }, + "boundary": undefined, + "customTooltip": undefined, + "headerFormatter": [Function], + "type": "vertical", + } + } + /> + + + + + - -`; - -exports[`XYChart component it renders horizontal bar 1`] = ` - - - } - onBrushEnd={[Function]} - onElementClick={[Function]} - onPointerUpdate={[Function]} - onRenderChange={[Function]} - rotation={90} - showLegend={false} - showLegendExtra={false} - theme={ - Object { - "background": Object { - "color": undefined, - }, - "barSeriesStyle": Object {}, - "chartMargins": Object {}, - "legend": Object { - "labelOptions": Object { - "maxLines": 0, - }, - }, - "markSizeRatio": undefined, - } - } - tooltip={ - Object { - "boundary": undefined, - "customTooltip": undefined, - "headerFormatter": [Function], - "type": "vertical", - } - } - /> - - - - - + + + +`; + +exports[`XYChart component it renders bar 1`] = ` + + + + + } + onBrushEnd={[Function]} + onElementClick={[Function]} + onPointerUpdate={[Function]} + onRenderChange={[Function]} + rotation={0} + showLegend={false} + showLegendExtra={false} + theme={ + Object { + "background": Object { + "color": undefined, + }, + "barSeriesStyle": Object {}, + "chartMargins": Object {}, + "legend": Object { + "labelOptions": Object { + "maxLines": 0, + }, + }, + "markSizeRatio": undefined, + } + } + tooltip={ + Object { + "boundary": undefined, + "customTooltip": undefined, + "headerFormatter": [Function], + "type": "vertical", + } + } + /> + + + + + - -`; - -exports[`XYChart component it renders line 1`] = ` - - - } - onBrushEnd={[Function]} - onElementClick={[Function]} - onPointerUpdate={[Function]} - onRenderChange={[Function]} - rotation={0} - showLegend={false} - showLegendExtra={false} - theme={ - Object { - "background": Object { - "color": undefined, - }, - "barSeriesStyle": Object {}, - "chartMargins": Object {}, - "legend": Object { - "labelOptions": Object { - "maxLines": 0, - }, - }, - "markSizeRatio": undefined, - } - } - tooltip={ - Object { - "boundary": undefined, - "customTooltip": undefined, - "headerFormatter": [Function], - "type": "vertical", - } - } - /> - - - - - + + + +`; + +exports[`XYChart component it renders horizontal bar 1`] = ` + + + + + } + onBrushEnd={[Function]} + onElementClick={[Function]} + onPointerUpdate={[Function]} + onRenderChange={[Function]} + rotation={90} + showLegend={false} + showLegendExtra={false} + theme={ + Object { + "background": Object { + "color": undefined, }, - ], - Array [ - Object { - "id": "number", - "params": Object { - "pattern": "0,0.000", + "barSeriesStyle": Object {}, + "chartMargins": Object {}, + "legend": Object { + "labelOptions": Object { + "maxLines": 0, }, }, - ], - Array [ - Object { - "id": "number", - "params": Object { - "pattern": "0,0.000", - }, + "markSizeRatio": undefined, + } + } + tooltip={ + Object { + "boundary": undefined, + "customTooltip": undefined, + "headerFormatter": [Function], + "type": "vertical", + } + } + /> + + + + + - -`; - -exports[`XYChart component it renders stacked area 1`] = ` - - - } - onBrushEnd={[Function]} - onElementClick={[Function]} - onPointerUpdate={[Function]} - onRenderChange={[Function]} - rotation={0} - showLegend={false} - showLegendExtra={false} - theme={ - Object { - "background": Object { - "color": undefined, - }, - "barSeriesStyle": Object {}, - "chartMargins": Object {}, - "legend": Object { - "labelOptions": Object { - "maxLines": 0, - }, - }, - "markSizeRatio": undefined, - } - } - tooltip={ - Object { - "boundary": undefined, - "customTooltip": undefined, - "headerFormatter": [Function], - "type": "vertical", - } - } - /> - - - - - + + + +`; + +exports[`XYChart component it renders line 1`] = ` + + + + + } + onBrushEnd={[Function]} + onElementClick={[Function]} + onPointerUpdate={[Function]} + onRenderChange={[Function]} + rotation={0} + showLegend={false} + showLegendExtra={false} + theme={ + Object { + "background": Object { + "color": undefined, + }, + "barSeriesStyle": Object {}, + "chartMargins": Object {}, + "legend": Object { + "labelOptions": Object { + "maxLines": 0, }, }, - }, + "markSizeRatio": undefined, + } + } + tooltip={ Object { - "type": "return", - "value": Object { - "convert": [MockFunction] { - "calls": Array [ - Array [ - 1652034840000, - ], - Array [ - 1652122440000, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": 1652034840000, - }, - Object { - "type": "return", - "value": 1652122440000, - }, - ], - }, + "boundary": undefined, + "customTooltip": undefined, + "headerFormatter": [Function], + "type": "vertical", + } + } + /> + + + + + - -`; - -exports[`XYChart component it renders stacked bar 1`] = ` - - - } - onBrushEnd={[Function]} - onElementClick={[Function]} - onPointerUpdate={[Function]} - onRenderChange={[Function]} - rotation={0} - showLegend={false} - showLegendExtra={false} - theme={ - Object { - "background": Object { - "color": undefined, - }, - "barSeriesStyle": Object {}, - "chartMargins": Object {}, - "legend": Object { - "labelOptions": Object { - "maxLines": 0, - }, - }, - "markSizeRatio": undefined, - } - } - tooltip={ - Object { - "boundary": undefined, - "customTooltip": undefined, - "headerFormatter": [Function], - "type": "vertical", - } - } - /> - - - - - + + + +`; + +exports[`XYChart component it renders stacked area 1`] = ` + + + + + } + onBrushEnd={[Function]} + onElementClick={[Function]} + onPointerUpdate={[Function]} + onRenderChange={[Function]} + rotation={0} + showLegend={false} + showLegendExtra={false} + theme={ + Object { + "background": Object { + "color": undefined, }, - ], - Array [ - Object { - "id": "number", - "params": Object { - "pattern": "000,0", + "barSeriesStyle": Object {}, + "chartMargins": Object {}, + "legend": Object { + "labelOptions": Object { + "maxLines": 0, }, }, - ], - Array [ - Object { - "id": "string", - }, - ], - Array [ - Object { - "id": "string", - }, - ], - Array [ - Object { - "id": "string", - }, - ], - Array [ - Object { - "id": "string", + "markSizeRatio": undefined, + } + } + tooltip={ + Object { + "boundary": undefined, + "customTooltip": undefined, + "headerFormatter": [Function], + "type": "vertical", + } + } + /> + + + + + - -`; - -exports[`XYChart component it renders stacked horizontal bar 1`] = ` - - - } - onBrushEnd={[Function]} - onElementClick={[Function]} - onPointerUpdate={[Function]} - onRenderChange={[Function]} - rotation={90} - showLegend={false} - showLegendExtra={false} - theme={ - Object { - "background": Object { - "color": undefined, - }, - "barSeriesStyle": Object {}, - "chartMargins": Object {}, - "legend": Object { - "labelOptions": Object { - "maxLines": 0, - }, - }, - "markSizeRatio": undefined, - } - } - tooltip={ - Object { - "boundary": undefined, - "customTooltip": undefined, - "headerFormatter": [Function], - "type": "vertical", - } - } - /> - - - - - + + + +`; + +exports[`XYChart component it renders stacked bar 1`] = ` + + + + + } + onBrushEnd={[Function]} + onElementClick={[Function]} + onPointerUpdate={[Function]} + onRenderChange={[Function]} + rotation={0} + showLegend={false} + showLegendExtra={false} + theme={ + Object { + "background": Object { + "color": undefined, }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Object { - "convert": [MockFunction] { - "calls": Array [ - Array [ - 1652034840000, - ], - Array [ - 1652122440000, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": 1652034840000, - }, - Object { - "type": "return", - "value": 1652122440000, - }, - ], + "barSeriesStyle": Object {}, + "chartMargins": Object {}, + "legend": Object { + "labelOptions": Object { + "maxLines": 0, }, }, - }, + "markSizeRatio": undefined, + } + } + tooltip={ Object { - "type": "return", - "value": Object { - "convert": [MockFunction] { - "calls": Array [ - Array [ - 1652034840000, - ], - Array [ - 1652122440000, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": 1652034840000, - }, - Object { - "type": "return", - "value": 1652122440000, - }, - ], - }, - }, - }, + "boundary": undefined, + "customTooltip": undefined, + "headerFormatter": [Function], + "type": "vertical", + } + } + /> + + + + + - -`; - -exports[`XYChart component split chart should render split chart if both, splitRowAccessor and splitColumnAccessor are specified 1`] = ` - - - } - onBrushEnd={[Function]} - onElementClick={[Function]} - onPointerUpdate={[Function]} - onRenderChange={[Function]} - rotation={0} - showLegend={false} - showLegendExtra={false} - theme={ - Object { - "background": Object { - "color": undefined, - }, - "barSeriesStyle": Object {}, - "chartMargins": Object {}, - "legend": Object { - "labelOptions": Object { - "maxLines": 0, - }, - }, - "markSizeRatio": undefined, - } - } - tooltip={ - Object { - "boundary": undefined, - "customTooltip": undefined, - "headerFormatter": [Function], - "type": "vertical", - } - } - /> - - - - - - + + + +`; + +exports[`XYChart component it renders stacked horizontal bar 1`] = ` + + + + + } + onBrushEnd={[Function]} + onElementClick={[Function]} + onPointerUpdate={[Function]} + onRenderChange={[Function]} + rotation={90} + showLegend={false} + showLegendExtra={false} + theme={ + Object { + "background": Object { + "color": undefined, }, - ], - Array [ - Object { - "id": "number", - "params": Object { - "pattern": "0,0.000", + "barSeriesStyle": Object {}, + "chartMargins": Object {}, + "legend": Object { + "labelOptions": Object { + "maxLines": 0, }, }, - ], - Array [ - Object { - "id": "number", - "params": Object { - "pattern": "0,0.000", - }, + "markSizeRatio": undefined, + } + } + tooltip={ + Object { + "boundary": undefined, + "customTooltip": undefined, + "headerFormatter": [Function], + "type": "vertical", + } + } + /> + + + + + - -`; - -exports[`XYChart component split chart should render split chart if splitColumnAccessor is specified 1`] = ` - - - } - onBrushEnd={[Function]} - onElementClick={[Function]} - onPointerUpdate={[Function]} - onRenderChange={[Function]} - rotation={0} - showLegend={false} - showLegendExtra={false} - theme={ - Object { - "background": Object { - "color": undefined, - }, - "barSeriesStyle": Object {}, - "chartMargins": Object {}, - "legend": Object { - "labelOptions": Object { - "maxLines": 0, - }, - }, - "markSizeRatio": undefined, - } - } - tooltip={ - Object { - "boundary": undefined, - "customTooltip": undefined, - "headerFormatter": [Function], - "type": "vertical", - } - } - /> - - - - - - + + + +`; + +exports[`XYChart component split chart should render split chart if both, splitRowAccessor and splitColumnAccessor are specified 1`] = ` + + + + + } + onBrushEnd={[Function]} + onElementClick={[Function]} + onPointerUpdate={[Function]} + onRenderChange={[Function]} + rotation={0} + showLegend={false} + showLegendExtra={false} + theme={ + Object { + "background": Object { + "color": undefined, }, - ], - Array [ - Object { - "id": "number", - "params": Object { - "pattern": "000,0", + "barSeriesStyle": Object {}, + "chartMargins": Object {}, + "legend": Object { + "labelOptions": Object { + "maxLines": 0, }, }, - ], - Array [ - Object { - "id": "string", - }, - ], - Array [ - Object { - "id": "string", - }, - ], - Array [ - Object { - "id": "string", + "markSizeRatio": undefined, + } + } + tooltip={ + Object { + "boundary": undefined, + "customTooltip": undefined, + "headerFormatter": [Function], + "type": "vertical", + } + } + /> + + + + + + - + ] + } + /> + + + `; -exports[`XYChart component split chart should render split chart if splitRowAccessor is specified 1`] = ` - - - } - onBrushEnd={[Function]} - onElementClick={[Function]} - onPointerUpdate={[Function]} - onRenderChange={[Function]} - rotation={0} - showLegend={false} - showLegendExtra={false} - theme={ - Object { - "background": Object { - "color": undefined, - }, - "barSeriesStyle": Object {}, - "chartMargins": Object {}, - "legend": Object { - "labelOptions": Object { - "maxLines": 0, - }, - }, - "markSizeRatio": undefined, - } - } - tooltip={ - Object { - "boundary": undefined, - "customTooltip": undefined, - "headerFormatter": [Function], - "type": "vertical", - } - } - /> - - - + + + + } + onBrushEnd={[Function]} + onElementClick={[Function]} + onPointerUpdate={[Function]} + onRenderChange={[Function]} + rotation={0} + showLegend={false} + showLegendExtra={false} + theme={ + Object { + "background": Object { + "color": undefined, + }, + "barSeriesStyle": Object {}, + "chartMargins": Object {}, + "legend": Object { + "labelOptions": Object { + "maxLines": 0, }, }, - "type": "number", - }, - "name": "b", - }, - Object { - "id": "c", - "meta": Object { - "field": "order_date", - "params": Object { - "id": "string", + "markSizeRatio": undefined, + } + } + tooltip={ + Object { + "boundary": undefined, + "customTooltip": undefined, + "headerFormatter": [Function], + "type": "vertical", + } + } + /> + + + + + + - - - + + + +`; + +exports[`XYChart component split chart should render split chart if splitRowAccessor is specified 1`] = ` + + + + + } + onBrushEnd={[Function]} + onElementClick={[Function]} + onPointerUpdate={[Function]} + onRenderChange={[Function]} + rotation={0} + showLegend={false} + showLegendExtra={false} + theme={ + Object { + "background": Object { + "color": undefined, }, - ], - Array [ - Object { - "id": "number", - "params": Object { - "pattern": "000,0", + "barSeriesStyle": Object {}, + "chartMargins": Object {}, + "legend": Object { + "labelOptions": Object { + "maxLines": 0, }, }, - ], - Array [ - Object { - "id": "string", - }, - ], - Array [ - Object { - "id": "string", - }, - ], - Array [ - Object { - "id": "string", - }, - ], - Array [ - Object { - "id": "string", + "markSizeRatio": undefined, + } + } + tooltip={ + Object { + "boundary": undefined, + "customTooltip": undefined, + "headerFormatter": [Function], + "type": "vertical", + } + } + /> + + + + + + - + ] + } + /> + + + `; diff --git a/src/plugins/chart_expressions/expression_xy/public/components/data_layers.tsx b/src/plugins/chart_expressions/expression_xy/public/components/data_layers.tsx index b8f2bca232c49..6ea40b99e701d 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/data_layers.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/data_layers.tsx @@ -16,7 +16,7 @@ import React, { FC } from 'react'; import { PaletteRegistry } from '@kbn/coloring'; import { FormatFactory } from '@kbn/field-formats-plugin/common'; import { getAccessorByDimension } from '@kbn/visualizations-plugin/common/utils'; - +import { PersistedState } from '@kbn/visualizations-plugin/public'; import { CommonXYDataLayerConfig, EndValue, @@ -54,6 +54,7 @@ interface Props { defaultXScaleType: XScaleType; fieldFormats: LayersFieldFormats; handleEmptyXAccessor?: boolean; + uiState?: PersistedState; } export const DataLayers: FC = ({ @@ -75,6 +76,7 @@ export const DataLayers: FC = ({ defaultXScaleType, fieldFormats, handleEmptyXAccessor, + uiState, }) => { const colorAssignments = getColorAssignments(layers, titles, fieldFormats, formattedDatatables); return ( @@ -118,6 +120,7 @@ export const DataLayers: FC = ({ defaultXScaleType, fieldFormats, handleEmptyXAccessor, + uiState, }); const index = `${layer.layerId}-${accessorIndex}`; diff --git a/src/plugins/chart_expressions/expression_xy/public/components/legend_color_picker.tsx b/src/plugins/chart_expressions/expression_xy/public/components/legend_color_picker.tsx new file mode 100644 index 0000000000000..099e9eeae0e73 --- /dev/null +++ b/src/plugins/chart_expressions/expression_xy/public/components/legend_color_picker.tsx @@ -0,0 +1,103 @@ +/* + * 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 React, { createContext, useCallback, useContext } from 'react'; +import { LegendColorPicker, Position } from '@elastic/charts'; +import { PopoverAnchorPosition, EuiWrappingPopover, EuiOutsideClickDetector } from '@elastic/eui'; +import type { PersistedState } from '@kbn/visualizations-plugin/public'; +import { ColorPicker } from '@kbn/charts-plugin/public'; + +const KEY_CODE_ENTER = 13; + +function getAnchorPosition(legendPosition: Position): PopoverAnchorPosition { + switch (legendPosition) { + case Position.Bottom: + return 'upCenter'; + case Position.Top: + return 'downCenter'; + case Position.Left: + return 'rightCenter'; + default: + return 'leftCenter'; + } +} + +export interface LegendColorPickerWrapperContextType { + legendPosition: Position; + setColor: (newColor: string | null, seriesKey: string | number) => void; + uiState?: PersistedState; +} + +export const LegendColorPickerWrapperContext = createContext< + LegendColorPickerWrapperContextType | undefined +>(undefined); + +export const LegendColorPickerWrapper: LegendColorPicker = ({ + anchor, + color, + onClose, + onChange, + seriesIdentifiers: [seriesIdentifier], +}) => { + const colorPickerWrappingContext = useContext(LegendColorPickerWrapperContext); + const handleOutsideClick = useCallback(() => { + onClose?.(); + }, [onClose]); + + if (!colorPickerWrappingContext) { + return null; + } + + const { legendPosition, setColor, uiState } = colorPickerWrappingContext; + const seriesName = seriesIdentifier.key; + + const overwriteColors: Record = uiState?.get('vis.colors', {}) ?? {}; + const colorIsOverwritten = seriesName.toString() in overwriteColors; + let keyDownEventOn = false; + + const handleChange = (newColor: string | null) => { + if (newColor) { + onChange(newColor); + } + setColor(newColor, seriesName); + // close the popover if no color is applied or the user has clicked a color + if (!newColor || !keyDownEventOn) { + onClose(); + } + }; + + const onKeyDown = (e: React.KeyboardEvent) => { + if (e.keyCode === KEY_CODE_ENTER) { + onClose?.(); + } + keyDownEventOn = true; + }; + + return ( + + + + + + ); +}; diff --git a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.test.tsx b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.test.tsx index d09eedfaaf7b7..03361a9383632 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.test.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.test.tsx @@ -421,7 +421,7 @@ describe('XYChart component', () => { expect(component.find(Settings).prop('xDomain')).toEqual({ // shortened to 24th midnight (elastic-charts automatically adds one min interval) - max: new Date('2021-04-24').valueOf(), + max: new Date('2021-04-25').valueOf(), // extended to 22nd midnight because of first bucket min: new Date('2021-04-22').valueOf(), minInterval: 24 * 60 * 60 * 1000, @@ -446,7 +446,7 @@ describe('XYChart component', () => { domainStart: new Date('2021-04-22T12:00:00.000Z').valueOf(), domainEnd: new Date('2021-04-24T12:00:00.000Z').valueOf(), domainMin: new Date('2021-04-22').valueOf(), - domainMax: new Date('2021-04-24').valueOf(), + domainMax: new Date('2021-04-25').valueOf(), }) ); }); diff --git a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx index 07f161e7a6080..73c98d479f9a9 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx @@ -6,7 +6,8 @@ * Side Public License, v 1. */ -import React, { useCallback, useMemo, useRef } from 'react'; +import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import { css } from '@emotion/react'; import { Chart, Settings, @@ -32,7 +33,7 @@ import { IconType } from '@elastic/eui'; import { PaletteRegistry } from '@kbn/coloring'; import { RenderMode } from '@kbn/expressions-plugin/common'; import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; -import { EmptyPlaceholder } from '@kbn/charts-plugin/public'; +import { EmptyPlaceholder, LegendToggle } from '@kbn/charts-plugin/public'; import { EventAnnotationServiceType } from '@kbn/event-annotation-plugin/public'; import { ChartsPluginSetup, ChartsPluginStart, useActiveCursor } from '@kbn/charts-plugin/public'; import { MULTILAYER_TIME_AXIS_STYLE } from '@kbn/charts-plugin/common'; @@ -44,6 +45,7 @@ import { DEFAULT_LEGEND_SIZE, LegendSizeToPixels, } from '@kbn/visualizations-plugin/common/constants'; +import { PersistedState } from '@kbn/visualizations-plugin/public'; import type { FilterEvent, BrushEvent, FormatFactory } from '../types'; import { isTimeChart } from '../../common/helpers'; import type { @@ -97,6 +99,7 @@ import { XYCurrentTime } from './xy_current_time'; import './xy_chart.scss'; import { TooltipHeader } from './tooltip'; +import { LegendColorPickerWrapperContext, LegendColorPickerWrapper } from './legend_color_picker'; declare global { interface Window { @@ -124,6 +127,7 @@ export type XYChartRenderProps = XYChartProps & { syncTooltips: boolean; eventAnnotationService: EventAnnotationServiceType; renderComplete: () => void; + uiState?: PersistedState; }; function getValueLabelsStyling(isHorizontal: boolean): { @@ -177,6 +181,7 @@ export function XYChart({ syncTooltips, useLegacyTimeAxis, renderComplete, + uiState, }: XYChartRenderProps) { const { legend, @@ -202,6 +207,49 @@ export function XYChart({ (hashMap, layer) => ({ ...hashMap, [layer.layerId]: layer }), {} ); + const chartHasMoreThanOneSeries = + filteredLayers.length > 1 || + filteredLayers.some((layer) => layer.accessors.length > 1) || + filteredLayers.some( + (layer) => isDataLayer(layer) && layer.splitAccessors && layer.splitAccessors.length + ); + + const getShowLegendDefault = useCallback(() => { + const legendStateDefault = + legend.isVisible && !legend.showSingleSeries ? chartHasMoreThanOneSeries : legend.isVisible; + return uiState?.get('vis.legendOpen', legendStateDefault) || legendStateDefault; + }, [chartHasMoreThanOneSeries, legend.isVisible, legend.showSingleSeries, uiState]); + + const [showLegend, setShowLegend] = useState(() => getShowLegendDefault()); + + useEffect(() => { + const legendShow = getShowLegendDefault(); + setShowLegend(legendShow); + }, [getShowLegendDefault]); + + const toggleLegend = useCallback(() => { + setShowLegend((value) => { + const newValue = !value; + uiState?.set?.('vis.legendOpen', newValue); + return newValue; + }); + }, [uiState]); + + const setColor = useCallback( + (newColor: string | null, seriesLabel: string | number) => { + const colors = uiState?.get('vis.colors') || {}; + if (colors[seriesLabel] === newColor || !newColor) { + delete colors[seriesLabel]; + } else { + colors[seriesLabel] = newColor; + } + uiState?.setSilent('vis.colors', null); + uiState?.set('vis.colors', colors); + uiState?.emit('reload'); + uiState?.emit('colorChanged'); + }, + [uiState] + ); const handleCursorUpdate = useActiveCursor(chartsActiveCursorService, chartRef, { datatables: filteredLayers.map(({ table }) => table), @@ -250,12 +298,6 @@ export function XYChart({ ? String(value) : String(xAxisFormatter.convert(value)); - const chartHasMoreThanOneSeries = - filteredLayers.length > 1 || - filteredLayers.some((layer) => layer.accessors.length > 1) || - filteredLayers.some( - (layer) => isDataLayer(layer) && layer.splitAccessors && layer.splitAccessors.length - ); const shouldRotate = isHorizontalChart(dataLayers); const yAxesConfiguration = getAxesConfiguration( @@ -631,251 +673,272 @@ export function XYChart({ splitRowAccessor && splitTable ? getAccessorByDimension(splitRowAccessor, splitTable?.columns) : undefined; - const splitLayerFieldFormats = fieldFormats[dataLayers[0].layerId]; - const splitFieldFormats = { - ...(splitColumnId - ? { [splitColumnId]: splitLayerFieldFormats.splitColumnAccessors[splitColumnId] } - : {}), - ...(splitRowId ? { [splitRowId]: splitLayerFieldFormats.splitRowAccessors[splitRowId] } : {}), - }; + + const chartContainerStyle = css({ + width: '100%', + height: '100%', + overflowX: 'hidden', + position: uiState ? 'absolute' : 'relative', + }); return ( - - - } - onRenderChange={onRenderChange} - onPointerUpdate={handleCursorUpdate} - externalPointerEvents={{ - tooltip: { visible: syncTooltips, placement: Placement.Right }, - }} - debugState={window._echDebugStateFlag ?? false} - showLegend={ - legend.isVisible && !legend.showSingleSeries - ? chartHasMoreThanOneSeries - : legend.isVisible - } - legendPosition={legend?.isInside ? legendInsideParams : legend.position} - legendSize={LegendSizeToPixels[legend.legendSize ?? DEFAULT_LEGEND_SIZE]} - theme={{ - ...chartTheme, - barSeriesStyle: { - ...chartTheme.barSeriesStyle, - ...valueLabelsStyling, - }, - background: { - color: undefined, // removes background for embeddables - }, - legend: { - labelOptions: { maxLines: legend.shouldTruncate ? legend?.maxLines ?? 1 : 0 }, - }, - // if not title or labels are shown for axes, add some padding if required by reference line markers - chartMargins: { - ...chartTheme.chartPaddings, - ...computeChartMargins( - linesPaddings, - { ...tickLabelsVisibilitySettings, x: xAxisConfig?.showLabels }, - { ...axisTitlesVisibilitySettings, x: xAxisConfig?.showTitle }, - yAxesMap, - shouldRotate - ), - }, - markSizeRatio: args.markSizeRatio, - }} - baseTheme={chartBaseTheme} - tooltip={{ - boundary: document.getElementById('app-fixed-viewport') ?? undefined, - headerFormatter: !args.detailedTooltip - ? ({ value }) => ( - - ) - : undefined, - customTooltip: args.detailedTooltip - ? ({ header, values }) => ( - - ) - : undefined, - type: args.showTooltip ? TooltipType.VerticalCursor : TooltipType.None, - }} - allowBrushingLastHistogramBin={isTimeViz} - rotation={shouldRotate ? 90 : 0} - xDomain={xDomain} - onBrushEnd={interactive ? (brushHandler as BrushEndListener) : undefined} - onElementClick={interactive ? clickHandler : undefined} - legendAction={ - interactive - ? getLegendAction(dataLayers, onClickValue, fieldFormats, formattedDatatables, titles) - : undefined - } - showLegendExtra={isHistogramViz && valuesInLegend} - ariaLabel={args.ariaLabel} - ariaUseDefaultSummary={!args.ariaLabel} - orderOrdinalBinsBy={ - args.orderBucketsBySum - ? { - direction: Direction.Descending, - } - : undefined - } - /> - - - { - let value = safeXAccessorLabelRenderer(d) || ''; - if (xAxisConfig?.truncate && value.length > xAxisConfig.truncate) { - value = `${value.slice(0, xAxisConfig.truncate)}...`; - } - return value; - }} - style={xAxisStyle} - showOverlappingLabels={xAxisConfig?.showOverlappingLabels} - showDuplicatedTicks={xAxisConfig?.showDuplicates} - timeAxisLayerCount={shouldUseNewTimeAxis ? 3 : 0} - /> - {isSplitChart && splitTable && ( - + {showLegend !== undefined && uiState && ( + )} - {yAxesConfiguration.map((axis) => { - return ( - + + + } + onRenderChange={onRenderChange} + onPointerUpdate={handleCursorUpdate} + externalPointerEvents={{ + tooltip: { visible: syncTooltips, placement: Placement.Right }, }} - hide={axis.hide || dataLayers[0]?.simpleView} + legendColorPicker={uiState ? LegendColorPickerWrapper : undefined} + debugState={window._echDebugStateFlag ?? false} + showLegend={showLegend} + legendPosition={legend?.isInside ? legendInsideParams : legend.position} + legendSize={LegendSizeToPixels[legend.legendSize ?? DEFAULT_LEGEND_SIZE]} + theme={{ + ...chartTheme, + barSeriesStyle: { + ...chartTheme.barSeriesStyle, + ...valueLabelsStyling, + }, + background: { + color: undefined, // removes background for embeddables + }, + legend: { + labelOptions: { maxLines: legend.shouldTruncate ? legend?.maxLines ?? 1 : 0 }, + }, + // if not title or labels are shown for axes, add some padding if required by reference line markers + chartMargins: { + ...chartTheme.chartPaddings, + ...computeChartMargins( + linesPaddings, + { ...tickLabelsVisibilitySettings, x: xAxisConfig?.showLabels }, + { ...axisTitlesVisibilitySettings, x: xAxisConfig?.showTitle }, + yAxesMap, + shouldRotate + ), + }, + markSizeRatio: args.markSizeRatio, + }} + baseTheme={chartBaseTheme} + tooltip={{ + boundary: document.getElementById('app-fixed-viewport') ?? undefined, + headerFormatter: !args.detailedTooltip + ? ({ value }) => ( + + ) + : undefined, + customTooltip: args.detailedTooltip + ? ({ header, values }) => ( + + ) + : undefined, + type: args.showTooltip ? TooltipType.VerticalCursor : TooltipType.None, + }} + allowBrushingLastHistogramBin={isTimeViz} + rotation={shouldRotate ? 90 : 0} + xDomain={xDomain} + onBrushEnd={interactive ? (brushHandler as BrushEndListener) : undefined} + onElementClick={interactive ? clickHandler : undefined} + legendAction={ + interactive + ? getLegendAction( + dataLayers, + onClickValue, + fieldFormats, + formattedDatatables, + titles + ) + : undefined + } + showLegendExtra={isHistogramViz && valuesInLegend} + ariaLabel={args.ariaLabel} + ariaUseDefaultSummary={!args.ariaLabel} + orderOrdinalBinsBy={ + args.orderBucketsBySum + ? { + direction: Direction.Descending, + } + : undefined + } + /> + + + { - let value = axis.formatter?.convert(d) || ''; - if (axis.truncate && value.length > axis.truncate) { - value = `${value.slice(0, axis.truncate)}...`; + let value = safeXAccessorLabelRenderer(d) || ''; + if (xAxisConfig?.truncate && value.length > xAxisConfig.truncate) { + value = `${value.slice(0, xAxisConfig.truncate)}...`; } return value; }} - style={getYAxesStyle(axis)} - domain={getYAxisDomain(axis)} - showOverlappingLabels={axis.showOverlappingLabels} - showDuplicatedTicks={axis.showDuplicates} - ticks={5} + style={xAxisStyle} + showOverlappingLabels={xAxisConfig?.showOverlappingLabels} + showDuplicatedTicks={xAxisConfig?.showDuplicates} + timeAxisLayerCount={shouldUseNewTimeAxis ? 3 : 0} /> - ); - })} - - {!hideEndzones && ( - - layer.isHistogram && - (layer.isStacked || !layer.splitAccessors || !layer.splitAccessors.length) && - (layer.isStacked || - layer.seriesType !== SeriesTypes.BAR || - !chartHasMoreThanOneBarSeries) + {isSplitChart && splitTable && ( + + )} + {yAxesConfiguration.map((axis) => { + return ( + { + let value = axis.formatter?.convert(d) || ''; + if (axis.truncate && value.length > axis.truncate) { + value = `${value.slice(0, axis.truncate)}...`; + } + return value; + }} + style={getYAxesStyle(axis)} + domain={getYAxisDomain(axis)} + showOverlappingLabels={axis.showOverlappingLabels} + showDuplicatedTicks={axis.showDuplicates} + ticks={5} + /> + ); + })} + + {!hideEndzones && ( + + layer.isHistogram && + (layer.isStacked || !layer.splitAccessors || !layer.splitAccessors.length) && + (layer.isStacked || + layer.seriesType !== SeriesTypes.BAR || + !chartHasMoreThanOneBarSeries) + )} + /> )} - /> - )} - {dataLayers.length && ( - - )} - {referenceLineLayers.length ? ( - - ) : null} - {rangeAnnotations.length || groupedLineAnnotations.length ? ( - 0} - minInterval={minInterval} - simpleView={annotationsLayers?.[0].simpleView} - outsideDimension={ - rangeAnnotations.length && shouldHideDetails - ? OUTSIDE_RECT_ANNOTATION_WIDTH_SUGGESTION - : shouldUseNewTimeAxis - ? Number(MULTILAYER_TIME_AXIS_STYLE.tickLine?.padding || 0) + - Number(chartTheme.axes?.tickLabel?.fontSize || 0) - : Number(chartTheme.axes?.tickLine?.size) || OUTSIDE_RECT_ANNOTATION_WIDTH - } - /> - ) : null} - + {dataLayers.length && ( + + )} + {referenceLineLayers.length ? ( + + ) : null} + {rangeAnnotations.length || groupedLineAnnotations.length ? ( + 0} + minInterval={minInterval} + simpleView={annotationsLayers?.[0].simpleView} + outsideDimension={ + rangeAnnotations.length && shouldHideDetails + ? OUTSIDE_RECT_ANNOTATION_WIDTH_SUGGESTION + : shouldUseNewTimeAxis + ? Number(MULTILAYER_TIME_AXIS_STYLE.tickLine?.padding || 0) + + Number(chartTheme.axes?.tickLabel?.fontSize || 0) + : Number(chartTheme.axes?.tickLine?.size) || OUTSIDE_RECT_ANNOTATION_WIDTH + } + /> + ) : null} + + +
); } diff --git a/src/plugins/chart_expressions/expression_xy/public/expression_renderers/xy_chart_renderer.tsx b/src/plugins/chart_expressions/expression_xy/public/expression_renderers/xy_chart_renderer.tsx index df870934df159..4746fa9f4aa41 100644 --- a/src/plugins/chart_expressions/expression_xy/public/expression_renderers/xy_chart_renderer.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/expression_renderers/xy_chart_renderer.tsx @@ -13,6 +13,7 @@ import { css } from '@emotion/react'; import React from 'react'; import ReactDOM from 'react-dom'; import type { PaletteRegistry } from '@kbn/coloring'; +import { PersistedState } from '@kbn/visualizations-plugin/public'; import type { ChartsPluginStart } from '@kbn/charts-plugin/public'; import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; import { EventAnnotationServiceType } from '@kbn/event-annotation-plugin/public'; @@ -64,10 +65,9 @@ export const getXyChartRenderer = ({ ]); const chartContainerStyle = css({ + position: 'relative', width: '100%', height: '100%', - overflowX: 'hidden', - position: handlers.uiState ? 'absolute' : 'relative', }); ReactDOM.render( @@ -92,6 +92,7 @@ export const getXyChartRenderer = ({ syncColors={handlers.isSyncColorsEnabled()} syncTooltips={handlers.isSyncTooltipsEnabled()} renderComplete={() => handlers.done()} + uiState={handlers.uiState as PersistedState} />
{' '}
diff --git a/src/plugins/chart_expressions/expression_xy/public/helpers/data_layers.tsx b/src/plugins/chart_expressions/expression_xy/public/helpers/data_layers.tsx index 1dd66c0d85a8d..250893e603a04 100644 --- a/src/plugins/chart_expressions/expression_xy/public/helpers/data_layers.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/helpers/data_layers.tsx @@ -20,6 +20,7 @@ import { import { i18n } from '@kbn/i18n'; import { IFieldFormat } from '@kbn/field-formats-plugin/common'; import { Datatable } from '@kbn/expressions-plugin'; +import type { PersistedState } from '@kbn/visualizations-plugin/public'; import { getAccessorByDimension } from '@kbn/visualizations-plugin/common/utils'; import type { ExpressionValueVisDimension } from '@kbn/visualizations-plugin/common/expression_functions'; import { PaletteRegistry, SeriesLayer } from '@kbn/coloring'; @@ -52,6 +53,7 @@ type GetSeriesPropsFn = (config: { defaultXScaleType: XScaleType; fieldFormats: LayersFieldFormats; handleEmptyXAccessor?: boolean; + uiState?: PersistedState; }) => SeriesSpec; type GetSeriesNameFn = ( @@ -76,7 +78,8 @@ type GetColorFn = ( paletteService: PaletteRegistry; getSeriesNameFn: (d: XYChartSeriesIdentifier) => SeriesName; syncColors?: boolean; - } + }, + uiState?: PersistedState ) => string | null; type GetPointConfigFn = (config: { @@ -291,12 +294,19 @@ const getLineConfig: GetLineConfigFn = ({ showLines, lineWidth }) => ({ const getColor: GetColorFn = ( series, - { layer, accessor, colorAssignments, paletteService, syncColors, getSeriesNameFn } + { layer, accessor, colorAssignments, paletteService, syncColors, getSeriesNameFn }, + uiState ) => { const overwriteColor = getSeriesColor(layer, accessor); if (overwriteColor !== null) { return overwriteColor; } + + const overwriteColors: Record = uiState?.get ? uiState.get('vis.colors', {}) : {}; + + if (Object.keys(overwriteColors).includes(series.key)) { + return overwriteColors[series.key]; + } const colorAssignment = colorAssignments[layer.palette.name]; const name = getSeriesNameFn(series)?.toString() || ''; @@ -362,6 +372,7 @@ export const getSeriesProps: GetSeriesPropsFn = ({ defaultXScaleType, fieldFormats, handleEmptyXAccessor, + uiState, }): SeriesSpec => { const { table, isStacked, markSizeAccessor } = layer; const isPercentage = layer.isPercentage; @@ -466,14 +477,18 @@ export const getSeriesProps: GetSeriesPropsFn = ({ ? ScaleType.LinearBinary : scaleType, color: (series) => - getColor(series, { - layer, - accessor, - colorAssignments, - paletteService, - getSeriesNameFn, - syncColors, - }), + getColor( + series, + { + layer, + accessor, + colorAssignments, + paletteService, + getSeriesNameFn, + syncColors, + }, + uiState + ), groupId: yAxis?.groupId, enableHistogramMode, stackMode, diff --git a/src/plugins/vis_types/xy/public/to_ast.ts b/src/plugins/vis_types/xy/public/to_ast.ts index 635489ba9299a..9cd5bd51fec3d 100644 --- a/src/plugins/vis_types/xy/public/to_ast.ts +++ b/src/plugins/vis_types/xy/public/to_ast.ts @@ -126,7 +126,6 @@ const prepareLayers = ( decorations: yAccessors.map((accessor) => prepareDecoration(seriesParam.valueAxis, accessor, seriesParam.data.id) ), - hide: !seriesParam.show, accessors: yAccessors.map((accessor) => prepareVisDimension(accessor)), xAccessor: xAccessor ? prepareVisDimension(xAccessor) : undefined, xScaleType: getScaleType( @@ -379,6 +378,7 @@ export const toExpressionAst: VisToExpressionAst = async (vis, params } } }); + let legendSize = vis.params.legendSize; if (vis.params.legendPosition === Position.Top || vis.params.legendPosition === Position.Bottom) { @@ -400,19 +400,21 @@ export const toExpressionAst: VisToExpressionAst = async (vis, params const visTypeXy = buildExpressionFunction('layeredXyVis', { layers: [ - ...finalSeriesParams.map((seriesParam) => - prepareLayers( - seriesParam, - isHistogram, - vis.params.valueAxes, - yAccessors[seriesParam.data.id], - dimensions.x, - dimensions.series, - dimensions.z ? dimensions.z[0] : undefined, - vis.params.palette, - xScale - ) - ), + ...finalSeriesParams + .filter((seriesParam) => seriesParam.show) + .map((seriesParam) => + prepareLayers( + seriesParam, + isHistogram, + vis.params.valueAxes, + yAccessors[seriesParam.data.id], + dimensions.x, + dimensions.series, + dimensions.z ? dimensions.z[0] : undefined, + vis.params.palette, + xScale + ) + ), ...(vis.params.thresholdLine.show ? [prepareReferenceLine(vis.params.thresholdLine, vis.params.valueAxes[0].id)] : []), diff --git a/x-pack/plugins/lens/public/xy_visualization/to_expression.ts b/x-pack/plugins/lens/public/xy_visualization/to_expression.ts index e2689ca49c324..3f10854058a84 100644 --- a/x-pack/plugins/lens/public/xy_visualization/to_expression.ts +++ b/x-pack/plugins/lens/public/xy_visualization/to_expression.ts @@ -10,6 +10,7 @@ import { Position, ScaleType } from '@elastic/charts'; import type { PaletteRegistry } from '@kbn/coloring'; import { EventAnnotationServiceType } from '@kbn/event-annotation-plugin/public'; import { LegendSize } from '@kbn/visualizations-plugin/public'; +import { XYCurveType } from '@kbn/expression-xy-plugin/common'; import { State, YConfig, @@ -429,7 +430,7 @@ const dataLayerToExpression = ( metadata: Record>, paletteService: PaletteRegistry, datasourceExpression: Ast, - curveType: any + curveType: XYCurveType ): Ast => { const columnToLabel = getColumnToLabelMap(layer, datasourceLayer); From b5d27c8bedf6cb3b45dd3bb4fdd40cbaf8a4e2f0 Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Fri, 15 Jul 2022 18:31:41 +0300 Subject: [PATCH 03/27] Fix snapshots --- .../__snapshots__/xy_chart.test.tsx.snap | 140 +++++++++++++++--- .../public/__snapshots__/to_ast.test.ts.snap | 59 +------- .../__snapshots__/to_expression.test.ts.snap | 12 +- 3 files changed, 130 insertions(+), 81 deletions(-) diff --git a/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap b/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap index f761b332562f3..204a9d12b04d0 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap +++ b/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap @@ -281,7 +281,17 @@ Array [ `; exports[`XYChart component it renders area 1`] = ` - +
- +
`; exports[`XYChart component it renders bar 1`] = ` - +
- +
`; exports[`XYChart component it renders horizontal bar 1`] = ` - +
- +
`; exports[`XYChart component it renders line 1`] = ` - +
- +
`; exports[`XYChart component it renders stacked area 1`] = ` - +
- +
`; exports[`XYChart component it renders stacked bar 1`] = ` - +
- +
`; exports[`XYChart component it renders stacked horizontal bar 1`] = ` - +
- +
`; exports[`XYChart component split chart should render split chart if both, splitRowAccessor and splitColumnAccessor are specified 1`] = ` - +
- +
`; exports[`XYChart component split chart should render split chart if splitColumnAccessor is specified 1`] = ` - +
- +
`; exports[`XYChart component split chart should render split chart if splitRowAccessor is specified 1`] = ` - +
- +
`; diff --git a/src/plugins/vis_types/xy/public/__snapshots__/to_ast.test.ts.snap b/src/plugins/vis_types/xy/public/__snapshots__/to_ast.test.ts.snap index aa2a68204108a..0d1ea9a54f6e0 100644 --- a/src/plugins/vis_types/xy/public/__snapshots__/to_ast.test.ts.snap +++ b/src/plugins/vis_types/xy/public/__snapshots__/to_ast.test.ts.snap @@ -4,83 +4,38 @@ exports[`xy vis toExpressionAst function should match basic snapshot 1`] = ` Object { "addArgument": [Function], "arguments": Object { - "addLegend": Array [ - true, - ], "addTimeMarker": Array [ false, ], - "addTooltip": Array [ + "handleEmptyXAccessor": Array [ true, ], - "categoryAxes": Array [ - Object { - "toAst": [Function], - }, - ], - "chartType": Array [ - "area", - ], - "gridCategoryLines": Array [ - false, - ], - "labels": Array [ - Object { - "toAst": [Function], - }, - ], - "legendPosition": Array [ - "top", - ], - "legendSize": Array [ - "auto", - ], - "maxLegendLines": Array [ - 1, - ], - "palette": Array [ - "default", - ], - "seriesDimension": Array [ + "layers": Array [ Object { "toAst": [Function], }, ], - "seriesParams": Array [ + "legend": Array [ Object { "toAst": [Function], }, ], - "thresholdLine": Array [ - Object { - "toAst": [Function], - }, - ], - "times": Array [], - "truncateLegend": Array [ + "showTooltip": Array [ true, ], - "type": Array [ - "area", - ], - "valueAxes": Array [ - Object { - "toAst": [Function], - }, - ], - "xDimension": Array [ + "xAxisConfig": Array [ Object { "toAst": [Function], }, ], - "yDimension": Array [ + "yAxisConfigs": Array [ Object { "toAst": [Function], }, ], }, "getArgument": [Function], - "name": "xy_vis", + "name": "layeredXyVis", "removeArgument": [Function], "replaceArgument": [Function], "toAst": [Function], diff --git a/x-pack/plugins/lens/public/xy_visualization/__snapshots__/to_expression.test.ts.snap b/x-pack/plugins/lens/public/xy_visualization/__snapshots__/to_expression.test.ts.snap index 66162b0bee018..d06c798e630c0 100644 --- a/x-pack/plugins/lens/public/xy_visualization/__snapshots__/to_expression.test.ts.snap +++ b/x-pack/plugins/lens/public/xy_visualization/__snapshots__/to_expression.test.ts.snap @@ -5,9 +5,6 @@ Object { "chain": Array [ Object { "arguments": Object { - "curveType": Array [ - "LINEAR", - ], "emphasizeFitting": Array [ true, ], @@ -35,6 +32,9 @@ Object { "columnToLabel": Array [ "{\\"b\\":\\"col_b\\",\\"c\\":\\"col_c\\",\\"d\\":\\"col_d\\"}", ], + "curveType": Array [ + "LINEAR", + ], "decorations": Array [], "isHistogram": Array [ false, @@ -70,12 +70,6 @@ Object { "splitAccessors": Array [ "d", ], - "table": Array [ - Object { - "chain": Array [], - "type": "expression", - }, - ], "xAccessor": Array [ "a", ], From c89335d580fe2a77fc8f5d76a5e1ce512146067d Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Mon, 18 Jul 2022 13:06:15 +0300 Subject: [PATCH 04/27] Fix tests --- .../chart_expressions/expression_xy/common/i18n/index.tsx | 2 +- test/functional/apps/dashboard/group1/embeddable_rendering.ts | 4 ++-- test/functional/apps/dashboard/group3/dashboard_state.ts | 2 +- test/functional/apps/getting_started/_shakespeare.ts | 2 +- .../apps/visualize/replaced_vislib_chart_types/_area_chart.ts | 2 +- .../replaced_vislib_chart_types/_line_chart_split_chart.ts | 2 +- .../replaced_vislib_chart_types/_line_chart_split_series.ts | 2 +- .../replaced_vislib_chart_types/_point_series_options.ts | 2 +- .../replaced_vislib_chart_types/_vertical_bar_chart.ts | 2 +- .../_vertical_bar_chart_nontimeindex.ts | 2 +- .../tests/apps/dashboard/async_search/async_search.ts | 2 +- .../tests/apps/dashboard/async_search/save_search_session.ts | 2 +- 12 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/plugins/chart_expressions/expression_xy/common/i18n/index.tsx b/src/plugins/chart_expressions/expression_xy/common/i18n/index.tsx index ac2b20f8bdf49..cd5976aec5d6e 100644 --- a/src/plugins/chart_expressions/expression_xy/common/i18n/index.tsx +++ b/src/plugins/chart_expressions/expression_xy/common/i18n/index.tsx @@ -118,7 +118,7 @@ export const strings = { defaultMessage: 'Specifies split row of the xy chart', }), getHandleEmptyXAccessorHelp: () => - i18n.translate('expressionXY.xyVis.splitRowAccessor.help', { + i18n.translate('expressionXY.xyVis.handleEmptyXAccessor.help', { defaultMessage: 'Allow handling empty x accessor', }), getLayersHelp: () => diff --git a/test/functional/apps/dashboard/group1/embeddable_rendering.ts b/test/functional/apps/dashboard/group1/embeddable_rendering.ts index 42f2e9a24f3d0..6fbac83a17edd 100644 --- a/test/functional/apps/dashboard/group1/embeddable_rendering.ts +++ b/test/functional/apps/dashboard/group1/embeddable_rendering.ts @@ -60,7 +60,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // TODO add test for 'animal sound pie' viz // This tests line charts that do not use timeseries data - const dogData = await elasticChart.getChartDebugData('visTypeXyChart', 2); + const dogData = await elasticChart.getChartDebugData('xyVisChart', 2); const pointCount = dogData?.areas?.reduce((acc, a) => { return acc + a.lines.y1.points.length; }, 0); @@ -83,7 +83,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // Three instead of 0 because there is a visualization based off a non time based index that // should still show data. - const dogData = await elasticChart.getChartDebugData('visTypeXyChart'); + const dogData = await elasticChart.getChartDebugData('xyVisChart'); const pointCount = dogData?.areas?.reduce((acc, a) => { return acc + a.lines.y1.points.length; }, 0); diff --git a/test/functional/apps/dashboard/group3/dashboard_state.ts b/test/functional/apps/dashboard/group3/dashboard_state.ts index 79179b7c9d08b..9de3ef263ba24 100644 --- a/test/functional/apps/dashboard/group3/dashboard_state.ts +++ b/test/functional/apps/dashboard/group3/dashboard_state.ts @@ -31,7 +31,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const elasticChart = getService('elasticChart'); const kibanaServer = getService('kibanaServer'); const dashboardAddPanel = getService('dashboardAddPanel'); - const xyChartSelector = 'visTypeXyChart'; + const xyChartSelector = 'xyVisChart'; const enableNewChartLibraryDebug = async (force = false) => { if ((await PageObjects.visChart.isNewChartsLibraryEnabled()) || force) { diff --git a/test/functional/apps/getting_started/_shakespeare.ts b/test/functional/apps/getting_started/_shakespeare.ts index 8cdf4a5f2ff76..0c833f185f9c4 100644 --- a/test/functional/apps/getting_started/_shakespeare.ts +++ b/test/functional/apps/getting_started/_shakespeare.ts @@ -28,7 +28,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { 'visChart', ]); - const xyChartSelector = 'visTypeXyChart'; + const xyChartSelector = 'xyVisChart'; // https://www.elastic.co/guide/en/kibana/current/tutorial-load-dataset.html diff --git a/test/functional/apps/visualize/replaced_vislib_chart_types/_area_chart.ts b/test/functional/apps/visualize/replaced_vislib_chart_types/_area_chart.ts index 5fbb264910dca..309d1abb9961b 100644 --- a/test/functional/apps/visualize/replaced_vislib_chart_types/_area_chart.ts +++ b/test/functional/apps/visualize/replaced_vislib_chart_types/_area_chart.ts @@ -26,7 +26,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { 'header', 'timePicker', ]); - const xyChartSelector = 'visTypeXyChart'; + const xyChartSelector = 'xyVisChart'; const vizName = 'Visualization AreaChart Name Test - Charts library'; diff --git a/test/functional/apps/visualize/replaced_vislib_chart_types/_line_chart_split_chart.ts b/test/functional/apps/visualize/replaced_vislib_chart_types/_line_chart_split_chart.ts index 77ddc3bbac1a4..a42aa6a0ef3e1 100644 --- a/test/functional/apps/visualize/replaced_vislib_chart_types/_line_chart_split_chart.ts +++ b/test/functional/apps/visualize/replaced_vislib_chart_types/_line_chart_split_chart.ts @@ -23,7 +23,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { 'visChart', 'timePicker', ]); - const xyChartSelector = 'visTypeXyChart'; + const xyChartSelector = 'xyVisChart'; describe('line charts - split chart', function () { const initLineChart = async function () { diff --git a/test/functional/apps/visualize/replaced_vislib_chart_types/_line_chart_split_series.ts b/test/functional/apps/visualize/replaced_vislib_chart_types/_line_chart_split_series.ts index a46c46fda48ad..764cccaa40500 100644 --- a/test/functional/apps/visualize/replaced_vislib_chart_types/_line_chart_split_series.ts +++ b/test/functional/apps/visualize/replaced_vislib_chart_types/_line_chart_split_series.ts @@ -23,7 +23,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { 'visChart', 'timePicker', ]); - const xyChartSelector = 'visTypeXyChart'; + const xyChartSelector = 'xyVisChart'; describe('line charts - split series', function () { const initLineChart = async function () { diff --git a/test/functional/apps/visualize/replaced_vislib_chart_types/_point_series_options.ts b/test/functional/apps/visualize/replaced_vislib_chart_types/_point_series_options.ts index 1a11d19064ce7..d093959f45405 100644 --- a/test/functional/apps/visualize/replaced_vislib_chart_types/_point_series_options.ts +++ b/test/functional/apps/visualize/replaced_vislib_chart_types/_point_series_options.ts @@ -25,7 +25,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { 'common', ]); const inspector = getService('inspector'); - const xyChartSelector = 'visTypeXyChart'; + const xyChartSelector = 'xyVisChart'; async function initChart() { log.debug('navigateToApp visualize'); diff --git a/test/functional/apps/visualize/replaced_vislib_chart_types/_vertical_bar_chart.ts b/test/functional/apps/visualize/replaced_vislib_chart_types/_vertical_bar_chart.ts index b8d5cd64bbc1f..896f2ed238067 100644 --- a/test/functional/apps/visualize/replaced_vislib_chart_types/_vertical_bar_chart.ts +++ b/test/functional/apps/visualize/replaced_vislib_chart_types/_vertical_bar_chart.ts @@ -18,7 +18,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const filterBar = getService('filterBar'); const PageObjects = getPageObjects(['visualize', 'visEditor', 'visChart', 'timePicker']); - const xyChartSelector = 'visTypeXyChart'; + const xyChartSelector = 'xyVisChart'; describe('vertical bar chart', function () { before(async () => { diff --git a/test/functional/apps/visualize/replaced_vislib_chart_types/_vertical_bar_chart_nontimeindex.ts b/test/functional/apps/visualize/replaced_vislib_chart_types/_vertical_bar_chart_nontimeindex.ts index 4f00bac7792c4..7d8ffe17566fe 100644 --- a/test/functional/apps/visualize/replaced_vislib_chart_types/_vertical_bar_chart_nontimeindex.ts +++ b/test/functional/apps/visualize/replaced_vislib_chart_types/_vertical_bar_chart_nontimeindex.ts @@ -16,7 +16,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const inspector = getService('inspector'); const PageObjects = getPageObjects(['common', 'visualize', 'header', 'visEditor', 'visChart']); - const xyChartSelector = 'visTypeXyChart'; + const xyChartSelector = 'xyVisChart'; describe('vertical bar chart with index without time filter', function () { const vizName1 = 'Visualization VerticalBarChart without time filter'; diff --git a/x-pack/test/search_sessions_integration/tests/apps/dashboard/async_search/async_search.ts b/x-pack/test/search_sessions_integration/tests/apps/dashboard/async_search/async_search.ts index 95f2a1f926ad7..d37d8a937601a 100644 --- a/x-pack/test/search_sessions_integration/tests/apps/dashboard/async_search/async_search.ts +++ b/x-pack/test/search_sessions_integration/tests/apps/dashboard/async_search/async_search.ts @@ -16,7 +16,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const dashboardPanelActions = getService('dashboardPanelActions'); const queryBar = getService('queryBar'); const elasticChart = getService('elasticChart'); - const xyChartSelector = 'visTypeXyChart'; + const xyChartSelector = 'xyVisChart'; const enableNewChartLibraryDebug = async () => { await elasticChart.setNewChartUiDebugFlag(); diff --git a/x-pack/test/search_sessions_integration/tests/apps/dashboard/async_search/save_search_session.ts b/x-pack/test/search_sessions_integration/tests/apps/dashboard/async_search/save_search_session.ts index 41ecf3b3015d4..ded0f097abdc7 100644 --- a/x-pack/test/search_sessions_integration/tests/apps/dashboard/async_search/save_search_session.ts +++ b/x-pack/test/search_sessions_integration/tests/apps/dashboard/async_search/save_search_session.ts @@ -104,7 +104,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.dashboard.switchToEditMode(); await searchSessions.expectState('restored'); - const xyChartSelector = 'visTypeXyChart'; + const xyChartSelector = 'xyVisChart'; await enableNewChartLibraryDebug(); const data = await PageObjects.visChart.getBarChartData(xyChartSelector, 'Sum of bytes'); expect(data.length).to.be(5); From 1aa9577208595eed62aed51d05557000106bf4ec Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Mon, 18 Jul 2022 18:52:40 +0300 Subject: [PATCH 05/27] Fix some tests --- .../expression_functions/layered_xy_vis_fn.ts | 9 +++++-- .../common/expression_functions/xy_vis_fn.ts | 26 +++---------------- .../expression_xy/common/utils/index.tsx | 2 +- .../common/utils/log_datatables.ts | 24 ++++++++++++++++- .../public/components/xy_chart.tsx | 14 +++++----- src/plugins/vis_types/xy/public/to_ast.ts | 2 ++ 6 files changed, 44 insertions(+), 33 deletions(-) diff --git a/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis_fn.ts b/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis_fn.ts index 9e1ef1cc0cb9f..9c4275de25c81 100644 --- a/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis_fn.ts +++ b/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis_fn.ts @@ -8,7 +8,7 @@ import { XY_VIS_RENDERER } from '../constants'; import { LayeredXyVisFn } from '../types'; -import { logDatatables } from '../utils'; +import { logDatatables, logDatatable } from '../utils'; import { validateMarkSizeRatioLimits, validateAddTimeMarker, @@ -22,7 +22,12 @@ import { appendLayerIds, getDataLayers } from '../helpers'; export const layeredXyVisFn: LayeredXyVisFn['fn'] = async (data, args, handlers) => { const layers = appendLayerIds(args.layers ?? [], 'layers'); - logDatatables(layers, handlers); + // for visialize we should log one datable for all layers + if (handlers.getExecutionContext()?.name === 'visualize') { + logDatatable(data, layers, handlers); + } else { + logDatatables(layers, handlers); + } const dataLayers = getDataLayers(layers); const hasBar = hasBarLayer(dataLayers); diff --git a/src/plugins/chart_expressions/expression_xy/common/expression_functions/xy_vis_fn.ts b/src/plugins/chart_expressions/expression_xy/common/expression_functions/xy_vis_fn.ts index 789b7fb9ceb63..35914834645ea 100644 --- a/src/plugins/chart_expressions/expression_xy/common/expression_functions/xy_vis_fn.ts +++ b/src/plugins/chart_expressions/expression_xy/common/expression_functions/xy_vis_fn.ts @@ -6,17 +6,12 @@ * Side Public License, v 1. */ -import { - Dimension, - prepareLogTable, - validateAccessor, -} from '@kbn/visualizations-plugin/common/utils'; +import { validateAccessor } from '@kbn/visualizations-plugin/common/utils'; import type { Datatable } from '@kbn/expressions-plugin/common'; import { ExpressionValueVisDimension } from '@kbn/visualizations-plugin/common/expression_functions'; -import { LayerTypes, XY_VIS_RENDERER, DATA_LAYER, REFERENCE_LINE } from '../constants'; +import { LayerTypes, XY_VIS_RENDERER, DATA_LAYER } from '../constants'; import { appendLayerIds, getAccessors, getShowLines, normalizeTable } from '../helpers'; import { DataLayerConfigResult, XYLayerConfig, XyVisFn, XYArgs } from '../types'; -import { getLayerDimensions } from '../utils'; import { hasAreaLayer, hasBarLayer, @@ -35,6 +30,7 @@ import { validateLinesVisibilityForChartType, validateAxes, } from './validate'; +import { logDatatable } from '../utils'; const createDataLayer = (args: XYArgs, table: Datatable): DataLayerConfigResult => { const accessors = getAccessors(args, table); @@ -108,21 +104,7 @@ export const xyVisFn: XyVisFn['fn'] = async (data, args, handlers) => { ...appendLayerIds(annotationLayers, 'annotationLayers'), ]; - if (handlers.inspectorAdapters.tables) { - handlers.inspectorAdapters.tables.reset(); - handlers.inspectorAdapters.tables.allowCsvExport = true; - - const layerDimensions = layers.reduce((dimensions, layer) => { - if (layer.layerType === LayerTypes.ANNOTATIONS || layer.type === REFERENCE_LINE) { - return dimensions; - } - - return [...dimensions, ...getLayerDimensions(layer)]; - }, []); - - const logTable = prepareLogTable(data, layerDimensions, true); - handlers.inspectorAdapters.tables.logDatatable('default', logTable); - } + logDatatable(data, layers, handlers); const hasBar = hasBarLayer(dataLayers); const hasArea = hasAreaLayer(dataLayers); diff --git a/src/plugins/chart_expressions/expression_xy/common/utils/index.tsx b/src/plugins/chart_expressions/expression_xy/common/utils/index.tsx index ba40d5768f50c..b367b14b0e117 100644 --- a/src/plugins/chart_expressions/expression_xy/common/utils/index.tsx +++ b/src/plugins/chart_expressions/expression_xy/common/utils/index.tsx @@ -6,4 +6,4 @@ * Side Public License, v 1. */ -export { logDatatables, getLayerDimensions } from './log_datatables'; +export { logDatatables, logDatatable, getLayerDimensions } from './log_datatables'; diff --git a/src/plugins/chart_expressions/expression_xy/common/utils/log_datatables.ts b/src/plugins/chart_expressions/expression_xy/common/utils/log_datatables.ts index f2a85241d1aec..66606ff453f86 100644 --- a/src/plugins/chart_expressions/expression_xy/common/utils/log_datatables.ts +++ b/src/plugins/chart_expressions/expression_xy/common/utils/log_datatables.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { ExecutionContext } from '@kbn/expressions-plugin'; +import { Datatable, ExecutionContext } from '@kbn/expressions-plugin'; import { Dimension, prepareLogTable } from '@kbn/visualizations-plugin/common/utils'; import { LayerTypes, REFERENCE_LINE } from '../constants'; import { strings } from '../i18n'; @@ -30,6 +30,28 @@ export const logDatatables = (layers: CommonXYLayerConfig[], handlers: Execution }); }; +export const logDatatable = ( + data: Datatable, + layers: CommonXYLayerConfig[], + handlers: ExecutionContext +) => { + if (handlers.inspectorAdapters.tables) { + handlers.inspectorAdapters.tables.reset(); + handlers.inspectorAdapters.tables.allowCsvExport = true; + + const layerDimensions = layers.reduce((dimensions, layer) => { + if (layer.layerType === LayerTypes.ANNOTATIONS || layer.type === REFERENCE_LINE) { + return dimensions; + } + + return [...dimensions, ...getLayerDimensions(layer)]; + }, []); + + const logTable = prepareLogTable(data, layerDimensions, true); + handlers.inspectorAdapters.tables.logDatatable('default', logTable); + } +}; + export const getLayerDimensions = ( layer: CommonXYDataLayerConfig | ReferenceLineLayerConfig ): Dimension[] => { diff --git a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx index 73c98d479f9a9..fbbd884534298 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx @@ -316,7 +316,7 @@ export function XYChart({ [...(yAxisConfigs ?? []), ...(xAxisConfig ? [xAxisConfig] : [])] ); - const allDocs = i18n.translate('visTypeXy.aggResponse.allDocsTitle', { + const allDocs = i18n.translate('expressionXY.xyVis.allDocsTitle', { defaultMessage: 'All docs', }); @@ -504,11 +504,12 @@ export function XYChart({ }; }; - const shouldShowValueLabels = - // No stacked bar charts - dataLayers.every((layer) => !layer.isStacked) && - // No histogram charts - !isHistogramViz; + const shouldShowValueLabels = uiState + ? valueLabels !== ValueLabelModes.HIDE + : // No stacked bar charts + dataLayers.every((layer) => !layer.isStacked) && + // No histogram charts + !isHistogramViz; const valueLabelsStyling = shouldShowValueLabels && @@ -862,7 +863,6 @@ export function XYChart({ domain={getYAxisDomain(axis)} showOverlappingLabels={axis.showOverlappingLabels} showDuplicatedTicks={axis.showDuplicates} - ticks={5} /> ); })} diff --git a/src/plugins/vis_types/xy/public/to_ast.ts b/src/plugins/vis_types/xy/public/to_ast.ts index 9cd5bd51fec3d..bd90f3159f9e8 100644 --- a/src/plugins/vis_types/xy/public/to_ast.ts +++ b/src/plugins/vis_types/xy/public/to_ast.ts @@ -59,6 +59,7 @@ const prepareLengend = (params: VisParams, legendSize?: LegendSize) => { maxLines: params.maxLegendLines, position: params.legendPosition, shouldTruncate: params.truncateLegend, + showSingleSeries: true, legendSize, }); @@ -452,6 +453,7 @@ export const toExpressionAst: VisToExpressionAst = async (vis, params splitColumnAccessor: dimensions.splitColumn?.map(prepareVisDimension), splitRowAccessor: dimensions.splitRow?.map(prepareVisDimension), handleEmptyXAccessor: true, + valueLabels: vis.params.labels.show ? 'show' : 'hide', }); const ast = buildExpression([visTypeXy]); From dfc353d424ceda5ab3dc169cb152ecf6f6165d13 Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Mon, 18 Jul 2022 19:49:50 +0300 Subject: [PATCH 06/27] Fix snapshots --- .../components/__snapshots__/xy_chart.test.tsx.snap | 10 ---------- .../xy/public/__snapshots__/to_ast.test.ts.snap | 3 +++ 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap b/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap index 204a9d12b04d0..3f9b47b1f2c2b 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap +++ b/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap @@ -430,7 +430,6 @@ exports[`XYChart component it renders area 1`] = ` } } tickFormat={[Function]} - ticks={5} title="a" /> Date: Tue, 19 Jul 2022 13:39:31 +0300 Subject: [PATCH 07/27] Fix tests --- .../expression_functions/layered_xy_vis_fn.ts | 4 +- .../common/expression_functions/xy_vis_fn.ts | 2 +- .../expression_xy/common/i18n/index.tsx | 12 ++++++ .../common/utils/log_datatables.ts | 37 +++++++++++++++++-- src/plugins/vis_types/xy/public/to_ast.ts | 2 +- 5 files changed, 50 insertions(+), 7 deletions(-) diff --git a/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis_fn.ts b/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis_fn.ts index 9c4275de25c81..f022e14535b68 100644 --- a/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis_fn.ts +++ b/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis_fn.ts @@ -24,9 +24,9 @@ export const layeredXyVisFn: LayeredXyVisFn['fn'] = async (data, args, handlers) // for visialize we should log one datable for all layers if (handlers.getExecutionContext()?.name === 'visualize') { - logDatatable(data, layers, handlers); + logDatatable(data, layers, handlers, args.splitColumnAccessor, args.splitRowAccessor); } else { - logDatatables(layers, handlers); + logDatatables(layers, handlers, args.splitColumnAccessor, args.splitRowAccessor); } const dataLayers = getDataLayers(layers); diff --git a/src/plugins/chart_expressions/expression_xy/common/expression_functions/xy_vis_fn.ts b/src/plugins/chart_expressions/expression_xy/common/expression_functions/xy_vis_fn.ts index 35914834645ea..2808b861c6df8 100644 --- a/src/plugins/chart_expressions/expression_xy/common/expression_functions/xy_vis_fn.ts +++ b/src/plugins/chart_expressions/expression_xy/common/expression_functions/xy_vis_fn.ts @@ -104,7 +104,7 @@ export const xyVisFn: XyVisFn['fn'] = async (data, args, handlers) => { ...appendLayerIds(annotationLayers, 'annotationLayers'), ]; - logDatatable(data, layers, handlers); + logDatatable(data, layers, handlers, args.splitColumnAccessor, args.splitRowAccessor); const hasBar = hasBarLayer(dataLayers); const hasArea = hasAreaLayer(dataLayers); diff --git a/src/plugins/chart_expressions/expression_xy/common/i18n/index.tsx b/src/plugins/chart_expressions/expression_xy/common/i18n/index.tsx index cd5976aec5d6e..979028871b1d8 100644 --- a/src/plugins/chart_expressions/expression_xy/common/i18n/index.tsx +++ b/src/plugins/chart_expressions/expression_xy/common/i18n/index.tsx @@ -25,6 +25,18 @@ export const strings = { i18n.translate('expressionXY.xyVis.logDatatable.breakDown', { defaultMessage: 'Break down by', }), + getSplitRowHelp: () => + i18n.translate('expressionXY.xyVis.logDatatable.splitRow', { + defaultMessage: 'Split rows by', + }), + getSplitColumnHelp: () => + i18n.translate('expressionXY.xyVis.logDatatable.splitColumn', { + defaultMessage: 'Split columns by', + }), + getMarkSizeHelp: () => + i18n.translate('expressionXY.xyVis.logDatatable.markSize', { + defaultMessage: 'Mark size', + }), getReferenceLineHelp: () => i18n.translate('expressionXY.xyVis.logDatatable.breakDown', { defaultMessage: 'Break down by', diff --git a/src/plugins/chart_expressions/expression_xy/common/utils/log_datatables.ts b/src/plugins/chart_expressions/expression_xy/common/utils/log_datatables.ts index 66606ff453f86..79e5025afc0c4 100644 --- a/src/plugins/chart_expressions/expression_xy/common/utils/log_datatables.ts +++ b/src/plugins/chart_expressions/expression_xy/common/utils/log_datatables.ts @@ -7,12 +7,18 @@ */ import { Datatable, ExecutionContext } from '@kbn/expressions-plugin'; +import { ExpressionValueVisDimension } from '@kbn/visualizations-plugin/common'; import { Dimension, prepareLogTable } from '@kbn/visualizations-plugin/common/utils'; import { LayerTypes, REFERENCE_LINE } from '../constants'; import { strings } from '../i18n'; import { CommonXYDataLayerConfig, CommonXYLayerConfig, ReferenceLineLayerConfig } from '../types'; -export const logDatatables = (layers: CommonXYLayerConfig[], handlers: ExecutionContext) => { +export const logDatatables = ( + layers: CommonXYLayerConfig[], + handlers: ExecutionContext, + splitColumnAccessor?: string | ExpressionValueVisDimension, + splitRowAccessor?: string | ExpressionValueVisDimension +) => { if (!handlers?.inspectorAdapters?.tables) { return; } @@ -25,7 +31,18 @@ export const logDatatables = (layers: CommonXYLayerConfig[], handlers: Execution return; } - const logTable = prepareLogTable(layer.table, getLayerDimensions(layer), true); + const layerDimensions = getLayerDimensions(layer); + + layerDimensions.push([ + splitColumnAccessor ? [splitColumnAccessor] : undefined, + strings.getSplitColumnHelp(), + ]); + layerDimensions.push([ + splitRowAccessor ? [splitRowAccessor] : undefined, + strings.getSplitRowHelp(), + ]); + + const logTable = prepareLogTable(layer.table, layerDimensions, true); handlers.inspectorAdapters.tables.logDatatable(layer.layerId, logTable); }); }; @@ -33,7 +50,9 @@ export const logDatatables = (layers: CommonXYLayerConfig[], handlers: Execution export const logDatatable = ( data: Datatable, layers: CommonXYLayerConfig[], - handlers: ExecutionContext + handlers: ExecutionContext, + splitColumnAccessor?: string | ExpressionValueVisDimension, + splitRowAccessor?: string | ExpressionValueVisDimension ) => { if (handlers.inspectorAdapters.tables) { handlers.inspectorAdapters.tables.reset(); @@ -47,6 +66,15 @@ export const logDatatable = ( return [...dimensions, ...getLayerDimensions(layer)]; }, []); + layerDimensions.push([ + splitColumnAccessor ? [splitColumnAccessor] : undefined, + strings.getSplitColumnHelp(), + ]); + layerDimensions.push([ + splitRowAccessor ? [splitRowAccessor] : undefined, + strings.getSplitRowHelp(), + ]); + const logTable = prepareLogTable(data, layerDimensions, true); handlers.inspectorAdapters.tables.logDatatable('default', logTable); } @@ -57,9 +85,11 @@ export const getLayerDimensions = ( ): Dimension[] => { let xAccessor; let splitAccessors; + let markSizeAccessor; if (layer.layerType === LayerTypes.DATA) { xAccessor = layer.xAccessor; splitAccessors = layer.splitAccessors; + markSizeAccessor = layer.markSizeAccessor; } const { accessors, layerType } = layer; @@ -70,5 +100,6 @@ export const getLayerDimensions = ( ], [xAccessor ? [xAccessor] : undefined, strings.getXAxisHelp()], [splitAccessors ? splitAccessors : undefined, strings.getBreakdownHelp()], + [markSizeAccessor ? [markSizeAccessor] : undefined, strings.getMarkSizeHelp()], ]; }; diff --git a/src/plugins/vis_types/xy/public/to_ast.ts b/src/plugins/vis_types/xy/public/to_ast.ts index bd90f3159f9e8..018f9a75670cb 100644 --- a/src/plugins/vis_types/xy/public/to_ast.ts +++ b/src/plugins/vis_types/xy/public/to_ast.ts @@ -121,7 +121,7 @@ const prepareLayers = ( isStacked: seriesParam.mode === ChartMode.Stacked, lineWidth: !isBar ? seriesParam.lineWidth : undefined, showPoints: !isBar ? seriesParam.showCircles : undefined, - pointsRadius: !isBar ? seriesParam.circlesRadius : undefined, + pointsRadius: !isBar ? seriesParam.circlesRadius ?? 3 : undefined, showLines: !isBar ? seriesParam.drawLinesBetweenPoints : undefined, curveType: getCurveType(seriesParam.interpolate), decorations: yAccessors.map((accessor) => From e533a2cff21353b73572e4ec0d91a91f58e4ebc5 Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Tue, 19 Jul 2022 18:47:16 +0300 Subject: [PATCH 08/27] Fix some tests --- packages/kbn-optimizer/limits.yml | 2 +- .../fixtures/kbn_archiver/dashboard_async/async_search.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/kbn-optimizer/limits.yml b/packages/kbn-optimizer/limits.yml index 0dc1e1ee4675e..9302a7fe022fa 100644 --- a/packages/kbn-optimizer/limits.yml +++ b/packages/kbn-optimizer/limits.yml @@ -129,6 +129,6 @@ pageLoadAssetSize: eventAnnotation: 19334 screenshotting: 22870 synthetics: 40958 - expressionXY: 34000 + expressionXY: 35000 kibanaUsageCollection: 16463 kubernetesSecurity: 77234 diff --git a/x-pack/test/functional/fixtures/kbn_archiver/dashboard_async/async_search.json b/x-pack/test/functional/fixtures/kbn_archiver/dashboard_async/async_search.json index 8dbd2dedeaf72..08a64e34168f1 100644 --- a/x-pack/test/functional/fixtures/kbn_archiver/dashboard_async/async_search.json +++ b/x-pack/test/functional/fixtures/kbn_archiver/dashboard_async/async_search.json @@ -50,7 +50,7 @@ "title": "Sum of Bytes by Extension (Delayed 5s)", "uiStateJSON": "{}", "version": 1, - "visState": "{\"title\":\"Sum of Bytes by Extension (Delayed 5s)\",\"type\":\"histogram\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"sum\",\"params\":{\"field\":\"bytes\"},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"params\":{\"field\":\"extension.raw\",\"orderBy\":\"1\",\"order\":\"desc\",\"size\":5,\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"},\"schema\":\"segment\"},{\"id\":\"3\",\"enabled\":true,\"type\":\"shard_delay\",\"params\":{\"delay\":\"5s\"},\"schema\":\"group\"}],\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"filter\":true,\"truncate\":100},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Sum of bytes\"}}],\"seriesParams\":[{\"show\":true,\"type\":\"histogram\",\"mode\":\"stacked\",\"data\":{\"label\":\"Sum of bytes\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"lineWidth\":2,\"showCircles\":true,\"circlesRadius\":1}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"labels\":{\"show\":false},\"thresholdLine\":{\"show\":false,\"value\":10,\"width\":1,\"style\":\"full\",\"color\":\"#E7664C\"},\"row\":true,\"palette\":{\"type\":\"palette\",\"name\":\"kibana_palette\"},\"isVislibVis\":true,\"detailedTooltip\":true,\"legendSize\":\"auto\"}}" + "visState": "{\"title\":\"Sum of Bytes by Extension (Delayed 5s)\",\"type\":\"histogram\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"sum\",\"params\":{\"field\":\"bytes\"},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"params\":{\"field\":\"extension.raw\",\"orderBy\":\"1\",\"order\":\"desc\",\"size\":5,\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"},\"schema\":\"segment\"},{\"id\":\"3\",\"enabled\":true,\"type\":\"shard_delay\",\"params\":{\"delay\":\"5s\"},\"schema\":\"split\"}],\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"filter\":true,\"truncate\":100},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Sum of bytes\"}}],\"seriesParams\":[{\"show\":true,\"type\":\"histogram\",\"mode\":\"stacked\",\"data\":{\"label\":\"Sum of bytes\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"lineWidth\":2,\"showCircles\":true,\"circlesRadius\":1}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"labels\":{\"show\":false},\"thresholdLine\":{\"show\":false,\"value\":10,\"width\":1,\"style\":\"full\",\"color\":\"#E7664C\"},\"row\":true,\"palette\":{\"type\":\"palette\",\"name\":\"kibana_palette\"},\"isVislibVis\":true,\"detailedTooltip\":true,\"legendSize\":\"auto\"}}" }, "coreMigrationVersion": "8.4.0", "id": "6c9f3830-01e3-11eb-9b63-176d7b28a352", From ebfdd1caffb4d07cceeb27a90f4b8c87af0f86c7 Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Wed, 20 Jul 2022 18:41:35 +0300 Subject: [PATCH 09/27] Fix some tests --- .../expression_functions/common_xy_args.ts | 5 +++++ .../expression_xy/common/i18n/index.tsx | 4 ++++ .../common/types/expression_functions.ts | 3 +++ .../public/components/split_chart.tsx | 4 ++-- .../public/components/x_domain.tsx | 17 ++++++++++++++--- .../public/components/xy_chart.tsx | 3 +++ src/plugins/vis_types/xy/public/to_ast.ts | 1 + 7 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/plugins/chart_expressions/expression_xy/common/expression_functions/common_xy_args.ts b/src/plugins/chart_expressions/expression_xy/common/expression_functions/common_xy_args.ts index 8fb32aa39b366..1e3bcdbcfcb82 100644 --- a/src/plugins/chart_expressions/expression_xy/common/expression_functions/common_xy_args.ts +++ b/src/plugins/chart_expressions/expression_xy/common/expression_functions/common_xy_args.ts @@ -108,4 +108,9 @@ export const commonXYArgs: CommonXYFn['args'] = { default: false, help: strings.getHandleEmptyXAccessorHelp(), }, + useAdjustedInterval: { + types: ['boolean'], + default: false, + help: strings.getUseAdjustedIntervalHelp(), + }, }; diff --git a/src/plugins/chart_expressions/expression_xy/common/i18n/index.tsx b/src/plugins/chart_expressions/expression_xy/common/i18n/index.tsx index 979028871b1d8..29837d06a8063 100644 --- a/src/plugins/chart_expressions/expression_xy/common/i18n/index.tsx +++ b/src/plugins/chart_expressions/expression_xy/common/i18n/index.tsx @@ -133,6 +133,10 @@ export const strings = { i18n.translate('expressionXY.xyVis.handleEmptyXAccessor.help', { defaultMessage: 'Allow handling empty x accessor', }), + getUseAdjustedIntervalHelp: () => + i18n.translate('expressionXY.xyVis.useAdjustedInterval.help', { + defaultMessage: 'Use adjusted interval fox x domain', + }), getLayersHelp: () => i18n.translate('expressionXY.layeredXyVis.layers.help', { defaultMessage: 'Layers of visual series', diff --git a/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts b/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts index 83002c57e7514..b248c8cf702b5 100644 --- a/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts +++ b/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts @@ -231,6 +231,7 @@ export interface XYArgs extends DataLayerArgs { orderBucketsBySum?: boolean; showTooltip: boolean; handleEmptyXAccessor?: boolean; + useAdjustedInterval?: boolean; } export interface LayeredXYArgs { @@ -255,6 +256,7 @@ export interface LayeredXYArgs { splitRowAccessor?: ExpressionValueVisDimension | string; splitColumnAccessor?: ExpressionValueVisDimension | string; handleEmptyXAccessor?: boolean; + useAdjustedInterval?: boolean; } export interface XYProps { @@ -279,6 +281,7 @@ export interface XYProps { orderBucketsBySum?: boolean; showTooltip: boolean; handleEmptyXAccessor?: boolean; + useAdjustedInterval?: boolean; } export interface AnnotationLayerArgs { diff --git a/src/plugins/chart_expressions/expression_xy/public/components/split_chart.tsx b/src/plugins/chart_expressions/expression_xy/public/components/split_chart.tsx index 6df2d10a777b3..3487b89fff290 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/split_chart.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/split_chart.tsx @@ -47,8 +47,8 @@ export const SplitChart = ({ splitColumnAccessor, splitRowAccessor, columns }: S /> )} ) : null; diff --git a/src/plugins/chart_expressions/expression_xy/public/components/x_domain.tsx b/src/plugins/chart_expressions/expression_xy/public/components/x_domain.tsx index e1d873d5ad171..c1bcb70e7590f 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/x_domain.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/x_domain.tsx @@ -6,10 +6,11 @@ * Side Public License, v 1. */ -import { isUndefined, uniq } from 'lodash'; +import { isUndefined, uniq, find } from 'lodash'; import React from 'react'; import moment from 'moment'; -import { Endzones } from '@kbn/charts-plugin/public'; +import dateMath, { Unit } from '@kbn/datemath'; +import { Endzones, getAdjustedInterval } from '@kbn/charts-plugin/public'; import type { DatatableUtilitiesService } from '@kbn/data-plugin/common'; import { getAccessorByDimension, @@ -48,6 +49,8 @@ export const getXDomain = ( isTimeViz: boolean, isHistogram: boolean, hasBars: boolean, + timeZone: string, + useAdjustedInterval?: boolean, xExtent?: AxisExtentConfigResult ) => { const appliedTimeRange = getAppliedTimeRange(datatableUtilitites, layers)?.timeRange; @@ -91,11 +94,19 @@ export const getXDomain = ( const domainMaxValue = Math.max(baseDomain.max - baseDomain.minInterval, lastXValue); const domainMax = hasBars ? domainMaxValue : domainMaxValue + baseDomain.minInterval; + const duration = moment.duration(baseDomain.minInterval); + const selectedUnit = find(dateMath.units, (u) => { + const value = duration.as(u); + return Number.isInteger(value); + }) as Unit; + return { extendedDomain: { min: domainMin, max: domainMax, - minInterval: baseDomain.minInterval, + minInterval: useAdjustedInterval + ? getAdjustedInterval(xValues, duration.as(selectedUnit), selectedUnit, timeZone) + : baseDomain.minInterval, }, baseDomain, }; diff --git a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx index fbbd884534298..b9360622e6c67 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx @@ -197,6 +197,7 @@ export function XYChart({ splitColumnAccessor, splitRowAccessor, handleEmptyXAccessor, + useAdjustedInterval, } = args; const chartRef = useRef(null); const chartTheme = chartsThemeService.useChartsTheme(); @@ -364,6 +365,8 @@ export function XYChart({ isTimeViz, isHistogramViz, hasBars, + timeZone, + useAdjustedInterval, xAxisConfig?.extent ); diff --git a/src/plugins/vis_types/xy/public/to_ast.ts b/src/plugins/vis_types/xy/public/to_ast.ts index 018f9a75670cb..8111551a7d195 100644 --- a/src/plugins/vis_types/xy/public/to_ast.ts +++ b/src/plugins/vis_types/xy/public/to_ast.ts @@ -454,6 +454,7 @@ export const toExpressionAst: VisToExpressionAst = async (vis, params splitRowAccessor: dimensions.splitRow?.map(prepareVisDimension), handleEmptyXAccessor: true, valueLabels: vis.params.labels.show ? 'show' : 'hide', + useAdjustedInterval: true, }); const ast = buildExpression([visTypeXy]); From 2d46b7ef076e26ba5955eba21197a1174e0a9618 Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Thu, 21 Jul 2022 12:37:41 +0300 Subject: [PATCH 10/27] Fix some more tests --- .../expression_xy/public/components/xy_chart.test.tsx | 8 ++++---- .../vis_types/xy/public/__snapshots__/to_ast.test.ts.snap | 3 +++ test/functional/page_objects/visualize_chart_page.ts | 4 +--- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.test.tsx b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.test.tsx index 03361a9383632..e744d0109bd42 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.test.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.test.tsx @@ -3208,7 +3208,7 @@ describe('XYChart component', () => { const smallMultiples = splitChart.dive().find(SmallMultiples); expect(groupBy.at(0).prop('id')).toEqual(SPLIT_ROW); - expect(smallMultiples.prop('splitHorizontally')).toEqual(SPLIT_ROW); + expect(smallMultiples.prop('splitVertically')).toEqual(SPLIT_ROW); }); it('should render split chart if splitColumnAccessor is specified', () => { @@ -3234,7 +3234,7 @@ describe('XYChart component', () => { const smallMultiples = splitChart.dive().find(SmallMultiples); expect(groupBy.at(0).prop('id')).toEqual(SPLIT_COLUMN); - expect(smallMultiples.prop('splitVertically')).toEqual(SPLIT_COLUMN); + expect(smallMultiples.prop('splitHorizontally')).toEqual(SPLIT_COLUMN); }); it('should render split chart if both, splitRowAccessor and splitColumnAccessor are specified', () => { @@ -3266,8 +3266,8 @@ describe('XYChart component', () => { expect(groupBy.at(0).prop('id')).toEqual(SPLIT_COLUMN); expect(groupBy.at(1).prop('id')).toEqual(SPLIT_ROW); - expect(smallMultiples.prop('splitVertically')).toEqual(SPLIT_COLUMN); - expect(smallMultiples.prop('splitHorizontally')).toEqual(SPLIT_ROW); + expect(smallMultiples.prop('splitVertically')).toEqual(SPLIT_ROW); + expect(smallMultiples.prop('splitHorizontally')).toEqual(SPLIT_COLUMN); }); }); diff --git a/src/plugins/vis_types/xy/public/__snapshots__/to_ast.test.ts.snap b/src/plugins/vis_types/xy/public/__snapshots__/to_ast.test.ts.snap index aaaa5b2c50ae1..506cae28aa17d 100644 --- a/src/plugins/vis_types/xy/public/__snapshots__/to_ast.test.ts.snap +++ b/src/plugins/vis_types/xy/public/__snapshots__/to_ast.test.ts.snap @@ -23,6 +23,9 @@ Object { "showTooltip": Array [ true, ], + "useAdjustedInterval": Array [ + true, + ], "valueLabels": Array [ "hide", ], diff --git a/test/functional/page_objects/visualize_chart_page.ts b/test/functional/page_objects/visualize_chart_page.ts index bec2383629e7b..beda8e75f3efe 100644 --- a/test/functional/page_objects/visualize_chart_page.ts +++ b/test/functional/page_objects/visualize_chart_page.ts @@ -135,9 +135,7 @@ export class VisualizeChartPageObject extends FtrService { * @param axis axis value, 'ValueAxis-1' by default */ public async getLineChartData(selector: string, dataLabel = 'Count') { - // For now lines are rendered as areas to enable stacking - const areas = (await this.getEsChartDebugState(selector))?.areas ?? []; - const lines = areas.map(({ lines: { y1 }, name, color }) => ({ ...y1, name, color })); + const lines = (await this.getEsChartDebugState(selector))?.lines ?? []; const points = lines.find(({ name }) => name === dataLabel)?.points ?? []; return points.map(({ y }) => y); } From 61d5149680cd4fdbbeb3df914c8ab09fbb1ef68c Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Thu, 21 Jul 2022 15:32:12 +0300 Subject: [PATCH 11/27] Update snapshot for area chart --- .../screenshots/baseline/area_chart.png | Bin 190127 -> 190569 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/test/functional/screenshots/baseline/area_chart.png b/test/functional/screenshots/baseline/area_chart.png index 7bbaa256f036098b8b8256e4a39e111024b65a42..7a0d5be0477127810f7a6334b3fd78a8202d6b6b 100644 GIT binary patch literal 190569 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≤b1u4ji_pVNLur>(y%dfCRgbm(AjF07s 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 z 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

V>&!E(b0i)#P+!`Y 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�SrmkHV9x%DTnE-k!Z-}#HYI40bL!Xc|b8_={zqlgsLR@%tPfgjzOCgeX%W%v@8d zU;SfLi4IN+dqUd9Al3HMcN1RT&C~o?l!VBvvnGS2Z>fV@AFHMj0@3`gEI#$=6iLk< zOJxsB?JygfQm_MR|2*;j4vs_5_`MU<^%=pSc@5p<@Dv8*wP6$H#&|Ji8|T*^vx(g< z=!{t0RK3N;8Nd9lfd9Cf;V z9Z?mKHe{P>aWj-G;iK4)lYOr%8n0t2l+5Kd#zla9-Yi;OyN7u;syM4jeAvKQw=Y{EDHgH6J16Pn zUVHv$q+WG<8( zdgVLFeHCtubOnd|aw1u0y$Ln@-D80Vvn`<$^jlg4KhT#3*wE(0OO$1YN zRm5zW16Tf?4vWjszxejzqL*LktEq9}Q;T6h;<*lWJ-qUUFFm~8zwH>c!1&?W@Q{QA zH%-uo8y^CcXRc2nme{oh_>7G5c;ux1+p|KFd729)TlLJdRnHF7qLP9O3n_muIenqo z=WKwB&_#6(G8YO`Z0~Ywdh~uo+UN zHV@8t$HBdAHBx$R?oGtS1!k7@%t4Vd)K_bxvZCUlc(if4R`%9FUyr=CwUCt5M^5{G zmx{1K-=A+(^z$MFQTpp*`XooN!{e_`y-I8)(M@pmynym@o}hbc!Dq$nrRC+)?~-Cy zr(|7CS6&t#B%@=S7l}&)XNS6}7%lRG5xM@2{$+>w;m={3&YPZ=;J%Rh5@jPO~=MjZkZSwU_}# zct?TFc>|llBBpCSod0k}dfmQ+uA#)VuFgAcM7!7(V`Ii9uOB)VW24{9H+50xV>~jt zcr~%B0r4vy+8W}m6Me@`_Qy%^@pOeuT>lnC^MajJg9>VISU>*s@w8el=Bk}t@#+{o zIejp}Z~`LVn=EeJrd7p zS2MILJ8C6zknQBilE&a)p-BV2@ItZfPOU*W_>s*1=GNw5roP3H`>>nX)r0wX(GR0#%S$A4>I+)Y(a{U- zd9TY68e>gyg5BNSgFj(U&W_f;M>*v>zJY*?3keMg)D&Khc6@b>^gySOS(-@c@j)D1 z^B6rjHm}XI>eSNOkJo0EEmA!bJ;|Wp98Z?`wK$>~86u(@pvpfj7C~hL;X_itATead z`+Kkk@EVe>{&`{#w^uz->ILkPmXB27v%0ADto`oFEX8W5;$_^!xOANe%P&--niel} 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

A-A;AR&`jrF( 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 Date: Fri, 22 Jul 2022 12:13:58 +0300 Subject: [PATCH 12/27] Fix dashboards tests --- .../apps/dashboard/group1/embeddable_rendering.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/functional/apps/dashboard/group1/embeddable_rendering.ts b/test/functional/apps/dashboard/group1/embeddable_rendering.ts index f8e0f869e6cce..251ccdac3a402 100644 --- a/test/functional/apps/dashboard/group1/embeddable_rendering.ts +++ b/test/functional/apps/dashboard/group1/embeddable_rendering.ts @@ -61,8 +61,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // This tests line charts that do not use timeseries data const dogData = await elasticChart.getChartDebugData('xyVisChart', 2); - const pointCount = dogData?.areas?.reduce((acc, a) => { - return acc + a.lines.y1.points.length; + const pointCount = dogData?.lines?.reduce((acc, a) => { + return acc + a.points.length; }, 0); expect(pointCount).to.equal(6); @@ -84,8 +84,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // Three instead of 0 because there is a visualization based off a non time based index that // should still show data. const dogData = await elasticChart.getChartDebugData('xyVisChart'); - const pointCount = dogData?.areas?.reduce((acc, a) => { - return acc + a.lines.y1.points.length; + const pointCount = dogData?.lines?.reduce((acc, a) => { + return acc + a.points.length; }, 0); expect(pointCount).to.equal(6); From 61f94189f6ee67b63a8616bb5fe1add612631930 Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Fri, 22 Jul 2022 15:28:28 +0300 Subject: [PATCH 13/27] Fix test --- test/functional/apps/dashboard/group1/embeddable_rendering.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/functional/apps/dashboard/group1/embeddable_rendering.ts b/test/functional/apps/dashboard/group1/embeddable_rendering.ts index 251ccdac3a402..c0d5a47dbeb27 100644 --- a/test/functional/apps/dashboard/group1/embeddable_rendering.ts +++ b/test/functional/apps/dashboard/group1/embeddable_rendering.ts @@ -83,7 +83,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // Three instead of 0 because there is a visualization based off a non time based index that // should still show data. - const dogData = await elasticChart.getChartDebugData('xyVisChart'); + const dogData = await elasticChart.getChartDebugData('xyVisChart', 2); const pointCount = dogData?.lines?.reduce((acc, a) => { return acc + a.points.length; }, 0); From 2c38d2c9625c2fbabb5cb474bf47bc44f35cc25c Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Mon, 25 Jul 2022 15:27:38 +0300 Subject: [PATCH 14/27] Fix some remarks --- .../expression_functions/common_xy_args.ts | 5 - .../expression_xy/common/i18n/index.tsx | 4 - .../common/types/expression_functions.ts | 3 - .../__snapshots__/xy_chart.test.tsx.snap | 2593 ++++++++++++++++- .../public/components/data_layers.tsx | 3 - .../public/components/legend_color_picker.tsx | 42 +- .../public/components/tooltip/tooltip.tsx | 7 +- .../public/components/xy_chart.tsx | 26 +- .../public/helpers/data_layers.tsx | 27 +- .../expression_xy/public/helpers/layers.ts | 20 +- .../public/__snapshots__/to_ast.test.ts.snap | 40 +- src/plugins/vis_types/xy/public/to_ast.ts | 14 +- 12 files changed, 2605 insertions(+), 179 deletions(-) diff --git a/src/plugins/chart_expressions/expression_xy/common/expression_functions/common_xy_args.ts b/src/plugins/chart_expressions/expression_xy/common/expression_functions/common_xy_args.ts index 1e3bcdbcfcb82..531085285206c 100644 --- a/src/plugins/chart_expressions/expression_xy/common/expression_functions/common_xy_args.ts +++ b/src/plugins/chart_expressions/expression_xy/common/expression_functions/common_xy_args.ts @@ -103,11 +103,6 @@ export const commonXYArgs: CommonXYFn['args'] = { types: ['string'], help: strings.getMinTimeBarIntervalHelp(), }, - handleEmptyXAccessor: { - types: ['boolean'], - default: false, - help: strings.getHandleEmptyXAccessorHelp(), - }, useAdjustedInterval: { types: ['boolean'], default: false, diff --git a/src/plugins/chart_expressions/expression_xy/common/i18n/index.tsx b/src/plugins/chart_expressions/expression_xy/common/i18n/index.tsx index 29837d06a8063..46d2dbadb1d20 100644 --- a/src/plugins/chart_expressions/expression_xy/common/i18n/index.tsx +++ b/src/plugins/chart_expressions/expression_xy/common/i18n/index.tsx @@ -129,10 +129,6 @@ export const strings = { i18n.translate('expressionXY.xyVis.splitRowAccessor.help', { defaultMessage: 'Specifies split row of the xy chart', }), - getHandleEmptyXAccessorHelp: () => - i18n.translate('expressionXY.xyVis.handleEmptyXAccessor.help', { - defaultMessage: 'Allow handling empty x accessor', - }), getUseAdjustedIntervalHelp: () => i18n.translate('expressionXY.xyVis.useAdjustedInterval.help', { defaultMessage: 'Use adjusted interval fox x domain', diff --git a/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts b/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts index b248c8cf702b5..6b3a1443c1d48 100644 --- a/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts +++ b/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts @@ -230,7 +230,6 @@ export interface XYArgs extends DataLayerArgs { detailedTooltip?: boolean; orderBucketsBySum?: boolean; showTooltip: boolean; - handleEmptyXAccessor?: boolean; useAdjustedInterval?: boolean; } @@ -255,7 +254,6 @@ export interface LayeredXYArgs { showTooltip: boolean; splitRowAccessor?: ExpressionValueVisDimension | string; splitColumnAccessor?: ExpressionValueVisDimension | string; - handleEmptyXAccessor?: boolean; useAdjustedInterval?: boolean; } @@ -280,7 +278,6 @@ export interface XYProps { detailedTooltip?: boolean; orderBucketsBySum?: boolean; showTooltip: boolean; - handleEmptyXAccessor?: boolean; useAdjustedInterval?: boolean; } diff --git a/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap b/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap index 3f9b47b1f2c2b..0fcb66319a0c7 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap +++ b/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap @@ -295,8 +295,251 @@ exports[`XYChart component it renders area 1`] = ` - - - } - onBrushEnd={[Function]} - onElementClick={[Function]} - onPointerUpdate={[Function]} - onRenderChange={[Function]} - rotation={90} + "accessors": Array [ + "a", + "b", + ], + "columnToLabel": "{\\"a\\": \\"Label A\\", \\"b\\": \\"Label B\\", \\"d\\": \\"Label D\\"}", + "isHistogram": false, + "isHorizontal": true, + "isPercentage": false, + "isStacked": false, + "layerId": "first", + "layerType": "data", + "palette": Object { + "name": "mock", + "params": Object {}, + "type": "palette", + }, + "seriesType": "bar", + "showLines": true, + "splitAccessors": Array [ + "d", + ], + "table": Object { + "columns": Array [ + Object { + "id": "a", + "meta": Object { + "params": Object { + "id": "number", + "params": Object { + "pattern": "0,0.000", + }, + }, + "type": "number", + }, + "name": "a", + }, + Object { + "id": "b", + "meta": Object { + "params": Object { + "id": "number", + "params": Object { + "pattern": "000,0", + }, + }, + "type": "number", + }, + "name": "b", + }, + Object { + "id": "c", + "meta": Object { + "field": "order_date", + "params": Object { + "id": "string", + }, + "sourceParams": Object { + "params": Object { + "interval": "auto", + }, + "type": "date-histogram", + }, + "type": "date", + }, + "name": "c", + }, + Object { + "id": "d", + "meta": Object { + "type": "string", + }, + "name": "ColD", + }, + ], + "rows": Array [ + Object { + "a": 1, + "b": 2, + "c": 1652034840000, + "d": "Foo", + }, + Object { + "a": 1, + "b": 5, + "c": 1652122440000, + "d": "Bar", + }, + ], + "type": "datatable", + }, + "type": "dataLayer", + "xAccessor": "c", + "xScaleType": "ordinal", + }, + ], + "fieldFormats": Object { + "first": Object { + "splitColumnAccessors": Object {}, + "splitRowAccessors": Object {}, + "splitSeriesAccessors": Object { + "d": Object { + "format": Object { + "id": "string", + }, + "formatter": Object { + "convert": [MockFunction] { + "calls": Array [ + Array [ + 1652034840000, + ], + Array [ + 1652122440000, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": 1652034840000, + }, + Object { + "type": "return", + "value": 1652122440000, + }, + ], + }, + }, + }, + }, + "xAccessors": Object { + "c": Object { + "id": "string", + }, + }, + "yAccessors": Object { + "a": Object { + "id": "number", + "params": Object { + "pattern": "0,0.000", + }, + }, + "b": Object { + "id": "number", + "params": Object { + "pattern": "000,0", + }, + }, + }, + }, + }, + "formattedDatatables": Object { + "first": Object { + "formattedColumns": Object { + "c": true, + }, + "table": Object { + "columns": Array [ + Object { + "id": "a", + "meta": Object { + "params": Object { + "id": "number", + "params": Object { + "pattern": "0,0.000", + }, + }, + "type": "number", + }, + "name": "a", + }, + Object { + "id": "b", + "meta": Object { + "params": Object { + "id": "number", + "params": Object { + "pattern": "000,0", + }, + }, + "type": "number", + }, + "name": "b", + }, + Object { + "id": "c", + "meta": Object { + "field": "order_date", + "params": Object { + "id": "string", + }, + "sourceParams": Object { + "params": Object { + "interval": "auto", + }, + "type": "date-histogram", + }, + "type": "date", + }, + "name": "c", + }, + Object { + "id": "d", + "meta": Object { + "type": "string", + }, + "name": "ColD", + }, + ], + "rows": Array [ + Object { + "a": 1, + "b": 2, + "c": 1652034840000, + "d": "Foo", + }, + Object { + "a": 1, + "b": 5, + "c": 1652122440000, + "d": "Bar", + }, + ], + "type": "datatable", + }, + }, + }, + "legendPosition": "top", + "setColor": [Function], + "titles": Object { + "first": Object { + "splitColumnTitles": Object {}, + "splitRowTitles": Object {}, + "splitSeriesTitles": Object { + "d": "ColD", + }, + "xTitles": Object { + "c": "c", + }, + "yTitles": Object { + "a": "a", + "b": "b", + }, + }, + }, + "uiState": undefined, + } + } + > + + + } + onBrushEnd={[Function]} + onElementClick={[Function]} + onPointerUpdate={[Function]} + onRenderChange={[Function]} + rotation={90} showLegend={false} showLegendExtra={false} theme={ @@ -2503,8 +3232,251 @@ exports[`XYChart component it renders line 1`] = ` - - - -`; - -exports[`XYChart component split chart should render split chart if both, splitRowAccessor and splitColumnAccessor are specified 1`] = ` -
- + + +
+`; + +exports[`XYChart component split chart should render split chart if both, splitRowAccessor and splitColumnAccessor are specified 1`] = ` +
+ = ({ chartHasMoreThanOneBarSeries, defaultXScaleType, fieldFormats, - handleEmptyXAccessor, uiState, }) => { const colorAssignments = getColorAssignments(layers, titles, fieldFormats, formattedDatatables); @@ -119,7 +117,6 @@ export const DataLayers: FC = ({ fillOpacity, defaultXScaleType, fieldFormats, - handleEmptyXAccessor, uiState, }); diff --git a/src/plugins/chart_expressions/expression_xy/public/components/legend_color_picker.tsx b/src/plugins/chart_expressions/expression_xy/public/components/legend_color_picker.tsx index 099e9eeae0e73..9fb81bc951338 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/legend_color_picker.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/legend_color_picker.tsx @@ -7,10 +7,18 @@ */ import React, { createContext, useCallback, useContext } from 'react'; -import { LegendColorPicker, Position } from '@elastic/charts'; +import { LegendColorPicker, Position, XYChartSeriesIdentifier } from '@elastic/charts'; import { PopoverAnchorPosition, EuiWrappingPopover, EuiOutsideClickDetector } from '@elastic/eui'; import type { PersistedState } from '@kbn/visualizations-plugin/public'; import { ColorPicker } from '@kbn/charts-plugin/public'; +import { + DatatablesWithFormatInfo, + getMetaFromSeriesId, + getSeriesName, + LayersAccessorsTitles, + LayersFieldFormats, +} from '../helpers'; +import type { CommonXYDataLayerConfig } from '../../common/types'; const KEY_CODE_ENTER = 13; @@ -31,6 +39,10 @@ export interface LegendColorPickerWrapperContextType { legendPosition: Position; setColor: (newColor: string | null, seriesKey: string | number) => void; uiState?: PersistedState; + dataLayers: CommonXYDataLayerConfig[]; + formattedDatatables: DatatablesWithFormatInfo; + titles: LayersAccessorsTitles; + fieldFormats: LayersFieldFormats; } export const LegendColorPickerWrapperContext = createContext< @@ -53,8 +65,32 @@ export const LegendColorPickerWrapper: LegendColorPicker = ({ return null; } - const { legendPosition, setColor, uiState } = colorPickerWrappingContext; - const seriesName = seriesIdentifier.key; + const { + legendPosition, + setColor, + uiState, + dataLayers, + titles, + formattedDatatables, + fieldFormats, + } = colorPickerWrappingContext; + const { layerId } = getMetaFromSeriesId(seriesIdentifier.specId); + + const layer = dataLayers.find((dataLayer) => dataLayer.layerId === layerId); + const seriesName = layer + ? getSeriesName( + seriesIdentifier as XYChartSeriesIdentifier, + { + splitAccessors: layer.splitAccessors ?? [], + accessorsCount: layer.accessors.length, + columns: formattedDatatables[layer.layerId].table.columns, + splitAccessorsFormats: fieldFormats[layer.layerId].splitSeriesAccessors, + alreadyFormattedColumns: formattedDatatables[layer.layerId].formattedColumns, + columnToLabelMap: layer.columnToLabel ? JSON.parse(layer.columnToLabel) : {}, + }, + titles[layer.layerId] + )?.toString() || '' + : ''; const overwriteColors: Record = uiState?.get('vis.colors', {}) ?? {}; const colorIsOverwritten = seriesName.toString() in overwriteColors; diff --git a/src/plugins/chart_expressions/expression_xy/public/components/tooltip/tooltip.tsx b/src/plugins/chart_expressions/expression_xy/public/components/tooltip/tooltip.tsx index 45cd2a87c1651..7ab7c9f549e24 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/tooltip/tooltip.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/tooltip/tooltip.tsx @@ -32,7 +32,6 @@ type Props = TooltipInfo & { splitRowAccessor?: string; splitColumnAccessor?: string; }; - handleEmptyXAccessor?: boolean; }; export const Tooltip: FC = ({ @@ -44,7 +43,6 @@ export const Tooltip: FC = ({ formattedDatatables, splitAccessors, xDomain, - handleEmptyXAccessor, }) => { const pickedValue = values.find(({ isHighlighted }) => isHighlighted); @@ -54,10 +52,7 @@ export const Tooltip: FC = ({ const data: TooltipData[] = []; const seriesIdentifier = pickedValue.seriesIdentifier as XYChartSeriesIdentifier; - const { layerId, xAccessor, yAccessor } = getMetaFromSeriesId( - seriesIdentifier.specId, - handleEmptyXAccessor - ); + const { layerId, xAccessor, yAccessor } = getMetaFromSeriesId(seriesIdentifier.specId); const { formattedColumns } = formattedDatatables[layerId]; const layerTitles = titles[layerId]; const layerFormats = fieldFormats[layerId]; diff --git a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx index b9360622e6c67..41fb5234e48ed 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx @@ -28,7 +28,6 @@ import { Direction, XYChartElementEvent, } from '@elastic/charts'; -import { i18n } from '@kbn/i18n'; import { IconType } from '@elastic/eui'; import { PaletteRegistry } from '@kbn/coloring'; import { RenderMode } from '@kbn/expressions-plugin/common'; @@ -196,7 +195,6 @@ export function XYChart({ xAxisConfig, splitColumnAccessor, splitRowAccessor, - handleEmptyXAccessor, useAdjustedInterval, } = args; const chartRef = useRef(null); @@ -317,14 +315,7 @@ export function XYChart({ [...(yAxisConfigs ?? []), ...(xAxisConfig ? [xAxisConfig] : [])] ); - const allDocs = i18n.translate('expressionXY.xyVis.allDocsTitle', { - defaultMessage: 'All docs', - }); - - const xTitle = - xAxisConfig?.title || - (xAxisColumn && xAxisColumn.name) || - (handleEmptyXAccessor ? allDocs : undefined); + const xTitle = xAxisConfig?.title || (xAxisColumn && xAxisColumn.name) || undefined; const yAxesMap = { left: yAxesConfiguration.find( ({ position }) => position === getAxisPosition(Position.Left, shouldRotate) @@ -338,8 +329,7 @@ export function XYChart({ dataLayers, { splitColumnAccessor, splitRowAccessor }, { xTitle }, - yAxesConfiguration, - handleEmptyXAccessor + yAxesConfiguration ); const filteredBarLayers = dataLayers.filter(({ seriesType }) => seriesType === SeriesTypes.BAR); @@ -699,6 +689,10 @@ export function XYChart({ uiState, setColor, legendPosition: legend.position, + dataLayers, + formattedDatatables, + titles, + fieldFormats, }} > @@ -771,7 +765,6 @@ export function XYChart({ splitRowAccessor: splitRowId, }} xDomain={isTimeViz ? rawXDomain : undefined} - handleEmptyXAccessor={handleEmptyXAccessor} /> ) : undefined, @@ -819,11 +812,7 @@ export function XYChart({ } title={xTitle} gridLine={gridLineStyle} - hide={ - xAxisConfig?.hide || - dataLayers[0]?.simpleView || - !(handleEmptyXAccessor || dataLayers[0]?.xAccessor) - } + hide={xAxisConfig?.hide || dataLayers[0]?.simpleView || !dataLayers[0]?.xAccessor} tickFormat={(d) => { let value = safeXAccessorLabelRenderer(d) || ''; if (xAxisConfig?.truncate && value.length > xAxisConfig.truncate) { @@ -905,7 +894,6 @@ export function XYChart({ chartHasMoreThanOneBarSeries={chartHasMoreThanOneBarSeries} defaultXScaleType={defaultXScaleType} fieldFormats={fieldFormats} - handleEmptyXAccessor={handleEmptyXAccessor} uiState={uiState} /> )} diff --git a/src/plugins/chart_expressions/expression_xy/public/helpers/data_layers.tsx b/src/plugins/chart_expressions/expression_xy/public/helpers/data_layers.tsx index 250893e603a04..8ca2d77fd33a3 100644 --- a/src/plugins/chart_expressions/expression_xy/public/helpers/data_layers.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/helpers/data_layers.tsx @@ -52,7 +52,6 @@ type GetSeriesPropsFn = (config: { formattedDatatableInfo: DatatableWithFormatInfo; defaultXScaleType: XScaleType; fieldFormats: LayersFieldFormats; - handleEmptyXAccessor?: boolean; uiState?: PersistedState; }) => SeriesSpec; @@ -302,15 +301,15 @@ const getColor: GetColorFn = ( return overwriteColor; } + const name = getSeriesNameFn(series)?.toString() || ''; + const overwriteColors: Record = uiState?.get ? uiState.get('vis.colors', {}) : {}; - if (Object.keys(overwriteColors).includes(series.key)) { - return overwriteColors[series.key]; + if (Object.keys(overwriteColors).includes(name)) { + return overwriteColors[name]; } const colorAssignment = colorAssignments[layer.palette.name]; - const name = getSeriesNameFn(series)?.toString() || ''; - const seriesLayers: SeriesLayer[] = [ { name, @@ -343,12 +342,11 @@ export const generateSeriesId = ( SPLIT_CHAR ); -export const getMetaFromSeriesId = (seriesId: string, handleEmptyXAccessor?: boolean) => { +export const getMetaFromSeriesId = (seriesId: string) => { const [layerId, xAccessor, yAccessor, ...splitAccessors] = seriesId.split(SPLIT_CHAR); return { layerId, - xAccessor: - xAccessor === EMPTY_ACCESSOR ? (handleEmptyXAccessor ? 'all' : undefined) : xAccessor, + xAccessor: xAccessor === EMPTY_ACCESSOR ? undefined : xAccessor, yAccessor, splitAccessor: splitAccessors[0] === EMPTY_ACCESSOR ? undefined : splitAccessors, }; @@ -371,7 +369,6 @@ export const getSeriesProps: GetSeriesPropsFn = ({ formattedDatatableInfo, defaultXScaleType, fieldFormats, - handleEmptyXAccessor, uiState, }): SeriesSpec => { const { table, isStacked, markSizeAccessor } = layer; @@ -421,20 +418,12 @@ export const getSeriesProps: GetSeriesPropsFn = ({ ) ); - let emptyX: Record = { + const emptyX: Record = { unifiedX: i18n.translate('expressionXY.xyChart.emptyXLabel', { defaultMessage: '(empty)', }), }; - if (handleEmptyXAccessor) { - emptyX = { - all: i18n.translate('expressionXY.xyChart.handledEmptyXLabel', { - defaultMessage: '_all', - }), - }; - } - if (!xColumnId) { rows = rows.map((row) => ({ ...row, @@ -466,7 +455,7 @@ export const getSeriesProps: GetSeriesPropsFn = ({ accessor, xColumnId ), - xAccessor: xColumnId || (handleEmptyXAccessor ? 'all' : 'unifiedX'), + xAccessor: xColumnId || 'unifiedX', yAccessors: [accessor], markSizeAccessor: markSizeColumnId, markFormat: (value) => markFormatter.convert(value), diff --git a/src/plugins/chart_expressions/expression_xy/public/helpers/layers.ts b/src/plugins/chart_expressions/expression_xy/public/helpers/layers.ts index 03a3f412b7af3..8ff87e381cf48 100644 --- a/src/plugins/chart_expressions/expression_xy/public/helpers/layers.ts +++ b/src/plugins/chart_expressions/expression_xy/public/helpers/layers.ts @@ -199,8 +199,7 @@ export const getLayerTitles = ( { xAccessor, accessors, splitAccessors = [], table, layerId }: CommonXYDataLayerConfig, { splitColumnAccessor, splitRowAccessor }: SplitAccessors, { xTitle }: CustomTitles, - groups: GroupsConfiguration, - handleEmptyXAccessor?: boolean + groups: GroupsConfiguration ): LayerAccessorsTitles => { const mapTitle = (dimension?: string | ExpressionValueVisDimension) => { if (!dimension) { @@ -215,11 +214,7 @@ export const getLayerTitles = ( [accessor]: getTitleForYAccessor(layerId, accessor, groups, table.columns), }); - const xColumnId = xAccessor - ? getAccessorByDimension(xAccessor, table.columns) - : handleEmptyXAccessor - ? 'all' - : undefined; + const xColumnId = xAccessor ? getAccessorByDimension(xAccessor, table.columns) : undefined; const yColumnIds = accessors.map((a) => getAccessorByDimension(a, table.columns)); const splitColumnAccessors: Array = splitAccessors; @@ -245,19 +240,12 @@ export const getLayersTitles = ( layers: CommonXYDataLayerConfig[], splitAccessors: SplitAccessors, customTitles: CustomTitles, - groups: GroupsConfiguration, - handleEmptyXAccessor?: boolean + groups: GroupsConfiguration ): LayersAccessorsTitles => layers.reduce( (formatters, layer) => ({ ...formatters, - [layer.layerId]: getLayerTitles( - layer, - splitAccessors, - customTitles, - groups, - handleEmptyXAccessor - ), + [layer.layerId]: getLayerTitles(layer, splitAccessors, customTitles, groups), }), {} ); diff --git a/src/plugins/vis_types/xy/public/__snapshots__/to_ast.test.ts.snap b/src/plugins/vis_types/xy/public/__snapshots__/to_ast.test.ts.snap index 506cae28aa17d..f6a2e427fccb4 100644 --- a/src/plugins/vis_types/xy/public/__snapshots__/to_ast.test.ts.snap +++ b/src/plugins/vis_types/xy/public/__snapshots__/to_ast.test.ts.snap @@ -4,44 +4,18 @@ exports[`xy vis toExpressionAst function should match basic snapshot 1`] = ` Object { "addArgument": [Function], "arguments": Object { - "addTimeMarker": Array [ - false, + "expression": Array [ + "_all", ], - "handleEmptyXAccessor": Array [ - true, + "id": Array [ + "all", ], - "layers": Array [ - Object { - "toAst": [Function], - }, - ], - "legend": Array [ - Object { - "toAst": [Function], - }, - ], - "showTooltip": Array [ - true, - ], - "useAdjustedInterval": Array [ - true, - ], - "valueLabels": Array [ - "hide", - ], - "xAxisConfig": Array [ - Object { - "toAst": [Function], - }, - ], - "yAxisConfigs": Array [ - Object { - "toAst": [Function], - }, + "name": Array [ + "All docs", ], }, "getArgument": [Function], - "name": "layeredXyVis", + "name": "mapColumn", "removeArgument": [Function], "replaceArgument": [Function], "toAst": [Function], diff --git a/src/plugins/vis_types/xy/public/to_ast.ts b/src/plugins/vis_types/xy/public/to_ast.ts index 8111551a7d195..cd3f07c61423f 100644 --- a/src/plugins/vis_types/xy/public/to_ast.ts +++ b/src/plugins/vis_types/xy/public/to_ast.ts @@ -8,6 +8,7 @@ import moment from 'moment'; import { Position, ScaleType as ECScaleType } from '@elastic/charts'; +import { i18n } from '@kbn/i18n'; import { VisToExpressionAst, getVisSchemas, @@ -128,7 +129,7 @@ const prepareLayers = ( prepareDecoration(seriesParam.valueAxis, accessor, seriesParam.data.id) ), accessors: yAccessors.map((accessor) => prepareVisDimension(accessor)), - xAccessor: xAccessor ? prepareVisDimension(xAccessor) : undefined, + xAccessor: xAccessor ? prepareVisDimension(xAccessor) : 'all', xScaleType: getScaleType( xScale, xAccessor?.format?.id === 'number' || @@ -399,6 +400,14 @@ export const toExpressionAst: VisToExpressionAst = async (vis, params const xScale = vis.params.categoryAxes[0].scale; + const mapColumn = buildExpressionFunction('mapColumn', { + id: 'all', + expression: '_all', + name: i18n.translate('visTypeXy.allDocsTitle', { + defaultMessage: 'All docs', + }), + }); + const visTypeXy = buildExpressionFunction('layeredXyVis', { layers: [ ...finalSeriesParams @@ -452,12 +461,11 @@ export const toExpressionAst: VisToExpressionAst = async (vis, params : undefined, splitColumnAccessor: dimensions.splitColumn?.map(prepareVisDimension), splitRowAccessor: dimensions.splitRow?.map(prepareVisDimension), - handleEmptyXAccessor: true, valueLabels: vis.params.labels.show ? 'show' : 'hide', useAdjustedInterval: true, }); - const ast = buildExpression([visTypeXy]); + const ast = buildExpression([mapColumn, visTypeXy]); return ast.toAst(); }; From d8067fd2aafe0d5cccf0edbbb3bb8a8ef5a8d4da Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Mon, 25 Jul 2022 18:18:28 +0300 Subject: [PATCH 15/27] Fix tests --- .../public/__snapshots__/to_ast.test.ts.snap | 37 +++++++++++++++---- src/plugins/vis_types/xy/public/to_ast.ts | 20 ++++++---- .../apps/visualize/group2/_inspector.ts | 4 +- .../_line_chart_split_series.ts | 10 ++--- 4 files changed, 49 insertions(+), 22 deletions(-) diff --git a/src/plugins/vis_types/xy/public/__snapshots__/to_ast.test.ts.snap b/src/plugins/vis_types/xy/public/__snapshots__/to_ast.test.ts.snap index f6a2e427fccb4..d659b195429b4 100644 --- a/src/plugins/vis_types/xy/public/__snapshots__/to_ast.test.ts.snap +++ b/src/plugins/vis_types/xy/public/__snapshots__/to_ast.test.ts.snap @@ -4,18 +4,41 @@ exports[`xy vis toExpressionAst function should match basic snapshot 1`] = ` Object { "addArgument": [Function], "arguments": Object { - "expression": Array [ - "_all", + "addTimeMarker": Array [ + false, ], - "id": Array [ - "all", + "layers": Array [ + Object { + "toAst": [Function], + }, ], - "name": Array [ - "All docs", + "legend": Array [ + Object { + "toAst": [Function], + }, + ], + "showTooltip": Array [ + true, + ], + "useAdjustedInterval": Array [ + true, + ], + "valueLabels": Array [ + "hide", + ], + "xAxisConfig": Array [ + Object { + "toAst": [Function], + }, + ], + "yAxisConfigs": Array [ + Object { + "toAst": [Function], + }, ], }, "getArgument": [Function], - "name": "mapColumn", + "name": "layeredXyVis", "removeArgument": [Function], "replaceArgument": [Function], "toAst": [Function], diff --git a/src/plugins/vis_types/xy/public/to_ast.ts b/src/plugins/vis_types/xy/public/to_ast.ts index cd3f07c61423f..f4c0e42b87466 100644 --- a/src/plugins/vis_types/xy/public/to_ast.ts +++ b/src/plugins/vis_types/xy/public/to_ast.ts @@ -400,13 +400,17 @@ export const toExpressionAst: VisToExpressionAst = async (vis, params const xScale = vis.params.categoryAxes[0].scale; - const mapColumn = buildExpressionFunction('mapColumn', { - id: 'all', - expression: '_all', - name: i18n.translate('visTypeXy.allDocsTitle', { - defaultMessage: 'All docs', - }), - }); + let mapColumn; + + if (!dimensions.x) { + mapColumn = buildExpressionFunction('mapColumn', { + id: 'all', + expression: '_all', + name: i18n.translate('visTypeXy.allDocsTitle', { + defaultMessage: 'All docs', + }), + }); + } const visTypeXy = buildExpressionFunction('layeredXyVis', { layers: [ @@ -465,7 +469,7 @@ export const toExpressionAst: VisToExpressionAst = async (vis, params useAdjustedInterval: true, }); - const ast = buildExpression([mapColumn, visTypeXy]); + const ast = buildExpression(mapColumn ? [mapColumn, visTypeXy] : [visTypeXy]); return ast.toAst(); }; diff --git a/test/functional/apps/visualize/group2/_inspector.ts b/test/functional/apps/visualize/group2/_inspector.ts index 7b306f7817f5c..e996c2140718e 100644 --- a/test/functional/apps/visualize/group2/_inspector.ts +++ b/test/functional/apps/visualize/group2/_inspector.ts @@ -58,7 +58,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { describe('inspector table', function indexPatternCreation() { it('should update table header when columns change', async function () { await inspector.open(); - await inspector.expectTableHeaders(['Count']); + await inspector.expectTableHeaders(['Count', 'All docs']); await inspector.close(); log.debug('Add Average Metric on machine.ram field'); @@ -67,7 +67,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.visEditor.selectField('machine.ram', 'metrics'); await PageObjects.visEditor.clickGo(); await inspector.open(); - await inspector.expectTableHeaders(['Count', 'Average machine.ram']); + await inspector.expectTableHeaders(['Count', 'Average machine.ram', 'All docs']); await inspector.close(); }); diff --git a/test/functional/apps/visualize/replaced_vislib_chart_types/_line_chart_split_series.ts b/test/functional/apps/visualize/replaced_vislib_chart_types/_line_chart_split_series.ts index 764cccaa40500..c1df1570008a3 100644 --- a/test/functional/apps/visualize/replaced_vislib_chart_types/_line_chart_split_series.ts +++ b/test/functional/apps/visualize/replaced_vislib_chart_types/_line_chart_split_series.ts @@ -114,11 +114,11 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('should show correct data, ordered by Term', async function () { const expectedChartData = [ - ['png', '1,373'], - ['php', '445'], - ['jpg', '9,109'], - ['gif', '918'], - ['css', '2,159'], + ['png', '1,373', '_all'], + ['php', '445', '_all'], + ['jpg', '9,109', '_all'], + ['gif', '918', '_all'], + ['css', '2,159', '_all'], ]; await inspector.open(); From 8da7181f36662f5274648eece9a4a8f478b3c9ea Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Tue, 26 Jul 2022 10:54:58 +0300 Subject: [PATCH 16/27] Fix test --- .../_line_chart_split_chart.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/functional/apps/visualize/replaced_vislib_chart_types/_line_chart_split_chart.ts b/test/functional/apps/visualize/replaced_vislib_chart_types/_line_chart_split_chart.ts index a42aa6a0ef3e1..4403c2157465a 100644 --- a/test/functional/apps/visualize/replaced_vislib_chart_types/_line_chart_split_chart.ts +++ b/test/functional/apps/visualize/replaced_vislib_chart_types/_line_chart_split_chart.ts @@ -116,11 +116,11 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('should show correct data, ordered by Term', async function () { const expectedChartData = [ - ['png', '1,373'], - ['php', '445'], - ['jpg', '9,109'], - ['gif', '918'], - ['css', '2,159'], + ['png', '1,373', '_all'], + ['php', '445', '_all'], + ['jpg', '9,109', '_all'], + ['gif', '918', '_all'], + ['css', '2,159', '_all'], ]; await inspector.open(); From a85f84514d6517ffb95627e8c0a36bfcc8c75603 Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Tue, 26 Jul 2022 11:51:13 +0300 Subject: [PATCH 17/27] Remove useAdjustedInterval arg --- .../common/expression_functions/common_xy_args.ts | 5 ----- .../expression_xy/common/i18n/index.tsx | 4 ---- .../expression_xy/common/types/expression_functions.ts | 3 --- .../expression_xy/public/components/x_domain.tsx | 10 ++++++---- .../expression_xy/public/components/xy_chart.tsx | 2 -- .../xy/public/__snapshots__/to_ast.test.ts.snap | 3 --- src/plugins/vis_types/xy/public/to_ast.ts | 1 - 7 files changed, 6 insertions(+), 22 deletions(-) diff --git a/src/plugins/chart_expressions/expression_xy/common/expression_functions/common_xy_args.ts b/src/plugins/chart_expressions/expression_xy/common/expression_functions/common_xy_args.ts index 531085285206c..799dc12b1ea5b 100644 --- a/src/plugins/chart_expressions/expression_xy/common/expression_functions/common_xy_args.ts +++ b/src/plugins/chart_expressions/expression_xy/common/expression_functions/common_xy_args.ts @@ -103,9 +103,4 @@ export const commonXYArgs: CommonXYFn['args'] = { types: ['string'], help: strings.getMinTimeBarIntervalHelp(), }, - useAdjustedInterval: { - types: ['boolean'], - default: false, - help: strings.getUseAdjustedIntervalHelp(), - }, }; diff --git a/src/plugins/chart_expressions/expression_xy/common/i18n/index.tsx b/src/plugins/chart_expressions/expression_xy/common/i18n/index.tsx index 46d2dbadb1d20..1e9df3c3ffe64 100644 --- a/src/plugins/chart_expressions/expression_xy/common/i18n/index.tsx +++ b/src/plugins/chart_expressions/expression_xy/common/i18n/index.tsx @@ -129,10 +129,6 @@ export const strings = { i18n.translate('expressionXY.xyVis.splitRowAccessor.help', { defaultMessage: 'Specifies split row of the xy chart', }), - getUseAdjustedIntervalHelp: () => - i18n.translate('expressionXY.xyVis.useAdjustedInterval.help', { - defaultMessage: 'Use adjusted interval fox x domain', - }), getLayersHelp: () => i18n.translate('expressionXY.layeredXyVis.layers.help', { defaultMessage: 'Layers of visual series', diff --git a/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts b/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts index 384f65ca037df..9908f391ec381 100644 --- a/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts +++ b/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts @@ -230,7 +230,6 @@ export interface XYArgs extends DataLayerArgs { detailedTooltip?: boolean; orderBucketsBySum?: boolean; showTooltip: boolean; - useAdjustedInterval?: boolean; } export interface LayeredXYArgs { @@ -254,7 +253,6 @@ export interface LayeredXYArgs { showTooltip: boolean; splitRowAccessor?: ExpressionValueVisDimension | string; splitColumnAccessor?: ExpressionValueVisDimension | string; - useAdjustedInterval?: boolean; } export interface XYProps { @@ -278,7 +276,6 @@ export interface XYProps { detailedTooltip?: boolean; orderBucketsBySum?: boolean; showTooltip: boolean; - useAdjustedInterval?: boolean; } export interface AnnotationLayerArgs { diff --git a/src/plugins/chart_expressions/expression_xy/public/components/x_domain.tsx b/src/plugins/chart_expressions/expression_xy/public/components/x_domain.tsx index c1bcb70e7590f..d11bcb0bfe071 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/x_domain.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/x_domain.tsx @@ -50,7 +50,6 @@ export const getXDomain = ( isHistogram: boolean, hasBars: boolean, timeZone: string, - useAdjustedInterval?: boolean, xExtent?: AxisExtentConfigResult ) => { const appliedTimeRange = getAppliedTimeRange(datatableUtilitites, layers)?.timeRange; @@ -104,9 +103,12 @@ export const getXDomain = ( extendedDomain: { min: domainMin, max: domainMax, - minInterval: useAdjustedInterval - ? getAdjustedInterval(xValues, duration.as(selectedUnit), selectedUnit, timeZone) - : baseDomain.minInterval, + minInterval: getAdjustedInterval( + xValues, + duration.as(selectedUnit), + selectedUnit, + timeZone + ), }, baseDomain, }; diff --git a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx index 41fb5234e48ed..05f2d53b5902b 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx @@ -195,7 +195,6 @@ export function XYChart({ xAxisConfig, splitColumnAccessor, splitRowAccessor, - useAdjustedInterval, } = args; const chartRef = useRef(null); const chartTheme = chartsThemeService.useChartsTheme(); @@ -356,7 +355,6 @@ export function XYChart({ isHistogramViz, hasBars, timeZone, - useAdjustedInterval, xAxisConfig?.extent ); diff --git a/src/plugins/vis_types/xy/public/__snapshots__/to_ast.test.ts.snap b/src/plugins/vis_types/xy/public/__snapshots__/to_ast.test.ts.snap index d659b195429b4..8f11e3521cdd7 100644 --- a/src/plugins/vis_types/xy/public/__snapshots__/to_ast.test.ts.snap +++ b/src/plugins/vis_types/xy/public/__snapshots__/to_ast.test.ts.snap @@ -20,9 +20,6 @@ Object { "showTooltip": Array [ true, ], - "useAdjustedInterval": Array [ - true, - ], "valueLabels": Array [ "hide", ], diff --git a/src/plugins/vis_types/xy/public/to_ast.ts b/src/plugins/vis_types/xy/public/to_ast.ts index f4c0e42b87466..025732a9e24ae 100644 --- a/src/plugins/vis_types/xy/public/to_ast.ts +++ b/src/plugins/vis_types/xy/public/to_ast.ts @@ -466,7 +466,6 @@ export const toExpressionAst: VisToExpressionAst = async (vis, params splitColumnAccessor: dimensions.splitColumn?.map(prepareVisDimension), splitRowAccessor: dimensions.splitRow?.map(prepareVisDimension), valueLabels: vis.params.labels.show ? 'show' : 'hide', - useAdjustedInterval: true, }); const ast = buildExpression(mapColumn ? [mapColumn, visTypeXy] : [visTypeXy]); From 7a6faa41c877b76811dd252aab27b0dfa4f1d532 Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Wed, 27 Jul 2022 17:43:10 +0300 Subject: [PATCH 18/27] Fix remarks --- .../expression_xy/common/constants.ts | 1 + .../axis_extent_config.ts | 6 + .../expression_functions/layered_xy_vis_fn.ts | 4 +- .../common/expression_functions/validate.ts | 2 +- .../expression_xy/common/helpers/table.ts | 5 +- .../common/types/expression_functions.ts | 1 + .../__snapshots__/xy_chart.test.tsx.snap | 468 ++++++++++++++++++ .../components/reference_lines/utils.tsx | 7 + .../components/tooltip/tooltip.test.tsx | 4 +- .../public/components/tooltip/tooltip.tsx | 8 +- .../public/components/xy_chart.tsx | 73 ++- .../public/definitions/visualizations.ts | 1 + .../public/helpers/data_layers.tsx | 23 +- src/plugins/vis_types/xy/public/to_ast.ts | 20 +- 14 files changed, 587 insertions(+), 36 deletions(-) diff --git a/src/plugins/chart_expressions/expression_xy/common/constants.ts b/src/plugins/chart_expressions/expression_xy/common/constants.ts index 7392bb9da43c2..8116f0146f19a 100644 --- a/src/plugins/chart_expressions/expression_xy/common/constants.ts +++ b/src/plugins/chart_expressions/expression_xy/common/constants.ts @@ -62,6 +62,7 @@ export const LineStyles = { SOLID: 'solid', DASHED: 'dashed', DOTTED: 'dotted', + DOT_DASHED: 'dot-dashed', } as const; export const FillStyles = { diff --git a/src/plugins/chart_expressions/expression_xy/common/expression_functions/axis_extent_config.ts b/src/plugins/chart_expressions/expression_xy/common/expression_functions/axis_extent_config.ts index c1a4070225a64..613b631d8c9c4 100644 --- a/src/plugins/chart_expressions/expression_xy/common/expression_functions/axis_extent_config.ts +++ b/src/plugins/chart_expressions/expression_xy/common/expression_functions/axis_extent_config.ts @@ -53,6 +53,12 @@ export const axisExtentConfigFunction: ExpressionFunctionDefinition< defaultMessage: 'Upper bound', }), }, + enforce: { + types: ['boolean'], + help: i18n.translate('expressionXY.axisExtentConfig.enforce.help', { + defaultMessage: 'Enforce extent params.', + }), + }, }, fn(input, args) { if (args.mode === AxisExtentModes.CUSTOM) { diff --git a/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis_fn.ts b/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis_fn.ts index f022e14535b68..b23e811584aab 100644 --- a/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis_fn.ts +++ b/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis_fn.ts @@ -21,15 +21,15 @@ import { appendLayerIds, getDataLayers } from '../helpers'; export const layeredXyVisFn: LayeredXyVisFn['fn'] = async (data, args, handlers) => { const layers = appendLayerIds(args.layers ?? [], 'layers'); + const dataLayers = getDataLayers(layers); // for visialize we should log one datable for all layers - if (handlers.getExecutionContext()?.name === 'visualize') { + if (dataLayers.every((l) => l.table === dataLayers[0].table)) { logDatatable(data, layers, handlers, args.splitColumnAccessor, args.splitRowAccessor); } else { logDatatables(layers, handlers, args.splitColumnAccessor, args.splitRowAccessor); } - const dataLayers = getDataLayers(layers); const hasBar = hasBarLayer(dataLayers); validateAddTimeMarker(dataLayers, args.addTimeMarker); validateMarkSizeRatioLimits(args.markSizeRatio); diff --git a/src/plugins/chart_expressions/expression_xy/common/expression_functions/validate.ts b/src/plugins/chart_expressions/expression_xy/common/expression_functions/validate.ts index 9b8183abfa205..6c88d0ff6a62c 100644 --- a/src/plugins/chart_expressions/expression_xy/common/expression_functions/validate.ts +++ b/src/plugins/chart_expressions/expression_xy/common/expression_functions/validate.ts @@ -171,7 +171,7 @@ export const validateExtents = ( xAxisConfig?: XAxisConfigResult ) => { yAxisConfigs?.forEach((axis) => { - if (!axis.extent) { + if (!axis.extent || axis.extent.enforce) { return; } if ( diff --git a/src/plugins/chart_expressions/expression_xy/common/helpers/table.ts b/src/plugins/chart_expressions/expression_xy/common/helpers/table.ts index 65cae152c0caf..09171f8f72ff5 100644 --- a/src/plugins/chart_expressions/expression_xy/common/helpers/table.ts +++ b/src/plugins/chart_expressions/expression_xy/common/helpers/table.ts @@ -15,7 +15,10 @@ export function normalizeTable(data: Datatable, xAccessor?: string | ExpressionV const xColumn = xAccessor && getColumnByAccessor(xAccessor, data.columns); if (xColumn && xColumn?.meta.type === 'date') { const xColumnId = xColumn.id; - if (!data.rows.some((row) => typeof row[xColumnId] === 'string')) return data; + if ( + !data.rows.some((row) => typeof row[xColumnId] === 'string' && row[xColumnId] !== '__other__') + ) + return data; const rows = data.rows.map((row) => { return typeof row[xColumnId] !== 'string' ? row diff --git a/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts b/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts index 9908f391ec381..afb6909482a4c 100644 --- a/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts +++ b/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts @@ -71,6 +71,7 @@ export interface AxisExtentConfig { mode: AxisExtentMode; lowerBound?: number; upperBound?: number; + enforce?: boolean; } export interface AxisConfig { diff --git a/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap b/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap index 0fcb66319a0c7..60acbd6fd3daf 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap +++ b/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap @@ -7268,18 +7268,32 @@ exports[`XYChart component split chart should render split chart if both, splitR "formatter": Object { "convert": [MockFunction] { "calls": Array [ + Array [ + 2, + ], Array [ 1652034840000, ], + Array [ + 5, + ], Array [ 1652122440000, ], ], "results": Array [ + Object { + "type": "return", + "value": 2, + }, Object { "type": "return", "value": 1652034840000, }, + Object { + "type": "return", + "value": 5, + }, Object { "type": "return", "value": 1652122440000, @@ -7313,6 +7327,7 @@ exports[`XYChart component split chart should render split chart if both, splitR "formattedDatatables": Object { "first": Object { "formattedColumns": Object { + "b": true, "c": true, }, "table": Object { @@ -7632,18 +7647,32 @@ exports[`XYChart component split chart should render split chart if both, splitR "formatter": Object { "convert": [MockFunction] { "calls": Array [ + Array [ + 2, + ], Array [ 1652034840000, ], + Array [ + 5, + ], Array [ 1652122440000, ], ], "results": Array [ + Object { + "type": "return", + "value": 2, + }, Object { "type": "return", "value": 1652034840000, }, + Object { + "type": "return", + "value": 5, + }, Object { "type": "return", "value": 1652122440000, @@ -7737,18 +7766,32 @@ exports[`XYChart component split chart should render split chart if both, splitR "value": Object { "convert": [MockFunction] { "calls": Array [ + Array [ + 2, + ], Array [ 1652034840000, ], + Array [ + 5, + ], Array [ 1652122440000, ], ], "results": Array [ + Object { + "type": "return", + "value": 2, + }, Object { "type": "return", "value": 1652034840000, }, + Object { + "type": "return", + "value": 5, + }, Object { "type": "return", "value": 1652122440000, @@ -7762,18 +7805,32 @@ exports[`XYChart component split chart should render split chart if both, splitR "value": Object { "convert": [MockFunction] { "calls": Array [ + Array [ + 2, + ], Array [ 1652034840000, ], + Array [ + 5, + ], Array [ 1652122440000, ], ], "results": Array [ + Object { + "type": "return", + "value": 2, + }, Object { "type": "return", "value": 1652034840000, }, + Object { + "type": "return", + "value": 5, + }, Object { "type": "return", "value": 1652122440000, @@ -7787,18 +7844,32 @@ exports[`XYChart component split chart should render split chart if both, splitR "value": Object { "convert": [MockFunction] { "calls": Array [ + Array [ + 2, + ], Array [ 1652034840000, ], + Array [ + 5, + ], Array [ 1652122440000, ], ], "results": Array [ + Object { + "type": "return", + "value": 2, + }, Object { "type": "return", "value": 1652034840000, }, + Object { + "type": "return", + "value": 5, + }, Object { "type": "return", "value": 1652122440000, @@ -7812,18 +7883,32 @@ exports[`XYChart component split chart should render split chart if both, splitR "value": Object { "convert": [MockFunction] { "calls": Array [ + Array [ + 2, + ], Array [ 1652034840000, ], + Array [ + 5, + ], Array [ 1652122440000, ], ], "results": Array [ + Object { + "type": "return", + "value": 2, + }, Object { "type": "return", "value": 1652034840000, }, + Object { + "type": "return", + "value": 5, + }, Object { "type": "return", "value": 1652122440000, @@ -7837,18 +7922,32 @@ exports[`XYChart component split chart should render split chart if both, splitR "value": Object { "convert": [MockFunction] { "calls": Array [ + Array [ + 2, + ], Array [ 1652034840000, ], + Array [ + 5, + ], Array [ 1652122440000, ], ], "results": Array [ + Object { + "type": "return", + "value": 2, + }, Object { "type": "return", "value": 1652034840000, }, + Object { + "type": "return", + "value": 5, + }, Object { "type": "return", "value": 1652122440000, @@ -7862,18 +7961,32 @@ exports[`XYChart component split chart should render split chart if both, splitR "value": Object { "convert": [MockFunction] { "calls": Array [ + Array [ + 2, + ], Array [ 1652034840000, ], + Array [ + 5, + ], Array [ 1652122440000, ], ], "results": Array [ + Object { + "type": "return", + "value": 2, + }, Object { "type": "return", "value": 1652034840000, }, + Object { + "type": "return", + "value": 5, + }, Object { "type": "return", "value": 1652122440000, @@ -7887,18 +8000,32 @@ exports[`XYChart component split chart should render split chart if both, splitR "value": Object { "convert": [MockFunction] { "calls": Array [ + Array [ + 2, + ], Array [ 1652034840000, ], + Array [ + 5, + ], Array [ 1652122440000, ], ], "results": Array [ + Object { + "type": "return", + "value": 2, + }, Object { "type": "return", "value": 1652034840000, }, + Object { + "type": "return", + "value": 5, + }, Object { "type": "return", "value": 1652122440000, @@ -7912,18 +8039,32 @@ exports[`XYChart component split chart should render split chart if both, splitR "value": Object { "convert": [MockFunction] { "calls": Array [ + Array [ + 2, + ], Array [ 1652034840000, ], + Array [ + 5, + ], Array [ 1652122440000, ], ], "results": Array [ + Object { + "type": "return", + "value": 2, + }, Object { "type": "return", "value": 1652034840000, }, + Object { + "type": "return", + "value": 5, + }, Object { "type": "return", "value": 1652122440000, @@ -7939,6 +8080,7 @@ exports[`XYChart component split chart should render split chart if both, splitR Object { "first": Object { "formattedColumns": Object { + "b": true, "c": true, }, "table": Object { @@ -8154,18 +8296,32 @@ exports[`XYChart component split chart should render split chart if both, splitR "formatter": Object { "convert": [MockFunction] { "calls": Array [ + Array [ + 2, + ], Array [ 1652034840000, ], + Array [ + 5, + ], Array [ 1652122440000, ], ], "results": Array [ + Object { + "type": "return", + "value": 2, + }, Object { "type": "return", "value": 1652034840000, }, + Object { + "type": "return", + "value": 5, + }, Object { "type": "return", "value": 1652122440000, @@ -8331,18 +8487,32 @@ exports[`XYChart component split chart should render split chart if splitColumnA "formatter": Object { "convert": [MockFunction] { "calls": Array [ + Array [ + 2, + ], Array [ 1652034840000, ], + Array [ + 5, + ], Array [ 1652122440000, ], ], "results": Array [ + Object { + "type": "return", + "value": 2, + }, Object { "type": "return", "value": 1652034840000, }, + Object { + "type": "return", + "value": 5, + }, Object { "type": "return", "value": 1652122440000, @@ -8376,6 +8546,7 @@ exports[`XYChart component split chart should render split chart if splitColumnA "formattedDatatables": Object { "first": Object { "formattedColumns": Object { + "b": true, "c": true, }, "table": Object { @@ -8688,18 +8859,32 @@ exports[`XYChart component split chart should render split chart if splitColumnA "formatter": Object { "convert": [MockFunction] { "calls": Array [ + Array [ + 2, + ], Array [ 1652034840000, ], + Array [ + 5, + ], Array [ 1652122440000, ], ], "results": Array [ + Object { + "type": "return", + "value": 2, + }, Object { "type": "return", "value": 1652034840000, }, + Object { + "type": "return", + "value": 5, + }, Object { "type": "return", "value": 1652122440000, @@ -8793,18 +8978,32 @@ exports[`XYChart component split chart should render split chart if splitColumnA "value": Object { "convert": [MockFunction] { "calls": Array [ + Array [ + 2, + ], Array [ 1652034840000, ], + Array [ + 5, + ], Array [ 1652122440000, ], ], "results": Array [ + Object { + "type": "return", + "value": 2, + }, Object { "type": "return", "value": 1652034840000, }, + Object { + "type": "return", + "value": 5, + }, Object { "type": "return", "value": 1652122440000, @@ -8818,18 +9017,32 @@ exports[`XYChart component split chart should render split chart if splitColumnA "value": Object { "convert": [MockFunction] { "calls": Array [ + Array [ + 2, + ], Array [ 1652034840000, ], + Array [ + 5, + ], Array [ 1652122440000, ], ], "results": Array [ + Object { + "type": "return", + "value": 2, + }, Object { "type": "return", "value": 1652034840000, }, + Object { + "type": "return", + "value": 5, + }, Object { "type": "return", "value": 1652122440000, @@ -8843,18 +9056,32 @@ exports[`XYChart component split chart should render split chart if splitColumnA "value": Object { "convert": [MockFunction] { "calls": Array [ + Array [ + 2, + ], Array [ 1652034840000, ], + Array [ + 5, + ], Array [ 1652122440000, ], ], "results": Array [ + Object { + "type": "return", + "value": 2, + }, Object { "type": "return", "value": 1652034840000, }, + Object { + "type": "return", + "value": 5, + }, Object { "type": "return", "value": 1652122440000, @@ -8868,18 +9095,32 @@ exports[`XYChart component split chart should render split chart if splitColumnA "value": Object { "convert": [MockFunction] { "calls": Array [ + Array [ + 2, + ], Array [ 1652034840000, ], + Array [ + 5, + ], Array [ 1652122440000, ], ], "results": Array [ + Object { + "type": "return", + "value": 2, + }, Object { "type": "return", "value": 1652034840000, }, + Object { + "type": "return", + "value": 5, + }, Object { "type": "return", "value": 1652122440000, @@ -8893,18 +9134,32 @@ exports[`XYChart component split chart should render split chart if splitColumnA "value": Object { "convert": [MockFunction] { "calls": Array [ + Array [ + 2, + ], Array [ 1652034840000, ], + Array [ + 5, + ], Array [ 1652122440000, ], ], "results": Array [ + Object { + "type": "return", + "value": 2, + }, Object { "type": "return", "value": 1652034840000, }, + Object { + "type": "return", + "value": 5, + }, Object { "type": "return", "value": 1652122440000, @@ -8918,18 +9173,32 @@ exports[`XYChart component split chart should render split chart if splitColumnA "value": Object { "convert": [MockFunction] { "calls": Array [ + Array [ + 2, + ], Array [ 1652034840000, ], + Array [ + 5, + ], Array [ 1652122440000, ], ], "results": Array [ + Object { + "type": "return", + "value": 2, + }, Object { "type": "return", "value": 1652034840000, }, + Object { + "type": "return", + "value": 5, + }, Object { "type": "return", "value": 1652122440000, @@ -8943,18 +9212,32 @@ exports[`XYChart component split chart should render split chart if splitColumnA "value": Object { "convert": [MockFunction] { "calls": Array [ + Array [ + 2, + ], Array [ 1652034840000, ], + Array [ + 5, + ], Array [ 1652122440000, ], ], "results": Array [ + Object { + "type": "return", + "value": 2, + }, Object { "type": "return", "value": 1652034840000, }, + Object { + "type": "return", + "value": 5, + }, Object { "type": "return", "value": 1652122440000, @@ -8968,18 +9251,32 @@ exports[`XYChart component split chart should render split chart if splitColumnA "value": Object { "convert": [MockFunction] { "calls": Array [ + Array [ + 2, + ], Array [ 1652034840000, ], + Array [ + 5, + ], Array [ 1652122440000, ], ], "results": Array [ + Object { + "type": "return", + "value": 2, + }, Object { "type": "return", "value": 1652034840000, }, + Object { + "type": "return", + "value": 5, + }, Object { "type": "return", "value": 1652122440000, @@ -8995,6 +9292,7 @@ exports[`XYChart component split chart should render split chart if splitColumnA Object { "first": Object { "formattedColumns": Object { + "b": true, "c": true, }, "table": Object { @@ -9208,18 +9506,32 @@ exports[`XYChart component split chart should render split chart if splitColumnA "formatter": Object { "convert": [MockFunction] { "calls": Array [ + Array [ + 2, + ], Array [ 1652034840000, ], + Array [ + 5, + ], Array [ 1652122440000, ], ], "results": Array [ + Object { + "type": "return", + "value": 2, + }, Object { "type": "return", "value": 1652034840000, }, + Object { + "type": "return", + "value": 5, + }, Object { "type": "return", "value": 1652122440000, @@ -9385,18 +9697,32 @@ exports[`XYChart component split chart should render split chart if splitRowAcce "formatter": Object { "convert": [MockFunction] { "calls": Array [ + Array [ + 2, + ], Array [ 1652034840000, ], + Array [ + 5, + ], Array [ 1652122440000, ], ], "results": Array [ + Object { + "type": "return", + "value": 2, + }, Object { "type": "return", "value": 1652034840000, }, + Object { + "type": "return", + "value": 5, + }, Object { "type": "return", "value": 1652122440000, @@ -9430,6 +9756,7 @@ exports[`XYChart component split chart should render split chart if splitRowAcce "formattedDatatables": Object { "first": Object { "formattedColumns": Object { + "b": true, "c": true, }, "table": Object { @@ -9742,18 +10069,32 @@ exports[`XYChart component split chart should render split chart if splitRowAcce "formatter": Object { "convert": [MockFunction] { "calls": Array [ + Array [ + 2, + ], Array [ 1652034840000, ], + Array [ + 5, + ], Array [ 1652122440000, ], ], "results": Array [ + Object { + "type": "return", + "value": 2, + }, Object { "type": "return", "value": 1652034840000, }, + Object { + "type": "return", + "value": 5, + }, Object { "type": "return", "value": 1652122440000, @@ -9847,18 +10188,32 @@ exports[`XYChart component split chart should render split chart if splitRowAcce "value": Object { "convert": [MockFunction] { "calls": Array [ + Array [ + 2, + ], Array [ 1652034840000, ], + Array [ + 5, + ], Array [ 1652122440000, ], ], "results": Array [ + Object { + "type": "return", + "value": 2, + }, Object { "type": "return", "value": 1652034840000, }, + Object { + "type": "return", + "value": 5, + }, Object { "type": "return", "value": 1652122440000, @@ -9872,18 +10227,32 @@ exports[`XYChart component split chart should render split chart if splitRowAcce "value": Object { "convert": [MockFunction] { "calls": Array [ + Array [ + 2, + ], Array [ 1652034840000, ], + Array [ + 5, + ], Array [ 1652122440000, ], ], "results": Array [ + Object { + "type": "return", + "value": 2, + }, Object { "type": "return", "value": 1652034840000, }, + Object { + "type": "return", + "value": 5, + }, Object { "type": "return", "value": 1652122440000, @@ -9897,18 +10266,32 @@ exports[`XYChart component split chart should render split chart if splitRowAcce "value": Object { "convert": [MockFunction] { "calls": Array [ + Array [ + 2, + ], Array [ 1652034840000, ], + Array [ + 5, + ], Array [ 1652122440000, ], ], "results": Array [ + Object { + "type": "return", + "value": 2, + }, Object { "type": "return", "value": 1652034840000, }, + Object { + "type": "return", + "value": 5, + }, Object { "type": "return", "value": 1652122440000, @@ -9922,18 +10305,32 @@ exports[`XYChart component split chart should render split chart if splitRowAcce "value": Object { "convert": [MockFunction] { "calls": Array [ + Array [ + 2, + ], Array [ 1652034840000, ], + Array [ + 5, + ], Array [ 1652122440000, ], ], "results": Array [ + Object { + "type": "return", + "value": 2, + }, Object { "type": "return", "value": 1652034840000, }, + Object { + "type": "return", + "value": 5, + }, Object { "type": "return", "value": 1652122440000, @@ -9947,18 +10344,32 @@ exports[`XYChart component split chart should render split chart if splitRowAcce "value": Object { "convert": [MockFunction] { "calls": Array [ + Array [ + 2, + ], Array [ 1652034840000, ], + Array [ + 5, + ], Array [ 1652122440000, ], ], "results": Array [ + Object { + "type": "return", + "value": 2, + }, Object { "type": "return", "value": 1652034840000, }, + Object { + "type": "return", + "value": 5, + }, Object { "type": "return", "value": 1652122440000, @@ -9972,18 +10383,32 @@ exports[`XYChart component split chart should render split chart if splitRowAcce "value": Object { "convert": [MockFunction] { "calls": Array [ + Array [ + 2, + ], Array [ 1652034840000, ], + Array [ + 5, + ], Array [ 1652122440000, ], ], "results": Array [ + Object { + "type": "return", + "value": 2, + }, Object { "type": "return", "value": 1652034840000, }, + Object { + "type": "return", + "value": 5, + }, Object { "type": "return", "value": 1652122440000, @@ -9997,18 +10422,32 @@ exports[`XYChart component split chart should render split chart if splitRowAcce "value": Object { "convert": [MockFunction] { "calls": Array [ + Array [ + 2, + ], Array [ 1652034840000, ], + Array [ + 5, + ], Array [ 1652122440000, ], ], "results": Array [ + Object { + "type": "return", + "value": 2, + }, Object { "type": "return", "value": 1652034840000, }, + Object { + "type": "return", + "value": 5, + }, Object { "type": "return", "value": 1652122440000, @@ -10022,18 +10461,32 @@ exports[`XYChart component split chart should render split chart if splitRowAcce "value": Object { "convert": [MockFunction] { "calls": Array [ + Array [ + 2, + ], Array [ 1652034840000, ], + Array [ + 5, + ], Array [ 1652122440000, ], ], "results": Array [ + Object { + "type": "return", + "value": 2, + }, Object { "type": "return", "value": 1652034840000, }, + Object { + "type": "return", + "value": 5, + }, Object { "type": "return", "value": 1652122440000, @@ -10049,6 +10502,7 @@ exports[`XYChart component split chart should render split chart if splitRowAcce Object { "first": Object { "formattedColumns": Object { + "b": true, "c": true, }, "table": Object { @@ -10262,18 +10716,32 @@ exports[`XYChart component split chart should render split chart if splitRowAcce "formatter": Object { "convert": [MockFunction] { "calls": Array [ + Array [ + 2, + ], Array [ 1652034840000, ], + Array [ + 5, + ], Array [ 1652122440000, ], ], "results": Array [ + Object { + "type": "return", + "value": 2, + }, Object { "type": "return", "value": 1652034840000, }, + Object { + "type": "return", + "value": 5, + }, Object { "type": "return", "value": 1652122440000, diff --git a/src/plugins/chart_expressions/expression_xy/public/components/reference_lines/utils.tsx b/src/plugins/chart_expressions/expression_xy/public/components/reference_lines/utils.tsx index fab4f9a665526..387dc6b499f80 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/reference_lines/utils.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/reference_lines/utils.tsx @@ -72,6 +72,13 @@ export const getSharedStyle = (config: ReferenceLineAnnotationConfig) => ({ ? [(config.lineWidth || 1) * 3, config.lineWidth || 1] : config.lineStyle === 'dotted' ? [config.lineWidth || 1, config.lineWidth || 1] + : config.lineStyle === 'dot-dashed' + ? [ + (config.lineWidth || 1) * 5, + config.lineWidth || 1, + config.lineWidth || 1, + config.lineWidth || 1, + ] : undefined, }); diff --git a/src/plugins/chart_expressions/expression_xy/public/components/tooltip/tooltip.test.tsx b/src/plugins/chart_expressions/expression_xy/public/components/tooltip/tooltip.test.tsx index 38ef236e971a6..da6d5032158cb 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/tooltip/tooltip.test.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/tooltip/tooltip.test.tsx @@ -37,8 +37,8 @@ const getSeriesIdentifier = ({ splitAccessors: seriesSplitAccessors, seriesKeys: [], key: '1', - smVerticalAccessorValue: splitColumnAccessor, - smHorizontalAccessorValue: splitRowAccessor, + smVerticalAccessorValue: splitRowAccessor, + smHorizontalAccessorValue: splitColumnAccessor, }); describe('Tooltip', () => { diff --git a/src/plugins/chart_expressions/expression_xy/public/components/tooltip/tooltip.tsx b/src/plugins/chart_expressions/expression_xy/public/components/tooltip/tooltip.tsx index 7ab7c9f549e24..4f4568bdcd1be 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/tooltip/tooltip.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/tooltip/tooltip.tsx @@ -87,21 +87,21 @@ export const Tooltip: FC = ({ if ( splitAccessors?.splitColumnAccessor && - seriesIdentifier.smVerticalAccessorValue !== undefined + seriesIdentifier.smHorizontalAccessorValue !== undefined ) { data.push({ label: layerTitles?.splitColumnTitles?.[splitAccessors?.splitColumnAccessor], - value: `${seriesIdentifier.smVerticalAccessorValue}`, + value: `${seriesIdentifier.smHorizontalAccessorValue}`, }); } if ( splitAccessors?.splitRowAccessor && - seriesIdentifier.smHorizontalAccessorValue !== undefined + seriesIdentifier.smVerticalAccessorValue !== undefined ) { data.push({ label: layerTitles?.splitRowTitles?.[splitAccessors?.splitRowAccessor], - value: `${seriesIdentifier.smHorizontalAccessorValue}`, + value: `${seriesIdentifier.smVerticalAccessorValue}`, }); } diff --git a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx index 05f2d53b5902b..7462453d5a20a 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx @@ -30,7 +30,7 @@ import { } from '@elastic/charts'; import { IconType } from '@elastic/eui'; import { PaletteRegistry } from '@kbn/coloring'; -import { RenderMode } from '@kbn/expressions-plugin/common'; +import { Datatable, RenderMode } from '@kbn/expressions-plugin/common'; import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; import { EmptyPlaceholder, LegendToggle } from '@kbn/charts-plugin/public'; import { EventAnnotationServiceType } from '@kbn/event-annotation-plugin/public'; @@ -158,10 +158,29 @@ function getIconForSeriesType(layer: CommonXYDataLayerConfig): IconType { `${layer.seriesType}${layer.isHorizontal ? '_horizontal' : ''}${ layer.isPercentage ? '_percentage' : '' }${layer.isStacked ? '_stacked' : ''}` - )!.icon || 'empty' + )?.icon || 'empty' ); } +function createSplitPoint( + accessor: string | number, + value: string | number, + rows: Datatable['rows'], + table: Datatable +) { + const splitPointRowIndex = rows.findIndex((row) => { + return row[accessor] === value; + }); + if (splitPointRowIndex !== -1) { + return { + row: splitPointRowIndex, + column: table.columns.findIndex((column) => column.id === accessor), + value: table.rows[splitPointRowIndex][accessor], + table, + }; + } +} + export const XYChartReportable = React.memo(XYChart); export function XYChart({ @@ -264,7 +283,8 @@ export function XYChart({ const dataLayers: CommonXYDataLayerConfig[] = filteredLayers.filter(isDataLayer); const formattedDatatables = useMemo( - () => getFormattedTablesByLayers(dataLayers, formatFactory), + () => + getFormattedTablesByLayers(dataLayers, formatFactory, splitColumnAccessor, splitRowAccessor), [dataLayers, formatFactory] ); @@ -463,7 +483,7 @@ export function XYChart({ let max: number = NaN; if (extent.mode === 'custom') { const { inclusiveZeroError, boundaryError } = validateExtent(hasBarOrArea, extent); - if (!inclusiveZeroError && !boundaryError) { + if ((!inclusiveZeroError && !boundaryError) || extent.enforce) { min = extent.lowerBound ?? NaN; max = extent.upperBound ?? NaN; } @@ -560,21 +580,44 @@ export function XYChart({ if (xySeries.seriesKeys.length > 1) { xySeries.splitAccessors.forEach((value, accessor) => { - const splitPointRowIndex = formattedDatatables[layer.layerId].table.rows.findIndex( - (row) => { - return row[accessor] === value; - } + const point = createSplitPoint( + accessor, + value, + formattedDatatables[layer.layerId].table.rows, + table ); - if (splitPointRowIndex !== -1) { - splitPoints.push({ - row: splitPointRowIndex, - column: table.columns.findIndex((column) => column.id === accessor), - value: table.rows[splitPointRowIndex][accessor], - table, - }); + if (point) { + splitPoints.push(point); } }); } + + if (xySeries.smHorizontalAccessorValue && splitColumnAccessor) { + const accessor = getAccessorByDimension(splitColumnAccessor, table.columns); + const point = createSplitPoint( + accessor, + xySeries.smHorizontalAccessorValue, + formattedDatatables[layer.layerId].table.rows, + table + ); + if (point) { + splitPoints.push(point); + } + } + + if (xySeries.smVerticalAccessorValue && splitRowAccessor) { + const accessor = getAccessorByDimension(splitRowAccessor, table.columns); + const point = createSplitPoint( + accessor, + xySeries.smVerticalAccessorValue, + formattedDatatables[layer.layerId].table.rows, + table + ); + if (point) { + splitPoints.push(point); + } + } + const context: FilterEvent['data'] = { data: [...points, ...splitPoints], }; diff --git a/src/plugins/chart_expressions/expression_xy/public/definitions/visualizations.ts b/src/plugins/chart_expressions/expression_xy/public/definitions/visualizations.ts index d16d8204846fc..bb4acd7fa50de 100644 --- a/src/plugins/chart_expressions/expression_xy/public/definitions/visualizations.ts +++ b/src/plugins/chart_expressions/expression_xy/public/definitions/visualizations.ts @@ -28,6 +28,7 @@ export const visualizationDefinitions = [ { id: `${SeriesTypes.BAR}_horizontal_stacked`, icon: BarHorizontalStackedIcon }, { id: `${SeriesTypes.BAR}_horizontal_percentage_stacked`, icon: BarHorizontalPercentageIcon }, { id: SeriesTypes.LINE, icon: LineIcon }, + { id: `${SeriesTypes.LINE}_stacked`, icon: LineIcon }, { id: SeriesTypes.AREA, icon: AreaIcon }, { id: `${SeriesTypes.AREA}_stacked`, icon: AreaStackedIcon }, { id: `${SeriesTypes.AREA}_percentage_stacked`, icon: AreaPercentageIcon }, diff --git a/src/plugins/chart_expressions/expression_xy/public/helpers/data_layers.tsx b/src/plugins/chart_expressions/expression_xy/public/helpers/data_layers.tsx index 66d080c73db96..96c2fece7301d 100644 --- a/src/plugins/chart_expressions/expression_xy/public/helpers/data_layers.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/helpers/data_layers.tsx @@ -110,6 +110,8 @@ export const getFormattedRow = ( columns: Datatable['columns'], columnsFormatters: Record, xAccessor: string | undefined, + splitColumnAccessor: string | undefined, + splitRowAccessor: string | undefined, xScaleType: XScaleType ): { row: Datatable['rows'][number]; formattedColumns: Record } => columns.reduce( @@ -118,7 +120,10 @@ export const getFormattedRow = ( if ( record != null && // pre-format values for ordinal x axes because there can only be a single x axis formatter on chart level - (!isPrimitive(record) || (id === xAccessor && xScaleType === 'ordinal')) + (!isPrimitive(record) || + (id === xAccessor && xScaleType === 'ordinal') || + id === splitColumnAccessor || + id === splitRowAccessor) ) { return { row: { ...formattedInfo.row, [id]: columnsFormatters[id]!.convert(record) }, @@ -134,6 +139,8 @@ export const getFormattedTable = ( table: Datatable, formatFactory: FormatFactory, xAccessor: string | ExpressionValueVisDimension | undefined, + splitColumnAccessor: string | ExpressionValueVisDimension | undefined, + splitRowAccessor: string | ExpressionValueVisDimension | undefined, accessors: Array, xScaleType: XScaleType ): { table: Datatable; formattedColumns: Record } => { @@ -164,6 +171,8 @@ export const getFormattedTable = ( table.columns, columnsFormatters, xAccessor ? getAccessorByDimension(xAccessor, table.columns) : undefined, + splitColumnAccessor ? getAccessorByDimension(splitColumnAccessor, table.columns) : undefined, + splitRowAccessor ? getAccessorByDimension(splitRowAccessor, table.columns) : undefined, xScaleType ); formattedTableInfo.rows.push(formattedRowInfo.row); @@ -181,7 +190,9 @@ export const getFormattedTable = ( export const getFormattedTablesByLayers = ( layers: CommonXYDataLayerConfig[], - formatFactory: FormatFactory + formatFactory: FormatFactory, + splitColumnAccessor?: string | ExpressionValueVisDimension, + splitRowAccessor?: string | ExpressionValueVisDimension ): DatatablesWithFormatInfo => layers.reduce( ( @@ -193,9 +204,11 @@ export const getFormattedTablesByLayers = ( table, formatFactory, xAccessor, - [xAccessor, ...splitAccessors, ...accessors].filter( - (a): a is string | ExpressionValueVisDimension => a !== undefined - ), + splitColumnAccessor, + splitRowAccessor, + [xAccessor, ...splitAccessors, ...accessors, splitColumnAccessor, splitRowAccessor].filter< + string | ExpressionValueVisDimension + >((a): a is string | ExpressionValueVisDimension => a !== undefined), xScaleType ), }), diff --git a/src/plugins/vis_types/xy/public/to_ast.ts b/src/plugins/vis_types/xy/public/to_ast.ts index 025732a9e24ae..07a58a258abd6 100644 --- a/src/plugins/vis_types/xy/public/to_ast.ts +++ b/src/plugins/vis_types/xy/public/to_ast.ts @@ -140,7 +140,8 @@ const prepareLayers = ( 'interval' in (xAccessor?.params || {}) ), splitAccessors: splitAccessors ? splitAccessors.map(prepareVisDimension) : undefined, - markSizeAccessor: markSizeAccessor ? prepareVisDimension(markSizeAccessor) : undefined, + markSizeAccessor: + markSizeAccessor && !isBar ? prepareVisDimension(markSizeAccessor) : undefined, palette: palette ? preparePalette(palette) : undefined, columnToLabel: JSON.stringify( [...yAccessors, xAccessor, ...(splitAccessors ?? [])].reduce>( @@ -172,10 +173,11 @@ const getMode = (scale: Scale, bounds?: Bounds) => { const getLabelArgs = (data: CategoryAxis, isTimeChart?: boolean) => { return { truncate: data.labels.truncate, - labelsOrientation: data.labels.rotate ?? (isTimeChart ? 0 : -90), + labelsOrientation: -(data.labels.rotate ?? (isTimeChart ? 0 : 90)), showOverlappingLabels: data.labels.filter === false, showDuplicates: data.labels.filter === false, labelColor: data.labels.color, + showLabels: data.labels.show, }; }; @@ -184,6 +186,7 @@ const prepareAxisExtentConfig = (scale: Scale, bounds?: Bounds) => { mode: getMode(scale, bounds), lowerBound: bounds?.min || scale.min, upperBound: bounds?.max || scale.max, + enforce: true, }); return buildExpression([axisExtentConfig]); @@ -274,9 +277,8 @@ const getLineStyle = (style: ThresholdLine['style']) => { case 'full': return 'solid'; case 'dashed': - return 'dashed'; case 'dot-dashed': - return 'dotted'; + return style; } }; @@ -433,7 +435,7 @@ export const toExpressionAst: VisToExpressionAst = async (vis, params ? [prepareReferenceLine(vis.params.thresholdLine, vis.params.valueAxes[0].id)] : []), ], - addTimeMarker: vis.params.addTimeMarker, + addTimeMarker: vis.params.addTimeMarker && (dimensions.x?.params as DateHistogramParams)?.date, orderBucketsBySum: vis.params.orderBucketsBySum, fittingFunction: vis.params.fittingFunction ? vis.params.fittingFunction.charAt(0).toUpperCase() + vis.params.fittingFunction.slice(1) @@ -441,7 +443,13 @@ export const toExpressionAst: VisToExpressionAst = async (vis, params detailedTooltip: vis.params.detailedTooltip, fillOpacity: vis.params.fillOpacity, showTooltip: vis.params.addTooltip, - markSizeRatio: dimensions.z ? vis.params.radiusRatio : undefined, + markSizeRatio: + dimensions.z && + finalSeriesParams.some( + (param) => param.type === ChartType.Area || param.type === ChartType.Line + ) + ? vis.params.radiusRatio * 0.6 // NOTE: downscale ratio to match current vislib implementation + : undefined, legend: prepareLengend(vis.params, legendSize), xAxisConfig: prepareXAxis( vis.params.categoryAxes[0], From 526bb0ee2932c35754520e8443481cadf4446172 Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Wed, 27 Jul 2022 17:51:58 +0300 Subject: [PATCH 19/27] Fix CI checks --- .../expression_xy/public/components/xy_chart.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx index 7462453d5a20a..1c3b19d044b81 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx @@ -285,7 +285,7 @@ export function XYChart({ const formattedDatatables = useMemo( () => getFormattedTablesByLayers(dataLayers, formatFactory, splitColumnAccessor, splitRowAccessor), - [dataLayers, formatFactory] + [dataLayers, formatFactory, splitColumnAccessor, splitRowAccessor] ); const fieldFormats = useMemo( From 06d3ccd0b15e69c58cd126bd033dfd349cbe5db1 Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Wed, 27 Jul 2022 15:18:35 +0000 Subject: [PATCH 20/27] [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' --- .../expression_xy/public/components/tooltip/tooltip.tsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/plugins/chart_expressions/expression_xy/public/components/tooltip/tooltip.tsx b/src/plugins/chart_expressions/expression_xy/public/components/tooltip/tooltip.tsx index 4f4568bdcd1be..e41fd00a09920 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/tooltip/tooltip.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/tooltip/tooltip.tsx @@ -95,10 +95,7 @@ export const Tooltip: FC = ({ }); } - if ( - splitAccessors?.splitRowAccessor && - seriesIdentifier.smVerticalAccessorValue !== undefined - ) { + if (splitAccessors?.splitRowAccessor && seriesIdentifier.smVerticalAccessorValue !== undefined) { data.push({ label: layerTitles?.splitRowTitles?.[splitAccessors?.splitRowAccessor], value: `${seriesIdentifier.smVerticalAccessorValue}`, From d20b31f2d4df59122058c564941a9ed631f320eb Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Thu, 28 Jul 2022 12:30:37 +0300 Subject: [PATCH 21/27] Fix CI --- .../expression_functions/layered_xy_vis_fn.ts | 15 +++++++++++---- .../expression_xy/common/helpers/index.ts | 8 +++++++- .../expression_xy/common/helpers/layers.ts | 10 +++++++++- .../common/types/expression_functions.ts | 4 ++++ 4 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis_fn.ts b/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis_fn.ts index b23e811584aab..42f77121cd114 100644 --- a/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis_fn.ts +++ b/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis_fn.ts @@ -17,15 +17,22 @@ import { errors, validateAxes, } from './validate'; -import { appendLayerIds, getDataLayers } from '../helpers'; +import { appendLayerIds, getDataLayers, getLayersWithTable } from '../helpers'; export const layeredXyVisFn: LayeredXyVisFn['fn'] = async (data, args, handlers) => { const layers = appendLayerIds(args.layers ?? [], 'layers'); const dataLayers = getDataLayers(layers); + const layersWithTable = getLayersWithTable(layers); - // for visialize we should log one datable for all layers - if (dataLayers.every((l) => l.table === dataLayers[0].table)) { - logDatatable(data, layers, handlers, args.splitColumnAccessor, args.splitRowAccessor); + // if layers have the same table should log only one + if (layersWithTable.every((l) => l.table === layersWithTable[0].table)) { + logDatatable( + layersWithTable[0].table, + layers, + handlers, + args.splitColumnAccessor, + args.splitRowAccessor + ); } else { logDatatables(layers, handlers, args.splitColumnAccessor, args.splitRowAccessor); } diff --git a/src/plugins/chart_expressions/expression_xy/common/helpers/index.ts b/src/plugins/chart_expressions/expression_xy/common/helpers/index.ts index 915a296571b10..e2cb4a7bf419c 100644 --- a/src/plugins/chart_expressions/expression_xy/common/helpers/index.ts +++ b/src/plugins/chart_expressions/expression_xy/common/helpers/index.ts @@ -6,6 +6,12 @@ * Side Public License, v 1. */ -export { appendLayerIds, getDataLayers, getAccessors, getShowLines } from './layers'; +export { + appendLayerIds, + getDataLayers, + getAccessors, + getShowLines, + getLayersWithTable, +} from './layers'; export { isTimeChart } from './visualization'; export { normalizeTable } from './table'; diff --git a/src/plugins/chart_expressions/expression_xy/common/helpers/layers.ts b/src/plugins/chart_expressions/expression_xy/common/helpers/layers.ts index 84ef7e41fbe5d..6b681944d7611 100644 --- a/src/plugins/chart_expressions/expression_xy/common/helpers/layers.ts +++ b/src/plugins/chart_expressions/expression_xy/common/helpers/layers.ts @@ -13,8 +13,9 @@ import { XYExtendedLayerConfigResult, ExtendedDataLayerArgs, DataLayerArgs, + XYExtendedLayerConfigResultWithTable, } from '../types'; -import { LayerTypes, SeriesTypes } from '../constants'; +import { LayerTypes, SeriesTypes, REFERENCE_LINE_LAYER } from '../constants'; function isWithLayerId(layer: T): layer is T & WithLayerId { return (layer as T & WithLayerId).layerId ? true : false; @@ -44,6 +45,13 @@ export function getDataLayers(layers: XYExtendedLayerConfigResult[]) { ); } +export function getLayersWithTable(layers: XYExtendedLayerConfigResult[]) { + return layers.filter( + (layer): layer is XYExtendedLayerConfigResultWithTable => + layer.layerType === LayerTypes.DATA || layer.type === REFERENCE_LINE_LAYER || !layer.layerType + ); +} + export function getAccessors< T, U extends { splitAccessors?: T[]; xAccessor?: T; accessors: T[]; markSizeAccessor?: T } diff --git a/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts b/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts index afb6909482a4c..f210cc844c7d3 100644 --- a/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts +++ b/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts @@ -327,6 +327,10 @@ export type XYExtendedLayerConfigResult = | ExtendedAnnotationLayerConfigResult | ReferenceLineConfigResult; + export type XYExtendedLayerConfigResultWithTable = + | ExtendedDataLayerConfigResult + | ReferenceLineLayerConfigResult; + export interface ExtendedReferenceLineDecorationConfig extends ReferenceLineArgs { type: typeof EXTENDED_REFERENCE_LINE_DECORATION_CONFIG; } From 159c923d76bff0b9ade264a6b6e29f3c13cb0de0 Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Thu, 28 Jul 2022 09:36:50 +0000 Subject: [PATCH 22/27] [CI] Auto-commit changed files from 'node scripts/precommit_hook.js --ref HEAD~1..HEAD --fix' --- .../expression_xy/common/types/expression_functions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts b/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts index f210cc844c7d3..56351eb5226b9 100644 --- a/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts +++ b/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts @@ -327,7 +327,7 @@ export type XYExtendedLayerConfigResult = | ExtendedAnnotationLayerConfigResult | ReferenceLineConfigResult; - export type XYExtendedLayerConfigResultWithTable = +export type XYExtendedLayerConfigResultWithTable = | ExtendedDataLayerConfigResult | ReferenceLineLayerConfigResult; From 8a756f87235271c76008f4b4431cbded852d1a6f Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Wed, 3 Aug 2022 13:12:40 +0300 Subject: [PATCH 23/27] Fix all remarks --- .../expression_functions/layered_xy_vis.ts | 7 + .../expression_functions/layered_xy_vis_fn.ts | 14 +- .../expression_xy/common/helpers/layers.ts | 10 +- .../common/types/expression_functions.ts | 6 +- .../__snapshots__/xy_chart.test.tsx.snap | 20 +++ .../public/components/data_layers.tsx | 35 ++++- .../public/components/legend_color_picker.tsx | 4 +- .../components/tooltip/tooltip.test.tsx | 10 ++ .../public/components/tooltip/tooltip.tsx | 16 +- .../public/components/xy_chart.tsx | 11 +- .../public/helpers/color_assignment.test.ts | 145 +++++------------- .../public/helpers/color_assignment.ts | 28 ++-- .../public/helpers/data_layers.tsx | 19 ++- .../expression_xy/public/helpers/layers.ts | 13 +- .../public/__snapshots__/to_ast.test.ts.snap | 3 + src/plugins/vis_types/xy/public/to_ast.ts | 40 +++-- 16 files changed, 208 insertions(+), 173 deletions(-) diff --git a/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis.ts b/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis.ts index 2de0d1305df52..392c9a0d5830a 100644 --- a/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis.ts +++ b/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis.ts @@ -40,6 +40,13 @@ export const layeredXyVisFunction: LayeredXyVisFn = { types: ['vis_dimension', 'string'], help: strings.getSplitRowAccessorHelp(), }, + singleTable: { + types: ['boolean'], + help: i18n.translate('expressionXY.layeredXyVis.singleTable.help', { + defaultMessage: 'All layers use the one datatable', + }), + default: false, + }, }, async fn(data, args, handlers) { const { layeredXyVisFn } = await import('./layered_xy_vis_fn'); diff --git a/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis_fn.ts b/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis_fn.ts index 42f77121cd114..50549d5f8ac1c 100644 --- a/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis_fn.ts +++ b/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis_fn.ts @@ -17,22 +17,14 @@ import { errors, validateAxes, } from './validate'; -import { appendLayerIds, getDataLayers, getLayersWithTable } from '../helpers'; +import { appendLayerIds, getDataLayers } from '../helpers'; export const layeredXyVisFn: LayeredXyVisFn['fn'] = async (data, args, handlers) => { const layers = appendLayerIds(args.layers ?? [], 'layers'); const dataLayers = getDataLayers(layers); - const layersWithTable = getLayersWithTable(layers); - // if layers have the same table should log only one - if (layersWithTable.every((l) => l.table === layersWithTable[0].table)) { - logDatatable( - layersWithTable[0].table, - layers, - handlers, - args.splitColumnAccessor, - args.splitRowAccessor - ); + if (args.singleTable) { + logDatatable(data, layers, handlers, args.splitColumnAccessor, args.splitRowAccessor); } else { logDatatables(layers, handlers, args.splitColumnAccessor, args.splitRowAccessor); } diff --git a/src/plugins/chart_expressions/expression_xy/common/helpers/layers.ts b/src/plugins/chart_expressions/expression_xy/common/helpers/layers.ts index 6b681944d7611..84ef7e41fbe5d 100644 --- a/src/plugins/chart_expressions/expression_xy/common/helpers/layers.ts +++ b/src/plugins/chart_expressions/expression_xy/common/helpers/layers.ts @@ -13,9 +13,8 @@ import { XYExtendedLayerConfigResult, ExtendedDataLayerArgs, DataLayerArgs, - XYExtendedLayerConfigResultWithTable, } from '../types'; -import { LayerTypes, SeriesTypes, REFERENCE_LINE_LAYER } from '../constants'; +import { LayerTypes, SeriesTypes } from '../constants'; function isWithLayerId(layer: T): layer is T & WithLayerId { return (layer as T & WithLayerId).layerId ? true : false; @@ -45,13 +44,6 @@ export function getDataLayers(layers: XYExtendedLayerConfigResult[]) { ); } -export function getLayersWithTable(layers: XYExtendedLayerConfigResult[]) { - return layers.filter( - (layer): layer is XYExtendedLayerConfigResultWithTable => - layer.layerType === LayerTypes.DATA || layer.type === REFERENCE_LINE_LAYER || !layer.layerType - ); -} - export function getAccessors< T, U extends { splitAccessors?: T[]; xAccessor?: T; accessors: T[]; markSizeAccessor?: T } diff --git a/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts b/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts index 2d7700fd5240d..0970cec985d30 100644 --- a/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts +++ b/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts @@ -254,6 +254,7 @@ export interface LayeredXYArgs { showTooltip: boolean; splitRowAccessor?: ExpressionValueVisDimension | string; splitColumnAccessor?: ExpressionValueVisDimension | string; + singleTable?: boolean; } export interface XYProps { @@ -277,6 +278,7 @@ export interface XYProps { detailedTooltip?: boolean; orderBucketsBySum?: boolean; showTooltip: boolean; + singleTable?: boolean; } export interface AnnotationLayerArgs { @@ -327,10 +329,6 @@ export type XYExtendedLayerConfigResult = | ExtendedAnnotationLayerConfigResult | ReferenceLineConfigResult; -export type XYExtendedLayerConfigResultWithTable = - | ExtendedDataLayerConfigResult - | ReferenceLineLayerConfigResult; - export interface ExtendedReferenceLineDecorationConfig extends ReferenceLineArgs { type: typeof EXTENDED_REFERENCE_LINE_DECORATION_CONFIG; } diff --git a/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap b/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap index 60acbd6fd3daf..1390545591f6c 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap +++ b/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap @@ -526,6 +526,7 @@ exports[`XYChart component it renders area 1`] = ` "setColor": [Function], "titles": Object { "first": Object { + "markSizeTitles": Object {}, "splitColumnTitles": Object {}, "splitRowTitles": Object {}, "splitSeriesTitles": Object { @@ -1187,6 +1188,7 @@ exports[`XYChart component it renders area 1`] = ` titles={ Object { "first": Object { + "markSizeTitles": Object {}, "splitColumnTitles": Object {}, "splitRowTitles": Object {}, "splitSeriesTitles": Object { @@ -1505,6 +1507,7 @@ exports[`XYChart component it renders bar 1`] = ` "setColor": [Function], "titles": Object { "first": Object { + "markSizeTitles": Object {}, "splitColumnTitles": Object {}, "splitRowTitles": Object {}, "splitSeriesTitles": Object { @@ -2166,6 +2169,7 @@ exports[`XYChart component it renders bar 1`] = ` titles={ Object { "first": Object { + "markSizeTitles": Object {}, "splitColumnTitles": Object {}, "splitRowTitles": Object {}, "splitSeriesTitles": Object { @@ -2484,6 +2488,7 @@ exports[`XYChart component it renders horizontal bar 1`] = ` "setColor": [Function], "titles": Object { "first": Object { + "markSizeTitles": Object {}, "splitColumnTitles": Object {}, "splitRowTitles": Object {}, "splitSeriesTitles": Object { @@ -3145,6 +3150,7 @@ exports[`XYChart component it renders horizontal bar 1`] = ` titles={ Object { "first": Object { + "markSizeTitles": Object {}, "splitColumnTitles": Object {}, "splitRowTitles": Object {}, "splitSeriesTitles": Object { @@ -3463,6 +3469,7 @@ exports[`XYChart component it renders line 1`] = ` "setColor": [Function], "titles": Object { "first": Object { + "markSizeTitles": Object {}, "splitColumnTitles": Object {}, "splitRowTitles": Object {}, "splitSeriesTitles": Object { @@ -4124,6 +4131,7 @@ exports[`XYChart component it renders line 1`] = ` titles={ Object { "first": Object { + "markSizeTitles": Object {}, "splitColumnTitles": Object {}, "splitRowTitles": Object {}, "splitSeriesTitles": Object { @@ -4442,6 +4450,7 @@ exports[`XYChart component it renders stacked area 1`] = ` "setColor": [Function], "titles": Object { "first": Object { + "markSizeTitles": Object {}, "splitColumnTitles": Object {}, "splitRowTitles": Object {}, "splitSeriesTitles": Object { @@ -5103,6 +5112,7 @@ exports[`XYChart component it renders stacked area 1`] = ` titles={ Object { "first": Object { + "markSizeTitles": Object {}, "splitColumnTitles": Object {}, "splitRowTitles": Object {}, "splitSeriesTitles": Object { @@ -5421,6 +5431,7 @@ exports[`XYChart component it renders stacked bar 1`] = ` "setColor": [Function], "titles": Object { "first": Object { + "markSizeTitles": Object {}, "splitColumnTitles": Object {}, "splitRowTitles": Object {}, "splitSeriesTitles": Object { @@ -6082,6 +6093,7 @@ exports[`XYChart component it renders stacked bar 1`] = ` titles={ Object { "first": Object { + "markSizeTitles": Object {}, "splitColumnTitles": Object {}, "splitRowTitles": Object {}, "splitSeriesTitles": Object { @@ -6400,6 +6412,7 @@ exports[`XYChart component it renders stacked horizontal bar 1`] = ` "setColor": [Function], "titles": Object { "first": Object { + "markSizeTitles": Object {}, "splitColumnTitles": Object {}, "splitRowTitles": Object {}, "splitSeriesTitles": Object { @@ -7061,6 +7074,7 @@ exports[`XYChart component it renders stacked horizontal bar 1`] = ` titles={ Object { "first": Object { + "markSizeTitles": Object {}, "splitColumnTitles": Object {}, "splitRowTitles": Object {}, "splitSeriesTitles": Object { @@ -7405,6 +7419,7 @@ exports[`XYChart component split chart should render split chart if both, splitR "setColor": [Function], "titles": Object { "first": Object { + "markSizeTitles": Object {}, "splitColumnTitles": Object { "b": "b", }, @@ -8266,6 +8281,7 @@ exports[`XYChart component split chart should render split chart if both, splitR titles={ Object { "first": Object { + "markSizeTitles": Object {}, "splitColumnTitles": Object { "b": "b", }, @@ -8624,6 +8640,7 @@ exports[`XYChart component split chart should render split chart if splitColumnA "setColor": [Function], "titles": Object { "first": Object { + "markSizeTitles": Object {}, "splitColumnTitles": Object { "b": "b", }, @@ -9478,6 +9495,7 @@ exports[`XYChart component split chart should render split chart if splitColumnA titles={ Object { "first": Object { + "markSizeTitles": Object {}, "splitColumnTitles": Object { "b": "b", }, @@ -9834,6 +9852,7 @@ exports[`XYChart component split chart should render split chart if splitRowAcce "setColor": [Function], "titles": Object { "first": Object { + "markSizeTitles": Object {}, "splitColumnTitles": Object {}, "splitRowTitles": Object { "b": "b", @@ -10688,6 +10707,7 @@ exports[`XYChart component split chart should render split chart if splitRowAcce titles={ Object { "first": Object { + "markSizeTitles": Object {}, "splitColumnTitles": Object {}, "splitRowTitles": Object { "b": "b", diff --git a/src/plugins/chart_expressions/expression_xy/public/components/data_layers.tsx b/src/plugins/chart_expressions/expression_xy/public/components/data_layers.tsx index 930acbcabf87b..ca7acd25fd785 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/data_layers.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/data_layers.tsx @@ -54,6 +54,7 @@ interface Props { defaultXScaleType: XScaleType; fieldFormats: LayersFieldFormats; uiState?: PersistedState; + singleTable?: boolean; } export const DataLayers: FC = ({ @@ -75,8 +76,38 @@ export const DataLayers: FC = ({ defaultXScaleType, fieldFormats, uiState, + singleTable, }) => { - const colorAssignments = getColorAssignments(layers, titles, fieldFormats, formattedDatatables); + // for singleTable mode we should use y accessors from all layers for creating correct series name and getting color + const allYAccessors = layers.flatMap((layer) => layer.accessors); + const allColumnsToLabel = layers.reduce((acc, layer) => { + if (layer.columnToLabel) { + return { ...acc, ...JSON.parse(layer.columnToLabel) }; + } + + return acc; + }, {}); + const allYTitles = Object.keys(titles).reduce((acc, key) => { + if (titles[key].yTitles) { + return { ...acc, ...titles[key].yTitles }; + } + return acc; + }, {}); + const colorAssignments = singleTable + ? getColorAssignments( + [ + { + ...layers[0], + layerId: 'commonLayerId', + accessors: allYAccessors, + columnToLabel: JSON.stringify(allColumnsToLabel), + }, + ], + { commonLayerId: { ...titles, yTitles: allYTitles } }, + { commonLayerId: fieldFormats[layers[0].layerId] }, + { commonLayerId: formattedDatatables[layers[0].layerId] } + ) + : getColorAssignments(layers, titles, fieldFormats, formattedDatatables); return ( <> {layers.flatMap((layer) => @@ -118,6 +149,8 @@ export const DataLayers: FC = ({ defaultXScaleType, fieldFormats, uiState, + allYAccessors, + singleTable, }); const index = `${layer.layerId}-${accessorIndex}`; diff --git a/src/plugins/chart_expressions/expression_xy/public/components/legend_color_picker.tsx b/src/plugins/chart_expressions/expression_xy/public/components/legend_color_picker.tsx index 9fb81bc951338..fa4e02a5a9d74 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/legend_color_picker.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/legend_color_picker.tsx @@ -126,10 +126,10 @@ export const LegendColorPickerWrapper: LegendColorPicker = ({ panelPaddingSize="s" > diff --git a/src/plugins/chart_expressions/expression_xy/public/components/tooltip/tooltip.test.tsx b/src/plugins/chart_expressions/expression_xy/public/components/tooltip/tooltip.test.tsx index da6d5032158cb..fa8638afc68d1 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/tooltip/tooltip.test.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/tooltip/tooltip.test.tsx @@ -113,6 +113,7 @@ describe('Tooltip', () => { formatFactory={formatFactory} formattedDatatables={{ [layerId]: { table: data, formattedColumns: {} } }} splitAccessors={{ splitColumnAccessor, splitRowAccessor }} + layers={[sampleLayer]} /> ); @@ -133,6 +134,7 @@ describe('Tooltip', () => { formattedDatatables={{ [layerId]: { table: data, formattedColumns: {} } }} splitAccessors={{ splitColumnAccessor, splitRowAccessor }} xDomain={xDomain} + layers={[sampleLayer]} /> ); @@ -153,6 +155,7 @@ describe('Tooltip', () => { formattedDatatables={{ [layerId]: { table: data, formattedColumns: {} } }} splitAccessors={{ splitColumnAccessor, splitRowAccessor }} xDomain={xDomain} + layers={[sampleLayer]} /> ); @@ -170,6 +173,7 @@ describe('Tooltip', () => { formattedDatatables={{ [layerId]: { table: data, formattedColumns: {} } }} splitAccessors={{ splitColumnAccessor, splitRowAccessor }} xDomain={xDomain2} + layers={[sampleLayer]} /> ); @@ -188,6 +192,7 @@ describe('Tooltip', () => { formatFactory={formatFactory} formattedDatatables={{ [layerId]: { table: data, formattedColumns: {} } }} splitAccessors={{ splitColumnAccessor, splitRowAccessor }} + layers={[sampleLayer]} /> ); @@ -213,6 +218,7 @@ describe('Tooltip', () => { formatFactory={formatFactory} formattedDatatables={{ [layerId]: { table: data, formattedColumns: {} } }} splitAccessors={{ splitColumnAccessor, splitRowAccessor }} + layers={[sampleLayer]} /> ); @@ -240,6 +246,7 @@ describe('Tooltip', () => { formatFactory={formatFactory} formattedDatatables={{ [layerId]: { table: data, formattedColumns: {} } }} splitAccessors={{ splitColumnAccessor, splitRowAccessor }} + layers={[sampleLayer]} /> ); @@ -268,6 +275,7 @@ describe('Tooltip', () => { formatFactory={formatFactory} formattedDatatables={{ [layerId]: { table: data, formattedColumns: {} } }} splitAccessors={{ splitColumnAccessor, splitRowAccessor }} + layers={[sampleLayer]} /> ); @@ -295,6 +303,7 @@ describe('Tooltip', () => { formatFactory={formatFactory} formattedDatatables={{ [layerId]: { table: data, formattedColumns: {} } }} splitAccessors={{ splitColumnAccessor }} + layers={[sampleLayer]} /> ); @@ -322,6 +331,7 @@ describe('Tooltip', () => { formatFactory={formatFactory} formattedDatatables={{ [layerId]: { table: data, formattedColumns: {} } }} splitAccessors={{ splitRowAccessor }} + layers={[sampleLayer]} /> ); diff --git a/src/plugins/chart_expressions/expression_xy/public/components/tooltip/tooltip.tsx b/src/plugins/chart_expressions/expression_xy/public/components/tooltip/tooltip.tsx index e41fd00a09920..ca7152e485c9f 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/tooltip/tooltip.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/tooltip/tooltip.tsx @@ -8,7 +8,9 @@ import { TooltipInfo, XYChartSeriesIdentifier } from '@elastic/charts'; import { FormatFactory } from '@kbn/field-formats-plugin/common'; +import { getAccessorByDimension } from '@kbn/visualizations-plugin/common/utils'; import React, { FC } from 'react'; +import { CommonXYDataLayerConfig } from '../../../common'; import { DatatablesWithFormatInfo, getMetaFromSeriesId, @@ -32,6 +34,7 @@ type Props = TooltipInfo & { splitRowAccessor?: string; splitColumnAccessor?: string; }; + layers: CommonXYDataLayerConfig[]; }; export const Tooltip: FC = ({ @@ -43,6 +46,7 @@ export const Tooltip: FC = ({ formattedDatatables, splitAccessors, xDomain, + layers, }) => { const pickedValue = values.find(({ isHighlighted }) => isHighlighted); @@ -53,9 +57,13 @@ export const Tooltip: FC = ({ const data: TooltipData[] = []; const seriesIdentifier = pickedValue.seriesIdentifier as XYChartSeriesIdentifier; const { layerId, xAccessor, yAccessor } = getMetaFromSeriesId(seriesIdentifier.specId); - const { formattedColumns } = formattedDatatables[layerId]; + const { formattedColumns, table } = formattedDatatables[layerId]; const layerTitles = titles[layerId]; const layerFormats = fieldFormats[layerId]; + const markSizeAccessor = layers.find((layer) => layer.layerId === layerId)?.markSizeAccessor; + const markSizeColumnId = markSizeAccessor + ? getAccessorByDimension(markSizeAccessor, table.columns) + : undefined; let headerFormatter; if (header && xAccessor) { headerFormatter = formattedColumns[xAccessor] @@ -75,6 +83,12 @@ export const Tooltip: FC = ({ value: yFormatter ? yFormatter.convert(pickedValue.value) : `${pickedValue.value}`, }); } + if (markSizeColumnId && pickedValue.formattedMarkValue) { + data.push({ + label: layerTitles?.markSizeTitles?.[markSizeColumnId], + value: pickedValue.formattedMarkValue, + }); + } seriesIdentifier.splitAccessors.forEach((splitValue, key) => { const splitSeriesFormatter = formattedColumns[key] ? null diff --git a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx index 1c3b19d044b81..16db7775a6d86 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx @@ -214,6 +214,7 @@ export function XYChart({ xAxisConfig, splitColumnAccessor, splitRowAccessor, + singleTable, } = args; const chartRef = useRef(null); const chartTheme = chartsThemeService.useChartsTheme(); @@ -234,7 +235,7 @@ export function XYChart({ const getShowLegendDefault = useCallback(() => { const legendStateDefault = legend.isVisible && !legend.showSingleSeries ? chartHasMoreThanOneSeries : legend.isVisible; - return uiState?.get('vis.legendOpen', legendStateDefault) || legendStateDefault; + return uiState?.get('vis.legendOpen', legendStateDefault) ?? legendStateDefault; }, [chartHasMoreThanOneSeries, legend.isVisible, legend.showSingleSeries, uiState]); const [showLegend, setShowLegend] = useState(() => getShowLegendDefault()); @@ -476,7 +477,9 @@ export function XYChart({ }) ); - const fit = !hasBarOrArea && extent.mode === AxisExtentModes.DATA_BOUNDS; + const fit = Boolean( + (!hasBarOrArea || axis.extent?.enforce) && extent.mode === AxisExtentModes.DATA_BOUNDS + ); const padding = axis.boundsMargin || undefined; let min: number = NaN; @@ -805,6 +808,7 @@ export function XYChart({ splitColumnAccessor: splitColumnId, splitRowAccessor: splitRowId, }} + layers={dataLayers} xDomain={isTimeViz ? rawXDomain : undefined} /> ) @@ -880,7 +884,7 @@ export function XYChart({ id={axis.groupId} groupId={axis.groupId} position={axis.position} - title={getYAxesTitles(axis.series)} + title={axis.title || getYAxesTitles(axis.series)} gridLine={{ visible: axis.showGridLines, }} @@ -936,6 +940,7 @@ export function XYChart({ defaultXScaleType={defaultXScaleType} fieldFormats={fieldFormats} uiState={uiState} + singleTable={singleTable} /> )} {referenceLineLayers.length ? ( diff --git a/src/plugins/chart_expressions/expression_xy/public/helpers/color_assignment.test.ts b/src/plugins/chart_expressions/expression_xy/public/helpers/color_assignment.test.ts index f1a11bbe06185..6442845b0ecf3 100644 --- a/src/plugins/chart_expressions/expression_xy/public/helpers/color_assignment.test.ts +++ b/src/plugins/chart_expressions/expression_xy/public/helpers/color_assignment.test.ts @@ -118,21 +118,28 @@ describe('color_assignment', () => { }, }; + const titles = { + [layers[0].layerId]: { + yTitles: { + y1: 'test1', + y2: 'test2', + y3: 'test3', + y4: 'test4', + }, + }, + [layers[1].layerId]: { + yTitles: { + y1: 'test1', + y2: 'test2', + y3: 'test3', + y4: 'test4', + }, + }, + }; + describe('totalSeriesCount', () => { it('should calculate total number of series per palette', () => { - const assignments = getColorAssignments( - layers, - { - yTitles: { - y1: 'test1', - y2: 'test2', - y3: 'test3', - y4: 'test4', - }, - }, - fieldFormats, - formattedDatatables - ); + const assignments = getColorAssignments(layers, titles, fieldFormats, formattedDatatables); // two y accessors, with 3 splitted series expect(assignments.palette1.totalSeriesCount).toEqual(2 * 3); expect(assignments.palette2.totalSeriesCount).toEqual(2 * 3); @@ -141,14 +148,7 @@ describe('color_assignment', () => { it('should calculate total number of series spanning multible layers', () => { const assignments = getColorAssignments( [layers[0], { ...layers[1], palette: layers[0].palette }], - { - yTitles: { - y1: 'test1', - y2: 'test2', - y3: 'test3', - y4: 'test4', - }, - }, + titles, fieldFormats, formattedDatatables ); @@ -160,14 +160,7 @@ describe('color_assignment', () => { it('should calculate total number of series for non split series', () => { const assignments = getColorAssignments( [layers[0], { ...layers[1], palette: layers[0].palette, splitAccessors: undefined }], - { - yTitles: { - y1: 'test1', - y2: 'test2', - y3: 'test3', - y4: 'test4', - }, - }, + titles, fieldFormats, formattedDatatables ); @@ -200,14 +193,7 @@ describe('color_assignment', () => { const assignments = getColorAssignments( newLayers, - { - yTitles: { - y1: 'test1', - y2: 'test2', - y3: 'test3', - y4: 'test4', - }, - }, + titles, fieldFormats, newFormattedDatatables ); @@ -230,14 +216,7 @@ describe('color_assignment', () => { }; const assignments = getColorAssignments( newLayers, - { - yTitles: { - y1: 'test1', - y2: 'test2', - y3: 'test3', - y4: 'test4', - }, - }, + titles, fieldFormats, newFormattedDatatables ); @@ -249,44 +228,20 @@ describe('color_assignment', () => { describe('getRank', () => { it('should return the correct rank for a series key', () => { - const assignments = getColorAssignments( - layers, - { - yTitles: { - y1: 'test1', - y2: 'test2', - y3: 'test3', - y4: 'test4', - }, - }, - fieldFormats, - formattedDatatables - ); + const assignments = getColorAssignments(layers, titles, fieldFormats, formattedDatatables); // 3 series in front of 2/y2 - 1/y1, 1/y2 and 2/y1 - expect(assignments.palette1.getRank(layers[0], '2 - test2')).toEqual(3); + expect(assignments.palette1.getRank(layers[0].layerId, '2 - test2')).toEqual(3); // 1 series in front of 1/y4 - 1/y3 - expect(assignments.palette2.getRank(layers[1], '1 - test4')).toEqual(1); + expect(assignments.palette2.getRank(layers[1].layerId, '1 - test4')).toEqual(1); }); it('should return the correct rank for a series key spanning multiple layers', () => { const newLayers = [layers[0], { ...layers[1], palette: layers[0].palette }]; - const assignments = getColorAssignments( - newLayers, - { - yTitles: { - y1: 'test1', - y2: 'test2', - y3: 'test3', - y4: 'test4', - }, - }, - fieldFormats, - formattedDatatables - ); + const assignments = getColorAssignments(newLayers, titles, fieldFormats, formattedDatatables); // 3 series in front of 2/y2 - 1/y1, 1/y2 and 2/y1 - expect(assignments.palette1.getRank(newLayers[0], '2 - test2')).toEqual(3); + expect(assignments.palette1.getRank(newLayers[0].layerId, '2 - test2')).toEqual(3); // 2 series in front for the current layer (1/y3, 1/y4), plus all 6 series from the first layer - expect(assignments.palette1.getRank(newLayers[1], '2 - test3')).toEqual(8); + expect(assignments.palette1.getRank(newLayers[1].layerId, '2 - test3')).toEqual(8); }); it('should return the correct rank for a series without a split', () => { @@ -294,23 +249,11 @@ describe('color_assignment', () => { layers[0], { ...layers[1], palette: layers[0].palette, splitAccessors: undefined }, ]; - const assignments = getColorAssignments( - newLayers, - { - yTitles: { - y1: 'test1', - y2: 'test2', - y3: 'test3', - y4: 'test4', - }, - }, - fieldFormats, - formattedDatatables - ); + const assignments = getColorAssignments(newLayers, titles, fieldFormats, formattedDatatables); // 3 series in front of 2/y2 - 1/y1, 1/y2 and 2/y1 - expect(assignments.palette1.getRank(newLayers[0], '2 - test2')).toEqual(3); + expect(assignments.palette1.getRank(newLayers[0].layerId, '2 - test2')).toEqual(3); // 1 series in front for the current layer (y3), plus all 6 series from the first layer - expect(assignments.palette1.getRank(newLayers[1], 'test4')).toEqual(7); + expect(assignments.palette1.getRank(newLayers[1].layerId, 'test4')).toEqual(7); }); it('should return the correct rank for a series with a non-primitive value', () => { @@ -336,21 +279,14 @@ describe('color_assignment', () => { const assignments = getColorAssignments( newLayers, - { - yTitles: { - y1: 'test1', - y2: 'test2', - y3: 'test3', - y4: 'test4', - }, - }, + titles, fieldFormats, newFormattedDatatables ); fieldFormats.first.splitSeriesAccessors.split1.formatter.convert = (x) => x as string; // 3 series in front of (complex object)/y1 - abc/y1, abc/y2 - expect(assignments.palette1.getRank(layers[0], 'formatted - test1')).toEqual(2); + expect(assignments.palette1.getRank(layers[0].layerId, 'formatted - test1')).toEqual(2); }); it('should handle missing columns', () => { @@ -365,20 +301,13 @@ describe('color_assignment', () => { const assignments = getColorAssignments( newLayers, - { - yTitles: { - y1: 'test1', - y2: 'test2', - y3: 'test3', - y4: 'test4', - }, - }, + titles, fieldFormats, newFormattedDatatables ); // if the split column is missing, assume it is the first splitted series. One series in front - 0/y1 - expect(assignments.palette1.getRank(layers[0], 'test2')).toEqual(1); + expect(assignments.palette1.getRank(layers[0].layerId, 'test2')).toEqual(1); }); }); }); diff --git a/src/plugins/chart_expressions/expression_xy/public/helpers/color_assignment.ts b/src/plugins/chart_expressions/expression_xy/public/helpers/color_assignment.ts index c7139cf036fa2..2cce918d4b798 100644 --- a/src/plugins/chart_expressions/expression_xy/public/helpers/color_assignment.ts +++ b/src/plugins/chart_expressions/expression_xy/public/helpers/color_assignment.ts @@ -13,7 +13,12 @@ import { getAccessorByDimension } from '@kbn/visualizations-plugin/common/utils' import type { ExpressionValueVisDimension } from '@kbn/visualizations-plugin/common'; import { isDataLayer } from './visualization'; import { CommonXYDataLayerConfig, CommonXYLayerConfig } from '../../common'; -import { LayerAccessorsTitles, LayerFieldFormats, LayersFieldFormats } from './layers'; +import { + LayerAccessorsTitles, + LayerFieldFormats, + LayersAccessorsTitles, + LayersFieldFormats, +} from './layers'; import { DatatablesWithFormatInfo, DatatableWithFormatInfo } from './data_layers'; export const defaultReferenceLineColor = euiLightVars.euiColorDarkShade; @@ -22,7 +27,7 @@ export type ColorAssignments = Record< string, { totalSeriesCount: number; - getRank(sortedLayer: CommonXYDataLayerConfig, seriesName: string): number; + getRank(layerId: string, seriesName: string): number; } >; @@ -53,7 +58,8 @@ export const getAllSeries = ( accessors: Array, columnToLabel: CommonXYDataLayerConfig['columnToLabel'], titles: LayerAccessorsTitles, - fieldFormats: LayerFieldFormats + fieldFormats: LayerFieldFormats, + accessorsCount: number ) => { if (!formattedDatatable.table) { return []; @@ -71,7 +77,7 @@ export const getAllSeries = ( const yTitle = columnToLabelMap[yAccessor] ?? titles?.yTitles?.[yAccessor] ?? null; let name = yTitle; if (splitName) { - name = accessors.length > 1 ? `${splitName} - ${yTitle}` : splitName; + name = accessorsCount > 1 ? `${splitName} - ${yTitle}` : splitName; } if (!allSeries.includes(name)) { @@ -85,7 +91,7 @@ export const getAllSeries = ( export function getColorAssignments( layers: CommonXYLayerConfig[], - titles: LayerAccessorsTitles, + titles: LayersAccessorsTitles, fieldFormats: LayersFieldFormats, formattedDatatables: DatatablesWithFormatInfo ): ColorAssignments { @@ -111,22 +117,22 @@ export function getColorAssignments( layer.splitAccessors, layer.accessors, layer.columnToLabel, - titles, - fieldFormats[layer.layerId] + titles[layer.layerId], + fieldFormats[layer.layerId], + layer.accessors.length ) || []; return { numberOfSeries: allSeries.length, allSeries }; }); + const totalSeriesCount = seriesPerLayer.reduce( (sum, perLayer) => sum + perLayer.numberOfSeries, 0 ); return { totalSeriesCount, - getRank(sortedLayer: CommonXYDataLayerConfig, seriesName: string) { - const layerIndex = paletteLayers.findIndex( - (layer) => sortedLayer.layerId === layer.layerId - ); + getRank(layerId: string, seriesName: string) { + const layerIndex = paletteLayers.findIndex((layer) => layerId === layer.layerId); const currentSeriesPerLayer = seriesPerLayer[layerIndex]; const rank = currentSeriesPerLayer.allSeries.indexOf(seriesName); return ( diff --git a/src/plugins/chart_expressions/expression_xy/public/helpers/data_layers.tsx b/src/plugins/chart_expressions/expression_xy/public/helpers/data_layers.tsx index 96c2fece7301d..bb37e1c2a56fb 100644 --- a/src/plugins/chart_expressions/expression_xy/public/helpers/data_layers.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/helpers/data_layers.tsx @@ -53,6 +53,8 @@ type GetSeriesPropsFn = (config: { defaultXScaleType: XScaleType; fieldFormats: LayersFieldFormats; uiState?: PersistedState; + allYAccessors: Array; + singleTable?: boolean; }) => SeriesSpec; type GetSeriesNameFn = ( @@ -78,7 +80,8 @@ type GetColorFn = ( getSeriesNameFn: (d: XYChartSeriesIdentifier) => SeriesName; syncColors?: boolean; }, - uiState?: PersistedState + uiState?: PersistedState, + singleTable?: boolean ) => string | null; type GetPointConfigFn = (config: { @@ -307,7 +310,8 @@ const getLineConfig: GetLineConfigFn = ({ showLines, lineWidth }) => ({ const getColor: GetColorFn = ( series, { layer, accessor, colorAssignments, paletteService, syncColors, getSeriesNameFn }, - uiState + uiState, + singleTable ) => { const overwriteColor = getSeriesColor(layer, accessor); if (overwriteColor !== null) { @@ -327,7 +331,7 @@ const getColor: GetColorFn = ( { name, totalSeriesAtDepth: colorAssignment.totalSeriesCount, - rankAtDepth: colorAssignment.getRank(layer, name), + rankAtDepth: colorAssignment.getRank(singleTable ? 'commonLayerId' : layer.layerId, name), }, ]; return paletteService.get(layer.palette.name).getCategoricalColor( @@ -343,7 +347,7 @@ const getColor: GetColorFn = ( }; const EMPTY_ACCESSOR = '-'; -const SPLIT_CHAR = '.'; +const SPLIT_CHAR = ':'; export const generateSeriesId = ( { layerId }: Pick, @@ -383,6 +387,8 @@ export const getSeriesProps: GetSeriesPropsFn = ({ defaultXScaleType, fieldFormats, uiState, + allYAccessors, + singleTable, }): SeriesSpec => { const { table, isStacked, markSizeAccessor } = layer; const isPercentage = layer.isPercentage; @@ -449,7 +455,7 @@ export const getSeriesProps: GetSeriesPropsFn = ({ d, { splitAccessors: layer.splitAccessors || [], - accessorsCount: layer.accessors.length, + accessorsCount: singleTable ? allYAccessors.length : layer.accessors.length, alreadyFormattedColumns: formattedColumns, columns: formattedTable.columns, splitAccessorsFormats: fieldFormats[layer.layerId].splitSeriesAccessors, @@ -489,7 +495,8 @@ export const getSeriesProps: GetSeriesPropsFn = ({ getSeriesNameFn, syncColors, }, - uiState + uiState, + singleTable ), groupId: yAxis?.groupId, enableHistogramMode, diff --git a/src/plugins/chart_expressions/expression_xy/public/helpers/layers.ts b/src/plugins/chart_expressions/expression_xy/public/helpers/layers.ts index 8ff87e381cf48..7dc26e4c76cf1 100644 --- a/src/plugins/chart_expressions/expression_xy/public/helpers/layers.ts +++ b/src/plugins/chart_expressions/expression_xy/public/helpers/layers.ts @@ -61,6 +61,7 @@ export interface LayerAccessorsTitles { splitSeriesTitles?: AccessorsTitles; splitColumnTitles?: AccessorsTitles; splitRowTitles?: AccessorsTitles; + markSizeTitles?: AccessorsTitles; } export type LayersAccessorsTitles = Record; @@ -192,11 +193,18 @@ const getTitleForYAccessor = ( group.series.some(({ accessor, layer }) => accessor === yAccessor && layer === layerId) ); - return axisGroup?.title || column!.name; + return column?.name ?? axisGroup?.title; }; export const getLayerTitles = ( - { xAccessor, accessors, splitAccessors = [], table, layerId }: CommonXYDataLayerConfig, + { + xAccessor, + accessors, + splitAccessors = [], + table, + layerId, + markSizeAccessor, + }: CommonXYDataLayerConfig, { splitColumnAccessor, splitRowAccessor }: SplitAccessors, { xTitle }: CustomTitles, groups: GroupsConfiguration @@ -231,6 +239,7 @@ export const getLayerTitles = ( }), {} ), + markSizeTitles: mapTitle(markSizeAccessor), splitColumnTitles: mapTitle(splitColumnAccessor), splitRowTitles: mapTitle(splitRowAccessor), }; diff --git a/src/plugins/vis_types/xy/public/__snapshots__/to_ast.test.ts.snap b/src/plugins/vis_types/xy/public/__snapshots__/to_ast.test.ts.snap index 8f11e3521cdd7..37b8daab6a7a4 100644 --- a/src/plugins/vis_types/xy/public/__snapshots__/to_ast.test.ts.snap +++ b/src/plugins/vis_types/xy/public/__snapshots__/to_ast.test.ts.snap @@ -20,6 +20,9 @@ Object { "showTooltip": Array [ true, ], + "singleTable": Array [ + true, + ], "valueLabels": Array [ "hide", ], diff --git a/src/plugins/vis_types/xy/public/to_ast.ts b/src/plugins/vis_types/xy/public/to_ast.ts index 07a58a258abd6..7f8212eef7625 100644 --- a/src/plugins/vis_types/xy/public/to_ast.ts +++ b/src/plugins/vis_types/xy/public/to_ast.ts @@ -42,6 +42,8 @@ interface Bounds { max?: string | number; } +type YDimension = Omit & { accessor: string }; + const getCurveType = (type?: InterpolationMode) => { switch (type) { case 'cardinal': @@ -67,13 +69,13 @@ const prepareLengend = (params: VisParams, legendSize?: LegendSize) => { return buildExpression([legend]); }; -const getCorrectAccessor = (yAccessor: Dimension, aggId: string) => { +const getCorrectAccessor = (yAccessor: Dimension | YDimension, aggId: string) => { return typeof yAccessor.accessor === 'number' ? `col-${yAccessor.accessor}-${aggId}` : yAccessor.accessor; }; -const prepareDecoration = (axisId: string, yAccessor: Dimension, aggId: string) => { +const prepareDecoration = (axisId: string, yAccessor: YDimension, aggId: string) => { const dataDecorationConfig = buildExpressionFunction('dataDecorationConfig', { forAccessor: getCorrectAccessor(yAccessor, aggId), axisId, @@ -99,7 +101,7 @@ const prepareLayers = ( seriesParam: SeriesParam, isHistogram: boolean, valueAxes: ValueAxis[], - yAccessors: Dimension[], + yAccessors: YDimension[], xAccessor: Dimension | null, splitAccessors?: Dimension[], markSizeAccessor?: Dimension, @@ -294,7 +296,7 @@ const prepareReferenceLine = (thresholdLine: ThresholdLine, axisId: string) => { return buildExpression([referenceLine]); }; -const prepareVisDimension = (data: Dimension) => { +const prepareVisDimension = (data: Dimension | YDimension) => { const visDimension = buildExpressionFunction('visdimension', { accessor: data.accessor }); if (data.format) { @@ -389,16 +391,23 @@ export const toExpressionAst: VisToExpressionAst = async (vis, params legendSize = LegendSize.AUTO; } - const yAccessors = (dimensions.y || []).reduce>((acc, yDimension) => { - const yAgg = responseAggs[yDimension.accessor]; - const aggId = getSafeId(yAgg.id); - if (acc[aggId]) { - acc[aggId].push(yDimension); - } else { - acc[aggId] = [yDimension]; - } - return acc; - }, {}); + const yAccessors = (dimensions.y || []).reduce>( + (acc, yDimension) => { + const yAgg = responseAggs[yDimension.accessor]; + const aggId = getSafeId(yAgg.id); + const dimension: YDimension = { + ...yDimension, + accessor: getCorrectAccessor(yDimension, yAgg.id), + }; + if (acc[aggId]) { + acc[aggId].push(dimension); + } else { + acc[aggId] = [dimension]; + } + return acc; + }, + {} + ); const xScale = vis.params.categoryAxes[0].scale; @@ -417,7 +426,7 @@ export const toExpressionAst: VisToExpressionAst = async (vis, params const visTypeXy = buildExpressionFunction('layeredXyVis', { layers: [ ...finalSeriesParams - .filter((seriesParam) => seriesParam.show) + .filter((seriesParam) => seriesParam.show && yAccessors[seriesParam.data.id]) .map((seriesParam) => prepareLayers( seriesParam, @@ -474,6 +483,7 @@ export const toExpressionAst: VisToExpressionAst = async (vis, params splitColumnAccessor: dimensions.splitColumn?.map(prepareVisDimension), splitRowAccessor: dimensions.splitRow?.map(prepareVisDimension), valueLabels: vis.params.labels.show ? 'show' : 'hide', + singleTable: true, }); const ast = buildExpression(mapColumn ? [mapColumn, visTypeXy] : [visTypeXy]); From 4b4544d8f1acf2a0942854025e1075cd3f5a6cf4 Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Wed, 3 Aug 2022 13:27:14 +0300 Subject: [PATCH 24/27] Remove unused code --- .../expression_xy/common/helpers/index.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/plugins/chart_expressions/expression_xy/common/helpers/index.ts b/src/plugins/chart_expressions/expression_xy/common/helpers/index.ts index e2cb4a7bf419c..915a296571b10 100644 --- a/src/plugins/chart_expressions/expression_xy/common/helpers/index.ts +++ b/src/plugins/chart_expressions/expression_xy/common/helpers/index.ts @@ -6,12 +6,6 @@ * Side Public License, v 1. */ -export { - appendLayerIds, - getDataLayers, - getAccessors, - getShowLines, - getLayersWithTable, -} from './layers'; +export { appendLayerIds, getDataLayers, getAccessors, getShowLines } from './layers'; export { isTimeChart } from './visualization'; export { normalizeTable } from './table'; From 99ae23f0be9be341ad4372fb88c2d1fb57868e35 Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Tue, 9 Aug 2022 15:50:28 +0300 Subject: [PATCH 25/27] Fix Percentile aggragtion --- .../__snapshots__/xy_chart.test.tsx.snap | 10 +++++ .../public/components/data_layers.tsx | 26 ++++++++---- .../public/components/legend_action.tsx | 6 ++- .../public/components/legend_color_picker.tsx | 5 ++- .../public/components/tooltip/tooltip.tsx | 6 ++- .../public/components/xy_chart.tsx | 4 +- .../public/helpers/data_layers.tsx | 25 ++++++----- src/plugins/vis_types/xy/public/to_ast.ts | 42 ++++++++++++------- 8 files changed, 85 insertions(+), 39 deletions(-) diff --git a/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap b/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap index 1390545591f6c..e92644d7d2fb5 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap +++ b/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap @@ -524,6 +524,7 @@ exports[`XYChart component it renders area 1`] = ` }, "legendPosition": "top", "setColor": [Function], + "singleTable": undefined, "titles": Object { "first": Object { "markSizeTitles": Object {}, @@ -1505,6 +1506,7 @@ exports[`XYChart component it renders bar 1`] = ` }, "legendPosition": "top", "setColor": [Function], + "singleTable": undefined, "titles": Object { "first": Object { "markSizeTitles": Object {}, @@ -2486,6 +2488,7 @@ exports[`XYChart component it renders horizontal bar 1`] = ` }, "legendPosition": "top", "setColor": [Function], + "singleTable": undefined, "titles": Object { "first": Object { "markSizeTitles": Object {}, @@ -3467,6 +3470,7 @@ exports[`XYChart component it renders line 1`] = ` }, "legendPosition": "top", "setColor": [Function], + "singleTable": undefined, "titles": Object { "first": Object { "markSizeTitles": Object {}, @@ -4448,6 +4452,7 @@ exports[`XYChart component it renders stacked area 1`] = ` }, "legendPosition": "top", "setColor": [Function], + "singleTable": undefined, "titles": Object { "first": Object { "markSizeTitles": Object {}, @@ -5429,6 +5434,7 @@ exports[`XYChart component it renders stacked bar 1`] = ` }, "legendPosition": "top", "setColor": [Function], + "singleTable": undefined, "titles": Object { "first": Object { "markSizeTitles": Object {}, @@ -6410,6 +6416,7 @@ exports[`XYChart component it renders stacked horizontal bar 1`] = ` }, "legendPosition": "top", "setColor": [Function], + "singleTable": undefined, "titles": Object { "first": Object { "markSizeTitles": Object {}, @@ -7417,6 +7424,7 @@ exports[`XYChart component split chart should render split chart if both, splitR }, "legendPosition": "top", "setColor": [Function], + "singleTable": undefined, "titles": Object { "first": Object { "markSizeTitles": Object {}, @@ -8638,6 +8646,7 @@ exports[`XYChart component split chart should render split chart if splitColumnA }, "legendPosition": "top", "setColor": [Function], + "singleTable": undefined, "titles": Object { "first": Object { "markSizeTitles": Object {}, @@ -9850,6 +9859,7 @@ exports[`XYChart component split chart should render split chart if splitRowAcce }, "legendPosition": "top", "setColor": [Function], + "singleTable": undefined, "titles": Object { "first": Object { "markSizeTitles": Object {}, diff --git a/src/plugins/chart_expressions/expression_xy/public/components/data_layers.tsx b/src/plugins/chart_expressions/expression_xy/public/components/data_layers.tsx index ca7acd25fd785..035faf8d22b00 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/data_layers.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/data_layers.tsx @@ -110,10 +110,22 @@ export const DataLayers: FC = ({ : getColorAssignments(layers, titles, fieldFormats, formattedDatatables); return ( <> - {layers.flatMap((layer) => - layer.accessors.map((accessor, accessorIndex) => { - const { seriesType, columnToLabel, layerId, table } = layer; - const yColumnId = getAccessorByDimension(accessor, table.columns); + {layers.flatMap((layer) => { + const yPercentileAccessors: string[] = []; + const yAccessors: string[] = []; + layer.accessors.forEach((accessor) => { + const columnId = getAccessorByDimension(accessor, layer.table.columns); + if (columnId.includes('.')) { + yPercentileAccessors.push(columnId); + } else { + yAccessors.push(columnId); + } + }); + return ( + yPercentileAccessors.length ? [...yAccessors, yPercentileAccessors] : [...yAccessors] + ).map((accessor, accessorIndex) => { + const { seriesType, columnToLabel, layerId } = layer; + const yColumnId = Array.isArray(accessor) ? accessor[0] : accessor; const columnToLabelMap: Record = columnToLabel ? JSON.parse(columnToLabel) : {}; @@ -134,7 +146,7 @@ export const DataLayers: FC = ({ const seriesProps = getSeriesProps({ layer, titles: titles[layer.layerId], - accessor: yColumnId, + accessor, chartHasMoreThanOneBarSeries, colorAssignments, formatFactory, @@ -194,8 +206,8 @@ export const DataLayers: FC = ({ /> ); } - }) - )} + }); + })} ); }; diff --git a/src/plugins/chart_expressions/expression_xy/public/components/legend_action.tsx b/src/plugins/chart_expressions/expression_xy/public/components/legend_action.tsx index e27bb716c35c7..0d1d3b5b59256 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/legend_action.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/legend_action.tsx @@ -24,7 +24,8 @@ export const getLegendAction = ( onFilter: (data: FilterEvent['data']) => void, fieldFormats: LayersFieldFormats, formattedDatatables: DatatablesWithFormatInfo, - titles: LayersAccessorsTitles + titles: LayersAccessorsTitles, + singleTable?: boolean ): LegendAction => React.memo(({ series: [xySeries] }) => { const series = xySeries as XYChartSeriesIdentifier; @@ -35,6 +36,7 @@ export const getLegendAction = ( ) ) ); + const allYAccessors = dataLayers.flatMap((dataLayer) => dataLayer.accessors); if (layerIndex === -1) { return null; @@ -78,7 +80,7 @@ export const getLegendAction = ( series, { splitAccessors: layer.splitAccessors, - accessorsCount: layer.accessors.length, + accessorsCount: singleTable ? allYAccessors.length : layer.accessors.length, columns: table.columns, splitAccessorsFormats: fieldFormats[layer.layerId].splitSeriesAccessors, alreadyFormattedColumns: formattedDatatables[layer.layerId].formattedColumns, diff --git a/src/plugins/chart_expressions/expression_xy/public/components/legend_color_picker.tsx b/src/plugins/chart_expressions/expression_xy/public/components/legend_color_picker.tsx index fa4e02a5a9d74..3573fc65e5288 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/legend_color_picker.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/legend_color_picker.tsx @@ -43,6 +43,7 @@ export interface LegendColorPickerWrapperContextType { formattedDatatables: DatatablesWithFormatInfo; titles: LayersAccessorsTitles; fieldFormats: LayersFieldFormats; + singleTable?: boolean; } export const LegendColorPickerWrapperContext = createContext< @@ -73,16 +74,18 @@ export const LegendColorPickerWrapper: LegendColorPicker = ({ titles, formattedDatatables, fieldFormats, + singleTable, } = colorPickerWrappingContext; const { layerId } = getMetaFromSeriesId(seriesIdentifier.specId); const layer = dataLayers.find((dataLayer) => dataLayer.layerId === layerId); + const allYAccessors = dataLayers.flatMap((dataLayer) => dataLayer.accessors); const seriesName = layer ? getSeriesName( seriesIdentifier as XYChartSeriesIdentifier, { splitAccessors: layer.splitAccessors ?? [], - accessorsCount: layer.accessors.length, + accessorsCount: singleTable ? allYAccessors.length : layer.accessors.length, columns: formattedDatatables[layer.layerId].table.columns, splitAccessorsFormats: fieldFormats[layer.layerId].splitSeriesAccessors, alreadyFormattedColumns: formattedDatatables[layer.layerId].formattedColumns, diff --git a/src/plugins/chart_expressions/expression_xy/public/components/tooltip/tooltip.tsx b/src/plugins/chart_expressions/expression_xy/public/components/tooltip/tooltip.tsx index ca7152e485c9f..6d4ba715dae0d 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/tooltip/tooltip.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/tooltip/tooltip.tsx @@ -56,7 +56,7 @@ export const Tooltip: FC = ({ const data: TooltipData[] = []; const seriesIdentifier = pickedValue.seriesIdentifier as XYChartSeriesIdentifier; - const { layerId, xAccessor, yAccessor } = getMetaFromSeriesId(seriesIdentifier.specId); + const { layerId, xAccessor, yAccessors } = getMetaFromSeriesId(seriesIdentifier.specId); const { formattedColumns, table } = formattedDatatables[layerId]; const layerTitles = titles[layerId]; const layerFormats = fieldFormats[layerId]; @@ -75,7 +75,9 @@ export const Tooltip: FC = ({ }); } - const tooltipYAccessor = yAccessor === seriesIdentifier.yAccessor ? yAccessor : null; + const tooltipYAccessor = yAccessors.includes(seriesIdentifier.yAccessor as string) + ? (seriesIdentifier.yAccessor as string) + : null; if (tooltipYAccessor) { const yFormatter = formatFactory(layerFormats.yAccessors[tooltipYAccessor]); data.push({ diff --git a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx index 16db7775a6d86..c94eccaeed0ba 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx @@ -737,6 +737,7 @@ export function XYChart({ formattedDatatables, titles, fieldFormats, + singleTable, }} > @@ -827,7 +828,8 @@ export function XYChart({ onClickValue, fieldFormats, formattedDatatables, - titles + titles, + singleTable ) : undefined } diff --git a/src/plugins/chart_expressions/expression_xy/public/helpers/data_layers.tsx b/src/plugins/chart_expressions/expression_xy/public/helpers/data_layers.tsx index bb37e1c2a56fb..8098bb0efe02b 100644 --- a/src/plugins/chart_expressions/expression_xy/public/helpers/data_layers.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/helpers/data_layers.tsx @@ -38,7 +38,7 @@ type SeriesSpec = LineSeriesProps & BarSeriesProps & AreaSeriesProps; type GetSeriesPropsFn = (config: { layer: CommonXYDataLayerConfig; titles?: LayerAccessorsTitles; - accessor: string; + accessor: string | string[]; chartHasMoreThanOneBarSeries?: boolean; formatFactory: FormatFactory; colorAssignments: ColorAssignments; @@ -74,7 +74,6 @@ type GetColorFn = ( seriesIdentifier: XYChartSeriesIdentifier, config: { layer: CommonXYDataLayerConfig; - accessor: string; colorAssignments: ColorAssignments; paletteService: PaletteRegistry; getSeriesNameFn: (d: XYChartSeriesIdentifier) => SeriesName; @@ -309,11 +308,11 @@ const getLineConfig: GetLineConfigFn = ({ showLines, lineWidth }) => ({ const getColor: GetColorFn = ( series, - { layer, accessor, colorAssignments, paletteService, syncColors, getSeriesNameFn }, + { layer, colorAssignments, paletteService, syncColors, getSeriesNameFn }, uiState, singleTable ) => { - const overwriteColor = getSeriesColor(layer, accessor); + const overwriteColor = getSeriesColor(layer, series.yAccessor as string); if (overwriteColor !== null) { return overwriteColor; } @@ -348,6 +347,7 @@ const getColor: GetColorFn = ( const EMPTY_ACCESSOR = '-'; const SPLIT_CHAR = ':'; +const SPLIT_Y_ACCESSORS = '|'; export const generateSeriesId = ( { layerId }: Pick, @@ -360,11 +360,11 @@ export const generateSeriesId = ( ); export const getMetaFromSeriesId = (seriesId: string) => { - const [layerId, xAccessor, yAccessor, ...splitAccessors] = seriesId.split(SPLIT_CHAR); + const [layerId, xAccessor, yAccessors, ...splitAccessors] = seriesId.split(SPLIT_CHAR); return { layerId, xAccessor: xAccessor === EMPTY_ACCESSOR ? undefined : xAccessor, - yAccessor, + yAccessors: yAccessors.split(SPLIT_Y_ACCESSORS), splitAccessor: splitAccessors[0] === EMPTY_ACCESSOR ? undefined : splitAccessors, }; }; @@ -411,7 +411,9 @@ export const getSeriesProps: GetSeriesPropsFn = ({ (isStacked || !splitColumnIds.length) && (isStacked || !isBarChart || !chartHasMoreThanOneBarSeries); - const formatter = table?.columns.find((column) => column.id === accessor)?.meta?.params; + const formatter = table?.columns.find( + (column) => column.id === (Array.isArray(accessor) ? accessor[0] : accessor) + )?.meta?.params; const markSizeColumnId = markSizeAccessor ? getAccessorByDimension(markSizeAccessor, table.columns) @@ -433,7 +435,9 @@ export const getSeriesProps: GetSeriesPropsFn = ({ !(xColumnId && row[xColumnId] === undefined) && !( splitColumnIds.some((splitColumnId) => row[splitColumnId] === undefined) && - row[accessor] === undefined + (Array.isArray(accessor) + ? accessor.some((a) => row[a] === undefined) + : row[accessor] === undefined) ) ); @@ -471,11 +475,11 @@ export const getSeriesProps: GetSeriesPropsFn = ({ id: generateSeriesId( layer, splitColumnIds.length ? splitColumnIds : [EMPTY_ACCESSOR], - accessor, + Array.isArray(accessor) ? accessor.join(SPLIT_Y_ACCESSORS) : accessor, xColumnId ), xAccessor: xColumnId || 'unifiedX', - yAccessors: [accessor], + yAccessors: Array.isArray(accessor) ? accessor : [accessor], markSizeAccessor: markSizeColumnId, markFormat: (value) => markFormatter.convert(value), data: rows, @@ -489,7 +493,6 @@ export const getSeriesProps: GetSeriesPropsFn = ({ series, { layer, - accessor, colorAssignments, paletteService, getSeriesNameFn, diff --git a/src/plugins/vis_types/xy/public/to_ast.ts b/src/plugins/vis_types/xy/public/to_ast.ts index 7f8212eef7625..05806c4549b7c 100644 --- a/src/plugins/vis_types/xy/public/to_ast.ts +++ b/src/plugins/vis_types/xy/public/to_ast.ts @@ -423,23 +423,35 @@ export const toExpressionAst: VisToExpressionAst = async (vis, params }); } + const series = finalSeriesParams.reduce>((acc, param) => { + if (param.show && yAccessors[param.data.id]) { + if (param.valueAxis && acc[param.valueAxis]) { + acc[param.valueAxis].yAccessors.push(...yAccessors[param.data.id]); + } else { + acc[param.valueAxis] = { + ...param, + yAccessors: [...yAccessors[param.data.id]], + }; + } + } + return acc; + }, {}); + const visTypeXy = buildExpressionFunction('layeredXyVis', { layers: [ - ...finalSeriesParams - .filter((seriesParam) => seriesParam.show && yAccessors[seriesParam.data.id]) - .map((seriesParam) => - prepareLayers( - seriesParam, - isHistogram, - vis.params.valueAxes, - yAccessors[seriesParam.data.id], - dimensions.x, - dimensions.series, - dimensions.z ? dimensions.z[0] : undefined, - vis.params.palette, - xScale - ) - ), + ...Object.keys(series).map((key) => + prepareLayers( + series[key], + isHistogram, + vis.params.valueAxes, + series[key].yAccessors, + dimensions.x, + dimensions.series, + dimensions.z ? dimensions.z[0] : undefined, + vis.params.palette, + xScale + ) + ), ...(vis.params.thresholdLine.show ? [prepareReferenceLine(vis.params.thresholdLine, vis.params.valueAxes[0].id)] : []), From f0e1bf2eeb37e40abcd414d0d9546b749de1f678 Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Wed, 10 Aug 2022 11:45:51 +0300 Subject: [PATCH 26/27] Fix problems with several series --- src/plugins/vis_types/xy/public/to_ast.ts | 42 ++++++++--------------- 1 file changed, 15 insertions(+), 27 deletions(-) diff --git a/src/plugins/vis_types/xy/public/to_ast.ts b/src/plugins/vis_types/xy/public/to_ast.ts index 05806c4549b7c..77b6790b08891 100644 --- a/src/plugins/vis_types/xy/public/to_ast.ts +++ b/src/plugins/vis_types/xy/public/to_ast.ts @@ -423,35 +423,23 @@ export const toExpressionAst: VisToExpressionAst = async (vis, params }); } - const series = finalSeriesParams.reduce>((acc, param) => { - if (param.show && yAccessors[param.data.id]) { - if (param.valueAxis && acc[param.valueAxis]) { - acc[param.valueAxis].yAccessors.push(...yAccessors[param.data.id]); - } else { - acc[param.valueAxis] = { - ...param, - yAccessors: [...yAccessors[param.data.id]], - }; - } - } - return acc; - }, {}); - const visTypeXy = buildExpressionFunction('layeredXyVis', { layers: [ - ...Object.keys(series).map((key) => - prepareLayers( - series[key], - isHistogram, - vis.params.valueAxes, - series[key].yAccessors, - dimensions.x, - dimensions.series, - dimensions.z ? dimensions.z[0] : undefined, - vis.params.palette, - xScale - ) - ), + ...finalSeriesParams + .filter((param) => param.show && yAccessors[param.data.id]) + .map((seriesParams) => + prepareLayers( + seriesParams, + isHistogram, + vis.params.valueAxes, + yAccessors[seriesParams.data.id], + dimensions.x, + dimensions.series, + dimensions.z ? dimensions.z[0] : undefined, + vis.params.palette, + xScale + ) + ), ...(vis.params.thresholdLine.show ? [prepareReferenceLine(vis.params.thresholdLine, vis.params.valueAxes[0].id)] : []), From 32b29f5490abedd781c8cb3e1af9eaa89c638ea8 Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Wed, 10 Aug 2022 12:01:32 +0300 Subject: [PATCH 27/27] Fix problems with hidden series --- src/plugins/vis_types/xy/public/to_ast.ts | 40 +++++++++++------------ 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/plugins/vis_types/xy/public/to_ast.ts b/src/plugins/vis_types/xy/public/to_ast.ts index 77b6790b08891..4041075b98c4d 100644 --- a/src/plugins/vis_types/xy/public/to_ast.ts +++ b/src/plugins/vis_types/xy/public/to_ast.ts @@ -423,23 +423,25 @@ export const toExpressionAst: VisToExpressionAst = async (vis, params }); } + const visibleSeries = finalSeriesParams.filter( + (param) => param.show && yAccessors[param.data.id] + ); + const visTypeXy = buildExpressionFunction('layeredXyVis', { layers: [ - ...finalSeriesParams - .filter((param) => param.show && yAccessors[param.data.id]) - .map((seriesParams) => - prepareLayers( - seriesParams, - isHistogram, - vis.params.valueAxes, - yAccessors[seriesParams.data.id], - dimensions.x, - dimensions.series, - dimensions.z ? dimensions.z[0] : undefined, - vis.params.palette, - xScale - ) - ), + ...visibleSeries.map((seriesParams) => + prepareLayers( + seriesParams, + isHistogram, + vis.params.valueAxes, + yAccessors[seriesParams.data.id], + dimensions.x, + dimensions.series, + dimensions.z ? dimensions.z[0] : undefined, + vis.params.palette, + xScale + ) + ), ...(vis.params.thresholdLine.show ? [prepareReferenceLine(vis.params.thresholdLine, vis.params.valueAxes[0].id)] : []), @@ -454,9 +456,7 @@ export const toExpressionAst: VisToExpressionAst = async (vis, params showTooltip: vis.params.addTooltip, markSizeRatio: dimensions.z && - finalSeriesParams.some( - (param) => param.type === ChartType.Area || param.type === ChartType.Line - ) + visibleSeries.some((param) => param.type === ChartType.Area || param.type === ChartType.Line) ? vis.params.radiusRatio * 0.6 // NOTE: downscale ratio to match current vislib implementation : undefined, legend: prepareLengend(vis.params, legendSize), @@ -471,13 +471,13 @@ export const toExpressionAst: VisToExpressionAst = async (vis, params : undefined ), // as we have only one x axis yAxisConfigs: vis.params.valueAxes - .filter((axis) => finalSeriesParams.some((seriesParam) => seriesParam.valueAxis === axis.id)) + .filter((axis) => visibleSeries.some((seriesParam) => seriesParam.valueAxis === axis.id)) .map((valueAxis) => prepareYAxis(valueAxis, vis.params.grid.valueAxis === valueAxis.id)), minTimeBarInterval: dimensions.x?.params && isDateHistogramParams(dimensions.x?.params) && dimensions.x?.params.date && - finalSeriesParams.some((param) => param.type === ChartType.Histogram) + visibleSeries.some((param) => param.type === ChartType.Histogram) ? dimensions.x?.params.intervalESValue + dimensions.x?.params.intervalESUnit : undefined, splitColumnAccessor: dimensions.splitColumn?.map(prepareVisDimension),