mirror of
https://github.com/elastic/kibana.git
synced 2025-06-27 18:51:07 -04:00
[XY] Add axes
support (#129476)
* Added `axes` support * Refactoring auto-assignment logic * Fixed reference line position * Fixed bug with auto-assignment. * Fixed snapshots * Fixed behavior of the horizontal reference lines. Co-authored-by: Yaroslav Kuznietsov <kuznetsov.yaroslav.yk@gmail.com> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Marta Bondyra <marta.bondyra@gmail.com>
This commit is contained in:
parent
ec3e3b27c6
commit
8fa2608172
81 changed files with 2784 additions and 1737 deletions
|
@ -58,6 +58,9 @@ export const sampleLayer: DataLayerConfig = {
|
||||||
columnToLabel: '{"a": "Label A", "b": "Label B", "d": "Label D"}',
|
columnToLabel: '{"a": "Label A", "b": "Label B", "d": "Label D"}',
|
||||||
xScaleType: 'ordinal',
|
xScaleType: 'ordinal',
|
||||||
isHistogram: false,
|
isHistogram: false,
|
||||||
|
isHorizontal: false,
|
||||||
|
isPercentage: false,
|
||||||
|
isStacked: false,
|
||||||
palette: mockPaletteOutput,
|
palette: mockPaletteOutput,
|
||||||
table: createSampleDatatableWithRows([]),
|
table: createSampleDatatableWithRows([]),
|
||||||
};
|
};
|
||||||
|
@ -73,6 +76,9 @@ export const sampleExtendedLayer: ExtendedDataLayerConfig = {
|
||||||
columnToLabel: '{"a": "Label A", "b": "Label B", "d": "Label D"}',
|
columnToLabel: '{"a": "Label A", "b": "Label B", "d": "Label D"}',
|
||||||
xScaleType: 'ordinal',
|
xScaleType: 'ordinal',
|
||||||
isHistogram: false,
|
isHistogram: false,
|
||||||
|
isHorizontal: false,
|
||||||
|
isStacked: false,
|
||||||
|
isPercentage: false,
|
||||||
palette: mockPaletteOutput,
|
palette: mockPaletteOutput,
|
||||||
table: createSampleDatatableWithRows([]),
|
table: createSampleDatatableWithRows([]),
|
||||||
};
|
};
|
||||||
|
@ -80,9 +86,6 @@ export const sampleExtendedLayer: ExtendedDataLayerConfig = {
|
||||||
export const createArgsWithLayers = (
|
export const createArgsWithLayers = (
|
||||||
layers: DataLayerConfig | DataLayerConfig[] = sampleLayer
|
layers: DataLayerConfig | DataLayerConfig[] = sampleLayer
|
||||||
): XYProps => ({
|
): XYProps => ({
|
||||||
xTitle: '',
|
|
||||||
yTitle: '',
|
|
||||||
yRightTitle: '',
|
|
||||||
showTooltip: true,
|
showTooltip: true,
|
||||||
legend: {
|
legend: {
|
||||||
type: 'legendConfig',
|
type: 'legendConfig',
|
||||||
|
@ -91,41 +94,44 @@ export const createArgsWithLayers = (
|
||||||
},
|
},
|
||||||
valueLabels: 'hide',
|
valueLabels: 'hide',
|
||||||
valuesInLegend: false,
|
valuesInLegend: false,
|
||||||
axisTitlesVisibilitySettings: {
|
xAxisConfig: {
|
||||||
type: 'axisTitlesVisibilityConfig',
|
type: 'xAxisConfig',
|
||||||
x: true,
|
position: 'bottom',
|
||||||
yLeft: true,
|
showGridLines: true,
|
||||||
yRight: true,
|
labelsOrientation: 0,
|
||||||
},
|
showLabels: true,
|
||||||
tickLabelsVisibilitySettings: {
|
showTitle: true,
|
||||||
type: 'tickLabelsConfig',
|
title: '',
|
||||||
x: true,
|
|
||||||
yLeft: false,
|
|
||||||
yRight: false,
|
|
||||||
},
|
|
||||||
labelsOrientation: {
|
|
||||||
type: 'labelsOrientationConfig',
|
|
||||||
x: 0,
|
|
||||||
yLeft: -90,
|
|
||||||
yRight: -45,
|
|
||||||
},
|
|
||||||
gridlinesVisibilitySettings: {
|
|
||||||
type: 'gridlinesConfig',
|
|
||||||
x: true,
|
|
||||||
yLeft: false,
|
|
||||||
yRight: false,
|
|
||||||
},
|
|
||||||
yLeftExtent: {
|
|
||||||
mode: 'full',
|
|
||||||
type: 'axisExtentConfig',
|
|
||||||
},
|
|
||||||
yRightExtent: {
|
|
||||||
mode: 'full',
|
|
||||||
type: 'axisExtentConfig',
|
|
||||||
},
|
},
|
||||||
|
yAxisConfigs: [
|
||||||
|
{
|
||||||
|
type: 'yAxisConfig',
|
||||||
|
position: 'right',
|
||||||
|
showGridLines: false,
|
||||||
|
labelsOrientation: -45,
|
||||||
|
showLabels: false,
|
||||||
|
showTitle: true,
|
||||||
|
title: '',
|
||||||
|
extent: {
|
||||||
|
mode: 'full',
|
||||||
|
type: 'axisExtentConfig',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'yAxisConfig',
|
||||||
|
position: 'left',
|
||||||
|
showGridLines: false,
|
||||||
|
labelsOrientation: -90,
|
||||||
|
showLabels: false,
|
||||||
|
showTitle: true,
|
||||||
|
title: '',
|
||||||
|
extent: {
|
||||||
|
mode: 'full',
|
||||||
|
type: 'axisExtentConfig',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
layers: Array.isArray(layers) ? layers : [layers],
|
layers: Array.isArray(layers) ? layers : [layers],
|
||||||
yLeftScale: 'linear',
|
|
||||||
yRightScale: 'linear',
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export function sampleArgs() {
|
export function sampleArgs() {
|
||||||
|
|
|
@ -8,22 +8,20 @@
|
||||||
|
|
||||||
export const XY_VIS = 'xyVis';
|
export const XY_VIS = 'xyVis';
|
||||||
export const LAYERED_XY_VIS = 'layeredXyVis';
|
export const LAYERED_XY_VIS = 'layeredXyVis';
|
||||||
export const Y_CONFIG = 'yConfig';
|
export const DATA_DECORATION_CONFIG = 'dataDecorationConfig';
|
||||||
export const REFERENCE_LINE_Y_CONFIG = 'referenceLineYConfig';
|
export const REFERENCE_LINE_DECORATION_CONFIG = 'referenceLineDecorationConfig';
|
||||||
export const EXTENDED_Y_CONFIG = 'extendedYConfig';
|
export const EXTENDED_REFERENCE_LINE_DECORATION_CONFIG = 'extendedReferenceLineDecorationConfig';
|
||||||
|
export const X_AXIS_CONFIG = 'xAxisConfig';
|
||||||
|
export const Y_AXIS_CONFIG = 'yAxisConfig';
|
||||||
export const DATA_LAYER = 'dataLayer';
|
export const DATA_LAYER = 'dataLayer';
|
||||||
export const EXTENDED_DATA_LAYER = 'extendedDataLayer';
|
export const EXTENDED_DATA_LAYER = 'extendedDataLayer';
|
||||||
export const LEGEND_CONFIG = 'legendConfig';
|
export const LEGEND_CONFIG = 'legendConfig';
|
||||||
export const XY_VIS_RENDERER = 'xyVis';
|
export const XY_VIS_RENDERER = 'xyVis';
|
||||||
export const GRID_LINES_CONFIG = 'gridlinesConfig';
|
|
||||||
export const ANNOTATION_LAYER = 'annotationLayer';
|
export const ANNOTATION_LAYER = 'annotationLayer';
|
||||||
export const EXTENDED_ANNOTATION_LAYER = 'extendedAnnotationLayer';
|
export const EXTENDED_ANNOTATION_LAYER = 'extendedAnnotationLayer';
|
||||||
export const TICK_LABELS_CONFIG = 'tickLabelsConfig';
|
|
||||||
export const AXIS_EXTENT_CONFIG = 'axisExtentConfig';
|
export const AXIS_EXTENT_CONFIG = 'axisExtentConfig';
|
||||||
export const REFERENCE_LINE = 'referenceLine';
|
export const REFERENCE_LINE = 'referenceLine';
|
||||||
export const REFERENCE_LINE_LAYER = 'referenceLineLayer';
|
export const REFERENCE_LINE_LAYER = 'referenceLineLayer';
|
||||||
export const LABELS_ORIENTATION_CONFIG = 'labelsOrientationConfig';
|
|
||||||
export const AXIS_TITLES_VISIBILITY_CONFIG = 'axisTitlesVisibilityConfig';
|
|
||||||
|
|
||||||
export const LayerTypes = {
|
export const LayerTypes = {
|
||||||
DATA: 'data',
|
DATA: 'data',
|
||||||
|
@ -82,13 +80,6 @@ export const SeriesTypes = {
|
||||||
BAR: 'bar',
|
BAR: 'bar',
|
||||||
LINE: 'line',
|
LINE: 'line',
|
||||||
AREA: 'area',
|
AREA: 'area',
|
||||||
BAR_STACKED: 'bar_stacked',
|
|
||||||
AREA_STACKED: 'area_stacked',
|
|
||||||
BAR_HORIZONTAL: 'bar_horizontal',
|
|
||||||
BAR_PERCENTAGE_STACKED: 'bar_percentage_stacked',
|
|
||||||
BAR_HORIZONTAL_STACKED: 'bar_horizontal_stacked',
|
|
||||||
AREA_PERCENTAGE_STACKED: 'area_percentage_stacked',
|
|
||||||
BAR_HORIZONTAL_PERCENTAGE_STACKED: 'bar_horizontal_percentage_stacked',
|
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export const YScaleTypes = {
|
export const YScaleTypes = {
|
||||||
|
@ -131,3 +122,10 @@ export const AvailableReferenceLineIcons = {
|
||||||
TAG: 'tag',
|
TAG: 'tag',
|
||||||
TRIANGLE: 'triangle',
|
TRIANGLE: 'triangle',
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
export const AxisModes = {
|
||||||
|
NORMAL: 'normal',
|
||||||
|
PERCENTAGE: 'percentage',
|
||||||
|
WIGGLE: 'wiggle',
|
||||||
|
SILHOUETTE: 'silhouette',
|
||||||
|
} as const;
|
||||||
|
|
|
@ -1,53 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 { i18n } from '@kbn/i18n';
|
|
||||||
import type { ExpressionFunctionDefinition } from '@kbn/expressions-plugin/common';
|
|
||||||
import { AXIS_TITLES_VISIBILITY_CONFIG } from '../constants';
|
|
||||||
import { AxesSettingsConfig, AxisTitlesVisibilityConfigResult } from '../types';
|
|
||||||
|
|
||||||
export const axisTitlesVisibilityConfigFunction: ExpressionFunctionDefinition<
|
|
||||||
typeof AXIS_TITLES_VISIBILITY_CONFIG,
|
|
||||||
null,
|
|
||||||
AxesSettingsConfig,
|
|
||||||
AxisTitlesVisibilityConfigResult
|
|
||||||
> = {
|
|
||||||
name: AXIS_TITLES_VISIBILITY_CONFIG,
|
|
||||||
aliases: [],
|
|
||||||
type: AXIS_TITLES_VISIBILITY_CONFIG,
|
|
||||||
help: i18n.translate('expressionXY.axisTitlesVisibilityConfig.help', {
|
|
||||||
defaultMessage: `Configure the xy chart's axis titles appearance`,
|
|
||||||
}),
|
|
||||||
inputTypes: ['null'],
|
|
||||||
args: {
|
|
||||||
x: {
|
|
||||||
types: ['boolean'],
|
|
||||||
help: i18n.translate('expressionXY.axisTitlesVisibilityConfig.x.help', {
|
|
||||||
defaultMessage: 'Specifies whether or not the title of the x-axis are visible.',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
yLeft: {
|
|
||||||
types: ['boolean'],
|
|
||||||
help: i18n.translate('expressionXY.axisTitlesVisibilityConfig.yLeft.help', {
|
|
||||||
defaultMessage: 'Specifies whether or not the title of the left y-axis are visible.',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
yRight: {
|
|
||||||
types: ['boolean'],
|
|
||||||
help: i18n.translate('expressionXY.axisTitlesVisibilityConfig.yRight.help', {
|
|
||||||
defaultMessage: 'Specifies whether or not the title of the right y-axis are visible.',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
fn(inputn, args) {
|
|
||||||
return {
|
|
||||||
type: AXIS_TITLES_VISIBILITY_CONFIG,
|
|
||||||
...args,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* 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 { strings } from '../i18n';
|
||||||
|
import { XAxisConfigFn, YAxisConfigFn } from '../types';
|
||||||
|
import { AXIS_EXTENT_CONFIG } from '../constants';
|
||||||
|
|
||||||
|
type CommonAxisConfigFn = XAxisConfigFn | YAxisConfigFn;
|
||||||
|
|
||||||
|
export const commonAxisConfigArgs: Omit<
|
||||||
|
CommonAxisConfigFn['args'],
|
||||||
|
'scaleType' | 'mode' | 'boundsMargin'
|
||||||
|
> = {
|
||||||
|
title: {
|
||||||
|
types: ['string'],
|
||||||
|
help: strings.getAxisTitleHelp(),
|
||||||
|
},
|
||||||
|
id: {
|
||||||
|
types: ['string'],
|
||||||
|
help: strings.getAxisIdHelp(),
|
||||||
|
},
|
||||||
|
hide: {
|
||||||
|
types: ['boolean'],
|
||||||
|
help: strings.getAxisHideHelp(),
|
||||||
|
},
|
||||||
|
labelColor: {
|
||||||
|
types: ['string'],
|
||||||
|
help: strings.getAxisLabelColorHelp(),
|
||||||
|
},
|
||||||
|
showOverlappingLabels: {
|
||||||
|
types: ['boolean'],
|
||||||
|
help: strings.getAxisShowOverlappingLabelsHelp(),
|
||||||
|
},
|
||||||
|
showDuplicates: {
|
||||||
|
types: ['boolean'],
|
||||||
|
help: strings.getAxisShowDuplicatesHelp(),
|
||||||
|
},
|
||||||
|
showGridLines: {
|
||||||
|
types: ['boolean'],
|
||||||
|
help: strings.getAxisShowGridLinesHelp(),
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
labelsOrientation: {
|
||||||
|
types: ['number'],
|
||||||
|
options: [0, -90, -45],
|
||||||
|
help: strings.getAxisLabelsOrientationHelp(),
|
||||||
|
},
|
||||||
|
showLabels: {
|
||||||
|
types: ['boolean'],
|
||||||
|
help: strings.getAxisShowLabelsHelp(),
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
showTitle: {
|
||||||
|
types: ['boolean'],
|
||||||
|
help: strings.getAxisShowTitleHelp(),
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
truncate: {
|
||||||
|
types: ['number'],
|
||||||
|
help: strings.getAxisTruncateHelp(),
|
||||||
|
},
|
||||||
|
extent: {
|
||||||
|
types: [AXIS_EXTENT_CONFIG],
|
||||||
|
help: strings.getAxisExtentHelp(),
|
||||||
|
default: `{${AXIS_EXTENT_CONFIG}}`,
|
||||||
|
},
|
||||||
|
};
|
|
@ -7,7 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ArgumentType } from '@kbn/expressions-plugin/common';
|
import { ArgumentType } from '@kbn/expressions-plugin/common';
|
||||||
import { SeriesTypes, XScaleTypes, Y_CONFIG } from '../constants';
|
import { SeriesTypes, XScaleTypes, DATA_DECORATION_CONFIG } from '../constants';
|
||||||
import { strings } from '../i18n';
|
import { strings } from '../i18n';
|
||||||
import { DataLayerArgs, ExtendedDataLayerArgs } from '../types';
|
import { DataLayerArgs, ExtendedDataLayerArgs } from '../types';
|
||||||
|
|
||||||
|
@ -43,6 +43,21 @@ export const commonDataLayerArgs: Omit<
|
||||||
default: false,
|
default: false,
|
||||||
help: strings.getIsHistogramHelp(),
|
help: strings.getIsHistogramHelp(),
|
||||||
},
|
},
|
||||||
|
isPercentage: {
|
||||||
|
types: ['boolean'],
|
||||||
|
default: false,
|
||||||
|
help: strings.getIsPercentageHelp(),
|
||||||
|
},
|
||||||
|
isStacked: {
|
||||||
|
types: ['boolean'],
|
||||||
|
default: false,
|
||||||
|
help: strings.getIsStackedHelp(),
|
||||||
|
},
|
||||||
|
isHorizontal: {
|
||||||
|
types: ['boolean'],
|
||||||
|
default: false,
|
||||||
|
help: strings.getIsHorizontalHelp(),
|
||||||
|
},
|
||||||
lineWidth: {
|
lineWidth: {
|
||||||
types: ['number'],
|
types: ['number'],
|
||||||
help: strings.getLineWidthHelp(),
|
help: strings.getLineWidthHelp(),
|
||||||
|
@ -59,9 +74,9 @@ export const commonDataLayerArgs: Omit<
|
||||||
types: ['boolean'],
|
types: ['boolean'],
|
||||||
help: strings.getShowLinesHelp(),
|
help: strings.getShowLinesHelp(),
|
||||||
},
|
},
|
||||||
yConfig: {
|
decorations: {
|
||||||
types: [Y_CONFIG],
|
types: [DATA_DECORATION_CONFIG],
|
||||||
help: strings.getYConfigHelp(),
|
help: strings.getDecorationsHelp(),
|
||||||
multi: true,
|
multi: true,
|
||||||
},
|
},
|
||||||
columnToLabel: {
|
columnToLabel: {
|
||||||
|
|
|
@ -7,17 +7,13 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import {
|
||||||
AXIS_EXTENT_CONFIG,
|
|
||||||
AXIS_TITLES_VISIBILITY_CONFIG,
|
|
||||||
EndValues,
|
EndValues,
|
||||||
FittingFunctions,
|
FittingFunctions,
|
||||||
GRID_LINES_CONFIG,
|
|
||||||
LABELS_ORIENTATION_CONFIG,
|
|
||||||
LEGEND_CONFIG,
|
LEGEND_CONFIG,
|
||||||
TICK_LABELS_CONFIG,
|
|
||||||
ValueLabelModes,
|
ValueLabelModes,
|
||||||
XYCurveTypes,
|
XYCurveTypes,
|
||||||
YScaleTypes,
|
X_AXIS_CONFIG,
|
||||||
|
Y_AXIS_CONFIG,
|
||||||
} from '../constants';
|
} from '../constants';
|
||||||
import { strings } from '../i18n';
|
import { strings } from '../i18n';
|
||||||
import { LayeredXyVisFn, XyVisFn } from '../types';
|
import { LayeredXyVisFn, XyVisFn } from '../types';
|
||||||
|
@ -25,45 +21,6 @@ import { LayeredXyVisFn, XyVisFn } from '../types';
|
||||||
type CommonXYFn = XyVisFn | LayeredXyVisFn;
|
type CommonXYFn = XyVisFn | LayeredXyVisFn;
|
||||||
|
|
||||||
export const commonXYArgs: CommonXYFn['args'] = {
|
export const commonXYArgs: CommonXYFn['args'] = {
|
||||||
xTitle: {
|
|
||||||
types: ['string'],
|
|
||||||
help: strings.getXTitleHelp(),
|
|
||||||
},
|
|
||||||
yTitle: {
|
|
||||||
types: ['string'],
|
|
||||||
help: strings.getYTitleHelp(),
|
|
||||||
},
|
|
||||||
yRightTitle: {
|
|
||||||
types: ['string'],
|
|
||||||
help: strings.getYRightTitleHelp(),
|
|
||||||
},
|
|
||||||
xExtent: {
|
|
||||||
types: [AXIS_EXTENT_CONFIG],
|
|
||||||
help: strings.getXExtentHelp(),
|
|
||||||
default: `{${AXIS_EXTENT_CONFIG}}`,
|
|
||||||
},
|
|
||||||
yLeftExtent: {
|
|
||||||
types: [AXIS_EXTENT_CONFIG],
|
|
||||||
help: strings.getYLeftExtentHelp(),
|
|
||||||
default: `{${AXIS_EXTENT_CONFIG}}`,
|
|
||||||
},
|
|
||||||
yRightExtent: {
|
|
||||||
types: [AXIS_EXTENT_CONFIG],
|
|
||||||
help: strings.getYRightExtentHelp(),
|
|
||||||
default: `{${AXIS_EXTENT_CONFIG}}`,
|
|
||||||
},
|
|
||||||
yLeftScale: {
|
|
||||||
options: [...Object.values(YScaleTypes)],
|
|
||||||
help: strings.getYLeftScaleTypeHelp(),
|
|
||||||
default: YScaleTypes.LINEAR,
|
|
||||||
strict: true,
|
|
||||||
},
|
|
||||||
yRightScale: {
|
|
||||||
options: [...Object.values(YScaleTypes)],
|
|
||||||
help: strings.getYRightScaleTypeHelp(),
|
|
||||||
default: YScaleTypes.LINEAR,
|
|
||||||
strict: true,
|
|
||||||
},
|
|
||||||
legend: {
|
legend: {
|
||||||
types: [LEGEND_CONFIG],
|
types: [LEGEND_CONFIG],
|
||||||
help: strings.getLegendHelp(),
|
help: strings.getLegendHelp(),
|
||||||
|
@ -93,22 +50,6 @@ export const commonXYArgs: CommonXYFn['args'] = {
|
||||||
strict: true,
|
strict: true,
|
||||||
default: ValueLabelModes.HIDE,
|
default: ValueLabelModes.HIDE,
|
||||||
},
|
},
|
||||||
tickLabelsVisibilitySettings: {
|
|
||||||
types: [TICK_LABELS_CONFIG],
|
|
||||||
help: strings.getTickLabelsVisibilitySettingsHelp(),
|
|
||||||
},
|
|
||||||
labelsOrientation: {
|
|
||||||
types: [LABELS_ORIENTATION_CONFIG],
|
|
||||||
help: strings.getLabelsOrientationHelp(),
|
|
||||||
},
|
|
||||||
gridlinesVisibilitySettings: {
|
|
||||||
types: [GRID_LINES_CONFIG],
|
|
||||||
help: strings.getGridlinesVisibilitySettingsHelp(),
|
|
||||||
},
|
|
||||||
axisTitlesVisibilitySettings: {
|
|
||||||
types: [AXIS_TITLES_VISIBILITY_CONFIG],
|
|
||||||
help: strings.getAxisTitlesVisibilitySettingsHelp(),
|
|
||||||
},
|
|
||||||
curveType: {
|
curveType: {
|
||||||
types: ['string'],
|
types: ['string'],
|
||||||
options: [...Object.values(XYCurveTypes)],
|
options: [...Object.values(XYCurveTypes)],
|
||||||
|
@ -133,6 +74,15 @@ export const commonXYArgs: CommonXYFn['args'] = {
|
||||||
types: ['string'],
|
types: ['string'],
|
||||||
help: strings.getAriaLabelHelp(),
|
help: strings.getAriaLabelHelp(),
|
||||||
},
|
},
|
||||||
|
xAxisConfig: {
|
||||||
|
types: [X_AXIS_CONFIG],
|
||||||
|
help: strings.getXAxisConfigHelp(),
|
||||||
|
},
|
||||||
|
yAxisConfigs: {
|
||||||
|
types: [Y_AXIS_CONFIG],
|
||||||
|
help: strings.getyAxisConfigsHelp(),
|
||||||
|
multi: true,
|
||||||
|
},
|
||||||
detailedTooltip: {
|
detailedTooltip: {
|
||||||
types: ['boolean'],
|
types: ['boolean'],
|
||||||
help: strings.getDetailedTooltipHelp(),
|
help: strings.getDetailedTooltipHelp(),
|
||||||
|
|
|
@ -6,22 +6,19 @@
|
||||||
* Side Public License, v 1.
|
* Side Public License, v 1.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { YAxisModes } from '../constants';
|
|
||||||
import { strings } from '../i18n';
|
import { strings } from '../i18n';
|
||||||
import { YConfigFn, ExtendedYConfigFn } from '../types';
|
import { DataDecorationConfigFn, ReferenceLineDecorationConfigFn } from '../types';
|
||||||
|
|
||||||
type CommonYConfigFn = YConfigFn | ExtendedYConfigFn;
|
type CommonDecorationConfigFn = DataDecorationConfigFn | ReferenceLineDecorationConfigFn;
|
||||||
|
|
||||||
export const commonYConfigArgs: CommonYConfigFn['args'] = {
|
export const commonDecorationConfigArgs: CommonDecorationConfigFn['args'] = {
|
||||||
forAccessor: {
|
forAccessor: {
|
||||||
types: ['string'],
|
types: ['string'],
|
||||||
help: strings.getForAccessorHelp(),
|
help: strings.getForAccessorHelp(),
|
||||||
},
|
},
|
||||||
axisMode: {
|
axisId: {
|
||||||
types: ['string'],
|
types: ['string'],
|
||||||
options: [...Object.values(YAxisModes)],
|
help: strings.getAxisIdHelp(),
|
||||||
help: strings.getAxisModeHelp(),
|
|
||||||
strict: true,
|
|
||||||
},
|
},
|
||||||
color: {
|
color: {
|
||||||
types: ['string'],
|
types: ['string'],
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* 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 { i18n } from '@kbn/i18n';
|
||||||
|
import type { ExpressionFunctionDefinition } from '@kbn/expressions-plugin/common';
|
||||||
|
import { DATA_DECORATION_CONFIG } from '../constants';
|
||||||
|
import { DataDecorationConfig, DataDecorationConfigResult } from '../types';
|
||||||
|
import { commonDecorationConfigArgs } from './common_y_config_args';
|
||||||
|
|
||||||
|
export const dataDecorationConfigFunction: ExpressionFunctionDefinition<
|
||||||
|
typeof DATA_DECORATION_CONFIG,
|
||||||
|
null,
|
||||||
|
DataDecorationConfig,
|
||||||
|
DataDecorationConfigResult
|
||||||
|
> = {
|
||||||
|
name: DATA_DECORATION_CONFIG,
|
||||||
|
aliases: [],
|
||||||
|
type: DATA_DECORATION_CONFIG,
|
||||||
|
help: i18n.translate('expressionXY.dataDecorationConfig.help', {
|
||||||
|
defaultMessage: `Configure the decoration of data`,
|
||||||
|
}),
|
||||||
|
inputTypes: ['null'],
|
||||||
|
args: {
|
||||||
|
...commonDecorationConfigArgs,
|
||||||
|
},
|
||||||
|
fn(input, args) {
|
||||||
|
return {
|
||||||
|
type: DATA_DECORATION_CONFIG,
|
||||||
|
...args,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
|
@ -20,6 +20,9 @@ describe('extendedDataLayerConfig', () => {
|
||||||
splitAccessor: 'd',
|
splitAccessor: 'd',
|
||||||
xScaleType: 'linear',
|
xScaleType: 'linear',
|
||||||
isHistogram: false,
|
isHistogram: false,
|
||||||
|
isHorizontal: false,
|
||||||
|
isPercentage: false,
|
||||||
|
isStacked: false,
|
||||||
palette: mockPaletteOutput,
|
palette: mockPaletteOutput,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 { AxesSettingsConfig } from '../types';
|
|
||||||
import { gridlinesConfigFunction } from '.';
|
|
||||||
import { createMockExecutionContext } from '@kbn/expressions-plugin/common/mocks';
|
|
||||||
|
|
||||||
describe('gridlinesConfig', () => {
|
|
||||||
test('produces the correct arguments', () => {
|
|
||||||
const args: AxesSettingsConfig = { x: true, yLeft: false, yRight: false };
|
|
||||||
const result = gridlinesConfigFunction.fn(null, args, createMockExecutionContext());
|
|
||||||
|
|
||||||
expect(result).toEqual({ type: 'gridlinesConfig', ...args });
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,53 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 { i18n } from '@kbn/i18n';
|
|
||||||
import type { ExpressionFunctionDefinition } from '@kbn/expressions-plugin/common';
|
|
||||||
import { GRID_LINES_CONFIG } from '../constants';
|
|
||||||
import { AxesSettingsConfig, GridlinesConfigResult } from '../types';
|
|
||||||
|
|
||||||
export const gridlinesConfigFunction: ExpressionFunctionDefinition<
|
|
||||||
typeof GRID_LINES_CONFIG,
|
|
||||||
null,
|
|
||||||
AxesSettingsConfig,
|
|
||||||
GridlinesConfigResult
|
|
||||||
> = {
|
|
||||||
name: GRID_LINES_CONFIG,
|
|
||||||
aliases: [],
|
|
||||||
type: GRID_LINES_CONFIG,
|
|
||||||
help: i18n.translate('expressionXY.gridlinesConfig.help', {
|
|
||||||
defaultMessage: `Configure the xy chart's gridlines appearance`,
|
|
||||||
}),
|
|
||||||
inputTypes: ['null'],
|
|
||||||
args: {
|
|
||||||
x: {
|
|
||||||
types: ['boolean'],
|
|
||||||
help: i18n.translate('expressionXY.gridlinesConfig.x.help', {
|
|
||||||
defaultMessage: 'Specifies whether or not the gridlines of the x-axis are visible.',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
yLeft: {
|
|
||||||
types: ['boolean'],
|
|
||||||
help: i18n.translate('expressionXY.gridlinesConfig.yLeft.help', {
|
|
||||||
defaultMessage: 'Specifies whether or not the gridlines of the left y-axis are visible.',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
yRight: {
|
|
||||||
types: ['boolean'],
|
|
||||||
help: i18n.translate('expressionXY.gridlinesConfig.yRight.help', {
|
|
||||||
defaultMessage: 'Specifies whether or not the gridlines of the right y-axis are visible.',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
fn(input, args) {
|
|
||||||
return {
|
|
||||||
type: GRID_LINES_CONFIG,
|
|
||||||
...args,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
|
@ -11,13 +11,11 @@ export * from './layered_xy_vis';
|
||||||
export * from './legend_config';
|
export * from './legend_config';
|
||||||
export * from './annotation_layer';
|
export * from './annotation_layer';
|
||||||
export * from './extended_annotation_layer';
|
export * from './extended_annotation_layer';
|
||||||
|
export * from './data_decoration_config';
|
||||||
export * from './y_axis_config';
|
export * from './y_axis_config';
|
||||||
export * from './extended_y_axis_config';
|
export * from './x_axis_config';
|
||||||
|
export * from './reference_line_decoration_config';
|
||||||
export * from './extended_data_layer';
|
export * from './extended_data_layer';
|
||||||
export * from './grid_lines_config';
|
|
||||||
export * from './axis_extent_config';
|
export * from './axis_extent_config';
|
||||||
export * from './tick_labels_config';
|
|
||||||
export * from './labels_orientation_config';
|
|
||||||
export * from './reference_line';
|
export * from './reference_line';
|
||||||
export * from './reference_line_layer';
|
export * from './reference_line_layer';
|
||||||
export * from './axis_titles_visibility_config';
|
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 { LabelsOrientationConfig } from '../types';
|
|
||||||
import { labelsOrientationConfigFunction } from '.';
|
|
||||||
import { createMockExecutionContext } from '@kbn/expressions-plugin/common/mocks';
|
|
||||||
|
|
||||||
describe('labelsOrientationConfig', () => {
|
|
||||||
test('produces the correct arguments', () => {
|
|
||||||
const args: LabelsOrientationConfig = { x: 0, yLeft: -90, yRight: -45 };
|
|
||||||
const result = labelsOrientationConfigFunction.fn(null, args, createMockExecutionContext());
|
|
||||||
|
|
||||||
expect(result).toEqual({ type: 'labelsOrientationConfig', ...args });
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,56 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 { i18n } from '@kbn/i18n';
|
|
||||||
import type { ExpressionFunctionDefinition } from '@kbn/expressions-plugin/common';
|
|
||||||
import { LABELS_ORIENTATION_CONFIG } from '../constants';
|
|
||||||
import { LabelsOrientationConfig, LabelsOrientationConfigResult } from '../types';
|
|
||||||
|
|
||||||
export const labelsOrientationConfigFunction: ExpressionFunctionDefinition<
|
|
||||||
typeof LABELS_ORIENTATION_CONFIG,
|
|
||||||
null,
|
|
||||||
LabelsOrientationConfig,
|
|
||||||
LabelsOrientationConfigResult
|
|
||||||
> = {
|
|
||||||
name: LABELS_ORIENTATION_CONFIG,
|
|
||||||
aliases: [],
|
|
||||||
type: LABELS_ORIENTATION_CONFIG,
|
|
||||||
help: i18n.translate('expressionXY.labelsOrientationConfig.help', {
|
|
||||||
defaultMessage: `Configure the xy chart's tick labels orientation`,
|
|
||||||
}),
|
|
||||||
inputTypes: ['null'],
|
|
||||||
args: {
|
|
||||||
x: {
|
|
||||||
types: ['number'],
|
|
||||||
options: [0, -90, -45],
|
|
||||||
help: i18n.translate('expressionXY.labelsOrientationConfig.x.help', {
|
|
||||||
defaultMessage: 'Specifies the labels orientation of the x-axis.',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
yLeft: {
|
|
||||||
types: ['number'],
|
|
||||||
options: [0, -90, -45],
|
|
||||||
help: i18n.translate('expressionXY.labelsOrientationConfig.yLeft.help', {
|
|
||||||
defaultMessage: 'Specifies the labels orientation of the left y-axis.',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
yRight: {
|
|
||||||
types: ['number'],
|
|
||||||
options: [0, -90, -45],
|
|
||||||
help: i18n.translate('expressionXY.labelsOrientationConfig.yRight.help', {
|
|
||||||
defaultMessage: 'Specifies the labels orientation of the right y-axis.',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
fn(input, args) {
|
|
||||||
return {
|
|
||||||
type: LABELS_ORIENTATION_CONFIG,
|
|
||||||
...args,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
|
@ -15,6 +15,7 @@ import {
|
||||||
validateMinTimeBarInterval,
|
validateMinTimeBarInterval,
|
||||||
hasBarLayer,
|
hasBarLayer,
|
||||||
errors,
|
errors,
|
||||||
|
validateAxes,
|
||||||
} from './validate';
|
} from './validate';
|
||||||
import { appendLayerIds, getDataLayers } from '../helpers';
|
import { appendLayerIds, getDataLayers } from '../helpers';
|
||||||
|
|
||||||
|
@ -35,6 +36,8 @@ export const layeredXyVisFn: LayeredXyVisFn['fn'] = async (data, args, handlers)
|
||||||
throw new Error(errors.markSizeRatioWithoutAccessor());
|
throw new Error(errors.markSizeRatioWithoutAccessor());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
validateAxes(dataLayers, args.yAxisConfigs);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: 'render',
|
type: 'render',
|
||||||
as: XY_VIS_RENDERER,
|
as: XY_VIS_RENDERER,
|
||||||
|
|
|
@ -15,6 +15,7 @@ describe('referenceLine', () => {
|
||||||
const args: ReferenceLineArgs = {
|
const args: ReferenceLineArgs = {
|
||||||
value: 100,
|
value: 100,
|
||||||
fill: 'above',
|
fill: 'above',
|
||||||
|
position: 'bottom',
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = referenceLineFunction.fn(null, args, createMockExecutionContext());
|
const result = referenceLineFunction.fn(null, args, createMockExecutionContext());
|
||||||
|
@ -23,9 +24,9 @@ describe('referenceLine', () => {
|
||||||
type: 'referenceLine',
|
type: 'referenceLine',
|
||||||
layerType: 'referenceLine',
|
layerType: 'referenceLine',
|
||||||
lineLength: 0,
|
lineLength: 0,
|
||||||
yConfig: [
|
decorations: [
|
||||||
{
|
{
|
||||||
type: 'referenceLineYConfig',
|
type: 'extendedReferenceLineDecorationConfig',
|
||||||
...args,
|
...args,
|
||||||
textVisibility: false,
|
textVisibility: false,
|
||||||
},
|
},
|
||||||
|
@ -40,7 +41,7 @@ describe('referenceLine', () => {
|
||||||
value: 100,
|
value: 100,
|
||||||
icon: 'alert',
|
icon: 'alert',
|
||||||
iconPosition: 'below',
|
iconPosition: 'below',
|
||||||
axisMode: 'bottom',
|
position: 'bottom',
|
||||||
lineStyle: 'solid',
|
lineStyle: 'solid',
|
||||||
lineWidth: 10,
|
lineWidth: 10,
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
|
@ -54,9 +55,9 @@ describe('referenceLine', () => {
|
||||||
type: 'referenceLine',
|
type: 'referenceLine',
|
||||||
layerType: 'referenceLine',
|
layerType: 'referenceLine',
|
||||||
lineLength: 0,
|
lineLength: 0,
|
||||||
yConfig: [
|
decorations: [
|
||||||
{
|
{
|
||||||
type: 'referenceLineYConfig',
|
type: 'extendedReferenceLineDecorationConfig',
|
||||||
...args,
|
...args,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -69,6 +70,7 @@ describe('referenceLine', () => {
|
||||||
name: 'some name',
|
name: 'some name',
|
||||||
value: 100,
|
value: 100,
|
||||||
fill: 'none',
|
fill: 'none',
|
||||||
|
position: 'bottom',
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = referenceLineFunction.fn(null, args, createMockExecutionContext());
|
const result = referenceLineFunction.fn(null, args, createMockExecutionContext());
|
||||||
|
@ -77,9 +79,9 @@ describe('referenceLine', () => {
|
||||||
type: 'referenceLine',
|
type: 'referenceLine',
|
||||||
layerType: 'referenceLine',
|
layerType: 'referenceLine',
|
||||||
lineLength: 0,
|
lineLength: 0,
|
||||||
yConfig: [
|
decorations: [
|
||||||
{
|
{
|
||||||
type: 'referenceLineYConfig',
|
type: 'extendedReferenceLineDecorationConfig',
|
||||||
...args,
|
...args,
|
||||||
textVisibility: true,
|
textVisibility: true,
|
||||||
},
|
},
|
||||||
|
@ -93,6 +95,7 @@ describe('referenceLine', () => {
|
||||||
value: 100,
|
value: 100,
|
||||||
textVisibility: true,
|
textVisibility: true,
|
||||||
fill: 'none',
|
fill: 'none',
|
||||||
|
position: 'bottom',
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = referenceLineFunction.fn(null, args, createMockExecutionContext());
|
const result = referenceLineFunction.fn(null, args, createMockExecutionContext());
|
||||||
|
@ -101,9 +104,9 @@ describe('referenceLine', () => {
|
||||||
type: 'referenceLine',
|
type: 'referenceLine',
|
||||||
layerType: 'referenceLine',
|
layerType: 'referenceLine',
|
||||||
lineLength: 0,
|
lineLength: 0,
|
||||||
yConfig: [
|
decorations: [
|
||||||
{
|
{
|
||||||
type: 'referenceLineYConfig',
|
type: 'extendedReferenceLineDecorationConfig',
|
||||||
...args,
|
...args,
|
||||||
textVisibility: false,
|
textVisibility: false,
|
||||||
},
|
},
|
||||||
|
@ -119,6 +122,7 @@ describe('referenceLine', () => {
|
||||||
name: 'some text',
|
name: 'some text',
|
||||||
textVisibility,
|
textVisibility,
|
||||||
fill: 'none',
|
fill: 'none',
|
||||||
|
position: 'bottom',
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = referenceLineFunction.fn(null, args, createMockExecutionContext());
|
const result = referenceLineFunction.fn(null, args, createMockExecutionContext());
|
||||||
|
@ -127,9 +131,9 @@ describe('referenceLine', () => {
|
||||||
type: 'referenceLine',
|
type: 'referenceLine',
|
||||||
layerType: 'referenceLine',
|
layerType: 'referenceLine',
|
||||||
lineLength: 0,
|
lineLength: 0,
|
||||||
yConfig: [
|
decorations: [
|
||||||
{
|
{
|
||||||
type: 'referenceLineYConfig',
|
type: 'extendedReferenceLineDecorationConfig',
|
||||||
...args,
|
...args,
|
||||||
textVisibility,
|
textVisibility,
|
||||||
},
|
},
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
* Side Public License, v 1.
|
* Side Public License, v 1.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { Position } from '@elastic/charts';
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
import {
|
import {
|
||||||
AvailableReferenceLineIcons,
|
AvailableReferenceLineIcons,
|
||||||
|
@ -14,8 +15,7 @@ import {
|
||||||
LayerTypes,
|
LayerTypes,
|
||||||
LineStyles,
|
LineStyles,
|
||||||
REFERENCE_LINE,
|
REFERENCE_LINE,
|
||||||
REFERENCE_LINE_Y_CONFIG,
|
EXTENDED_REFERENCE_LINE_DECORATION_CONFIG,
|
||||||
YAxisModes,
|
|
||||||
} from '../constants';
|
} from '../constants';
|
||||||
import { ReferenceLineFn } from '../types';
|
import { ReferenceLineFn } from '../types';
|
||||||
import { strings } from '../i18n';
|
import { strings } from '../i18n';
|
||||||
|
@ -36,13 +36,23 @@ export const referenceLineFunction: ReferenceLineFn = {
|
||||||
help: strings.getReferenceLineValueHelp(),
|
help: strings.getReferenceLineValueHelp(),
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
axisMode: {
|
position: {
|
||||||
types: ['string'],
|
types: ['string'],
|
||||||
options: [...Object.values(YAxisModes)],
|
options: [Position.Right, Position.Left],
|
||||||
help: strings.getAxisModeHelp(),
|
help: i18n.translate('expressionXY.referenceLine.position.help', {
|
||||||
default: YAxisModes.AUTO,
|
defaultMessage:
|
||||||
|
'Position of axis (first axis of that position) to which the reference line belongs.',
|
||||||
|
}),
|
||||||
|
default: Position.Left,
|
||||||
strict: true,
|
strict: true,
|
||||||
},
|
},
|
||||||
|
axisId: {
|
||||||
|
types: ['string'],
|
||||||
|
help: i18n.translate('expressionXY.referenceLine.axisId.help', {
|
||||||
|
defaultMessage:
|
||||||
|
'Id of axis to which the reference line belongs. It has higher priority than "position"',
|
||||||
|
}),
|
||||||
|
},
|
||||||
color: {
|
color: {
|
||||||
types: ['string'],
|
types: ['string'],
|
||||||
help: strings.getColorHelp(),
|
help: strings.getColorHelp(),
|
||||||
|
@ -50,7 +60,7 @@ export const referenceLineFunction: ReferenceLineFn = {
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
types: ['string'],
|
types: ['string'],
|
||||||
options: [...Object.values(LineStyles)],
|
options: [...Object.values(LineStyles)],
|
||||||
help: i18n.translate('expressionXY.yConfig.lineStyle.help', {
|
help: i18n.translate('expressionXY.decorationConfig.lineStyle.help', {
|
||||||
defaultMessage: 'The style of the reference line',
|
defaultMessage: 'The style of the reference line',
|
||||||
}),
|
}),
|
||||||
default: LineStyles.SOLID,
|
default: LineStyles.SOLID,
|
||||||
|
@ -58,14 +68,14 @@ export const referenceLineFunction: ReferenceLineFn = {
|
||||||
},
|
},
|
||||||
lineWidth: {
|
lineWidth: {
|
||||||
types: ['number'],
|
types: ['number'],
|
||||||
help: i18n.translate('expressionXY.yConfig.lineWidth.help', {
|
help: i18n.translate('expressionXY.decorationConfig.lineWidth.help', {
|
||||||
defaultMessage: 'The width of the reference line',
|
defaultMessage: 'The width of the reference line',
|
||||||
}),
|
}),
|
||||||
default: 1,
|
default: 1,
|
||||||
},
|
},
|
||||||
icon: {
|
icon: {
|
||||||
types: ['string'],
|
types: ['string'],
|
||||||
help: i18n.translate('expressionXY.yConfig.icon.help', {
|
help: i18n.translate('expressionXY.decorationConfig.icon.help', {
|
||||||
defaultMessage: 'An optional icon used for reference lines',
|
defaultMessage: 'An optional icon used for reference lines',
|
||||||
}),
|
}),
|
||||||
options: [...Object.values(AvailableReferenceLineIcons)],
|
options: [...Object.values(AvailableReferenceLineIcons)],
|
||||||
|
@ -74,7 +84,7 @@ export const referenceLineFunction: ReferenceLineFn = {
|
||||||
iconPosition: {
|
iconPosition: {
|
||||||
types: ['string'],
|
types: ['string'],
|
||||||
options: [...Object.values(IconPositions)],
|
options: [...Object.values(IconPositions)],
|
||||||
help: i18n.translate('expressionXY.yConfig.iconPosition.help', {
|
help: i18n.translate('expressionXY.decorationConfig.iconPosition.help', {
|
||||||
defaultMessage: 'The placement of the icon for the reference line',
|
defaultMessage: 'The placement of the icon for the reference line',
|
||||||
}),
|
}),
|
||||||
default: IconPositions.AUTO,
|
default: IconPositions.AUTO,
|
||||||
|
@ -82,14 +92,14 @@ export const referenceLineFunction: ReferenceLineFn = {
|
||||||
},
|
},
|
||||||
textVisibility: {
|
textVisibility: {
|
||||||
types: ['boolean'],
|
types: ['boolean'],
|
||||||
help: i18n.translate('expressionXY.yConfig.textVisibility.help', {
|
help: i18n.translate('expressionXY.decorationConfig.textVisibility.help', {
|
||||||
defaultMessage: 'Visibility of the label on the reference line',
|
defaultMessage: 'Visibility of the label on the reference line',
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
fill: {
|
fill: {
|
||||||
types: ['string'],
|
types: ['string'],
|
||||||
options: [...Object.values(FillStyles)],
|
options: [...Object.values(FillStyles)],
|
||||||
help: i18n.translate('expressionXY.yConfig.fill.help', {
|
help: i18n.translate('expressionXY.decorationConfig.fill.help', {
|
||||||
defaultMessage: 'Fill',
|
defaultMessage: 'Fill',
|
||||||
}),
|
}),
|
||||||
default: FillStyles.NONE,
|
default: FillStyles.NONE,
|
||||||
|
@ -108,7 +118,7 @@ export const referenceLineFunction: ReferenceLineFn = {
|
||||||
type: REFERENCE_LINE,
|
type: REFERENCE_LINE,
|
||||||
layerType: LayerTypes.REFERENCELINE,
|
layerType: LayerTypes.REFERENCELINE,
|
||||||
lineLength: table?.rows.length ?? 0,
|
lineLength: table?.rows.length ?? 0,
|
||||||
yConfig: [{ ...args, textVisibility, type: REFERENCE_LINE_Y_CONFIG }],
|
decorations: [{ ...args, textVisibility, type: EXTENDED_REFERENCE_LINE_DECORATION_CONFIG }],
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,43 +6,54 @@
|
||||||
* Side Public License, v 1.
|
* Side Public License, v 1.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { Position } from '@elastic/charts';
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
import {
|
import {
|
||||||
AvailableReferenceLineIcons,
|
AvailableReferenceLineIcons,
|
||||||
EXTENDED_Y_CONFIG,
|
REFERENCE_LINE_DECORATION_CONFIG,
|
||||||
FillStyles,
|
FillStyles,
|
||||||
IconPositions,
|
IconPositions,
|
||||||
LineStyles,
|
LineStyles,
|
||||||
} from '../constants';
|
} from '../constants';
|
||||||
import { strings } from '../i18n';
|
import { strings } from '../i18n';
|
||||||
import { ExtendedYConfigFn } from '../types';
|
import { ReferenceLineDecorationConfigFn } from '../types';
|
||||||
import { commonYConfigArgs } from './common_y_config_args';
|
import { commonDecorationConfigArgs } from './common_y_config_args';
|
||||||
|
|
||||||
export const extendedYAxisConfigFunction: ExtendedYConfigFn = {
|
export const referenceLineDecorationConfigFunction: ReferenceLineDecorationConfigFn = {
|
||||||
name: EXTENDED_Y_CONFIG,
|
name: REFERENCE_LINE_DECORATION_CONFIG,
|
||||||
aliases: [],
|
aliases: [],
|
||||||
type: EXTENDED_Y_CONFIG,
|
type: REFERENCE_LINE_DECORATION_CONFIG,
|
||||||
help: strings.getYConfigFnHelp(),
|
help: strings.getDecorationsHelp(),
|
||||||
inputTypes: ['null'],
|
inputTypes: ['null'],
|
||||||
args: {
|
args: {
|
||||||
...commonYConfigArgs,
|
...commonDecorationConfigArgs,
|
||||||
|
position: {
|
||||||
|
types: ['string'],
|
||||||
|
options: [Position.Right, Position.Left, Position.Bottom],
|
||||||
|
help: i18n.translate('expressionXY.referenceLine.position.help', {
|
||||||
|
defaultMessage:
|
||||||
|
'Position of axis (first axis of that position) to which the reference line belongs.',
|
||||||
|
}),
|
||||||
|
default: Position.Left,
|
||||||
|
strict: true,
|
||||||
|
},
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
types: ['string'],
|
types: ['string'],
|
||||||
options: [...Object.values(LineStyles)],
|
options: [...Object.values(LineStyles)],
|
||||||
help: i18n.translate('expressionXY.yConfig.lineStyle.help', {
|
help: i18n.translate('expressionXY.decorationConfig.lineStyle.help', {
|
||||||
defaultMessage: 'The style of the reference line',
|
defaultMessage: 'The style of the reference line',
|
||||||
}),
|
}),
|
||||||
strict: true,
|
strict: true,
|
||||||
},
|
},
|
||||||
lineWidth: {
|
lineWidth: {
|
||||||
types: ['number'],
|
types: ['number'],
|
||||||
help: i18n.translate('expressionXY.yConfig.lineWidth.help', {
|
help: i18n.translate('expressionXY.decorationConfig.lineWidth.help', {
|
||||||
defaultMessage: 'The width of the reference line',
|
defaultMessage: 'The width of the reference line',
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
icon: {
|
icon: {
|
||||||
types: ['string'],
|
types: ['string'],
|
||||||
help: i18n.translate('expressionXY.yConfig.icon.help', {
|
help: i18n.translate('expressionXY.decorationConfig.icon.help', {
|
||||||
defaultMessage: 'An optional icon used for reference lines',
|
defaultMessage: 'An optional icon used for reference lines',
|
||||||
}),
|
}),
|
||||||
options: [...Object.values(AvailableReferenceLineIcons)],
|
options: [...Object.values(AvailableReferenceLineIcons)],
|
||||||
|
@ -51,21 +62,21 @@ export const extendedYAxisConfigFunction: ExtendedYConfigFn = {
|
||||||
iconPosition: {
|
iconPosition: {
|
||||||
types: ['string'],
|
types: ['string'],
|
||||||
options: [...Object.values(IconPositions)],
|
options: [...Object.values(IconPositions)],
|
||||||
help: i18n.translate('expressionXY.yConfig.iconPosition.help', {
|
help: i18n.translate('expressionXY.decorationConfig.iconPosition.help', {
|
||||||
defaultMessage: 'The placement of the icon for the reference line',
|
defaultMessage: 'The placement of the icon for the reference line',
|
||||||
}),
|
}),
|
||||||
strict: true,
|
strict: true,
|
||||||
},
|
},
|
||||||
textVisibility: {
|
textVisibility: {
|
||||||
types: ['boolean'],
|
types: ['boolean'],
|
||||||
help: i18n.translate('expressionXY.yConfig.textVisibility.help', {
|
help: i18n.translate('expressionXY.decorationConfig.textVisibility.help', {
|
||||||
defaultMessage: 'Visibility of the label on the reference line',
|
defaultMessage: 'Visibility of the label on the reference line',
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
fill: {
|
fill: {
|
||||||
types: ['string'],
|
types: ['string'],
|
||||||
options: [...Object.values(FillStyles)],
|
options: [...Object.values(FillStyles)],
|
||||||
help: i18n.translate('expressionXY.yConfig.fill.help', {
|
help: i18n.translate('expressionXY.decorationConfig.fill.help', {
|
||||||
defaultMessage: 'Fill',
|
defaultMessage: 'Fill',
|
||||||
}),
|
}),
|
||||||
strict: true,
|
strict: true,
|
||||||
|
@ -73,7 +84,7 @@ export const extendedYAxisConfigFunction: ExtendedYConfigFn = {
|
||||||
},
|
},
|
||||||
fn(input, args) {
|
fn(input, args) {
|
||||||
return {
|
return {
|
||||||
type: EXTENDED_Y_CONFIG,
|
type: REFERENCE_LINE_DECORATION_CONFIG,
|
||||||
...args,
|
...args,
|
||||||
};
|
};
|
||||||
},
|
},
|
|
@ -6,7 +6,7 @@
|
||||||
* Side Public License, v 1.
|
* Side Public License, v 1.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { REFERENCE_LINE_LAYER, EXTENDED_Y_CONFIG } from '../constants';
|
import { REFERENCE_LINE_LAYER, REFERENCE_LINE_DECORATION_CONFIG } from '../constants';
|
||||||
import { ReferenceLineLayerFn } from '../types';
|
import { ReferenceLineLayerFn } from '../types';
|
||||||
import { strings } from '../i18n';
|
import { strings } from '../i18n';
|
||||||
|
|
||||||
|
@ -22,9 +22,9 @@ export const referenceLineLayerFunction: ReferenceLineLayerFn = {
|
||||||
help: strings.getRLAccessorsHelp(),
|
help: strings.getRLAccessorsHelp(),
|
||||||
multi: true,
|
multi: true,
|
||||||
},
|
},
|
||||||
yConfig: {
|
decorations: {
|
||||||
types: [EXTENDED_Y_CONFIG],
|
types: [REFERENCE_LINE_DECORATION_CONFIG],
|
||||||
help: strings.getRLYConfigHelp(),
|
help: strings.getRLDecorationConfigHelp(),
|
||||||
multi: true,
|
multi: true,
|
||||||
},
|
},
|
||||||
columnToLabel: {
|
columnToLabel: {
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 { AxesSettingsConfig } from '../types';
|
|
||||||
import { tickLabelsConfigFunction } from '.';
|
|
||||||
import { createMockExecutionContext } from '@kbn/expressions-plugin/common/mocks';
|
|
||||||
|
|
||||||
describe('tickLabelsConfig', () => {
|
|
||||||
test('produces the correct arguments', () => {
|
|
||||||
const args: AxesSettingsConfig = { x: true, yLeft: false, yRight: false };
|
|
||||||
const result = tickLabelsConfigFunction.fn(null, args, createMockExecutionContext());
|
|
||||||
|
|
||||||
expect(result).toEqual({ type: 'tickLabelsConfig', ...args });
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,53 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 { i18n } from '@kbn/i18n';
|
|
||||||
import type { ExpressionFunctionDefinition } from '@kbn/expressions-plugin/common';
|
|
||||||
import { TICK_LABELS_CONFIG } from '../constants';
|
|
||||||
import { AxesSettingsConfig, TickLabelsConfigResult } from '../types';
|
|
||||||
|
|
||||||
export const tickLabelsConfigFunction: ExpressionFunctionDefinition<
|
|
||||||
typeof TICK_LABELS_CONFIG,
|
|
||||||
null,
|
|
||||||
AxesSettingsConfig,
|
|
||||||
TickLabelsConfigResult
|
|
||||||
> = {
|
|
||||||
name: TICK_LABELS_CONFIG,
|
|
||||||
aliases: [],
|
|
||||||
type: TICK_LABELS_CONFIG,
|
|
||||||
help: i18n.translate('expressionXY.tickLabelsConfig.help', {
|
|
||||||
defaultMessage: `Configure the xy chart's tick labels appearance`,
|
|
||||||
}),
|
|
||||||
inputTypes: ['null'],
|
|
||||||
args: {
|
|
||||||
x: {
|
|
||||||
types: ['boolean'],
|
|
||||||
help: i18n.translate('expressionXY.tickLabelsConfig.x.help', {
|
|
||||||
defaultMessage: 'Specifies whether or not the tick labels of the x-axis are visible.',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
yLeft: {
|
|
||||||
types: ['boolean'],
|
|
||||||
help: i18n.translate('expressionXY.tickLabelsConfig.yLeft.help', {
|
|
||||||
defaultMessage: 'Specifies whether or not the tick labels of the left y-axis are visible.',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
yRight: {
|
|
||||||
types: ['boolean'],
|
|
||||||
help: i18n.translate('expressionXY.tickLabelsConfig.yRight.help', {
|
|
||||||
defaultMessage: 'Specifies whether or not the tick labels of the right y-axis are visible.',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
fn(input, args) {
|
|
||||||
return {
|
|
||||||
type: TICK_LABELS_CONFIG,
|
|
||||||
...args,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
|
@ -9,7 +9,7 @@
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
import { isValidInterval } from '@kbn/data-plugin/common';
|
import { isValidInterval } from '@kbn/data-plugin/common';
|
||||||
import { ExpressionValueVisDimension } from '@kbn/visualizations-plugin/common';
|
import { ExpressionValueVisDimension } from '@kbn/visualizations-plugin/common';
|
||||||
import { AxisExtentModes, ValueLabelModes } from '../constants';
|
import { AxisExtentModes, ValueLabelModes, SeriesTypes } from '../constants';
|
||||||
import {
|
import {
|
||||||
SeriesType,
|
SeriesType,
|
||||||
AxisExtentConfigResult,
|
AxisExtentConfigResult,
|
||||||
|
@ -17,7 +17,9 @@ import {
|
||||||
CommonXYDataLayerConfigResult,
|
CommonXYDataLayerConfigResult,
|
||||||
ValueLabelMode,
|
ValueLabelMode,
|
||||||
CommonXYDataLayerConfig,
|
CommonXYDataLayerConfig,
|
||||||
|
YAxisConfigResult,
|
||||||
ExtendedDataLayerConfigResult,
|
ExtendedDataLayerConfigResult,
|
||||||
|
XAxisConfigResult,
|
||||||
} from '../types';
|
} from '../types';
|
||||||
import { isTimeChart } from '../helpers';
|
import { isTimeChart } from '../helpers';
|
||||||
|
|
||||||
|
@ -111,19 +113,23 @@ export const errors = {
|
||||||
defaultMessage: '`minTimeBarInterval` argument is applicable only for time bar charts.',
|
defaultMessage: '`minTimeBarInterval` argument is applicable only for time bar charts.',
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
|
axisIsNotAssignedError: (axisId: string) =>
|
||||||
|
i18n.translate('expressionXY.reusable.function.xyVis.errors.axisIsNotAssignedError', {
|
||||||
|
defaultMessage:
|
||||||
|
'Axis with id: "{axisId}" is not assigned to any accessor. Please assign axis using the following construction: `decorations=\\{dataDecorationConfig forAccessor="your-accessor" axisId="{axisId}"\\}`',
|
||||||
|
values: { axisId },
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
export const hasBarLayer = (layers: Array<DataLayerConfigResult | CommonXYDataLayerConfig>) =>
|
export const hasBarLayer = (layers: Array<DataLayerConfigResult | CommonXYDataLayerConfig>) =>
|
||||||
layers.filter(({ seriesType }) => seriesType.includes('bar')).length > 0;
|
layers.some(({ seriesType }) => seriesType === SeriesTypes.BAR);
|
||||||
|
|
||||||
export const hasAreaLayer = (layers: Array<DataLayerConfigResult | CommonXYDataLayerConfig>) =>
|
export const hasAreaLayer = (layers: Array<DataLayerConfigResult | CommonXYDataLayerConfig>) =>
|
||||||
layers.filter(({ seriesType }) => seriesType.includes('area')).length > 0;
|
layers.some(({ seriesType }) => seriesType === SeriesTypes.AREA);
|
||||||
|
|
||||||
export const hasHistogramBarLayer = (
|
export const hasHistogramBarLayer = (
|
||||||
layers: Array<DataLayerConfigResult | CommonXYDataLayerConfig>
|
layers: Array<DataLayerConfigResult | CommonXYDataLayerConfig>
|
||||||
) =>
|
) => layers.some(({ seriesType, isHistogram }) => seriesType === SeriesTypes.BAR && isHistogram);
|
||||||
layers.filter(({ seriesType, isHistogram }) => seriesType.includes('bar') && isHistogram).length >
|
|
||||||
0;
|
|
||||||
|
|
||||||
export const isValidExtentWithCustomMode = (extent: AxisExtentConfigResult) => {
|
export const isValidExtentWithCustomMode = (extent: AxisExtentConfigResult) => {
|
||||||
const isValidLowerBound =
|
const isValidLowerBound =
|
||||||
|
@ -138,8 +144,8 @@ export const validateExtentForDataBounds = (
|
||||||
extent: AxisExtentConfigResult,
|
extent: AxisExtentConfigResult,
|
||||||
layers: Array<DataLayerConfigResult | CommonXYDataLayerConfig>
|
layers: Array<DataLayerConfigResult | CommonXYDataLayerConfig>
|
||||||
) => {
|
) => {
|
||||||
const lineSeries = layers.filter(({ seriesType }) => seriesType.includes('line'));
|
const hasLineSeries = layers.some(({ seriesType }) => seriesType === SeriesTypes.LINE);
|
||||||
if (!lineSeries.length && extent.mode === AxisExtentModes.DATA_BOUNDS) {
|
if (!hasLineSeries && extent.mode === AxisExtentModes.DATA_BOUNDS) {
|
||||||
throw new Error(errors.dataBoundsForNotLineChartError());
|
throw new Error(errors.dataBoundsForNotLineChartError());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -158,20 +164,46 @@ export const validateXExtent = (
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const validateExtent = (
|
export const validateExtents = (
|
||||||
extent: AxisExtentConfigResult,
|
dataLayers: Array<DataLayerConfigResult | CommonXYDataLayerConfig>,
|
||||||
hasBarOrArea: boolean,
|
hasBarOrArea: boolean,
|
||||||
dataLayers: Array<DataLayerConfigResult | CommonXYDataLayerConfig>
|
yAxisConfigs?: YAxisConfigResult[],
|
||||||
|
xAxisConfig?: XAxisConfigResult
|
||||||
) => {
|
) => {
|
||||||
if (
|
yAxisConfigs?.forEach((axis) => {
|
||||||
extent.mode === AxisExtentModes.CUSTOM &&
|
if (!axis.extent) {
|
||||||
hasBarOrArea &&
|
return;
|
||||||
!isValidExtentWithCustomMode(extent)
|
}
|
||||||
) {
|
if (
|
||||||
throw new Error(errors.extendBoundsAreInvalidError());
|
hasBarOrArea &&
|
||||||
}
|
axis.extent?.mode === AxisExtentModes.CUSTOM &&
|
||||||
|
!isValidExtentWithCustomMode(axis.extent)
|
||||||
|
) {
|
||||||
|
throw new Error(errors.extendBoundsAreInvalidError());
|
||||||
|
}
|
||||||
|
|
||||||
validateExtentForDataBounds(extent, dataLayers);
|
validateExtentForDataBounds(axis.extent, dataLayers);
|
||||||
|
});
|
||||||
|
|
||||||
|
validateXExtent(xAxisConfig?.extent, dataLayers);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const validateAxes = (
|
||||||
|
dataLayers: Array<DataLayerConfigResult | CommonXYDataLayerConfig>,
|
||||||
|
yAxisConfigs?: YAxisConfigResult[]
|
||||||
|
) => {
|
||||||
|
yAxisConfigs?.forEach((axis) => {
|
||||||
|
if (
|
||||||
|
axis.id &&
|
||||||
|
dataLayers.every(
|
||||||
|
(layer) =>
|
||||||
|
!layer.decorations ||
|
||||||
|
layer.decorations?.every((decorationConfig) => decorationConfig.axisId !== axis.id)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
throw new Error(errors.axisIsNotAssignedError(axis.id));
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const validateFillOpacity = (fillOpacity: number | undefined, hasArea: boolean) => {
|
export const validateFillOpacity = (fillOpacity: number | undefined, hasArea: boolean) => {
|
||||||
|
@ -191,7 +223,7 @@ export const validateValueLabels = (
|
||||||
};
|
};
|
||||||
|
|
||||||
const isAreaOrLineChart = (seriesType: SeriesType) =>
|
const isAreaOrLineChart = (seriesType: SeriesType) =>
|
||||||
seriesType.includes('line') || seriesType.includes('area');
|
seriesType === SeriesTypes.LINE || seriesType === SeriesTypes.AREA;
|
||||||
|
|
||||||
export const validateAddTimeMarker = (
|
export const validateAddTimeMarker = (
|
||||||
dataLayers: Array<DataLayerConfigResult | ExtendedDataLayerConfigResult>,
|
dataLayers: Array<DataLayerConfigResult | ExtendedDataLayerConfigResult>,
|
||||||
|
@ -206,7 +238,7 @@ export const validateMarkSizeForChartType = (
|
||||||
markSizeAccessor: ExpressionValueVisDimension | string | undefined,
|
markSizeAccessor: ExpressionValueVisDimension | string | undefined,
|
||||||
seriesType: SeriesType
|
seriesType: SeriesType
|
||||||
) => {
|
) => {
|
||||||
if (markSizeAccessor && !seriesType.includes('line') && !seriesType.includes('area')) {
|
if (markSizeAccessor && !isAreaOrLineChart(seriesType)) {
|
||||||
throw new Error(errors.markSizeAccessorForNonLineOrAreaChartsError());
|
throw new Error(errors.markSizeAccessorForNonLineOrAreaChartsError());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -248,7 +280,7 @@ export const validateLinesVisibilityForChartType = (
|
||||||
showLines: boolean | undefined,
|
showLines: boolean | undefined,
|
||||||
seriesType: SeriesType
|
seriesType: SeriesType
|
||||||
) => {
|
) => {
|
||||||
if (showLines && !(seriesType.includes('line') || seriesType.includes('area'))) {
|
if (showLines && !isAreaOrLineChart(seriesType)) {
|
||||||
throw new Error(errors.linesVisibilityForNonLineChartError());
|
throw new Error(errors.linesVisibilityForNonLineChartError());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* 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 { Position } from '@elastic/charts';
|
||||||
|
import { strings } from '../i18n';
|
||||||
|
import { XAxisConfigFn } from '../types';
|
||||||
|
import { X_AXIS_CONFIG } from '../constants';
|
||||||
|
import { commonAxisConfigArgs } from './common_axis_args';
|
||||||
|
|
||||||
|
export const xAxisConfigFunction: XAxisConfigFn = {
|
||||||
|
name: X_AXIS_CONFIG,
|
||||||
|
aliases: [],
|
||||||
|
type: X_AXIS_CONFIG,
|
||||||
|
help: strings.getXAxisConfigFnHelp(),
|
||||||
|
inputTypes: ['null'],
|
||||||
|
args: {
|
||||||
|
...commonAxisConfigArgs,
|
||||||
|
position: {
|
||||||
|
types: ['string'],
|
||||||
|
options: [Position.Top, Position.Bottom],
|
||||||
|
help: strings.getAxisPositionHelp(),
|
||||||
|
strict: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
fn(input, args) {
|
||||||
|
return {
|
||||||
|
type: X_AXIS_CONFIG,
|
||||||
|
...args,
|
||||||
|
position: args.position ?? Position.Bottom,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
|
@ -233,7 +233,10 @@ describe('xyVis', () => {
|
||||||
annotationLayers: [],
|
annotationLayers: [],
|
||||||
isHistogram: true,
|
isHistogram: true,
|
||||||
xScaleType: 'time',
|
xScaleType: 'time',
|
||||||
xExtent: { type: 'axisExtentConfig', mode: 'dataBounds' },
|
xAxisConfig: {
|
||||||
|
type: 'xAxisConfig',
|
||||||
|
extent: { type: 'axisExtentConfig', mode: 'dataBounds' },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
createMockExecutionContext()
|
createMockExecutionContext()
|
||||||
)
|
)
|
||||||
|
@ -255,11 +258,14 @@ describe('xyVis', () => {
|
||||||
...restLayerArgs,
|
...restLayerArgs,
|
||||||
referenceLines: [],
|
referenceLines: [],
|
||||||
annotationLayers: [],
|
annotationLayers: [],
|
||||||
xExtent: {
|
xAxisConfig: {
|
||||||
type: 'axisExtentConfig',
|
type: 'xAxisConfig',
|
||||||
mode: 'full',
|
extent: {
|
||||||
lowerBound: undefined,
|
type: 'axisExtentConfig',
|
||||||
upperBound: undefined,
|
mode: 'full',
|
||||||
|
lowerBound: undefined,
|
||||||
|
upperBound: undefined,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
createMockExecutionContext()
|
createMockExecutionContext()
|
||||||
|
@ -282,9 +288,9 @@ describe('xyVis', () => {
|
||||||
...restLayerArgs,
|
...restLayerArgs,
|
||||||
referenceLines: [],
|
referenceLines: [],
|
||||||
annotationLayers: [],
|
annotationLayers: [],
|
||||||
xExtent: {
|
xAxisConfig: {
|
||||||
type: 'axisExtentConfig',
|
type: 'xAxisConfig',
|
||||||
mode: 'dataBounds',
|
extent: { type: 'axisExtentConfig', mode: 'dataBounds' },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
createMockExecutionContext()
|
createMockExecutionContext()
|
||||||
|
@ -292,7 +298,7 @@ describe('xyVis', () => {
|
||||||
).rejects.toThrowErrorMatchingSnapshot();
|
).rejects.toThrowErrorMatchingSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('it renders with custom xExtent for a numeric histogram', async () => {
|
test('it renders with custom x-axis extent for a numeric histogram', async () => {
|
||||||
const { data, args } = sampleArgs();
|
const { data, args } = sampleArgs();
|
||||||
const { layers, ...rest } = args;
|
const { layers, ...rest } = args;
|
||||||
const { layerId, layerType, table, type, ...restLayerArgs } = sampleLayer;
|
const { layerId, layerType, table, type, ...restLayerArgs } = sampleLayer;
|
||||||
|
@ -304,11 +310,14 @@ describe('xyVis', () => {
|
||||||
referenceLines: [],
|
referenceLines: [],
|
||||||
annotationLayers: [],
|
annotationLayers: [],
|
||||||
isHistogram: true,
|
isHistogram: true,
|
||||||
xExtent: {
|
xAxisConfig: {
|
||||||
type: 'axisExtentConfig',
|
type: 'xAxisConfig',
|
||||||
mode: 'custom',
|
extent: {
|
||||||
lowerBound: 0,
|
type: 'axisExtentConfig',
|
||||||
upperBound: 10,
|
mode: 'custom',
|
||||||
|
lowerBound: 0,
|
||||||
|
upperBound: 10,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
createMockExecutionContext()
|
createMockExecutionContext()
|
||||||
|
@ -320,11 +329,14 @@ describe('xyVis', () => {
|
||||||
value: {
|
value: {
|
||||||
args: {
|
args: {
|
||||||
...rest,
|
...rest,
|
||||||
xExtent: {
|
xAxisConfig: {
|
||||||
type: 'axisExtentConfig',
|
type: 'xAxisConfig',
|
||||||
mode: 'custom',
|
extent: {
|
||||||
lowerBound: 0,
|
type: 'axisExtentConfig',
|
||||||
upperBound: 10,
|
mode: 'custom',
|
||||||
|
lowerBound: 0,
|
||||||
|
upperBound: 10,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
layers: [
|
layers: [
|
||||||
{
|
{
|
||||||
|
|
|
@ -21,7 +21,7 @@ import {
|
||||||
hasAreaLayer,
|
hasAreaLayer,
|
||||||
hasBarLayer,
|
hasBarLayer,
|
||||||
hasHistogramBarLayer,
|
hasHistogramBarLayer,
|
||||||
validateExtent,
|
validateExtents,
|
||||||
validateFillOpacity,
|
validateFillOpacity,
|
||||||
validateMarkSizeRatioLimits,
|
validateMarkSizeRatioLimits,
|
||||||
validateValueLabels,
|
validateValueLabels,
|
||||||
|
@ -33,7 +33,7 @@ import {
|
||||||
validateLineWidthForChartType,
|
validateLineWidthForChartType,
|
||||||
validatePointsRadiusForChartType,
|
validatePointsRadiusForChartType,
|
||||||
validateLinesVisibilityForChartType,
|
validateLinesVisibilityForChartType,
|
||||||
validateXExtent,
|
validateAxes,
|
||||||
} from './validate';
|
} from './validate';
|
||||||
|
|
||||||
const createDataLayer = (args: XYArgs, table: Datatable): DataLayerConfigResult => {
|
const createDataLayer = (args: XYArgs, table: Datatable): DataLayerConfigResult => {
|
||||||
|
@ -46,8 +46,11 @@ const createDataLayer = (args: XYArgs, table: Datatable): DataLayerConfigResult
|
||||||
columnToLabel: args.columnToLabel,
|
columnToLabel: args.columnToLabel,
|
||||||
xScaleType: args.xScaleType,
|
xScaleType: args.xScaleType,
|
||||||
isHistogram: args.isHistogram,
|
isHistogram: args.isHistogram,
|
||||||
|
isPercentage: args.isPercentage,
|
||||||
|
isHorizontal: args.isHorizontal,
|
||||||
|
isStacked: args.isStacked,
|
||||||
palette: args.palette,
|
palette: args.palette,
|
||||||
yConfig: args.yConfig,
|
decorations: args.decorations,
|
||||||
showPoints: args.showPoints,
|
showPoints: args.showPoints,
|
||||||
pointsRadius: args.pointsRadius,
|
pointsRadius: args.pointsRadius,
|
||||||
lineWidth: args.lineWidth,
|
lineWidth: args.lineWidth,
|
||||||
|
@ -74,7 +77,10 @@ export const xyVisFn: XyVisFn['fn'] = async (data, args, handlers) => {
|
||||||
columnToLabel,
|
columnToLabel,
|
||||||
xScaleType,
|
xScaleType,
|
||||||
isHistogram,
|
isHistogram,
|
||||||
yConfig,
|
isHorizontal,
|
||||||
|
isPercentage,
|
||||||
|
isStacked,
|
||||||
|
decorations,
|
||||||
palette,
|
palette,
|
||||||
markSizeAccessor,
|
markSizeAccessor,
|
||||||
showPoints,
|
showPoints,
|
||||||
|
@ -121,9 +127,7 @@ export const xyVisFn: XyVisFn['fn'] = async (data, args, handlers) => {
|
||||||
const hasBar = hasBarLayer(dataLayers);
|
const hasBar = hasBarLayer(dataLayers);
|
||||||
const hasArea = hasAreaLayer(dataLayers);
|
const hasArea = hasAreaLayer(dataLayers);
|
||||||
|
|
||||||
validateXExtent(args.xExtent, dataLayers);
|
validateExtents(dataLayers, hasBar || hasArea, args.yAxisConfigs, args.xAxisConfig);
|
||||||
validateExtent(args.yLeftExtent, hasBar || hasArea, dataLayers);
|
|
||||||
validateExtent(args.yRightExtent, hasBar || hasArea, dataLayers);
|
|
||||||
validateFillOpacity(args.fillOpacity, hasArea);
|
validateFillOpacity(args.fillOpacity, hasArea);
|
||||||
validateAddTimeMarker(dataLayers, args.addTimeMarker);
|
validateAddTimeMarker(dataLayers, args.addTimeMarker);
|
||||||
validateMinTimeBarInterval(dataLayers, hasBar, args.minTimeBarInterval);
|
validateMinTimeBarInterval(dataLayers, hasBar, args.minTimeBarInterval);
|
||||||
|
@ -136,6 +140,7 @@ export const xyVisFn: XyVisFn['fn'] = async (data, args, handlers) => {
|
||||||
validateLineWidthForChartType(lineWidth, args.seriesType);
|
validateLineWidthForChartType(lineWidth, args.seriesType);
|
||||||
validateShowPointsForChartType(showPoints, args.seriesType);
|
validateShowPointsForChartType(showPoints, args.seriesType);
|
||||||
validatePointsRadiusForChartType(pointsRadius, args.seriesType);
|
validatePointsRadiusForChartType(pointsRadius, args.seriesType);
|
||||||
|
validateAxes(dataLayers, args.yAxisConfigs);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: 'render',
|
type: 'render',
|
||||||
|
|
|
@ -6,22 +6,46 @@
|
||||||
* Side Public License, v 1.
|
* Side Public License, v 1.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Y_CONFIG } from '../constants';
|
import { Position } from '@elastic/charts';
|
||||||
import { YConfigFn } from '../types';
|
|
||||||
import { strings } from '../i18n';
|
import { strings } from '../i18n';
|
||||||
import { commonYConfigArgs } from './common_y_config_args';
|
import { Y_AXIS_CONFIG, AxisModes, YScaleTypes } from '../constants';
|
||||||
|
import { YAxisConfigFn } from '../types';
|
||||||
|
import { commonAxisConfigArgs } from './common_axis_args';
|
||||||
|
|
||||||
export const yAxisConfigFunction: YConfigFn = {
|
export const yAxisConfigFunction: YAxisConfigFn = {
|
||||||
name: Y_CONFIG,
|
name: Y_AXIS_CONFIG,
|
||||||
aliases: [],
|
aliases: [],
|
||||||
type: Y_CONFIG,
|
type: Y_AXIS_CONFIG,
|
||||||
help: strings.getYConfigFnHelp(),
|
help: strings.getYAxisConfigFnHelp(),
|
||||||
inputTypes: ['null'],
|
inputTypes: ['null'],
|
||||||
args: { ...commonYConfigArgs },
|
args: {
|
||||||
|
...commonAxisConfigArgs,
|
||||||
|
mode: {
|
||||||
|
types: ['string'],
|
||||||
|
options: [...Object.values(AxisModes)],
|
||||||
|
help: strings.getAxisModeHelp(),
|
||||||
|
},
|
||||||
|
boundsMargin: {
|
||||||
|
types: ['number'],
|
||||||
|
help: strings.getAxisBoundsMarginHelp(),
|
||||||
|
},
|
||||||
|
scaleType: {
|
||||||
|
options: [...Object.values(YScaleTypes)],
|
||||||
|
help: strings.getAxisScaleTypeHelp(),
|
||||||
|
default: YScaleTypes.LINEAR,
|
||||||
|
},
|
||||||
|
position: {
|
||||||
|
types: ['string'],
|
||||||
|
options: [Position.Right, Position.Left],
|
||||||
|
help: strings.getAxisPositionHelp(),
|
||||||
|
strict: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
fn(input, args) {
|
fn(input, args) {
|
||||||
return {
|
return {
|
||||||
type: Y_CONFIG,
|
type: Y_AXIS_CONFIG,
|
||||||
...args,
|
...args,
|
||||||
|
position: args.position ?? Position.Left,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -59,6 +59,9 @@ describe('#getDataLayers', () => {
|
||||||
seriesType: 'bar',
|
seriesType: 'bar',
|
||||||
xScaleType: 'time',
|
xScaleType: 'time',
|
||||||
isHistogram: false,
|
isHistogram: false,
|
||||||
|
isHorizontal: false,
|
||||||
|
isPercentage: false,
|
||||||
|
isStacked: false,
|
||||||
table: { rows: [], columns: [], type: 'datatable' },
|
table: { rows: [], columns: [], type: 'datatable' },
|
||||||
palette: { type: 'system_palette', name: 'system' },
|
palette: { type: 'system_palette', name: 'system' },
|
||||||
},
|
},
|
||||||
|
|
|
@ -14,7 +14,7 @@ import {
|
||||||
ExtendedDataLayerArgs,
|
ExtendedDataLayerArgs,
|
||||||
DataLayerArgs,
|
DataLayerArgs,
|
||||||
} from '../types';
|
} from '../types';
|
||||||
import { LayerTypes } from '../constants';
|
import { LayerTypes, SeriesTypes } from '../constants';
|
||||||
|
|
||||||
function isWithLayerId<T>(layer: T): layer is T & WithLayerId {
|
function isWithLayerId<T>(layer: T): layer is T & WithLayerId {
|
||||||
return (layer as T & WithLayerId).layerId ? true : false;
|
return (layer as T & WithLayerId).layerId ? true : false;
|
||||||
|
@ -35,9 +35,7 @@ export function appendLayerIds<T>(
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getShowLines = (args: DataLayerArgs | ExtendedDataLayerArgs) =>
|
export const getShowLines = (args: DataLayerArgs | ExtendedDataLayerArgs) =>
|
||||||
args.seriesType.includes('line') || args.seriesType.includes('area')
|
args.showLines ?? (args.seriesType === SeriesTypes.LINE || args.seriesType !== SeriesTypes.AREA);
|
||||||
? args.showLines ?? true
|
|
||||||
: args.showLines;
|
|
||||||
|
|
||||||
export function getDataLayers(layers: XYExtendedLayerConfigResult[]) {
|
export function getDataLayers(layers: XYExtendedLayerConfigResult[]) {
|
||||||
return layers.filter<ExtendedDataLayerConfig>(
|
return layers.filter<ExtendedDataLayerConfig>(
|
||||||
|
|
|
@ -20,6 +20,9 @@ describe('#isTimeChart', () => {
|
||||||
seriesType: 'bar',
|
seriesType: 'bar',
|
||||||
xScaleType: 'time',
|
xScaleType: 'time',
|
||||||
isHistogram: false,
|
isHistogram: false,
|
||||||
|
isHorizontal: false,
|
||||||
|
isPercentage: false,
|
||||||
|
isStacked: false,
|
||||||
table: {
|
table: {
|
||||||
rows: [],
|
rows: [],
|
||||||
columns: [
|
columns: [
|
||||||
|
|
|
@ -29,38 +29,6 @@ export const strings = {
|
||||||
i18n.translate('expressionXY.xyVis.logDatatable.breakDown', {
|
i18n.translate('expressionXY.xyVis.logDatatable.breakDown', {
|
||||||
defaultMessage: 'Break down by',
|
defaultMessage: 'Break down by',
|
||||||
}),
|
}),
|
||||||
getXTitleHelp: () =>
|
|
||||||
i18n.translate('expressionXY.xyVis.xTitle.help', {
|
|
||||||
defaultMessage: 'X axis title',
|
|
||||||
}),
|
|
||||||
getYTitleHelp: () =>
|
|
||||||
i18n.translate('expressionXY.xyVis.yLeftTitle.help', {
|
|
||||||
defaultMessage: 'Y left axis title',
|
|
||||||
}),
|
|
||||||
getYRightTitleHelp: () =>
|
|
||||||
i18n.translate('expressionXY.xyVis.yRightTitle.help', {
|
|
||||||
defaultMessage: 'Y right axis title',
|
|
||||||
}),
|
|
||||||
getXExtentHelp: () =>
|
|
||||||
i18n.translate('expressionXY.xyVis.xExtent.help', {
|
|
||||||
defaultMessage: 'X axis extents',
|
|
||||||
}),
|
|
||||||
getYLeftExtentHelp: () =>
|
|
||||||
i18n.translate('expressionXY.xyVis.yLeftExtent.help', {
|
|
||||||
defaultMessage: 'Y left axis extents',
|
|
||||||
}),
|
|
||||||
getYRightExtentHelp: () =>
|
|
||||||
i18n.translate('expressionXY.xyVis.yRightExtent.help', {
|
|
||||||
defaultMessage: 'Y right axis extents',
|
|
||||||
}),
|
|
||||||
getYLeftScaleTypeHelp: () =>
|
|
||||||
i18n.translate('expressionXY.xyVis.yLeftScaleType.help', {
|
|
||||||
defaultMessage: 'The scale type of the left y axis',
|
|
||||||
}),
|
|
||||||
getYRightScaleTypeHelp: () =>
|
|
||||||
i18n.translate('expressionXY.xyVis.yRightScaleType.help', {
|
|
||||||
defaultMessage: 'The scale type of the right y axis',
|
|
||||||
}),
|
|
||||||
getLegendHelp: () =>
|
getLegendHelp: () =>
|
||||||
i18n.translate('expressionXY.xyVis.legend.help', {
|
i18n.translate('expressionXY.xyVis.legend.help', {
|
||||||
defaultMessage: 'Configure the chart legend.',
|
defaultMessage: 'Configure the chart legend.',
|
||||||
|
@ -77,22 +45,6 @@ export const strings = {
|
||||||
i18n.translate('expressionXY.xyVis.valueLabels.help', {
|
i18n.translate('expressionXY.xyVis.valueLabels.help', {
|
||||||
defaultMessage: 'Value labels mode',
|
defaultMessage: 'Value labels mode',
|
||||||
}),
|
}),
|
||||||
getTickLabelsVisibilitySettingsHelp: () =>
|
|
||||||
i18n.translate('expressionXY.xyVis.tickLabelsVisibilitySettings.help', {
|
|
||||||
defaultMessage: 'Show x and y axes tick labels',
|
|
||||||
}),
|
|
||||||
getLabelsOrientationHelp: () =>
|
|
||||||
i18n.translate('expressionXY.xyVis.labelsOrientation.help', {
|
|
||||||
defaultMessage: 'Defines the rotation of the axis labels',
|
|
||||||
}),
|
|
||||||
getGridlinesVisibilitySettingsHelp: () =>
|
|
||||||
i18n.translate('expressionXY.xyVis.gridlinesVisibilitySettings.help', {
|
|
||||||
defaultMessage: 'Show x and y axes gridlines',
|
|
||||||
}),
|
|
||||||
getAxisTitlesVisibilitySettingsHelp: () =>
|
|
||||||
i18n.translate('expressionXY.xyVis.axisTitlesVisibilitySettings.help', {
|
|
||||||
defaultMessage: 'Show x and y axes titles',
|
|
||||||
}),
|
|
||||||
getDataLayerHelp: () =>
|
getDataLayerHelp: () =>
|
||||||
i18n.translate('expressionXY.xyVis.dataLayer.help', {
|
i18n.translate('expressionXY.xyVis.dataLayer.help', {
|
||||||
defaultMessage: 'Data layer of visual series',
|
defaultMessage: 'Data layer of visual series',
|
||||||
|
@ -125,6 +77,14 @@ export const strings = {
|
||||||
i18n.translate('expressionXY.xyVis.ariaLabel.help', {
|
i18n.translate('expressionXY.xyVis.ariaLabel.help', {
|
||||||
defaultMessage: 'Specifies the aria label of the xy chart',
|
defaultMessage: 'Specifies the aria label of the xy chart',
|
||||||
}),
|
}),
|
||||||
|
getXAxisConfigHelp: () =>
|
||||||
|
i18n.translate('expressionXY.xyVis.xAxisConfig.help', {
|
||||||
|
defaultMessage: 'Specifies x-axis config',
|
||||||
|
}),
|
||||||
|
getyAxisConfigsHelp: () =>
|
||||||
|
i18n.translate('expressionXY.xyVis.yAxisConfigs.help', {
|
||||||
|
defaultMessage: 'Specifies y-axes configs',
|
||||||
|
}),
|
||||||
getDetailedTooltipHelp: () =>
|
getDetailedTooltipHelp: () =>
|
||||||
i18n.translate('expressionXY.xyVis.detailedTooltip.help', {
|
i18n.translate('expressionXY.xyVis.detailedTooltip.help', {
|
||||||
defaultMessage: 'Show detailed tooltip',
|
defaultMessage: 'Show detailed tooltip',
|
||||||
|
@ -185,6 +145,18 @@ export const strings = {
|
||||||
i18n.translate('expressionXY.dataLayer.isHistogram.help', {
|
i18n.translate('expressionXY.dataLayer.isHistogram.help', {
|
||||||
defaultMessage: 'Whether to layout the chart as a histogram',
|
defaultMessage: 'Whether to layout the chart as a histogram',
|
||||||
}),
|
}),
|
||||||
|
getIsStackedHelp: () =>
|
||||||
|
i18n.translate('expressionXY.dataLayer.isStacked.help', {
|
||||||
|
defaultMessage: 'Layout of the chart in stacked mode',
|
||||||
|
}),
|
||||||
|
getIsPercentageHelp: () =>
|
||||||
|
i18n.translate('expressionXY.dataLayer.isPercentage.help', {
|
||||||
|
defaultMessage: 'Whether to layout the chart has percentage mode',
|
||||||
|
}),
|
||||||
|
getIsHorizontalHelp: () =>
|
||||||
|
i18n.translate('expressionXY.dataLayer.isHorizontal.help', {
|
||||||
|
defaultMessage: 'Layout of the chart is horizontal',
|
||||||
|
}),
|
||||||
getSplitAccessorHelp: () =>
|
getSplitAccessorHelp: () =>
|
||||||
i18n.translate('expressionXY.dataLayer.splitAccessor.help', {
|
i18n.translate('expressionXY.dataLayer.splitAccessor.help', {
|
||||||
defaultMessage: 'The column to split by',
|
defaultMessage: 'The column to split by',
|
||||||
|
@ -213,9 +185,9 @@ export const strings = {
|
||||||
i18n.translate('expressionXY.dataLayer.showLines.help', {
|
i18n.translate('expressionXY.dataLayer.showLines.help', {
|
||||||
defaultMessage: 'Show lines between points',
|
defaultMessage: 'Show lines between points',
|
||||||
}),
|
}),
|
||||||
getYConfigHelp: () =>
|
getDecorationsHelp: () =>
|
||||||
i18n.translate('expressionXY.dataLayer.yConfig.help', {
|
i18n.translate('expressionXY.dataLayer.decorations.help', {
|
||||||
defaultMessage: 'Additional configuration for y axes',
|
defaultMessage: 'Additional decoration for data',
|
||||||
}),
|
}),
|
||||||
getColumnToLabelHelp: () =>
|
getColumnToLabelHelp: () =>
|
||||||
i18n.translate('expressionXY.layer.columnToLabel.help', {
|
i18n.translate('expressionXY.layer.columnToLabel.help', {
|
||||||
|
@ -237,30 +209,26 @@ export const strings = {
|
||||||
i18n.translate('expressionXY.referenceLineLayer.accessors.help', {
|
i18n.translate('expressionXY.referenceLineLayer.accessors.help', {
|
||||||
defaultMessage: 'The columns to display on the y axis.',
|
defaultMessage: 'The columns to display on the y axis.',
|
||||||
}),
|
}),
|
||||||
getRLYConfigHelp: () =>
|
getRLDecorationConfigHelp: () =>
|
||||||
i18n.translate('expressionXY.referenceLineLayer.yConfig.help', {
|
i18n.translate('expressionXY.referenceLineLayer.decorationConfig.help', {
|
||||||
defaultMessage: 'Additional configuration for y axes',
|
defaultMessage: 'Additional decoration for reference line',
|
||||||
}),
|
}),
|
||||||
getRLHelp: () =>
|
getRLHelp: () =>
|
||||||
i18n.translate('expressionXY.referenceLineLayer.help', {
|
i18n.translate('expressionXY.referenceLineLayer.help', {
|
||||||
defaultMessage: `Configure a reference line in the xy chart`,
|
defaultMessage: `Configure a reference line in the xy chart`,
|
||||||
}),
|
}),
|
||||||
getYConfigFnHelp: () =>
|
|
||||||
i18n.translate('expressionXY.yConfig.help', {
|
|
||||||
defaultMessage: `Configure the behavior of a xy chart's y axis metric`,
|
|
||||||
}),
|
|
||||||
getForAccessorHelp: () =>
|
getForAccessorHelp: () =>
|
||||||
i18n.translate('expressionXY.yConfig.forAccessor.help', {
|
i18n.translate('expressionXY.decorationConfig.forAccessor.help', {
|
||||||
defaultMessage: 'The accessor this configuration is for',
|
defaultMessage: 'The accessor this configuration is for',
|
||||||
}),
|
}),
|
||||||
getAxisModeHelp: () =>
|
|
||||||
i18n.translate('expressionXY.yConfig.axisMode.help', {
|
|
||||||
defaultMessage: 'The axis mode of the metric',
|
|
||||||
}),
|
|
||||||
getColorHelp: () =>
|
getColorHelp: () =>
|
||||||
i18n.translate('expressionXY.yConfig.color.help', {
|
i18n.translate('expressionXY.decorationConfig.color.help', {
|
||||||
defaultMessage: 'The color of the series',
|
defaultMessage: 'The color of the series',
|
||||||
}),
|
}),
|
||||||
|
getAxisIdHelp: () =>
|
||||||
|
i18n.translate('expressionXY.decorationConfig.axisId.help', {
|
||||||
|
defaultMessage: 'Id of axis',
|
||||||
|
}),
|
||||||
getAnnotationLayerFnHelp: () =>
|
getAnnotationLayerFnHelp: () =>
|
||||||
i18n.translate('expressionXY.annotationLayer.help', {
|
i18n.translate('expressionXY.annotationLayer.help', {
|
||||||
defaultMessage: `Configure an annotation layer in the xy chart`,
|
defaultMessage: `Configure an annotation layer in the xy chart`,
|
||||||
|
@ -273,6 +241,74 @@ export const strings = {
|
||||||
i18n.translate('expressionXY.annotationLayer.annotations.help', {
|
i18n.translate('expressionXY.annotationLayer.annotations.help', {
|
||||||
defaultMessage: 'Annotations',
|
defaultMessage: 'Annotations',
|
||||||
}),
|
}),
|
||||||
|
getXAxisConfigFnHelp: () =>
|
||||||
|
i18n.translate('expressionXY.xAxisConfigFn.help', {
|
||||||
|
defaultMessage: `Configure the xy chart's x-axis config`,
|
||||||
|
}),
|
||||||
|
getYAxisConfigFnHelp: () =>
|
||||||
|
i18n.translate('expressionXY.yAxisConfigFn.help', {
|
||||||
|
defaultMessage: `Configure the xy chart's y-axis config`,
|
||||||
|
}),
|
||||||
|
getAxisModeHelp: () =>
|
||||||
|
i18n.translate('expressionXY.axisConfig.mode.help', {
|
||||||
|
defaultMessage: 'Scale mode. Can be normal, percentage, wiggle or silhouette',
|
||||||
|
}),
|
||||||
|
getAxisBoundsMarginHelp: () =>
|
||||||
|
i18n.translate('expressionXY.axisConfig.boundsMargin.help', {
|
||||||
|
defaultMessage: 'Margin of bounds',
|
||||||
|
}),
|
||||||
|
getAxisExtentHelp: () =>
|
||||||
|
i18n.translate('expressionXY.axisConfig.extent.help', {
|
||||||
|
defaultMessage: 'Axis extents',
|
||||||
|
}),
|
||||||
|
getAxisScaleTypeHelp: () =>
|
||||||
|
i18n.translate('expressionXY.axisConfig.scaleType.help', {
|
||||||
|
defaultMessage: 'The scale type of the axis',
|
||||||
|
}),
|
||||||
|
getAxisTitleHelp: () =>
|
||||||
|
i18n.translate('expressionXY.axisConfig.title.help', {
|
||||||
|
defaultMessage: 'Title of axis',
|
||||||
|
}),
|
||||||
|
getAxisPositionHelp: () =>
|
||||||
|
i18n.translate('expressionXY.axisConfig.position.help', {
|
||||||
|
defaultMessage: 'Position of axis',
|
||||||
|
}),
|
||||||
|
getAxisHideHelp: () =>
|
||||||
|
i18n.translate('expressionXY.axisConfig.hide.help', {
|
||||||
|
defaultMessage: 'Hide the axis',
|
||||||
|
}),
|
||||||
|
getAxisLabelColorHelp: () =>
|
||||||
|
i18n.translate('expressionXY.axisConfig.labelColor.help', {
|
||||||
|
defaultMessage: 'Color of the axis labels',
|
||||||
|
}),
|
||||||
|
getAxisShowOverlappingLabelsHelp: () =>
|
||||||
|
i18n.translate('expressionXY.axisConfig.showOverlappingLabels.help', {
|
||||||
|
defaultMessage: 'Show overlapping labels',
|
||||||
|
}),
|
||||||
|
getAxisShowDuplicatesHelp: () =>
|
||||||
|
i18n.translate('expressionXY.axisConfig.showDuplicates.help', {
|
||||||
|
defaultMessage: 'Show duplicated ticks',
|
||||||
|
}),
|
||||||
|
getAxisShowGridLinesHelp: () =>
|
||||||
|
i18n.translate('expressionXY.axisConfig.showGridLines.help', {
|
||||||
|
defaultMessage: 'Specifies whether or not the gridlines of the axis are visible',
|
||||||
|
}),
|
||||||
|
getAxisLabelsOrientationHelp: () =>
|
||||||
|
i18n.translate('expressionXY.axisConfig.labelsOrientation.help', {
|
||||||
|
defaultMessage: 'Specifies the labels orientation of the axis',
|
||||||
|
}),
|
||||||
|
getAxisShowLabelsHelp: () =>
|
||||||
|
i18n.translate('expressionXY.axisConfig.showLabels.help', {
|
||||||
|
defaultMessage: 'Show labels',
|
||||||
|
}),
|
||||||
|
getAxisShowTitleHelp: () =>
|
||||||
|
i18n.translate('expressionXY.axisConfig.showTitle.help', {
|
||||||
|
defaultMessage: 'Show title of the axis',
|
||||||
|
}),
|
||||||
|
getAxisTruncateHelp: () =>
|
||||||
|
i18n.translate('expressionXY.axisConfig.truncate.help', {
|
||||||
|
defaultMessage: 'The number of symbols before truncating',
|
||||||
|
}),
|
||||||
getReferenceLineNameHelp: () =>
|
getReferenceLineNameHelp: () =>
|
||||||
i18n.translate('expressionXY.referenceLine.name.help', {
|
i18n.translate('expressionXY.referenceLine.name.help', {
|
||||||
defaultMessage: 'Reference line name',
|
defaultMessage: 'Reference line name',
|
||||||
|
|
|
@ -11,17 +11,17 @@ export const PLUGIN_NAME = 'expressionXy';
|
||||||
|
|
||||||
export type {
|
export type {
|
||||||
XYArgs,
|
XYArgs,
|
||||||
YConfig,
|
|
||||||
EndValue,
|
EndValue,
|
||||||
XYRender,
|
XYRender,
|
||||||
LayerType,
|
LayerType,
|
||||||
YAxisMode,
|
|
||||||
LineStyle,
|
LineStyle,
|
||||||
FillStyle,
|
FillStyle,
|
||||||
SeriesType,
|
SeriesType,
|
||||||
YScaleType,
|
YScaleType,
|
||||||
XScaleType,
|
XScaleType,
|
||||||
|
AxisMode,
|
||||||
AxisConfig,
|
AxisConfig,
|
||||||
|
YAxisConfig,
|
||||||
ValidLayer,
|
ValidLayer,
|
||||||
XYLayerArgs,
|
XYLayerArgs,
|
||||||
XYCurveType,
|
XYCurveType,
|
||||||
|
@ -33,30 +33,28 @@ export type {
|
||||||
AxisExtentMode,
|
AxisExtentMode,
|
||||||
DataLayerConfig,
|
DataLayerConfig,
|
||||||
FittingFunction,
|
FittingFunction,
|
||||||
ExtendedYConfig,
|
|
||||||
AxisExtentConfig,
|
AxisExtentConfig,
|
||||||
CollectiveConfig,
|
CollectiveConfig,
|
||||||
LegendConfigResult,
|
LegendConfigResult,
|
||||||
AxesSettingsConfig,
|
AxesSettingsConfig,
|
||||||
|
XAxisConfigResult,
|
||||||
|
YAxisConfigResult,
|
||||||
CommonXYLayerConfig,
|
CommonXYLayerConfig,
|
||||||
|
DataDecorationConfig,
|
||||||
AnnotationLayerArgs,
|
AnnotationLayerArgs,
|
||||||
ExtendedYConfigResult,
|
|
||||||
GridlinesConfigResult,
|
|
||||||
DataLayerConfigResult,
|
DataLayerConfigResult,
|
||||||
TickLabelsConfigResult,
|
|
||||||
AxisExtentConfigResult,
|
AxisExtentConfigResult,
|
||||||
ReferenceLineLayerArgs,
|
ReferenceLineLayerArgs,
|
||||||
CommonXYDataLayerConfig,
|
CommonXYDataLayerConfig,
|
||||||
LabelsOrientationConfig,
|
|
||||||
ReferenceLineLayerConfig,
|
ReferenceLineLayerConfig,
|
||||||
AvailableReferenceLineIcon,
|
AvailableReferenceLineIcon,
|
||||||
XYExtendedLayerConfigResult,
|
XYExtendedLayerConfigResult,
|
||||||
CommonXYAnnotationLayerConfig,
|
CommonXYAnnotationLayerConfig,
|
||||||
ExtendedDataLayerConfigResult,
|
ExtendedDataLayerConfigResult,
|
||||||
LabelsOrientationConfigResult,
|
|
||||||
CommonXYDataLayerConfigResult,
|
CommonXYDataLayerConfigResult,
|
||||||
ReferenceLineLayerConfigResult,
|
ReferenceLineLayerConfigResult,
|
||||||
|
ReferenceLineDecorationConfig,
|
||||||
CommonXYReferenceLineLayerConfig,
|
CommonXYReferenceLineLayerConfig,
|
||||||
AxisTitlesVisibilityConfigResult,
|
ReferenceLineDecorationConfigResult,
|
||||||
CommonXYReferenceLineLayerConfigResult,
|
CommonXYReferenceLineLayerConfigResult,
|
||||||
} from './types';
|
} from './types';
|
||||||
|
|
|
@ -25,14 +25,11 @@ import {
|
||||||
ValueLabelModes,
|
ValueLabelModes,
|
||||||
XScaleTypes,
|
XScaleTypes,
|
||||||
XYCurveTypes,
|
XYCurveTypes,
|
||||||
YAxisModes,
|
|
||||||
YScaleTypes,
|
YScaleTypes,
|
||||||
|
AxisModes,
|
||||||
REFERENCE_LINE,
|
REFERENCE_LINE,
|
||||||
Y_CONFIG,
|
DATA_DECORATION_CONFIG,
|
||||||
AXIS_TITLES_VISIBILITY_CONFIG,
|
REFERENCE_LINE_DECORATION_CONFIG,
|
||||||
LABELS_ORIENTATION_CONFIG,
|
|
||||||
TICK_LABELS_CONFIG,
|
|
||||||
GRID_LINES_CONFIG,
|
|
||||||
LEGEND_CONFIG,
|
LEGEND_CONFIG,
|
||||||
DATA_LAYER,
|
DATA_LAYER,
|
||||||
AXIS_EXTENT_CONFIG,
|
AXIS_EXTENT_CONFIG,
|
||||||
|
@ -40,23 +37,24 @@ import {
|
||||||
REFERENCE_LINE_LAYER,
|
REFERENCE_LINE_LAYER,
|
||||||
ANNOTATION_LAYER,
|
ANNOTATION_LAYER,
|
||||||
EndValues,
|
EndValues,
|
||||||
EXTENDED_Y_CONFIG,
|
X_AXIS_CONFIG,
|
||||||
|
Y_AXIS_CONFIG,
|
||||||
AvailableReferenceLineIcons,
|
AvailableReferenceLineIcons,
|
||||||
XY_VIS,
|
XY_VIS,
|
||||||
LAYERED_XY_VIS,
|
LAYERED_XY_VIS,
|
||||||
EXTENDED_ANNOTATION_LAYER,
|
EXTENDED_ANNOTATION_LAYER,
|
||||||
REFERENCE_LINE_Y_CONFIG,
|
EXTENDED_REFERENCE_LINE_DECORATION_CONFIG,
|
||||||
} from '../constants';
|
} from '../constants';
|
||||||
import { XYRender } from './expression_renderers';
|
import { XYRender } from './expression_renderers';
|
||||||
|
|
||||||
export type EndValue = $Values<typeof EndValues>;
|
export type EndValue = $Values<typeof EndValues>;
|
||||||
export type LayerType = $Values<typeof LayerTypes>;
|
export type LayerType = $Values<typeof LayerTypes>;
|
||||||
export type YAxisMode = $Values<typeof YAxisModes>;
|
|
||||||
export type LineStyle = $Values<typeof LineStyles>;
|
export type LineStyle = $Values<typeof LineStyles>;
|
||||||
export type FillStyle = $Values<typeof FillStyles>;
|
export type FillStyle = $Values<typeof FillStyles>;
|
||||||
export type SeriesType = $Values<typeof SeriesTypes>;
|
export type SeriesType = $Values<typeof SeriesTypes>;
|
||||||
export type YScaleType = $Values<typeof YScaleTypes>;
|
export type YScaleType = $Values<typeof YScaleTypes>;
|
||||||
export type XScaleType = $Values<typeof XScaleTypes>;
|
export type XScaleType = $Values<typeof XScaleTypes>;
|
||||||
|
export type AxisMode = $Values<typeof AxisModes>;
|
||||||
export type XYCurveType = $Values<typeof XYCurveTypes>;
|
export type XYCurveType = $Values<typeof XYCurveTypes>;
|
||||||
export type IconPosition = $Values<typeof IconPositions>;
|
export type IconPosition = $Values<typeof IconPositions>;
|
||||||
export type ValueLabelMode = $Values<typeof ValueLabelModes>;
|
export type ValueLabelMode = $Values<typeof ValueLabelModes>;
|
||||||
|
@ -65,7 +63,6 @@ export type FittingFunction = $Values<typeof FittingFunctions>;
|
||||||
export type AvailableReferenceLineIcon = $Values<typeof AvailableReferenceLineIcons>;
|
export type AvailableReferenceLineIcon = $Values<typeof AvailableReferenceLineIcons>;
|
||||||
|
|
||||||
export interface AxesSettingsConfig {
|
export interface AxesSettingsConfig {
|
||||||
x: boolean;
|
|
||||||
yLeft: boolean;
|
yLeft: boolean;
|
||||||
yRight: boolean;
|
yRight: boolean;
|
||||||
}
|
}
|
||||||
|
@ -77,23 +74,41 @@ export interface AxisExtentConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AxisConfig {
|
export interface AxisConfig {
|
||||||
title: string;
|
title?: string;
|
||||||
hide?: boolean;
|
hide?: boolean;
|
||||||
|
id?: string;
|
||||||
|
position?: Position;
|
||||||
|
labelColor?: string;
|
||||||
|
showOverlappingLabels?: boolean;
|
||||||
|
showDuplicates?: boolean;
|
||||||
|
labelsOrientation?: number;
|
||||||
|
truncate?: number;
|
||||||
|
showLabels?: boolean;
|
||||||
|
showTitle?: boolean;
|
||||||
|
showGridLines?: boolean;
|
||||||
|
extent?: AxisExtentConfigResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ExtendedYConfig extends YConfig {
|
export interface YAxisConfig extends AxisConfig {
|
||||||
|
mode?: AxisMode;
|
||||||
|
boundsMargin?: number;
|
||||||
|
scaleType?: YScaleType;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ReferenceLineDecorationConfig extends DataDecorationConfig {
|
||||||
icon?: AvailableReferenceLineIcon;
|
icon?: AvailableReferenceLineIcon;
|
||||||
lineWidth?: number;
|
lineWidth?: number;
|
||||||
lineStyle?: LineStyle;
|
lineStyle?: LineStyle;
|
||||||
fill?: FillStyle;
|
fill?: FillStyle;
|
||||||
iconPosition?: IconPosition;
|
iconPosition?: IconPosition;
|
||||||
textVisibility?: boolean;
|
textVisibility?: boolean;
|
||||||
|
position?: Position;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface YConfig {
|
export interface DataDecorationConfig {
|
||||||
forAccessor: string;
|
forAccessor: string;
|
||||||
axisMode?: YAxisMode;
|
|
||||||
color?: string;
|
color?: string;
|
||||||
|
axisId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DataLayerArgs {
|
export interface DataLayerArgs {
|
||||||
|
@ -110,8 +125,11 @@ export interface DataLayerArgs {
|
||||||
columnToLabel?: string; // Actually a JSON key-value pair
|
columnToLabel?: string; // Actually a JSON key-value pair
|
||||||
xScaleType: XScaleType;
|
xScaleType: XScaleType;
|
||||||
isHistogram: boolean;
|
isHistogram: boolean;
|
||||||
|
isPercentage: boolean;
|
||||||
|
isStacked: boolean;
|
||||||
|
isHorizontal: boolean;
|
||||||
palette: PaletteOutput;
|
palette: PaletteOutput;
|
||||||
yConfig?: YConfigResult[];
|
decorations?: DataDecorationConfigResult[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ValidLayer extends DataLayerConfigResult {
|
export interface ValidLayer extends DataLayerConfigResult {
|
||||||
|
@ -133,9 +151,12 @@ export interface ExtendedDataLayerArgs {
|
||||||
columnToLabel?: string; // Actually a JSON key-value pair
|
columnToLabel?: string; // Actually a JSON key-value pair
|
||||||
xScaleType: XScaleType;
|
xScaleType: XScaleType;
|
||||||
isHistogram: boolean;
|
isHistogram: boolean;
|
||||||
|
isPercentage: boolean;
|
||||||
|
isStacked: boolean;
|
||||||
|
isHorizontal: boolean;
|
||||||
palette: PaletteOutput;
|
palette: PaletteOutput;
|
||||||
// palette will always be set on the expression
|
// palette will always be set on the expression
|
||||||
yConfig?: YConfigResult[];
|
decorations?: DataDecorationConfigResult[];
|
||||||
table?: Datatable;
|
table?: Datatable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,22 +206,8 @@ export interface LegendConfig {
|
||||||
legendSize?: LegendSize;
|
legendSize?: LegendSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LabelsOrientationConfig {
|
|
||||||
x: number;
|
|
||||||
yLeft: number;
|
|
||||||
yRight: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Arguments to XY chart expression, with computed properties
|
// Arguments to XY chart expression, with computed properties
|
||||||
export interface XYArgs extends DataLayerArgs {
|
export interface XYArgs extends DataLayerArgs {
|
||||||
xTitle: string;
|
|
||||||
yTitle: string;
|
|
||||||
yRightTitle: string;
|
|
||||||
xExtent?: AxisExtentConfigResult;
|
|
||||||
yLeftExtent: AxisExtentConfigResult;
|
|
||||||
yRightExtent: AxisExtentConfigResult;
|
|
||||||
yLeftScale: YScaleType;
|
|
||||||
yRightScale: YScaleType;
|
|
||||||
legend: LegendConfigResult;
|
legend: LegendConfigResult;
|
||||||
endValue?: EndValue;
|
endValue?: EndValue;
|
||||||
emphasizeFitting?: boolean;
|
emphasizeFitting?: boolean;
|
||||||
|
@ -208,15 +215,13 @@ export interface XYArgs extends DataLayerArgs {
|
||||||
referenceLines: ReferenceLineConfigResult[];
|
referenceLines: ReferenceLineConfigResult[];
|
||||||
annotationLayers: AnnotationLayerConfigResult[];
|
annotationLayers: AnnotationLayerConfigResult[];
|
||||||
fittingFunction?: FittingFunction;
|
fittingFunction?: FittingFunction;
|
||||||
axisTitlesVisibilitySettings?: AxisTitlesVisibilityConfigResult;
|
|
||||||
tickLabelsVisibilitySettings?: TickLabelsConfigResult;
|
|
||||||
gridlinesVisibilitySettings?: GridlinesConfigResult;
|
|
||||||
labelsOrientation?: LabelsOrientationConfigResult;
|
|
||||||
curveType?: XYCurveType;
|
curveType?: XYCurveType;
|
||||||
fillOpacity?: number;
|
fillOpacity?: number;
|
||||||
hideEndzones?: boolean;
|
hideEndzones?: boolean;
|
||||||
valuesInLegend?: boolean;
|
valuesInLegend?: boolean;
|
||||||
ariaLabel?: string;
|
ariaLabel?: string;
|
||||||
|
yAxisConfigs?: YAxisConfigResult[];
|
||||||
|
xAxisConfig?: XAxisConfigResult;
|
||||||
addTimeMarker?: boolean;
|
addTimeMarker?: boolean;
|
||||||
markSizeRatio?: number;
|
markSizeRatio?: number;
|
||||||
minTimeBarInterval?: string;
|
minTimeBarInterval?: string;
|
||||||
|
@ -228,29 +233,19 @@ export interface XYArgs extends DataLayerArgs {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LayeredXYArgs {
|
export interface LayeredXYArgs {
|
||||||
xTitle: string;
|
|
||||||
yTitle: string;
|
|
||||||
yRightTitle: string;
|
|
||||||
xExtent?: AxisExtentConfigResult;
|
|
||||||
yLeftExtent: AxisExtentConfigResult;
|
|
||||||
yRightExtent: AxisExtentConfigResult;
|
|
||||||
yLeftScale: YScaleType;
|
|
||||||
yRightScale: YScaleType;
|
|
||||||
legend: LegendConfigResult;
|
legend: LegendConfigResult;
|
||||||
endValue?: EndValue;
|
endValue?: EndValue;
|
||||||
emphasizeFitting?: boolean;
|
emphasizeFitting?: boolean;
|
||||||
valueLabels: ValueLabelMode;
|
valueLabels: ValueLabelMode;
|
||||||
layers?: XYExtendedLayerConfigResult[];
|
layers?: XYExtendedLayerConfigResult[];
|
||||||
fittingFunction?: FittingFunction;
|
fittingFunction?: FittingFunction;
|
||||||
axisTitlesVisibilitySettings?: AxisTitlesVisibilityConfigResult;
|
|
||||||
tickLabelsVisibilitySettings?: TickLabelsConfigResult;
|
|
||||||
gridlinesVisibilitySettings?: GridlinesConfigResult;
|
|
||||||
labelsOrientation?: LabelsOrientationConfigResult;
|
|
||||||
curveType?: XYCurveType;
|
curveType?: XYCurveType;
|
||||||
fillOpacity?: number;
|
fillOpacity?: number;
|
||||||
hideEndzones?: boolean;
|
hideEndzones?: boolean;
|
||||||
valuesInLegend?: boolean;
|
valuesInLegend?: boolean;
|
||||||
ariaLabel?: string;
|
ariaLabel?: string;
|
||||||
|
yAxisConfigs?: YAxisConfigResult[];
|
||||||
|
xAxisConfig?: XAxisConfigResult;
|
||||||
detailedTooltip?: boolean;
|
detailedTooltip?: boolean;
|
||||||
addTimeMarker?: boolean;
|
addTimeMarker?: boolean;
|
||||||
markSizeRatio?: number;
|
markSizeRatio?: number;
|
||||||
|
@ -260,29 +255,19 @@ export interface LayeredXYArgs {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface XYProps {
|
export interface XYProps {
|
||||||
xTitle: string;
|
|
||||||
yTitle: string;
|
|
||||||
yRightTitle: string;
|
|
||||||
xExtent?: AxisExtentConfigResult;
|
|
||||||
yLeftExtent: AxisExtentConfigResult;
|
|
||||||
yRightExtent: AxisExtentConfigResult;
|
|
||||||
yLeftScale: YScaleType;
|
|
||||||
yRightScale: YScaleType;
|
|
||||||
legend: LegendConfigResult;
|
legend: LegendConfigResult;
|
||||||
endValue?: EndValue;
|
endValue?: EndValue;
|
||||||
emphasizeFitting?: boolean;
|
emphasizeFitting?: boolean;
|
||||||
valueLabels: ValueLabelMode;
|
valueLabels: ValueLabelMode;
|
||||||
layers: CommonXYLayerConfig[];
|
layers: CommonXYLayerConfig[];
|
||||||
fittingFunction?: FittingFunction;
|
fittingFunction?: FittingFunction;
|
||||||
axisTitlesVisibilitySettings?: AxisTitlesVisibilityConfigResult;
|
|
||||||
tickLabelsVisibilitySettings?: TickLabelsConfigResult;
|
|
||||||
gridlinesVisibilitySettings?: GridlinesConfigResult;
|
|
||||||
labelsOrientation?: LabelsOrientationConfigResult;
|
|
||||||
curveType?: XYCurveType;
|
curveType?: XYCurveType;
|
||||||
fillOpacity?: number;
|
fillOpacity?: number;
|
||||||
hideEndzones?: boolean;
|
hideEndzones?: boolean;
|
||||||
valuesInLegend?: boolean;
|
valuesInLegend?: boolean;
|
||||||
ariaLabel?: string;
|
ariaLabel?: string;
|
||||||
|
yAxisConfigs?: YAxisConfigResult[];
|
||||||
|
xAxisConfig?: XAxisConfigResult;
|
||||||
addTimeMarker?: boolean;
|
addTimeMarker?: boolean;
|
||||||
markSizeRatio?: number;
|
markSizeRatio?: number;
|
||||||
minTimeBarInterval?: string;
|
minTimeBarInterval?: string;
|
||||||
|
@ -312,7 +297,8 @@ export type ExtendedAnnotationLayerConfigResult = ExtendedAnnotationLayerArgs &
|
||||||
layerType: typeof LayerTypes.ANNOTATIONS;
|
layerType: typeof LayerTypes.ANNOTATIONS;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface ReferenceLineArgs extends Omit<ExtendedYConfig, 'forAccessor' | 'fill'> {
|
export interface ReferenceLineArgs
|
||||||
|
extends Omit<ReferenceLineDecorationConfig, 'forAccessor' | 'fill'> {
|
||||||
name?: string;
|
name?: string;
|
||||||
value: number;
|
value: number;
|
||||||
fill: FillStyle;
|
fill: FillStyle;
|
||||||
|
@ -322,7 +308,7 @@ export interface ReferenceLineLayerArgs {
|
||||||
layerId?: string;
|
layerId?: string;
|
||||||
accessors: string[];
|
accessors: string[];
|
||||||
columnToLabel?: string;
|
columnToLabel?: string;
|
||||||
yConfig?: ExtendedYConfigResult[];
|
decorations?: ReferenceLineDecorationConfigResult[];
|
||||||
table?: Datatable;
|
table?: Datatable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,15 +324,15 @@ export type XYExtendedLayerConfigResult =
|
||||||
| ReferenceLineLayerConfigResult
|
| ReferenceLineLayerConfigResult
|
||||||
| ExtendedAnnotationLayerConfigResult;
|
| ExtendedAnnotationLayerConfigResult;
|
||||||
|
|
||||||
export interface ReferenceLineYConfig extends ReferenceLineArgs {
|
export interface ExtendedReferenceLineDecorationConfig extends ReferenceLineArgs {
|
||||||
type: typeof REFERENCE_LINE_Y_CONFIG;
|
type: typeof EXTENDED_REFERENCE_LINE_DECORATION_CONFIG;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ReferenceLineConfigResult {
|
export interface ReferenceLineConfigResult {
|
||||||
type: typeof REFERENCE_LINE;
|
type: typeof REFERENCE_LINE;
|
||||||
layerType: typeof LayerTypes.REFERENCELINE;
|
layerType: typeof LayerTypes.REFERENCELINE;
|
||||||
lineLength: number;
|
lineLength: number;
|
||||||
yConfig: [ReferenceLineYConfig];
|
decorations: [ExtendedReferenceLineDecorationConfig];
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ReferenceLineLayerConfigResult = ReferenceLineLayerArgs & {
|
export type ReferenceLineLayerConfigResult = ReferenceLineLayerArgs & {
|
||||||
|
@ -381,21 +367,18 @@ export type ExtendedDataLayerConfigResult = Omit<ExtendedDataLayerArgs, 'palette
|
||||||
table: Datatable;
|
table: Datatable;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type YConfigResult = YConfig & { type: typeof Y_CONFIG };
|
export type DataDecorationConfigResult = DataDecorationConfig & {
|
||||||
export type ExtendedYConfigResult = ExtendedYConfig & { type: typeof EXTENDED_Y_CONFIG };
|
type: typeof DATA_DECORATION_CONFIG;
|
||||||
|
};
|
||||||
export type AxisTitlesVisibilityConfigResult = AxesSettingsConfig & {
|
export type ReferenceLineDecorationConfigResult = ReferenceLineDecorationConfig & {
|
||||||
type: typeof AXIS_TITLES_VISIBILITY_CONFIG;
|
type: typeof REFERENCE_LINE_DECORATION_CONFIG;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type LabelsOrientationConfigResult = LabelsOrientationConfig & {
|
export type XAxisConfigResult = AxisConfig & { type: typeof X_AXIS_CONFIG };
|
||||||
type: typeof LABELS_ORIENTATION_CONFIG;
|
export type YAxisConfigResult = YAxisConfig & { type: typeof Y_AXIS_CONFIG };
|
||||||
};
|
|
||||||
|
|
||||||
export type LegendConfigResult = LegendConfig & { type: typeof LEGEND_CONFIG };
|
export type LegendConfigResult = LegendConfig & { type: typeof LEGEND_CONFIG };
|
||||||
export type AxisExtentConfigResult = AxisExtentConfig & { type: typeof AXIS_EXTENT_CONFIG };
|
export type AxisExtentConfigResult = AxisExtentConfig & { type: typeof AXIS_EXTENT_CONFIG };
|
||||||
export type GridlinesConfigResult = AxesSettingsConfig & { type: typeof GRID_LINES_CONFIG };
|
|
||||||
export type TickLabelsConfigResult = AxesSettingsConfig & { type: typeof TICK_LABELS_CONFIG };
|
|
||||||
|
|
||||||
export type CommonXYLayerConfig = XYLayerConfig | XYExtendedLayerConfig;
|
export type CommonXYLayerConfig = XYLayerConfig | XYExtendedLayerConfig;
|
||||||
export type CommonXYDataLayerConfigResult = DataLayerConfigResult | ExtendedDataLayerConfigResult;
|
export type CommonXYDataLayerConfigResult = DataLayerConfigResult | ExtendedDataLayerConfigResult;
|
||||||
|
@ -441,12 +424,17 @@ export type ReferenceLineLayerFn = ExpressionFunctionDefinition<
|
||||||
Promise<ReferenceLineLayerConfigResult>
|
Promise<ReferenceLineLayerConfigResult>
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export type YConfigFn = ExpressionFunctionDefinition<typeof Y_CONFIG, null, YConfig, YConfigResult>;
|
export type DataDecorationConfigFn = ExpressionFunctionDefinition<
|
||||||
export type ExtendedYConfigFn = ExpressionFunctionDefinition<
|
typeof DATA_DECORATION_CONFIG,
|
||||||
typeof EXTENDED_Y_CONFIG,
|
|
||||||
null,
|
null,
|
||||||
ExtendedYConfig,
|
DataDecorationConfig,
|
||||||
ExtendedYConfigResult
|
DataDecorationConfigResult
|
||||||
|
>;
|
||||||
|
export type ReferenceLineDecorationConfigFn = ExpressionFunctionDefinition<
|
||||||
|
typeof REFERENCE_LINE_DECORATION_CONFIG,
|
||||||
|
null,
|
||||||
|
ReferenceLineDecorationConfig,
|
||||||
|
ReferenceLineDecorationConfigResult
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export type LegendConfigFn = ExpressionFunctionDefinition<
|
export type LegendConfigFn = ExpressionFunctionDefinition<
|
||||||
|
@ -455,3 +443,17 @@ export type LegendConfigFn = ExpressionFunctionDefinition<
|
||||||
LegendConfig,
|
LegendConfig,
|
||||||
Promise<LegendConfigResult>
|
Promise<LegendConfigResult>
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
export type XAxisConfigFn = ExpressionFunctionDefinition<
|
||||||
|
typeof X_AXIS_CONFIG,
|
||||||
|
null,
|
||||||
|
AxisConfig,
|
||||||
|
XAxisConfigResult
|
||||||
|
>;
|
||||||
|
|
||||||
|
export type YAxisConfigFn = ExpressionFunctionDefinition<
|
||||||
|
typeof Y_AXIS_CONFIG,
|
||||||
|
null,
|
||||||
|
YAxisConfig,
|
||||||
|
YAxisConfigResult
|
||||||
|
>;
|
||||||
|
|
|
@ -26,7 +26,7 @@ export interface XYRender {
|
||||||
|
|
||||||
export interface CollectiveConfig extends Omit<ManualPointEventAnnotationArgs, 'icon'> {
|
export interface CollectiveConfig extends Omit<ManualPointEventAnnotationArgs, 'icon'> {
|
||||||
roundedTimestamp: number;
|
roundedTimestamp: number;
|
||||||
axisMode: 'bottom';
|
position: 'bottom';
|
||||||
icon?: AvailableAnnotationIcon | string;
|
icon?: AvailableAnnotationIcon | string;
|
||||||
customTooltipDetails?: AnnotationTooltipFormatter | undefined;
|
customTooltipDetails?: AnnotationTooltipFormatter | undefined;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
* Side Public License, v 1.
|
* Side Public License, v 1.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { Position } from '@elastic/charts';
|
||||||
import { Datatable } from '@kbn/expressions-plugin/common';
|
import { Datatable } from '@kbn/expressions-plugin/common';
|
||||||
import { chartPluginMock } from '@kbn/charts-plugin/public/mocks';
|
import { chartPluginMock } from '@kbn/charts-plugin/public/mocks';
|
||||||
import { LayerTypes } from '../../common/constants';
|
import { LayerTypes } from '../../common/constants';
|
||||||
|
@ -167,8 +168,11 @@ export const dateHistogramLayer: DataLayerConfig = {
|
||||||
xAccessor: 'xAccessorId',
|
xAccessor: 'xAccessorId',
|
||||||
xScaleType: 'time',
|
xScaleType: 'time',
|
||||||
isHistogram: true,
|
isHistogram: true,
|
||||||
|
isStacked: true,
|
||||||
|
isPercentage: false,
|
||||||
|
isHorizontal: false,
|
||||||
splitAccessor: 'splitAccessorId',
|
splitAccessor: 'splitAccessorId',
|
||||||
seriesType: 'bar_stacked',
|
seriesType: 'bar',
|
||||||
accessors: ['yAccessorId'],
|
accessors: ['yAccessorId'],
|
||||||
palette: mockPaletteOutput,
|
palette: mockPaletteOutput,
|
||||||
table: dateHistogramData,
|
table: dateHistogramData,
|
||||||
|
@ -197,7 +201,13 @@ export function sampleArgsWithReferenceLine(value: number = 150) {
|
||||||
type: 'referenceLineLayer',
|
type: 'referenceLineLayer',
|
||||||
layerType: LayerTypes.REFERENCELINE,
|
layerType: LayerTypes.REFERENCELINE,
|
||||||
accessors: ['referenceLine-a'],
|
accessors: ['referenceLine-a'],
|
||||||
yConfig: [{ axisMode: 'left', forAccessor: 'referenceLine-a', type: 'extendedYConfig' }],
|
decorations: [
|
||||||
|
{
|
||||||
|
forAccessor: 'referenceLine-a',
|
||||||
|
type: 'referenceLineDecorationConfig',
|
||||||
|
position: Position.Left,
|
||||||
|
},
|
||||||
|
],
|
||||||
table: data,
|
table: data,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -155,7 +155,7 @@ export const getAnnotationsGroupedByInterval = (
|
||||||
collectiveConfig = {
|
collectiveConfig = {
|
||||||
...configArr[0],
|
...configArr[0],
|
||||||
roundedTimestamp: Number(roundedTimestamp),
|
roundedTimestamp: Number(roundedTimestamp),
|
||||||
axisMode: 'bottom',
|
position: 'bottom',
|
||||||
};
|
};
|
||||||
if (configArr.length > 1) {
|
if (configArr.length > 1) {
|
||||||
const commonStyles = getCommonStyles(configArr);
|
const commonStyles = getCommonStyles(configArr);
|
||||||
|
|
|
@ -25,7 +25,7 @@ import {
|
||||||
XYCurveType,
|
XYCurveType,
|
||||||
XScaleType,
|
XScaleType,
|
||||||
} from '../../common';
|
} from '../../common';
|
||||||
import { SeriesTypes, ValueLabelModes } from '../../common/constants';
|
import { SeriesTypes, ValueLabelModes, AxisModes } from '../../common/constants';
|
||||||
import {
|
import {
|
||||||
getColorAssignments,
|
getColorAssignments,
|
||||||
getFitOptions,
|
getFitOptions,
|
||||||
|
@ -90,12 +90,14 @@ export const DataLayers: FC<Props> = ({
|
||||||
// In order to do it we need to make a copy of the table as the raw one is required for more features (filters, etc...) later on
|
// In order to do it we need to make a copy of the table as the raw one is required for more features (filters, etc...) later on
|
||||||
const formattedDatatableInfo = formattedDatatables[layerId];
|
const formattedDatatableInfo = formattedDatatables[layerId];
|
||||||
|
|
||||||
const isPercentage = seriesType.includes('percentage');
|
|
||||||
|
|
||||||
const yAxis = yAxesConfiguration.find((axisConfiguration) =>
|
const yAxis = yAxesConfiguration.find((axisConfiguration) =>
|
||||||
axisConfiguration.series.find((currentSeries) => currentSeries.accessor === yColumnId)
|
axisConfiguration.series.find((currentSeries) => currentSeries.accessor === yColumnId)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const isPercentage = yAxis?.mode
|
||||||
|
? yAxis?.mode === AxisModes.PERCENTAGE
|
||||||
|
: layer.isPercentage;
|
||||||
|
|
||||||
const seriesProps = getSeriesProps({
|
const seriesProps = getSeriesProps({
|
||||||
layer,
|
layer,
|
||||||
titles: titles[layer.layerId],
|
titles: titles[layer.layerId],
|
||||||
|
@ -129,11 +131,6 @@ export const DataLayers: FC<Props> = ({
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
case SeriesTypes.BAR:
|
case SeriesTypes.BAR:
|
||||||
case SeriesTypes.BAR_STACKED:
|
|
||||||
case SeriesTypes.BAR_PERCENTAGE_STACKED:
|
|
||||||
case SeriesTypes.BAR_HORIZONTAL:
|
|
||||||
case SeriesTypes.BAR_HORIZONTAL_STACKED:
|
|
||||||
case SeriesTypes.BAR_HORIZONTAL_PERCENTAGE_STACKED:
|
|
||||||
const valueLabelsSettings = {
|
const valueLabelsSettings = {
|
||||||
displayValueSettings: {
|
displayValueSettings: {
|
||||||
// This format double fixes two issues in elastic-chart
|
// This format double fixes two issues in elastic-chart
|
||||||
|
@ -150,22 +147,12 @@ export const DataLayers: FC<Props> = ({
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
return <BarSeries key={index} {...seriesProps} {...valueLabelsSettings} />;
|
return <BarSeries key={index} {...seriesProps} {...valueLabelsSettings} />;
|
||||||
case SeriesTypes.AREA_STACKED:
|
|
||||||
case SeriesTypes.AREA_PERCENTAGE_STACKED:
|
|
||||||
return (
|
|
||||||
<AreaSeries
|
|
||||||
key={index}
|
|
||||||
{...seriesProps}
|
|
||||||
fit={isPercentage ? 'zero' : getFitOptions(fittingFunction, endValue)}
|
|
||||||
curve={curve}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
case SeriesTypes.AREA:
|
case SeriesTypes.AREA:
|
||||||
return (
|
return (
|
||||||
<AreaSeries
|
<AreaSeries
|
||||||
key={index}
|
key={index}
|
||||||
{...seriesProps}
|
{...seriesProps}
|
||||||
fit={getFitOptions(fittingFunction, endValue)}
|
fit={isPercentage ? 'zero' : getFitOptions(fittingFunction, endValue)}
|
||||||
curve={curve}
|
curve={curve}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
|
@ -157,6 +157,9 @@ const sampleLayer: DataLayerConfig = {
|
||||||
type: 'dataLayer',
|
type: 'dataLayer',
|
||||||
layerType: LayerTypes.DATA,
|
layerType: LayerTypes.DATA,
|
||||||
seriesType: 'line',
|
seriesType: 'line',
|
||||||
|
isStacked: false,
|
||||||
|
isPercentage: false,
|
||||||
|
isHorizontal: false,
|
||||||
showLines: true,
|
showLines: true,
|
||||||
xAccessor: 'c',
|
xAccessor: 'c',
|
||||||
accessors: ['a', 'b'],
|
accessors: ['a', 'b'],
|
||||||
|
|
|
@ -10,47 +10,49 @@ import React, { FC } from 'react';
|
||||||
import { Position } from '@elastic/charts';
|
import { Position } from '@elastic/charts';
|
||||||
import { FieldFormat } from '@kbn/field-formats-plugin/common';
|
import { FieldFormat } from '@kbn/field-formats-plugin/common';
|
||||||
import { ReferenceLineConfig } from '../../../common/types';
|
import { ReferenceLineConfig } from '../../../common/types';
|
||||||
import { getGroupId } from './utils';
|
|
||||||
import { ReferenceLineAnnotations } from './reference_line_annotations';
|
import { ReferenceLineAnnotations } from './reference_line_annotations';
|
||||||
|
import { AxesMap, GroupsConfiguration } from '../../helpers';
|
||||||
|
import { getAxisGroupForReferenceLine } from './utils';
|
||||||
|
|
||||||
interface ReferenceLineProps {
|
interface ReferenceLineProps {
|
||||||
layer: ReferenceLineConfig;
|
layer: ReferenceLineConfig;
|
||||||
paddingMap: Partial<Record<Position, number>>;
|
paddingMap: Partial<Record<Position, number>>;
|
||||||
formatters: Record<'left' | 'right' | 'bottom', FieldFormat | undefined>;
|
xAxisFormatter: FieldFormat;
|
||||||
axesMap: Record<'left' | 'right', boolean>;
|
axesConfiguration: GroupsConfiguration;
|
||||||
isHorizontal: boolean;
|
isHorizontal: boolean;
|
||||||
nextValue?: number;
|
nextValue?: number;
|
||||||
|
yAxesMap: AxesMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ReferenceLine: FC<ReferenceLineProps> = ({
|
export const ReferenceLine: FC<ReferenceLineProps> = ({
|
||||||
layer,
|
layer,
|
||||||
axesMap,
|
axesConfiguration,
|
||||||
formatters,
|
xAxisFormatter,
|
||||||
paddingMap,
|
paddingMap,
|
||||||
isHorizontal,
|
isHorizontal,
|
||||||
nextValue,
|
nextValue,
|
||||||
|
yAxesMap,
|
||||||
}) => {
|
}) => {
|
||||||
const {
|
const {
|
||||||
yConfig: [yConfig],
|
decorations: [decorationConfig],
|
||||||
} = layer;
|
} = layer;
|
||||||
|
|
||||||
if (!yConfig) {
|
if (!decorationConfig) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { axisMode, value } = yConfig;
|
const { value } = decorationConfig;
|
||||||
|
|
||||||
// Find the formatter for the given axis
|
const axisGroup = getAxisGroupForReferenceLine(axesConfiguration, decorationConfig, isHorizontal);
|
||||||
const groupId = getGroupId(axisMode);
|
|
||||||
|
|
||||||
const formatter = formatters[groupId || 'bottom'];
|
const formatter = axisGroup?.formatter || xAxisFormatter;
|
||||||
const id = `${layer.layerId}-${value}`;
|
const id = `${layer.layerId}-${value}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ReferenceLineAnnotations
|
<ReferenceLineAnnotations
|
||||||
config={{ id, ...yConfig, nextValue }}
|
config={{ id, ...decorationConfig, nextValue, axisGroup }}
|
||||||
paddingMap={paddingMap}
|
paddingMap={paddingMap}
|
||||||
axesMap={axesMap}
|
axesMap={yAxesMap}
|
||||||
formatter={formatter}
|
formatter={formatter}
|
||||||
isHorizontal={isHorizontal}
|
isHorizontal={isHorizontal}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -10,18 +10,21 @@ import { AnnotationDomainType, LineAnnotation, Position, RectAnnotation } from '
|
||||||
import { euiLightVars } from '@kbn/ui-theme';
|
import { euiLightVars } from '@kbn/ui-theme';
|
||||||
import React, { FC } from 'react';
|
import React, { FC } from 'react';
|
||||||
import { FieldFormat } from '@kbn/field-formats-plugin/common';
|
import { FieldFormat } from '@kbn/field-formats-plugin/common';
|
||||||
import { LINES_MARKER_SIZE } from '../../helpers';
|
import {
|
||||||
|
AxesMap,
|
||||||
|
AxisConfiguration,
|
||||||
|
getOriginalAxisPosition,
|
||||||
|
LINES_MARKER_SIZE,
|
||||||
|
} from '../../helpers';
|
||||||
import {
|
import {
|
||||||
AvailableReferenceLineIcon,
|
AvailableReferenceLineIcon,
|
||||||
FillStyle,
|
FillStyle,
|
||||||
IconPosition,
|
IconPosition,
|
||||||
LineStyle,
|
LineStyle,
|
||||||
YAxisMode,
|
|
||||||
} from '../../../common/types';
|
} from '../../../common/types';
|
||||||
import {
|
import {
|
||||||
getBaseIconPlacement,
|
getBaseIconPlacement,
|
||||||
getBottomRect,
|
getBottomRect,
|
||||||
getGroupId,
|
|
||||||
getHorizontalRect,
|
getHorizontalRect,
|
||||||
getLineAnnotationProps,
|
getLineAnnotationProps,
|
||||||
getSharedStyle,
|
getSharedStyle,
|
||||||
|
@ -38,7 +41,7 @@ export interface ReferenceLineAnnotationConfig {
|
||||||
fill?: FillStyle;
|
fill?: FillStyle;
|
||||||
iconPosition?: IconPosition;
|
iconPosition?: IconPosition;
|
||||||
textVisibility?: boolean;
|
textVisibility?: boolean;
|
||||||
axisMode?: YAxisMode;
|
axisGroup?: AxisConfiguration;
|
||||||
color?: string;
|
color?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,18 +49,19 @@ interface Props {
|
||||||
config: ReferenceLineAnnotationConfig;
|
config: ReferenceLineAnnotationConfig;
|
||||||
paddingMap: Partial<Record<Position, number>>;
|
paddingMap: Partial<Record<Position, number>>;
|
||||||
formatter?: FieldFormat;
|
formatter?: FieldFormat;
|
||||||
axesMap: Record<'left' | 'right', boolean>;
|
axesMap: AxesMap;
|
||||||
isHorizontal: boolean;
|
isHorizontal: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const getRectDataValue = (
|
const getRectDataValue = (
|
||||||
annotationConfig: ReferenceLineAnnotationConfig,
|
annotationConfig: ReferenceLineAnnotationConfig,
|
||||||
formatter: FieldFormat | undefined
|
formatter: FieldFormat | undefined,
|
||||||
|
groupId: string
|
||||||
) => {
|
) => {
|
||||||
const { name, value, nextValue, fill, axisMode } = annotationConfig;
|
const { name, value, nextValue, fill } = annotationConfig;
|
||||||
const isFillAbove = fill === 'above';
|
const isFillAbove = fill === 'above';
|
||||||
|
|
||||||
if (axisMode === 'bottom') {
|
if (groupId === Position.Bottom) {
|
||||||
return getBottomRect(name, isFillAbove, formatter, value, nextValue);
|
return getBottomRect(name, isFillAbove, formatter, value, nextValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,13 +75,15 @@ export const ReferenceLineAnnotations: FC<Props> = ({
|
||||||
paddingMap,
|
paddingMap,
|
||||||
isHorizontal,
|
isHorizontal,
|
||||||
}) => {
|
}) => {
|
||||||
const { id, axisMode, iconPosition, name, textVisibility, value, fill, color } = config;
|
const { id, axisGroup, iconPosition, name, textVisibility, value, fill, color } = config;
|
||||||
|
|
||||||
// Find the formatter for the given axis
|
|
||||||
const groupId = getGroupId(axisMode);
|
|
||||||
const defaultColor = euiLightVars.euiColorDarkShade;
|
const defaultColor = euiLightVars.euiColorDarkShade;
|
||||||
// get the position for vertical chart
|
// get the position for vertical chart
|
||||||
const markerPositionVertical = getBaseIconPlacement(iconPosition, axesMap, axisMode);
|
const markerPositionVertical = getBaseIconPlacement(
|
||||||
|
iconPosition,
|
||||||
|
axesMap,
|
||||||
|
getOriginalAxisPosition(axisGroup?.position ?? Position.Bottom, isHorizontal)
|
||||||
|
);
|
||||||
// the padding map is built for vertical chart
|
// the padding map is built for vertical chart
|
||||||
const hasReducedPadding = paddingMap[markerPositionVertical] === LINES_MARKER_SIZE;
|
const hasReducedPadding = paddingMap[markerPositionVertical] === LINES_MARKER_SIZE;
|
||||||
|
|
||||||
|
@ -89,7 +95,6 @@ export const ReferenceLineAnnotations: FC<Props> = ({
|
||||||
},
|
},
|
||||||
axesMap,
|
axesMap,
|
||||||
paddingMap,
|
paddingMap,
|
||||||
groupId,
|
|
||||||
isHorizontal
|
isHorizontal
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -108,7 +113,9 @@ export const ReferenceLineAnnotations: FC<Props> = ({
|
||||||
key={`${id}-line`}
|
key={`${id}-line`}
|
||||||
dataValues={[dataValues]}
|
dataValues={[dataValues]}
|
||||||
domainType={
|
domainType={
|
||||||
axisMode === 'bottom' ? AnnotationDomainType.XDomain : AnnotationDomainType.YDomain
|
props.groupId === Position.Bottom
|
||||||
|
? AnnotationDomainType.XDomain
|
||||||
|
: AnnotationDomainType.YDomain
|
||||||
}
|
}
|
||||||
style={{ line: { ...sharedStyle, opacity: 1 } }}
|
style={{ line: { ...sharedStyle, opacity: 1 } }}
|
||||||
/>
|
/>
|
||||||
|
@ -116,7 +123,7 @@ export const ReferenceLineAnnotations: FC<Props> = ({
|
||||||
|
|
||||||
let rect;
|
let rect;
|
||||||
if (fill && fill !== 'none') {
|
if (fill && fill !== 'none') {
|
||||||
const rectDataValues = getRectDataValue(config, formatter);
|
const rectDataValues = getRectDataValue(config, formatter, props.groupId);
|
||||||
|
|
||||||
rect = (
|
rect = (
|
||||||
<RectAnnotation
|
<RectAnnotation
|
||||||
|
|
|
@ -11,67 +11,73 @@ import { FieldFormat } from '@kbn/field-formats-plugin/common';
|
||||||
import { groupBy } from 'lodash';
|
import { groupBy } from 'lodash';
|
||||||
import { Position } from '@elastic/charts';
|
import { Position } from '@elastic/charts';
|
||||||
import { ReferenceLineLayerConfig } from '../../../common/types';
|
import { ReferenceLineLayerConfig } from '../../../common/types';
|
||||||
import { getGroupId } from './utils';
|
|
||||||
import { ReferenceLineAnnotations } from './reference_line_annotations';
|
import { ReferenceLineAnnotations } from './reference_line_annotations';
|
||||||
import { LayerAccessorsTitles } from '../../helpers';
|
import { LayerAccessorsTitles, GroupsConfiguration, AxesMap } from '../../helpers';
|
||||||
|
import { getAxisGroupForReferenceLine } from './utils';
|
||||||
|
|
||||||
interface ReferenceLineLayerProps {
|
interface ReferenceLineLayerProps {
|
||||||
layer: ReferenceLineLayerConfig;
|
layer: ReferenceLineLayerConfig;
|
||||||
formatters: Record<'left' | 'right' | 'bottom', FieldFormat | undefined>;
|
|
||||||
paddingMap: Partial<Record<Position, number>>;
|
paddingMap: Partial<Record<Position, number>>;
|
||||||
axesMap: Record<'left' | 'right', boolean>;
|
|
||||||
isHorizontal: boolean;
|
isHorizontal: boolean;
|
||||||
titles?: LayerAccessorsTitles;
|
titles?: LayerAccessorsTitles;
|
||||||
|
xAxisFormatter: FieldFormat;
|
||||||
|
axesConfiguration: GroupsConfiguration;
|
||||||
|
yAxesMap: AxesMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ReferenceLineLayer: FC<ReferenceLineLayerProps> = ({
|
export const ReferenceLineLayer: FC<ReferenceLineLayerProps> = ({
|
||||||
layer,
|
layer,
|
||||||
formatters,
|
axesConfiguration,
|
||||||
|
xAxisFormatter,
|
||||||
paddingMap,
|
paddingMap,
|
||||||
axesMap,
|
|
||||||
isHorizontal,
|
isHorizontal,
|
||||||
titles,
|
titles,
|
||||||
|
yAxesMap,
|
||||||
}) => {
|
}) => {
|
||||||
if (!layer.yConfig) {
|
if (!layer.decorations) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { columnToLabel, yConfig: yConfigs, table } = layer;
|
const { columnToLabel, decorations, table } = layer;
|
||||||
const columnToLabelMap: Record<string, string> = columnToLabel ? JSON.parse(columnToLabel) : {};
|
const columnToLabelMap: Record<string, string> = columnToLabel ? JSON.parse(columnToLabel) : {};
|
||||||
|
|
||||||
const row = table.rows[0];
|
const row = table.rows[0];
|
||||||
|
|
||||||
const yConfigByValue = yConfigs.sort(
|
const decorationConfigsByValue = decorations.sort(
|
||||||
({ forAccessor: idA }, { forAccessor: idB }) => row[idA] - row[idB]
|
({ forAccessor: idA }, { forAccessor: idB }) => row[idA] - row[idB]
|
||||||
);
|
);
|
||||||
|
|
||||||
const groupedByDirection = groupBy(yConfigByValue, 'fill');
|
const groupedByDirection = groupBy(decorationConfigsByValue, 'fill');
|
||||||
if (groupedByDirection.below) {
|
if (groupedByDirection.below) {
|
||||||
groupedByDirection.below.reverse();
|
groupedByDirection.below.reverse();
|
||||||
}
|
}
|
||||||
|
|
||||||
const referenceLineElements = yConfigByValue.flatMap((yConfig) => {
|
const referenceLineElements = decorationConfigsByValue.flatMap((decorationConfig) => {
|
||||||
const { axisMode } = yConfig;
|
const axisGroup = getAxisGroupForReferenceLine(
|
||||||
|
axesConfiguration,
|
||||||
// Find the formatter for the given axis
|
decorationConfig,
|
||||||
const groupId = getGroupId(axisMode);
|
isHorizontal
|
||||||
|
|
||||||
const formatter = formatters[groupId || 'bottom'];
|
|
||||||
const name = columnToLabelMap[yConfig.forAccessor] ?? titles?.yTitles?.[yConfig.forAccessor];
|
|
||||||
const value = row[yConfig.forAccessor];
|
|
||||||
const yConfigsWithSameDirection = groupedByDirection[yConfig.fill!];
|
|
||||||
const indexFromSameType = yConfigsWithSameDirection.findIndex(
|
|
||||||
({ forAccessor }) => forAccessor === yConfig.forAccessor
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const shouldCheckNextReferenceLine = indexFromSameType < yConfigsWithSameDirection.length - 1;
|
const formatter = axisGroup?.formatter || xAxisFormatter;
|
||||||
|
const name =
|
||||||
|
columnToLabelMap[decorationConfig.forAccessor] ??
|
||||||
|
titles?.yTitles?.[decorationConfig.forAccessor];
|
||||||
|
const value = row[decorationConfig.forAccessor];
|
||||||
|
const yDecorationsWithSameDirection = groupedByDirection[decorationConfig.fill!];
|
||||||
|
const indexFromSameType = yDecorationsWithSameDirection.findIndex(
|
||||||
|
({ forAccessor }) => forAccessor === decorationConfig.forAccessor
|
||||||
|
);
|
||||||
|
|
||||||
|
const shouldCheckNextReferenceLine =
|
||||||
|
indexFromSameType < yDecorationsWithSameDirection.length - 1;
|
||||||
|
|
||||||
const nextValue = shouldCheckNextReferenceLine
|
const nextValue = shouldCheckNextReferenceLine
|
||||||
? row[yConfigsWithSameDirection[indexFromSameType + 1].forAccessor]
|
? row[yDecorationsWithSameDirection[indexFromSameType + 1].forAccessor]
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
const { forAccessor, type, ...restAnnotationConfig } = yConfig;
|
const { forAccessor, type, ...restAnnotationConfig } = decorationConfig;
|
||||||
const id = `${layer.layerId}-${yConfig.forAccessor}`;
|
const id = `${layer.layerId}-${decorationConfig.forAccessor}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ReferenceLineAnnotations
|
<ReferenceLineAnnotations
|
||||||
|
@ -82,9 +88,10 @@ export const ReferenceLineLayer: FC<ReferenceLineLayerProps> = ({
|
||||||
nextValue,
|
nextValue,
|
||||||
name,
|
name,
|
||||||
...restAnnotationConfig,
|
...restAnnotationConfig,
|
||||||
|
axisGroup,
|
||||||
}}
|
}}
|
||||||
|
axesMap={yAxesMap}
|
||||||
paddingMap={paddingMap}
|
paddingMap={paddingMap}
|
||||||
axesMap={axesMap}
|
|
||||||
formatter={formatter}
|
formatter={formatter}
|
||||||
isHorizontal={isHorizontal}
|
isHorizontal={isHorizontal}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -15,7 +15,7 @@ import { LayerTypes } from '../../../common/constants';
|
||||||
import {
|
import {
|
||||||
ReferenceLineLayerArgs,
|
ReferenceLineLayerArgs,
|
||||||
ReferenceLineLayerConfig,
|
ReferenceLineLayerConfig,
|
||||||
ExtendedYConfig,
|
ExtendedReferenceLineDecorationConfig,
|
||||||
ReferenceLineArgs,
|
ReferenceLineArgs,
|
||||||
ReferenceLineConfig,
|
ReferenceLineConfig,
|
||||||
} from '../../../common/types';
|
} from '../../../common/types';
|
||||||
|
@ -46,12 +46,14 @@ const data: Datatable = {
|
||||||
})),
|
})),
|
||||||
};
|
};
|
||||||
|
|
||||||
function createLayers(yConfigs: ReferenceLineLayerArgs['yConfig']): ReferenceLineLayerConfig[] {
|
function createLayers(
|
||||||
|
decorations: ReferenceLineLayerArgs['decorations']
|
||||||
|
): ReferenceLineLayerConfig[] {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
layerId: 'first',
|
layerId: 'first',
|
||||||
accessors: (yConfigs || []).map(({ forAccessor }) => forAccessor),
|
accessors: (decorations || []).map(({ forAccessor }) => forAccessor),
|
||||||
yConfig: yConfigs,
|
decorations,
|
||||||
type: 'referenceLineLayer',
|
type: 'referenceLineLayer',
|
||||||
layerType: LayerTypes.REFERENCELINE,
|
layerType: LayerTypes.REFERENCELINE,
|
||||||
table: data,
|
table: data,
|
||||||
|
@ -69,7 +71,7 @@ function createReferenceLine(
|
||||||
type: 'referenceLine',
|
type: 'referenceLine',
|
||||||
layerType: 'referenceLine',
|
layerType: 'referenceLine',
|
||||||
lineLength,
|
lineLength,
|
||||||
yConfig: [{ type: 'referenceLineYConfig', ...args }],
|
decorations: [{ type: 'extendedReferenceLineDecorationConfig', ...args }],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +84,7 @@ interface XCoords {
|
||||||
x1: number | undefined;
|
x1: number | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAxisFromId(layerPrefix: string): ExtendedYConfig['axisMode'] {
|
function getAxisFromId(layerPrefix: string): ExtendedReferenceLineDecorationConfig['position'] {
|
||||||
return /left/i.test(layerPrefix) ? 'left' : /right/i.test(layerPrefix) ? 'right' : 'bottom';
|
return /left/i.test(layerPrefix) ? 'left' : /right/i.test(layerPrefix) ? 'right' : 'bottom';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,21 +92,42 @@ const emptyCoords = { x0: undefined, x1: undefined, y0: undefined, y1: undefined
|
||||||
|
|
||||||
describe('ReferenceLines', () => {
|
describe('ReferenceLines', () => {
|
||||||
describe('referenceLineLayers', () => {
|
describe('referenceLineLayers', () => {
|
||||||
let formatters: Record<'left' | 'right' | 'bottom', FieldFormat | undefined>;
|
|
||||||
let defaultProps: Omit<ReferenceLinesProps, 'data' | 'layers'>;
|
let defaultProps: Omit<ReferenceLinesProps, 'data' | 'layers'>;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
formatters = {
|
|
||||||
left: { convert: jest.fn((x) => x) } as unknown as FieldFormat,
|
|
||||||
right: { convert: jest.fn((x) => x) } as unknown as FieldFormat,
|
|
||||||
bottom: { convert: jest.fn((x) => x) } as unknown as FieldFormat,
|
|
||||||
};
|
|
||||||
|
|
||||||
defaultProps = {
|
defaultProps = {
|
||||||
formatters,
|
xAxisFormatter: { convert: jest.fn((x) => x) } as unknown as FieldFormat,
|
||||||
isHorizontal: false,
|
isHorizontal: false,
|
||||||
axesMap: { left: true, right: false },
|
axesConfiguration: [
|
||||||
|
{
|
||||||
|
groupId: 'left',
|
||||||
|
position: 'left',
|
||||||
|
series: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
groupId: 'right',
|
||||||
|
position: 'right',
|
||||||
|
series: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
groupId: 'bottom',
|
||||||
|
position: 'bottom',
|
||||||
|
series: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
paddingMap: {},
|
paddingMap: {},
|
||||||
|
yAxesMap: {
|
||||||
|
left: {
|
||||||
|
groupId: 'left',
|
||||||
|
position: 'left',
|
||||||
|
series: [],
|
||||||
|
},
|
||||||
|
right: {
|
||||||
|
groupId: 'right',
|
||||||
|
position: 'right',
|
||||||
|
series: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -113,20 +136,20 @@ describe('ReferenceLines', () => {
|
||||||
['yAccessorLeft', 'below'],
|
['yAccessorLeft', 'below'],
|
||||||
['yAccessorRight', 'above'],
|
['yAccessorRight', 'above'],
|
||||||
['yAccessorRight', 'below'],
|
['yAccessorRight', 'below'],
|
||||||
] as Array<[string, Exclude<ExtendedYConfig['fill'], undefined>]>)(
|
] as Array<[string, Exclude<ExtendedReferenceLineDecorationConfig['fill'], undefined>]>)(
|
||||||
'should render a RectAnnotation for a reference line with fill set: %s %s',
|
'should render a RectAnnotation for a reference line with fill set: %s %s',
|
||||||
(layerPrefix, fill) => {
|
(layerPrefix, fill) => {
|
||||||
const axisMode = getAxisFromId(layerPrefix);
|
const position = getAxisFromId(layerPrefix);
|
||||||
const wrapper = shallow(
|
const wrapper = shallow(
|
||||||
<ReferenceLines
|
<ReferenceLines
|
||||||
{...defaultProps}
|
{...defaultProps}
|
||||||
layers={createLayers([
|
layers={createLayers([
|
||||||
{
|
{
|
||||||
forAccessor: `${layerPrefix}FirstId`,
|
forAccessor: `${layerPrefix}FirstId`,
|
||||||
axisMode,
|
position,
|
||||||
lineStyle: 'solid',
|
lineStyle: 'solid',
|
||||||
fill,
|
fill,
|
||||||
type: 'extendedYConfig',
|
type: 'referenceLineDecorationConfig',
|
||||||
},
|
},
|
||||||
])}
|
])}
|
||||||
/>
|
/>
|
||||||
|
@ -154,7 +177,7 @@ describe('ReferenceLines', () => {
|
||||||
it.each([
|
it.each([
|
||||||
['xAccessor', 'above'],
|
['xAccessor', 'above'],
|
||||||
['xAccessor', 'below'],
|
['xAccessor', 'below'],
|
||||||
] as Array<[string, Exclude<ExtendedYConfig['fill'], undefined>]>)(
|
] as Array<[string, Exclude<ExtendedReferenceLineDecorationConfig['fill'], undefined>]>)(
|
||||||
'should render a RectAnnotation for a reference line with fill set: %s %s',
|
'should render a RectAnnotation for a reference line with fill set: %s %s',
|
||||||
(layerPrefix, fill) => {
|
(layerPrefix, fill) => {
|
||||||
const wrapper = shallow(
|
const wrapper = shallow(
|
||||||
|
@ -163,9 +186,9 @@ describe('ReferenceLines', () => {
|
||||||
layers={createLayers([
|
layers={createLayers([
|
||||||
{
|
{
|
||||||
forAccessor: `${layerPrefix}FirstId`,
|
forAccessor: `${layerPrefix}FirstId`,
|
||||||
axisMode: 'bottom',
|
position: 'bottom',
|
||||||
lineStyle: 'solid',
|
lineStyle: 'solid',
|
||||||
type: 'extendedYConfig',
|
type: 'referenceLineDecorationConfig',
|
||||||
fill,
|
fill,
|
||||||
},
|
},
|
||||||
])}
|
])}
|
||||||
|
@ -196,26 +219,26 @@ describe('ReferenceLines', () => {
|
||||||
['yAccessorLeft', 'below', { y0: undefined, y1: 5 }, { y0: 5, y1: 10 }],
|
['yAccessorLeft', 'below', { y0: undefined, y1: 5 }, { y0: 5, y1: 10 }],
|
||||||
['yAccessorRight', 'above', { y0: 5, y1: 10 }, { y0: 10, y1: undefined }],
|
['yAccessorRight', 'above', { y0: 5, y1: 10 }, { y0: 10, y1: undefined }],
|
||||||
['yAccessorRight', 'below', { y0: undefined, y1: 5 }, { y0: 5, y1: 10 }],
|
['yAccessorRight', 'below', { y0: undefined, y1: 5 }, { y0: 5, y1: 10 }],
|
||||||
] as Array<[string, Exclude<ExtendedYConfig['fill'], undefined>, YCoords, YCoords]>)(
|
] as Array<[string, Exclude<ExtendedReferenceLineDecorationConfig['fill'], undefined>, YCoords, YCoords]>)(
|
||||||
'should avoid overlap between two reference lines with fill in the same direction: 2 x %s %s',
|
'should avoid overlap between two reference lines with fill in the same direction: 2 x %s %s',
|
||||||
(layerPrefix, fill, coordsA, coordsB) => {
|
(layerPrefix, fill, coordsA, coordsB) => {
|
||||||
const axisMode = getAxisFromId(layerPrefix);
|
const position = getAxisFromId(layerPrefix);
|
||||||
const wrapper = shallow(
|
const wrapper = shallow(
|
||||||
<ReferenceLines
|
<ReferenceLines
|
||||||
{...defaultProps}
|
{...defaultProps}
|
||||||
layers={createLayers([
|
layers={createLayers([
|
||||||
{
|
{
|
||||||
forAccessor: `${layerPrefix}FirstId`,
|
forAccessor: `${layerPrefix}FirstId`,
|
||||||
axisMode,
|
position,
|
||||||
lineStyle: 'solid',
|
lineStyle: 'solid',
|
||||||
type: 'extendedYConfig',
|
type: 'referenceLineDecorationConfig',
|
||||||
fill,
|
fill,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
forAccessor: `${layerPrefix}SecondId`,
|
forAccessor: `${layerPrefix}SecondId`,
|
||||||
axisMode,
|
position,
|
||||||
lineStyle: 'solid',
|
lineStyle: 'solid',
|
||||||
type: 'extendedYConfig',
|
type: 'referenceLineDecorationConfig',
|
||||||
fill,
|
fill,
|
||||||
},
|
},
|
||||||
])}
|
])}
|
||||||
|
@ -252,7 +275,7 @@ describe('ReferenceLines', () => {
|
||||||
it.each([
|
it.each([
|
||||||
['xAccessor', 'above', { x0: 1, x1: 2 }, { x0: 2, x1: undefined }],
|
['xAccessor', 'above', { x0: 1, x1: 2 }, { x0: 2, x1: undefined }],
|
||||||
['xAccessor', 'below', { x0: undefined, x1: 1 }, { x0: 1, x1: 2 }],
|
['xAccessor', 'below', { x0: undefined, x1: 1 }, { x0: 1, x1: 2 }],
|
||||||
] as Array<[string, Exclude<ExtendedYConfig['fill'], undefined>, XCoords, XCoords]>)(
|
] as Array<[string, Exclude<ExtendedReferenceLineDecorationConfig['fill'], undefined>, XCoords, XCoords]>)(
|
||||||
'should avoid overlap between two reference lines with fill in the same direction: 2 x %s %s',
|
'should avoid overlap between two reference lines with fill in the same direction: 2 x %s %s',
|
||||||
(layerPrefix, fill, coordsA, coordsB) => {
|
(layerPrefix, fill, coordsA, coordsB) => {
|
||||||
const wrapper = shallow(
|
const wrapper = shallow(
|
||||||
|
@ -261,16 +284,16 @@ describe('ReferenceLines', () => {
|
||||||
layers={createLayers([
|
layers={createLayers([
|
||||||
{
|
{
|
||||||
forAccessor: `${layerPrefix}FirstId`,
|
forAccessor: `${layerPrefix}FirstId`,
|
||||||
axisMode: 'bottom',
|
position: 'bottom',
|
||||||
lineStyle: 'solid',
|
lineStyle: 'solid',
|
||||||
type: 'extendedYConfig',
|
type: 'referenceLineDecorationConfig',
|
||||||
fill,
|
fill,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
forAccessor: `${layerPrefix}SecondId`,
|
forAccessor: `${layerPrefix}SecondId`,
|
||||||
axisMode: 'bottom',
|
position: 'bottom',
|
||||||
lineStyle: 'solid',
|
lineStyle: 'solid',
|
||||||
type: 'extendedYConfig',
|
type: 'referenceLineDecorationConfig',
|
||||||
fill,
|
fill,
|
||||||
},
|
},
|
||||||
])}
|
])}
|
||||||
|
@ -307,7 +330,7 @@ describe('ReferenceLines', () => {
|
||||||
it.each(['yAccessorLeft', 'yAccessorRight', 'xAccessor'])(
|
it.each(['yAccessorLeft', 'yAccessorRight', 'xAccessor'])(
|
||||||
'should let areas in different directions overlap: %s',
|
'should let areas in different directions overlap: %s',
|
||||||
(layerPrefix) => {
|
(layerPrefix) => {
|
||||||
const axisMode = getAxisFromId(layerPrefix);
|
const position = getAxisFromId(layerPrefix);
|
||||||
|
|
||||||
const wrapper = shallow(
|
const wrapper = shallow(
|
||||||
<ReferenceLines
|
<ReferenceLines
|
||||||
|
@ -315,17 +338,17 @@ describe('ReferenceLines', () => {
|
||||||
layers={createLayers([
|
layers={createLayers([
|
||||||
{
|
{
|
||||||
forAccessor: `${layerPrefix}FirstId`,
|
forAccessor: `${layerPrefix}FirstId`,
|
||||||
axisMode,
|
position,
|
||||||
lineStyle: 'solid',
|
lineStyle: 'solid',
|
||||||
fill: 'above',
|
fill: 'above',
|
||||||
type: 'extendedYConfig',
|
type: 'referenceLineDecorationConfig',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
forAccessor: `${layerPrefix}SecondId`,
|
forAccessor: `${layerPrefix}SecondId`,
|
||||||
axisMode,
|
position,
|
||||||
lineStyle: 'solid',
|
lineStyle: 'solid',
|
||||||
fill: 'below',
|
fill: 'below',
|
||||||
type: 'extendedYConfig',
|
type: 'referenceLineDecorationConfig',
|
||||||
},
|
},
|
||||||
])}
|
])}
|
||||||
/>
|
/>
|
||||||
|
@ -338,8 +361,8 @@ describe('ReferenceLines', () => {
|
||||||
).toEqual(
|
).toEqual(
|
||||||
expect.arrayContaining([
|
expect.arrayContaining([
|
||||||
{
|
{
|
||||||
coordinates: { ...emptyCoords, ...(axisMode === 'bottom' ? { x0: 1 } : { y0: 5 }) },
|
coordinates: { ...emptyCoords, ...(position === 'bottom' ? { x0: 1 } : { y0: 5 }) },
|
||||||
details: axisMode === 'bottom' ? 1 : 5,
|
details: position === 'bottom' ? 1 : 5,
|
||||||
header: undefined,
|
header: undefined,
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
@ -349,8 +372,8 @@ describe('ReferenceLines', () => {
|
||||||
).toEqual(
|
).toEqual(
|
||||||
expect.arrayContaining([
|
expect.arrayContaining([
|
||||||
{
|
{
|
||||||
coordinates: { ...emptyCoords, ...(axisMode === 'bottom' ? { x1: 2 } : { y1: 10 }) },
|
coordinates: { ...emptyCoords, ...(position === 'bottom' ? { x1: 2 } : { y1: 10 }) },
|
||||||
details: axisMode === 'bottom' ? 2 : 10,
|
details: position === 'bottom' ? 2 : 10,
|
||||||
header: undefined,
|
header: undefined,
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
@ -361,7 +384,7 @@ describe('ReferenceLines', () => {
|
||||||
it.each([
|
it.each([
|
||||||
['above', { y0: 5, y1: 10 }, { y0: 10, y1: undefined }],
|
['above', { y0: 5, y1: 10 }, { y0: 10, y1: undefined }],
|
||||||
['below', { y0: undefined, y1: 5 }, { y0: 5, y1: 10 }],
|
['below', { y0: undefined, y1: 5 }, { y0: 5, y1: 10 }],
|
||||||
] as Array<[Exclude<ExtendedYConfig['fill'], undefined>, YCoords, YCoords]>)(
|
] as Array<[Exclude<ExtendedReferenceLineDecorationConfig['fill'], undefined>, YCoords, YCoords]>)(
|
||||||
'should be robust and works also for different axes when on same direction: 1x Left + 1x Right both %s',
|
'should be robust and works also for different axes when on same direction: 1x Left + 1x Right both %s',
|
||||||
(fill, coordsA, coordsB) => {
|
(fill, coordsA, coordsB) => {
|
||||||
const wrapper = shallow(
|
const wrapper = shallow(
|
||||||
|
@ -370,17 +393,17 @@ describe('ReferenceLines', () => {
|
||||||
layers={createLayers([
|
layers={createLayers([
|
||||||
{
|
{
|
||||||
forAccessor: `yAccessorLeftFirstId`,
|
forAccessor: `yAccessorLeftFirstId`,
|
||||||
axisMode: 'left',
|
position: 'left',
|
||||||
lineStyle: 'solid',
|
lineStyle: 'solid',
|
||||||
fill,
|
fill,
|
||||||
type: 'extendedYConfig',
|
type: 'referenceLineDecorationConfig',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
forAccessor: `yAccessorRightSecondId`,
|
forAccessor: `yAccessorRightSecondId`,
|
||||||
axisMode: 'right',
|
position: 'right',
|
||||||
lineStyle: 'solid',
|
lineStyle: 'solid',
|
||||||
fill,
|
fill,
|
||||||
type: 'extendedYConfig',
|
type: 'referenceLineDecorationConfig',
|
||||||
},
|
},
|
||||||
])}
|
])}
|
||||||
/>
|
/>
|
||||||
|
@ -415,21 +438,42 @@ describe('ReferenceLines', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('referenceLines', () => {
|
describe('referenceLines', () => {
|
||||||
let formatters: Record<'left' | 'right' | 'bottom', FieldFormat | undefined>;
|
|
||||||
let defaultProps: Omit<ReferenceLinesProps, 'data' | 'layers'>;
|
let defaultProps: Omit<ReferenceLinesProps, 'data' | 'layers'>;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
formatters = {
|
|
||||||
left: { convert: jest.fn((x) => x) } as unknown as FieldFormat,
|
|
||||||
right: { convert: jest.fn((x) => x) } as unknown as FieldFormat,
|
|
||||||
bottom: { convert: jest.fn((x) => x) } as unknown as FieldFormat,
|
|
||||||
};
|
|
||||||
|
|
||||||
defaultProps = {
|
defaultProps = {
|
||||||
formatters,
|
xAxisFormatter: { convert: jest.fn((x) => x) } as unknown as FieldFormat,
|
||||||
isHorizontal: false,
|
isHorizontal: false,
|
||||||
axesMap: { left: true, right: false },
|
axesConfiguration: [
|
||||||
|
{
|
||||||
|
groupId: 'left',
|
||||||
|
position: 'left',
|
||||||
|
series: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
groupId: 'right',
|
||||||
|
position: 'right',
|
||||||
|
series: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
groupId: 'bottom',
|
||||||
|
position: 'bottom',
|
||||||
|
series: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
paddingMap: {},
|
paddingMap: {},
|
||||||
|
yAxesMap: {
|
||||||
|
left: {
|
||||||
|
groupId: 'left',
|
||||||
|
position: 'left',
|
||||||
|
series: [],
|
||||||
|
},
|
||||||
|
right: {
|
||||||
|
groupId: 'right',
|
||||||
|
position: 'right',
|
||||||
|
series: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -438,17 +482,17 @@ describe('ReferenceLines', () => {
|
||||||
['yAccessorLeft', 'below'],
|
['yAccessorLeft', 'below'],
|
||||||
['yAccessorRight', 'above'],
|
['yAccessorRight', 'above'],
|
||||||
['yAccessorRight', 'below'],
|
['yAccessorRight', 'below'],
|
||||||
] as Array<[string, Exclude<ExtendedYConfig['fill'], undefined>]>)(
|
] as Array<[string, Exclude<ExtendedReferenceLineDecorationConfig['fill'], undefined>]>)(
|
||||||
'should render a RectAnnotation for a reference line with fill set: %s %s',
|
'should render a RectAnnotation for a reference line with fill set: %s %s',
|
||||||
(layerPrefix, fill) => {
|
(layerPrefix, fill) => {
|
||||||
const axisMode = getAxisFromId(layerPrefix);
|
const position = getAxisFromId(layerPrefix);
|
||||||
const value = 5;
|
const value = 5;
|
||||||
const wrapper = shallow(
|
const wrapper = shallow(
|
||||||
<ReferenceLines
|
<ReferenceLines
|
||||||
{...defaultProps}
|
{...defaultProps}
|
||||||
layers={[
|
layers={[
|
||||||
createReferenceLine(layerPrefix, 1, {
|
createReferenceLine(layerPrefix, 1, {
|
||||||
axisMode,
|
position,
|
||||||
lineStyle: 'solid',
|
lineStyle: 'solid',
|
||||||
fill,
|
fill,
|
||||||
value,
|
value,
|
||||||
|
@ -479,7 +523,7 @@ describe('ReferenceLines', () => {
|
||||||
it.each([
|
it.each([
|
||||||
['xAccessor', 'above'],
|
['xAccessor', 'above'],
|
||||||
['xAccessor', 'below'],
|
['xAccessor', 'below'],
|
||||||
] as Array<[string, Exclude<ExtendedYConfig['fill'], undefined>]>)(
|
] as Array<[string, Exclude<ExtendedReferenceLineDecorationConfig['fill'], undefined>]>)(
|
||||||
'should render a RectAnnotation for a reference line with fill set: %s %s',
|
'should render a RectAnnotation for a reference line with fill set: %s %s',
|
||||||
(layerPrefix, fill) => {
|
(layerPrefix, fill) => {
|
||||||
const value = 1;
|
const value = 1;
|
||||||
|
@ -488,7 +532,7 @@ describe('ReferenceLines', () => {
|
||||||
{...defaultProps}
|
{...defaultProps}
|
||||||
layers={[
|
layers={[
|
||||||
createReferenceLine(layerPrefix, 1, {
|
createReferenceLine(layerPrefix, 1, {
|
||||||
axisMode: 'bottom',
|
position: 'bottom',
|
||||||
lineStyle: 'solid',
|
lineStyle: 'solid',
|
||||||
fill,
|
fill,
|
||||||
value,
|
value,
|
||||||
|
@ -519,23 +563,23 @@ describe('ReferenceLines', () => {
|
||||||
it.each([
|
it.each([
|
||||||
['yAccessorLeft', 'above', { y0: 10, y1: undefined }, { y0: 10, y1: undefined }],
|
['yAccessorLeft', 'above', { y0: 10, y1: undefined }, { y0: 10, y1: undefined }],
|
||||||
['yAccessorLeft', 'below', { y0: undefined, y1: 5 }, { y0: undefined, y1: 5 }],
|
['yAccessorLeft', 'below', { y0: undefined, y1: 5 }, { y0: undefined, y1: 5 }],
|
||||||
] as Array<[string, Exclude<ExtendedYConfig['fill'], undefined>, YCoords, YCoords]>)(
|
] as Array<[string, Exclude<ExtendedReferenceLineDecorationConfig['fill'], undefined>, YCoords, YCoords]>)(
|
||||||
'should avoid overlap between two reference lines with fill in the same direction: 2 x %s %s',
|
'should avoid overlap between two reference lines with fill in the same direction: 2 x %s %s',
|
||||||
(layerPrefix, fill, coordsA, coordsB) => {
|
(layerPrefix, fill, coordsA, coordsB) => {
|
||||||
const axisMode = getAxisFromId(layerPrefix);
|
const position = getAxisFromId(layerPrefix);
|
||||||
const value = coordsA.y0 ?? coordsA.y1!;
|
const value = coordsA.y0 ?? coordsA.y1!;
|
||||||
const wrapper = shallow(
|
const wrapper = shallow(
|
||||||
<ReferenceLines
|
<ReferenceLines
|
||||||
{...defaultProps}
|
{...defaultProps}
|
||||||
layers={[
|
layers={[
|
||||||
createReferenceLine(layerPrefix, 10, {
|
createReferenceLine(layerPrefix, 10, {
|
||||||
axisMode,
|
position,
|
||||||
lineStyle: 'solid',
|
lineStyle: 'solid',
|
||||||
fill,
|
fill,
|
||||||
value,
|
value,
|
||||||
}),
|
}),
|
||||||
createReferenceLine(layerPrefix, 10, {
|
createReferenceLine(layerPrefix, 10, {
|
||||||
axisMode,
|
position,
|
||||||
lineStyle: 'solid',
|
lineStyle: 'solid',
|
||||||
fill,
|
fill,
|
||||||
value,
|
value,
|
||||||
|
@ -570,7 +614,7 @@ describe('ReferenceLines', () => {
|
||||||
it.each([
|
it.each([
|
||||||
['xAccessor', 'above', { x0: 1, x1: undefined }, { x0: 1, x1: undefined }],
|
['xAccessor', 'above', { x0: 1, x1: undefined }, { x0: 1, x1: undefined }],
|
||||||
['xAccessor', 'below', { x0: undefined, x1: 1 }, { x0: undefined, x1: 1 }],
|
['xAccessor', 'below', { x0: undefined, x1: 1 }, { x0: undefined, x1: 1 }],
|
||||||
] as Array<[string, Exclude<ExtendedYConfig['fill'], undefined>, XCoords, XCoords]>)(
|
] as Array<[string, Exclude<ExtendedReferenceLineDecorationConfig['fill'], undefined>, XCoords, XCoords]>)(
|
||||||
'should avoid overlap between two reference lines with fill in the same direction: 2 x %s %s',
|
'should avoid overlap between two reference lines with fill in the same direction: 2 x %s %s',
|
||||||
(layerPrefix, fill, coordsA, coordsB) => {
|
(layerPrefix, fill, coordsA, coordsB) => {
|
||||||
const value = coordsA.x0 ?? coordsA.x1!;
|
const value = coordsA.x0 ?? coordsA.x1!;
|
||||||
|
@ -579,13 +623,13 @@ describe('ReferenceLines', () => {
|
||||||
{...defaultProps}
|
{...defaultProps}
|
||||||
layers={[
|
layers={[
|
||||||
createReferenceLine(layerPrefix, 10, {
|
createReferenceLine(layerPrefix, 10, {
|
||||||
axisMode: 'bottom',
|
position: 'bottom',
|
||||||
lineStyle: 'solid',
|
lineStyle: 'solid',
|
||||||
fill,
|
fill,
|
||||||
value,
|
value,
|
||||||
}),
|
}),
|
||||||
createReferenceLine(layerPrefix, 10, {
|
createReferenceLine(layerPrefix, 10, {
|
||||||
axisMode: 'bottom',
|
position: 'bottom',
|
||||||
lineStyle: 'solid',
|
lineStyle: 'solid',
|
||||||
fill,
|
fill,
|
||||||
value,
|
value,
|
||||||
|
@ -624,7 +668,7 @@ describe('ReferenceLines', () => {
|
||||||
it.each(['yAccessorLeft', 'yAccessorRight', 'xAccessor'])(
|
it.each(['yAccessorLeft', 'yAccessorRight', 'xAccessor'])(
|
||||||
'should let areas in different directions overlap: %s',
|
'should let areas in different directions overlap: %s',
|
||||||
(layerPrefix) => {
|
(layerPrefix) => {
|
||||||
const axisMode = getAxisFromId(layerPrefix);
|
const position = getAxisFromId(layerPrefix);
|
||||||
const value1 = 1;
|
const value1 = 1;
|
||||||
const value2 = 10;
|
const value2 = 10;
|
||||||
const wrapper = shallow(
|
const wrapper = shallow(
|
||||||
|
@ -632,13 +676,13 @@ describe('ReferenceLines', () => {
|
||||||
{...defaultProps}
|
{...defaultProps}
|
||||||
layers={[
|
layers={[
|
||||||
createReferenceLine(layerPrefix, 10, {
|
createReferenceLine(layerPrefix, 10, {
|
||||||
axisMode,
|
position,
|
||||||
lineStyle: 'solid',
|
lineStyle: 'solid',
|
||||||
fill: 'above',
|
fill: 'above',
|
||||||
value: value1,
|
value: value1,
|
||||||
}),
|
}),
|
||||||
createReferenceLine(layerPrefix, 10, {
|
createReferenceLine(layerPrefix, 10, {
|
||||||
axisMode,
|
position,
|
||||||
lineStyle: 'solid',
|
lineStyle: 'solid',
|
||||||
fill: 'below',
|
fill: 'below',
|
||||||
value: value2,
|
value: value2,
|
||||||
|
@ -654,7 +698,7 @@ describe('ReferenceLines', () => {
|
||||||
{
|
{
|
||||||
coordinates: {
|
coordinates: {
|
||||||
...emptyCoords,
|
...emptyCoords,
|
||||||
...(axisMode === 'bottom' ? { x0: value1 } : { y0: value1 }),
|
...(position === 'bottom' ? { x0: value1 } : { y0: value1 }),
|
||||||
},
|
},
|
||||||
details: value1,
|
details: value1,
|
||||||
header: undefined,
|
header: undefined,
|
||||||
|
@ -670,7 +714,7 @@ describe('ReferenceLines', () => {
|
||||||
{
|
{
|
||||||
coordinates: {
|
coordinates: {
|
||||||
...emptyCoords,
|
...emptyCoords,
|
||||||
...(axisMode === 'bottom' ? { x1: value2 } : { y1: value2 }),
|
...(position === 'bottom' ? { x1: value2 } : { y1: value2 }),
|
||||||
},
|
},
|
||||||
details: value2,
|
details: value2,
|
||||||
header: undefined,
|
header: undefined,
|
||||||
|
|
|
@ -12,18 +12,24 @@ import React from 'react';
|
||||||
import { Position } from '@elastic/charts';
|
import { Position } from '@elastic/charts';
|
||||||
import type { FieldFormat } from '@kbn/field-formats-plugin/common';
|
import type { FieldFormat } from '@kbn/field-formats-plugin/common';
|
||||||
import type { CommonXYReferenceLineLayerConfig, ReferenceLineConfig } from '../../../common/types';
|
import type { CommonXYReferenceLineLayerConfig, ReferenceLineConfig } from '../../../common/types';
|
||||||
import { isReferenceLine, LayersAccessorsTitles } from '../../helpers';
|
import {
|
||||||
|
AxesMap,
|
||||||
|
GroupsConfiguration,
|
||||||
|
isReferenceLine,
|
||||||
|
LayersAccessorsTitles,
|
||||||
|
} from '../../helpers';
|
||||||
import { ReferenceLineLayer } from './reference_line_layer';
|
import { ReferenceLineLayer } from './reference_line_layer';
|
||||||
import { ReferenceLine } from './reference_line';
|
import { ReferenceLine } from './reference_line';
|
||||||
import { getNextValuesForReferenceLines } from './utils';
|
import { getNextValuesForReferenceLines } from './utils';
|
||||||
|
|
||||||
export interface ReferenceLinesProps {
|
export interface ReferenceLinesProps {
|
||||||
layers: CommonXYReferenceLineLayerConfig[];
|
layers: CommonXYReferenceLineLayerConfig[];
|
||||||
formatters: Record<'left' | 'right' | 'bottom', FieldFormat | undefined>;
|
xAxisFormatter: FieldFormat;
|
||||||
axesMap: Record<'left' | 'right', boolean>;
|
axesConfiguration: GroupsConfiguration;
|
||||||
isHorizontal: boolean;
|
isHorizontal: boolean;
|
||||||
paddingMap: Partial<Record<Position, number>>;
|
paddingMap: Partial<Record<Position, number>>;
|
||||||
titles?: LayersAccessorsTitles;
|
titles?: LayersAccessorsTitles;
|
||||||
|
yAxesMap: AxesMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ReferenceLines = ({ layers, titles = {}, ...rest }: ReferenceLinesProps) => {
|
export const ReferenceLines = ({ layers, titles = {}, ...rest }: ReferenceLinesProps) => {
|
||||||
|
@ -36,13 +42,13 @@ export const ReferenceLines = ({ layers, titles = {}, ...rest }: ReferenceLinesP
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{layers.flatMap((layer) => {
|
{layers.flatMap((layer) => {
|
||||||
if (!layer.yConfig) {
|
if (!layer.decorations) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const key = `referenceLine-${layer.layerId}`;
|
const key = `referenceLine-${layer.layerId}`;
|
||||||
if (isReferenceLine(layer)) {
|
if (isReferenceLine(layer)) {
|
||||||
const nextValue = referenceLinesNextValues[layer.yConfig[0].fill][layer.layerId];
|
const nextValue = referenceLinesNextValues[layer.decorations[0].fill][layer.layerId];
|
||||||
return <ReferenceLine key={key} layer={layer} {...rest} nextValue={nextValue} />;
|
return <ReferenceLine key={key} layer={layer} {...rest} nextValue={nextValue} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,13 +11,23 @@ import { Position } from '@elastic/charts';
|
||||||
import { euiLightVars } from '@kbn/ui-theme';
|
import { euiLightVars } from '@kbn/ui-theme';
|
||||||
import { FieldFormat } from '@kbn/field-formats-plugin/common';
|
import { FieldFormat } from '@kbn/field-formats-plugin/common';
|
||||||
import { groupBy, orderBy } from 'lodash';
|
import { groupBy, orderBy } from 'lodash';
|
||||||
import { IconPosition, ReferenceLineConfig, YAxisMode, FillStyle } from '../../../common/types';
|
import {
|
||||||
|
IconPosition,
|
||||||
|
ReferenceLineConfig,
|
||||||
|
FillStyle,
|
||||||
|
ExtendedReferenceLineDecorationConfig,
|
||||||
|
ReferenceLineDecorationConfig,
|
||||||
|
} from '../../../common/types';
|
||||||
import { FillStyles } from '../../../common/constants';
|
import { FillStyles } from '../../../common/constants';
|
||||||
import {
|
import {
|
||||||
|
GroupsConfiguration,
|
||||||
LINES_MARKER_SIZE,
|
LINES_MARKER_SIZE,
|
||||||
mapVerticalToHorizontalPlacement,
|
mapVerticalToHorizontalPlacement,
|
||||||
Marker,
|
Marker,
|
||||||
MarkerBody,
|
MarkerBody,
|
||||||
|
getAxisPosition,
|
||||||
|
getOriginalAxisPosition,
|
||||||
|
AxesMap,
|
||||||
} from '../../helpers';
|
} from '../../helpers';
|
||||||
import { ReferenceLineAnnotationConfig } from './reference_line_annotations';
|
import { ReferenceLineAnnotationConfig } from './reference_line_annotations';
|
||||||
|
|
||||||
|
@ -26,17 +36,18 @@ import { ReferenceLineAnnotationConfig } from './reference_line_annotations';
|
||||||
// this function assume the chart is vertical
|
// this function assume the chart is vertical
|
||||||
export function getBaseIconPlacement(
|
export function getBaseIconPlacement(
|
||||||
iconPosition: IconPosition | undefined,
|
iconPosition: IconPosition | undefined,
|
||||||
axesMap?: Record<string, unknown>,
|
axesMap?: AxesMap,
|
||||||
axisMode?: YAxisMode
|
position?: Position
|
||||||
) {
|
) {
|
||||||
if (iconPosition === 'auto') {
|
if (iconPosition === 'auto') {
|
||||||
if (axisMode === 'bottom') {
|
if (position === Position.Bottom) {
|
||||||
return Position.Top;
|
return Position.Top;
|
||||||
}
|
}
|
||||||
if (axesMap) {
|
if (axesMap) {
|
||||||
if (axisMode === 'left') {
|
if (position === Position.Left) {
|
||||||
return axesMap.right ? Position.Left : Position.Right;
|
return axesMap.right ? Position.Left : Position.Right;
|
||||||
}
|
}
|
||||||
|
|
||||||
return axesMap.left ? Position.Right : Position.Left;
|
return axesMap.left ? Position.Right : Position.Left;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,22 +78,26 @@ export const getSharedStyle = (config: ReferenceLineAnnotationConfig) => ({
|
||||||
export const getLineAnnotationProps = (
|
export const getLineAnnotationProps = (
|
||||||
config: ReferenceLineAnnotationConfig,
|
config: ReferenceLineAnnotationConfig,
|
||||||
labels: { markerLabel?: string; markerBodyLabel?: string },
|
labels: { markerLabel?: string; markerBodyLabel?: string },
|
||||||
axesMap: Record<'left' | 'right', boolean>,
|
axesMap: AxesMap,
|
||||||
paddingMap: Partial<Record<Position, number>>,
|
paddingMap: Partial<Record<Position, number>>,
|
||||||
groupId: 'left' | 'right' | undefined,
|
|
||||||
isHorizontal: boolean
|
isHorizontal: boolean
|
||||||
) => {
|
) => {
|
||||||
// get the position for vertical chart
|
// get the position for vertical chart
|
||||||
const markerPositionVertical = getBaseIconPlacement(
|
const markerPositionVertical = getBaseIconPlacement(
|
||||||
config.iconPosition,
|
config.iconPosition,
|
||||||
axesMap,
|
axesMap,
|
||||||
config.axisMode
|
getOriginalAxisPosition(config.axisGroup?.position ?? Position.Bottom, isHorizontal)
|
||||||
);
|
);
|
||||||
|
|
||||||
// the padding map is built for vertical chart
|
// the padding map is built for vertical chart
|
||||||
const hasReducedPadding = paddingMap[markerPositionVertical] === LINES_MARKER_SIZE;
|
const hasReducedPadding = paddingMap[markerPositionVertical] === LINES_MARKER_SIZE;
|
||||||
|
|
||||||
|
const markerPosition = isHorizontal
|
||||||
|
? mapVerticalToHorizontalPlacement(markerPositionVertical)
|
||||||
|
: markerPositionVertical;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
groupId,
|
groupId: config.axisGroup?.groupId || 'bottom',
|
||||||
marker: (
|
marker: (
|
||||||
<Marker
|
<Marker
|
||||||
config={config}
|
config={config}
|
||||||
|
@ -94,22 +109,14 @@ export const getLineAnnotationProps = (
|
||||||
markerBody: (
|
markerBody: (
|
||||||
<MarkerBody
|
<MarkerBody
|
||||||
label={labels.markerBodyLabel}
|
label={labels.markerBodyLabel}
|
||||||
isHorizontal={
|
isHorizontal={markerPosition === Position.Bottom || markerPosition === Position.Top}
|
||||||
(!isHorizontal && config.axisMode === 'bottom') ||
|
|
||||||
(isHorizontal && config.axisMode !== 'bottom')
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
// rotate the position if required
|
// rotate the position if required
|
||||||
markerPosition: isHorizontal
|
markerPosition,
|
||||||
? mapVerticalToHorizontalPlacement(markerPositionVertical)
|
|
||||||
: markerPositionVertical,
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getGroupId = (axisMode: YAxisMode | undefined) =>
|
|
||||||
axisMode === 'bottom' ? undefined : axisMode === 'right' ? 'right' : 'left';
|
|
||||||
|
|
||||||
export const getBottomRect = (
|
export const getBottomRect = (
|
||||||
headerLabel: string | undefined,
|
headerLabel: string | undefined,
|
||||||
isFillAbove: boolean,
|
isFillAbove: boolean,
|
||||||
|
@ -147,13 +154,16 @@ export const getHorizontalRect = (
|
||||||
const sortReferenceLinesByGroup = (referenceLines: ReferenceLineConfig[], group: FillStyle) => {
|
const sortReferenceLinesByGroup = (referenceLines: ReferenceLineConfig[], group: FillStyle) => {
|
||||||
if (group === FillStyles.ABOVE || group === FillStyles.BELOW) {
|
if (group === FillStyles.ABOVE || group === FillStyles.BELOW) {
|
||||||
const order = group === FillStyles.ABOVE ? 'asc' : 'desc';
|
const order = group === FillStyles.ABOVE ? 'asc' : 'desc';
|
||||||
return orderBy(referenceLines, ({ yConfig: [{ value }] }) => value, [order]);
|
return orderBy(referenceLines, ({ decorations: [{ value }] }) => value, [order]);
|
||||||
}
|
}
|
||||||
return referenceLines;
|
return referenceLines;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getNextValuesForReferenceLines = (referenceLines: ReferenceLineConfig[]) => {
|
export const getNextValuesForReferenceLines = (referenceLines: ReferenceLineConfig[]) => {
|
||||||
const grouppedReferenceLines = groupBy(referenceLines, ({ yConfig: [yConfig] }) => yConfig.fill);
|
const grouppedReferenceLines = groupBy(
|
||||||
|
referenceLines,
|
||||||
|
({ decorations: [decorationConfig] }) => decorationConfig.fill
|
||||||
|
);
|
||||||
const groups = Object.keys(grouppedReferenceLines) as FillStyle[];
|
const groups = Object.keys(grouppedReferenceLines) as FillStyle[];
|
||||||
|
|
||||||
return groups.reduce<Record<FillStyle, Record<string, number | undefined>>>(
|
return groups.reduce<Record<FillStyle, Record<string, number | undefined>>>(
|
||||||
|
@ -164,8 +174,8 @@ export const getNextValuesForReferenceLines = (referenceLines: ReferenceLineConf
|
||||||
(nextValues, referenceLine, index, lines) => {
|
(nextValues, referenceLine, index, lines) => {
|
||||||
let nextValue: number | undefined;
|
let nextValue: number | undefined;
|
||||||
if (index < lines.length - 1) {
|
if (index < lines.length - 1) {
|
||||||
const [yConfig] = lines[index + 1].yConfig;
|
const [decorationConfig] = lines[index + 1].decorations;
|
||||||
nextValue = yConfig.value;
|
nextValue = decorationConfig.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return { ...nextValues, [referenceLine.layerId]: nextValue };
|
return { ...nextValues, [referenceLine.layerId]: nextValue };
|
||||||
|
@ -183,7 +193,7 @@ export const computeChartMargins = (
|
||||||
referenceLinePaddings: Partial<Record<Position, number>>,
|
referenceLinePaddings: Partial<Record<Position, number>>,
|
||||||
labelVisibility: Partial<Record<'x' | 'yLeft' | 'yRight', boolean>>,
|
labelVisibility: Partial<Record<'x' | 'yLeft' | 'yRight', boolean>>,
|
||||||
titleVisibility: Partial<Record<'x' | 'yLeft' | 'yRight', boolean>>,
|
titleVisibility: Partial<Record<'x' | 'yLeft' | 'yRight', boolean>>,
|
||||||
axesMap: Record<'left' | 'right', unknown>,
|
axesMap: AxesMap,
|
||||||
isHorizontal: boolean
|
isHorizontal: boolean
|
||||||
) => {
|
) => {
|
||||||
const result: Partial<Record<Position, number>> = {};
|
const result: Partial<Record<Position, number>> = {};
|
||||||
|
@ -210,5 +220,18 @@ export const computeChartMargins = (
|
||||||
const placement = isHorizontal ? mapVerticalToHorizontalPlacement('top') : 'top';
|
const placement = isHorizontal ? mapVerticalToHorizontalPlacement('top') : 'top';
|
||||||
result[placement] = referenceLinePaddings.top;
|
result[placement] = referenceLinePaddings.top;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function getAxisGroupForReferenceLine(
|
||||||
|
axesConfiguration: GroupsConfiguration,
|
||||||
|
decorationConfig: ReferenceLineDecorationConfig | ExtendedReferenceLineDecorationConfig,
|
||||||
|
shouldRotate: boolean
|
||||||
|
) {
|
||||||
|
return axesConfiguration.find(
|
||||||
|
(axis) =>
|
||||||
|
(decorationConfig.axisId && axis.groupId.includes(decorationConfig.axisId)) ||
|
||||||
|
getAxisPosition(decorationConfig.position ?? Position.Left, shouldRotate) === axis.position
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -155,6 +155,9 @@ describe('XYChart component', () => {
|
||||||
type: 'dataLayer',
|
type: 'dataLayer',
|
||||||
layerType: LayerTypes.DATA,
|
layerType: LayerTypes.DATA,
|
||||||
seriesType: 'line',
|
seriesType: 'line',
|
||||||
|
isPercentage: false,
|
||||||
|
isHorizontal: false,
|
||||||
|
isStacked: false,
|
||||||
xAccessor: 'c',
|
xAccessor: 'c',
|
||||||
accessors: ['a', 'b'],
|
accessors: ['a', 'b'],
|
||||||
showLines: true,
|
showLines: true,
|
||||||
|
@ -255,6 +258,9 @@ describe('XYChart component', () => {
|
||||||
layerType: LayerTypes.DATA,
|
layerType: LayerTypes.DATA,
|
||||||
showLines: true,
|
showLines: true,
|
||||||
seriesType: 'line',
|
seriesType: 'line',
|
||||||
|
isHorizontal: false,
|
||||||
|
isStacked: false,
|
||||||
|
isPercentage: false,
|
||||||
xAccessor: 'c',
|
xAccessor: 'c',
|
||||||
accessors: ['a', 'b'],
|
accessors: ['a', 'b'],
|
||||||
splitAccessor: 'd',
|
splitAccessor: 'd',
|
||||||
|
@ -339,7 +345,8 @@ describe('XYChart component', () => {
|
||||||
test('it should enable the new time axis for a stacked vertical bar with break down dimension', () => {
|
test('it should enable the new time axis for a stacked vertical bar with break down dimension', () => {
|
||||||
const timeLayer: DataLayerConfig = {
|
const timeLayer: DataLayerConfig = {
|
||||||
...defaultTimeLayer,
|
...defaultTimeLayer,
|
||||||
seriesType: 'bar_stacked',
|
seriesType: 'bar',
|
||||||
|
isStacked: true,
|
||||||
};
|
};
|
||||||
const timeLayerArgs = createArgsWithLayers([timeLayer]);
|
const timeLayerArgs = createArgsWithLayers([timeLayer]);
|
||||||
|
|
||||||
|
@ -514,11 +521,14 @@ describe('XYChart component', () => {
|
||||||
isHistogram: true,
|
isHistogram: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
xExtent: {
|
xAxisConfig: {
|
||||||
type: 'axisExtentConfig',
|
type: 'xAxisConfig',
|
||||||
mode: 'custom',
|
extent: {
|
||||||
lowerBound: 123,
|
type: 'axisExtentConfig',
|
||||||
upperBound: 456,
|
mode: 'custom',
|
||||||
|
lowerBound: 123,
|
||||||
|
upperBound: 456,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
@ -541,12 +551,18 @@ describe('XYChart component', () => {
|
||||||
{...defaultProps}
|
{...defaultProps}
|
||||||
args={{
|
args={{
|
||||||
...args,
|
...args,
|
||||||
yLeftExtent: {
|
yAxisConfigs: [
|
||||||
type: 'axisExtentConfig',
|
{
|
||||||
mode: 'custom',
|
type: 'yAxisConfig',
|
||||||
lowerBound: 123,
|
position: 'left',
|
||||||
upperBound: 456,
|
extent: {
|
||||||
},
|
type: 'axisExtentConfig',
|
||||||
|
mode: 'custom',
|
||||||
|
lowerBound: 123,
|
||||||
|
upperBound: 456,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -564,10 +580,16 @@ describe('XYChart component', () => {
|
||||||
{...defaultProps}
|
{...defaultProps}
|
||||||
args={{
|
args={{
|
||||||
...args,
|
...args,
|
||||||
yLeftExtent: {
|
yAxisConfigs: [
|
||||||
type: 'axisExtentConfig',
|
{
|
||||||
mode: 'dataBounds',
|
type: 'yAxisConfig',
|
||||||
},
|
position: 'left',
|
||||||
|
extent: {
|
||||||
|
type: 'axisExtentConfig',
|
||||||
|
mode: 'dataBounds',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -585,10 +607,16 @@ describe('XYChart component', () => {
|
||||||
{...defaultProps}
|
{...defaultProps}
|
||||||
args={{
|
args={{
|
||||||
...args,
|
...args,
|
||||||
yLeftExtent: {
|
yAxisConfigs: [
|
||||||
type: 'axisExtentConfig',
|
{
|
||||||
mode: 'dataBounds',
|
type: 'yAxisConfig',
|
||||||
},
|
position: 'left',
|
||||||
|
extent: {
|
||||||
|
type: 'axisExtentConfig',
|
||||||
|
mode: 'dataBounds',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
layers: [
|
layers: [
|
||||||
{
|
{
|
||||||
...(args.layers[0] as DataLayerConfig),
|
...(args.layers[0] as DataLayerConfig),
|
||||||
|
@ -612,16 +640,16 @@ describe('XYChart component', () => {
|
||||||
{...defaultProps}
|
{...defaultProps}
|
||||||
args={{
|
args={{
|
||||||
...args,
|
...args,
|
||||||
yLeftExtent: {
|
yAxisConfigs: [
|
||||||
type: 'axisExtentConfig',
|
|
||||||
mode: 'custom',
|
|
||||||
lowerBound: 123,
|
|
||||||
upperBound: 456,
|
|
||||||
},
|
|
||||||
layers: [
|
|
||||||
{
|
{
|
||||||
...(args.layers[0] as DataLayerConfig),
|
type: 'yAxisConfig',
|
||||||
seriesType: 'bar',
|
position: 'left',
|
||||||
|
extent: {
|
||||||
|
type: 'axisExtentConfig',
|
||||||
|
mode: 'custom',
|
||||||
|
lowerBound: 123,
|
||||||
|
upperBound: 456,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}}
|
}}
|
||||||
|
@ -629,8 +657,8 @@ describe('XYChart component', () => {
|
||||||
);
|
);
|
||||||
expect(component.find(Axis).find('[id="left"]').prop('domain')).toEqual({
|
expect(component.find(Axis).find('[id="left"]').prop('domain')).toEqual({
|
||||||
fit: false,
|
fit: false,
|
||||||
min: NaN,
|
min: 123,
|
||||||
max: NaN,
|
max: 456,
|
||||||
includeDataFromIds: [],
|
includeDataFromIds: [],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -901,7 +929,9 @@ describe('XYChart component', () => {
|
||||||
{...defaultProps}
|
{...defaultProps}
|
||||||
args={{
|
args={{
|
||||||
...args,
|
...args,
|
||||||
layers: [{ ...(args.layers[0] as DataLayerConfig), seriesType: 'bar_horizontal' }],
|
layers: [
|
||||||
|
{ ...(args.layers[0] as DataLayerConfig), isHorizontal: true, seriesType: 'bar' },
|
||||||
|
],
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -1020,7 +1050,10 @@ describe('XYChart component', () => {
|
||||||
xAccessor: 'xAccessorId',
|
xAccessor: 'xAccessorId',
|
||||||
xScaleType: 'linear',
|
xScaleType: 'linear',
|
||||||
isHistogram: true,
|
isHistogram: true,
|
||||||
seriesType: 'bar_stacked',
|
isHorizontal: false,
|
||||||
|
isStacked: true,
|
||||||
|
seriesType: 'bar',
|
||||||
|
isPercentage: false,
|
||||||
accessors: ['yAccessorId'],
|
accessors: ['yAccessorId'],
|
||||||
palette: mockPaletteOutput,
|
palette: mockPaletteOutput,
|
||||||
table: numberHistogramData,
|
table: numberHistogramData,
|
||||||
|
@ -1091,8 +1124,11 @@ describe('XYChart component', () => {
|
||||||
type: 'dataLayer',
|
type: 'dataLayer',
|
||||||
layerType: LayerTypes.DATA,
|
layerType: LayerTypes.DATA,
|
||||||
isHistogram: true,
|
isHistogram: true,
|
||||||
|
seriesType: 'bar',
|
||||||
|
isStacked: true,
|
||||||
|
isHorizontal: false,
|
||||||
|
isPercentage: false,
|
||||||
showLines: true,
|
showLines: true,
|
||||||
seriesType: 'bar_stacked',
|
|
||||||
xAccessor: 'b',
|
xAccessor: 'b',
|
||||||
xScaleType: 'time',
|
xScaleType: 'time',
|
||||||
splitAccessor: 'b',
|
splitAccessor: 'b',
|
||||||
|
@ -1218,7 +1254,10 @@ describe('XYChart component', () => {
|
||||||
xAccessor: 'xAccessorId',
|
xAccessor: 'xAccessorId',
|
||||||
xScaleType: 'linear',
|
xScaleType: 'linear',
|
||||||
isHistogram: true,
|
isHistogram: true,
|
||||||
seriesType: 'bar_stacked',
|
isPercentage: false,
|
||||||
|
seriesType: 'bar',
|
||||||
|
isStacked: true,
|
||||||
|
isHorizontal: false,
|
||||||
accessors: ['yAccessorId'],
|
accessors: ['yAccessorId'],
|
||||||
palette: mockPaletteOutput,
|
palette: mockPaletteOutput,
|
||||||
table: numberHistogramData,
|
table: numberHistogramData,
|
||||||
|
@ -1291,6 +1330,9 @@ describe('XYChart component', () => {
|
||||||
type: 'dataLayer',
|
type: 'dataLayer',
|
||||||
layerType: LayerTypes.DATA,
|
layerType: LayerTypes.DATA,
|
||||||
seriesType: 'line',
|
seriesType: 'line',
|
||||||
|
isHorizontal: false,
|
||||||
|
isStacked: false,
|
||||||
|
isPercentage: false,
|
||||||
showLines: true,
|
showLines: true,
|
||||||
xAccessor: 'd',
|
xAccessor: 'd',
|
||||||
accessors: ['a', 'b'],
|
accessors: ['a', 'b'],
|
||||||
|
@ -1351,6 +1393,9 @@ describe('XYChart component', () => {
|
||||||
layerType: LayerTypes.DATA,
|
layerType: LayerTypes.DATA,
|
||||||
showLines: true,
|
showLines: true,
|
||||||
seriesType: 'line',
|
seriesType: 'line',
|
||||||
|
isHorizontal: false,
|
||||||
|
isStacked: false,
|
||||||
|
isPercentage: false,
|
||||||
xAccessor: 'd',
|
xAccessor: 'd',
|
||||||
accessors: ['a', 'b'],
|
accessors: ['a', 'b'],
|
||||||
columnToLabel: '{"a": "Label A", "b": "Label B", "d": "Label D"}',
|
columnToLabel: '{"a": "Label A", "b": "Label B", "d": "Label D"}',
|
||||||
|
@ -1382,6 +1427,9 @@ describe('XYChart component', () => {
|
||||||
layerType: LayerTypes.DATA,
|
layerType: LayerTypes.DATA,
|
||||||
showLines: true,
|
showLines: true,
|
||||||
seriesType: 'line',
|
seriesType: 'line',
|
||||||
|
isHorizontal: false,
|
||||||
|
isStacked: false,
|
||||||
|
isPercentage: false,
|
||||||
xAccessor: 'd',
|
xAccessor: 'd',
|
||||||
accessors: ['a', 'b'],
|
accessors: ['a', 'b'],
|
||||||
columnToLabel: '{"a": "Label A", "b": "Label B", "d": "Label D"}',
|
columnToLabel: '{"a": "Label A", "b": "Label B", "d": "Label D"}',
|
||||||
|
@ -1421,7 +1469,7 @@ describe('XYChart component', () => {
|
||||||
{...defaultProps}
|
{...defaultProps}
|
||||||
args={{
|
args={{
|
||||||
...args,
|
...args,
|
||||||
layers: [{ ...(args.layers[0] as DataLayerConfig), seriesType: 'bar_stacked' }],
|
layers: [{ ...(args.layers[0] as DataLayerConfig), seriesType: 'bar', isStacked: true }],
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -1440,7 +1488,7 @@ describe('XYChart component', () => {
|
||||||
{...defaultProps}
|
{...defaultProps}
|
||||||
args={{
|
args={{
|
||||||
...args,
|
...args,
|
||||||
layers: [{ ...(args.layers[0] as DataLayerConfig), seriesType: 'area_stacked' }],
|
layers: [{ ...(args.layers[0] as DataLayerConfig), seriesType: 'area', isStacked: true }],
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -1460,7 +1508,12 @@ describe('XYChart component', () => {
|
||||||
args={{
|
args={{
|
||||||
...args,
|
...args,
|
||||||
layers: [
|
layers: [
|
||||||
{ ...(args.layers[0] as DataLayerConfig), seriesType: 'bar_horizontal_stacked' },
|
{
|
||||||
|
...(args.layers[0] as DataLayerConfig),
|
||||||
|
seriesType: 'bar',
|
||||||
|
isStacked: true,
|
||||||
|
isHorizontal: true,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
@ -1487,7 +1540,8 @@ describe('XYChart component', () => {
|
||||||
...(args.layers[0] as DataLayerConfig),
|
...(args.layers[0] as DataLayerConfig),
|
||||||
xAccessor: undefined,
|
xAccessor: undefined,
|
||||||
splitAccessor: 'e',
|
splitAccessor: 'e',
|
||||||
seriesType: 'bar_stacked',
|
seriesType: 'bar',
|
||||||
|
isStacked: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}}
|
}}
|
||||||
|
@ -1574,7 +1628,8 @@ describe('XYChart component', () => {
|
||||||
layers: [
|
layers: [
|
||||||
{
|
{
|
||||||
...(args.layers[0] as DataLayerConfig),
|
...(args.layers[0] as DataLayerConfig),
|
||||||
seriesType: 'bar_stacked',
|
seriesType: 'bar',
|
||||||
|
isStacked: true,
|
||||||
isHistogram: true,
|
isHistogram: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -1630,21 +1685,33 @@ describe('XYChart component', () => {
|
||||||
{
|
{
|
||||||
...layer,
|
...layer,
|
||||||
accessors: ['a', 'b'],
|
accessors: ['a', 'b'],
|
||||||
yConfig: [
|
decorations: [
|
||||||
{
|
{
|
||||||
type: 'yConfig',
|
type: 'dataDecorationConfig',
|
||||||
forAccessor: 'a',
|
forAccessor: 'a',
|
||||||
axisMode: 'left',
|
axisId: '1',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'yConfig',
|
type: 'dataDecorationConfig',
|
||||||
forAccessor: 'b',
|
forAccessor: 'b',
|
||||||
axisMode: 'right',
|
axisId: '2',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
table: dataWithoutFormats,
|
table: dataWithoutFormats,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
yAxisConfigs: [
|
||||||
|
{
|
||||||
|
type: 'yAxisConfig',
|
||||||
|
id: '1',
|
||||||
|
position: 'left',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'yAxisConfig',
|
||||||
|
id: '2',
|
||||||
|
position: 'right',
|
||||||
|
},
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
const component = getRenderedComponent(newArgs);
|
const component = getRenderedComponent(newArgs);
|
||||||
|
@ -1684,21 +1751,28 @@ describe('XYChart component', () => {
|
||||||
{
|
{
|
||||||
...layer,
|
...layer,
|
||||||
accessors: ['c', 'd'],
|
accessors: ['c', 'd'],
|
||||||
yConfig: [
|
decorations: [
|
||||||
{
|
{
|
||||||
type: 'yConfig',
|
type: 'dataDecorationConfig',
|
||||||
forAccessor: 'c',
|
forAccessor: 'c',
|
||||||
axisMode: 'left',
|
axisId: '1',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'yConfig',
|
type: 'dataDecorationConfig',
|
||||||
forAccessor: 'd',
|
forAccessor: 'd',
|
||||||
axisMode: 'left',
|
axisId: '1',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
table: dataWithoutFormats,
|
table: dataWithoutFormats,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
yAxisConfigs: [
|
||||||
|
{
|
||||||
|
type: 'yAxisConfig',
|
||||||
|
id: '1',
|
||||||
|
position: 'left',
|
||||||
|
},
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
const component = getRenderedComponent(newArgs);
|
const component = getRenderedComponent(newArgs);
|
||||||
|
@ -1720,14 +1794,14 @@ describe('XYChart component', () => {
|
||||||
type: 'extendedDataLayer',
|
type: 'extendedDataLayer',
|
||||||
accessors: ['a', 'b'],
|
accessors: ['a', 'b'],
|
||||||
splitAccessor: undefined,
|
splitAccessor: undefined,
|
||||||
yConfig: [
|
decorations: [
|
||||||
{
|
{
|
||||||
type: 'yConfig',
|
type: 'dataDecorationConfig',
|
||||||
forAccessor: 'a',
|
forAccessor: 'a',
|
||||||
color: '#550000',
|
color: '#550000',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'yConfig',
|
type: 'dataDecorationConfig',
|
||||||
forAccessor: 'b',
|
forAccessor: 'b',
|
||||||
color: '#FFFF00',
|
color: '#FFFF00',
|
||||||
},
|
},
|
||||||
|
@ -1739,9 +1813,9 @@ describe('XYChart component', () => {
|
||||||
type: 'extendedDataLayer',
|
type: 'extendedDataLayer',
|
||||||
accessors: ['c'],
|
accessors: ['c'],
|
||||||
splitAccessor: undefined,
|
splitAccessor: undefined,
|
||||||
yConfig: [
|
decorations: [
|
||||||
{
|
{
|
||||||
type: 'yConfig',
|
type: 'dataDecorationConfig',
|
||||||
forAccessor: 'c',
|
forAccessor: 'c',
|
||||||
color: '#FEECDF',
|
color: '#FEECDF',
|
||||||
},
|
},
|
||||||
|
@ -1772,16 +1846,16 @@ describe('XYChart component', () => {
|
||||||
})
|
})
|
||||||
).toEqual('#FEECDF');
|
).toEqual('#FEECDF');
|
||||||
});
|
});
|
||||||
test('color is not applied to chart when splitAccessor is defined or when yConfig is not configured', () => {
|
test('color is not applied to chart when splitAccessor is defined or when decorations is not configured', () => {
|
||||||
const newArgs: XYProps = {
|
const newArgs: XYProps = {
|
||||||
...args,
|
...args,
|
||||||
layers: [
|
layers: [
|
||||||
{
|
{
|
||||||
...layer,
|
...layer,
|
||||||
accessors: ['a'],
|
accessors: ['a'],
|
||||||
yConfig: [
|
decorations: [
|
||||||
{
|
{
|
||||||
type: 'yConfig',
|
type: 'dataDecorationConfig',
|
||||||
forAccessor: 'a',
|
forAccessor: 'a',
|
||||||
color: '#550000',
|
color: '#550000',
|
||||||
},
|
},
|
||||||
|
@ -2067,7 +2141,14 @@ describe('XYChart component', () => {
|
||||||
{...defaultProps}
|
{...defaultProps}
|
||||||
args={{
|
args={{
|
||||||
...args,
|
...args,
|
||||||
yLeftScale: 'sqrt',
|
yAxisConfigs: [
|
||||||
|
{
|
||||||
|
type: 'yAxisConfig',
|
||||||
|
position: 'left',
|
||||||
|
showLabels: true,
|
||||||
|
scaleType: 'sqrt',
|
||||||
|
},
|
||||||
|
],
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -2115,11 +2196,24 @@ describe('XYChart component', () => {
|
||||||
test('it should set the tickLabel visibility on the x axis if the tick labels is hidden', () => {
|
test('it should set the tickLabel visibility on the x axis if the tick labels is hidden', () => {
|
||||||
const { args } = sampleArgs();
|
const { args } = sampleArgs();
|
||||||
|
|
||||||
args.tickLabelsVisibilitySettings = {
|
args.yAxisConfigs = [
|
||||||
x: false,
|
{
|
||||||
yLeft: true,
|
type: 'yAxisConfig',
|
||||||
yRight: true,
|
position: 'left',
|
||||||
type: 'tickLabelsConfig',
|
showLabels: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'yAxisConfig',
|
||||||
|
position: 'right',
|
||||||
|
showLabels: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
args.xAxisConfig = {
|
||||||
|
type: 'xAxisConfig',
|
||||||
|
id: 'x',
|
||||||
|
showLabels: false,
|
||||||
|
position: 'bottom',
|
||||||
};
|
};
|
||||||
|
|
||||||
const instance = shallow(<XYChart {...defaultProps} args={{ ...args }} />);
|
const instance = shallow(<XYChart {...defaultProps} args={{ ...args }} />);
|
||||||
|
@ -2136,12 +2230,18 @@ describe('XYChart component', () => {
|
||||||
test('it should set the tickLabel visibility on the y axis if the tick labels is hidden', () => {
|
test('it should set the tickLabel visibility on the y axis if the tick labels is hidden', () => {
|
||||||
const { args } = sampleArgs();
|
const { args } = sampleArgs();
|
||||||
|
|
||||||
args.tickLabelsVisibilitySettings = {
|
args.yAxisConfigs = [
|
||||||
x: true,
|
{
|
||||||
yLeft: false,
|
type: 'yAxisConfig',
|
||||||
yRight: false,
|
position: 'left',
|
||||||
type: 'tickLabelsConfig',
|
showLabels: false,
|
||||||
};
|
},
|
||||||
|
{
|
||||||
|
type: 'yAxisConfig',
|
||||||
|
position: 'right',
|
||||||
|
showLabels: false,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
const instance = shallow(<XYChart {...defaultProps} args={{ ...args }} />);
|
const instance = shallow(<XYChart {...defaultProps} args={{ ...args }} />);
|
||||||
|
|
||||||
|
@ -2157,11 +2257,24 @@ describe('XYChart component', () => {
|
||||||
test('it should set the tickLabel visibility on the x axis if the tick labels is shown', () => {
|
test('it should set the tickLabel visibility on the x axis if the tick labels is shown', () => {
|
||||||
const { args } = sampleArgs();
|
const { args } = sampleArgs();
|
||||||
|
|
||||||
args.tickLabelsVisibilitySettings = {
|
args.yAxisConfigs = [
|
||||||
x: true,
|
{
|
||||||
yLeft: true,
|
type: 'yAxisConfig',
|
||||||
yRight: true,
|
position: 'left',
|
||||||
type: 'tickLabelsConfig',
|
showLabels: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'yAxisConfig',
|
||||||
|
position: 'right',
|
||||||
|
showLabels: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
args.xAxisConfig = {
|
||||||
|
type: 'xAxisConfig',
|
||||||
|
id: 'x',
|
||||||
|
showLabels: true,
|
||||||
|
position: 'bottom',
|
||||||
};
|
};
|
||||||
|
|
||||||
const instance = shallow(<XYChart {...defaultProps} args={{ ...args }} />);
|
const instance = shallow(<XYChart {...defaultProps} args={{ ...args }} />);
|
||||||
|
@ -2178,11 +2291,25 @@ describe('XYChart component', () => {
|
||||||
test('it should set the tickLabel orientation on the x axis', () => {
|
test('it should set the tickLabel orientation on the x axis', () => {
|
||||||
const { args } = sampleArgs();
|
const { args } = sampleArgs();
|
||||||
|
|
||||||
args.labelsOrientation = {
|
args.yAxisConfigs = [
|
||||||
x: -45,
|
{
|
||||||
yLeft: 0,
|
type: 'yAxisConfig',
|
||||||
yRight: -90,
|
position: 'left',
|
||||||
type: 'labelsOrientationConfig',
|
labelsOrientation: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'yAxisConfig',
|
||||||
|
position: 'right',
|
||||||
|
labelsOrientation: -90,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
args.xAxisConfig = {
|
||||||
|
type: 'xAxisConfig',
|
||||||
|
id: 'x',
|
||||||
|
showLabels: true,
|
||||||
|
labelsOrientation: -45,
|
||||||
|
position: 'bottom',
|
||||||
};
|
};
|
||||||
|
|
||||||
const instance = shallow(<XYChart {...defaultProps} args={{ ...args }} />);
|
const instance = shallow(<XYChart {...defaultProps} args={{ ...args }} />);
|
||||||
|
@ -2199,11 +2326,24 @@ describe('XYChart component', () => {
|
||||||
test('it should set the tickLabel visibility on the y axis if the tick labels is shown', () => {
|
test('it should set the tickLabel visibility on the y axis if the tick labels is shown', () => {
|
||||||
const { args } = sampleArgs();
|
const { args } = sampleArgs();
|
||||||
|
|
||||||
args.tickLabelsVisibilitySettings = {
|
args.yAxisConfigs = [
|
||||||
x: false,
|
{
|
||||||
yLeft: true,
|
type: 'yAxisConfig',
|
||||||
yRight: true,
|
position: 'left',
|
||||||
type: 'tickLabelsConfig',
|
showLabels: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'yAxisConfig',
|
||||||
|
position: 'right',
|
||||||
|
showLabels: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
args.xAxisConfig = {
|
||||||
|
type: 'xAxisConfig',
|
||||||
|
id: 'x',
|
||||||
|
showLabels: true,
|
||||||
|
position: 'bottom',
|
||||||
};
|
};
|
||||||
|
|
||||||
const instance = shallow(<XYChart {...defaultProps} args={{ ...args }} />);
|
const instance = shallow(<XYChart {...defaultProps} args={{ ...args }} />);
|
||||||
|
@ -2220,11 +2360,25 @@ describe('XYChart component', () => {
|
||||||
test('it should set the tickLabel orientation on the y axis', () => {
|
test('it should set the tickLabel orientation on the y axis', () => {
|
||||||
const { args } = sampleArgs();
|
const { args } = sampleArgs();
|
||||||
|
|
||||||
args.labelsOrientation = {
|
args.yAxisConfigs = [
|
||||||
x: -45,
|
{
|
||||||
yLeft: -90,
|
type: 'yAxisConfig',
|
||||||
yRight: -90,
|
position: 'left',
|
||||||
type: 'labelsOrientationConfig',
|
labelsOrientation: -90,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'yAxisConfig',
|
||||||
|
position: 'right',
|
||||||
|
labelsOrientation: -90,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
args.xAxisConfig = {
|
||||||
|
type: 'xAxisConfig',
|
||||||
|
id: 'x',
|
||||||
|
showLabels: true,
|
||||||
|
labelsOrientation: -45,
|
||||||
|
position: 'bottom',
|
||||||
};
|
};
|
||||||
|
|
||||||
const instance = shallow(<XYChart {...defaultProps} args={{ ...args }} />);
|
const instance = shallow(<XYChart {...defaultProps} args={{ ...args }} />);
|
||||||
|
@ -2266,43 +2420,47 @@ describe('XYChart component', () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const args: XYProps = {
|
const args: XYProps = {
|
||||||
xTitle: '',
|
|
||||||
yTitle: '',
|
|
||||||
yRightTitle: '',
|
|
||||||
yLeftScale: 'linear',
|
|
||||||
yRightScale: 'linear',
|
|
||||||
showTooltip: true,
|
showTooltip: true,
|
||||||
legend: { type: 'legendConfig', isVisible: false, position: Position.Top },
|
legend: { type: 'legendConfig', isVisible: false, position: Position.Top },
|
||||||
valueLabels: 'hide',
|
valueLabels: 'hide',
|
||||||
tickLabelsVisibilitySettings: {
|
yAxisConfigs: [
|
||||||
type: 'tickLabelsConfig',
|
{
|
||||||
x: true,
|
type: 'yAxisConfig',
|
||||||
yLeft: true,
|
position: 'left',
|
||||||
yRight: true,
|
labelsOrientation: 0,
|
||||||
},
|
showGridLines: false,
|
||||||
gridlinesVisibilitySettings: {
|
showLabels: true,
|
||||||
type: 'gridlinesConfig',
|
title: '',
|
||||||
x: true,
|
extent: {
|
||||||
yLeft: false,
|
mode: 'full',
|
||||||
yRight: false,
|
type: 'axisExtentConfig',
|
||||||
},
|
},
|
||||||
labelsOrientation: {
|
},
|
||||||
type: 'labelsOrientationConfig',
|
{
|
||||||
x: 0,
|
type: 'yAxisConfig',
|
||||||
yLeft: 0,
|
position: 'right',
|
||||||
yRight: 0,
|
labelsOrientation: 0,
|
||||||
},
|
showGridLines: false,
|
||||||
xExtent: {
|
showLabels: true,
|
||||||
mode: 'dataBounds',
|
title: '',
|
||||||
type: 'axisExtentConfig',
|
extent: {
|
||||||
},
|
mode: 'full',
|
||||||
yLeftExtent: {
|
type: 'axisExtentConfig',
|
||||||
mode: 'full',
|
},
|
||||||
type: 'axisExtentConfig',
|
},
|
||||||
},
|
],
|
||||||
yRightExtent: {
|
xAxisConfig: {
|
||||||
mode: 'full',
|
type: 'xAxisConfig',
|
||||||
type: 'axisExtentConfig',
|
id: 'x',
|
||||||
|
title: '',
|
||||||
|
showLabels: true,
|
||||||
|
showGridLines: true,
|
||||||
|
labelsOrientation: 0,
|
||||||
|
position: 'bottom',
|
||||||
|
extent: {
|
||||||
|
mode: 'dataBounds',
|
||||||
|
type: 'axisExtentConfig',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
markSizeRatio: 1,
|
markSizeRatio: 1,
|
||||||
layers: [
|
layers: [
|
||||||
|
@ -2311,6 +2469,8 @@ describe('XYChart component', () => {
|
||||||
type: 'dataLayer',
|
type: 'dataLayer',
|
||||||
layerType: LayerTypes.DATA,
|
layerType: LayerTypes.DATA,
|
||||||
seriesType: 'line',
|
seriesType: 'line',
|
||||||
|
isStacked: false,
|
||||||
|
isHorizontal: false,
|
||||||
showLines: true,
|
showLines: true,
|
||||||
xAccessor: 'a',
|
xAccessor: 'a',
|
||||||
accessors: ['c'],
|
accessors: ['c'],
|
||||||
|
@ -2318,6 +2478,7 @@ describe('XYChart component', () => {
|
||||||
columnToLabel: '',
|
columnToLabel: '',
|
||||||
xScaleType: 'ordinal',
|
xScaleType: 'ordinal',
|
||||||
isHistogram: false,
|
isHistogram: false,
|
||||||
|
isPercentage: false,
|
||||||
palette: mockPaletteOutput,
|
palette: mockPaletteOutput,
|
||||||
table: data1,
|
table: data1,
|
||||||
},
|
},
|
||||||
|
@ -2333,6 +2494,9 @@ describe('XYChart component', () => {
|
||||||
columnToLabel: '',
|
columnToLabel: '',
|
||||||
xScaleType: 'ordinal',
|
xScaleType: 'ordinal',
|
||||||
isHistogram: false,
|
isHistogram: false,
|
||||||
|
isStacked: false,
|
||||||
|
isHorizontal: false,
|
||||||
|
isPercentage: false,
|
||||||
palette: mockPaletteOutput,
|
palette: mockPaletteOutput,
|
||||||
table: data2,
|
table: data2,
|
||||||
},
|
},
|
||||||
|
@ -2363,45 +2527,51 @@ describe('XYChart component', () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const args: XYProps = {
|
const args: XYProps = {
|
||||||
xTitle: '',
|
|
||||||
yTitle: '',
|
|
||||||
yRightTitle: '',
|
|
||||||
legend: { type: 'legendConfig', isVisible: false, position: Position.Top },
|
legend: { type: 'legendConfig', isVisible: false, position: Position.Top },
|
||||||
valueLabels: 'hide',
|
valueLabels: 'hide',
|
||||||
|
yAxisConfigs: [
|
||||||
|
{
|
||||||
|
type: 'yAxisConfig',
|
||||||
|
position: 'left',
|
||||||
|
labelsOrientation: 0,
|
||||||
|
showGridLines: false,
|
||||||
|
showLabels: false,
|
||||||
|
title: '',
|
||||||
|
scaleType: 'linear',
|
||||||
|
extent: {
|
||||||
|
mode: 'full',
|
||||||
|
type: 'axisExtentConfig',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'yAxisConfig',
|
||||||
|
position: 'right',
|
||||||
|
labelsOrientation: 0,
|
||||||
|
showGridLines: false,
|
||||||
|
showLabels: false,
|
||||||
|
scaleType: 'linear',
|
||||||
|
title: '',
|
||||||
|
extent: {
|
||||||
|
mode: 'full',
|
||||||
|
type: 'axisExtentConfig',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
xAxisConfig: {
|
||||||
|
type: 'xAxisConfig',
|
||||||
|
id: 'x',
|
||||||
|
title: '',
|
||||||
|
showLabels: true,
|
||||||
|
showGridLines: true,
|
||||||
|
labelsOrientation: 0,
|
||||||
|
position: 'bottom',
|
||||||
|
extent: {
|
||||||
|
mode: 'dataBounds',
|
||||||
|
type: 'axisExtentConfig',
|
||||||
|
},
|
||||||
|
},
|
||||||
showTooltip: true,
|
showTooltip: true,
|
||||||
tickLabelsVisibilitySettings: {
|
|
||||||
type: 'tickLabelsConfig',
|
|
||||||
x: true,
|
|
||||||
yLeft: false,
|
|
||||||
yRight: false,
|
|
||||||
},
|
|
||||||
gridlinesVisibilitySettings: {
|
|
||||||
type: 'gridlinesConfig',
|
|
||||||
x: true,
|
|
||||||
yLeft: false,
|
|
||||||
yRight: false,
|
|
||||||
},
|
|
||||||
labelsOrientation: {
|
|
||||||
type: 'labelsOrientationConfig',
|
|
||||||
x: 0,
|
|
||||||
yLeft: 0,
|
|
||||||
yRight: 0,
|
|
||||||
},
|
|
||||||
xExtent: {
|
|
||||||
mode: 'dataBounds',
|
|
||||||
type: 'axisExtentConfig',
|
|
||||||
},
|
|
||||||
yLeftExtent: {
|
|
||||||
mode: 'full',
|
|
||||||
type: 'axisExtentConfig',
|
|
||||||
},
|
|
||||||
yRightExtent: {
|
|
||||||
mode: 'full',
|
|
||||||
type: 'axisExtentConfig',
|
|
||||||
},
|
|
||||||
markSizeRatio: 1,
|
markSizeRatio: 1,
|
||||||
yLeftScale: 'linear',
|
|
||||||
yRightScale: 'linear',
|
|
||||||
layers: [
|
layers: [
|
||||||
{
|
{
|
||||||
layerId: 'first',
|
layerId: 'first',
|
||||||
|
@ -2415,6 +2585,9 @@ describe('XYChart component', () => {
|
||||||
columnToLabel: '',
|
columnToLabel: '',
|
||||||
xScaleType: 'ordinal',
|
xScaleType: 'ordinal',
|
||||||
isHistogram: false,
|
isHistogram: false,
|
||||||
|
isStacked: false,
|
||||||
|
isHorizontal: false,
|
||||||
|
isPercentage: false,
|
||||||
palette: mockPaletteOutput,
|
palette: mockPaletteOutput,
|
||||||
table: data,
|
table: data,
|
||||||
},
|
},
|
||||||
|
@ -2443,45 +2616,51 @@ describe('XYChart component', () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const args: XYProps = {
|
const args: XYProps = {
|
||||||
xTitle: '',
|
|
||||||
yTitle: '',
|
|
||||||
yRightTitle: '',
|
|
||||||
showTooltip: true,
|
showTooltip: true,
|
||||||
legend: { type: 'legendConfig', isVisible: true, position: Position.Top },
|
legend: { type: 'legendConfig', isVisible: true, position: Position.Top },
|
||||||
valueLabels: 'hide',
|
valueLabels: 'hide',
|
||||||
tickLabelsVisibilitySettings: {
|
yAxisConfigs: [
|
||||||
type: 'tickLabelsConfig',
|
{
|
||||||
x: true,
|
type: 'yAxisConfig',
|
||||||
yLeft: false,
|
position: 'left',
|
||||||
yRight: false,
|
labelsOrientation: 0,
|
||||||
},
|
showGridLines: false,
|
||||||
gridlinesVisibilitySettings: {
|
showLabels: false,
|
||||||
type: 'gridlinesConfig',
|
title: '',
|
||||||
x: true,
|
scaleType: 'linear',
|
||||||
yLeft: false,
|
extent: {
|
||||||
yRight: false,
|
mode: 'full',
|
||||||
},
|
type: 'axisExtentConfig',
|
||||||
labelsOrientation: {
|
},
|
||||||
type: 'labelsOrientationConfig',
|
},
|
||||||
x: 0,
|
{
|
||||||
yLeft: 0,
|
type: 'yAxisConfig',
|
||||||
yRight: 0,
|
position: 'right',
|
||||||
},
|
labelsOrientation: 0,
|
||||||
xExtent: {
|
showGridLines: false,
|
||||||
mode: 'dataBounds',
|
showLabels: false,
|
||||||
type: 'axisExtentConfig',
|
scaleType: 'linear',
|
||||||
},
|
title: '',
|
||||||
yLeftExtent: {
|
extent: {
|
||||||
mode: 'full',
|
mode: 'full',
|
||||||
type: 'axisExtentConfig',
|
type: 'axisExtentConfig',
|
||||||
},
|
},
|
||||||
yRightExtent: {
|
},
|
||||||
mode: 'full',
|
],
|
||||||
type: 'axisExtentConfig',
|
xAxisConfig: {
|
||||||
|
type: 'xAxisConfig',
|
||||||
|
id: 'x',
|
||||||
|
showLabels: true,
|
||||||
|
showGridLines: true,
|
||||||
|
labelsOrientation: 0,
|
||||||
|
title: '',
|
||||||
|
position: 'bottom',
|
||||||
|
extent: {
|
||||||
|
mode: 'dataBounds',
|
||||||
|
type: 'axisExtentConfig',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
markSizeRatio: 1,
|
markSizeRatio: 1,
|
||||||
yLeftScale: 'linear',
|
|
||||||
yRightScale: 'linear',
|
|
||||||
layers: [
|
layers: [
|
||||||
{
|
{
|
||||||
layerId: 'first',
|
layerId: 'first',
|
||||||
|
@ -2495,6 +2674,9 @@ describe('XYChart component', () => {
|
||||||
columnToLabel: '',
|
columnToLabel: '',
|
||||||
xScaleType: 'ordinal',
|
xScaleType: 'ordinal',
|
||||||
isHistogram: false,
|
isHistogram: false,
|
||||||
|
isStacked: false,
|
||||||
|
isHorizontal: false,
|
||||||
|
isPercentage: false,
|
||||||
palette: mockPaletteOutput,
|
palette: mockPaletteOutput,
|
||||||
table: data,
|
table: data,
|
||||||
},
|
},
|
||||||
|
@ -2631,7 +2813,7 @@ describe('XYChart component', () => {
|
||||||
{ ...sampleLayer, accessors: ['a'], table: data },
|
{ ...sampleLayer, accessors: ['a'], table: data },
|
||||||
{ ...sampleLayer, seriesType: 'bar', accessors: ['a'], table: data },
|
{ ...sampleLayer, seriesType: 'bar', accessors: ['a'], table: data },
|
||||||
{ ...sampleLayer, seriesType: 'area', accessors: ['a'], table: data },
|
{ ...sampleLayer, seriesType: 'area', accessors: ['a'], table: data },
|
||||||
{ ...sampleLayer, seriesType: 'area_stacked', accessors: ['a'], table: data },
|
{ ...sampleLayer, seriesType: 'area', isStacked: true, accessors: ['a'], table: data },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const component = shallow(
|
const component = shallow(
|
||||||
|
@ -2661,7 +2843,13 @@ describe('XYChart component', () => {
|
||||||
test('it should apply the xTitle if is specified', () => {
|
test('it should apply the xTitle if is specified', () => {
|
||||||
const { args } = sampleArgs();
|
const { args } = sampleArgs();
|
||||||
|
|
||||||
args.xTitle = 'My custom x-axis title';
|
args.xAxisConfig = {
|
||||||
|
type: 'xAxisConfig',
|
||||||
|
id: 'x',
|
||||||
|
showLabels: true,
|
||||||
|
title: 'My custom x-axis title',
|
||||||
|
position: 'bottom',
|
||||||
|
};
|
||||||
|
|
||||||
const component = shallow(<XYChart {...defaultProps} args={{ ...args }} />);
|
const component = shallow(<XYChart {...defaultProps} args={{ ...args }} />);
|
||||||
|
|
||||||
|
@ -2671,11 +2859,26 @@ describe('XYChart component', () => {
|
||||||
test('it should hide the X axis title if the corresponding switch is off', () => {
|
test('it should hide the X axis title if the corresponding switch is off', () => {
|
||||||
const { args } = sampleArgs();
|
const { args } = sampleArgs();
|
||||||
|
|
||||||
args.axisTitlesVisibilitySettings = {
|
args.yAxisConfigs = [
|
||||||
x: false,
|
{
|
||||||
yLeft: true,
|
type: 'yAxisConfig',
|
||||||
yRight: true,
|
position: 'left',
|
||||||
type: 'axisTitlesVisibilityConfig',
|
showTitle: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'yAxisConfig',
|
||||||
|
position: 'right',
|
||||||
|
showTitle: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
args.xAxisConfig = {
|
||||||
|
type: 'xAxisConfig',
|
||||||
|
id: 'x',
|
||||||
|
showLabels: true,
|
||||||
|
showTitle: false,
|
||||||
|
title: 'My custom x-axis title',
|
||||||
|
position: 'bottom',
|
||||||
};
|
};
|
||||||
|
|
||||||
const component = shallow(<XYChart {...defaultProps} args={{ ...args }} />);
|
const component = shallow(<XYChart {...defaultProps} args={{ ...args }} />);
|
||||||
|
@ -2692,11 +2895,26 @@ describe('XYChart component', () => {
|
||||||
test('it should show the X axis gridlines if the setting is on', () => {
|
test('it should show the X axis gridlines if the setting is on', () => {
|
||||||
const { args } = sampleArgs();
|
const { args } = sampleArgs();
|
||||||
|
|
||||||
args.gridlinesVisibilitySettings = {
|
args.yAxisConfigs = [
|
||||||
x: true,
|
{
|
||||||
yLeft: false,
|
type: 'yAxisConfig',
|
||||||
yRight: false,
|
position: 'left',
|
||||||
type: 'gridlinesConfig',
|
showGridLines: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'yAxisConfig',
|
||||||
|
position: 'right',
|
||||||
|
showGridLines: false,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
args.xAxisConfig = {
|
||||||
|
type: 'xAxisConfig',
|
||||||
|
id: 'x',
|
||||||
|
showLabels: true,
|
||||||
|
showGridLines: true,
|
||||||
|
title: 'My custom x-axis title',
|
||||||
|
position: 'bottom',
|
||||||
};
|
};
|
||||||
|
|
||||||
const component = shallow(<XYChart {...defaultProps} args={{ ...args }} />);
|
const component = shallow(<XYChart {...defaultProps} args={{ ...args }} />);
|
||||||
|
@ -2741,10 +2959,13 @@ describe('XYChart component', () => {
|
||||||
layerType: LayerTypes.DATA,
|
layerType: LayerTypes.DATA,
|
||||||
showLines: true,
|
showLines: true,
|
||||||
seriesType: 'line',
|
seriesType: 'line',
|
||||||
|
isStacked: false,
|
||||||
|
isHorizontal: false,
|
||||||
xAccessor: 'c',
|
xAccessor: 'c',
|
||||||
accessors: ['a', 'b'],
|
accessors: ['a', 'b'],
|
||||||
xScaleType: 'ordinal',
|
xScaleType: 'ordinal',
|
||||||
isHistogram: false,
|
isHistogram: false,
|
||||||
|
isPercentage: false,
|
||||||
palette: mockPaletteOutput,
|
palette: mockPaletteOutput,
|
||||||
table: data,
|
table: data,
|
||||||
};
|
};
|
||||||
|
|
|
@ -47,20 +47,21 @@ import type { FilterEvent, BrushEvent, FormatFactory } from '../types';
|
||||||
import { isTimeChart } from '../../common/helpers';
|
import { isTimeChart } from '../../common/helpers';
|
||||||
import type {
|
import type {
|
||||||
CommonXYDataLayerConfig,
|
CommonXYDataLayerConfig,
|
||||||
ExtendedYConfig,
|
ReferenceLineDecorationConfig,
|
||||||
ReferenceLineYConfig,
|
ExtendedReferenceLineDecorationConfig,
|
||||||
SeriesType,
|
|
||||||
XYChartProps,
|
XYChartProps,
|
||||||
|
AxisExtentConfigResult,
|
||||||
} from '../../common/types';
|
} from '../../common/types';
|
||||||
import {
|
import {
|
||||||
isHorizontalChart,
|
isHorizontalChart,
|
||||||
getAnnotationsLayers,
|
getAnnotationsLayers,
|
||||||
getDataLayers,
|
getDataLayers,
|
||||||
Series,
|
AxisConfiguration,
|
||||||
|
getAxisPosition,
|
||||||
getFormattedTablesByLayers,
|
getFormattedTablesByLayers,
|
||||||
getLayersFormats,
|
getLayersFormats,
|
||||||
getLayersTitles,
|
getLayersTitles,
|
||||||
isReferenceLineYConfig,
|
isReferenceLineDecorationConfig,
|
||||||
getFilteredLayers,
|
getFilteredLayers,
|
||||||
getReferenceLayers,
|
getReferenceLayers,
|
||||||
isDataLayer,
|
isDataLayer,
|
||||||
|
@ -68,10 +69,16 @@ import {
|
||||||
GroupsConfiguration,
|
GroupsConfiguration,
|
||||||
getLinesCausedPaddings,
|
getLinesCausedPaddings,
|
||||||
validateExtent,
|
validateExtent,
|
||||||
|
Series,
|
||||||
|
getOriginalAxisPosition,
|
||||||
} from '../helpers';
|
} from '../helpers';
|
||||||
import { getXDomain, XyEndzones } from './x_domain';
|
import { getXDomain, XyEndzones } from './x_domain';
|
||||||
import { getLegendAction } from './legend_action';
|
import { getLegendAction } from './legend_action';
|
||||||
import { ReferenceLines, computeChartMargins } from './reference_lines';
|
import {
|
||||||
|
ReferenceLines,
|
||||||
|
computeChartMargins,
|
||||||
|
getAxisGroupForReferenceLine,
|
||||||
|
} from './reference_lines';
|
||||||
import { visualizationDefinitions } from '../definitions';
|
import { visualizationDefinitions } from '../definitions';
|
||||||
import { CommonXYLayerConfig } from '../../common/types';
|
import { CommonXYLayerConfig } from '../../common/types';
|
||||||
import { SplitChart } from './split_chart';
|
import { SplitChart } from './split_chart';
|
||||||
|
@ -138,8 +145,16 @@ function getValueLabelsStyling(isHorizontal: boolean): {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function getIconForSeriesType(seriesType: SeriesType): IconType {
|
function getIconForSeriesType(layer: CommonXYDataLayerConfig): IconType {
|
||||||
return visualizationDefinitions.find((c) => c.id === seriesType)!.icon || 'empty';
|
return (
|
||||||
|
visualizationDefinitions.find(
|
||||||
|
(c) =>
|
||||||
|
c.id ===
|
||||||
|
`${layer.seriesType}${layer.isHorizontal ? '_horizontal' : ''}${
|
||||||
|
layer.isPercentage ? '_percentage' : ''
|
||||||
|
}${layer.isStacked ? '_stacked' : ''}`
|
||||||
|
)!.icon || 'empty'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const XYChartReportable = React.memo(XYChart);
|
export const XYChartReportable = React.memo(XYChart);
|
||||||
|
@ -166,15 +181,11 @@ export function XYChart({
|
||||||
fittingFunction,
|
fittingFunction,
|
||||||
endValue,
|
endValue,
|
||||||
emphasizeFitting,
|
emphasizeFitting,
|
||||||
gridlinesVisibilitySettings,
|
|
||||||
valueLabels,
|
valueLabels,
|
||||||
hideEndzones,
|
hideEndzones,
|
||||||
xExtent,
|
|
||||||
yLeftExtent,
|
|
||||||
yRightExtent,
|
|
||||||
valuesInLegend,
|
valuesInLegend,
|
||||||
yLeftScale,
|
yAxisConfigs,
|
||||||
yRightScale,
|
xAxisConfig,
|
||||||
splitColumnAccessor,
|
splitColumnAccessor,
|
||||||
splitRowAccessor,
|
splitRowAccessor,
|
||||||
} = args;
|
} = args;
|
||||||
|
@ -204,9 +215,7 @@ export function XYChart({
|
||||||
);
|
);
|
||||||
|
|
||||||
if (dataLayers.length === 0) {
|
if (dataLayers.length === 0) {
|
||||||
const icon: IconType = getIconForSeriesType(
|
const icon: IconType = getIconForSeriesType(getDataLayers(layers)?.[0]);
|
||||||
getDataLayers(layers)?.[0]?.seriesType || SeriesTypes.BAR
|
|
||||||
);
|
|
||||||
return <EmptyPlaceholder className="xyChart__empty" icon={icon} />;
|
return <EmptyPlaceholder className="xyChart__empty" icon={icon} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,37 +245,35 @@ export function XYChart({
|
||||||
shouldRotate,
|
shouldRotate,
|
||||||
formatFactory,
|
formatFactory,
|
||||||
fieldFormats,
|
fieldFormats,
|
||||||
yLeftScale,
|
yAxisConfigs
|
||||||
yRightScale
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const xTitle = args.xTitle || (xAxisColumn && xAxisColumn.name);
|
const axesConfiguration = getAxesConfiguration(
|
||||||
|
dataLayers,
|
||||||
|
shouldRotate,
|
||||||
|
formatFactory,
|
||||||
|
fieldFormats,
|
||||||
|
[...(yAxisConfigs ?? []), ...(xAxisConfig ? [xAxisConfig] : [])]
|
||||||
|
);
|
||||||
|
|
||||||
|
const xTitle = xAxisConfig?.title || (xAxisColumn && xAxisColumn.name);
|
||||||
const yAxesMap = {
|
const yAxesMap = {
|
||||||
left: yAxesConfiguration.find(({ groupId }) => groupId === 'left'),
|
left: yAxesConfiguration.find(
|
||||||
right: yAxesConfiguration.find(({ groupId }) => groupId === 'right'),
|
({ position }) => position === getAxisPosition(Position.Left, shouldRotate)
|
||||||
|
),
|
||||||
|
right: yAxesConfiguration.find(
|
||||||
|
({ position }) => position === getAxisPosition(Position.Right, shouldRotate)
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
const titles = getLayersTitles(
|
const titles = getLayersTitles(
|
||||||
dataLayers,
|
dataLayers,
|
||||||
{ splitColumnAccessor, splitRowAccessor },
|
{ splitColumnAccessor, splitRowAccessor },
|
||||||
{ xTitle: args.xTitle, yTitle: args.yTitle, yRightTitle: args.yRightTitle },
|
{ xTitle },
|
||||||
yAxesConfiguration
|
yAxesConfiguration
|
||||||
);
|
);
|
||||||
|
|
||||||
const axisTitlesVisibilitySettings = args.axisTitlesVisibilitySettings || {
|
const filteredBarLayers = dataLayers.filter(({ seriesType }) => seriesType === SeriesTypes.BAR);
|
||||||
x: true,
|
|
||||||
yLeft: true,
|
|
||||||
yRight: true,
|
|
||||||
};
|
|
||||||
const tickLabelsVisibilitySettings = args.tickLabelsVisibilitySettings || {
|
|
||||||
x: true,
|
|
||||||
yLeft: true,
|
|
||||||
yRight: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
const labelsOrientation = args.labelsOrientation || { x: 0, yLeft: 0, yRight: 0 };
|
|
||||||
|
|
||||||
const filteredBarLayers = dataLayers.filter((layer) => layer.seriesType.includes('bar'));
|
|
||||||
|
|
||||||
const chartHasMoreThanOneBarSeries =
|
const chartHasMoreThanOneBarSeries =
|
||||||
filteredBarLayers.length > 1 ||
|
filteredBarLayers.length > 1 ||
|
||||||
|
@ -285,9 +292,18 @@ export function XYChart({
|
||||||
minInterval,
|
minInterval,
|
||||||
isTimeViz,
|
isTimeViz,
|
||||||
isHistogramViz,
|
isHistogramViz,
|
||||||
xExtent
|
xAxisConfig?.extent
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const axisTitlesVisibilitySettings = {
|
||||||
|
yLeft: yAxesMap?.left?.showTitle ?? true,
|
||||||
|
yRight: yAxesMap?.right?.showTitle ?? true,
|
||||||
|
};
|
||||||
|
const tickLabelsVisibilitySettings = {
|
||||||
|
yLeft: yAxesMap?.left?.showLabels ?? true,
|
||||||
|
yRight: yAxesMap?.right?.showLabels ?? true,
|
||||||
|
};
|
||||||
|
|
||||||
const getYAxesTitles = (axisSeries: Series[]) => {
|
const getYAxesTitles = (axisSeries: Series[]) => {
|
||||||
return axisSeries
|
return axisSeries
|
||||||
.map(({ layer, accessor }) => titles?.[layer]?.yTitles?.[accessor])
|
.map(({ layer, accessor }) => titles?.[layer]?.yTitles?.[accessor])
|
||||||
|
@ -312,45 +328,48 @@ export function XYChart({
|
||||||
const rangeAnnotations = getRangeAnnotations(annotationsLayers);
|
const rangeAnnotations = getRangeAnnotations(annotationsLayers);
|
||||||
|
|
||||||
const visualConfigs = [
|
const visualConfigs = [
|
||||||
...referenceLineLayers.flatMap<ExtendedYConfig | ReferenceLineYConfig | undefined>(
|
...referenceLineLayers
|
||||||
({ yConfig }) => yConfig
|
.flatMap<ReferenceLineDecorationConfig | ExtendedReferenceLineDecorationConfig | undefined>(
|
||||||
),
|
({ decorations }) => decorations
|
||||||
|
)
|
||||||
|
.map((config) => ({
|
||||||
|
...config,
|
||||||
|
position: config
|
||||||
|
? getAxisGroupForReferenceLine(axesConfiguration, config, shouldRotate)?.position ??
|
||||||
|
Position.Left
|
||||||
|
: Position.Bottom,
|
||||||
|
})),
|
||||||
...groupedLineAnnotations,
|
...groupedLineAnnotations,
|
||||||
].filter(Boolean);
|
].filter(Boolean);
|
||||||
|
|
||||||
const shouldHideDetails = annotationsLayers.length > 0 ? annotationsLayers[0].hide : false;
|
const shouldHideDetails = annotationsLayers.length > 0 ? annotationsLayers[0].hide : false;
|
||||||
const linesPaddings = !shouldHideDetails ? getLinesCausedPaddings(visualConfigs, yAxesMap) : {};
|
const linesPaddings = !shouldHideDetails
|
||||||
|
? getLinesCausedPaddings(visualConfigs, yAxesMap, shouldRotate)
|
||||||
|
: {};
|
||||||
|
|
||||||
const getYAxesStyle = (groupId: 'left' | 'right') => {
|
const getYAxesStyle = (axis: AxisConfiguration) => {
|
||||||
const tickVisible =
|
const tickVisible = axis.showLabels;
|
||||||
groupId === 'right'
|
const position = getOriginalAxisPosition(axis.position, shouldRotate);
|
||||||
? tickLabelsVisibilitySettings?.yRight
|
|
||||||
: tickLabelsVisibilitySettings?.yLeft;
|
|
||||||
|
|
||||||
const style = {
|
const style = {
|
||||||
tickLabel: {
|
tickLabel: {
|
||||||
|
fill: axis.labelColor,
|
||||||
visible: tickVisible,
|
visible: tickVisible,
|
||||||
rotation:
|
rotation: axis.labelsOrientation,
|
||||||
groupId === 'right'
|
|
||||||
? args.labelsOrientation?.yRight || 0
|
|
||||||
: args.labelsOrientation?.yLeft || 0,
|
|
||||||
padding:
|
padding:
|
||||||
linesPaddings[groupId] != null
|
linesPaddings[position] != null
|
||||||
? {
|
? {
|
||||||
inner: linesPaddings[groupId],
|
inner: linesPaddings[position],
|
||||||
}
|
}
|
||||||
: undefined,
|
: undefined,
|
||||||
},
|
},
|
||||||
axisTitle: {
|
axisTitle: {
|
||||||
visible:
|
visible: axis.showTitle,
|
||||||
groupId === 'right'
|
|
||||||
? axisTitlesVisibilitySettings?.yRight
|
|
||||||
: axisTitlesVisibilitySettings?.yLeft,
|
|
||||||
// if labels are not visible add the padding to the title
|
// if labels are not visible add the padding to the title
|
||||||
padding:
|
padding:
|
||||||
!tickVisible && linesPaddings[groupId] != null
|
!tickVisible && linesPaddings[position] != null
|
||||||
? {
|
? {
|
||||||
inner: linesPaddings[groupId],
|
inner: linesPaddings[position],
|
||||||
}
|
}
|
||||||
: undefined,
|
: undefined,
|
||||||
},
|
},
|
||||||
|
@ -359,7 +378,10 @@ export function XYChart({
|
||||||
};
|
};
|
||||||
|
|
||||||
const getYAxisDomain = (axis: GroupsConfiguration[number]) => {
|
const getYAxisDomain = (axis: GroupsConfiguration[number]) => {
|
||||||
const extent = axis.groupId === 'left' ? yLeftExtent : yRightExtent;
|
const extent: AxisExtentConfigResult = axis.extent || {
|
||||||
|
type: 'axisExtentConfig',
|
||||||
|
mode: 'full',
|
||||||
|
};
|
||||||
const hasBarOrArea = Boolean(
|
const hasBarOrArea = Boolean(
|
||||||
axis.series.some((series) => {
|
axis.series.some((series) => {
|
||||||
const layer = layersById[series.layer];
|
const layer = layersById[series.layer];
|
||||||
|
@ -367,11 +389,12 @@ export function XYChart({
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return layer.seriesType.includes('bar') || layer.seriesType.includes('area');
|
return layer.seriesType === SeriesTypes.BAR || layer.seriesType === SeriesTypes.AREA;
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
const fit = !hasBarOrArea && extent.mode === AxisExtentModes.DATA_BOUNDS;
|
const fit = !hasBarOrArea && extent.mode === AxisExtentModes.DATA_BOUNDS;
|
||||||
|
const padding = axis.boundsMargin || undefined;
|
||||||
|
|
||||||
let min: number = NaN;
|
let min: number = NaN;
|
||||||
let max: number = NaN;
|
let max: number = NaN;
|
||||||
|
@ -387,22 +410,31 @@ export function XYChart({
|
||||||
fit,
|
fit,
|
||||||
min,
|
min,
|
||||||
max,
|
max,
|
||||||
|
padding,
|
||||||
includeDataFromIds: referenceLineLayers
|
includeDataFromIds: referenceLineLayers
|
||||||
.flatMap((l) =>
|
.flatMap(
|
||||||
l.yConfig ? l.yConfig.map((yConfig) => ({ layerId: l.layerId, yConfig })) : []
|
(l) => l.decorations?.map((decoration) => ({ layerId: l.layerId, decoration })) || []
|
||||||
)
|
)
|
||||||
.filter(({ yConfig }) => yConfig.axisMode === axis.groupId)
|
.filter(({ decoration }) => {
|
||||||
.map(({ layerId, yConfig }) =>
|
if (decoration.axisId) {
|
||||||
isReferenceLineYConfig(yConfig)
|
return axis.groupId.includes(decoration.axisId);
|
||||||
? `${layerId}-${yConfig.value}-${yConfig.fill !== 'none' ? 'rect' : 'line'}`
|
}
|
||||||
: `${layerId}-${yConfig.forAccessor}-${yConfig.fill !== 'none' ? 'rect' : 'line'}`
|
|
||||||
|
return (
|
||||||
|
axis.position === getAxisPosition(decoration.position ?? Position.Left, shouldRotate)
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.map(({ layerId, decoration }) =>
|
||||||
|
isReferenceLineDecorationConfig(decoration)
|
||||||
|
? `${layerId}-${decoration.value}-${decoration.fill !== 'none' ? 'rect' : 'line'}`
|
||||||
|
: `${layerId}-${decoration.forAccessor}-${decoration.fill !== 'none' ? 'rect' : 'line'}`
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const shouldShowValueLabels =
|
const shouldShowValueLabels =
|
||||||
// No stacked bar charts
|
// No stacked bar charts
|
||||||
dataLayers.every((layer) => !layer.seriesType.includes('stacked')) &&
|
dataLayers.every((layer) => !layer.isStacked) &&
|
||||||
// No histogram charts
|
// No histogram charts
|
||||||
!isHistogramViz;
|
!isHistogramViz;
|
||||||
|
|
||||||
|
@ -516,18 +548,17 @@ export function XYChart({
|
||||||
};
|
};
|
||||||
|
|
||||||
const isHistogramModeEnabled = dataLayers.some(
|
const isHistogramModeEnabled = dataLayers.some(
|
||||||
({ isHistogram, seriesType }) =>
|
({ isHistogram, seriesType, isStacked }) =>
|
||||||
isHistogram &&
|
isHistogram && (isStacked || seriesType !== SeriesTypes.BAR || !chartHasMoreThanOneBarSeries)
|
||||||
(seriesType.includes('stacked') ||
|
|
||||||
!seriesType.includes('bar') ||
|
|
||||||
!chartHasMoreThanOneBarSeries)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const shouldUseNewTimeAxis =
|
const shouldUseNewTimeAxis =
|
||||||
isTimeViz && isHistogramModeEnabled && !useLegacyTimeAxis && !shouldRotate;
|
isTimeViz && isHistogramModeEnabled && !useLegacyTimeAxis && !shouldRotate;
|
||||||
|
|
||||||
|
const defaultXAxisPosition = shouldRotate ? Position.Left : Position.Bottom;
|
||||||
|
|
||||||
const gridLineStyle = {
|
const gridLineStyle = {
|
||||||
visible: gridlinesVisibilitySettings?.x,
|
visible: xAxisConfig?.showGridLines,
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
};
|
};
|
||||||
const xAxisStyle: RecursivePartial<AxisStyle> = shouldUseNewTimeAxis
|
const xAxisStyle: RecursivePartial<AxisStyle> = shouldUseNewTimeAxis
|
||||||
|
@ -535,26 +566,28 @@ export function XYChart({
|
||||||
...MULTILAYER_TIME_AXIS_STYLE,
|
...MULTILAYER_TIME_AXIS_STYLE,
|
||||||
tickLabel: {
|
tickLabel: {
|
||||||
...MULTILAYER_TIME_AXIS_STYLE.tickLabel,
|
...MULTILAYER_TIME_AXIS_STYLE.tickLabel,
|
||||||
visible: Boolean(tickLabelsVisibilitySettings?.x),
|
visible: Boolean(xAxisConfig?.showLabels),
|
||||||
|
fill: xAxisConfig?.labelColor,
|
||||||
},
|
},
|
||||||
tickLine: {
|
tickLine: {
|
||||||
...MULTILAYER_TIME_AXIS_STYLE.tickLine,
|
...MULTILAYER_TIME_AXIS_STYLE.tickLine,
|
||||||
visible: Boolean(tickLabelsVisibilitySettings?.x),
|
visible: Boolean(xAxisConfig?.showLabels),
|
||||||
},
|
},
|
||||||
axisTitle: {
|
axisTitle: {
|
||||||
visible: axisTitlesVisibilitySettings.x,
|
visible: xAxisConfig?.showTitle,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
tickLabel: {
|
tickLabel: {
|
||||||
visible: tickLabelsVisibilitySettings?.x,
|
visible: xAxisConfig?.showLabels,
|
||||||
rotation: labelsOrientation?.x,
|
rotation: xAxisConfig?.labelsOrientation,
|
||||||
padding: linesPaddings.bottom != null ? { inner: linesPaddings.bottom } : undefined,
|
padding: linesPaddings.bottom != null ? { inner: linesPaddings.bottom } : undefined,
|
||||||
|
fill: xAxisConfig?.labelColor,
|
||||||
},
|
},
|
||||||
axisTitle: {
|
axisTitle: {
|
||||||
visible: axisTitlesVisibilitySettings.x,
|
visible: xAxisConfig?.showTitle,
|
||||||
padding:
|
padding:
|
||||||
!tickLabelsVisibilitySettings?.x && linesPaddings.bottom != null
|
!xAxisConfig?.showLabels && linesPaddings.bottom != null
|
||||||
? { inner: linesPaddings.bottom }
|
? { inner: linesPaddings.bottom }
|
||||||
: undefined,
|
: undefined,
|
||||||
},
|
},
|
||||||
|
@ -610,8 +643,8 @@ export function XYChart({
|
||||||
...chartTheme.chartPaddings,
|
...chartTheme.chartPaddings,
|
||||||
...computeChartMargins(
|
...computeChartMargins(
|
||||||
linesPaddings,
|
linesPaddings,
|
||||||
tickLabelsVisibilitySettings,
|
{ ...tickLabelsVisibilitySettings, x: xAxisConfig?.showLabels },
|
||||||
axisTitlesVisibilitySettings,
|
{ ...axisTitlesVisibilitySettings, x: xAxisConfig?.showTitle },
|
||||||
yAxesMap,
|
yAxesMap,
|
||||||
shouldRotate
|
shouldRotate
|
||||||
),
|
),
|
||||||
|
@ -678,12 +711,24 @@ export function XYChart({
|
||||||
|
|
||||||
<Axis
|
<Axis
|
||||||
id="x"
|
id="x"
|
||||||
position={shouldRotate ? Position.Left : Position.Bottom}
|
position={
|
||||||
|
xAxisConfig?.position
|
||||||
|
? getOriginalAxisPosition(xAxisConfig?.position, shouldRotate)
|
||||||
|
: defaultXAxisPosition
|
||||||
|
}
|
||||||
title={xTitle}
|
title={xTitle}
|
||||||
gridLine={gridLineStyle}
|
gridLine={gridLineStyle}
|
||||||
hide={dataLayers[0]?.hide || !dataLayers[0]?.xAccessor}
|
hide={xAxisConfig?.hide || dataLayers[0]?.hide || !dataLayers[0]?.xAccessor}
|
||||||
tickFormat={(d) => safeXAccessorLabelRenderer(d)}
|
tickFormat={(d) => {
|
||||||
|
let value = safeXAccessorLabelRenderer(d) || '';
|
||||||
|
if (xAxisConfig?.truncate && value.length > xAxisConfig.truncate) {
|
||||||
|
value = `${value.slice(0, xAxisConfig.truncate)}...`;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}}
|
||||||
style={xAxisStyle}
|
style={xAxisStyle}
|
||||||
|
showOverlappingLabels={xAxisConfig?.showOverlappingLabels}
|
||||||
|
showDuplicatedTicks={xAxisConfig?.showDuplicates}
|
||||||
timeAxisLayerCount={shouldUseNewTimeAxis ? 3 : 0}
|
timeAxisLayerCount={shouldUseNewTimeAxis ? 3 : 0}
|
||||||
/>
|
/>
|
||||||
{isSplitChart && splitTable && (
|
{isSplitChart && splitTable && (
|
||||||
|
@ -704,15 +749,20 @@ export function XYChart({
|
||||||
position={axis.position}
|
position={axis.position}
|
||||||
title={getYAxesTitles(axis.series)}
|
title={getYAxesTitles(axis.series)}
|
||||||
gridLine={{
|
gridLine={{
|
||||||
visible:
|
visible: axis.showGridLines,
|
||||||
axis.groupId === 'right'
|
|
||||||
? gridlinesVisibilitySettings?.yRight
|
|
||||||
: gridlinesVisibilitySettings?.yLeft,
|
|
||||||
}}
|
}}
|
||||||
hide={dataLayers[0]?.hide}
|
hide={axis.hide || dataLayers[0]?.hide}
|
||||||
tickFormat={(d) => axis.formatter?.convert(d) || ''}
|
tickFormat={(d) => {
|
||||||
style={getYAxesStyle(axis.groupId)}
|
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)}
|
domain={getYAxisDomain(axis)}
|
||||||
|
showOverlappingLabels={axis.showOverlappingLabels}
|
||||||
|
showDuplicatedTicks={axis.showDuplicates}
|
||||||
ticks={5}
|
ticks={5}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -726,9 +776,9 @@ export function XYChart({
|
||||||
histogramMode={dataLayers.every(
|
histogramMode={dataLayers.every(
|
||||||
(layer) =>
|
(layer) =>
|
||||||
layer.isHistogram &&
|
layer.isHistogram &&
|
||||||
(layer.seriesType.includes('stacked') || !layer.splitAccessor) &&
|
(layer.isStacked || !layer.splitAccessor) &&
|
||||||
(layer.seriesType.includes('stacked') ||
|
(layer.isStacked ||
|
||||||
!layer.seriesType.includes('bar') ||
|
layer.seriesType !== SeriesTypes.BAR ||
|
||||||
!chartHasMoreThanOneBarSeries)
|
!chartHasMoreThanOneBarSeries)
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
@ -758,18 +808,12 @@ export function XYChart({
|
||||||
{referenceLineLayers.length ? (
|
{referenceLineLayers.length ? (
|
||||||
<ReferenceLines
|
<ReferenceLines
|
||||||
layers={referenceLineLayers}
|
layers={referenceLineLayers}
|
||||||
formatters={{
|
xAxisFormatter={xAxisFormatter}
|
||||||
left: yAxesMap.left?.formatter,
|
axesConfiguration={axesConfiguration}
|
||||||
right: yAxesMap.right?.formatter,
|
|
||||||
bottom: xAxisFormatter,
|
|
||||||
}}
|
|
||||||
axesMap={{
|
|
||||||
left: Boolean(yAxesMap.left),
|
|
||||||
right: Boolean(yAxesMap.right),
|
|
||||||
}}
|
|
||||||
isHorizontal={shouldRotate}
|
isHorizontal={shouldRotate}
|
||||||
paddingMap={linesPaddings}
|
paddingMap={linesPaddings}
|
||||||
titles={titles}
|
titles={titles}
|
||||||
|
yAxesMap={yAxesMap}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
{rangeAnnotations.length || groupedLineAnnotations.length ? (
|
{rangeAnnotations.length || groupedLineAnnotations.length ? (
|
||||||
|
|
|
@ -22,13 +22,13 @@ import {
|
||||||
|
|
||||||
export const visualizationDefinitions = [
|
export const visualizationDefinitions = [
|
||||||
{ id: SeriesTypes.BAR, icon: BarIcon },
|
{ id: SeriesTypes.BAR, icon: BarIcon },
|
||||||
{ id: SeriesTypes.BAR_STACKED, icon: BarStackedIcon },
|
{ id: `${SeriesTypes.BAR}_stacked`, icon: BarStackedIcon },
|
||||||
{ id: SeriesTypes.BAR_HORIZONTAL, icon: BarHorizontalIcon },
|
{ id: `${SeriesTypes.BAR}_horizontal`, icon: BarHorizontalIcon },
|
||||||
{ id: SeriesTypes.BAR_PERCENTAGE_STACKED, icon: BarPercentageIcon },
|
{ id: `${SeriesTypes.BAR}_percentage_stacked`, icon: BarPercentageIcon },
|
||||||
{ id: SeriesTypes.BAR_HORIZONTAL_STACKED, icon: BarHorizontalStackedIcon },
|
{ id: `${SeriesTypes.BAR}_horizontal_stacked`, icon: BarHorizontalStackedIcon },
|
||||||
{ id: SeriesTypes.BAR_HORIZONTAL_PERCENTAGE_STACKED, icon: BarHorizontalPercentageIcon },
|
{ id: `${SeriesTypes.BAR}_horizontal_percentage_stacked`, icon: BarHorizontalPercentageIcon },
|
||||||
{ id: SeriesTypes.LINE, icon: LineIcon },
|
{ id: SeriesTypes.LINE, icon: LineIcon },
|
||||||
{ id: SeriesTypes.AREA, icon: AreaIcon },
|
{ id: SeriesTypes.AREA, icon: AreaIcon },
|
||||||
{ id: SeriesTypes.AREA_STACKED, icon: AreaStackedIcon },
|
{ id: `${SeriesTypes.AREA}_stacked`, icon: AreaStackedIcon },
|
||||||
{ id: SeriesTypes.AREA_PERCENTAGE_STACKED, icon: AreaPercentageIcon },
|
{ id: `${SeriesTypes.AREA}_percentage_stacked`, icon: AreaPercentageIcon },
|
||||||
];
|
];
|
||||||
|
|
|
@ -11,31 +11,34 @@ import { EuiFlexGroup, EuiIcon, EuiIconProps, EuiText } from '@elastic/eui';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import type {
|
import type {
|
||||||
IconPosition,
|
IconPosition,
|
||||||
YAxisMode,
|
ReferenceLineDecorationConfig,
|
||||||
ExtendedYConfig,
|
|
||||||
CollectiveConfig,
|
CollectiveConfig,
|
||||||
} from '../../common/types';
|
} from '../../common/types';
|
||||||
import { getBaseIconPlacement } from '../components';
|
import { getBaseIconPlacement } from '../components';
|
||||||
import { hasIcon, iconSet } from './icon';
|
import { hasIcon, iconSet } from './icon';
|
||||||
|
import { AxesMap, getOriginalAxisPosition } from './axes_configuration';
|
||||||
|
|
||||||
export const LINES_MARKER_SIZE = 20;
|
export const LINES_MARKER_SIZE = 20;
|
||||||
|
|
||||||
type PartialExtendedYConfig = Pick<
|
type PartialReferenceLineDecorationConfig = Pick<
|
||||||
ExtendedYConfig,
|
ReferenceLineDecorationConfig,
|
||||||
'axisMode' | 'icon' | 'iconPosition' | 'textVisibility'
|
'icon' | 'iconPosition' | 'textVisibility'
|
||||||
>;
|
> & {
|
||||||
|
position?: Position;
|
||||||
|
};
|
||||||
|
|
||||||
type PartialCollectiveConfig = Pick<CollectiveConfig, 'axisMode' | 'icon' | 'textVisibility'>;
|
type PartialCollectiveConfig = Pick<CollectiveConfig, 'position' | 'icon' | 'textVisibility'>;
|
||||||
|
|
||||||
const isExtendedYConfig = (
|
const isExtendedDecorationConfig = (
|
||||||
config: PartialExtendedYConfig | PartialCollectiveConfig | undefined
|
config: PartialReferenceLineDecorationConfig | PartialCollectiveConfig | undefined
|
||||||
): config is PartialExtendedYConfig =>
|
): config is PartialReferenceLineDecorationConfig =>
|
||||||
(config as PartialExtendedYConfig)?.iconPosition ? true : false;
|
(config as PartialReferenceLineDecorationConfig)?.iconPosition ? true : false;
|
||||||
|
|
||||||
// Note: it does not take into consideration whether the reference line is in view or not
|
// Note: it does not take into consideration whether the reference line is in view or not
|
||||||
export const getLinesCausedPaddings = (
|
export const getLinesCausedPaddings = (
|
||||||
visualConfigs: Array<PartialExtendedYConfig | PartialCollectiveConfig | undefined>,
|
visualConfigs: Array<PartialReferenceLineDecorationConfig | PartialCollectiveConfig | undefined>,
|
||||||
axesMap: Record<'left' | 'right', unknown>
|
axesMap: AxesMap,
|
||||||
|
shouldRotate: boolean
|
||||||
) => {
|
) => {
|
||||||
// collect all paddings for the 4 axis: if any text is detected double it.
|
// collect all paddings for the 4 axis: if any text is detected double it.
|
||||||
const paddings: Partial<Record<Position, number>> = {};
|
const paddings: Partial<Record<Position, number>> = {};
|
||||||
|
@ -44,11 +47,15 @@ export const getLinesCausedPaddings = (
|
||||||
if (!config) {
|
if (!config) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const { axisMode, icon, textVisibility } = config;
|
const { position, icon, textVisibility } = config;
|
||||||
const iconPosition = isExtendedYConfig(config) ? config.iconPosition : undefined;
|
const iconPosition = isExtendedDecorationConfig(config) ? config.iconPosition : undefined;
|
||||||
|
|
||||||
if (axisMode && (hasIcon(icon) || textVisibility)) {
|
if (position && (hasIcon(icon) || textVisibility)) {
|
||||||
const placement = getBaseIconPlacement(iconPosition, axesMap, axisMode);
|
const placement = getBaseIconPlacement(
|
||||||
|
iconPosition,
|
||||||
|
axesMap,
|
||||||
|
getOriginalAxisPosition(position, shouldRotate)
|
||||||
|
);
|
||||||
paddings[placement] = Math.max(
|
paddings[placement] = Math.max(
|
||||||
paddings[placement] || 0,
|
paddings[placement] || 0,
|
||||||
LINES_MARKER_SIZE * (textVisibility ? 2 : 1) // double the padding size if there's text
|
LINES_MARKER_SIZE * (textVisibility ? 2 : 1) // double the padding size if there's text
|
||||||
|
@ -174,7 +181,7 @@ export const AnnotationIcon = ({
|
||||||
};
|
};
|
||||||
|
|
||||||
interface MarkerConfig {
|
interface MarkerConfig {
|
||||||
axisMode?: YAxisMode;
|
position?: Position;
|
||||||
icon?: string;
|
icon?: string;
|
||||||
textVisibility?: boolean;
|
textVisibility?: boolean;
|
||||||
iconPosition?: IconPosition;
|
iconPosition?: IconPosition;
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* Side Public License, v 1.
|
* Side Public License, v 1.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { DataLayerConfig } from '../../common';
|
import { DataLayerConfig, YAxisConfigResult } from '../../common';
|
||||||
import { LayerTypes } from '../../common/constants';
|
import { LayerTypes } from '../../common/constants';
|
||||||
import { Datatable } from '@kbn/expressions-plugin/public';
|
import { Datatable } from '@kbn/expressions-plugin/public';
|
||||||
import { getAxesConfiguration } from './axes_configuration';
|
import { getAxesConfiguration } from './axes_configuration';
|
||||||
|
@ -221,6 +221,14 @@ describe('axes_configuration', () => {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const yAxisConfigs: YAxisConfigResult[] = [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
position: 'right',
|
||||||
|
type: 'yAxisConfig',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
const sampleLayer: DataLayerConfig = {
|
const sampleLayer: DataLayerConfig = {
|
||||||
layerId: 'first',
|
layerId: 'first',
|
||||||
type: 'dataLayer',
|
type: 'dataLayer',
|
||||||
|
@ -233,6 +241,9 @@ describe('axes_configuration', () => {
|
||||||
columnToLabel: '{"a": "Label A", "b": "Label B", "d": "Label D"}',
|
columnToLabel: '{"a": "Label A", "b": "Label B", "d": "Label D"}',
|
||||||
xScaleType: 'ordinal',
|
xScaleType: 'ordinal',
|
||||||
isHistogram: false,
|
isHistogram: false,
|
||||||
|
isPercentage: false,
|
||||||
|
isStacked: false,
|
||||||
|
isHorizontal: false,
|
||||||
palette: { type: 'palette', name: 'default' },
|
palette: { type: 'palette', name: 'default' },
|
||||||
table: tables.first,
|
table: tables.first,
|
||||||
};
|
};
|
||||||
|
@ -253,7 +264,7 @@ describe('axes_configuration', () => {
|
||||||
|
|
||||||
it('should map auto series to left axis', () => {
|
it('should map auto series to left axis', () => {
|
||||||
const formatFactory = jest.fn();
|
const formatFactory = jest.fn();
|
||||||
const groups = getAxesConfiguration([sampleLayer], false, formatFactory, fieldFormats);
|
const groups = getAxesConfiguration([sampleLayer], false, formatFactory, fieldFormats, []);
|
||||||
expect(groups.length).toEqual(1);
|
expect(groups.length).toEqual(1);
|
||||||
expect(groups[0].position).toEqual('left');
|
expect(groups[0].position).toEqual('left');
|
||||||
expect(groups[0].series[0].accessor).toEqual('yAccessorId');
|
expect(groups[0].series[0].accessor).toEqual('yAccessorId');
|
||||||
|
@ -263,7 +274,7 @@ describe('axes_configuration', () => {
|
||||||
it('should map auto series to right axis if formatters do not match', () => {
|
it('should map auto series to right axis if formatters do not match', () => {
|
||||||
const formatFactory = jest.fn();
|
const formatFactory = jest.fn();
|
||||||
const twoSeriesLayer = { ...sampleLayer, accessors: ['yAccessorId', 'yAccessorId2'] };
|
const twoSeriesLayer = { ...sampleLayer, accessors: ['yAccessorId', 'yAccessorId2'] };
|
||||||
const groups = getAxesConfiguration([twoSeriesLayer], false, formatFactory, fieldFormats);
|
const groups = getAxesConfiguration([twoSeriesLayer], false, formatFactory, fieldFormats, []);
|
||||||
expect(groups.length).toEqual(2);
|
expect(groups.length).toEqual(2);
|
||||||
expect(groups[0].position).toEqual('left');
|
expect(groups[0].position).toEqual('left');
|
||||||
expect(groups[1].position).toEqual('right');
|
expect(groups[1].position).toEqual('right');
|
||||||
|
@ -277,7 +288,7 @@ describe('axes_configuration', () => {
|
||||||
...sampleLayer,
|
...sampleLayer,
|
||||||
accessors: ['yAccessorId', 'yAccessorId2', 'yAccessorId3'],
|
accessors: ['yAccessorId', 'yAccessorId2', 'yAccessorId3'],
|
||||||
};
|
};
|
||||||
const groups = getAxesConfiguration([threeSeriesLayer], false, formatFactory, fieldFormats);
|
const groups = getAxesConfiguration([threeSeriesLayer], false, formatFactory, fieldFormats, []);
|
||||||
expect(groups.length).toEqual(2);
|
expect(groups.length).toEqual(2);
|
||||||
expect(groups[0].position).toEqual('left');
|
expect(groups[0].position).toEqual('left');
|
||||||
expect(groups[1].position).toEqual('right');
|
expect(groups[1].position).toEqual('right');
|
||||||
|
@ -292,12 +303,13 @@ describe('axes_configuration', () => {
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
...sampleLayer,
|
...sampleLayer,
|
||||||
yConfig: [{ type: 'yConfig', forAccessor: 'yAccessorId', axisMode: 'right' }],
|
decorations: [{ type: 'dataDecorationConfig', forAccessor: 'yAccessorId', axisId: '1' }],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
false,
|
false,
|
||||||
formatFactory,
|
formatFactory,
|
||||||
fieldFormats
|
fieldFormats,
|
||||||
|
yAxisConfigs
|
||||||
);
|
);
|
||||||
expect(groups.length).toEqual(1);
|
expect(groups.length).toEqual(1);
|
||||||
expect(groups[0].position).toEqual('right');
|
expect(groups[0].position).toEqual('right');
|
||||||
|
@ -312,19 +324,20 @@ describe('axes_configuration', () => {
|
||||||
{
|
{
|
||||||
...sampleLayer,
|
...sampleLayer,
|
||||||
accessors: ['yAccessorId', 'yAccessorId3', 'yAccessorId4'],
|
accessors: ['yAccessorId', 'yAccessorId3', 'yAccessorId4'],
|
||||||
yConfig: [{ type: 'yConfig', forAccessor: 'yAccessorId', axisMode: 'right' }],
|
decorations: [{ type: 'dataDecorationConfig', forAccessor: 'yAccessorId', axisId: '1' }],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
false,
|
false,
|
||||||
formatFactory,
|
formatFactory,
|
||||||
fieldFormats
|
fieldFormats,
|
||||||
|
yAxisConfigs
|
||||||
);
|
);
|
||||||
expect(groups.length).toEqual(2);
|
expect(groups.length).toEqual(2);
|
||||||
expect(groups[0].position).toEqual('left');
|
expect(groups[0].position).toEqual('right');
|
||||||
expect(groups[0].series[0].accessor).toEqual('yAccessorId3');
|
expect(groups[0].series[0].accessor).toEqual('yAccessorId');
|
||||||
expect(groups[0].series[1].accessor).toEqual('yAccessorId4');
|
expect(groups[1].position).toEqual('left');
|
||||||
expect(groups[1].position).toEqual('right');
|
expect(groups[1].series[0].accessor).toEqual('yAccessorId3');
|
||||||
expect(groups[1].series[0].accessor).toEqual('yAccessorId');
|
expect(groups[1].series[1].accessor).toEqual('yAccessorId4');
|
||||||
expect(formatFactory).toHaveBeenCalledWith({ id: 'number', params: {} });
|
expect(formatFactory).toHaveBeenCalledWith({ id: 'number', params: {} });
|
||||||
expect(formatFactory).toHaveBeenCalledWith({ id: 'currency', params: {} });
|
expect(formatFactory).toHaveBeenCalledWith({ id: 'currency', params: {} });
|
||||||
});
|
});
|
||||||
|
@ -336,12 +349,13 @@ describe('axes_configuration', () => {
|
||||||
{
|
{
|
||||||
...sampleLayer,
|
...sampleLayer,
|
||||||
accessors: ['yAccessorId', 'yAccessorId3', 'yAccessorId4'],
|
accessors: ['yAccessorId', 'yAccessorId3', 'yAccessorId4'],
|
||||||
yConfig: [{ type: 'yConfig', forAccessor: 'yAccessorId', axisMode: 'right' }],
|
decorations: [{ type: 'dataDecorationConfig', forAccessor: 'yAccessorId', axisId: '1' }],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
false,
|
false,
|
||||||
formatFactory,
|
formatFactory,
|
||||||
fieldFormats
|
fieldFormats,
|
||||||
|
yAxisConfigs
|
||||||
);
|
);
|
||||||
expect(formatFactory).toHaveBeenCalledTimes(2);
|
expect(formatFactory).toHaveBeenCalledTimes(2);
|
||||||
expect(formatFactory).toHaveBeenCalledWith({ id: 'number', params: {} });
|
expect(formatFactory).toHaveBeenCalledWith({ id: 'number', params: {} });
|
||||||
|
|
|
@ -6,15 +6,18 @@
|
||||||
* Side Public License, v 1.
|
* Side Public License, v 1.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { Position } from '@elastic/charts';
|
||||||
import type { IFieldFormat, SerializedFieldFormat } from '@kbn/field-formats-plugin/common';
|
import type { IFieldFormat, SerializedFieldFormat } from '@kbn/field-formats-plugin/common';
|
||||||
import { getAccessorByDimension } from '@kbn/visualizations-plugin/common/utils';
|
import { getAccessorByDimension } from '@kbn/visualizations-plugin/common/utils';
|
||||||
import { FormatFactory } from '../types';
|
import { FormatFactory } from '../types';
|
||||||
import {
|
import {
|
||||||
AxisExtentConfig,
|
AxisExtentConfig,
|
||||||
CommonXYDataLayerConfig,
|
CommonXYDataLayerConfig,
|
||||||
ExtendedYConfig,
|
DataDecorationConfig,
|
||||||
YConfig,
|
YAxisConfig,
|
||||||
YScaleType,
|
ReferenceLineDecorationConfig,
|
||||||
|
YAxisConfigResult,
|
||||||
|
XAxisConfigResult,
|
||||||
} from '../../common';
|
} from '../../common';
|
||||||
import { LayersFieldFormats } from './layers';
|
import { LayersFieldFormats } from './layers';
|
||||||
|
|
||||||
|
@ -25,15 +28,26 @@ export interface Series {
|
||||||
|
|
||||||
interface FormattedMetric extends Series {
|
interface FormattedMetric extends Series {
|
||||||
fieldFormat: SerializedFieldFormat;
|
fieldFormat: SerializedFieldFormat;
|
||||||
|
axisId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type GroupsConfiguration = Array<{
|
interface AxesSeries {
|
||||||
groupId: 'left' | 'right';
|
[key: string]: FormattedMetric[];
|
||||||
position: 'left' | 'right' | 'bottom' | 'top';
|
}
|
||||||
|
|
||||||
|
export interface AxisConfiguration extends Omit<YAxisConfig, 'id'> {
|
||||||
|
/**
|
||||||
|
* Axis group identificator. Format: `axis-${axis.id}` or just `left`/`right`.
|
||||||
|
*/
|
||||||
|
groupId: string;
|
||||||
|
position: Position;
|
||||||
formatter?: IFieldFormat;
|
formatter?: IFieldFormat;
|
||||||
series: Series[];
|
series: Series[];
|
||||||
scale?: YScaleType;
|
}
|
||||||
}>;
|
|
||||||
|
export type GroupsConfiguration = AxisConfiguration[];
|
||||||
|
|
||||||
|
export type AxesMap = Record<'left' | 'right', AxisConfiguration | undefined>;
|
||||||
|
|
||||||
export function isFormatterCompatible(
|
export function isFormatterCompatible(
|
||||||
formatter1: SerializedFieldFormat,
|
formatter1: SerializedFieldFormat,
|
||||||
|
@ -42,91 +56,203 @@ export function isFormatterCompatible(
|
||||||
return formatter1?.id === formatter2?.id;
|
return formatter1?.id === formatter2?.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const LEFT_GLOBAL_AXIS_ID = 'left';
|
||||||
|
const RIGHT_GLOBAL_AXIS_ID = 'right';
|
||||||
|
|
||||||
|
function isAxisSeriesAppliedForFormatter(
|
||||||
|
series: FormattedMetric[],
|
||||||
|
currentSeries: FormattedMetric
|
||||||
|
) {
|
||||||
|
return series.every((leftSeries) =>
|
||||||
|
isFormatterCompatible(leftSeries.fieldFormat, currentSeries.fieldFormat)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function groupAxesByType(
|
export function groupAxesByType(
|
||||||
layers: CommonXYDataLayerConfig[],
|
layers: CommonXYDataLayerConfig[],
|
||||||
fieldFormats: LayersFieldFormats
|
fieldFormats: LayersFieldFormats,
|
||||||
|
yAxisConfigs?: YAxisConfig[]
|
||||||
) {
|
) {
|
||||||
const series: {
|
const series: AxesSeries = {
|
||||||
auto: FormattedMetric[];
|
|
||||||
left: FormattedMetric[];
|
|
||||||
right: FormattedMetric[];
|
|
||||||
bottom: FormattedMetric[];
|
|
||||||
} = {
|
|
||||||
auto: [],
|
auto: [],
|
||||||
left: [],
|
left: [],
|
||||||
right: [],
|
right: [],
|
||||||
bottom: [],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const leftSeriesKeys: string[] = [];
|
||||||
|
const rightSeriesKeys: string[] = [];
|
||||||
|
|
||||||
layers.forEach((layer) => {
|
layers.forEach((layer) => {
|
||||||
const { layerId, table } = layer;
|
const { layerId, table } = layer;
|
||||||
layer.accessors.forEach((accessor) => {
|
layer.accessors.forEach((accessor) => {
|
||||||
const yConfig: Array<YConfig | ExtendedYConfig> | undefined = layer.yConfig;
|
const dataDecorations:
|
||||||
|
| Array<DataDecorationConfig | ReferenceLineDecorationConfig>
|
||||||
|
| undefined = layer.decorations;
|
||||||
const yAccessor = getAccessorByDimension(accessor, table.columns);
|
const yAccessor = getAccessorByDimension(accessor, table.columns);
|
||||||
const mode =
|
const decorationByAccessor = dataDecorations?.find(
|
||||||
yConfig?.find(({ forAccessor }) => forAccessor === yAccessor)?.axisMode || 'auto';
|
(decorationConfig) => decorationConfig.forAccessor === yAccessor
|
||||||
|
);
|
||||||
|
const axisConfigById = yAxisConfigs?.find(
|
||||||
|
(axis) =>
|
||||||
|
decorationByAccessor?.axisId && axis.id && axis.id === decorationByAccessor?.axisId
|
||||||
|
);
|
||||||
|
const key = axisConfigById?.id ? `axis-${axisConfigById?.id}` : 'auto';
|
||||||
const fieldFormat = fieldFormats[layerId].yAccessors[yAccessor]!;
|
const fieldFormat = fieldFormats[layerId].yAccessors[yAccessor]!;
|
||||||
series[mode].push({ layer: layer.layerId, accessor: yAccessor, fieldFormat });
|
if (!series[key]) {
|
||||||
|
series[key] = [];
|
||||||
|
}
|
||||||
|
series[key].push({ layer: layer.layerId, accessor: yAccessor, fieldFormat });
|
||||||
|
|
||||||
|
if (axisConfigById?.position === Position.Left) {
|
||||||
|
leftSeriesKeys.push(key);
|
||||||
|
} else if (axisConfigById?.position === Position.Right) {
|
||||||
|
rightSeriesKeys.push(key);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const tablesExist = layers.filter(({ table }) => Boolean(table)).length > 0;
|
const tablesExist = layers.filter(({ table }) => Boolean(table)).length > 0;
|
||||||
|
|
||||||
|
leftSeriesKeys.push(LEFT_GLOBAL_AXIS_ID);
|
||||||
|
rightSeriesKeys.push(RIGHT_GLOBAL_AXIS_ID);
|
||||||
|
|
||||||
series.auto.forEach((currentSeries) => {
|
series.auto.forEach((currentSeries) => {
|
||||||
if (
|
const leftAxisGroupId = tablesExist
|
||||||
series.left.length === 0 ||
|
? leftSeriesKeys.find((leftSeriesKey) =>
|
||||||
(tablesExist &&
|
isAxisSeriesAppliedForFormatter(series[leftSeriesKey], currentSeries)
|
||||||
series.left.every((leftSeries) =>
|
)
|
||||||
isFormatterCompatible(leftSeries.fieldFormat, currentSeries.fieldFormat)
|
: undefined;
|
||||||
))
|
|
||||||
) {
|
const rightAxisGroupId = tablesExist
|
||||||
series.left.push(currentSeries);
|
? rightSeriesKeys.find((rightSeriesKey) =>
|
||||||
} else if (
|
isAxisSeriesAppliedForFormatter(series[rightSeriesKey], currentSeries)
|
||||||
series.right.length === 0 ||
|
)
|
||||||
(tablesExist &&
|
: undefined;
|
||||||
series.left.every((leftSeries) =>
|
|
||||||
isFormatterCompatible(leftSeries.fieldFormat, currentSeries.fieldFormat)
|
let axisGroupId = LEFT_GLOBAL_AXIS_ID;
|
||||||
))
|
|
||||||
) {
|
if (series[LEFT_GLOBAL_AXIS_ID].length === 0 || leftAxisGroupId) {
|
||||||
series.right.push(currentSeries);
|
axisGroupId = leftAxisGroupId || LEFT_GLOBAL_AXIS_ID;
|
||||||
} else if (series.right.length >= series.left.length) {
|
} else if (series[RIGHT_GLOBAL_AXIS_ID].length === 0 || rightAxisGroupId) {
|
||||||
series.left.push(currentSeries);
|
axisGroupId = rightAxisGroupId || RIGHT_GLOBAL_AXIS_ID;
|
||||||
|
} else if (series[RIGHT_GLOBAL_AXIS_ID].length >= series[LEFT_GLOBAL_AXIS_ID].length) {
|
||||||
|
axisGroupId = LEFT_GLOBAL_AXIS_ID;
|
||||||
} else {
|
} else {
|
||||||
series.right.push(currentSeries);
|
axisGroupId = RIGHT_GLOBAL_AXIS_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
series[axisGroupId].push(currentSeries);
|
||||||
});
|
});
|
||||||
|
|
||||||
return series;
|
return series;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getAxisPosition(position: Position, shouldRotate: boolean) {
|
||||||
|
if (shouldRotate) {
|
||||||
|
switch (position) {
|
||||||
|
case Position.Bottom: {
|
||||||
|
return Position.Right;
|
||||||
|
}
|
||||||
|
case Position.Right: {
|
||||||
|
return Position.Top;
|
||||||
|
}
|
||||||
|
case Position.Top: {
|
||||||
|
return Position.Left;
|
||||||
|
}
|
||||||
|
case Position.Left: {
|
||||||
|
return Position.Bottom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getOriginalAxisPosition(position: Position, shouldRotate: boolean) {
|
||||||
|
if (shouldRotate) {
|
||||||
|
switch (position) {
|
||||||
|
case Position.Bottom: {
|
||||||
|
return Position.Left;
|
||||||
|
}
|
||||||
|
case Position.Right: {
|
||||||
|
return Position.Bottom;
|
||||||
|
}
|
||||||
|
case Position.Top: {
|
||||||
|
return Position.Right;
|
||||||
|
}
|
||||||
|
case Position.Left: {
|
||||||
|
return Position.Top;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
function axisGlobalConfig(position: Position, yAxisConfigs?: YAxisConfig[]) {
|
||||||
|
return yAxisConfigs?.find((axis) => !axis.id && axis.position === position) || {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const getXAxisConfig = (axisConfigs: Array<XAxisConfigResult | YAxisConfigResult> = []) =>
|
||||||
|
axisConfigs.find(({ type }) => type === 'xAxisConfig');
|
||||||
|
|
||||||
export function getAxesConfiguration(
|
export function getAxesConfiguration(
|
||||||
layers: CommonXYDataLayerConfig[],
|
layers: CommonXYDataLayerConfig[],
|
||||||
shouldRotate: boolean,
|
shouldRotate: boolean,
|
||||||
formatFactory: FormatFactory | undefined,
|
formatFactory: FormatFactory | undefined,
|
||||||
fieldFormats: LayersFieldFormats,
|
fieldFormats: LayersFieldFormats,
|
||||||
yLeftScale?: YScaleType,
|
axisConfigs?: Array<XAxisConfigResult | YAxisConfigResult>
|
||||||
yRightScale?: YScaleType
|
|
||||||
): GroupsConfiguration {
|
): GroupsConfiguration {
|
||||||
const series = groupAxesByType(layers, fieldFormats);
|
const series = groupAxesByType(layers, fieldFormats, axisConfigs);
|
||||||
|
|
||||||
const axisGroups: GroupsConfiguration = [];
|
const axisGroups: GroupsConfiguration = [];
|
||||||
|
let position: Position;
|
||||||
|
|
||||||
if (series.left.length > 0) {
|
axisConfigs?.forEach((axis) => {
|
||||||
|
const groupId = axis.id ? `axis-${axis.id}` : undefined;
|
||||||
|
if (groupId && series[groupId] && series[groupId].length > 0) {
|
||||||
|
position = getAxisPosition(axis.position || Position.Left, shouldRotate);
|
||||||
|
axisGroups.push({
|
||||||
|
groupId,
|
||||||
|
formatter: formatFactory?.(series[groupId][0].fieldFormat),
|
||||||
|
series: series[groupId].map(({ fieldFormat, ...currentSeries }) => currentSeries),
|
||||||
|
...axisGlobalConfig(axis.position || Position.Left, axisConfigs),
|
||||||
|
...axis,
|
||||||
|
position,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (series[LEFT_GLOBAL_AXIS_ID].length > 0) {
|
||||||
|
position = shouldRotate ? Position.Bottom : Position.Left;
|
||||||
axisGroups.push({
|
axisGroups.push({
|
||||||
groupId: 'left',
|
groupId: LEFT_GLOBAL_AXIS_ID,
|
||||||
position: shouldRotate ? 'bottom' : 'left',
|
|
||||||
formatter: formatFactory?.(series.left[0].fieldFormat),
|
formatter: formatFactory?.(series.left[0].fieldFormat),
|
||||||
series: series.left.map(({ fieldFormat, ...currentSeries }) => currentSeries),
|
series: series.left.map(({ fieldFormat, ...currentSeries }) => currentSeries),
|
||||||
scale: yLeftScale,
|
...axisGlobalConfig(Position.Left, axisConfigs),
|
||||||
|
position,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (series.right.length > 0) {
|
if (series[RIGHT_GLOBAL_AXIS_ID].length > 0) {
|
||||||
|
position = shouldRotate ? Position.Top : Position.Right;
|
||||||
axisGroups.push({
|
axisGroups.push({
|
||||||
groupId: 'right',
|
groupId: RIGHT_GLOBAL_AXIS_ID,
|
||||||
position: shouldRotate ? 'top' : 'right',
|
|
||||||
formatter: formatFactory?.(series.right[0].fieldFormat),
|
formatter: formatFactory?.(series.right[0].fieldFormat),
|
||||||
series: series.right.map(({ fieldFormat, ...currentSeries }) => currentSeries),
|
series: series.right.map(({ fieldFormat, ...currentSeries }) => currentSeries),
|
||||||
scale: yRightScale,
|
...axisGlobalConfig(Position.Right, axisConfigs),
|
||||||
|
position,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const xAxisConfig = getXAxisConfig(axisConfigs);
|
||||||
|
if (xAxisConfig) {
|
||||||
|
position = getAxisPosition(xAxisConfig.position || Position.Bottom, shouldRotate);
|
||||||
|
axisGroups.push({
|
||||||
|
groupId: 'bottom',
|
||||||
|
series: [],
|
||||||
|
...xAxisConfig,
|
||||||
|
position,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,8 +54,11 @@ describe('color_assignment', () => {
|
||||||
type: 'dataLayer',
|
type: 'dataLayer',
|
||||||
showLines: true,
|
showLines: true,
|
||||||
isHistogram: true,
|
isHistogram: true,
|
||||||
|
isPercentage: false,
|
||||||
xScaleType: 'linear',
|
xScaleType: 'linear',
|
||||||
seriesType: 'bar',
|
seriesType: 'bar',
|
||||||
|
isStacked: false,
|
||||||
|
isHorizontal: false,
|
||||||
palette: { type: 'palette', name: 'palette1' },
|
palette: { type: 'palette', name: 'palette1' },
|
||||||
layerType: LayerTypes.DATA,
|
layerType: LayerTypes.DATA,
|
||||||
splitAccessor: 'split1',
|
splitAccessor: 'split1',
|
||||||
|
@ -68,7 +71,10 @@ describe('color_assignment', () => {
|
||||||
showLines: true,
|
showLines: true,
|
||||||
xScaleType: 'linear',
|
xScaleType: 'linear',
|
||||||
isHistogram: true,
|
isHistogram: true,
|
||||||
|
isPercentage: false,
|
||||||
seriesType: 'bar',
|
seriesType: 'bar',
|
||||||
|
isStacked: false,
|
||||||
|
isHorizontal: false,
|
||||||
palette: { type: 'palette', name: 'palette2' },
|
palette: { type: 'palette', name: 'palette2' },
|
||||||
layerType: LayerTypes.DATA,
|
layerType: LayerTypes.DATA,
|
||||||
splitAccessor: 'split2',
|
splitAccessor: 'split2',
|
||||||
|
|
|
@ -27,6 +27,7 @@ import {
|
||||||
import type { ExpressionValueVisDimension } from '@kbn/visualizations-plugin/common/expression_functions';
|
import type { ExpressionValueVisDimension } from '@kbn/visualizations-plugin/common/expression_functions';
|
||||||
import { PaletteRegistry, SeriesLayer } from '@kbn/coloring';
|
import { PaletteRegistry, SeriesLayer } from '@kbn/coloring';
|
||||||
import { CommonXYDataLayerConfig, XScaleType } from '../../common';
|
import { CommonXYDataLayerConfig, XScaleType } from '../../common';
|
||||||
|
import { AxisModes, SeriesTypes } from '../../common/constants';
|
||||||
import { FormatFactory } from '../types';
|
import { FormatFactory } from '../types';
|
||||||
import { getSeriesColor } from './state';
|
import { getSeriesColor } from './state';
|
||||||
import { ColorAssignments } from './color_assignment';
|
import { ColorAssignments } from './color_assignment';
|
||||||
|
@ -350,10 +351,14 @@ export const getSeriesProps: GetSeriesPropsFn = ({
|
||||||
formattedDatatableInfo,
|
formattedDatatableInfo,
|
||||||
defaultXScaleType,
|
defaultXScaleType,
|
||||||
}): SeriesSpec => {
|
}): SeriesSpec => {
|
||||||
const { table, markSizeAccessor } = layer;
|
const { table, isStacked, markSizeAccessor } = layer;
|
||||||
const isStacked = layer.seriesType.includes('stacked');
|
const isPercentage = layer.isPercentage;
|
||||||
const isPercentage = layer.seriesType.includes('percentage');
|
let stackMode: StackMode | undefined = isPercentage ? AxisModes.PERCENTAGE : undefined;
|
||||||
const isBarChart = layer.seriesType.includes('bar');
|
if (yAxis?.mode) {
|
||||||
|
stackMode = yAxis?.mode === AxisModes.NORMAL ? undefined : yAxis?.mode;
|
||||||
|
}
|
||||||
|
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 && getAccessorByDimension(layer.xAccessor, table.columns);
|
||||||
const splitColumnId =
|
const splitColumnId =
|
||||||
layer.splitAccessor && getAccessorByDimension(layer.splitAccessor, table.columns);
|
layer.splitAccessor && getAccessorByDimension(layer.splitAccessor, table.columns);
|
||||||
|
@ -413,9 +418,9 @@ export const getSeriesProps: GetSeriesPropsFn = ({
|
||||||
data: rows,
|
data: rows,
|
||||||
xScaleType: xColumnId ? layer.xScaleType ?? defaultXScaleType : 'ordinal',
|
xScaleType: xColumnId ? layer.xScaleType ?? defaultXScaleType : 'ordinal',
|
||||||
yScaleType:
|
yScaleType:
|
||||||
formatter?.id === 'bytes' && yAxis?.scale === ScaleType.Linear
|
formatter?.id === 'bytes' && scaleType === ScaleType.Linear
|
||||||
? ScaleType.LinearBinary
|
? ScaleType.LinearBinary
|
||||||
: yAxis?.scale || ScaleType.Linear,
|
: scaleType,
|
||||||
color: (series) =>
|
color: (series) =>
|
||||||
getColor(
|
getColor(
|
||||||
series,
|
series,
|
||||||
|
@ -431,7 +436,7 @@ export const getSeriesProps: GetSeriesPropsFn = ({
|
||||||
),
|
),
|
||||||
groupId: yAxis?.groupId,
|
groupId: yAxis?.groupId,
|
||||||
enableHistogramMode,
|
enableHistogramMode,
|
||||||
stackMode: isPercentage ? StackMode.Percentage : undefined,
|
stackMode,
|
||||||
timeZone,
|
timeZone,
|
||||||
areaSeriesStyle: {
|
areaSeriesStyle: {
|
||||||
point: getPointConfig({
|
point: getPointConfig({
|
||||||
|
|
|
@ -17,7 +17,6 @@ import {
|
||||||
CommonXYDataLayerConfig,
|
CommonXYDataLayerConfig,
|
||||||
CommonXYLayerConfig,
|
CommonXYLayerConfig,
|
||||||
ReferenceLineLayerConfig,
|
ReferenceLineLayerConfig,
|
||||||
SeriesType,
|
|
||||||
} from '../../common/types';
|
} from '../../common/types';
|
||||||
import { GroupsConfiguration } from './axes_configuration';
|
import { GroupsConfiguration } from './axes_configuration';
|
||||||
import { getFormat } from './format';
|
import { getFormat } from './format';
|
||||||
|
@ -110,7 +109,7 @@ const getAccessorWithFieldFormat = (
|
||||||
const getYAccessorWithFieldFormat = (
|
const getYAccessorWithFieldFormat = (
|
||||||
dimension: string | ExpressionValueVisDimension | undefined,
|
dimension: string | ExpressionValueVisDimension | undefined,
|
||||||
columns: Datatable['columns'],
|
columns: Datatable['columns'],
|
||||||
seriesType: SeriesType
|
isPercentage: boolean
|
||||||
) => {
|
) => {
|
||||||
if (!dimension) {
|
if (!dimension) {
|
||||||
return {};
|
return {};
|
||||||
|
@ -118,7 +117,7 @@ const getYAccessorWithFieldFormat = (
|
||||||
|
|
||||||
const accessor = getAccessorByDimension(dimension, columns);
|
const accessor = getAccessorByDimension(dimension, columns);
|
||||||
let format = getFormat(columns, dimension) ?? { id: 'number' };
|
let format = getFormat(columns, dimension) ?? { id: 'number' };
|
||||||
if (format?.id !== 'percent' && seriesType.includes('percentage')) {
|
if (format?.id !== 'percent' && isPercentage) {
|
||||||
format = { id: 'percent', params: { pattern: '0.[00]%' } };
|
format = { id: 'percent', params: { pattern: '0.[00]%' } };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,7 +125,7 @@ const getYAccessorWithFieldFormat = (
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getLayerFormats = (
|
export const getLayerFormats = (
|
||||||
{ xAccessor, accessors, splitAccessor, table, seriesType }: CommonXYDataLayerConfig,
|
{ xAccessor, accessors, splitAccessor, table, isPercentage }: CommonXYDataLayerConfig,
|
||||||
{ splitColumnAccessor, splitRowAccessor }: SplitAccessors
|
{ splitColumnAccessor, splitRowAccessor }: SplitAccessors
|
||||||
): LayerFieldFormats => {
|
): LayerFieldFormats => {
|
||||||
const yAccessors: Array<string | ExpressionValueVisDimension> = accessors;
|
const yAccessors: Array<string | ExpressionValueVisDimension> = accessors;
|
||||||
|
@ -135,7 +134,7 @@ export const getLayerFormats = (
|
||||||
yAccessors: yAccessors.reduce(
|
yAccessors: yAccessors.reduce(
|
||||||
(formatters, a) => ({
|
(formatters, a) => ({
|
||||||
...formatters,
|
...formatters,
|
||||||
...getYAccessorWithFieldFormat(a, table.columns, seriesType),
|
...getYAccessorWithFieldFormat(a, table.columns, isPercentage),
|
||||||
}),
|
}),
|
||||||
{}
|
{}
|
||||||
),
|
),
|
||||||
|
@ -160,28 +159,21 @@ export const getLayersFormats = (
|
||||||
const getTitleForYAccessor = (
|
const getTitleForYAccessor = (
|
||||||
layerId: string,
|
layerId: string,
|
||||||
yAccessor: string | ExpressionValueVisDimension,
|
yAccessor: string | ExpressionValueVisDimension,
|
||||||
{ yTitle, yRightTitle }: Omit<CustomTitles, 'xTitle'>,
|
|
||||||
groups: GroupsConfiguration,
|
groups: GroupsConfiguration,
|
||||||
columns: Datatable['columns']
|
columns: Datatable['columns']
|
||||||
) => {
|
) => {
|
||||||
const column = getColumnByAccessor(yAccessor, columns);
|
const column = getColumnByAccessor(yAccessor, columns);
|
||||||
const isRight = groups.some((group) =>
|
const axisGroup = groups.find((group) =>
|
||||||
group.series.some(
|
group.series.some(({ accessor, layer }) => accessor === yAccessor && layer === layerId)
|
||||||
({ accessor, layer }) =>
|
|
||||||
accessor === yAccessor && layer === layerId && group.groupId === 'right'
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
if (isRight) {
|
|
||||||
return yRightTitle || column!.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
return yTitle || column!.name;
|
return axisGroup?.title || column!.name;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getLayerTitles = (
|
export const getLayerTitles = (
|
||||||
{ xAccessor, accessors, splitAccessor, table, layerId }: CommonXYDataLayerConfig,
|
{ xAccessor, accessors, splitAccessor, table, layerId }: CommonXYDataLayerConfig,
|
||||||
{ splitColumnAccessor, splitRowAccessor }: SplitAccessors,
|
{ splitColumnAccessor, splitRowAccessor }: SplitAccessors,
|
||||||
{ xTitle, yTitle, yRightTitle }: CustomTitles,
|
{ xTitle }: CustomTitles,
|
||||||
groups: GroupsConfiguration
|
groups: GroupsConfiguration
|
||||||
): LayerAccessorsTitles => {
|
): LayerAccessorsTitles => {
|
||||||
const mapTitle = (dimension?: string | ExpressionValueVisDimension) => {
|
const mapTitle = (dimension?: string | ExpressionValueVisDimension) => {
|
||||||
|
@ -194,13 +186,7 @@ export const getLayerTitles = (
|
||||||
};
|
};
|
||||||
|
|
||||||
const getYTitle = (accessor: string) => ({
|
const getYTitle = (accessor: string) => ({
|
||||||
[accessor]: getTitleForYAccessor(
|
[accessor]: getTitleForYAccessor(layerId, accessor, groups, table.columns),
|
||||||
layerId,
|
|
||||||
accessor,
|
|
||||||
{ yTitle, yRightTitle },
|
|
||||||
groups,
|
|
||||||
table.columns
|
|
||||||
),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const xColumnId = xAccessor && getAccessorByDimension(xAccessor, table.columns);
|
const xColumnId = xAccessor && getAccessorByDimension(xAccessor, table.columns);
|
||||||
|
|
|
@ -6,23 +6,15 @@
|
||||||
* Side Public License, v 1.
|
* Side Public License, v 1.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { CommonXYLayerConfig, SeriesType, ExtendedYConfig, YConfig } from '../../common';
|
import type {
|
||||||
|
CommonXYLayerConfig,
|
||||||
|
ReferenceLineDecorationConfig,
|
||||||
|
DataDecorationConfig,
|
||||||
|
} from '../../common';
|
||||||
import { getDataLayers, isAnnotationsLayer, isDataLayer, isReferenceLine } from './visualization';
|
import { getDataLayers, isAnnotationsLayer, isDataLayer, isReferenceLine } from './visualization';
|
||||||
|
|
||||||
export function isHorizontalSeries(seriesType: SeriesType) {
|
|
||||||
return (
|
|
||||||
seriesType === 'bar_horizontal' ||
|
|
||||||
seriesType === 'bar_horizontal_stacked' ||
|
|
||||||
seriesType === 'bar_horizontal_percentage_stacked'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isStackedChart(seriesType: SeriesType) {
|
|
||||||
return seriesType.includes('stacked');
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isHorizontalChart(layers: CommonXYLayerConfig[]) {
|
export function isHorizontalChart(layers: CommonXYLayerConfig[]) {
|
||||||
return getDataLayers(layers).every((l) => isHorizontalSeries(l.seriesType));
|
return getDataLayers(layers).every((l) => l.isHorizontal);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getSeriesColor = (layer: CommonXYLayerConfig, accessor: string) => {
|
export const getSeriesColor = (layer: CommonXYLayerConfig, accessor: string) => {
|
||||||
|
@ -33,6 +25,10 @@ export const getSeriesColor = (layer: CommonXYLayerConfig, accessor: string) =>
|
||||||
) {
|
) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const yConfig: Array<YConfig | ExtendedYConfig> | undefined = layer?.yConfig;
|
const decorations: Array<DataDecorationConfig | ReferenceLineDecorationConfig> | undefined =
|
||||||
return yConfig?.find((yConf) => yConf.forAccessor === accessor)?.color || null;
|
layer?.decorations;
|
||||||
|
return (
|
||||||
|
decorations?.find((decorationConfig) => decorationConfig.forAccessor === accessor)?.color ||
|
||||||
|
null
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,7 +10,7 @@ import {
|
||||||
LayerTypes,
|
LayerTypes,
|
||||||
REFERENCE_LINE,
|
REFERENCE_LINE,
|
||||||
REFERENCE_LINE_LAYER,
|
REFERENCE_LINE_LAYER,
|
||||||
REFERENCE_LINE_Y_CONFIG,
|
EXTENDED_REFERENCE_LINE_DECORATION_CONFIG,
|
||||||
} from '../../common/constants';
|
} from '../../common/constants';
|
||||||
import {
|
import {
|
||||||
CommonXYLayerConfig,
|
CommonXYLayerConfig,
|
||||||
|
@ -19,8 +19,8 @@ import {
|
||||||
CommonXYAnnotationLayerConfig,
|
CommonXYAnnotationLayerConfig,
|
||||||
ReferenceLineLayerConfig,
|
ReferenceLineLayerConfig,
|
||||||
ReferenceLineConfig,
|
ReferenceLineConfig,
|
||||||
ExtendedYConfigResult,
|
ReferenceLineDecorationConfigResult,
|
||||||
ReferenceLineYConfig,
|
ExtendedReferenceLineDecorationConfig,
|
||||||
} from '../../common/types';
|
} from '../../common/types';
|
||||||
|
|
||||||
export const isDataLayer = (layer: CommonXYLayerConfig): layer is CommonXYDataLayerConfig =>
|
export const isDataLayer = (layer: CommonXYLayerConfig): layer is CommonXYDataLayerConfig =>
|
||||||
|
@ -35,9 +35,10 @@ export const isReferenceLayer = (layer: CommonXYLayerConfig): layer is Reference
|
||||||
export const isReferenceLine = (layer: CommonXYLayerConfig): layer is ReferenceLineConfig =>
|
export const isReferenceLine = (layer: CommonXYLayerConfig): layer is ReferenceLineConfig =>
|
||||||
layer.type === REFERENCE_LINE;
|
layer.type === REFERENCE_LINE;
|
||||||
|
|
||||||
export const isReferenceLineYConfig = (
|
export const isReferenceLineDecorationConfig = (
|
||||||
yConfig: ReferenceLineYConfig | ExtendedYConfigResult
|
decoration: ExtendedReferenceLineDecorationConfig | ReferenceLineDecorationConfigResult
|
||||||
): yConfig is ReferenceLineYConfig => yConfig.type === REFERENCE_LINE_Y_CONFIG;
|
): decoration is ExtendedReferenceLineDecorationConfig =>
|
||||||
|
decoration.type === EXTENDED_REFERENCE_LINE_DECORATION_CONFIG;
|
||||||
|
|
||||||
export const isReferenceLineOrLayer = (
|
export const isReferenceLineOrLayer = (
|
||||||
layer: CommonXYLayerConfig
|
layer: CommonXYLayerConfig
|
||||||
|
|
|
@ -18,18 +18,16 @@ import {
|
||||||
xyVisFunction,
|
xyVisFunction,
|
||||||
layeredXyVisFunction,
|
layeredXyVisFunction,
|
||||||
extendedDataLayerFunction,
|
extendedDataLayerFunction,
|
||||||
|
dataDecorationConfigFunction,
|
||||||
|
xAxisConfigFunction,
|
||||||
yAxisConfigFunction,
|
yAxisConfigFunction,
|
||||||
extendedYAxisConfigFunction,
|
|
||||||
legendConfigFunction,
|
legendConfigFunction,
|
||||||
gridlinesConfigFunction,
|
|
||||||
axisExtentConfigFunction,
|
axisExtentConfigFunction,
|
||||||
tickLabelsConfigFunction,
|
|
||||||
referenceLineFunction,
|
referenceLineFunction,
|
||||||
referenceLineLayerFunction,
|
referenceLineLayerFunction,
|
||||||
annotationLayerFunction,
|
annotationLayerFunction,
|
||||||
labelsOrientationConfigFunction,
|
|
||||||
axisTitlesVisibilityConfigFunction,
|
|
||||||
extendedAnnotationLayerFunction,
|
extendedAnnotationLayerFunction,
|
||||||
|
referenceLineDecorationConfigFunction,
|
||||||
} from '../common/expression_functions';
|
} from '../common/expression_functions';
|
||||||
import { GetStartDepsFn, getXyChartRenderer } from './expression_renderers';
|
import { GetStartDepsFn, getXyChartRenderer } from './expression_renderers';
|
||||||
|
|
||||||
|
@ -55,18 +53,16 @@ export class ExpressionXyPlugin {
|
||||||
{ expressions, charts }: SetupDeps
|
{ expressions, charts }: SetupDeps
|
||||||
): ExpressionXyPluginSetup {
|
): ExpressionXyPluginSetup {
|
||||||
expressions.registerFunction(yAxisConfigFunction);
|
expressions.registerFunction(yAxisConfigFunction);
|
||||||
expressions.registerFunction(extendedYAxisConfigFunction);
|
expressions.registerFunction(dataDecorationConfigFunction);
|
||||||
|
expressions.registerFunction(referenceLineDecorationConfigFunction);
|
||||||
expressions.registerFunction(legendConfigFunction);
|
expressions.registerFunction(legendConfigFunction);
|
||||||
expressions.registerFunction(gridlinesConfigFunction);
|
|
||||||
expressions.registerFunction(extendedDataLayerFunction);
|
expressions.registerFunction(extendedDataLayerFunction);
|
||||||
expressions.registerFunction(axisExtentConfigFunction);
|
expressions.registerFunction(axisExtentConfigFunction);
|
||||||
expressions.registerFunction(tickLabelsConfigFunction);
|
expressions.registerFunction(xAxisConfigFunction);
|
||||||
expressions.registerFunction(annotationLayerFunction);
|
expressions.registerFunction(annotationLayerFunction);
|
||||||
expressions.registerFunction(extendedAnnotationLayerFunction);
|
expressions.registerFunction(extendedAnnotationLayerFunction);
|
||||||
expressions.registerFunction(labelsOrientationConfigFunction);
|
|
||||||
expressions.registerFunction(referenceLineFunction);
|
expressions.registerFunction(referenceLineFunction);
|
||||||
expressions.registerFunction(referenceLineLayerFunction);
|
expressions.registerFunction(referenceLineLayerFunction);
|
||||||
expressions.registerFunction(axisTitlesVisibilityConfigFunction);
|
|
||||||
expressions.registerFunction(xyVisFunction);
|
expressions.registerFunction(xyVisFunction);
|
||||||
expressions.registerFunction(layeredXyVisFunction);
|
expressions.registerFunction(layeredXyVisFunction);
|
||||||
|
|
||||||
|
|
|
@ -11,16 +11,14 @@ import { CoreSetup, CoreStart, Plugin } from '@kbn/core/server';
|
||||||
import { ExpressionXyPluginSetup, ExpressionXyPluginStart } from './types';
|
import { ExpressionXyPluginSetup, ExpressionXyPluginStart } from './types';
|
||||||
import {
|
import {
|
||||||
xyVisFunction,
|
xyVisFunction,
|
||||||
yAxisConfigFunction,
|
|
||||||
extendedYAxisConfigFunction,
|
|
||||||
legendConfigFunction,
|
legendConfigFunction,
|
||||||
gridlinesConfigFunction,
|
dataDecorationConfigFunction,
|
||||||
|
xAxisConfigFunction,
|
||||||
|
yAxisConfigFunction,
|
||||||
|
referenceLineDecorationConfigFunction,
|
||||||
axisExtentConfigFunction,
|
axisExtentConfigFunction,
|
||||||
tickLabelsConfigFunction,
|
|
||||||
annotationLayerFunction,
|
annotationLayerFunction,
|
||||||
labelsOrientationConfigFunction,
|
|
||||||
referenceLineFunction,
|
referenceLineFunction,
|
||||||
axisTitlesVisibilityConfigFunction,
|
|
||||||
extendedDataLayerFunction,
|
extendedDataLayerFunction,
|
||||||
referenceLineLayerFunction,
|
referenceLineLayerFunction,
|
||||||
layeredXyVisFunction,
|
layeredXyVisFunction,
|
||||||
|
@ -33,18 +31,16 @@ export class ExpressionXyPlugin
|
||||||
{
|
{
|
||||||
public setup(core: CoreSetup, { expressions }: SetupDeps) {
|
public setup(core: CoreSetup, { expressions }: SetupDeps) {
|
||||||
expressions.registerFunction(yAxisConfigFunction);
|
expressions.registerFunction(yAxisConfigFunction);
|
||||||
expressions.registerFunction(extendedYAxisConfigFunction);
|
expressions.registerFunction(dataDecorationConfigFunction);
|
||||||
|
expressions.registerFunction(xAxisConfigFunction);
|
||||||
|
expressions.registerFunction(referenceLineDecorationConfigFunction);
|
||||||
expressions.registerFunction(legendConfigFunction);
|
expressions.registerFunction(legendConfigFunction);
|
||||||
expressions.registerFunction(gridlinesConfigFunction);
|
|
||||||
expressions.registerFunction(extendedDataLayerFunction);
|
expressions.registerFunction(extendedDataLayerFunction);
|
||||||
expressions.registerFunction(axisExtentConfigFunction);
|
expressions.registerFunction(axisExtentConfigFunction);
|
||||||
expressions.registerFunction(tickLabelsConfigFunction);
|
|
||||||
expressions.registerFunction(annotationLayerFunction);
|
expressions.registerFunction(annotationLayerFunction);
|
||||||
expressions.registerFunction(extendedAnnotationLayerFunction);
|
expressions.registerFunction(extendedAnnotationLayerFunction);
|
||||||
expressions.registerFunction(labelsOrientationConfigFunction);
|
|
||||||
expressions.registerFunction(referenceLineFunction);
|
expressions.registerFunction(referenceLineFunction);
|
||||||
expressions.registerFunction(referenceLineLayerFunction);
|
expressions.registerFunction(referenceLineLayerFunction);
|
||||||
expressions.registerFunction(axisTitlesVisibilityConfigFunction);
|
|
||||||
expressions.registerFunction(xyVisFunction);
|
expressions.registerFunction(xyVisFunction);
|
||||||
expressions.registerFunction(layeredXyVisFunction);
|
expressions.registerFunction(layeredXyVisFunction);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,9 @@ export type {
|
||||||
ValidLayer,
|
ValidLayer,
|
||||||
XYDataLayerConfig,
|
XYDataLayerConfig,
|
||||||
XYAnnotationLayerConfig,
|
XYAnnotationLayerConfig,
|
||||||
|
YAxisMode,
|
||||||
|
SeriesType,
|
||||||
|
YConfig,
|
||||||
} from './xy_visualization/types';
|
} from './xy_visualization/types';
|
||||||
export type {
|
export type {
|
||||||
DatasourcePublicAPI,
|
DatasourcePublicAPI,
|
||||||
|
@ -74,13 +77,10 @@ export type {
|
||||||
} from './indexpattern_datasource/types';
|
} from './indexpattern_datasource/types';
|
||||||
export type {
|
export type {
|
||||||
XYArgs,
|
XYArgs,
|
||||||
ExtendedYConfig,
|
|
||||||
XYRender,
|
XYRender,
|
||||||
LayerType,
|
LayerType,
|
||||||
YAxisMode,
|
|
||||||
LineStyle,
|
LineStyle,
|
||||||
FillStyle,
|
FillStyle,
|
||||||
SeriesType,
|
|
||||||
YScaleType,
|
YScaleType,
|
||||||
XScaleType,
|
XScaleType,
|
||||||
AxisConfig,
|
AxisConfig,
|
||||||
|
@ -88,7 +88,6 @@ export type {
|
||||||
XYChartProps,
|
XYChartProps,
|
||||||
LegendConfig,
|
LegendConfig,
|
||||||
IconPosition,
|
IconPosition,
|
||||||
ExtendedYConfigResult,
|
|
||||||
DataLayerArgs,
|
DataLayerArgs,
|
||||||
ValueLabelMode,
|
ValueLabelMode,
|
||||||
AxisExtentMode,
|
AxisExtentMode,
|
||||||
|
@ -97,14 +96,9 @@ export type {
|
||||||
AxisExtentConfig,
|
AxisExtentConfig,
|
||||||
LegendConfigResult,
|
LegendConfigResult,
|
||||||
AxesSettingsConfig,
|
AxesSettingsConfig,
|
||||||
GridlinesConfigResult,
|
|
||||||
TickLabelsConfigResult,
|
|
||||||
AxisExtentConfigResult,
|
AxisExtentConfigResult,
|
||||||
ReferenceLineLayerArgs,
|
ReferenceLineLayerArgs,
|
||||||
LabelsOrientationConfig,
|
|
||||||
ReferenceLineLayerConfig,
|
ReferenceLineLayerConfig,
|
||||||
LabelsOrientationConfigResult,
|
|
||||||
AxisTitlesVisibilityConfigResult,
|
|
||||||
} from '@kbn/expression-xy-plugin/common';
|
} from '@kbn/expression-xy-plugin/common';
|
||||||
export type { LensEmbeddableInput, LensSavedObjectAttributes, Embeddable } from './embeddable';
|
export type { LensEmbeddableInput, LensSavedObjectAttributes, Embeddable } from './embeddable';
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
import React, { useCallback, useMemo } from 'react';
|
import React, { useCallback, useMemo } from 'react';
|
||||||
import { EuiSpacer, EuiFormRow } from '@elastic/eui';
|
import { EuiSpacer, EuiFormRow } from '@elastic/eui';
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
import { AxesSettingsConfig } from '@kbn/expression-xy-plugin/common';
|
import { AxesSettingsConfig } from '../xy_visualization/types';
|
||||||
import { LabelMode, useDebouncedValue, VisLabel } from '.';
|
import { LabelMode, useDebouncedValue, VisLabel } from '.';
|
||||||
|
|
||||||
type AxesSettingsConfigKeys = keyof AxesSettingsConfig;
|
type AxesSettingsConfigKeys = keyof AxesSettingsConfig;
|
||||||
|
|
|
@ -5,28 +5,6 @@ Object {
|
||||||
"chain": Array [
|
"chain": Array [
|
||||||
Object {
|
Object {
|
||||||
"arguments": Object {
|
"arguments": Object {
|
||||||
"axisTitlesVisibilitySettings": Array [
|
|
||||||
Object {
|
|
||||||
"chain": Array [
|
|
||||||
Object {
|
|
||||||
"arguments": Object {
|
|
||||||
"x": Array [
|
|
||||||
true,
|
|
||||||
],
|
|
||||||
"yLeft": Array [
|
|
||||||
true,
|
|
||||||
],
|
|
||||||
"yRight": Array [
|
|
||||||
true,
|
|
||||||
],
|
|
||||||
},
|
|
||||||
"function": "axisTitlesVisibilityConfig",
|
|
||||||
"type": "function",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"type": "expression",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"curveType": Array [
|
"curveType": Array [
|
||||||
"LINEAR",
|
"LINEAR",
|
||||||
],
|
],
|
||||||
|
@ -42,53 +20,9 @@ Object {
|
||||||
"fittingFunction": Array [
|
"fittingFunction": Array [
|
||||||
"Carry",
|
"Carry",
|
||||||
],
|
],
|
||||||
"gridlinesVisibilitySettings": Array [
|
|
||||||
Object {
|
|
||||||
"chain": Array [
|
|
||||||
Object {
|
|
||||||
"arguments": Object {
|
|
||||||
"x": Array [
|
|
||||||
false,
|
|
||||||
],
|
|
||||||
"yLeft": Array [
|
|
||||||
true,
|
|
||||||
],
|
|
||||||
"yRight": Array [
|
|
||||||
true,
|
|
||||||
],
|
|
||||||
},
|
|
||||||
"function": "gridlinesConfig",
|
|
||||||
"type": "function",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"type": "expression",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"hideEndzones": Array [
|
"hideEndzones": Array [
|
||||||
true,
|
true,
|
||||||
],
|
],
|
||||||
"labelsOrientation": Array [
|
|
||||||
Object {
|
|
||||||
"chain": Array [
|
|
||||||
Object {
|
|
||||||
"arguments": Object {
|
|
||||||
"x": Array [
|
|
||||||
0,
|
|
||||||
],
|
|
||||||
"yLeft": Array [
|
|
||||||
-90,
|
|
||||||
],
|
|
||||||
"yRight": Array [
|
|
||||||
-45,
|
|
||||||
],
|
|
||||||
},
|
|
||||||
"function": "labelsOrientationConfig",
|
|
||||||
"type": "function",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"type": "expression",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"layers": Array [
|
"layers": Array [
|
||||||
Object {
|
Object {
|
||||||
"chain": Array [
|
"chain": Array [
|
||||||
|
@ -101,12 +35,16 @@ Object {
|
||||||
"columnToLabel": Array [
|
"columnToLabel": Array [
|
||||||
"{\\"b\\":\\"col_b\\",\\"c\\":\\"col_c\\",\\"d\\":\\"col_d\\"}",
|
"{\\"b\\":\\"col_b\\",\\"c\\":\\"col_c\\",\\"d\\":\\"col_d\\"}",
|
||||||
],
|
],
|
||||||
|
"decorations": Array [],
|
||||||
"hide": Array [
|
"hide": Array [
|
||||||
false,
|
false,
|
||||||
],
|
],
|
||||||
"isHistogram": Array [
|
"isHistogram": Array [
|
||||||
false,
|
false,
|
||||||
],
|
],
|
||||||
|
"isHorizontal": Array [],
|
||||||
|
"isPercentage": Array [],
|
||||||
|
"isStacked": Array [],
|
||||||
"layerId": Array [
|
"layerId": Array [
|
||||||
"first",
|
"first",
|
||||||
],
|
],
|
||||||
|
@ -144,7 +82,6 @@ Object {
|
||||||
"xScaleType": Array [
|
"xScaleType": Array [
|
||||||
"linear",
|
"linear",
|
||||||
],
|
],
|
||||||
"yConfig": Array [],
|
|
||||||
},
|
},
|
||||||
"function": "extendedDataLayer",
|
"function": "extendedDataLayer",
|
||||||
"type": "function",
|
"type": "function",
|
||||||
|
@ -182,103 +119,138 @@ Object {
|
||||||
"type": "expression",
|
"type": "expression",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
"tickLabelsVisibilitySettings": Array [
|
|
||||||
Object {
|
|
||||||
"chain": Array [
|
|
||||||
Object {
|
|
||||||
"arguments": Object {
|
|
||||||
"x": Array [
|
|
||||||
false,
|
|
||||||
],
|
|
||||||
"yLeft": Array [
|
|
||||||
true,
|
|
||||||
],
|
|
||||||
"yRight": Array [
|
|
||||||
true,
|
|
||||||
],
|
|
||||||
},
|
|
||||||
"function": "tickLabelsConfig",
|
|
||||||
"type": "function",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"type": "expression",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"valueLabels": Array [
|
"valueLabels": Array [
|
||||||
"hide",
|
"hide",
|
||||||
],
|
],
|
||||||
"valuesInLegend": Array [
|
"valuesInLegend": Array [
|
||||||
false,
|
false,
|
||||||
],
|
],
|
||||||
"xExtent": Array [
|
"xAxisConfig": Array [
|
||||||
Object {
|
Object {
|
||||||
"chain": Array [
|
"chain": Array [
|
||||||
Object {
|
Object {
|
||||||
"arguments": Object {
|
"arguments": Object {
|
||||||
"lowerBound": Array [],
|
"extent": Array [],
|
||||||
"mode": Array [],
|
"id": Array [
|
||||||
"upperBound": Array [],
|
"x",
|
||||||
|
],
|
||||||
|
"labelsOrientation": Array [
|
||||||
|
0,
|
||||||
|
],
|
||||||
|
"position": Array [
|
||||||
|
"bottom",
|
||||||
|
],
|
||||||
|
"showGridLines": Array [
|
||||||
|
false,
|
||||||
|
],
|
||||||
|
"showLabels": Array [
|
||||||
|
false,
|
||||||
|
],
|
||||||
|
"showTitle": Array [
|
||||||
|
true,
|
||||||
|
],
|
||||||
|
"title": Array [
|
||||||
|
"",
|
||||||
|
],
|
||||||
},
|
},
|
||||||
"function": "axisExtentConfig",
|
"function": "xAxisConfig",
|
||||||
"type": "function",
|
"type": "function",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
"type": "expression",
|
"type": "expression",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
"xTitle": Array [
|
"yAxisConfigs": Array [
|
||||||
"",
|
|
||||||
],
|
|
||||||
"yLeftExtent": Array [
|
|
||||||
Object {
|
Object {
|
||||||
"chain": Array [
|
"chain": Array [
|
||||||
Object {
|
Object {
|
||||||
"arguments": Object {
|
"arguments": Object {
|
||||||
"lowerBound": Array [],
|
"extent": Array [],
|
||||||
"mode": Array [],
|
"id": Array [],
|
||||||
"upperBound": Array [],
|
"labelsOrientation": Array [
|
||||||
|
-90,
|
||||||
|
],
|
||||||
|
"position": Array [
|
||||||
|
"left",
|
||||||
|
],
|
||||||
|
"scaleType": Array [
|
||||||
|
"linear",
|
||||||
|
],
|
||||||
|
"showGridLines": Array [
|
||||||
|
true,
|
||||||
|
],
|
||||||
|
"showLabels": Array [
|
||||||
|
true,
|
||||||
|
],
|
||||||
|
"showTitle": Array [
|
||||||
|
true,
|
||||||
|
],
|
||||||
|
"title": Array [
|
||||||
|
"",
|
||||||
|
],
|
||||||
},
|
},
|
||||||
"function": "axisExtentConfig",
|
"function": "yAxisConfig",
|
||||||
"type": "function",
|
"type": "function",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
"type": "expression",
|
"type": "expression",
|
||||||
},
|
},
|
||||||
],
|
|
||||||
"yLeftScale": Array [
|
|
||||||
"linear",
|
|
||||||
],
|
|
||||||
"yRightExtent": Array [
|
|
||||||
Object {
|
Object {
|
||||||
"chain": Array [
|
"chain": Array [
|
||||||
Object {
|
Object {
|
||||||
"arguments": Object {
|
"arguments": Object {
|
||||||
"lowerBound": Array [
|
"extent": Array [
|
||||||
123,
|
Object {
|
||||||
|
"chain": Array [
|
||||||
|
Object {
|
||||||
|
"arguments": Object {
|
||||||
|
"lowerBound": Array [
|
||||||
|
123,
|
||||||
|
],
|
||||||
|
"mode": Array [
|
||||||
|
"custom",
|
||||||
|
],
|
||||||
|
"upperBound": Array [
|
||||||
|
456,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"function": "axisExtentConfig",
|
||||||
|
"type": "function",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"type": "expression",
|
||||||
|
},
|
||||||
],
|
],
|
||||||
"mode": Array [
|
"id": Array [],
|
||||||
"custom",
|
"labelsOrientation": Array [
|
||||||
|
-45,
|
||||||
],
|
],
|
||||||
"upperBound": Array [
|
"position": Array [
|
||||||
456,
|
"right",
|
||||||
|
],
|
||||||
|
"scaleType": Array [
|
||||||
|
"linear",
|
||||||
|
],
|
||||||
|
"showGridLines": Array [
|
||||||
|
true,
|
||||||
|
],
|
||||||
|
"showLabels": Array [
|
||||||
|
true,
|
||||||
|
],
|
||||||
|
"showTitle": Array [
|
||||||
|
true,
|
||||||
|
],
|
||||||
|
"title": Array [
|
||||||
|
"",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
"function": "axisExtentConfig",
|
"function": "yAxisConfig",
|
||||||
"type": "function",
|
"type": "function",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
"type": "expression",
|
"type": "expression",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
"yRightScale": Array [
|
|
||||||
"linear",
|
|
||||||
],
|
|
||||||
"yRightTitle": Array [
|
|
||||||
"",
|
|
||||||
],
|
|
||||||
"yTitle": Array [
|
|
||||||
"",
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
"function": "layeredXyVis",
|
"function": "layeredXyVis",
|
||||||
"type": "function",
|
"type": "function",
|
||||||
|
|
|
@ -7,13 +7,18 @@
|
||||||
|
|
||||||
import { groupBy, partition } from 'lodash';
|
import { groupBy, partition } from 'lodash';
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
import type { YAxisMode, ExtendedYConfig } from '@kbn/expression-xy-plugin/common';
|
|
||||||
import { Datatable } from '@kbn/expressions-plugin/public';
|
import { Datatable } from '@kbn/expressions-plugin/public';
|
||||||
import { layerTypes } from '../../common';
|
import { layerTypes } from '../../common';
|
||||||
import type { DatasourceLayers, FramePublicAPI, Visualization } from '../types';
|
import type { DatasourceLayers, FramePublicAPI, Visualization } from '../types';
|
||||||
import { groupAxesByType } from './axes_configuration';
|
import { groupAxesByType } from './axes_configuration';
|
||||||
import { isHorizontalChart, isPercentageSeries, isStackedChart } from './state_helpers';
|
import { isHorizontalChart, isPercentageSeries, isStackedChart } from './state_helpers';
|
||||||
import type { XYState, XYDataLayerConfig, XYReferenceLineLayerConfig } from './types';
|
import type {
|
||||||
|
XYState,
|
||||||
|
XYDataLayerConfig,
|
||||||
|
XYReferenceLineLayerConfig,
|
||||||
|
YAxisMode,
|
||||||
|
YConfig,
|
||||||
|
} from './types';
|
||||||
import {
|
import {
|
||||||
checkScaleOperation,
|
checkScaleOperation,
|
||||||
getAxisName,
|
getAxisName,
|
||||||
|
@ -35,7 +40,7 @@ export interface ReferenceLineBase {
|
||||||
* * what groups are current defined in data layers
|
* * what groups are current defined in data layers
|
||||||
* * what existing reference line are currently defined in reference layers
|
* * what existing reference line are currently defined in reference layers
|
||||||
*/
|
*/
|
||||||
export function getGroupsToShow<T extends ReferenceLineBase & { config?: ExtendedYConfig[] }>(
|
export function getGroupsToShow<T extends ReferenceLineBase & { config?: YConfig[] }>(
|
||||||
referenceLayers: T[],
|
referenceLayers: T[],
|
||||||
state: XYState | undefined,
|
state: XYState | undefined,
|
||||||
datasourceLayers: DatasourceLayers,
|
datasourceLayers: DatasourceLayers,
|
||||||
|
|
|
@ -6,13 +6,14 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { EuiIconType } from '@elastic/eui/src/components/icon/icon';
|
import { EuiIconType } from '@elastic/eui/src/components/icon/icon';
|
||||||
import type { SeriesType, ExtendedYConfig } from '@kbn/expression-xy-plugin/common';
|
|
||||||
import type { FramePublicAPI, DatasourcePublicAPI } from '../types';
|
import type { FramePublicAPI, DatasourcePublicAPI } from '../types';
|
||||||
import {
|
import {
|
||||||
visualizationTypes,
|
visualizationTypes,
|
||||||
XYLayerConfig,
|
XYLayerConfig,
|
||||||
XYDataLayerConfig,
|
XYDataLayerConfig,
|
||||||
XYReferenceLineLayerConfig,
|
XYReferenceLineLayerConfig,
|
||||||
|
SeriesType,
|
||||||
|
YConfig,
|
||||||
} from './types';
|
} from './types';
|
||||||
import { getDataLayers, isAnnotationsLayer, isDataLayer } from './visualization_helpers';
|
import { getDataLayers, isAnnotationsLayer, isDataLayer } from './visualization_helpers';
|
||||||
|
|
||||||
|
@ -58,8 +59,7 @@ export const getSeriesColor = (layer: XYLayerConfig, accessor: string) => {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
layer?.yConfig?.find((yConfig: ExtendedYConfig) => yConfig.forAccessor === accessor)?.color ||
|
layer?.yConfig?.find((yConfig: YConfig) => yConfig.forAccessor === accessor)?.color || null
|
||||||
null
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -159,13 +159,23 @@ describe('#toExpression', () => {
|
||||||
undefined,
|
undefined,
|
||||||
datasourceExpressionsByLayers
|
datasourceExpressionsByLayers
|
||||||
) as Ast;
|
) as Ast;
|
||||||
expect(
|
expect((expression.chain[0].arguments.yAxisConfigs[0] as Ast).chain[0].arguments).toEqual(
|
||||||
(expression.chain[0].arguments.axisTitlesVisibilitySettings[0] as Ast).chain[0].arguments
|
expect.objectContaining({
|
||||||
).toEqual({
|
showTitle: [true],
|
||||||
x: [true],
|
position: ['left'],
|
||||||
yLeft: [true],
|
})
|
||||||
yRight: [true],
|
);
|
||||||
});
|
expect((expression.chain[0].arguments.yAxisConfigs[1] as Ast).chain[0].arguments).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
showTitle: [true],
|
||||||
|
position: ['right'],
|
||||||
|
})
|
||||||
|
);
|
||||||
|
expect((expression.chain[0].arguments.xAxisConfig[0] as Ast).chain[0].arguments).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
showTitle: [true],
|
||||||
|
})
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should generate an expression without x accessor', () => {
|
it('should generate an expression without x accessor', () => {
|
||||||
|
@ -244,9 +254,6 @@ describe('#toExpression', () => {
|
||||||
expect(mockDatasource.publicAPIMock.getOperationForColumnId).toHaveBeenCalledWith('b');
|
expect(mockDatasource.publicAPIMock.getOperationForColumnId).toHaveBeenCalledWith('b');
|
||||||
expect(mockDatasource.publicAPIMock.getOperationForColumnId).toHaveBeenCalledWith('c');
|
expect(mockDatasource.publicAPIMock.getOperationForColumnId).toHaveBeenCalledWith('c');
|
||||||
expect(mockDatasource.publicAPIMock.getOperationForColumnId).toHaveBeenCalledWith('d');
|
expect(mockDatasource.publicAPIMock.getOperationForColumnId).toHaveBeenCalledWith('d');
|
||||||
expect(expression.chain[0].arguments.xTitle).toEqual(['']);
|
|
||||||
expect(expression.chain[0].arguments.yTitle).toEqual(['']);
|
|
||||||
expect(expression.chain[0].arguments.yRightTitle).toEqual(['']);
|
|
||||||
expect(
|
expect(
|
||||||
(expression.chain[0].arguments.layers[0] as Ast).chain[0].arguments.columnToLabel
|
(expression.chain[0].arguments.layers[0] as Ast).chain[0].arguments.columnToLabel
|
||||||
).toEqual([
|
).toEqual([
|
||||||
|
@ -279,13 +286,23 @@ describe('#toExpression', () => {
|
||||||
undefined,
|
undefined,
|
||||||
datasourceExpressionsByLayers
|
datasourceExpressionsByLayers
|
||||||
) as Ast;
|
) as Ast;
|
||||||
expect(
|
expect((expression.chain[0].arguments.yAxisConfigs[0] as Ast).chain[0].arguments).toEqual(
|
||||||
(expression.chain[0].arguments.tickLabelsVisibilitySettings[0] as Ast).chain[0].arguments
|
expect.objectContaining({
|
||||||
).toEqual({
|
showLabels: [true],
|
||||||
x: [true],
|
position: ['left'],
|
||||||
yLeft: [true],
|
})
|
||||||
yRight: [true],
|
);
|
||||||
});
|
expect((expression.chain[0].arguments.yAxisConfigs[1] as Ast).chain[0].arguments).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
showLabels: [true],
|
||||||
|
position: ['right'],
|
||||||
|
})
|
||||||
|
);
|
||||||
|
expect((expression.chain[0].arguments.xAxisConfig[0] as Ast).chain[0].arguments).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
showLabels: [true],
|
||||||
|
})
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should default the tick labels orientation settings to 0', () => {
|
it('should default the tick labels orientation settings to 0', () => {
|
||||||
|
@ -309,11 +326,23 @@ describe('#toExpression', () => {
|
||||||
undefined,
|
undefined,
|
||||||
datasourceExpressionsByLayers
|
datasourceExpressionsByLayers
|
||||||
) as Ast;
|
) as Ast;
|
||||||
expect((expression.chain[0].arguments.labelsOrientation[0] as Ast).chain[0].arguments).toEqual({
|
expect((expression.chain[0].arguments.yAxisConfigs[0] as Ast).chain[0].arguments).toEqual(
|
||||||
x: [0],
|
expect.objectContaining({
|
||||||
yLeft: [0],
|
labelsOrientation: [0],
|
||||||
yRight: [0],
|
position: ['left'],
|
||||||
});
|
})
|
||||||
|
);
|
||||||
|
expect((expression.chain[0].arguments.yAxisConfigs[1] as Ast).chain[0].arguments).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
labelsOrientation: [0],
|
||||||
|
position: ['right'],
|
||||||
|
})
|
||||||
|
);
|
||||||
|
expect((expression.chain[0].arguments.xAxisConfig[0] as Ast).chain[0].arguments).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
labelsOrientation: [0],
|
||||||
|
})
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should default the gridlines visibility settings to true', () => {
|
it('should default the gridlines visibility settings to true', () => {
|
||||||
|
@ -337,13 +366,23 @@ describe('#toExpression', () => {
|
||||||
undefined,
|
undefined,
|
||||||
datasourceExpressionsByLayers
|
datasourceExpressionsByLayers
|
||||||
) as Ast;
|
) as Ast;
|
||||||
expect(
|
expect((expression.chain[0].arguments.yAxisConfigs[0] as Ast).chain[0].arguments).toEqual(
|
||||||
(expression.chain[0].arguments.gridlinesVisibilitySettings[0] as Ast).chain[0].arguments
|
expect.objectContaining({
|
||||||
).toEqual({
|
showGridLines: [true],
|
||||||
x: [true],
|
position: ['left'],
|
||||||
yLeft: [true],
|
})
|
||||||
yRight: [true],
|
);
|
||||||
});
|
expect((expression.chain[0].arguments.yAxisConfigs[1] as Ast).chain[0].arguments).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
showGridLines: [true],
|
||||||
|
position: ['right'],
|
||||||
|
})
|
||||||
|
);
|
||||||
|
expect((expression.chain[0].arguments.xAxisConfig[0] as Ast).chain[0].arguments).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
showGridLines: [true],
|
||||||
|
})
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly report the valueLabels visibility settings', () => {
|
it('should correctly report the valueLabels visibility settings', () => {
|
||||||
|
@ -488,8 +527,9 @@ describe('#toExpression', () => {
|
||||||
) as Ast;
|
) as Ast;
|
||||||
|
|
||||||
function getYConfigColorForLayer(ast: Ast, index: number) {
|
function getYConfigColorForLayer(ast: Ast, index: number) {
|
||||||
return ((ast.chain[0].arguments.layers[index] as Ast).chain[0].arguments.yConfig[0] as Ast)
|
return (
|
||||||
.chain[0].arguments.color;
|
(ast.chain[0].arguments.layers[index] as Ast).chain[0].arguments.decorations[0] as Ast
|
||||||
|
).chain[0].arguments.color;
|
||||||
}
|
}
|
||||||
expect(getYConfigColorForLayer(expression, 0)).toEqual([]);
|
expect(getYConfigColorForLayer(expression, 0)).toEqual([]);
|
||||||
expect(getYConfigColorForLayer(expression, 1)).toEqual([defaultReferenceLineColor]);
|
expect(getYConfigColorForLayer(expression, 1)).toEqual([defaultReferenceLineColor]);
|
||||||
|
|
|
@ -8,15 +8,15 @@
|
||||||
import { Ast, AstFunction } from '@kbn/interpreter';
|
import { Ast, AstFunction } from '@kbn/interpreter';
|
||||||
import { Position, ScaleType } from '@elastic/charts';
|
import { Position, ScaleType } from '@elastic/charts';
|
||||||
import type { PaletteRegistry } from '@kbn/coloring';
|
import type { PaletteRegistry } from '@kbn/coloring';
|
||||||
|
|
||||||
import { EventAnnotationServiceType } from '@kbn/event-annotation-plugin/public';
|
import { EventAnnotationServiceType } from '@kbn/event-annotation-plugin/public';
|
||||||
import type { YConfig, ExtendedYConfig } from '@kbn/expression-xy-plugin/common';
|
|
||||||
import { LegendSize } from '@kbn/visualizations-plugin/public';
|
import { LegendSize } from '@kbn/visualizations-plugin/public';
|
||||||
import {
|
import {
|
||||||
State,
|
State,
|
||||||
|
YConfig,
|
||||||
XYDataLayerConfig,
|
XYDataLayerConfig,
|
||||||
XYReferenceLineLayerConfig,
|
XYReferenceLineLayerConfig,
|
||||||
XYAnnotationLayerConfig,
|
XYAnnotationLayerConfig,
|
||||||
|
AxisConfig,
|
||||||
} from './types';
|
} from './types';
|
||||||
import type { ValidXYDataLayerConfig } from './types';
|
import type { ValidXYDataLayerConfig } from './types';
|
||||||
import { OperationMetadata, DatasourcePublicAPI, DatasourceLayers } from '../types';
|
import { OperationMetadata, DatasourcePublicAPI, DatasourceLayers } from '../types';
|
||||||
|
@ -191,6 +191,54 @@ export const buildExpression = (
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isLeftAxis = validDataLayers.some(({ yConfig }) =>
|
||||||
|
yConfig?.some((config) => config.axisMode === Position.Left)
|
||||||
|
);
|
||||||
|
const isRightAxis = validDataLayers.some(({ yConfig }) =>
|
||||||
|
yConfig?.some((config) => config.axisMode === Position.Right)
|
||||||
|
);
|
||||||
|
|
||||||
|
const yAxisConfigs: AxisConfig[] = [
|
||||||
|
{
|
||||||
|
position: Position.Left,
|
||||||
|
extent: state?.yLeftExtent,
|
||||||
|
showTitle: state?.axisTitlesVisibilitySettings?.yLeft ?? true,
|
||||||
|
title: state.yTitle || '',
|
||||||
|
showLabels: state?.tickLabelsVisibilitySettings?.yLeft ?? true,
|
||||||
|
showGridLines: state?.gridlinesVisibilitySettings?.yLeft ?? true,
|
||||||
|
labelsOrientation: state?.labelsOrientation?.yLeft ?? 0,
|
||||||
|
scaleType: state.yLeftScale || 'linear',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
position: Position.Right,
|
||||||
|
extent: state?.yRightExtent,
|
||||||
|
showTitle: state?.axisTitlesVisibilitySettings?.yRight ?? true,
|
||||||
|
title: state.yRightTitle || '',
|
||||||
|
showLabels: state?.tickLabelsVisibilitySettings?.yRight ?? true,
|
||||||
|
showGridLines: state?.gridlinesVisibilitySettings?.yRight ?? true,
|
||||||
|
labelsOrientation: state?.labelsOrientation?.yRight ?? 0,
|
||||||
|
scaleType: state.yRightScale || 'linear',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
if (isLeftAxis) {
|
||||||
|
yAxisConfigs.push({
|
||||||
|
id: Position.Left,
|
||||||
|
position: Position.Left,
|
||||||
|
// we need also settings from global config here so that default's doesn't override it
|
||||||
|
...yAxisConfigs[0],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isRightAxis) {
|
||||||
|
yAxisConfigs.push({
|
||||||
|
id: Position.Right,
|
||||||
|
position: Position.Right,
|
||||||
|
// we need also settings from global config here so that default's doesn't override it
|
||||||
|
...yAxisConfigs[1],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: 'expression',
|
type: 'expression',
|
||||||
chain: [
|
chain: [
|
||||||
|
@ -198,9 +246,6 @@ export const buildExpression = (
|
||||||
type: 'function',
|
type: 'function',
|
||||||
function: 'layeredXyVis',
|
function: 'layeredXyVis',
|
||||||
arguments: {
|
arguments: {
|
||||||
xTitle: [state.xTitle || ''],
|
|
||||||
yTitle: [state.yTitle || ''],
|
|
||||||
yRightTitle: [state.yRightTitle || ''],
|
|
||||||
legend: [
|
legend: [
|
||||||
{
|
{
|
||||||
type: 'expression',
|
type: 'expression',
|
||||||
|
@ -252,82 +297,36 @@ export const buildExpression = (
|
||||||
emphasizeFitting: [state.emphasizeFitting || false],
|
emphasizeFitting: [state.emphasizeFitting || false],
|
||||||
curveType: [state.curveType || 'LINEAR'],
|
curveType: [state.curveType || 'LINEAR'],
|
||||||
fillOpacity: [state.fillOpacity || 0.3],
|
fillOpacity: [state.fillOpacity || 0.3],
|
||||||
xExtent: [axisExtentConfigToExpression(state.xExtent)],
|
|
||||||
yLeftExtent: [axisExtentConfigToExpression(state.yLeftExtent)],
|
|
||||||
yRightExtent: [axisExtentConfigToExpression(state.yRightExtent)],
|
|
||||||
yLeftScale: [state.yLeftScale || 'linear'],
|
|
||||||
yRightScale: [state.yRightScale || 'linear'],
|
|
||||||
axisTitlesVisibilitySettings: [
|
|
||||||
{
|
|
||||||
type: 'expression',
|
|
||||||
chain: [
|
|
||||||
{
|
|
||||||
type: 'function',
|
|
||||||
function: 'axisTitlesVisibilityConfig',
|
|
||||||
arguments: {
|
|
||||||
x: [state?.axisTitlesVisibilitySettings?.x ?? true],
|
|
||||||
yLeft: [state?.axisTitlesVisibilitySettings?.yLeft ?? true],
|
|
||||||
yRight: [state?.axisTitlesVisibilitySettings?.yRight ?? true],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
tickLabelsVisibilitySettings: [
|
|
||||||
{
|
|
||||||
type: 'expression',
|
|
||||||
chain: [
|
|
||||||
{
|
|
||||||
type: 'function',
|
|
||||||
function: 'tickLabelsConfig',
|
|
||||||
arguments: {
|
|
||||||
x: [state?.tickLabelsVisibilitySettings?.x ?? true],
|
|
||||||
yLeft: [state?.tickLabelsVisibilitySettings?.yLeft ?? true],
|
|
||||||
yRight: [state?.tickLabelsVisibilitySettings?.yRight ?? true],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
gridlinesVisibilitySettings: [
|
|
||||||
{
|
|
||||||
type: 'expression',
|
|
||||||
chain: [
|
|
||||||
{
|
|
||||||
type: 'function',
|
|
||||||
function: 'gridlinesConfig',
|
|
||||||
arguments: {
|
|
||||||
x: [state?.gridlinesVisibilitySettings?.x ?? true],
|
|
||||||
yLeft: [state?.gridlinesVisibilitySettings?.yLeft ?? true],
|
|
||||||
yRight: [state?.gridlinesVisibilitySettings?.yRight ?? true],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
labelsOrientation: [
|
|
||||||
{
|
|
||||||
type: 'expression',
|
|
||||||
chain: [
|
|
||||||
{
|
|
||||||
type: 'function',
|
|
||||||
function: 'labelsOrientationConfig',
|
|
||||||
arguments: {
|
|
||||||
x: [state?.labelsOrientation?.x ?? 0],
|
|
||||||
yLeft: [state?.labelsOrientation?.yLeft ?? 0],
|
|
||||||
yRight: [state?.labelsOrientation?.yRight ?? 0],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
valueLabels: [state?.valueLabels || 'hide'],
|
valueLabels: [state?.valueLabels || 'hide'],
|
||||||
hideEndzones: [state?.hideEndzones || false],
|
hideEndzones: [state?.hideEndzones || false],
|
||||||
valuesInLegend: [state?.valuesInLegend || false],
|
valuesInLegend: [state?.valuesInLegend || false],
|
||||||
|
yAxisConfigs: [...yAxisConfigsToExpression(yAxisConfigs)],
|
||||||
|
xAxisConfig: [
|
||||||
|
{
|
||||||
|
type: 'expression',
|
||||||
|
chain: [
|
||||||
|
{
|
||||||
|
type: 'function',
|
||||||
|
function: 'xAxisConfig',
|
||||||
|
arguments: {
|
||||||
|
id: ['x'],
|
||||||
|
position: ['bottom'],
|
||||||
|
title: [state.xTitle || ''],
|
||||||
|
showTitle: [state?.axisTitlesVisibilitySettings?.x ?? true],
|
||||||
|
showLabels: [state?.tickLabelsVisibilitySettings?.x ?? true],
|
||||||
|
showGridLines: [state?.gridlinesVisibilitySettings?.x ?? true],
|
||||||
|
labelsOrientation: [state?.labelsOrientation?.x ?? 0],
|
||||||
|
extent: state.xExtent ? [axisExtentConfigToExpression(state.xExtent)] : [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
layers: [
|
layers: [
|
||||||
...validDataLayers.map((layer) =>
|
...validDataLayers.map((layer) =>
|
||||||
dataLayerToExpression(
|
dataLayerToExpression(
|
||||||
layer,
|
layer,
|
||||||
|
yAxisConfigs,
|
||||||
datasourceLayers[layer.layerId],
|
datasourceLayers[layer.layerId],
|
||||||
metadata,
|
metadata,
|
||||||
paletteService,
|
paletteService,
|
||||||
|
@ -351,6 +350,29 @@ export const buildExpression = (
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const yAxisConfigsToExpression = (yAxisConfigs: AxisConfig[]): Ast[] => {
|
||||||
|
return yAxisConfigs.map((axis) => ({
|
||||||
|
type: 'expression',
|
||||||
|
chain: [
|
||||||
|
{
|
||||||
|
type: 'function',
|
||||||
|
function: 'yAxisConfig',
|
||||||
|
arguments: {
|
||||||
|
id: axis.id ? [axis.id] : [],
|
||||||
|
position: axis.position ? [axis.position] : [],
|
||||||
|
extent: axis.extent ? [axisExtentConfigToExpression(axis.extent)] : [],
|
||||||
|
showTitle: [axis.showTitle ?? true],
|
||||||
|
title: axis.title !== undefined ? [axis.title] : [],
|
||||||
|
showLabels: [axis.showLabels ?? true],
|
||||||
|
showGridLines: [axis.showGridLines ?? true],
|
||||||
|
labelsOrientation: axis.labelsOrientation !== undefined ? [axis.labelsOrientation] : [],
|
||||||
|
scaleType: axis.scaleType ? [axis.scaleType] : [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
const referenceLineLayerToExpression = (
|
const referenceLineLayerToExpression = (
|
||||||
layer: XYReferenceLineLayerConfig,
|
layer: XYReferenceLineLayerConfig,
|
||||||
datasourceLayer: DatasourcePublicAPI,
|
datasourceLayer: DatasourcePublicAPI,
|
||||||
|
@ -364,9 +386,9 @@ const referenceLineLayerToExpression = (
|
||||||
function: 'referenceLineLayer',
|
function: 'referenceLineLayer',
|
||||||
arguments: {
|
arguments: {
|
||||||
layerId: [layer.layerId],
|
layerId: [layer.layerId],
|
||||||
yConfig: layer.yConfig
|
decorations: layer.yConfig
|
||||||
? layer.yConfig.map((yConfig) =>
|
? layer.yConfig.map((yConfig) =>
|
||||||
extendedYConfigToExpression(yConfig, defaultReferenceLineColor)
|
extendedYConfigToRLDecorationConfigExpression(yConfig, defaultReferenceLineColor)
|
||||||
)
|
)
|
||||||
: [],
|
: [],
|
||||||
accessors: layer.accessors,
|
accessors: layer.accessors,
|
||||||
|
@ -402,6 +424,7 @@ const annotationLayerToExpression = (
|
||||||
|
|
||||||
const dataLayerToExpression = (
|
const dataLayerToExpression = (
|
||||||
layer: ValidXYDataLayerConfig,
|
layer: ValidXYDataLayerConfig,
|
||||||
|
yAxisConfigs: AxisConfig[],
|
||||||
datasourceLayer: DatasourcePublicAPI,
|
datasourceLayer: DatasourcePublicAPI,
|
||||||
metadata: Record<string, Record<string, OperationMetadata | null>>,
|
metadata: Record<string, Record<string, OperationMetadata | null>>,
|
||||||
paletteService: PaletteRegistry,
|
paletteService: PaletteRegistry,
|
||||||
|
@ -418,6 +441,12 @@ const dataLayerToExpression = (
|
||||||
xAxisOperation.scale !== 'ordinal'
|
xAxisOperation.scale !== 'ordinal'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const dataFromType = layer.seriesType.split('_');
|
||||||
|
const seriesType = dataFromType[0];
|
||||||
|
const isPercentage = dataFromType.includes('percentage');
|
||||||
|
const isStacked = dataFromType.includes('stacked');
|
||||||
|
const isHorizontal = dataFromType.includes('horizontal');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: 'expression',
|
type: 'expression',
|
||||||
chain: [
|
chain: [
|
||||||
|
@ -430,11 +459,16 @@ const dataLayerToExpression = (
|
||||||
xAccessor: layer.xAccessor ? [layer.xAccessor] : [],
|
xAccessor: layer.xAccessor ? [layer.xAccessor] : [],
|
||||||
xScaleType: [getScaleType(metadata[layer.layerId][layer.xAccessor], ScaleType.Linear)],
|
xScaleType: [getScaleType(metadata[layer.layerId][layer.xAccessor], ScaleType.Linear)],
|
||||||
isHistogram: [isHistogramDimension],
|
isHistogram: [isHistogramDimension],
|
||||||
|
isPercentage: isPercentage ? [isPercentage] : [],
|
||||||
|
isStacked: isStacked ? [isStacked] : [],
|
||||||
|
isHorizontal: isHorizontal ? [isHorizontal] : [],
|
||||||
splitAccessor: layer.collapseFn || !layer.splitAccessor ? [] : [layer.splitAccessor],
|
splitAccessor: layer.collapseFn || !layer.splitAccessor ? [] : [layer.splitAccessor],
|
||||||
yConfig: layer.yConfig
|
decorations: layer.yConfig
|
||||||
? layer.yConfig.map((yConfig) => yConfigToExpression(yConfig))
|
? layer.yConfig.map((yConfig) =>
|
||||||
|
yConfigToDataDecorationConfigExpression(yConfig, yAxisConfigs)
|
||||||
|
)
|
||||||
: [],
|
: [],
|
||||||
seriesType: [layer.seriesType],
|
seriesType: [seriesType],
|
||||||
accessors: layer.accessors,
|
accessors: layer.accessors,
|
||||||
columnToLabel: [JSON.stringify(columnToLabel)],
|
columnToLabel: [JSON.stringify(columnToLabel)],
|
||||||
...(datasourceExpression
|
...(datasourceExpression
|
||||||
|
@ -493,16 +527,21 @@ const dataLayerToExpression = (
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const yConfigToExpression = (yConfig: YConfig, defaultColor?: string): Ast => {
|
const yConfigToDataDecorationConfigExpression = (
|
||||||
|
yConfig: YConfig,
|
||||||
|
yAxisConfigs: AxisConfig[],
|
||||||
|
defaultColor?: string
|
||||||
|
): Ast => {
|
||||||
|
const axisId = yAxisConfigs.find((axis) => axis.id && axis.position === yConfig.axisMode)?.id;
|
||||||
return {
|
return {
|
||||||
type: 'expression',
|
type: 'expression',
|
||||||
chain: [
|
chain: [
|
||||||
{
|
{
|
||||||
type: 'function',
|
type: 'function',
|
||||||
function: 'yConfig',
|
function: 'dataDecorationConfig',
|
||||||
arguments: {
|
arguments: {
|
||||||
|
axisId: axisId ? [axisId] : [],
|
||||||
forAccessor: [yConfig.forAccessor],
|
forAccessor: [yConfig.forAccessor],
|
||||||
axisMode: yConfig.axisMode ? [yConfig.axisMode] : [],
|
|
||||||
color: yConfig.color ? [yConfig.color] : defaultColor ? [defaultColor] : [],
|
color: yConfig.color ? [yConfig.color] : defaultColor ? [defaultColor] : [],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -510,16 +549,19 @@ const yConfigToExpression = (yConfig: YConfig, defaultColor?: string): Ast => {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const extendedYConfigToExpression = (yConfig: ExtendedYConfig, defaultColor?: string): Ast => {
|
const extendedYConfigToRLDecorationConfigExpression = (
|
||||||
|
yConfig: YConfig,
|
||||||
|
defaultColor?: string
|
||||||
|
): Ast => {
|
||||||
return {
|
return {
|
||||||
type: 'expression',
|
type: 'expression',
|
||||||
chain: [
|
chain: [
|
||||||
{
|
{
|
||||||
type: 'function',
|
type: 'function',
|
||||||
function: 'extendedYConfig',
|
function: 'referenceLineDecorationConfig',
|
||||||
arguments: {
|
arguments: {
|
||||||
forAccessor: [yConfig.forAccessor],
|
forAccessor: [yConfig.forAccessor],
|
||||||
axisMode: yConfig.axisMode ? [yConfig.axisMode] : [],
|
position: yConfig.axisMode ? [yConfig.axisMode] : [],
|
||||||
color: yConfig.color ? [yConfig.color] : defaultColor ? [defaultColor] : [],
|
color: yConfig.color ? [yConfig.color] : defaultColor ? [defaultColor] : [],
|
||||||
lineStyle: [yConfig.lineStyle || 'solid'],
|
lineStyle: [yConfig.lineStyle || 'solid'],
|
||||||
lineWidth: [yConfig.lineWidth || 1],
|
lineWidth: [yConfig.lineWidth || 1],
|
||||||
|
|
|
@ -6,20 +6,20 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
|
import { $Values } from '@kbn/utility-types';
|
||||||
import type { PaletteOutput } from '@kbn/coloring';
|
import type { PaletteOutput } from '@kbn/coloring';
|
||||||
import type {
|
import type {
|
||||||
SeriesType,
|
|
||||||
LegendConfig,
|
LegendConfig,
|
||||||
AxisExtentConfig,
|
AxisExtentConfig,
|
||||||
XYCurveType,
|
XYCurveType,
|
||||||
AxesSettingsConfig,
|
|
||||||
FittingFunction,
|
FittingFunction,
|
||||||
LabelsOrientationConfig,
|
|
||||||
EndValue,
|
EndValue,
|
||||||
ExtendedYConfig,
|
|
||||||
YConfig,
|
|
||||||
YScaleType,
|
YScaleType,
|
||||||
XScaleType,
|
XScaleType,
|
||||||
|
LineStyle,
|
||||||
|
IconPosition,
|
||||||
|
FillStyle,
|
||||||
|
YAxisConfig,
|
||||||
} from '@kbn/expression-xy-plugin/common';
|
} from '@kbn/expression-xy-plugin/common';
|
||||||
import { EventAnnotationConfig } from '@kbn/event-annotation-plugin/common';
|
import { EventAnnotationConfig } from '@kbn/event-annotation-plugin/common';
|
||||||
import { LensIconChartArea } from '../assets/chart_area';
|
import { LensIconChartArea } from '../assets/chart_area';
|
||||||
|
@ -36,6 +36,56 @@ import { LensIconChartLine } from '../assets/chart_line';
|
||||||
import type { VisualizationType, Suggestion } from '../types';
|
import type { VisualizationType, Suggestion } from '../types';
|
||||||
import type { ValueLabelConfig } from '../../common/types';
|
import type { ValueLabelConfig } from '../../common/types';
|
||||||
|
|
||||||
|
export const YAxisModes = {
|
||||||
|
AUTO: 'auto',
|
||||||
|
LEFT: 'left',
|
||||||
|
RIGHT: 'right',
|
||||||
|
BOTTOM: 'bottom',
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export const SeriesTypes = {
|
||||||
|
BAR: 'bar',
|
||||||
|
LINE: 'line',
|
||||||
|
AREA: 'area',
|
||||||
|
BAR_STACKED: 'bar_stacked',
|
||||||
|
AREA_STACKED: 'area_stacked',
|
||||||
|
BAR_HORIZONTAL: 'bar_horizontal',
|
||||||
|
BAR_PERCENTAGE_STACKED: 'bar_percentage_stacked',
|
||||||
|
BAR_HORIZONTAL_STACKED: 'bar_horizontal_stacked',
|
||||||
|
AREA_PERCENTAGE_STACKED: 'area_percentage_stacked',
|
||||||
|
BAR_HORIZONTAL_PERCENTAGE_STACKED: 'bar_horizontal_percentage_stacked',
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export type YAxisMode = $Values<typeof YAxisModes>;
|
||||||
|
export type SeriesType = $Values<typeof SeriesTypes>;
|
||||||
|
export interface AxesSettingsConfig {
|
||||||
|
x: boolean;
|
||||||
|
yRight: boolean;
|
||||||
|
yLeft: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AxisConfig extends Omit<YAxisConfig, 'extent'> {
|
||||||
|
extent?: AxisExtentConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LabelsOrientationConfig {
|
||||||
|
x: number;
|
||||||
|
yLeft: number;
|
||||||
|
yRight: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface YConfig {
|
||||||
|
forAccessor: string;
|
||||||
|
color?: string;
|
||||||
|
icon?: string;
|
||||||
|
lineWidth?: number;
|
||||||
|
lineStyle?: LineStyle;
|
||||||
|
fill?: FillStyle;
|
||||||
|
iconPosition?: IconPosition;
|
||||||
|
textVisibility?: boolean;
|
||||||
|
axisMode?: YAxisMode;
|
||||||
|
}
|
||||||
|
|
||||||
export interface XYDataLayerConfig {
|
export interface XYDataLayerConfig {
|
||||||
layerId: string;
|
layerId: string;
|
||||||
accessors: string[];
|
accessors: string[];
|
||||||
|
@ -55,7 +105,7 @@ export interface XYDataLayerConfig {
|
||||||
export interface XYReferenceLineLayerConfig {
|
export interface XYReferenceLineLayerConfig {
|
||||||
layerId: string;
|
layerId: string;
|
||||||
accessors: string[];
|
accessors: string[];
|
||||||
yConfig?: ExtendedYConfig[];
|
yConfig?: YConfig[];
|
||||||
layerType: 'referenceLine';
|
layerType: 'referenceLine';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,9 +15,9 @@ import type {
|
||||||
XYLayerConfig,
|
XYLayerConfig,
|
||||||
XYDataLayerConfig,
|
XYDataLayerConfig,
|
||||||
XYReferenceLineLayerConfig,
|
XYReferenceLineLayerConfig,
|
||||||
|
SeriesType,
|
||||||
} from './types';
|
} from './types';
|
||||||
import { createDatatableUtilitiesMock } from '@kbn/data-plugin/common/mocks';
|
import { createDatatableUtilitiesMock } from '@kbn/data-plugin/common/mocks';
|
||||||
import type { SeriesType } from '@kbn/expression-xy-plugin/common';
|
|
||||||
import { layerTypes } from '../../common';
|
import { layerTypes } from '../../common';
|
||||||
import { createMockDatasource, createMockFramePublicAPI } from '../mocks';
|
import { createMockDatasource, createMockFramePublicAPI } from '../mocks';
|
||||||
import { LensIconChartBar } from '../assets/chart_bar';
|
import { LensIconChartBar } from '../assets/chart_bar';
|
||||||
|
|
|
@ -17,18 +17,22 @@ import { ThemeServiceStart } from '@kbn/core/public';
|
||||||
import { EventAnnotationServiceType } from '@kbn/event-annotation-plugin/public';
|
import { EventAnnotationServiceType } from '@kbn/event-annotation-plugin/public';
|
||||||
import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public';
|
import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public';
|
||||||
import { VIS_EVENT_TO_TRIGGER } from '@kbn/visualizations-plugin/public';
|
import { VIS_EVENT_TO_TRIGGER } from '@kbn/visualizations-plugin/public';
|
||||||
import {
|
import { FillStyle } from '@kbn/expression-xy-plugin/common';
|
||||||
FillStyle,
|
|
||||||
SeriesType,
|
|
||||||
YAxisMode,
|
|
||||||
ExtendedYConfig,
|
|
||||||
} from '@kbn/expression-xy-plugin/common';
|
|
||||||
import { getSuggestions } from './xy_suggestions';
|
import { getSuggestions } from './xy_suggestions';
|
||||||
import { XyToolbar } from './xy_config_panel';
|
import { XyToolbar } from './xy_config_panel';
|
||||||
import { DimensionEditor } from './xy_config_panel/dimension_editor';
|
import { DimensionEditor } from './xy_config_panel/dimension_editor';
|
||||||
import { LayerHeader } from './xy_config_panel/layer_header';
|
import { LayerHeader } from './xy_config_panel/layer_header';
|
||||||
import { Visualization, AccessorConfig, FramePublicAPI } from '../types';
|
import type { Visualization, AccessorConfig, FramePublicAPI } from '../types';
|
||||||
import { State, visualizationTypes, XYSuggestion, XYLayerConfig, XYDataLayerConfig } from './types';
|
import {
|
||||||
|
State,
|
||||||
|
visualizationTypes,
|
||||||
|
XYSuggestion,
|
||||||
|
XYLayerConfig,
|
||||||
|
XYDataLayerConfig,
|
||||||
|
YConfig,
|
||||||
|
YAxisMode,
|
||||||
|
SeriesType,
|
||||||
|
} from './types';
|
||||||
import { layerTypes } from '../../common';
|
import { layerTypes } from '../../common';
|
||||||
import { isHorizontalChart } from './state_helpers';
|
import { isHorizontalChart } from './state_helpers';
|
||||||
import { toExpression, toPreviewExpression, getSortedAccessors } from './to_expression';
|
import { toExpression, toPreviewExpression, getSortedAccessors } from './to_expression';
|
||||||
|
@ -360,7 +364,7 @@ export const getXyVisualization = ({
|
||||||
}
|
}
|
||||||
const isReferenceLine = metrics.some((metric) => metric.agg === 'static_value');
|
const isReferenceLine = metrics.some((metric) => metric.agg === 'static_value');
|
||||||
const axisMode = axisPosition as YAxisMode;
|
const axisMode = axisPosition as YAxisMode;
|
||||||
const yConfig = metrics.map<ExtendedYConfig>((metric, idx) => {
|
const yConfig = metrics.map<YConfig>((metric, idx) => {
|
||||||
return {
|
return {
|
||||||
color: metric.color,
|
color: metric.color,
|
||||||
forAccessor: metric.accessor ?? foundLayer.accessors[idx],
|
forAccessor: metric.accessor ?? foundLayer.accessors[idx],
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
|
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
import { uniq } from 'lodash';
|
import { uniq } from 'lodash';
|
||||||
import { SeriesType } from '@kbn/expression-xy-plugin/common';
|
|
||||||
import { DatasourceLayers, OperationMetadata, VisualizationType } from '../types';
|
import { DatasourceLayers, OperationMetadata, VisualizationType } from '../types';
|
||||||
import {
|
import {
|
||||||
State,
|
State,
|
||||||
|
@ -17,6 +16,7 @@ import {
|
||||||
XYLayerConfig,
|
XYLayerConfig,
|
||||||
XYDataLayerConfig,
|
XYDataLayerConfig,
|
||||||
XYReferenceLineLayerConfig,
|
XYReferenceLineLayerConfig,
|
||||||
|
SeriesType,
|
||||||
} from './types';
|
} from './types';
|
||||||
import { isHorizontalChart } from './state_helpers';
|
import { isHorizontalChart } from './state_helpers';
|
||||||
import { layerTypes } from '..';
|
import { layerTypes } from '..';
|
||||||
|
|
|
@ -16,9 +16,9 @@ import {
|
||||||
} from '@elastic/eui';
|
} from '@elastic/eui';
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
import { isEqual } from 'lodash';
|
import { isEqual } from 'lodash';
|
||||||
import { AxesSettingsConfig, AxisExtentConfig, YScaleType } from '@kbn/expression-xy-plugin/common';
|
import { AxisExtentConfig, YScaleType } from '@kbn/expression-xy-plugin/common';
|
||||||
import { ToolbarButtonProps } from '@kbn/kibana-react-plugin/public';
|
import { ToolbarButtonProps } from '@kbn/kibana-react-plugin/public';
|
||||||
import { XYLayerConfig } from '../types';
|
import { XYLayerConfig, AxesSettingsConfig } from '../types';
|
||||||
import {
|
import {
|
||||||
ToolbarPopover,
|
ToolbarPopover,
|
||||||
useDebouncedValue,
|
useDebouncedValue,
|
||||||
|
|
|
@ -10,9 +10,8 @@ import { i18n } from '@kbn/i18n';
|
||||||
import { EuiButtonGroup, EuiFormRow, htmlIdGenerator } from '@elastic/eui';
|
import { EuiButtonGroup, EuiFormRow, htmlIdGenerator } from '@elastic/eui';
|
||||||
import type { PaletteRegistry } from '@kbn/coloring';
|
import type { PaletteRegistry } from '@kbn/coloring';
|
||||||
import type { DatatableUtilitiesService } from '@kbn/data-plugin/common';
|
import type { DatatableUtilitiesService } from '@kbn/data-plugin/common';
|
||||||
import { YAxisMode, ExtendedYConfig } from '@kbn/expression-xy-plugin/common';
|
|
||||||
import type { VisualizationDimensionEditorProps } from '../../types';
|
import type { VisualizationDimensionEditorProps } from '../../types';
|
||||||
import { State, XYState, XYDataLayerConfig } from '../types';
|
import { State, XYState, XYDataLayerConfig, YConfig, YAxisMode } from '../types';
|
||||||
import { FormatFactory } from '../../../common';
|
import { FormatFactory } from '../../../common';
|
||||||
import { getSeriesColor, isHorizontalChart } from '../state_helpers';
|
import { getSeriesColor, isHorizontalChart } from '../state_helpers';
|
||||||
import { ColorPicker } from './color_picker';
|
import { ColorPicker } from './color_picker';
|
||||||
|
@ -81,7 +80,7 @@ export function DataDimensionEditor(
|
||||||
const axisMode = localYConfig?.axisMode || 'auto';
|
const axisMode = localYConfig?.axisMode || 'auto';
|
||||||
|
|
||||||
const setConfig = useCallback(
|
const setConfig = useCallback(
|
||||||
(yConfig: Partial<ExtendedYConfig> | undefined) => {
|
(yConfig: Partial<YConfig> | undefined) => {
|
||||||
if (yConfig == null) {
|
if (yConfig == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,10 +9,10 @@ import React, { memo, useCallback, useMemo, useState } from 'react';
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
import { Position, ScaleType } from '@elastic/charts';
|
import { Position, ScaleType } from '@elastic/charts';
|
||||||
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||||
import { AxesSettingsConfig, AxisExtentConfig } from '@kbn/expression-xy-plugin/common';
|
import { AxisExtentConfig } from '@kbn/expression-xy-plugin/common';
|
||||||
import { LegendSize } from '@kbn/visualizations-plugin/public';
|
import { LegendSize } from '@kbn/visualizations-plugin/public';
|
||||||
import type { VisualizationToolbarProps, FramePublicAPI } from '../../types';
|
import type { VisualizationToolbarProps, FramePublicAPI } from '../../types';
|
||||||
import { State, XYState } from '../types';
|
import { State, XYState, AxesSettingsConfig } from '../types';
|
||||||
import { isHorizontalChart } from '../state_helpers';
|
import { isHorizontalChart } from '../state_helpers';
|
||||||
import { hasNumericHistogramDimension, LegendSettingsPopover } from '../../shared_components';
|
import { hasNumericHistogramDimension, LegendSettingsPopover } from '../../shared_components';
|
||||||
import { AxisSettingsPopover } from './axis_settings_popover';
|
import { AxisSettingsPopover } from './axis_settings_popover';
|
||||||
|
|
|
@ -8,10 +8,9 @@
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
import { EuiIcon, EuiPopover, EuiSelectable, EuiText, EuiPopoverTitle } from '@elastic/eui';
|
import { EuiIcon, EuiPopover, EuiSelectable, EuiText, EuiPopoverTitle } from '@elastic/eui';
|
||||||
import { SeriesType } from '@kbn/expression-xy-plugin/common';
|
|
||||||
import { ToolbarButton } from '@kbn/kibana-react-plugin/public';
|
import { ToolbarButton } from '@kbn/kibana-react-plugin/public';
|
||||||
import type { VisualizationLayerWidgetProps, VisualizationType } from '../../types';
|
import type { VisualizationLayerWidgetProps, VisualizationType } from '../../types';
|
||||||
import { State, visualizationTypes } from '../types';
|
import { State, visualizationTypes, SeriesType } from '../types';
|
||||||
import { isHorizontalChart, isHorizontalSeries } from '../state_helpers';
|
import { isHorizontalChart, isHorizontalSeries } from '../state_helpers';
|
||||||
import { trackUiEvent } from '../../lens_ui_telemetry';
|
import { trackUiEvent } from '../../lens_ui_telemetry';
|
||||||
import { StaticHeader } from '../../shared_components';
|
import { StaticHeader } from '../../shared_components';
|
||||||
|
|
|
@ -9,9 +9,9 @@ import React, { useCallback } from 'react';
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
import { EuiButtonGroup, EuiFormRow } from '@elastic/eui';
|
import { EuiButtonGroup, EuiFormRow } from '@elastic/eui';
|
||||||
import type { PaletteRegistry } from '@kbn/coloring';
|
import type { PaletteRegistry } from '@kbn/coloring';
|
||||||
import { FillStyle, ExtendedYConfig } from '@kbn/expression-xy-plugin/common';
|
import { FillStyle } from '@kbn/expression-xy-plugin/common';
|
||||||
import type { VisualizationDimensionEditorProps } from '../../../types';
|
import type { VisualizationDimensionEditorProps } from '../../../types';
|
||||||
import { State, XYState, XYReferenceLineLayerConfig } from '../../types';
|
import { State, XYState, XYReferenceLineLayerConfig, YConfig } from '../../types';
|
||||||
import { FormatFactory } from '../../../../common';
|
import { FormatFactory } from '../../../../common';
|
||||||
|
|
||||||
import { ColorPicker } from '../color_picker';
|
import { ColorPicker } from '../color_picker';
|
||||||
|
@ -52,7 +52,7 @@ export const ReferenceLinePanel = (
|
||||||
);
|
);
|
||||||
|
|
||||||
const setConfig = useCallback(
|
const setConfig = useCallback(
|
||||||
(yConfig: Partial<ExtendedYConfig> | undefined) => {
|
(yConfig: Partial<YConfig> | undefined) => {
|
||||||
if (yConfig == null) {
|
if (yConfig == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -108,7 +108,7 @@ export const ReferenceLinePanel = (
|
||||||
|
|
||||||
interface LabelConfigurationOptions {
|
interface LabelConfigurationOptions {
|
||||||
isHorizontal: boolean;
|
isHorizontal: boolean;
|
||||||
axisMode: ExtendedYConfig['axisMode'];
|
axisMode: YConfig['axisMode'];
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFillPositionOptions({ isHorizontal, axisMode }: LabelConfigurationOptions) {
|
function getFillPositionOptions({ isHorizontal, axisMode }: LabelConfigurationOptions) {
|
||||||
|
@ -154,8 +154,8 @@ export const FillSetting = ({
|
||||||
setConfig,
|
setConfig,
|
||||||
isHorizontal,
|
isHorizontal,
|
||||||
}: {
|
}: {
|
||||||
currentConfig?: ExtendedYConfig;
|
currentConfig?: YConfig;
|
||||||
setConfig: (yConfig: Partial<ExtendedYConfig> | undefined) => void;
|
setConfig: (yConfig: Partial<YConfig> | undefined) => void;
|
||||||
isHorizontal: boolean;
|
isHorizontal: boolean;
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -8,7 +8,8 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
import { EuiButtonGroup, EuiFormRow } from '@elastic/eui';
|
import { EuiButtonGroup, EuiFormRow } from '@elastic/eui';
|
||||||
import { IconPosition, YAxisMode } from '@kbn/expression-xy-plugin/common';
|
import { IconPosition } from '@kbn/expression-xy-plugin/common';
|
||||||
|
import { YAxisMode } from '../../types';
|
||||||
|
|
||||||
import { TooltipWrapper } from '../../../shared_components';
|
import { TooltipWrapper } from '../../../shared_components';
|
||||||
import { hasIcon, IconSelect, IconSet } from './icon_select';
|
import { hasIcon, IconSelect, IconSet } from './icon_select';
|
||||||
|
|
|
@ -9,7 +9,6 @@ import { i18n } from '@kbn/i18n';
|
||||||
import { partition } from 'lodash';
|
import { partition } from 'lodash';
|
||||||
import { Position } from '@elastic/charts';
|
import { Position } from '@elastic/charts';
|
||||||
import type { PaletteOutput } from '@kbn/coloring';
|
import type { PaletteOutput } from '@kbn/coloring';
|
||||||
import type { SeriesType } from '@kbn/expression-xy-plugin/common';
|
|
||||||
import {
|
import {
|
||||||
SuggestionRequest,
|
SuggestionRequest,
|
||||||
VisualizationSuggestion,
|
VisualizationSuggestion,
|
||||||
|
@ -17,7 +16,14 @@ import {
|
||||||
TableSuggestion,
|
TableSuggestion,
|
||||||
TableChangeType,
|
TableChangeType,
|
||||||
} from '../types';
|
} from '../types';
|
||||||
import { State, XYState, visualizationTypes, XYLayerConfig, XYDataLayerConfig } from './types';
|
import {
|
||||||
|
State,
|
||||||
|
XYState,
|
||||||
|
visualizationTypes,
|
||||||
|
XYLayerConfig,
|
||||||
|
XYDataLayerConfig,
|
||||||
|
SeriesType,
|
||||||
|
} from './types';
|
||||||
import { layerTypes } from '../../common';
|
import { layerTypes } from '../../common';
|
||||||
import { getIconForSeries } from './state_helpers';
|
import { getIconForSeries } from './state_helpers';
|
||||||
import { getDataLayers, isDataLayer } from './visualization_helpers';
|
import { getDataLayers, isDataLayer } from './visualization_helpers';
|
||||||
|
|
|
@ -29,6 +29,7 @@ import {
|
||||||
TypedLensByValueInput,
|
TypedLensByValueInput,
|
||||||
XYCurveType,
|
XYCurveType,
|
||||||
XYState,
|
XYState,
|
||||||
|
YAxisMode,
|
||||||
} from '@kbn/lens-plugin/public';
|
} from '@kbn/lens-plugin/public';
|
||||||
import type { DataView } from '@kbn/data-views-plugin/common';
|
import type { DataView } from '@kbn/data-views-plugin/common';
|
||||||
import { PersistableFilter } from '@kbn/lens-plugin/common';
|
import { PersistableFilter } from '@kbn/lens-plugin/common';
|
||||||
|
@ -900,8 +901,8 @@ export class LensAttributes {
|
||||||
this.layerConfigs[0].indexPattern.fieldFormatMap[
|
this.layerConfigs[0].indexPattern.fieldFormatMap[
|
||||||
this.layerConfigs[0].selectedMetricField
|
this.layerConfigs[0].selectedMetricField
|
||||||
]?.id
|
]?.id
|
||||||
? 'left'
|
? ('left' as YAxisMode)
|
||||||
: 'right',
|
: ('right' as YAxisMode),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
xAccessor: `x-axis-column-layer${index}`,
|
xAccessor: `x-axis-column-layer${index}`,
|
||||||
|
|
|
@ -13,7 +13,7 @@ import type {
|
||||||
FieldBasedIndexPatternColumn,
|
FieldBasedIndexPatternColumn,
|
||||||
SeriesType,
|
SeriesType,
|
||||||
OperationType,
|
OperationType,
|
||||||
ExtendedYConfig,
|
YConfig,
|
||||||
} from '@kbn/lens-plugin/public';
|
} from '@kbn/lens-plugin/public';
|
||||||
|
|
||||||
import type { PersistableFilter } from '@kbn/lens-plugin/common';
|
import type { PersistableFilter } from '@kbn/lens-plugin/common';
|
||||||
|
@ -84,7 +84,7 @@ export interface SeriesConfig {
|
||||||
hasOperationType: boolean;
|
hasOperationType: boolean;
|
||||||
palette?: PaletteOutput;
|
palette?: PaletteOutput;
|
||||||
yTitle?: string;
|
yTitle?: string;
|
||||||
yConfig?: ExtendedYConfig[];
|
yConfig?: YConfig[];
|
||||||
query?: { query: string; language: 'kuery' };
|
query?: { query: string; language: 'kuery' };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3402,10 +3402,6 @@
|
||||||
"expressionXY.axisExtentConfig.help": "Configurer les étendues d’axe du graphique xy",
|
"expressionXY.axisExtentConfig.help": "Configurer les étendues d’axe du graphique xy",
|
||||||
"expressionXY.axisExtentConfig.lowerBound.help": "Limite inférieure",
|
"expressionXY.axisExtentConfig.lowerBound.help": "Limite inférieure",
|
||||||
"expressionXY.axisExtentConfig.upperBound.help": "Limite supérieure",
|
"expressionXY.axisExtentConfig.upperBound.help": "Limite supérieure",
|
||||||
"expressionXY.axisTitlesVisibilityConfig.help": "Configurer l’aspect des titres d’axe du graphique xy",
|
|
||||||
"expressionXY.axisTitlesVisibilityConfig.x.help": "Spécifie si le titre de l'axe X est visible ou non.",
|
|
||||||
"expressionXY.axisTitlesVisibilityConfig.yLeft.help": "Spécifie si le titre de l'axe Y de gauche est visible ou non.",
|
|
||||||
"expressionXY.axisTitlesVisibilityConfig.yRight.help": "Spécifie si le titre de l'axe Y de droite est visible ou non.",
|
|
||||||
"expressionXY.dataLayer.accessors.help": "Les colonnes à afficher sur l’axe y.",
|
"expressionXY.dataLayer.accessors.help": "Les colonnes à afficher sur l’axe y.",
|
||||||
"expressionXY.layer.columnToLabel.help": "Paires clé-valeur JSON de l’ID de colonne pour l’étiquette",
|
"expressionXY.layer.columnToLabel.help": "Paires clé-valeur JSON de l’ID de colonne pour l’étiquette",
|
||||||
"expressionXY.dataLayer.help": "Configurer un calque dans le graphique xy",
|
"expressionXY.dataLayer.help": "Configurer un calque dans le graphique xy",
|
||||||
|
@ -3417,15 +3413,6 @@
|
||||||
"expressionXY.dataLayer.splitAccessor.help": "Colonne selon laquelle effectuer la division",
|
"expressionXY.dataLayer.splitAccessor.help": "Colonne selon laquelle effectuer la division",
|
||||||
"expressionXY.dataLayer.xAccessor.help": "Axe X",
|
"expressionXY.dataLayer.xAccessor.help": "Axe X",
|
||||||
"expressionXY.dataLayer.xScaleType.help": "Type d’échelle de l’axe x",
|
"expressionXY.dataLayer.xScaleType.help": "Type d’échelle de l’axe x",
|
||||||
"expressionXY.dataLayer.yConfig.help": "Configuration supplémentaire pour les axes y",
|
|
||||||
"expressionXY.gridlinesConfig.help": "Configurer l’aspect du quadrillage du graphique xy",
|
|
||||||
"expressionXY.gridlinesConfig.x.help": "Spécifie si le quadrillage de l'axe X est visible ou non.",
|
|
||||||
"expressionXY.gridlinesConfig.yLeft.help": "Spécifie si le quadrillage de l'axe Y de gauche est visible ou non.",
|
|
||||||
"expressionXY.gridlinesConfig.yRight.help": "Spécifie si le quadrillage de l'axe Y de droite est visible ou non.",
|
|
||||||
"expressionXY.labelsOrientationConfig.help": "Configurer l’orientation des étiquettes de coche du graphique xy",
|
|
||||||
"expressionXY.labelsOrientationConfig.x.help": "Spécifie l'orientation des étiquettes de l'axe X.",
|
|
||||||
"expressionXY.labelsOrientationConfig.yLeft.help": "Spécifie l'orientation des étiquettes de l'axe Y de gauche.",
|
|
||||||
"expressionXY.labelsOrientationConfig.yRight.help": "Spécifie l'orientation des étiquettes de l'axe Y de droite.",
|
|
||||||
"expressionXY.legend.filterForValueButtonAriaLabel": "Filtrer sur la valeur",
|
"expressionXY.legend.filterForValueButtonAriaLabel": "Filtrer sur la valeur",
|
||||||
"expressionXY.legend.filterOptionsLegend": "{legendDataLabel}, options de filtre",
|
"expressionXY.legend.filterOptionsLegend": "{legendDataLabel}, options de filtre",
|
||||||
"expressionXY.legend.filterOutValueButtonAriaLabel": "Exclure la valeur",
|
"expressionXY.legend.filterOutValueButtonAriaLabel": "Exclure la valeur",
|
||||||
|
@ -3442,11 +3429,6 @@
|
||||||
"expressionXY.legendConfig.verticalAlignment.help": "Spécifie l'alignement vertical de la légende lorsqu'elle est affichée à l'intérieur du graphique.",
|
"expressionXY.legendConfig.verticalAlignment.help": "Spécifie l'alignement vertical de la légende lorsqu'elle est affichée à l'intérieur du graphique.",
|
||||||
"expressionXY.referenceLineLayer.accessors.help": "Les colonnes à afficher sur l’axe y.",
|
"expressionXY.referenceLineLayer.accessors.help": "Les colonnes à afficher sur l’axe y.",
|
||||||
"expressionXY.referenceLineLayer.help": "Configurer une ligne de référence dans le graphique xy",
|
"expressionXY.referenceLineLayer.help": "Configurer une ligne de référence dans le graphique xy",
|
||||||
"expressionXY.referenceLineLayer.yConfig.help": "Configuration supplémentaire pour les axes y",
|
|
||||||
"expressionXY.tickLabelsConfig.help": "Configurer l’aspect des étiquettes de coche du graphique xy",
|
|
||||||
"expressionXY.tickLabelsConfig.x.help": "Spécifie si les étiquettes de graduation de l'axe X sont visibles ou non.",
|
|
||||||
"expressionXY.tickLabelsConfig.yLeft.help": "Spécifie si les étiquettes de graduation de l'axe Y de gauche sont visibles ou non.",
|
|
||||||
"expressionXY.tickLabelsConfig.yRight.help": "Spécifie si les étiquettes de graduation de l'axe Y de droite sont visibles ou non.",
|
|
||||||
"expressionXY.xyChart.emptyXLabel": "(vide)",
|
"expressionXY.xyChart.emptyXLabel": "(vide)",
|
||||||
"expressionXY.xyChart.iconSelect.alertIconLabel": "Alerte",
|
"expressionXY.xyChart.iconSelect.alertIconLabel": "Alerte",
|
||||||
"expressionXY.xyChart.iconSelect.asteriskIconLabel": "Astérisque",
|
"expressionXY.xyChart.iconSelect.asteriskIconLabel": "Astérisque",
|
||||||
|
@ -3463,39 +3445,20 @@
|
||||||
"expressionXY.xyChart.iconSelect.tagIconLabel": "Balise",
|
"expressionXY.xyChart.iconSelect.tagIconLabel": "Balise",
|
||||||
"expressionXY.xyChart.iconSelect.triangleIconLabel": "Triangle",
|
"expressionXY.xyChart.iconSelect.triangleIconLabel": "Triangle",
|
||||||
"expressionXY.xyVis.ariaLabel.help": "Spécifie l’attribut aria-label du graphique xy",
|
"expressionXY.xyVis.ariaLabel.help": "Spécifie l’attribut aria-label du graphique xy",
|
||||||
"expressionXY.xyVis.axisTitlesVisibilitySettings.help": "Afficher les titres des axes X et Y",
|
|
||||||
"expressionXY.xyVis.curveType.help": "Définir de quelle façon le type de courbe est rendu pour un graphique linéaire",
|
"expressionXY.xyVis.curveType.help": "Définir de quelle façon le type de courbe est rendu pour un graphique linéaire",
|
||||||
"expressionXY.xyVis.endValue.help": "Valeur de fin",
|
"expressionXY.xyVis.endValue.help": "Valeur de fin",
|
||||||
"expressionXY.xyVis.fillOpacity.help": "Définir l'opacité du remplissage du graphique en aires",
|
"expressionXY.xyVis.fillOpacity.help": "Définir l'opacité du remplissage du graphique en aires",
|
||||||
"expressionXY.xyVis.fittingFunction.help": "Définir le mode de traitement des valeurs manquantes",
|
"expressionXY.xyVis.fittingFunction.help": "Définir le mode de traitement des valeurs manquantes",
|
||||||
"expressionXY.xyVis.gridlinesVisibilitySettings.help": "Afficher le quadrillage des axes X et Y",
|
|
||||||
"expressionXY.xyVis.help": "Graphique X/Y",
|
"expressionXY.xyVis.help": "Graphique X/Y",
|
||||||
"expressionXY.xyVis.hideEndzones.help": "Masquer les marqueurs de zone de fin pour les données partielles",
|
"expressionXY.xyVis.hideEndzones.help": "Masquer les marqueurs de zone de fin pour les données partielles",
|
||||||
"expressionXY.xyVis.labelsOrientation.help": "Définit la rotation des étiquettes des axes",
|
|
||||||
"expressionXY.layeredXyVis.layers.help": "Calques de série visuelle",
|
"expressionXY.layeredXyVis.layers.help": "Calques de série visuelle",
|
||||||
"expressionXY.xyVis.legend.help": "Configurez la légende du graphique.",
|
"expressionXY.xyVis.legend.help": "Configurez la légende du graphique.",
|
||||||
"expressionXY.xyVis.logDatatable.breakDown": "Répartir par",
|
"expressionXY.xyVis.logDatatable.breakDown": "Répartir par",
|
||||||
"expressionXY.xyVis.logDatatable.metric": "Axe vertical",
|
"expressionXY.xyVis.logDatatable.metric": "Axe vertical",
|
||||||
"expressionXY.xyVis.logDatatable.x": "Axe horizontal",
|
"expressionXY.xyVis.logDatatable.x": "Axe horizontal",
|
||||||
"expressionXY.xyVis.renderer.help": "Outil de rendu de graphique X/Y",
|
"expressionXY.xyVis.renderer.help": "Outil de rendu de graphique X/Y",
|
||||||
"expressionXY.xyVis.tickLabelsVisibilitySettings.help": "Afficher les étiquettes de graduation des axes X et Y",
|
|
||||||
"expressionXY.xyVis.valueLabels.help": "Mode des étiquettes de valeur",
|
"expressionXY.xyVis.valueLabels.help": "Mode des étiquettes de valeur",
|
||||||
"expressionXY.xyVis.valuesInLegend.help": "Afficher les valeurs dans la légende",
|
"expressionXY.xyVis.valuesInLegend.help": "Afficher les valeurs dans la légende",
|
||||||
"expressionXY.xyVis.xTitle.help": "Titre de l'axe X",
|
|
||||||
"expressionXY.xyVis.yLeftExtent.help": "Portée de l'axe Y de gauche",
|
|
||||||
"expressionXY.xyVis.yLeftTitle.help": "Titre de l'axe Y de gauche",
|
|
||||||
"expressionXY.xyVis.yRightExtent.help": "Portée de l'axe Y de droite",
|
|
||||||
"expressionXY.xyVis.yRightTitle.help": "Titre de l'axe Y de droite",
|
|
||||||
"expressionXY.yConfig.axisMode.help": "Le mode axe de l’indicateur",
|
|
||||||
"expressionXY.yConfig.color.help": "La couleur des séries",
|
|
||||||
"expressionXY.yConfig.fill.help": "Remplir",
|
|
||||||
"expressionXY.yConfig.forAccessor.help": "L’accesseur auquel cette configuration s’applique",
|
|
||||||
"expressionXY.yConfig.help": "Configurer le comportement de l’indicateur d’axe y d’un graphique xy",
|
|
||||||
"expressionXY.yConfig.icon.help": "Icône facultative utilisée pour les lignes de référence",
|
|
||||||
"expressionXY.yConfig.iconPosition.help": "Le placement de l’icône pour la ligne de référence",
|
|
||||||
"expressionXY.yConfig.lineStyle.help": "Le style de la ligne de référence",
|
|
||||||
"expressionXY.yConfig.lineWidth.help": "La largeur de la ligne de référence",
|
|
||||||
"expressionXY.yConfig.textVisibility.help": "Visibilité de l’étiquette sur la ligne de référence",
|
|
||||||
"fieldFormats.advancedSettings.format.bytesFormat.numeralFormatLinkText": "Format numérique",
|
"fieldFormats.advancedSettings.format.bytesFormat.numeralFormatLinkText": "Format numérique",
|
||||||
"fieldFormats.advancedSettings.format.bytesFormatText": "{numeralFormatLink} par défaut pour le format \"octets\"",
|
"fieldFormats.advancedSettings.format.bytesFormatText": "{numeralFormatLink} par défaut pour le format \"octets\"",
|
||||||
"fieldFormats.advancedSettings.format.bytesFormatTitle": "Format octets",
|
"fieldFormats.advancedSettings.format.bytesFormatTitle": "Format octets",
|
||||||
|
|
|
@ -3501,10 +3501,6 @@
|
||||||
"expressionXY.axisExtentConfig.help": "xyグラフの軸範囲を構成",
|
"expressionXY.axisExtentConfig.help": "xyグラフの軸範囲を構成",
|
||||||
"expressionXY.axisExtentConfig.lowerBound.help": "下界",
|
"expressionXY.axisExtentConfig.lowerBound.help": "下界",
|
||||||
"expressionXY.axisExtentConfig.upperBound.help": "上界",
|
"expressionXY.axisExtentConfig.upperBound.help": "上界",
|
||||||
"expressionXY.axisTitlesVisibilityConfig.help": "xyグラフの軸タイトル表示を構成",
|
|
||||||
"expressionXY.axisTitlesVisibilityConfig.x.help": "x軸のタイトルを表示するかどうかを指定します。",
|
|
||||||
"expressionXY.axisTitlesVisibilityConfig.yLeft.help": "左y軸のタイトルを表示するかどうかを指定します。",
|
|
||||||
"expressionXY.axisTitlesVisibilityConfig.yRight.help": "右y軸のタイトルを表示するかどうかを指定します。",
|
|
||||||
"expressionXY.dataLayer.accessors.help": "y軸に表示する列。",
|
"expressionXY.dataLayer.accessors.help": "y軸に表示する列。",
|
||||||
"expressionXY.layer.columnToLabel.help": "ラベリングする列IDのJSONキー値のペア",
|
"expressionXY.layer.columnToLabel.help": "ラベリングする列IDのJSONキー値のペア",
|
||||||
"expressionXY.dataLayer.help": "xyグラフでレイヤーを構成",
|
"expressionXY.dataLayer.help": "xyグラフでレイヤーを構成",
|
||||||
|
@ -3516,15 +3512,6 @@
|
||||||
"expressionXY.dataLayer.splitAccessor.help": "分割の基準となる列",
|
"expressionXY.dataLayer.splitAccessor.help": "分割の基準となる列",
|
||||||
"expressionXY.dataLayer.xAccessor.help": "X 軸",
|
"expressionXY.dataLayer.xAccessor.help": "X 軸",
|
||||||
"expressionXY.dataLayer.xScaleType.help": "x軸の目盛タイプ",
|
"expressionXY.dataLayer.xScaleType.help": "x軸の目盛タイプ",
|
||||||
"expressionXY.dataLayer.yConfig.help": "y軸の詳細構成",
|
|
||||||
"expressionXY.gridlinesConfig.help": "xyグラフのグリッド線表示を構成",
|
|
||||||
"expressionXY.gridlinesConfig.x.help": "x 軸のグリッド線を表示するかどうかを指定します。",
|
|
||||||
"expressionXY.gridlinesConfig.yLeft.help": "左y軸のグリッド線を表示するかどうかを指定します。",
|
|
||||||
"expressionXY.gridlinesConfig.yRight.help": "右y軸のグリッド線を表示するかどうかを指定します。",
|
|
||||||
"expressionXY.labelsOrientationConfig.help": "xyグラフのティックラベルの向きを構成",
|
|
||||||
"expressionXY.labelsOrientationConfig.x.help": "x軸のラベルの向きを指定します。",
|
|
||||||
"expressionXY.labelsOrientationConfig.yLeft.help": "左y軸のラベルの向きを指定します。",
|
|
||||||
"expressionXY.labelsOrientationConfig.yRight.help": "右y軸のラベルの向きを指定します。",
|
|
||||||
"expressionXY.legend.filterForValueButtonAriaLabel": "値でフィルター",
|
"expressionXY.legend.filterForValueButtonAriaLabel": "値でフィルター",
|
||||||
"expressionXY.legend.filterOptionsLegend": "{legendDataLabel}、フィルターオプション",
|
"expressionXY.legend.filterOptionsLegend": "{legendDataLabel}、フィルターオプション",
|
||||||
"expressionXY.legend.filterOutValueButtonAriaLabel": "値を除外",
|
"expressionXY.legend.filterOutValueButtonAriaLabel": "値を除外",
|
||||||
|
@ -3541,11 +3528,6 @@
|
||||||
"expressionXY.legendConfig.verticalAlignment.help": "凡例がグラフ内に表示されるときに凡例の縦の配置を指定します。",
|
"expressionXY.legendConfig.verticalAlignment.help": "凡例がグラフ内に表示されるときに凡例の縦の配置を指定します。",
|
||||||
"expressionXY.referenceLineLayer.accessors.help": "y軸に表示する列。",
|
"expressionXY.referenceLineLayer.accessors.help": "y軸に表示する列。",
|
||||||
"expressionXY.referenceLineLayer.help": "xyグラフで基準線を構成",
|
"expressionXY.referenceLineLayer.help": "xyグラフで基準線を構成",
|
||||||
"expressionXY.referenceLineLayer.yConfig.help": "y軸の詳細構成",
|
|
||||||
"expressionXY.tickLabelsConfig.help": "xyグラフのティックラベルの表示を構成",
|
|
||||||
"expressionXY.tickLabelsConfig.x.help": "x軸の目盛ラベルを表示するかどうかを指定します。",
|
|
||||||
"expressionXY.tickLabelsConfig.yLeft.help": "左y軸の目盛ラベルを表示するかどうかを指定します。",
|
|
||||||
"expressionXY.tickLabelsConfig.yRight.help": "右y軸の目盛ラベルを表示するかどうかを指定します。",
|
|
||||||
"expressionXY.xyChart.emptyXLabel": "(空)",
|
"expressionXY.xyChart.emptyXLabel": "(空)",
|
||||||
"expressionXY.xyChart.iconSelect.alertIconLabel": "アラート",
|
"expressionXY.xyChart.iconSelect.alertIconLabel": "アラート",
|
||||||
"expressionXY.xyChart.iconSelect.asteriskIconLabel": "アスタリスク",
|
"expressionXY.xyChart.iconSelect.asteriskIconLabel": "アスタリスク",
|
||||||
|
@ -3562,39 +3544,20 @@
|
||||||
"expressionXY.xyChart.iconSelect.tagIconLabel": "タグ",
|
"expressionXY.xyChart.iconSelect.tagIconLabel": "タグ",
|
||||||
"expressionXY.xyChart.iconSelect.triangleIconLabel": "三角形",
|
"expressionXY.xyChart.iconSelect.triangleIconLabel": "三角形",
|
||||||
"expressionXY.xyVis.ariaLabel.help": "xyグラフのariaラベルを指定します",
|
"expressionXY.xyVis.ariaLabel.help": "xyグラフのariaラベルを指定します",
|
||||||
"expressionXY.xyVis.axisTitlesVisibilitySettings.help": "xおよびy軸のタイトルを表示",
|
|
||||||
"expressionXY.xyVis.curveType.help": "折れ線グラフで曲線タイプをレンダリングする方法を定義します",
|
"expressionXY.xyVis.curveType.help": "折れ線グラフで曲線タイプをレンダリングする方法を定義します",
|
||||||
"expressionXY.xyVis.endValue.help": "終了値",
|
"expressionXY.xyVis.endValue.help": "終了値",
|
||||||
"expressionXY.xyVis.fillOpacity.help": "エリアグラフの塗りつぶしの透明度を定義",
|
"expressionXY.xyVis.fillOpacity.help": "エリアグラフの塗りつぶしの透明度を定義",
|
||||||
"expressionXY.xyVis.fittingFunction.help": "欠測値の処理方法を定義",
|
"expressionXY.xyVis.fittingFunction.help": "欠測値の処理方法を定義",
|
||||||
"expressionXY.xyVis.gridlinesVisibilitySettings.help": "xおよびy軸のグリッド線を表示",
|
|
||||||
"expressionXY.xyVis.help": "X/Y チャート",
|
"expressionXY.xyVis.help": "X/Y チャート",
|
||||||
"expressionXY.xyVis.hideEndzones.help": "部分データの終了ゾーンマーカーを非表示",
|
"expressionXY.xyVis.hideEndzones.help": "部分データの終了ゾーンマーカーを非表示",
|
||||||
"expressionXY.xyVis.labelsOrientation.help": "軸ラベルの回転を定義します",
|
|
||||||
"expressionXY.layeredXyVis.layers.help": "視覚的な系列のレイヤー",
|
"expressionXY.layeredXyVis.layers.help": "視覚的な系列のレイヤー",
|
||||||
"expressionXY.xyVis.legend.help": "チャートの凡例を構成します。",
|
"expressionXY.xyVis.legend.help": "チャートの凡例を構成します。",
|
||||||
"expressionXY.xyVis.logDatatable.breakDown": "内訳の基準",
|
"expressionXY.xyVis.logDatatable.breakDown": "内訳の基準",
|
||||||
"expressionXY.xyVis.logDatatable.metric": "縦軸",
|
"expressionXY.xyVis.logDatatable.metric": "縦軸",
|
||||||
"expressionXY.xyVis.logDatatable.x": "横軸",
|
"expressionXY.xyVis.logDatatable.x": "横軸",
|
||||||
"expressionXY.xyVis.renderer.help": "X/Y チャートを再レンダリング",
|
"expressionXY.xyVis.renderer.help": "X/Y チャートを再レンダリング",
|
||||||
"expressionXY.xyVis.tickLabelsVisibilitySettings.help": "xおよびy軸の目盛ラベルを表示",
|
|
||||||
"expressionXY.xyVis.valueLabels.help": "値ラベルモード",
|
"expressionXY.xyVis.valueLabels.help": "値ラベルモード",
|
||||||
"expressionXY.xyVis.valuesInLegend.help": "凡例に値を表示",
|
"expressionXY.xyVis.valuesInLegend.help": "凡例に値を表示",
|
||||||
"expressionXY.xyVis.xTitle.help": "x軸のタイトル",
|
|
||||||
"expressionXY.xyVis.yLeftExtent.help": "Y左軸範囲",
|
|
||||||
"expressionXY.xyVis.yLeftTitle.help": "左y軸のタイトル",
|
|
||||||
"expressionXY.xyVis.yRightExtent.help": "Y右軸範囲",
|
|
||||||
"expressionXY.xyVis.yRightTitle.help": "右 y 軸のタイトル",
|
|
||||||
"expressionXY.yConfig.axisMode.help": "メトリックの軸モード",
|
|
||||||
"expressionXY.yConfig.color.help": "系列の色",
|
|
||||||
"expressionXY.yConfig.fill.help": "塗りつぶし",
|
|
||||||
"expressionXY.yConfig.forAccessor.help": "この構成のアクセサー",
|
|
||||||
"expressionXY.yConfig.help": "xyグラフのy軸メトリックの動作を構成",
|
|
||||||
"expressionXY.yConfig.icon.help": "基準線で使用される任意のアイコン",
|
|
||||||
"expressionXY.yConfig.iconPosition.help": "基準線のアイコンの配置",
|
|
||||||
"expressionXY.yConfig.lineStyle.help": "基準線のスタイル",
|
|
||||||
"expressionXY.yConfig.lineWidth.help": "基準線の幅",
|
|
||||||
"expressionXY.yConfig.textVisibility.help": "基準線のラベルの表示",
|
|
||||||
"fieldFormats.advancedSettings.format.bytesFormat.numeralFormatLinkText": "数字フォーマット",
|
"fieldFormats.advancedSettings.format.bytesFormat.numeralFormatLinkText": "数字フォーマット",
|
||||||
"fieldFormats.advancedSettings.format.bytesFormatText": "「バイト」フォーマットのデフォルト{numeralFormatLink}です",
|
"fieldFormats.advancedSettings.format.bytesFormatText": "「バイト」フォーマットのデフォルト{numeralFormatLink}です",
|
||||||
"fieldFormats.advancedSettings.format.bytesFormatTitle": "バイトフォーマット",
|
"fieldFormats.advancedSettings.format.bytesFormatTitle": "バイトフォーマット",
|
||||||
|
|
|
@ -3506,10 +3506,6 @@
|
||||||
"expressionXY.axisExtentConfig.help": "配置 xy 图表的轴范围",
|
"expressionXY.axisExtentConfig.help": "配置 xy 图表的轴范围",
|
||||||
"expressionXY.axisExtentConfig.lowerBound.help": "下边界",
|
"expressionXY.axisExtentConfig.lowerBound.help": "下边界",
|
||||||
"expressionXY.axisExtentConfig.upperBound.help": "上边界",
|
"expressionXY.axisExtentConfig.upperBound.help": "上边界",
|
||||||
"expressionXY.axisTitlesVisibilityConfig.help": "配置 xy 图表的轴标题外观",
|
|
||||||
"expressionXY.axisTitlesVisibilityConfig.x.help": "指定 x 轴的标题是否可见。",
|
|
||||||
"expressionXY.axisTitlesVisibilityConfig.yLeft.help": "指定左侧 y 轴的标题是否可见。",
|
|
||||||
"expressionXY.axisTitlesVisibilityConfig.yRight.help": "指定右侧 y 轴的标题是否可见。",
|
|
||||||
"expressionXY.dataLayer.accessors.help": "要在 y 轴上显示的列。",
|
"expressionXY.dataLayer.accessors.help": "要在 y 轴上显示的列。",
|
||||||
"expressionXY.layer.columnToLabel.help": "要标记的列 ID 的 JSON 键值对",
|
"expressionXY.layer.columnToLabel.help": "要标记的列 ID 的 JSON 键值对",
|
||||||
"expressionXY.dataLayer.help": "配置 xy 图表中的图层",
|
"expressionXY.dataLayer.help": "配置 xy 图表中的图层",
|
||||||
|
@ -3521,15 +3517,6 @@
|
||||||
"expressionXY.dataLayer.splitAccessor.help": "拆分要依据的列",
|
"expressionXY.dataLayer.splitAccessor.help": "拆分要依据的列",
|
||||||
"expressionXY.dataLayer.xAccessor.help": "X 轴",
|
"expressionXY.dataLayer.xAccessor.help": "X 轴",
|
||||||
"expressionXY.dataLayer.xScaleType.help": "x 轴的缩放类型",
|
"expressionXY.dataLayer.xScaleType.help": "x 轴的缩放类型",
|
||||||
"expressionXY.dataLayer.yConfig.help": "y 轴的其他配置",
|
|
||||||
"expressionXY.gridlinesConfig.help": "配置 xy 图表的网格线外观",
|
|
||||||
"expressionXY.gridlinesConfig.x.help": "指定 x 轴的网格线是否可见。",
|
|
||||||
"expressionXY.gridlinesConfig.yLeft.help": "指定左侧 y 轴的网格线是否可见。",
|
|
||||||
"expressionXY.gridlinesConfig.yRight.help": "指定右侧 y 轴的网格线是否可见。",
|
|
||||||
"expressionXY.labelsOrientationConfig.help": "配置 xy 图表的刻度标签方向",
|
|
||||||
"expressionXY.labelsOrientationConfig.x.help": "指定 x 轴的标签方向。",
|
|
||||||
"expressionXY.labelsOrientationConfig.yLeft.help": "指定左 y 轴的标签方向。",
|
|
||||||
"expressionXY.labelsOrientationConfig.yRight.help": "指定右 y 轴的标签方向。",
|
|
||||||
"expressionXY.legend.filterForValueButtonAriaLabel": "筛留值",
|
"expressionXY.legend.filterForValueButtonAriaLabel": "筛留值",
|
||||||
"expressionXY.legend.filterOptionsLegend": "{legendDataLabel}, 筛选选项",
|
"expressionXY.legend.filterOptionsLegend": "{legendDataLabel}, 筛选选项",
|
||||||
"expressionXY.legend.filterOutValueButtonAriaLabel": "筛除值",
|
"expressionXY.legend.filterOutValueButtonAriaLabel": "筛除值",
|
||||||
|
@ -3546,11 +3533,6 @@
|
||||||
"expressionXY.legendConfig.verticalAlignment.help": "指定图例显示在图表内时垂直对齐。",
|
"expressionXY.legendConfig.verticalAlignment.help": "指定图例显示在图表内时垂直对齐。",
|
||||||
"expressionXY.referenceLineLayer.accessors.help": "要在 y 轴上显示的列。",
|
"expressionXY.referenceLineLayer.accessors.help": "要在 y 轴上显示的列。",
|
||||||
"expressionXY.referenceLineLayer.help": "配置 xy 图表中的参考线",
|
"expressionXY.referenceLineLayer.help": "配置 xy 图表中的参考线",
|
||||||
"expressionXY.referenceLineLayer.yConfig.help": "y 轴的其他配置",
|
|
||||||
"expressionXY.tickLabelsConfig.help": "配置 xy 图表的刻度标签外观",
|
|
||||||
"expressionXY.tickLabelsConfig.x.help": "指定 x 轴的刻度标签是否可见。",
|
|
||||||
"expressionXY.tickLabelsConfig.yLeft.help": "指定左侧 y 轴的刻度标签是否可见。",
|
|
||||||
"expressionXY.tickLabelsConfig.yRight.help": "指定右侧 y 轴的刻度标签是否可见。",
|
|
||||||
"expressionXY.xyChart.emptyXLabel": "(空)",
|
"expressionXY.xyChart.emptyXLabel": "(空)",
|
||||||
"expressionXY.xyChart.iconSelect.alertIconLabel": "告警",
|
"expressionXY.xyChart.iconSelect.alertIconLabel": "告警",
|
||||||
"expressionXY.xyChart.iconSelect.asteriskIconLabel": "星号",
|
"expressionXY.xyChart.iconSelect.asteriskIconLabel": "星号",
|
||||||
|
@ -3567,39 +3549,20 @@
|
||||||
"expressionXY.xyChart.iconSelect.tagIconLabel": "标签",
|
"expressionXY.xyChart.iconSelect.tagIconLabel": "标签",
|
||||||
"expressionXY.xyChart.iconSelect.triangleIconLabel": "三角形",
|
"expressionXY.xyChart.iconSelect.triangleIconLabel": "三角形",
|
||||||
"expressionXY.xyVis.ariaLabel.help": "指定 xy 图表的 aria 标签",
|
"expressionXY.xyVis.ariaLabel.help": "指定 xy 图表的 aria 标签",
|
||||||
"expressionXY.xyVis.axisTitlesVisibilitySettings.help": "显示 x 和 y 轴标题",
|
|
||||||
"expressionXY.xyVis.curveType.help": "定义为折线图渲染曲线类型的方式",
|
"expressionXY.xyVis.curveType.help": "定义为折线图渲染曲线类型的方式",
|
||||||
"expressionXY.xyVis.endValue.help": "结束值",
|
"expressionXY.xyVis.endValue.help": "结束值",
|
||||||
"expressionXY.xyVis.fillOpacity.help": "定义面积图填充透明度",
|
"expressionXY.xyVis.fillOpacity.help": "定义面积图填充透明度",
|
||||||
"expressionXY.xyVis.fittingFunction.help": "定义处理缺失值的方式",
|
"expressionXY.xyVis.fittingFunction.help": "定义处理缺失值的方式",
|
||||||
"expressionXY.xyVis.gridlinesVisibilitySettings.help": "显示 x 和 y 轴网格线",
|
|
||||||
"expressionXY.xyVis.help": "X/Y 图表",
|
"expressionXY.xyVis.help": "X/Y 图表",
|
||||||
"expressionXY.xyVis.hideEndzones.help": "隐藏部分数据的末日区域标记",
|
"expressionXY.xyVis.hideEndzones.help": "隐藏部分数据的末日区域标记",
|
||||||
"expressionXY.xyVis.labelsOrientation.help": "定义轴标签的旋转",
|
|
||||||
"expressionXY.layeredXyVis.layers.help": "可视序列的图层",
|
"expressionXY.layeredXyVis.layers.help": "可视序列的图层",
|
||||||
"expressionXY.xyVis.legend.help": "配置图表图例。",
|
"expressionXY.xyVis.legend.help": "配置图表图例。",
|
||||||
"expressionXY.xyVis.logDatatable.breakDown": "细分方式",
|
"expressionXY.xyVis.logDatatable.breakDown": "细分方式",
|
||||||
"expressionXY.xyVis.logDatatable.metric": "垂直轴",
|
"expressionXY.xyVis.logDatatable.metric": "垂直轴",
|
||||||
"expressionXY.xyVis.logDatatable.x": "水平轴",
|
"expressionXY.xyVis.logDatatable.x": "水平轴",
|
||||||
"expressionXY.xyVis.renderer.help": "X/Y 图表呈现器",
|
"expressionXY.xyVis.renderer.help": "X/Y 图表呈现器",
|
||||||
"expressionXY.xyVis.tickLabelsVisibilitySettings.help": "显示 x 和 y 轴刻度标签",
|
|
||||||
"expressionXY.xyVis.valueLabels.help": "值标签模式",
|
"expressionXY.xyVis.valueLabels.help": "值标签模式",
|
||||||
"expressionXY.xyVis.valuesInLegend.help": "在图例中显示值",
|
"expressionXY.xyVis.valuesInLegend.help": "在图例中显示值",
|
||||||
"expressionXY.xyVis.xTitle.help": "X 轴标题",
|
|
||||||
"expressionXY.xyVis.yLeftExtent.help": "左侧 Y 轴范围",
|
|
||||||
"expressionXY.xyVis.yLeftTitle.help": "左侧 Y 轴标题",
|
|
||||||
"expressionXY.xyVis.yRightExtent.help": "右侧 Y 轴范围",
|
|
||||||
"expressionXY.xyVis.yRightTitle.help": "右侧 Y 轴标题",
|
|
||||||
"expressionXY.yConfig.axisMode.help": "指标的轴模式",
|
|
||||||
"expressionXY.yConfig.color.help": "序列的颜色",
|
|
||||||
"expressionXY.yConfig.fill.help": "填充",
|
|
||||||
"expressionXY.yConfig.forAccessor.help": "此配置针对的访问器",
|
|
||||||
"expressionXY.yConfig.help": "配置 xy 图表的 y 轴指标的行为",
|
|
||||||
"expressionXY.yConfig.icon.help": "用于参考线的可选图标",
|
|
||||||
"expressionXY.yConfig.iconPosition.help": "参考线图标的位置",
|
|
||||||
"expressionXY.yConfig.lineStyle.help": "参考线的样式",
|
|
||||||
"expressionXY.yConfig.lineWidth.help": "参考线的宽度",
|
|
||||||
"expressionXY.yConfig.textVisibility.help": "参考线上标签的可见性",
|
|
||||||
"fieldFormats.advancedSettings.format.bytesFormat.numeralFormatLinkText": "数值格式",
|
"fieldFormats.advancedSettings.format.bytesFormat.numeralFormatLinkText": "数值格式",
|
||||||
"fieldFormats.advancedSettings.format.bytesFormatText": "“字节”格式的默认{numeralFormatLink}",
|
"fieldFormats.advancedSettings.format.bytesFormatText": "“字节”格式的默认{numeralFormatLink}",
|
||||||
"fieldFormats.advancedSettings.format.bytesFormatTitle": "字节格式",
|
"fieldFormats.advancedSettings.format.bytesFormatTitle": "字节格式",
|
||||||
|
|
|
@ -274,13 +274,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||||
});
|
});
|
||||||
|
|
||||||
let data = await PageObjects.lens.getCurrentChartDebugState('xyVisChart');
|
let data = await PageObjects.lens.getCurrentChartDebugState('xyVisChart');
|
||||||
expect(data?.axes?.y?.[0].title).to.eql(axisTitle);
|
expect(data?.axes?.y?.[1].title).to.eql(axisTitle);
|
||||||
|
|
||||||
// hide the gridlines
|
// hide the gridlines
|
||||||
await testSubjects.click('lnsshowyLeftAxisGridlines');
|
await testSubjects.click('lnsshowyLeftAxisGridlines');
|
||||||
|
|
||||||
data = await PageObjects.lens.getCurrentChartDebugState('xyVisChart');
|
data = await PageObjects.lens.getCurrentChartDebugState('xyVisChart');
|
||||||
expect(data?.axes?.y?.[0].gridlines.length).to.eql(0);
|
expect(data?.axes?.y?.[1].gridlines.length).to.eql(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should transition from a multi-layer stacked bar to donut chart using suggestions', async () => {
|
it('should transition from a multi-layer stacked bar to donut chart using suggestions', async () => {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue