mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -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"}',
|
||||
xScaleType: 'ordinal',
|
||||
isHistogram: false,
|
||||
isHorizontal: false,
|
||||
isPercentage: false,
|
||||
isStacked: false,
|
||||
palette: mockPaletteOutput,
|
||||
table: createSampleDatatableWithRows([]),
|
||||
};
|
||||
|
@ -73,6 +76,9 @@ export const sampleExtendedLayer: ExtendedDataLayerConfig = {
|
|||
columnToLabel: '{"a": "Label A", "b": "Label B", "d": "Label D"}',
|
||||
xScaleType: 'ordinal',
|
||||
isHistogram: false,
|
||||
isHorizontal: false,
|
||||
isStacked: false,
|
||||
isPercentage: false,
|
||||
palette: mockPaletteOutput,
|
||||
table: createSampleDatatableWithRows([]),
|
||||
};
|
||||
|
@ -80,9 +86,6 @@ export const sampleExtendedLayer: ExtendedDataLayerConfig = {
|
|||
export const createArgsWithLayers = (
|
||||
layers: DataLayerConfig | DataLayerConfig[] = sampleLayer
|
||||
): XYProps => ({
|
||||
xTitle: '',
|
||||
yTitle: '',
|
||||
yRightTitle: '',
|
||||
showTooltip: true,
|
||||
legend: {
|
||||
type: 'legendConfig',
|
||||
|
@ -91,41 +94,44 @@ export const createArgsWithLayers = (
|
|||
},
|
||||
valueLabels: 'hide',
|
||||
valuesInLegend: false,
|
||||
axisTitlesVisibilitySettings: {
|
||||
type: 'axisTitlesVisibilityConfig',
|
||||
x: true,
|
||||
yLeft: true,
|
||||
yRight: true,
|
||||
},
|
||||
tickLabelsVisibilitySettings: {
|
||||
type: 'tickLabelsConfig',
|
||||
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',
|
||||
xAxisConfig: {
|
||||
type: 'xAxisConfig',
|
||||
position: 'bottom',
|
||||
showGridLines: true,
|
||||
labelsOrientation: 0,
|
||||
showLabels: true,
|
||||
showTitle: true,
|
||||
title: '',
|
||||
},
|
||||
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],
|
||||
yLeftScale: 'linear',
|
||||
yRightScale: 'linear',
|
||||
});
|
||||
|
||||
export function sampleArgs() {
|
||||
|
|
|
@ -8,22 +8,20 @@
|
|||
|
||||
export const XY_VIS = 'xyVis';
|
||||
export const LAYERED_XY_VIS = 'layeredXyVis';
|
||||
export const Y_CONFIG = 'yConfig';
|
||||
export const REFERENCE_LINE_Y_CONFIG = 'referenceLineYConfig';
|
||||
export const EXTENDED_Y_CONFIG = 'extendedYConfig';
|
||||
export const DATA_DECORATION_CONFIG = 'dataDecorationConfig';
|
||||
export const REFERENCE_LINE_DECORATION_CONFIG = 'referenceLineDecorationConfig';
|
||||
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 EXTENDED_DATA_LAYER = 'extendedDataLayer';
|
||||
export const LEGEND_CONFIG = 'legendConfig';
|
||||
export const XY_VIS_RENDERER = 'xyVis';
|
||||
export const GRID_LINES_CONFIG = 'gridlinesConfig';
|
||||
export const ANNOTATION_LAYER = 'annotationLayer';
|
||||
export const EXTENDED_ANNOTATION_LAYER = 'extendedAnnotationLayer';
|
||||
export const TICK_LABELS_CONFIG = 'tickLabelsConfig';
|
||||
export const AXIS_EXTENT_CONFIG = 'axisExtentConfig';
|
||||
export const REFERENCE_LINE = 'referenceLine';
|
||||
export const REFERENCE_LINE_LAYER = 'referenceLineLayer';
|
||||
export const LABELS_ORIENTATION_CONFIG = 'labelsOrientationConfig';
|
||||
export const AXIS_TITLES_VISIBILITY_CONFIG = 'axisTitlesVisibilityConfig';
|
||||
|
||||
export const LayerTypes = {
|
||||
DATA: 'data',
|
||||
|
@ -82,13 +80,6 @@ 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 const YScaleTypes = {
|
||||
|
@ -131,3 +122,10 @@ export const AvailableReferenceLineIcons = {
|
|||
TAG: 'tag',
|
||||
TRIANGLE: 'triangle',
|
||||
} 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 { SeriesTypes, XScaleTypes, Y_CONFIG } from '../constants';
|
||||
import { SeriesTypes, XScaleTypes, DATA_DECORATION_CONFIG } from '../constants';
|
||||
import { strings } from '../i18n';
|
||||
import { DataLayerArgs, ExtendedDataLayerArgs } from '../types';
|
||||
|
||||
|
@ -43,6 +43,21 @@ export const commonDataLayerArgs: Omit<
|
|||
default: false,
|
||||
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: {
|
||||
types: ['number'],
|
||||
help: strings.getLineWidthHelp(),
|
||||
|
@ -59,9 +74,9 @@ export const commonDataLayerArgs: Omit<
|
|||
types: ['boolean'],
|
||||
help: strings.getShowLinesHelp(),
|
||||
},
|
||||
yConfig: {
|
||||
types: [Y_CONFIG],
|
||||
help: strings.getYConfigHelp(),
|
||||
decorations: {
|
||||
types: [DATA_DECORATION_CONFIG],
|
||||
help: strings.getDecorationsHelp(),
|
||||
multi: true,
|
||||
},
|
||||
columnToLabel: {
|
||||
|
|
|
@ -7,17 +7,13 @@
|
|||
*/
|
||||
|
||||
import {
|
||||
AXIS_EXTENT_CONFIG,
|
||||
AXIS_TITLES_VISIBILITY_CONFIG,
|
||||
EndValues,
|
||||
FittingFunctions,
|
||||
GRID_LINES_CONFIG,
|
||||
LABELS_ORIENTATION_CONFIG,
|
||||
LEGEND_CONFIG,
|
||||
TICK_LABELS_CONFIG,
|
||||
ValueLabelModes,
|
||||
XYCurveTypes,
|
||||
YScaleTypes,
|
||||
X_AXIS_CONFIG,
|
||||
Y_AXIS_CONFIG,
|
||||
} from '../constants';
|
||||
import { strings } from '../i18n';
|
||||
import { LayeredXyVisFn, XyVisFn } from '../types';
|
||||
|
@ -25,45 +21,6 @@ import { LayeredXyVisFn, XyVisFn } from '../types';
|
|||
type CommonXYFn = XyVisFn | LayeredXyVisFn;
|
||||
|
||||
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: {
|
||||
types: [LEGEND_CONFIG],
|
||||
help: strings.getLegendHelp(),
|
||||
|
@ -93,22 +50,6 @@ export const commonXYArgs: CommonXYFn['args'] = {
|
|||
strict: true,
|
||||
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: {
|
||||
types: ['string'],
|
||||
options: [...Object.values(XYCurveTypes)],
|
||||
|
@ -133,6 +74,15 @@ export const commonXYArgs: CommonXYFn['args'] = {
|
|||
types: ['string'],
|
||||
help: strings.getAriaLabelHelp(),
|
||||
},
|
||||
xAxisConfig: {
|
||||
types: [X_AXIS_CONFIG],
|
||||
help: strings.getXAxisConfigHelp(),
|
||||
},
|
||||
yAxisConfigs: {
|
||||
types: [Y_AXIS_CONFIG],
|
||||
help: strings.getyAxisConfigsHelp(),
|
||||
multi: true,
|
||||
},
|
||||
detailedTooltip: {
|
||||
types: ['boolean'],
|
||||
help: strings.getDetailedTooltipHelp(),
|
||||
|
|
|
@ -6,22 +6,19 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { YAxisModes } from '../constants';
|
||||
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: {
|
||||
types: ['string'],
|
||||
help: strings.getForAccessorHelp(),
|
||||
},
|
||||
axisMode: {
|
||||
axisId: {
|
||||
types: ['string'],
|
||||
options: [...Object.values(YAxisModes)],
|
||||
help: strings.getAxisModeHelp(),
|
||||
strict: true,
|
||||
help: strings.getAxisIdHelp(),
|
||||
},
|
||||
color: {
|
||||
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',
|
||||
xScaleType: 'linear',
|
||||
isHistogram: false,
|
||||
isHorizontal: false,
|
||||
isPercentage: false,
|
||||
isStacked: false,
|
||||
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 './annotation_layer';
|
||||
export * from './extended_annotation_layer';
|
||||
export * from './data_decoration_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 './grid_lines_config';
|
||||
export * from './axis_extent_config';
|
||||
export * from './tick_labels_config';
|
||||
export * from './labels_orientation_config';
|
||||
export * from './reference_line';
|
||||
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,
|
||||
hasBarLayer,
|
||||
errors,
|
||||
validateAxes,
|
||||
} from './validate';
|
||||
import { appendLayerIds, getDataLayers } from '../helpers';
|
||||
|
||||
|
@ -35,6 +36,8 @@ export const layeredXyVisFn: LayeredXyVisFn['fn'] = async (data, args, handlers)
|
|||
throw new Error(errors.markSizeRatioWithoutAccessor());
|
||||
}
|
||||
|
||||
validateAxes(dataLayers, args.yAxisConfigs);
|
||||
|
||||
return {
|
||||
type: 'render',
|
||||
as: XY_VIS_RENDERER,
|
||||
|
|
|
@ -15,6 +15,7 @@ describe('referenceLine', () => {
|
|||
const args: ReferenceLineArgs = {
|
||||
value: 100,
|
||||
fill: 'above',
|
||||
position: 'bottom',
|
||||
};
|
||||
|
||||
const result = referenceLineFunction.fn(null, args, createMockExecutionContext());
|
||||
|
@ -23,9 +24,9 @@ describe('referenceLine', () => {
|
|||
type: 'referenceLine',
|
||||
layerType: 'referenceLine',
|
||||
lineLength: 0,
|
||||
yConfig: [
|
||||
decorations: [
|
||||
{
|
||||
type: 'referenceLineYConfig',
|
||||
type: 'extendedReferenceLineDecorationConfig',
|
||||
...args,
|
||||
textVisibility: false,
|
||||
},
|
||||
|
@ -40,7 +41,7 @@ describe('referenceLine', () => {
|
|||
value: 100,
|
||||
icon: 'alert',
|
||||
iconPosition: 'below',
|
||||
axisMode: 'bottom',
|
||||
position: 'bottom',
|
||||
lineStyle: 'solid',
|
||||
lineWidth: 10,
|
||||
color: '#fff',
|
||||
|
@ -54,9 +55,9 @@ describe('referenceLine', () => {
|
|||
type: 'referenceLine',
|
||||
layerType: 'referenceLine',
|
||||
lineLength: 0,
|
||||
yConfig: [
|
||||
decorations: [
|
||||
{
|
||||
type: 'referenceLineYConfig',
|
||||
type: 'extendedReferenceLineDecorationConfig',
|
||||
...args,
|
||||
},
|
||||
],
|
||||
|
@ -69,6 +70,7 @@ describe('referenceLine', () => {
|
|||
name: 'some name',
|
||||
value: 100,
|
||||
fill: 'none',
|
||||
position: 'bottom',
|
||||
};
|
||||
|
||||
const result = referenceLineFunction.fn(null, args, createMockExecutionContext());
|
||||
|
@ -77,9 +79,9 @@ describe('referenceLine', () => {
|
|||
type: 'referenceLine',
|
||||
layerType: 'referenceLine',
|
||||
lineLength: 0,
|
||||
yConfig: [
|
||||
decorations: [
|
||||
{
|
||||
type: 'referenceLineYConfig',
|
||||
type: 'extendedReferenceLineDecorationConfig',
|
||||
...args,
|
||||
textVisibility: true,
|
||||
},
|
||||
|
@ -93,6 +95,7 @@ describe('referenceLine', () => {
|
|||
value: 100,
|
||||
textVisibility: true,
|
||||
fill: 'none',
|
||||
position: 'bottom',
|
||||
};
|
||||
|
||||
const result = referenceLineFunction.fn(null, args, createMockExecutionContext());
|
||||
|
@ -101,9 +104,9 @@ describe('referenceLine', () => {
|
|||
type: 'referenceLine',
|
||||
layerType: 'referenceLine',
|
||||
lineLength: 0,
|
||||
yConfig: [
|
||||
decorations: [
|
||||
{
|
||||
type: 'referenceLineYConfig',
|
||||
type: 'extendedReferenceLineDecorationConfig',
|
||||
...args,
|
||||
textVisibility: false,
|
||||
},
|
||||
|
@ -119,6 +122,7 @@ describe('referenceLine', () => {
|
|||
name: 'some text',
|
||||
textVisibility,
|
||||
fill: 'none',
|
||||
position: 'bottom',
|
||||
};
|
||||
|
||||
const result = referenceLineFunction.fn(null, args, createMockExecutionContext());
|
||||
|
@ -127,9 +131,9 @@ describe('referenceLine', () => {
|
|||
type: 'referenceLine',
|
||||
layerType: 'referenceLine',
|
||||
lineLength: 0,
|
||||
yConfig: [
|
||||
decorations: [
|
||||
{
|
||||
type: 'referenceLineYConfig',
|
||||
type: 'extendedReferenceLineDecorationConfig',
|
||||
...args,
|
||||
textVisibility,
|
||||
},
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { Position } from '@elastic/charts';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import {
|
||||
AvailableReferenceLineIcons,
|
||||
|
@ -14,8 +15,7 @@ import {
|
|||
LayerTypes,
|
||||
LineStyles,
|
||||
REFERENCE_LINE,
|
||||
REFERENCE_LINE_Y_CONFIG,
|
||||
YAxisModes,
|
||||
EXTENDED_REFERENCE_LINE_DECORATION_CONFIG,
|
||||
} from '../constants';
|
||||
import { ReferenceLineFn } from '../types';
|
||||
import { strings } from '../i18n';
|
||||
|
@ -36,13 +36,23 @@ export const referenceLineFunction: ReferenceLineFn = {
|
|||
help: strings.getReferenceLineValueHelp(),
|
||||
required: true,
|
||||
},
|
||||
axisMode: {
|
||||
position: {
|
||||
types: ['string'],
|
||||
options: [...Object.values(YAxisModes)],
|
||||
help: strings.getAxisModeHelp(),
|
||||
default: YAxisModes.AUTO,
|
||||
options: [Position.Right, Position.Left],
|
||||
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,
|
||||
},
|
||||
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: {
|
||||
types: ['string'],
|
||||
help: strings.getColorHelp(),
|
||||
|
@ -50,7 +60,7 @@ export const referenceLineFunction: ReferenceLineFn = {
|
|||
lineStyle: {
|
||||
types: ['string'],
|
||||
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',
|
||||
}),
|
||||
default: LineStyles.SOLID,
|
||||
|
@ -58,14 +68,14 @@ export const referenceLineFunction: ReferenceLineFn = {
|
|||
},
|
||||
lineWidth: {
|
||||
types: ['number'],
|
||||
help: i18n.translate('expressionXY.yConfig.lineWidth.help', {
|
||||
help: i18n.translate('expressionXY.decorationConfig.lineWidth.help', {
|
||||
defaultMessage: 'The width of the reference line',
|
||||
}),
|
||||
default: 1,
|
||||
},
|
||||
icon: {
|
||||
types: ['string'],
|
||||
help: i18n.translate('expressionXY.yConfig.icon.help', {
|
||||
help: i18n.translate('expressionXY.decorationConfig.icon.help', {
|
||||
defaultMessage: 'An optional icon used for reference lines',
|
||||
}),
|
||||
options: [...Object.values(AvailableReferenceLineIcons)],
|
||||
|
@ -74,7 +84,7 @@ export const referenceLineFunction: ReferenceLineFn = {
|
|||
iconPosition: {
|
||||
types: ['string'],
|
||||
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',
|
||||
}),
|
||||
default: IconPositions.AUTO,
|
||||
|
@ -82,14 +92,14 @@ export const referenceLineFunction: ReferenceLineFn = {
|
|||
},
|
||||
textVisibility: {
|
||||
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',
|
||||
}),
|
||||
},
|
||||
fill: {
|
||||
types: ['string'],
|
||||
options: [...Object.values(FillStyles)],
|
||||
help: i18n.translate('expressionXY.yConfig.fill.help', {
|
||||
help: i18n.translate('expressionXY.decorationConfig.fill.help', {
|
||||
defaultMessage: 'Fill',
|
||||
}),
|
||||
default: FillStyles.NONE,
|
||||
|
@ -108,7 +118,7 @@ export const referenceLineFunction: ReferenceLineFn = {
|
|||
type: REFERENCE_LINE,
|
||||
layerType: LayerTypes.REFERENCELINE,
|
||||
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.
|
||||
*/
|
||||
|
||||
import { Position } from '@elastic/charts';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import {
|
||||
AvailableReferenceLineIcons,
|
||||
EXTENDED_Y_CONFIG,
|
||||
REFERENCE_LINE_DECORATION_CONFIG,
|
||||
FillStyles,
|
||||
IconPositions,
|
||||
LineStyles,
|
||||
} from '../constants';
|
||||
import { strings } from '../i18n';
|
||||
import { ExtendedYConfigFn } from '../types';
|
||||
import { commonYConfigArgs } from './common_y_config_args';
|
||||
import { ReferenceLineDecorationConfigFn } from '../types';
|
||||
import { commonDecorationConfigArgs } from './common_y_config_args';
|
||||
|
||||
export const extendedYAxisConfigFunction: ExtendedYConfigFn = {
|
||||
name: EXTENDED_Y_CONFIG,
|
||||
export const referenceLineDecorationConfigFunction: ReferenceLineDecorationConfigFn = {
|
||||
name: REFERENCE_LINE_DECORATION_CONFIG,
|
||||
aliases: [],
|
||||
type: EXTENDED_Y_CONFIG,
|
||||
help: strings.getYConfigFnHelp(),
|
||||
type: REFERENCE_LINE_DECORATION_CONFIG,
|
||||
help: strings.getDecorationsHelp(),
|
||||
inputTypes: ['null'],
|
||||
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: {
|
||||
types: ['string'],
|
||||
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',
|
||||
}),
|
||||
strict: true,
|
||||
},
|
||||
lineWidth: {
|
||||
types: ['number'],
|
||||
help: i18n.translate('expressionXY.yConfig.lineWidth.help', {
|
||||
help: i18n.translate('expressionXY.decorationConfig.lineWidth.help', {
|
||||
defaultMessage: 'The width of the reference line',
|
||||
}),
|
||||
},
|
||||
icon: {
|
||||
types: ['string'],
|
||||
help: i18n.translate('expressionXY.yConfig.icon.help', {
|
||||
help: i18n.translate('expressionXY.decorationConfig.icon.help', {
|
||||
defaultMessage: 'An optional icon used for reference lines',
|
||||
}),
|
||||
options: [...Object.values(AvailableReferenceLineIcons)],
|
||||
|
@ -51,21 +62,21 @@ export const extendedYAxisConfigFunction: ExtendedYConfigFn = {
|
|||
iconPosition: {
|
||||
types: ['string'],
|
||||
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',
|
||||
}),
|
||||
strict: true,
|
||||
},
|
||||
textVisibility: {
|
||||
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',
|
||||
}),
|
||||
},
|
||||
fill: {
|
||||
types: ['string'],
|
||||
options: [...Object.values(FillStyles)],
|
||||
help: i18n.translate('expressionXY.yConfig.fill.help', {
|
||||
help: i18n.translate('expressionXY.decorationConfig.fill.help', {
|
||||
defaultMessage: 'Fill',
|
||||
}),
|
||||
strict: true,
|
||||
|
@ -73,7 +84,7 @@ export const extendedYAxisConfigFunction: ExtendedYConfigFn = {
|
|||
},
|
||||
fn(input, args) {
|
||||
return {
|
||||
type: EXTENDED_Y_CONFIG,
|
||||
type: REFERENCE_LINE_DECORATION_CONFIG,
|
||||
...args,
|
||||
};
|
||||
},
|
|
@ -6,7 +6,7 @@
|
|||
* 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 { strings } from '../i18n';
|
||||
|
||||
|
@ -22,9 +22,9 @@ export const referenceLineLayerFunction: ReferenceLineLayerFn = {
|
|||
help: strings.getRLAccessorsHelp(),
|
||||
multi: true,
|
||||
},
|
||||
yConfig: {
|
||||
types: [EXTENDED_Y_CONFIG],
|
||||
help: strings.getRLYConfigHelp(),
|
||||
decorations: {
|
||||
types: [REFERENCE_LINE_DECORATION_CONFIG],
|
||||
help: strings.getRLDecorationConfigHelp(),
|
||||
multi: true,
|
||||
},
|
||||
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 { isValidInterval } from '@kbn/data-plugin/common';
|
||||
import { ExpressionValueVisDimension } from '@kbn/visualizations-plugin/common';
|
||||
import { AxisExtentModes, ValueLabelModes } from '../constants';
|
||||
import { AxisExtentModes, ValueLabelModes, SeriesTypes } from '../constants';
|
||||
import {
|
||||
SeriesType,
|
||||
AxisExtentConfigResult,
|
||||
|
@ -17,7 +17,9 @@ import {
|
|||
CommonXYDataLayerConfigResult,
|
||||
ValueLabelMode,
|
||||
CommonXYDataLayerConfig,
|
||||
YAxisConfigResult,
|
||||
ExtendedDataLayerConfigResult,
|
||||
XAxisConfigResult,
|
||||
} from '../types';
|
||||
import { isTimeChart } from '../helpers';
|
||||
|
||||
|
@ -111,19 +113,23 @@ export const errors = {
|
|||
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>) =>
|
||||
layers.filter(({ seriesType }) => seriesType.includes('bar')).length > 0;
|
||||
layers.some(({ seriesType }) => seriesType === SeriesTypes.BAR);
|
||||
|
||||
export const hasAreaLayer = (layers: Array<DataLayerConfigResult | CommonXYDataLayerConfig>) =>
|
||||
layers.filter(({ seriesType }) => seriesType.includes('area')).length > 0;
|
||||
layers.some(({ seriesType }) => seriesType === SeriesTypes.AREA);
|
||||
|
||||
export const hasHistogramBarLayer = (
|
||||
layers: Array<DataLayerConfigResult | CommonXYDataLayerConfig>
|
||||
) =>
|
||||
layers.filter(({ seriesType, isHistogram }) => seriesType.includes('bar') && isHistogram).length >
|
||||
0;
|
||||
) => layers.some(({ seriesType, isHistogram }) => seriesType === SeriesTypes.BAR && isHistogram);
|
||||
|
||||
export const isValidExtentWithCustomMode = (extent: AxisExtentConfigResult) => {
|
||||
const isValidLowerBound =
|
||||
|
@ -138,8 +144,8 @@ export const validateExtentForDataBounds = (
|
|||
extent: AxisExtentConfigResult,
|
||||
layers: Array<DataLayerConfigResult | CommonXYDataLayerConfig>
|
||||
) => {
|
||||
const lineSeries = layers.filter(({ seriesType }) => seriesType.includes('line'));
|
||||
if (!lineSeries.length && extent.mode === AxisExtentModes.DATA_BOUNDS) {
|
||||
const hasLineSeries = layers.some(({ seriesType }) => seriesType === SeriesTypes.LINE);
|
||||
if (!hasLineSeries && extent.mode === AxisExtentModes.DATA_BOUNDS) {
|
||||
throw new Error(errors.dataBoundsForNotLineChartError());
|
||||
}
|
||||
};
|
||||
|
@ -158,20 +164,46 @@ export const validateXExtent = (
|
|||
}
|
||||
};
|
||||
|
||||
export const validateExtent = (
|
||||
extent: AxisExtentConfigResult,
|
||||
export const validateExtents = (
|
||||
dataLayers: Array<DataLayerConfigResult | CommonXYDataLayerConfig>,
|
||||
hasBarOrArea: boolean,
|
||||
dataLayers: Array<DataLayerConfigResult | CommonXYDataLayerConfig>
|
||||
yAxisConfigs?: YAxisConfigResult[],
|
||||
xAxisConfig?: XAxisConfigResult
|
||||
) => {
|
||||
if (
|
||||
extent.mode === AxisExtentModes.CUSTOM &&
|
||||
hasBarOrArea &&
|
||||
!isValidExtentWithCustomMode(extent)
|
||||
) {
|
||||
throw new Error(errors.extendBoundsAreInvalidError());
|
||||
}
|
||||
yAxisConfigs?.forEach((axis) => {
|
||||
if (!axis.extent) {
|
||||
return;
|
||||
}
|
||||
if (
|
||||
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) => {
|
||||
|
@ -191,7 +223,7 @@ export const validateValueLabels = (
|
|||
};
|
||||
|
||||
const isAreaOrLineChart = (seriesType: SeriesType) =>
|
||||
seriesType.includes('line') || seriesType.includes('area');
|
||||
seriesType === SeriesTypes.LINE || seriesType === SeriesTypes.AREA;
|
||||
|
||||
export const validateAddTimeMarker = (
|
||||
dataLayers: Array<DataLayerConfigResult | ExtendedDataLayerConfigResult>,
|
||||
|
@ -206,7 +238,7 @@ export const validateMarkSizeForChartType = (
|
|||
markSizeAccessor: ExpressionValueVisDimension | string | undefined,
|
||||
seriesType: SeriesType
|
||||
) => {
|
||||
if (markSizeAccessor && !seriesType.includes('line') && !seriesType.includes('area')) {
|
||||
if (markSizeAccessor && !isAreaOrLineChart(seriesType)) {
|
||||
throw new Error(errors.markSizeAccessorForNonLineOrAreaChartsError());
|
||||
}
|
||||
};
|
||||
|
@ -248,7 +280,7 @@ export const validateLinesVisibilityForChartType = (
|
|||
showLines: boolean | undefined,
|
||||
seriesType: SeriesType
|
||||
) => {
|
||||
if (showLines && !(seriesType.includes('line') || seriesType.includes('area'))) {
|
||||
if (showLines && !isAreaOrLineChart(seriesType)) {
|
||||
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: [],
|
||||
isHistogram: true,
|
||||
xScaleType: 'time',
|
||||
xExtent: { type: 'axisExtentConfig', mode: 'dataBounds' },
|
||||
xAxisConfig: {
|
||||
type: 'xAxisConfig',
|
||||
extent: { type: 'axisExtentConfig', mode: 'dataBounds' },
|
||||
},
|
||||
},
|
||||
createMockExecutionContext()
|
||||
)
|
||||
|
@ -255,11 +258,14 @@ describe('xyVis', () => {
|
|||
...restLayerArgs,
|
||||
referenceLines: [],
|
||||
annotationLayers: [],
|
||||
xExtent: {
|
||||
type: 'axisExtentConfig',
|
||||
mode: 'full',
|
||||
lowerBound: undefined,
|
||||
upperBound: undefined,
|
||||
xAxisConfig: {
|
||||
type: 'xAxisConfig',
|
||||
extent: {
|
||||
type: 'axisExtentConfig',
|
||||
mode: 'full',
|
||||
lowerBound: undefined,
|
||||
upperBound: undefined,
|
||||
},
|
||||
},
|
||||
},
|
||||
createMockExecutionContext()
|
||||
|
@ -282,9 +288,9 @@ describe('xyVis', () => {
|
|||
...restLayerArgs,
|
||||
referenceLines: [],
|
||||
annotationLayers: [],
|
||||
xExtent: {
|
||||
type: 'axisExtentConfig',
|
||||
mode: 'dataBounds',
|
||||
xAxisConfig: {
|
||||
type: 'xAxisConfig',
|
||||
extent: { type: 'axisExtentConfig', mode: 'dataBounds' },
|
||||
},
|
||||
},
|
||||
createMockExecutionContext()
|
||||
|
@ -292,7 +298,7 @@ describe('xyVis', () => {
|
|||
).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 { layers, ...rest } = args;
|
||||
const { layerId, layerType, table, type, ...restLayerArgs } = sampleLayer;
|
||||
|
@ -304,11 +310,14 @@ describe('xyVis', () => {
|
|||
referenceLines: [],
|
||||
annotationLayers: [],
|
||||
isHistogram: true,
|
||||
xExtent: {
|
||||
type: 'axisExtentConfig',
|
||||
mode: 'custom',
|
||||
lowerBound: 0,
|
||||
upperBound: 10,
|
||||
xAxisConfig: {
|
||||
type: 'xAxisConfig',
|
||||
extent: {
|
||||
type: 'axisExtentConfig',
|
||||
mode: 'custom',
|
||||
lowerBound: 0,
|
||||
upperBound: 10,
|
||||
},
|
||||
},
|
||||
},
|
||||
createMockExecutionContext()
|
||||
|
@ -320,11 +329,14 @@ describe('xyVis', () => {
|
|||
value: {
|
||||
args: {
|
||||
...rest,
|
||||
xExtent: {
|
||||
type: 'axisExtentConfig',
|
||||
mode: 'custom',
|
||||
lowerBound: 0,
|
||||
upperBound: 10,
|
||||
xAxisConfig: {
|
||||
type: 'xAxisConfig',
|
||||
extent: {
|
||||
type: 'axisExtentConfig',
|
||||
mode: 'custom',
|
||||
lowerBound: 0,
|
||||
upperBound: 10,
|
||||
},
|
||||
},
|
||||
layers: [
|
||||
{
|
||||
|
|
|
@ -21,7 +21,7 @@ import {
|
|||
hasAreaLayer,
|
||||
hasBarLayer,
|
||||
hasHistogramBarLayer,
|
||||
validateExtent,
|
||||
validateExtents,
|
||||
validateFillOpacity,
|
||||
validateMarkSizeRatioLimits,
|
||||
validateValueLabels,
|
||||
|
@ -33,7 +33,7 @@ import {
|
|||
validateLineWidthForChartType,
|
||||
validatePointsRadiusForChartType,
|
||||
validateLinesVisibilityForChartType,
|
||||
validateXExtent,
|
||||
validateAxes,
|
||||
} from './validate';
|
||||
|
||||
const createDataLayer = (args: XYArgs, table: Datatable): DataLayerConfigResult => {
|
||||
|
@ -46,8 +46,11 @@ const createDataLayer = (args: XYArgs, table: Datatable): DataLayerConfigResult
|
|||
columnToLabel: args.columnToLabel,
|
||||
xScaleType: args.xScaleType,
|
||||
isHistogram: args.isHistogram,
|
||||
isPercentage: args.isPercentage,
|
||||
isHorizontal: args.isHorizontal,
|
||||
isStacked: args.isStacked,
|
||||
palette: args.palette,
|
||||
yConfig: args.yConfig,
|
||||
decorations: args.decorations,
|
||||
showPoints: args.showPoints,
|
||||
pointsRadius: args.pointsRadius,
|
||||
lineWidth: args.lineWidth,
|
||||
|
@ -74,7 +77,10 @@ export const xyVisFn: XyVisFn['fn'] = async (data, args, handlers) => {
|
|||
columnToLabel,
|
||||
xScaleType,
|
||||
isHistogram,
|
||||
yConfig,
|
||||
isHorizontal,
|
||||
isPercentage,
|
||||
isStacked,
|
||||
decorations,
|
||||
palette,
|
||||
markSizeAccessor,
|
||||
showPoints,
|
||||
|
@ -121,9 +127,7 @@ export const xyVisFn: XyVisFn['fn'] = async (data, args, handlers) => {
|
|||
const hasBar = hasBarLayer(dataLayers);
|
||||
const hasArea = hasAreaLayer(dataLayers);
|
||||
|
||||
validateXExtent(args.xExtent, dataLayers);
|
||||
validateExtent(args.yLeftExtent, hasBar || hasArea, dataLayers);
|
||||
validateExtent(args.yRightExtent, hasBar || hasArea, dataLayers);
|
||||
validateExtents(dataLayers, hasBar || hasArea, args.yAxisConfigs, args.xAxisConfig);
|
||||
validateFillOpacity(args.fillOpacity, hasArea);
|
||||
validateAddTimeMarker(dataLayers, args.addTimeMarker);
|
||||
validateMinTimeBarInterval(dataLayers, hasBar, args.minTimeBarInterval);
|
||||
|
@ -136,6 +140,7 @@ export const xyVisFn: XyVisFn['fn'] = async (data, args, handlers) => {
|
|||
validateLineWidthForChartType(lineWidth, args.seriesType);
|
||||
validateShowPointsForChartType(showPoints, args.seriesType);
|
||||
validatePointsRadiusForChartType(pointsRadius, args.seriesType);
|
||||
validateAxes(dataLayers, args.yAxisConfigs);
|
||||
|
||||
return {
|
||||
type: 'render',
|
||||
|
|
|
@ -6,22 +6,46 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { Y_CONFIG } from '../constants';
|
||||
import { YConfigFn } from '../types';
|
||||
import { Position } from '@elastic/charts';
|
||||
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 = {
|
||||
name: Y_CONFIG,
|
||||
export const yAxisConfigFunction: YAxisConfigFn = {
|
||||
name: Y_AXIS_CONFIG,
|
||||
aliases: [],
|
||||
type: Y_CONFIG,
|
||||
help: strings.getYConfigFnHelp(),
|
||||
type: Y_AXIS_CONFIG,
|
||||
help: strings.getYAxisConfigFnHelp(),
|
||||
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) {
|
||||
return {
|
||||
type: Y_CONFIG,
|
||||
type: Y_AXIS_CONFIG,
|
||||
...args,
|
||||
position: args.position ?? Position.Left,
|
||||
};
|
||||
},
|
||||
};
|
||||
|
|
|
@ -59,6 +59,9 @@ describe('#getDataLayers', () => {
|
|||
seriesType: 'bar',
|
||||
xScaleType: 'time',
|
||||
isHistogram: false,
|
||||
isHorizontal: false,
|
||||
isPercentage: false,
|
||||
isStacked: false,
|
||||
table: { rows: [], columns: [], type: 'datatable' },
|
||||
palette: { type: 'system_palette', name: 'system' },
|
||||
},
|
||||
|
|
|
@ -14,7 +14,7 @@ import {
|
|||
ExtendedDataLayerArgs,
|
||||
DataLayerArgs,
|
||||
} from '../types';
|
||||
import { LayerTypes } from '../constants';
|
||||
import { LayerTypes, SeriesTypes } from '../constants';
|
||||
|
||||
function isWithLayerId<T>(layer: T): layer is T & WithLayerId {
|
||||
return (layer as T & WithLayerId).layerId ? true : false;
|
||||
|
@ -35,9 +35,7 @@ export function appendLayerIds<T>(
|
|||
}
|
||||
|
||||
export const getShowLines = (args: DataLayerArgs | ExtendedDataLayerArgs) =>
|
||||
args.seriesType.includes('line') || args.seriesType.includes('area')
|
||||
? args.showLines ?? true
|
||||
: args.showLines;
|
||||
args.showLines ?? (args.seriesType === SeriesTypes.LINE || args.seriesType !== SeriesTypes.AREA);
|
||||
|
||||
export function getDataLayers(layers: XYExtendedLayerConfigResult[]) {
|
||||
return layers.filter<ExtendedDataLayerConfig>(
|
||||
|
|
|
@ -20,6 +20,9 @@ describe('#isTimeChart', () => {
|
|||
seriesType: 'bar',
|
||||
xScaleType: 'time',
|
||||
isHistogram: false,
|
||||
isHorizontal: false,
|
||||
isPercentage: false,
|
||||
isStacked: false,
|
||||
table: {
|
||||
rows: [],
|
||||
columns: [
|
||||
|
|
|
@ -29,38 +29,6 @@ export const strings = {
|
|||
i18n.translate('expressionXY.xyVis.logDatatable.breakDown', {
|
||||
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: () =>
|
||||
i18n.translate('expressionXY.xyVis.legend.help', {
|
||||
defaultMessage: 'Configure the chart legend.',
|
||||
|
@ -77,22 +45,6 @@ export const strings = {
|
|||
i18n.translate('expressionXY.xyVis.valueLabels.help', {
|
||||
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: () =>
|
||||
i18n.translate('expressionXY.xyVis.dataLayer.help', {
|
||||
defaultMessage: 'Data layer of visual series',
|
||||
|
@ -125,6 +77,14 @@ export const strings = {
|
|||
i18n.translate('expressionXY.xyVis.ariaLabel.help', {
|
||||
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: () =>
|
||||
i18n.translate('expressionXY.xyVis.detailedTooltip.help', {
|
||||
defaultMessage: 'Show detailed tooltip',
|
||||
|
@ -185,6 +145,18 @@ export const strings = {
|
|||
i18n.translate('expressionXY.dataLayer.isHistogram.help', {
|
||||
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: () =>
|
||||
i18n.translate('expressionXY.dataLayer.splitAccessor.help', {
|
||||
defaultMessage: 'The column to split by',
|
||||
|
@ -213,9 +185,9 @@ export const strings = {
|
|||
i18n.translate('expressionXY.dataLayer.showLines.help', {
|
||||
defaultMessage: 'Show lines between points',
|
||||
}),
|
||||
getYConfigHelp: () =>
|
||||
i18n.translate('expressionXY.dataLayer.yConfig.help', {
|
||||
defaultMessage: 'Additional configuration for y axes',
|
||||
getDecorationsHelp: () =>
|
||||
i18n.translate('expressionXY.dataLayer.decorations.help', {
|
||||
defaultMessage: 'Additional decoration for data',
|
||||
}),
|
||||
getColumnToLabelHelp: () =>
|
||||
i18n.translate('expressionXY.layer.columnToLabel.help', {
|
||||
|
@ -237,30 +209,26 @@ export const strings = {
|
|||
i18n.translate('expressionXY.referenceLineLayer.accessors.help', {
|
||||
defaultMessage: 'The columns to display on the y axis.',
|
||||
}),
|
||||
getRLYConfigHelp: () =>
|
||||
i18n.translate('expressionXY.referenceLineLayer.yConfig.help', {
|
||||
defaultMessage: 'Additional configuration for y axes',
|
||||
getRLDecorationConfigHelp: () =>
|
||||
i18n.translate('expressionXY.referenceLineLayer.decorationConfig.help', {
|
||||
defaultMessage: 'Additional decoration for reference line',
|
||||
}),
|
||||
getRLHelp: () =>
|
||||
i18n.translate('expressionXY.referenceLineLayer.help', {
|
||||
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: () =>
|
||||
i18n.translate('expressionXY.yConfig.forAccessor.help', {
|
||||
i18n.translate('expressionXY.decorationConfig.forAccessor.help', {
|
||||
defaultMessage: 'The accessor this configuration is for',
|
||||
}),
|
||||
getAxisModeHelp: () =>
|
||||
i18n.translate('expressionXY.yConfig.axisMode.help', {
|
||||
defaultMessage: 'The axis mode of the metric',
|
||||
}),
|
||||
getColorHelp: () =>
|
||||
i18n.translate('expressionXY.yConfig.color.help', {
|
||||
i18n.translate('expressionXY.decorationConfig.color.help', {
|
||||
defaultMessage: 'The color of the series',
|
||||
}),
|
||||
getAxisIdHelp: () =>
|
||||
i18n.translate('expressionXY.decorationConfig.axisId.help', {
|
||||
defaultMessage: 'Id of axis',
|
||||
}),
|
||||
getAnnotationLayerFnHelp: () =>
|
||||
i18n.translate('expressionXY.annotationLayer.help', {
|
||||
defaultMessage: `Configure an annotation layer in the xy chart`,
|
||||
|
@ -273,6 +241,74 @@ export const strings = {
|
|||
i18n.translate('expressionXY.annotationLayer.annotations.help', {
|
||||
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: () =>
|
||||
i18n.translate('expressionXY.referenceLine.name.help', {
|
||||
defaultMessage: 'Reference line name',
|
||||
|
|
|
@ -11,17 +11,17 @@ export const PLUGIN_NAME = 'expressionXy';
|
|||
|
||||
export type {
|
||||
XYArgs,
|
||||
YConfig,
|
||||
EndValue,
|
||||
XYRender,
|
||||
LayerType,
|
||||
YAxisMode,
|
||||
LineStyle,
|
||||
FillStyle,
|
||||
SeriesType,
|
||||
YScaleType,
|
||||
XScaleType,
|
||||
AxisMode,
|
||||
AxisConfig,
|
||||
YAxisConfig,
|
||||
ValidLayer,
|
||||
XYLayerArgs,
|
||||
XYCurveType,
|
||||
|
@ -33,30 +33,28 @@ export type {
|
|||
AxisExtentMode,
|
||||
DataLayerConfig,
|
||||
FittingFunction,
|
||||
ExtendedYConfig,
|
||||
AxisExtentConfig,
|
||||
CollectiveConfig,
|
||||
LegendConfigResult,
|
||||
AxesSettingsConfig,
|
||||
XAxisConfigResult,
|
||||
YAxisConfigResult,
|
||||
CommonXYLayerConfig,
|
||||
DataDecorationConfig,
|
||||
AnnotationLayerArgs,
|
||||
ExtendedYConfigResult,
|
||||
GridlinesConfigResult,
|
||||
DataLayerConfigResult,
|
||||
TickLabelsConfigResult,
|
||||
AxisExtentConfigResult,
|
||||
ReferenceLineLayerArgs,
|
||||
CommonXYDataLayerConfig,
|
||||
LabelsOrientationConfig,
|
||||
ReferenceLineLayerConfig,
|
||||
AvailableReferenceLineIcon,
|
||||
XYExtendedLayerConfigResult,
|
||||
CommonXYAnnotationLayerConfig,
|
||||
ExtendedDataLayerConfigResult,
|
||||
LabelsOrientationConfigResult,
|
||||
CommonXYDataLayerConfigResult,
|
||||
ReferenceLineLayerConfigResult,
|
||||
ReferenceLineDecorationConfig,
|
||||
CommonXYReferenceLineLayerConfig,
|
||||
AxisTitlesVisibilityConfigResult,
|
||||
ReferenceLineDecorationConfigResult,
|
||||
CommonXYReferenceLineLayerConfigResult,
|
||||
} from './types';
|
||||
|
|
|
@ -25,14 +25,11 @@ import {
|
|||
ValueLabelModes,
|
||||
XScaleTypes,
|
||||
XYCurveTypes,
|
||||
YAxisModes,
|
||||
YScaleTypes,
|
||||
AxisModes,
|
||||
REFERENCE_LINE,
|
||||
Y_CONFIG,
|
||||
AXIS_TITLES_VISIBILITY_CONFIG,
|
||||
LABELS_ORIENTATION_CONFIG,
|
||||
TICK_LABELS_CONFIG,
|
||||
GRID_LINES_CONFIG,
|
||||
DATA_DECORATION_CONFIG,
|
||||
REFERENCE_LINE_DECORATION_CONFIG,
|
||||
LEGEND_CONFIG,
|
||||
DATA_LAYER,
|
||||
AXIS_EXTENT_CONFIG,
|
||||
|
@ -40,23 +37,24 @@ import {
|
|||
REFERENCE_LINE_LAYER,
|
||||
ANNOTATION_LAYER,
|
||||
EndValues,
|
||||
EXTENDED_Y_CONFIG,
|
||||
X_AXIS_CONFIG,
|
||||
Y_AXIS_CONFIG,
|
||||
AvailableReferenceLineIcons,
|
||||
XY_VIS,
|
||||
LAYERED_XY_VIS,
|
||||
EXTENDED_ANNOTATION_LAYER,
|
||||
REFERENCE_LINE_Y_CONFIG,
|
||||
EXTENDED_REFERENCE_LINE_DECORATION_CONFIG,
|
||||
} from '../constants';
|
||||
import { XYRender } from './expression_renderers';
|
||||
|
||||
export type EndValue = $Values<typeof EndValues>;
|
||||
export type LayerType = $Values<typeof LayerTypes>;
|
||||
export type YAxisMode = $Values<typeof YAxisModes>;
|
||||
export type LineStyle = $Values<typeof LineStyles>;
|
||||
export type FillStyle = $Values<typeof FillStyles>;
|
||||
export type SeriesType = $Values<typeof SeriesTypes>;
|
||||
export type YScaleType = $Values<typeof YScaleTypes>;
|
||||
export type XScaleType = $Values<typeof XScaleTypes>;
|
||||
export type AxisMode = $Values<typeof AxisModes>;
|
||||
export type XYCurveType = $Values<typeof XYCurveTypes>;
|
||||
export type IconPosition = $Values<typeof IconPositions>;
|
||||
export type ValueLabelMode = $Values<typeof ValueLabelModes>;
|
||||
|
@ -65,7 +63,6 @@ export type FittingFunction = $Values<typeof FittingFunctions>;
|
|||
export type AvailableReferenceLineIcon = $Values<typeof AvailableReferenceLineIcons>;
|
||||
|
||||
export interface AxesSettingsConfig {
|
||||
x: boolean;
|
||||
yLeft: boolean;
|
||||
yRight: boolean;
|
||||
}
|
||||
|
@ -77,23 +74,41 @@ export interface AxisExtentConfig {
|
|||
}
|
||||
|
||||
export interface AxisConfig {
|
||||
title: string;
|
||||
title?: string;
|
||||
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;
|
||||
lineWidth?: number;
|
||||
lineStyle?: LineStyle;
|
||||
fill?: FillStyle;
|
||||
iconPosition?: IconPosition;
|
||||
textVisibility?: boolean;
|
||||
position?: Position;
|
||||
}
|
||||
|
||||
export interface YConfig {
|
||||
export interface DataDecorationConfig {
|
||||
forAccessor: string;
|
||||
axisMode?: YAxisMode;
|
||||
color?: string;
|
||||
axisId?: string;
|
||||
}
|
||||
|
||||
export interface DataLayerArgs {
|
||||
|
@ -110,8 +125,11 @@ export interface DataLayerArgs {
|
|||
columnToLabel?: string; // Actually a JSON key-value pair
|
||||
xScaleType: XScaleType;
|
||||
isHistogram: boolean;
|
||||
isPercentage: boolean;
|
||||
isStacked: boolean;
|
||||
isHorizontal: boolean;
|
||||
palette: PaletteOutput;
|
||||
yConfig?: YConfigResult[];
|
||||
decorations?: DataDecorationConfigResult[];
|
||||
}
|
||||
|
||||
export interface ValidLayer extends DataLayerConfigResult {
|
||||
|
@ -133,9 +151,12 @@ export interface ExtendedDataLayerArgs {
|
|||
columnToLabel?: string; // Actually a JSON key-value pair
|
||||
xScaleType: XScaleType;
|
||||
isHistogram: boolean;
|
||||
isPercentage: boolean;
|
||||
isStacked: boolean;
|
||||
isHorizontal: boolean;
|
||||
palette: PaletteOutput;
|
||||
// palette will always be set on the expression
|
||||
yConfig?: YConfigResult[];
|
||||
decorations?: DataDecorationConfigResult[];
|
||||
table?: Datatable;
|
||||
}
|
||||
|
||||
|
@ -185,22 +206,8 @@ export interface LegendConfig {
|
|||
legendSize?: LegendSize;
|
||||
}
|
||||
|
||||
export interface LabelsOrientationConfig {
|
||||
x: number;
|
||||
yLeft: number;
|
||||
yRight: number;
|
||||
}
|
||||
|
||||
// Arguments to XY chart expression, with computed properties
|
||||
export interface XYArgs extends DataLayerArgs {
|
||||
xTitle: string;
|
||||
yTitle: string;
|
||||
yRightTitle: string;
|
||||
xExtent?: AxisExtentConfigResult;
|
||||
yLeftExtent: AxisExtentConfigResult;
|
||||
yRightExtent: AxisExtentConfigResult;
|
||||
yLeftScale: YScaleType;
|
||||
yRightScale: YScaleType;
|
||||
legend: LegendConfigResult;
|
||||
endValue?: EndValue;
|
||||
emphasizeFitting?: boolean;
|
||||
|
@ -208,15 +215,13 @@ export interface XYArgs extends DataLayerArgs {
|
|||
referenceLines: ReferenceLineConfigResult[];
|
||||
annotationLayers: AnnotationLayerConfigResult[];
|
||||
fittingFunction?: FittingFunction;
|
||||
axisTitlesVisibilitySettings?: AxisTitlesVisibilityConfigResult;
|
||||
tickLabelsVisibilitySettings?: TickLabelsConfigResult;
|
||||
gridlinesVisibilitySettings?: GridlinesConfigResult;
|
||||
labelsOrientation?: LabelsOrientationConfigResult;
|
||||
curveType?: XYCurveType;
|
||||
fillOpacity?: number;
|
||||
hideEndzones?: boolean;
|
||||
valuesInLegend?: boolean;
|
||||
ariaLabel?: string;
|
||||
yAxisConfigs?: YAxisConfigResult[];
|
||||
xAxisConfig?: XAxisConfigResult;
|
||||
addTimeMarker?: boolean;
|
||||
markSizeRatio?: number;
|
||||
minTimeBarInterval?: string;
|
||||
|
@ -228,29 +233,19 @@ export interface XYArgs extends DataLayerArgs {
|
|||
}
|
||||
|
||||
export interface LayeredXYArgs {
|
||||
xTitle: string;
|
||||
yTitle: string;
|
||||
yRightTitle: string;
|
||||
xExtent?: AxisExtentConfigResult;
|
||||
yLeftExtent: AxisExtentConfigResult;
|
||||
yRightExtent: AxisExtentConfigResult;
|
||||
yLeftScale: YScaleType;
|
||||
yRightScale: YScaleType;
|
||||
legend: LegendConfigResult;
|
||||
endValue?: EndValue;
|
||||
emphasizeFitting?: boolean;
|
||||
valueLabels: ValueLabelMode;
|
||||
layers?: XYExtendedLayerConfigResult[];
|
||||
fittingFunction?: FittingFunction;
|
||||
axisTitlesVisibilitySettings?: AxisTitlesVisibilityConfigResult;
|
||||
tickLabelsVisibilitySettings?: TickLabelsConfigResult;
|
||||
gridlinesVisibilitySettings?: GridlinesConfigResult;
|
||||
labelsOrientation?: LabelsOrientationConfigResult;
|
||||
curveType?: XYCurveType;
|
||||
fillOpacity?: number;
|
||||
hideEndzones?: boolean;
|
||||
valuesInLegend?: boolean;
|
||||
ariaLabel?: string;
|
||||
yAxisConfigs?: YAxisConfigResult[];
|
||||
xAxisConfig?: XAxisConfigResult;
|
||||
detailedTooltip?: boolean;
|
||||
addTimeMarker?: boolean;
|
||||
markSizeRatio?: number;
|
||||
|
@ -260,29 +255,19 @@ export interface LayeredXYArgs {
|
|||
}
|
||||
|
||||
export interface XYProps {
|
||||
xTitle: string;
|
||||
yTitle: string;
|
||||
yRightTitle: string;
|
||||
xExtent?: AxisExtentConfigResult;
|
||||
yLeftExtent: AxisExtentConfigResult;
|
||||
yRightExtent: AxisExtentConfigResult;
|
||||
yLeftScale: YScaleType;
|
||||
yRightScale: YScaleType;
|
||||
legend: LegendConfigResult;
|
||||
endValue?: EndValue;
|
||||
emphasizeFitting?: boolean;
|
||||
valueLabels: ValueLabelMode;
|
||||
layers: CommonXYLayerConfig[];
|
||||
fittingFunction?: FittingFunction;
|
||||
axisTitlesVisibilitySettings?: AxisTitlesVisibilityConfigResult;
|
||||
tickLabelsVisibilitySettings?: TickLabelsConfigResult;
|
||||
gridlinesVisibilitySettings?: GridlinesConfigResult;
|
||||
labelsOrientation?: LabelsOrientationConfigResult;
|
||||
curveType?: XYCurveType;
|
||||
fillOpacity?: number;
|
||||
hideEndzones?: boolean;
|
||||
valuesInLegend?: boolean;
|
||||
ariaLabel?: string;
|
||||
yAxisConfigs?: YAxisConfigResult[];
|
||||
xAxisConfig?: XAxisConfigResult;
|
||||
addTimeMarker?: boolean;
|
||||
markSizeRatio?: number;
|
||||
minTimeBarInterval?: string;
|
||||
|
@ -312,7 +297,8 @@ export type ExtendedAnnotationLayerConfigResult = ExtendedAnnotationLayerArgs &
|
|||
layerType: typeof LayerTypes.ANNOTATIONS;
|
||||
};
|
||||
|
||||
export interface ReferenceLineArgs extends Omit<ExtendedYConfig, 'forAccessor' | 'fill'> {
|
||||
export interface ReferenceLineArgs
|
||||
extends Omit<ReferenceLineDecorationConfig, 'forAccessor' | 'fill'> {
|
||||
name?: string;
|
||||
value: number;
|
||||
fill: FillStyle;
|
||||
|
@ -322,7 +308,7 @@ export interface ReferenceLineLayerArgs {
|
|||
layerId?: string;
|
||||
accessors: string[];
|
||||
columnToLabel?: string;
|
||||
yConfig?: ExtendedYConfigResult[];
|
||||
decorations?: ReferenceLineDecorationConfigResult[];
|
||||
table?: Datatable;
|
||||
}
|
||||
|
||||
|
@ -338,15 +324,15 @@ export type XYExtendedLayerConfigResult =
|
|||
| ReferenceLineLayerConfigResult
|
||||
| ExtendedAnnotationLayerConfigResult;
|
||||
|
||||
export interface ReferenceLineYConfig extends ReferenceLineArgs {
|
||||
type: typeof REFERENCE_LINE_Y_CONFIG;
|
||||
export interface ExtendedReferenceLineDecorationConfig extends ReferenceLineArgs {
|
||||
type: typeof EXTENDED_REFERENCE_LINE_DECORATION_CONFIG;
|
||||
}
|
||||
|
||||
export interface ReferenceLineConfigResult {
|
||||
type: typeof REFERENCE_LINE;
|
||||
layerType: typeof LayerTypes.REFERENCELINE;
|
||||
lineLength: number;
|
||||
yConfig: [ReferenceLineYConfig];
|
||||
decorations: [ExtendedReferenceLineDecorationConfig];
|
||||
}
|
||||
|
||||
export type ReferenceLineLayerConfigResult = ReferenceLineLayerArgs & {
|
||||
|
@ -381,21 +367,18 @@ export type ExtendedDataLayerConfigResult = Omit<ExtendedDataLayerArgs, 'palette
|
|||
table: Datatable;
|
||||
};
|
||||
|
||||
export type YConfigResult = YConfig & { type: typeof Y_CONFIG };
|
||||
export type ExtendedYConfigResult = ExtendedYConfig & { type: typeof EXTENDED_Y_CONFIG };
|
||||
|
||||
export type AxisTitlesVisibilityConfigResult = AxesSettingsConfig & {
|
||||
type: typeof AXIS_TITLES_VISIBILITY_CONFIG;
|
||||
export type DataDecorationConfigResult = DataDecorationConfig & {
|
||||
type: typeof DATA_DECORATION_CONFIG;
|
||||
};
|
||||
export type ReferenceLineDecorationConfigResult = ReferenceLineDecorationConfig & {
|
||||
type: typeof REFERENCE_LINE_DECORATION_CONFIG;
|
||||
};
|
||||
|
||||
export type LabelsOrientationConfigResult = LabelsOrientationConfig & {
|
||||
type: typeof LABELS_ORIENTATION_CONFIG;
|
||||
};
|
||||
export type XAxisConfigResult = AxisConfig & { type: typeof X_AXIS_CONFIG };
|
||||
export type YAxisConfigResult = YAxisConfig & { type: typeof Y_AXIS_CONFIG };
|
||||
|
||||
export type LegendConfigResult = LegendConfig & { type: typeof LEGEND_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 CommonXYDataLayerConfigResult = DataLayerConfigResult | ExtendedDataLayerConfigResult;
|
||||
|
@ -441,12 +424,17 @@ export type ReferenceLineLayerFn = ExpressionFunctionDefinition<
|
|||
Promise<ReferenceLineLayerConfigResult>
|
||||
>;
|
||||
|
||||
export type YConfigFn = ExpressionFunctionDefinition<typeof Y_CONFIG, null, YConfig, YConfigResult>;
|
||||
export type ExtendedYConfigFn = ExpressionFunctionDefinition<
|
||||
typeof EXTENDED_Y_CONFIG,
|
||||
export type DataDecorationConfigFn = ExpressionFunctionDefinition<
|
||||
typeof DATA_DECORATION_CONFIG,
|
||||
null,
|
||||
ExtendedYConfig,
|
||||
ExtendedYConfigResult
|
||||
DataDecorationConfig,
|
||||
DataDecorationConfigResult
|
||||
>;
|
||||
export type ReferenceLineDecorationConfigFn = ExpressionFunctionDefinition<
|
||||
typeof REFERENCE_LINE_DECORATION_CONFIG,
|
||||
null,
|
||||
ReferenceLineDecorationConfig,
|
||||
ReferenceLineDecorationConfigResult
|
||||
>;
|
||||
|
||||
export type LegendConfigFn = ExpressionFunctionDefinition<
|
||||
|
@ -455,3 +443,17 @@ export type LegendConfigFn = ExpressionFunctionDefinition<
|
|||
LegendConfig,
|
||||
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'> {
|
||||
roundedTimestamp: number;
|
||||
axisMode: 'bottom';
|
||||
position: 'bottom';
|
||||
icon?: AvailableAnnotationIcon | string;
|
||||
customTooltipDetails?: AnnotationTooltipFormatter | undefined;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { Position } from '@elastic/charts';
|
||||
import { Datatable } from '@kbn/expressions-plugin/common';
|
||||
import { chartPluginMock } from '@kbn/charts-plugin/public/mocks';
|
||||
import { LayerTypes } from '../../common/constants';
|
||||
|
@ -167,8 +168,11 @@ export const dateHistogramLayer: DataLayerConfig = {
|
|||
xAccessor: 'xAccessorId',
|
||||
xScaleType: 'time',
|
||||
isHistogram: true,
|
||||
isStacked: true,
|
||||
isPercentage: false,
|
||||
isHorizontal: false,
|
||||
splitAccessor: 'splitAccessorId',
|
||||
seriesType: 'bar_stacked',
|
||||
seriesType: 'bar',
|
||||
accessors: ['yAccessorId'],
|
||||
palette: mockPaletteOutput,
|
||||
table: dateHistogramData,
|
||||
|
@ -197,7 +201,13 @@ export function sampleArgsWithReferenceLine(value: number = 150) {
|
|||
type: 'referenceLineLayer',
|
||||
layerType: LayerTypes.REFERENCELINE,
|
||||
accessors: ['referenceLine-a'],
|
||||
yConfig: [{ axisMode: 'left', forAccessor: 'referenceLine-a', type: 'extendedYConfig' }],
|
||||
decorations: [
|
||||
{
|
||||
forAccessor: 'referenceLine-a',
|
||||
type: 'referenceLineDecorationConfig',
|
||||
position: Position.Left,
|
||||
},
|
||||
],
|
||||
table: data,
|
||||
},
|
||||
],
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -155,7 +155,7 @@ export const getAnnotationsGroupedByInterval = (
|
|||
collectiveConfig = {
|
||||
...configArr[0],
|
||||
roundedTimestamp: Number(roundedTimestamp),
|
||||
axisMode: 'bottom',
|
||||
position: 'bottom',
|
||||
};
|
||||
if (configArr.length > 1) {
|
||||
const commonStyles = getCommonStyles(configArr);
|
||||
|
|
|
@ -25,7 +25,7 @@ import {
|
|||
XYCurveType,
|
||||
XScaleType,
|
||||
} from '../../common';
|
||||
import { SeriesTypes, ValueLabelModes } from '../../common/constants';
|
||||
import { SeriesTypes, ValueLabelModes, AxisModes } from '../../common/constants';
|
||||
import {
|
||||
getColorAssignments,
|
||||
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
|
||||
const formattedDatatableInfo = formattedDatatables[layerId];
|
||||
|
||||
const isPercentage = seriesType.includes('percentage');
|
||||
|
||||
const yAxis = yAxesConfiguration.find((axisConfiguration) =>
|
||||
axisConfiguration.series.find((currentSeries) => currentSeries.accessor === yColumnId)
|
||||
);
|
||||
|
||||
const isPercentage = yAxis?.mode
|
||||
? yAxis?.mode === AxisModes.PERCENTAGE
|
||||
: layer.isPercentage;
|
||||
|
||||
const seriesProps = getSeriesProps({
|
||||
layer,
|
||||
titles: titles[layer.layerId],
|
||||
|
@ -129,11 +131,6 @@ export const DataLayers: FC<Props> = ({
|
|||
/>
|
||||
);
|
||||
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 = {
|
||||
displayValueSettings: {
|
||||
// This format double fixes two issues in elastic-chart
|
||||
|
@ -150,22 +147,12 @@ export const DataLayers: FC<Props> = ({
|
|||
},
|
||||
};
|
||||
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:
|
||||
return (
|
||||
<AreaSeries
|
||||
key={index}
|
||||
{...seriesProps}
|
||||
fit={getFitOptions(fittingFunction, endValue)}
|
||||
fit={isPercentage ? 'zero' : getFitOptions(fittingFunction, endValue)}
|
||||
curve={curve}
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -157,6 +157,9 @@ const sampleLayer: DataLayerConfig = {
|
|||
type: 'dataLayer',
|
||||
layerType: LayerTypes.DATA,
|
||||
seriesType: 'line',
|
||||
isStacked: false,
|
||||
isPercentage: false,
|
||||
isHorizontal: false,
|
||||
showLines: true,
|
||||
xAccessor: 'c',
|
||||
accessors: ['a', 'b'],
|
||||
|
|
|
@ -10,47 +10,49 @@ import React, { FC } from 'react';
|
|||
import { Position } from '@elastic/charts';
|
||||
import { FieldFormat } from '@kbn/field-formats-plugin/common';
|
||||
import { ReferenceLineConfig } from '../../../common/types';
|
||||
import { getGroupId } from './utils';
|
||||
import { ReferenceLineAnnotations } from './reference_line_annotations';
|
||||
import { AxesMap, GroupsConfiguration } from '../../helpers';
|
||||
import { getAxisGroupForReferenceLine } from './utils';
|
||||
|
||||
interface ReferenceLineProps {
|
||||
layer: ReferenceLineConfig;
|
||||
paddingMap: Partial<Record<Position, number>>;
|
||||
formatters: Record<'left' | 'right' | 'bottom', FieldFormat | undefined>;
|
||||
axesMap: Record<'left' | 'right', boolean>;
|
||||
xAxisFormatter: FieldFormat;
|
||||
axesConfiguration: GroupsConfiguration;
|
||||
isHorizontal: boolean;
|
||||
nextValue?: number;
|
||||
yAxesMap: AxesMap;
|
||||
}
|
||||
|
||||
export const ReferenceLine: FC<ReferenceLineProps> = ({
|
||||
layer,
|
||||
axesMap,
|
||||
formatters,
|
||||
axesConfiguration,
|
||||
xAxisFormatter,
|
||||
paddingMap,
|
||||
isHorizontal,
|
||||
nextValue,
|
||||
yAxesMap,
|
||||
}) => {
|
||||
const {
|
||||
yConfig: [yConfig],
|
||||
decorations: [decorationConfig],
|
||||
} = layer;
|
||||
|
||||
if (!yConfig) {
|
||||
if (!decorationConfig) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { axisMode, value } = yConfig;
|
||||
const { value } = decorationConfig;
|
||||
|
||||
// Find the formatter for the given axis
|
||||
const groupId = getGroupId(axisMode);
|
||||
const axisGroup = getAxisGroupForReferenceLine(axesConfiguration, decorationConfig, isHorizontal);
|
||||
|
||||
const formatter = formatters[groupId || 'bottom'];
|
||||
const formatter = axisGroup?.formatter || xAxisFormatter;
|
||||
const id = `${layer.layerId}-${value}`;
|
||||
|
||||
return (
|
||||
<ReferenceLineAnnotations
|
||||
config={{ id, ...yConfig, nextValue }}
|
||||
config={{ id, ...decorationConfig, nextValue, axisGroup }}
|
||||
paddingMap={paddingMap}
|
||||
axesMap={axesMap}
|
||||
axesMap={yAxesMap}
|
||||
formatter={formatter}
|
||||
isHorizontal={isHorizontal}
|
||||
/>
|
||||
|
|
|
@ -10,18 +10,21 @@ import { AnnotationDomainType, LineAnnotation, Position, RectAnnotation } from '
|
|||
import { euiLightVars } from '@kbn/ui-theme';
|
||||
import React, { FC } from 'react';
|
||||
import { FieldFormat } from '@kbn/field-formats-plugin/common';
|
||||
import { LINES_MARKER_SIZE } from '../../helpers';
|
||||
import {
|
||||
AxesMap,
|
||||
AxisConfiguration,
|
||||
getOriginalAxisPosition,
|
||||
LINES_MARKER_SIZE,
|
||||
} from '../../helpers';
|
||||
import {
|
||||
AvailableReferenceLineIcon,
|
||||
FillStyle,
|
||||
IconPosition,
|
||||
LineStyle,
|
||||
YAxisMode,
|
||||
} from '../../../common/types';
|
||||
import {
|
||||
getBaseIconPlacement,
|
||||
getBottomRect,
|
||||
getGroupId,
|
||||
getHorizontalRect,
|
||||
getLineAnnotationProps,
|
||||
getSharedStyle,
|
||||
|
@ -38,7 +41,7 @@ export interface ReferenceLineAnnotationConfig {
|
|||
fill?: FillStyle;
|
||||
iconPosition?: IconPosition;
|
||||
textVisibility?: boolean;
|
||||
axisMode?: YAxisMode;
|
||||
axisGroup?: AxisConfiguration;
|
||||
color?: string;
|
||||
}
|
||||
|
||||
|
@ -46,18 +49,19 @@ interface Props {
|
|||
config: ReferenceLineAnnotationConfig;
|
||||
paddingMap: Partial<Record<Position, number>>;
|
||||
formatter?: FieldFormat;
|
||||
axesMap: Record<'left' | 'right', boolean>;
|
||||
axesMap: AxesMap;
|
||||
isHorizontal: boolean;
|
||||
}
|
||||
|
||||
const getRectDataValue = (
|
||||
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';
|
||||
|
||||
if (axisMode === 'bottom') {
|
||||
if (groupId === Position.Bottom) {
|
||||
return getBottomRect(name, isFillAbove, formatter, value, nextValue);
|
||||
}
|
||||
|
||||
|
@ -71,13 +75,15 @@ export const ReferenceLineAnnotations: FC<Props> = ({
|
|||
paddingMap,
|
||||
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;
|
||||
// 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
|
||||
const hasReducedPadding = paddingMap[markerPositionVertical] === LINES_MARKER_SIZE;
|
||||
|
||||
|
@ -89,7 +95,6 @@ export const ReferenceLineAnnotations: FC<Props> = ({
|
|||
},
|
||||
axesMap,
|
||||
paddingMap,
|
||||
groupId,
|
||||
isHorizontal
|
||||
);
|
||||
|
||||
|
@ -108,7 +113,9 @@ export const ReferenceLineAnnotations: FC<Props> = ({
|
|||
key={`${id}-line`}
|
||||
dataValues={[dataValues]}
|
||||
domainType={
|
||||
axisMode === 'bottom' ? AnnotationDomainType.XDomain : AnnotationDomainType.YDomain
|
||||
props.groupId === Position.Bottom
|
||||
? AnnotationDomainType.XDomain
|
||||
: AnnotationDomainType.YDomain
|
||||
}
|
||||
style={{ line: { ...sharedStyle, opacity: 1 } }}
|
||||
/>
|
||||
|
@ -116,7 +123,7 @@ export const ReferenceLineAnnotations: FC<Props> = ({
|
|||
|
||||
let rect;
|
||||
if (fill && fill !== 'none') {
|
||||
const rectDataValues = getRectDataValue(config, formatter);
|
||||
const rectDataValues = getRectDataValue(config, formatter, props.groupId);
|
||||
|
||||
rect = (
|
||||
<RectAnnotation
|
||||
|
|
|
@ -11,67 +11,73 @@ import { FieldFormat } from '@kbn/field-formats-plugin/common';
|
|||
import { groupBy } from 'lodash';
|
||||
import { Position } from '@elastic/charts';
|
||||
import { ReferenceLineLayerConfig } from '../../../common/types';
|
||||
import { getGroupId } from './utils';
|
||||
import { ReferenceLineAnnotations } from './reference_line_annotations';
|
||||
import { LayerAccessorsTitles } from '../../helpers';
|
||||
import { LayerAccessorsTitles, GroupsConfiguration, AxesMap } from '../../helpers';
|
||||
import { getAxisGroupForReferenceLine } from './utils';
|
||||
|
||||
interface ReferenceLineLayerProps {
|
||||
layer: ReferenceLineLayerConfig;
|
||||
formatters: Record<'left' | 'right' | 'bottom', FieldFormat | undefined>;
|
||||
paddingMap: Partial<Record<Position, number>>;
|
||||
axesMap: Record<'left' | 'right', boolean>;
|
||||
isHorizontal: boolean;
|
||||
titles?: LayerAccessorsTitles;
|
||||
xAxisFormatter: FieldFormat;
|
||||
axesConfiguration: GroupsConfiguration;
|
||||
yAxesMap: AxesMap;
|
||||
}
|
||||
|
||||
export const ReferenceLineLayer: FC<ReferenceLineLayerProps> = ({
|
||||
layer,
|
||||
formatters,
|
||||
axesConfiguration,
|
||||
xAxisFormatter,
|
||||
paddingMap,
|
||||
axesMap,
|
||||
isHorizontal,
|
||||
titles,
|
||||
yAxesMap,
|
||||
}) => {
|
||||
if (!layer.yConfig) {
|
||||
if (!layer.decorations) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { columnToLabel, yConfig: yConfigs, table } = layer;
|
||||
const { columnToLabel, decorations, table } = layer;
|
||||
const columnToLabelMap: Record<string, string> = columnToLabel ? JSON.parse(columnToLabel) : {};
|
||||
|
||||
const row = table.rows[0];
|
||||
|
||||
const yConfigByValue = yConfigs.sort(
|
||||
const decorationConfigsByValue = decorations.sort(
|
||||
({ forAccessor: idA }, { forAccessor: idB }) => row[idA] - row[idB]
|
||||
);
|
||||
|
||||
const groupedByDirection = groupBy(yConfigByValue, 'fill');
|
||||
const groupedByDirection = groupBy(decorationConfigsByValue, 'fill');
|
||||
if (groupedByDirection.below) {
|
||||
groupedByDirection.below.reverse();
|
||||
}
|
||||
|
||||
const referenceLineElements = yConfigByValue.flatMap((yConfig) => {
|
||||
const { axisMode } = yConfig;
|
||||
|
||||
// Find the formatter for the given axis
|
||||
const groupId = getGroupId(axisMode);
|
||||
|
||||
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 referenceLineElements = decorationConfigsByValue.flatMap((decorationConfig) => {
|
||||
const axisGroup = getAxisGroupForReferenceLine(
|
||||
axesConfiguration,
|
||||
decorationConfig,
|
||||
isHorizontal
|
||||
);
|
||||
|
||||
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
|
||||
? row[yConfigsWithSameDirection[indexFromSameType + 1].forAccessor]
|
||||
? row[yDecorationsWithSameDirection[indexFromSameType + 1].forAccessor]
|
||||
: undefined;
|
||||
|
||||
const { forAccessor, type, ...restAnnotationConfig } = yConfig;
|
||||
const id = `${layer.layerId}-${yConfig.forAccessor}`;
|
||||
const { forAccessor, type, ...restAnnotationConfig } = decorationConfig;
|
||||
const id = `${layer.layerId}-${decorationConfig.forAccessor}`;
|
||||
|
||||
return (
|
||||
<ReferenceLineAnnotations
|
||||
|
@ -82,9 +88,10 @@ export const ReferenceLineLayer: FC<ReferenceLineLayerProps> = ({
|
|||
nextValue,
|
||||
name,
|
||||
...restAnnotationConfig,
|
||||
axisGroup,
|
||||
}}
|
||||
axesMap={yAxesMap}
|
||||
paddingMap={paddingMap}
|
||||
axesMap={axesMap}
|
||||
formatter={formatter}
|
||||
isHorizontal={isHorizontal}
|
||||
/>
|
||||
|
|
|
@ -15,7 +15,7 @@ import { LayerTypes } from '../../../common/constants';
|
|||
import {
|
||||
ReferenceLineLayerArgs,
|
||||
ReferenceLineLayerConfig,
|
||||
ExtendedYConfig,
|
||||
ExtendedReferenceLineDecorationConfig,
|
||||
ReferenceLineArgs,
|
||||
ReferenceLineConfig,
|
||||
} from '../../../common/types';
|
||||
|
@ -46,12 +46,14 @@ const data: Datatable = {
|
|||
})),
|
||||
};
|
||||
|
||||
function createLayers(yConfigs: ReferenceLineLayerArgs['yConfig']): ReferenceLineLayerConfig[] {
|
||||
function createLayers(
|
||||
decorations: ReferenceLineLayerArgs['decorations']
|
||||
): ReferenceLineLayerConfig[] {
|
||||
return [
|
||||
{
|
||||
layerId: 'first',
|
||||
accessors: (yConfigs || []).map(({ forAccessor }) => forAccessor),
|
||||
yConfig: yConfigs,
|
||||
accessors: (decorations || []).map(({ forAccessor }) => forAccessor),
|
||||
decorations,
|
||||
type: 'referenceLineLayer',
|
||||
layerType: LayerTypes.REFERENCELINE,
|
||||
table: data,
|
||||
|
@ -69,7 +71,7 @@ function createReferenceLine(
|
|||
type: 'referenceLine',
|
||||
layerType: 'referenceLine',
|
||||
lineLength,
|
||||
yConfig: [{ type: 'referenceLineYConfig', ...args }],
|
||||
decorations: [{ type: 'extendedReferenceLineDecorationConfig', ...args }],
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -82,7 +84,7 @@ interface XCoords {
|
|||
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';
|
||||
}
|
||||
|
||||
|
@ -90,21 +92,42 @@ const emptyCoords = { x0: undefined, x1: undefined, y0: undefined, y1: undefined
|
|||
|
||||
describe('ReferenceLines', () => {
|
||||
describe('referenceLineLayers', () => {
|
||||
let formatters: Record<'left' | 'right' | 'bottom', FieldFormat | undefined>;
|
||||
let defaultProps: Omit<ReferenceLinesProps, 'data' | 'layers'>;
|
||||
|
||||
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 = {
|
||||
formatters,
|
||||
xAxisFormatter: { convert: jest.fn((x) => x) } as unknown as FieldFormat,
|
||||
isHorizontal: false,
|
||||
axesMap: { left: true, right: false },
|
||||
axesConfiguration: [
|
||||
{
|
||||
groupId: 'left',
|
||||
position: 'left',
|
||||
series: [],
|
||||
},
|
||||
{
|
||||
groupId: 'right',
|
||||
position: 'right',
|
||||
series: [],
|
||||
},
|
||||
{
|
||||
groupId: 'bottom',
|
||||
position: 'bottom',
|
||||
series: [],
|
||||
},
|
||||
],
|
||||
paddingMap: {},
|
||||
yAxesMap: {
|
||||
left: {
|
||||
groupId: 'left',
|
||||
position: 'left',
|
||||
series: [],
|
||||
},
|
||||
right: {
|
||||
groupId: 'right',
|
||||
position: 'right',
|
||||
series: [],
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -113,20 +136,20 @@ describe('ReferenceLines', () => {
|
|||
['yAccessorLeft', 'below'],
|
||||
['yAccessorRight', 'above'],
|
||||
['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',
|
||||
(layerPrefix, fill) => {
|
||||
const axisMode = getAxisFromId(layerPrefix);
|
||||
const position = getAxisFromId(layerPrefix);
|
||||
const wrapper = shallow(
|
||||
<ReferenceLines
|
||||
{...defaultProps}
|
||||
layers={createLayers([
|
||||
{
|
||||
forAccessor: `${layerPrefix}FirstId`,
|
||||
axisMode,
|
||||
position,
|
||||
lineStyle: 'solid',
|
||||
fill,
|
||||
type: 'extendedYConfig',
|
||||
type: 'referenceLineDecorationConfig',
|
||||
},
|
||||
])}
|
||||
/>
|
||||
|
@ -154,7 +177,7 @@ describe('ReferenceLines', () => {
|
|||
it.each([
|
||||
['xAccessor', 'above'],
|
||||
['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',
|
||||
(layerPrefix, fill) => {
|
||||
const wrapper = shallow(
|
||||
|
@ -163,9 +186,9 @@ describe('ReferenceLines', () => {
|
|||
layers={createLayers([
|
||||
{
|
||||
forAccessor: `${layerPrefix}FirstId`,
|
||||
axisMode: 'bottom',
|
||||
position: 'bottom',
|
||||
lineStyle: 'solid',
|
||||
type: 'extendedYConfig',
|
||||
type: 'referenceLineDecorationConfig',
|
||||
fill,
|
||||
},
|
||||
])}
|
||||
|
@ -196,26 +219,26 @@ describe('ReferenceLines', () => {
|
|||
['yAccessorLeft', 'below', { y0: undefined, y1: 5 }, { y0: 5, y1: 10 }],
|
||||
['yAccessorRight', 'above', { y0: 5, y1: 10 }, { y0: 10, y1: undefined }],
|
||||
['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',
|
||||
(layerPrefix, fill, coordsA, coordsB) => {
|
||||
const axisMode = getAxisFromId(layerPrefix);
|
||||
const position = getAxisFromId(layerPrefix);
|
||||
const wrapper = shallow(
|
||||
<ReferenceLines
|
||||
{...defaultProps}
|
||||
layers={createLayers([
|
||||
{
|
||||
forAccessor: `${layerPrefix}FirstId`,
|
||||
axisMode,
|
||||
position,
|
||||
lineStyle: 'solid',
|
||||
type: 'extendedYConfig',
|
||||
type: 'referenceLineDecorationConfig',
|
||||
fill,
|
||||
},
|
||||
{
|
||||
forAccessor: `${layerPrefix}SecondId`,
|
||||
axisMode,
|
||||
position,
|
||||
lineStyle: 'solid',
|
||||
type: 'extendedYConfig',
|
||||
type: 'referenceLineDecorationConfig',
|
||||
fill,
|
||||
},
|
||||
])}
|
||||
|
@ -252,7 +275,7 @@ describe('ReferenceLines', () => {
|
|||
it.each([
|
||||
['xAccessor', 'above', { x0: 1, x1: 2 }, { x0: 2, x1: undefined }],
|
||||
['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',
|
||||
(layerPrefix, fill, coordsA, coordsB) => {
|
||||
const wrapper = shallow(
|
||||
|
@ -261,16 +284,16 @@ describe('ReferenceLines', () => {
|
|||
layers={createLayers([
|
||||
{
|
||||
forAccessor: `${layerPrefix}FirstId`,
|
||||
axisMode: 'bottom',
|
||||
position: 'bottom',
|
||||
lineStyle: 'solid',
|
||||
type: 'extendedYConfig',
|
||||
type: 'referenceLineDecorationConfig',
|
||||
fill,
|
||||
},
|
||||
{
|
||||
forAccessor: `${layerPrefix}SecondId`,
|
||||
axisMode: 'bottom',
|
||||
position: 'bottom',
|
||||
lineStyle: 'solid',
|
||||
type: 'extendedYConfig',
|
||||
type: 'referenceLineDecorationConfig',
|
||||
fill,
|
||||
},
|
||||
])}
|
||||
|
@ -307,7 +330,7 @@ describe('ReferenceLines', () => {
|
|||
it.each(['yAccessorLeft', 'yAccessorRight', 'xAccessor'])(
|
||||
'should let areas in different directions overlap: %s',
|
||||
(layerPrefix) => {
|
||||
const axisMode = getAxisFromId(layerPrefix);
|
||||
const position = getAxisFromId(layerPrefix);
|
||||
|
||||
const wrapper = shallow(
|
||||
<ReferenceLines
|
||||
|
@ -315,17 +338,17 @@ describe('ReferenceLines', () => {
|
|||
layers={createLayers([
|
||||
{
|
||||
forAccessor: `${layerPrefix}FirstId`,
|
||||
axisMode,
|
||||
position,
|
||||
lineStyle: 'solid',
|
||||
fill: 'above',
|
||||
type: 'extendedYConfig',
|
||||
type: 'referenceLineDecorationConfig',
|
||||
},
|
||||
{
|
||||
forAccessor: `${layerPrefix}SecondId`,
|
||||
axisMode,
|
||||
position,
|
||||
lineStyle: 'solid',
|
||||
fill: 'below',
|
||||
type: 'extendedYConfig',
|
||||
type: 'referenceLineDecorationConfig',
|
||||
},
|
||||
])}
|
||||
/>
|
||||
|
@ -338,8 +361,8 @@ describe('ReferenceLines', () => {
|
|||
).toEqual(
|
||||
expect.arrayContaining([
|
||||
{
|
||||
coordinates: { ...emptyCoords, ...(axisMode === 'bottom' ? { x0: 1 } : { y0: 5 }) },
|
||||
details: axisMode === 'bottom' ? 1 : 5,
|
||||
coordinates: { ...emptyCoords, ...(position === 'bottom' ? { x0: 1 } : { y0: 5 }) },
|
||||
details: position === 'bottom' ? 1 : 5,
|
||||
header: undefined,
|
||||
},
|
||||
])
|
||||
|
@ -349,8 +372,8 @@ describe('ReferenceLines', () => {
|
|||
).toEqual(
|
||||
expect.arrayContaining([
|
||||
{
|
||||
coordinates: { ...emptyCoords, ...(axisMode === 'bottom' ? { x1: 2 } : { y1: 10 }) },
|
||||
details: axisMode === 'bottom' ? 2 : 10,
|
||||
coordinates: { ...emptyCoords, ...(position === 'bottom' ? { x1: 2 } : { y1: 10 }) },
|
||||
details: position === 'bottom' ? 2 : 10,
|
||||
header: undefined,
|
||||
},
|
||||
])
|
||||
|
@ -361,7 +384,7 @@ describe('ReferenceLines', () => {
|
|||
it.each([
|
||||
['above', { y0: 5, y1: 10 }, { y0: 10, y1: undefined }],
|
||||
['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',
|
||||
(fill, coordsA, coordsB) => {
|
||||
const wrapper = shallow(
|
||||
|
@ -370,17 +393,17 @@ describe('ReferenceLines', () => {
|
|||
layers={createLayers([
|
||||
{
|
||||
forAccessor: `yAccessorLeftFirstId`,
|
||||
axisMode: 'left',
|
||||
position: 'left',
|
||||
lineStyle: 'solid',
|
||||
fill,
|
||||
type: 'extendedYConfig',
|
||||
type: 'referenceLineDecorationConfig',
|
||||
},
|
||||
{
|
||||
forAccessor: `yAccessorRightSecondId`,
|
||||
axisMode: 'right',
|
||||
position: 'right',
|
||||
lineStyle: 'solid',
|
||||
fill,
|
||||
type: 'extendedYConfig',
|
||||
type: 'referenceLineDecorationConfig',
|
||||
},
|
||||
])}
|
||||
/>
|
||||
|
@ -415,21 +438,42 @@ describe('ReferenceLines', () => {
|
|||
});
|
||||
|
||||
describe('referenceLines', () => {
|
||||
let formatters: Record<'left' | 'right' | 'bottom', FieldFormat | undefined>;
|
||||
let defaultProps: Omit<ReferenceLinesProps, 'data' | 'layers'>;
|
||||
|
||||
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 = {
|
||||
formatters,
|
||||
xAxisFormatter: { convert: jest.fn((x) => x) } as unknown as FieldFormat,
|
||||
isHorizontal: false,
|
||||
axesMap: { left: true, right: false },
|
||||
axesConfiguration: [
|
||||
{
|
||||
groupId: 'left',
|
||||
position: 'left',
|
||||
series: [],
|
||||
},
|
||||
{
|
||||
groupId: 'right',
|
||||
position: 'right',
|
||||
series: [],
|
||||
},
|
||||
{
|
||||
groupId: 'bottom',
|
||||
position: 'bottom',
|
||||
series: [],
|
||||
},
|
||||
],
|
||||
paddingMap: {},
|
||||
yAxesMap: {
|
||||
left: {
|
||||
groupId: 'left',
|
||||
position: 'left',
|
||||
series: [],
|
||||
},
|
||||
right: {
|
||||
groupId: 'right',
|
||||
position: 'right',
|
||||
series: [],
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -438,17 +482,17 @@ describe('ReferenceLines', () => {
|
|||
['yAccessorLeft', 'below'],
|
||||
['yAccessorRight', 'above'],
|
||||
['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',
|
||||
(layerPrefix, fill) => {
|
||||
const axisMode = getAxisFromId(layerPrefix);
|
||||
const position = getAxisFromId(layerPrefix);
|
||||
const value = 5;
|
||||
const wrapper = shallow(
|
||||
<ReferenceLines
|
||||
{...defaultProps}
|
||||
layers={[
|
||||
createReferenceLine(layerPrefix, 1, {
|
||||
axisMode,
|
||||
position,
|
||||
lineStyle: 'solid',
|
||||
fill,
|
||||
value,
|
||||
|
@ -479,7 +523,7 @@ describe('ReferenceLines', () => {
|
|||
it.each([
|
||||
['xAccessor', 'above'],
|
||||
['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',
|
||||
(layerPrefix, fill) => {
|
||||
const value = 1;
|
||||
|
@ -488,7 +532,7 @@ describe('ReferenceLines', () => {
|
|||
{...defaultProps}
|
||||
layers={[
|
||||
createReferenceLine(layerPrefix, 1, {
|
||||
axisMode: 'bottom',
|
||||
position: 'bottom',
|
||||
lineStyle: 'solid',
|
||||
fill,
|
||||
value,
|
||||
|
@ -519,23 +563,23 @@ describe('ReferenceLines', () => {
|
|||
it.each([
|
||||
['yAccessorLeft', 'above', { y0: 10, y1: undefined }, { y0: 10, y1: undefined }],
|
||||
['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',
|
||||
(layerPrefix, fill, coordsA, coordsB) => {
|
||||
const axisMode = getAxisFromId(layerPrefix);
|
||||
const position = getAxisFromId(layerPrefix);
|
||||
const value = coordsA.y0 ?? coordsA.y1!;
|
||||
const wrapper = shallow(
|
||||
<ReferenceLines
|
||||
{...defaultProps}
|
||||
layers={[
|
||||
createReferenceLine(layerPrefix, 10, {
|
||||
axisMode,
|
||||
position,
|
||||
lineStyle: 'solid',
|
||||
fill,
|
||||
value,
|
||||
}),
|
||||
createReferenceLine(layerPrefix, 10, {
|
||||
axisMode,
|
||||
position,
|
||||
lineStyle: 'solid',
|
||||
fill,
|
||||
value,
|
||||
|
@ -570,7 +614,7 @@ describe('ReferenceLines', () => {
|
|||
it.each([
|
||||
['xAccessor', 'above', { x0: 1, x1: undefined }, { x0: 1, x1: undefined }],
|
||||
['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',
|
||||
(layerPrefix, fill, coordsA, coordsB) => {
|
||||
const value = coordsA.x0 ?? coordsA.x1!;
|
||||
|
@ -579,13 +623,13 @@ describe('ReferenceLines', () => {
|
|||
{...defaultProps}
|
||||
layers={[
|
||||
createReferenceLine(layerPrefix, 10, {
|
||||
axisMode: 'bottom',
|
||||
position: 'bottom',
|
||||
lineStyle: 'solid',
|
||||
fill,
|
||||
value,
|
||||
}),
|
||||
createReferenceLine(layerPrefix, 10, {
|
||||
axisMode: 'bottom',
|
||||
position: 'bottom',
|
||||
lineStyle: 'solid',
|
||||
fill,
|
||||
value,
|
||||
|
@ -624,7 +668,7 @@ describe('ReferenceLines', () => {
|
|||
it.each(['yAccessorLeft', 'yAccessorRight', 'xAccessor'])(
|
||||
'should let areas in different directions overlap: %s',
|
||||
(layerPrefix) => {
|
||||
const axisMode = getAxisFromId(layerPrefix);
|
||||
const position = getAxisFromId(layerPrefix);
|
||||
const value1 = 1;
|
||||
const value2 = 10;
|
||||
const wrapper = shallow(
|
||||
|
@ -632,13 +676,13 @@ describe('ReferenceLines', () => {
|
|||
{...defaultProps}
|
||||
layers={[
|
||||
createReferenceLine(layerPrefix, 10, {
|
||||
axisMode,
|
||||
position,
|
||||
lineStyle: 'solid',
|
||||
fill: 'above',
|
||||
value: value1,
|
||||
}),
|
||||
createReferenceLine(layerPrefix, 10, {
|
||||
axisMode,
|
||||
position,
|
||||
lineStyle: 'solid',
|
||||
fill: 'below',
|
||||
value: value2,
|
||||
|
@ -654,7 +698,7 @@ describe('ReferenceLines', () => {
|
|||
{
|
||||
coordinates: {
|
||||
...emptyCoords,
|
||||
...(axisMode === 'bottom' ? { x0: value1 } : { y0: value1 }),
|
||||
...(position === 'bottom' ? { x0: value1 } : { y0: value1 }),
|
||||
},
|
||||
details: value1,
|
||||
header: undefined,
|
||||
|
@ -670,7 +714,7 @@ describe('ReferenceLines', () => {
|
|||
{
|
||||
coordinates: {
|
||||
...emptyCoords,
|
||||
...(axisMode === 'bottom' ? { x1: value2 } : { y1: value2 }),
|
||||
...(position === 'bottom' ? { x1: value2 } : { y1: value2 }),
|
||||
},
|
||||
details: value2,
|
||||
header: undefined,
|
||||
|
|
|
@ -12,18 +12,24 @@ import React from 'react';
|
|||
import { Position } from '@elastic/charts';
|
||||
import type { FieldFormat } from '@kbn/field-formats-plugin/common';
|
||||
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 { ReferenceLine } from './reference_line';
|
||||
import { getNextValuesForReferenceLines } from './utils';
|
||||
|
||||
export interface ReferenceLinesProps {
|
||||
layers: CommonXYReferenceLineLayerConfig[];
|
||||
formatters: Record<'left' | 'right' | 'bottom', FieldFormat | undefined>;
|
||||
axesMap: Record<'left' | 'right', boolean>;
|
||||
xAxisFormatter: FieldFormat;
|
||||
axesConfiguration: GroupsConfiguration;
|
||||
isHorizontal: boolean;
|
||||
paddingMap: Partial<Record<Position, number>>;
|
||||
titles?: LayersAccessorsTitles;
|
||||
yAxesMap: AxesMap;
|
||||
}
|
||||
|
||||
export const ReferenceLines = ({ layers, titles = {}, ...rest }: ReferenceLinesProps) => {
|
||||
|
@ -36,13 +42,13 @@ export const ReferenceLines = ({ layers, titles = {}, ...rest }: ReferenceLinesP
|
|||
return (
|
||||
<>
|
||||
{layers.flatMap((layer) => {
|
||||
if (!layer.yConfig) {
|
||||
if (!layer.decorations) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const key = `referenceLine-${layer.layerId}`;
|
||||
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} />;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,13 +11,23 @@ import { Position } from '@elastic/charts';
|
|||
import { euiLightVars } from '@kbn/ui-theme';
|
||||
import { FieldFormat } from '@kbn/field-formats-plugin/common';
|
||||
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 {
|
||||
GroupsConfiguration,
|
||||
LINES_MARKER_SIZE,
|
||||
mapVerticalToHorizontalPlacement,
|
||||
Marker,
|
||||
MarkerBody,
|
||||
getAxisPosition,
|
||||
getOriginalAxisPosition,
|
||||
AxesMap,
|
||||
} from '../../helpers';
|
||||
import { ReferenceLineAnnotationConfig } from './reference_line_annotations';
|
||||
|
||||
|
@ -26,17 +36,18 @@ import { ReferenceLineAnnotationConfig } from './reference_line_annotations';
|
|||
// this function assume the chart is vertical
|
||||
export function getBaseIconPlacement(
|
||||
iconPosition: IconPosition | undefined,
|
||||
axesMap?: Record<string, unknown>,
|
||||
axisMode?: YAxisMode
|
||||
axesMap?: AxesMap,
|
||||
position?: Position
|
||||
) {
|
||||
if (iconPosition === 'auto') {
|
||||
if (axisMode === 'bottom') {
|
||||
if (position === Position.Bottom) {
|
||||
return Position.Top;
|
||||
}
|
||||
if (axesMap) {
|
||||
if (axisMode === 'left') {
|
||||
if (position === Position.Left) {
|
||||
return axesMap.right ? Position.Left : Position.Right;
|
||||
}
|
||||
|
||||
return axesMap.left ? Position.Right : Position.Left;
|
||||
}
|
||||
}
|
||||
|
@ -67,22 +78,26 @@ export const getSharedStyle = (config: ReferenceLineAnnotationConfig) => ({
|
|||
export const getLineAnnotationProps = (
|
||||
config: ReferenceLineAnnotationConfig,
|
||||
labels: { markerLabel?: string; markerBodyLabel?: string },
|
||||
axesMap: Record<'left' | 'right', boolean>,
|
||||
axesMap: AxesMap,
|
||||
paddingMap: Partial<Record<Position, number>>,
|
||||
groupId: 'left' | 'right' | undefined,
|
||||
isHorizontal: boolean
|
||||
) => {
|
||||
// get the position for vertical chart
|
||||
const markerPositionVertical = getBaseIconPlacement(
|
||||
config.iconPosition,
|
||||
axesMap,
|
||||
config.axisMode
|
||||
getOriginalAxisPosition(config.axisGroup?.position ?? Position.Bottom, isHorizontal)
|
||||
);
|
||||
|
||||
// the padding map is built for vertical chart
|
||||
const hasReducedPadding = paddingMap[markerPositionVertical] === LINES_MARKER_SIZE;
|
||||
|
||||
const markerPosition = isHorizontal
|
||||
? mapVerticalToHorizontalPlacement(markerPositionVertical)
|
||||
: markerPositionVertical;
|
||||
|
||||
return {
|
||||
groupId,
|
||||
groupId: config.axisGroup?.groupId || 'bottom',
|
||||
marker: (
|
||||
<Marker
|
||||
config={config}
|
||||
|
@ -94,22 +109,14 @@ export const getLineAnnotationProps = (
|
|||
markerBody: (
|
||||
<MarkerBody
|
||||
label={labels.markerBodyLabel}
|
||||
isHorizontal={
|
||||
(!isHorizontal && config.axisMode === 'bottom') ||
|
||||
(isHorizontal && config.axisMode !== 'bottom')
|
||||
}
|
||||
isHorizontal={markerPosition === Position.Bottom || markerPosition === Position.Top}
|
||||
/>
|
||||
),
|
||||
// rotate the position if required
|
||||
markerPosition: isHorizontal
|
||||
? mapVerticalToHorizontalPlacement(markerPositionVertical)
|
||||
: markerPositionVertical,
|
||||
markerPosition,
|
||||
};
|
||||
};
|
||||
|
||||
export const getGroupId = (axisMode: YAxisMode | undefined) =>
|
||||
axisMode === 'bottom' ? undefined : axisMode === 'right' ? 'right' : 'left';
|
||||
|
||||
export const getBottomRect = (
|
||||
headerLabel: string | undefined,
|
||||
isFillAbove: boolean,
|
||||
|
@ -147,13 +154,16 @@ export const getHorizontalRect = (
|
|||
const sortReferenceLinesByGroup = (referenceLines: ReferenceLineConfig[], group: FillStyle) => {
|
||||
if (group === FillStyles.ABOVE || group === FillStyles.BELOW) {
|
||||
const order = group === FillStyles.ABOVE ? 'asc' : 'desc';
|
||||
return orderBy(referenceLines, ({ yConfig: [{ value }] }) => value, [order]);
|
||||
return orderBy(referenceLines, ({ decorations: [{ value }] }) => value, [order]);
|
||||
}
|
||||
return referenceLines;
|
||||
};
|
||||
|
||||
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[];
|
||||
|
||||
return groups.reduce<Record<FillStyle, Record<string, number | undefined>>>(
|
||||
|
@ -164,8 +174,8 @@ export const getNextValuesForReferenceLines = (referenceLines: ReferenceLineConf
|
|||
(nextValues, referenceLine, index, lines) => {
|
||||
let nextValue: number | undefined;
|
||||
if (index < lines.length - 1) {
|
||||
const [yConfig] = lines[index + 1].yConfig;
|
||||
nextValue = yConfig.value;
|
||||
const [decorationConfig] = lines[index + 1].decorations;
|
||||
nextValue = decorationConfig.value;
|
||||
}
|
||||
|
||||
return { ...nextValues, [referenceLine.layerId]: nextValue };
|
||||
|
@ -183,7 +193,7 @@ export const computeChartMargins = (
|
|||
referenceLinePaddings: Partial<Record<Position, number>>,
|
||||
labelVisibility: Partial<Record<'x' | 'yLeft' | 'yRight', boolean>>,
|
||||
titleVisibility: Partial<Record<'x' | 'yLeft' | 'yRight', boolean>>,
|
||||
axesMap: Record<'left' | 'right', unknown>,
|
||||
axesMap: AxesMap,
|
||||
isHorizontal: boolean
|
||||
) => {
|
||||
const result: Partial<Record<Position, number>> = {};
|
||||
|
@ -210,5 +220,18 @@ export const computeChartMargins = (
|
|||
const placement = isHorizontal ? mapVerticalToHorizontalPlacement('top') : 'top';
|
||||
result[placement] = referenceLinePaddings.top;
|
||||
}
|
||||
|
||||
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',
|
||||
layerType: LayerTypes.DATA,
|
||||
seriesType: 'line',
|
||||
isPercentage: false,
|
||||
isHorizontal: false,
|
||||
isStacked: false,
|
||||
xAccessor: 'c',
|
||||
accessors: ['a', 'b'],
|
||||
showLines: true,
|
||||
|
@ -255,6 +258,9 @@ describe('XYChart component', () => {
|
|||
layerType: LayerTypes.DATA,
|
||||
showLines: true,
|
||||
seriesType: 'line',
|
||||
isHorizontal: false,
|
||||
isStacked: false,
|
||||
isPercentage: false,
|
||||
xAccessor: 'c',
|
||||
accessors: ['a', 'b'],
|
||||
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', () => {
|
||||
const timeLayer: DataLayerConfig = {
|
||||
...defaultTimeLayer,
|
||||
seriesType: 'bar_stacked',
|
||||
seriesType: 'bar',
|
||||
isStacked: true,
|
||||
};
|
||||
const timeLayerArgs = createArgsWithLayers([timeLayer]);
|
||||
|
||||
|
@ -514,11 +521,14 @@ describe('XYChart component', () => {
|
|||
isHistogram: true,
|
||||
},
|
||||
],
|
||||
xExtent: {
|
||||
type: 'axisExtentConfig',
|
||||
mode: 'custom',
|
||||
lowerBound: 123,
|
||||
upperBound: 456,
|
||||
xAxisConfig: {
|
||||
type: 'xAxisConfig',
|
||||
extent: {
|
||||
type: 'axisExtentConfig',
|
||||
mode: 'custom',
|
||||
lowerBound: 123,
|
||||
upperBound: 456,
|
||||
},
|
||||
},
|
||||
}}
|
||||
/>
|
||||
|
@ -541,12 +551,18 @@ describe('XYChart component', () => {
|
|||
{...defaultProps}
|
||||
args={{
|
||||
...args,
|
||||
yLeftExtent: {
|
||||
type: 'axisExtentConfig',
|
||||
mode: 'custom',
|
||||
lowerBound: 123,
|
||||
upperBound: 456,
|
||||
},
|
||||
yAxisConfigs: [
|
||||
{
|
||||
type: 'yAxisConfig',
|
||||
position: 'left',
|
||||
extent: {
|
||||
type: 'axisExtentConfig',
|
||||
mode: 'custom',
|
||||
lowerBound: 123,
|
||||
upperBound: 456,
|
||||
},
|
||||
},
|
||||
],
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
@ -564,10 +580,16 @@ describe('XYChart component', () => {
|
|||
{...defaultProps}
|
||||
args={{
|
||||
...args,
|
||||
yLeftExtent: {
|
||||
type: 'axisExtentConfig',
|
||||
mode: 'dataBounds',
|
||||
},
|
||||
yAxisConfigs: [
|
||||
{
|
||||
type: 'yAxisConfig',
|
||||
position: 'left',
|
||||
extent: {
|
||||
type: 'axisExtentConfig',
|
||||
mode: 'dataBounds',
|
||||
},
|
||||
},
|
||||
],
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
@ -585,10 +607,16 @@ describe('XYChart component', () => {
|
|||
{...defaultProps}
|
||||
args={{
|
||||
...args,
|
||||
yLeftExtent: {
|
||||
type: 'axisExtentConfig',
|
||||
mode: 'dataBounds',
|
||||
},
|
||||
yAxisConfigs: [
|
||||
{
|
||||
type: 'yAxisConfig',
|
||||
position: 'left',
|
||||
extent: {
|
||||
type: 'axisExtentConfig',
|
||||
mode: 'dataBounds',
|
||||
},
|
||||
},
|
||||
],
|
||||
layers: [
|
||||
{
|
||||
...(args.layers[0] as DataLayerConfig),
|
||||
|
@ -612,16 +640,16 @@ describe('XYChart component', () => {
|
|||
{...defaultProps}
|
||||
args={{
|
||||
...args,
|
||||
yLeftExtent: {
|
||||
type: 'axisExtentConfig',
|
||||
mode: 'custom',
|
||||
lowerBound: 123,
|
||||
upperBound: 456,
|
||||
},
|
||||
layers: [
|
||||
yAxisConfigs: [
|
||||
{
|
||||
...(args.layers[0] as DataLayerConfig),
|
||||
seriesType: 'bar',
|
||||
type: 'yAxisConfig',
|
||||
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({
|
||||
fit: false,
|
||||
min: NaN,
|
||||
max: NaN,
|
||||
min: 123,
|
||||
max: 456,
|
||||
includeDataFromIds: [],
|
||||
});
|
||||
});
|
||||
|
@ -901,7 +929,9 @@ describe('XYChart component', () => {
|
|||
{...defaultProps}
|
||||
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',
|
||||
xScaleType: 'linear',
|
||||
isHistogram: true,
|
||||
seriesType: 'bar_stacked',
|
||||
isHorizontal: false,
|
||||
isStacked: true,
|
||||
seriesType: 'bar',
|
||||
isPercentage: false,
|
||||
accessors: ['yAccessorId'],
|
||||
palette: mockPaletteOutput,
|
||||
table: numberHistogramData,
|
||||
|
@ -1091,8 +1124,11 @@ describe('XYChart component', () => {
|
|||
type: 'dataLayer',
|
||||
layerType: LayerTypes.DATA,
|
||||
isHistogram: true,
|
||||
seriesType: 'bar',
|
||||
isStacked: true,
|
||||
isHorizontal: false,
|
||||
isPercentage: false,
|
||||
showLines: true,
|
||||
seriesType: 'bar_stacked',
|
||||
xAccessor: 'b',
|
||||
xScaleType: 'time',
|
||||
splitAccessor: 'b',
|
||||
|
@ -1218,7 +1254,10 @@ describe('XYChart component', () => {
|
|||
xAccessor: 'xAccessorId',
|
||||
xScaleType: 'linear',
|
||||
isHistogram: true,
|
||||
seriesType: 'bar_stacked',
|
||||
isPercentage: false,
|
||||
seriesType: 'bar',
|
||||
isStacked: true,
|
||||
isHorizontal: false,
|
||||
accessors: ['yAccessorId'],
|
||||
palette: mockPaletteOutput,
|
||||
table: numberHistogramData,
|
||||
|
@ -1291,6 +1330,9 @@ describe('XYChart component', () => {
|
|||
type: 'dataLayer',
|
||||
layerType: LayerTypes.DATA,
|
||||
seriesType: 'line',
|
||||
isHorizontal: false,
|
||||
isStacked: false,
|
||||
isPercentage: false,
|
||||
showLines: true,
|
||||
xAccessor: 'd',
|
||||
accessors: ['a', 'b'],
|
||||
|
@ -1351,6 +1393,9 @@ describe('XYChart component', () => {
|
|||
layerType: LayerTypes.DATA,
|
||||
showLines: true,
|
||||
seriesType: 'line',
|
||||
isHorizontal: false,
|
||||
isStacked: false,
|
||||
isPercentage: false,
|
||||
xAccessor: 'd',
|
||||
accessors: ['a', 'b'],
|
||||
columnToLabel: '{"a": "Label A", "b": "Label B", "d": "Label D"}',
|
||||
|
@ -1382,6 +1427,9 @@ describe('XYChart component', () => {
|
|||
layerType: LayerTypes.DATA,
|
||||
showLines: true,
|
||||
seriesType: 'line',
|
||||
isHorizontal: false,
|
||||
isStacked: false,
|
||||
isPercentage: false,
|
||||
xAccessor: 'd',
|
||||
accessors: ['a', 'b'],
|
||||
columnToLabel: '{"a": "Label A", "b": "Label B", "d": "Label D"}',
|
||||
|
@ -1421,7 +1469,7 @@ describe('XYChart component', () => {
|
|||
{...defaultProps}
|
||||
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}
|
||||
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,
|
||||
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),
|
||||
xAccessor: undefined,
|
||||
splitAccessor: 'e',
|
||||
seriesType: 'bar_stacked',
|
||||
seriesType: 'bar',
|
||||
isStacked: true,
|
||||
},
|
||||
],
|
||||
}}
|
||||
|
@ -1574,7 +1628,8 @@ describe('XYChart component', () => {
|
|||
layers: [
|
||||
{
|
||||
...(args.layers[0] as DataLayerConfig),
|
||||
seriesType: 'bar_stacked',
|
||||
seriesType: 'bar',
|
||||
isStacked: true,
|
||||
isHistogram: true,
|
||||
},
|
||||
],
|
||||
|
@ -1630,21 +1685,33 @@ describe('XYChart component', () => {
|
|||
{
|
||||
...layer,
|
||||
accessors: ['a', 'b'],
|
||||
yConfig: [
|
||||
decorations: [
|
||||
{
|
||||
type: 'yConfig',
|
||||
type: 'dataDecorationConfig',
|
||||
forAccessor: 'a',
|
||||
axisMode: 'left',
|
||||
axisId: '1',
|
||||
},
|
||||
{
|
||||
type: 'yConfig',
|
||||
type: 'dataDecorationConfig',
|
||||
forAccessor: 'b',
|
||||
axisMode: 'right',
|
||||
axisId: '2',
|
||||
},
|
||||
],
|
||||
table: dataWithoutFormats,
|
||||
},
|
||||
],
|
||||
yAxisConfigs: [
|
||||
{
|
||||
type: 'yAxisConfig',
|
||||
id: '1',
|
||||
position: 'left',
|
||||
},
|
||||
{
|
||||
type: 'yAxisConfig',
|
||||
id: '2',
|
||||
position: 'right',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const component = getRenderedComponent(newArgs);
|
||||
|
@ -1684,21 +1751,28 @@ describe('XYChart component', () => {
|
|||
{
|
||||
...layer,
|
||||
accessors: ['c', 'd'],
|
||||
yConfig: [
|
||||
decorations: [
|
||||
{
|
||||
type: 'yConfig',
|
||||
type: 'dataDecorationConfig',
|
||||
forAccessor: 'c',
|
||||
axisMode: 'left',
|
||||
axisId: '1',
|
||||
},
|
||||
{
|
||||
type: 'yConfig',
|
||||
type: 'dataDecorationConfig',
|
||||
forAccessor: 'd',
|
||||
axisMode: 'left',
|
||||
axisId: '1',
|
||||
},
|
||||
],
|
||||
table: dataWithoutFormats,
|
||||
},
|
||||
],
|
||||
yAxisConfigs: [
|
||||
{
|
||||
type: 'yAxisConfig',
|
||||
id: '1',
|
||||
position: 'left',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const component = getRenderedComponent(newArgs);
|
||||
|
@ -1720,14 +1794,14 @@ describe('XYChart component', () => {
|
|||
type: 'extendedDataLayer',
|
||||
accessors: ['a', 'b'],
|
||||
splitAccessor: undefined,
|
||||
yConfig: [
|
||||
decorations: [
|
||||
{
|
||||
type: 'yConfig',
|
||||
type: 'dataDecorationConfig',
|
||||
forAccessor: 'a',
|
||||
color: '#550000',
|
||||
},
|
||||
{
|
||||
type: 'yConfig',
|
||||
type: 'dataDecorationConfig',
|
||||
forAccessor: 'b',
|
||||
color: '#FFFF00',
|
||||
},
|
||||
|
@ -1739,9 +1813,9 @@ describe('XYChart component', () => {
|
|||
type: 'extendedDataLayer',
|
||||
accessors: ['c'],
|
||||
splitAccessor: undefined,
|
||||
yConfig: [
|
||||
decorations: [
|
||||
{
|
||||
type: 'yConfig',
|
||||
type: 'dataDecorationConfig',
|
||||
forAccessor: 'c',
|
||||
color: '#FEECDF',
|
||||
},
|
||||
|
@ -1772,16 +1846,16 @@ describe('XYChart component', () => {
|
|||
})
|
||||
).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 = {
|
||||
...args,
|
||||
layers: [
|
||||
{
|
||||
...layer,
|
||||
accessors: ['a'],
|
||||
yConfig: [
|
||||
decorations: [
|
||||
{
|
||||
type: 'yConfig',
|
||||
type: 'dataDecorationConfig',
|
||||
forAccessor: 'a',
|
||||
color: '#550000',
|
||||
},
|
||||
|
@ -2067,7 +2141,14 @@ describe('XYChart component', () => {
|
|||
{...defaultProps}
|
||||
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', () => {
|
||||
const { args } = sampleArgs();
|
||||
|
||||
args.tickLabelsVisibilitySettings = {
|
||||
x: false,
|
||||
yLeft: true,
|
||||
yRight: true,
|
||||
type: 'tickLabelsConfig',
|
||||
args.yAxisConfigs = [
|
||||
{
|
||||
type: 'yAxisConfig',
|
||||
position: 'left',
|
||||
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 }} />);
|
||||
|
@ -2136,12 +2230,18 @@ describe('XYChart component', () => {
|
|||
test('it should set the tickLabel visibility on the y axis if the tick labels is hidden', () => {
|
||||
const { args } = sampleArgs();
|
||||
|
||||
args.tickLabelsVisibilitySettings = {
|
||||
x: true,
|
||||
yLeft: false,
|
||||
yRight: false,
|
||||
type: 'tickLabelsConfig',
|
||||
};
|
||||
args.yAxisConfigs = [
|
||||
{
|
||||
type: 'yAxisConfig',
|
||||
position: 'left',
|
||||
showLabels: false,
|
||||
},
|
||||
{
|
||||
type: 'yAxisConfig',
|
||||
position: 'right',
|
||||
showLabels: false,
|
||||
},
|
||||
];
|
||||
|
||||
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', () => {
|
||||
const { args } = sampleArgs();
|
||||
|
||||
args.tickLabelsVisibilitySettings = {
|
||||
x: true,
|
||||
yLeft: true,
|
||||
yRight: true,
|
||||
type: 'tickLabelsConfig',
|
||||
args.yAxisConfigs = [
|
||||
{
|
||||
type: 'yAxisConfig',
|
||||
position: 'left',
|
||||
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 }} />);
|
||||
|
@ -2178,11 +2291,25 @@ describe('XYChart component', () => {
|
|||
test('it should set the tickLabel orientation on the x axis', () => {
|
||||
const { args } = sampleArgs();
|
||||
|
||||
args.labelsOrientation = {
|
||||
x: -45,
|
||||
yLeft: 0,
|
||||
yRight: -90,
|
||||
type: 'labelsOrientationConfig',
|
||||
args.yAxisConfigs = [
|
||||
{
|
||||
type: 'yAxisConfig',
|
||||
position: 'left',
|
||||
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 }} />);
|
||||
|
@ -2199,11 +2326,24 @@ describe('XYChart component', () => {
|
|||
test('it should set the tickLabel visibility on the y axis if the tick labels is shown', () => {
|
||||
const { args } = sampleArgs();
|
||||
|
||||
args.tickLabelsVisibilitySettings = {
|
||||
x: false,
|
||||
yLeft: true,
|
||||
yRight: true,
|
||||
type: 'tickLabelsConfig',
|
||||
args.yAxisConfigs = [
|
||||
{
|
||||
type: 'yAxisConfig',
|
||||
position: 'left',
|
||||
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 }} />);
|
||||
|
@ -2220,11 +2360,25 @@ describe('XYChart component', () => {
|
|||
test('it should set the tickLabel orientation on the y axis', () => {
|
||||
const { args } = sampleArgs();
|
||||
|
||||
args.labelsOrientation = {
|
||||
x: -45,
|
||||
yLeft: -90,
|
||||
yRight: -90,
|
||||
type: 'labelsOrientationConfig',
|
||||
args.yAxisConfigs = [
|
||||
{
|
||||
type: 'yAxisConfig',
|
||||
position: 'left',
|
||||
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 }} />);
|
||||
|
@ -2266,43 +2420,47 @@ describe('XYChart component', () => {
|
|||
};
|
||||
|
||||
const args: XYProps = {
|
||||
xTitle: '',
|
||||
yTitle: '',
|
||||
yRightTitle: '',
|
||||
yLeftScale: 'linear',
|
||||
yRightScale: 'linear',
|
||||
showTooltip: true,
|
||||
legend: { type: 'legendConfig', isVisible: false, position: Position.Top },
|
||||
valueLabels: 'hide',
|
||||
tickLabelsVisibilitySettings: {
|
||||
type: 'tickLabelsConfig',
|
||||
x: true,
|
||||
yLeft: true,
|
||||
yRight: true,
|
||||
},
|
||||
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',
|
||||
yAxisConfigs: [
|
||||
{
|
||||
type: 'yAxisConfig',
|
||||
position: 'left',
|
||||
labelsOrientation: 0,
|
||||
showGridLines: false,
|
||||
showLabels: true,
|
||||
title: '',
|
||||
extent: {
|
||||
mode: 'full',
|
||||
type: 'axisExtentConfig',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'yAxisConfig',
|
||||
position: 'right',
|
||||
labelsOrientation: 0,
|
||||
showGridLines: false,
|
||||
showLabels: true,
|
||||
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',
|
||||
},
|
||||
},
|
||||
markSizeRatio: 1,
|
||||
layers: [
|
||||
|
@ -2311,6 +2469,8 @@ describe('XYChart component', () => {
|
|||
type: 'dataLayer',
|
||||
layerType: LayerTypes.DATA,
|
||||
seriesType: 'line',
|
||||
isStacked: false,
|
||||
isHorizontal: false,
|
||||
showLines: true,
|
||||
xAccessor: 'a',
|
||||
accessors: ['c'],
|
||||
|
@ -2318,6 +2478,7 @@ describe('XYChart component', () => {
|
|||
columnToLabel: '',
|
||||
xScaleType: 'ordinal',
|
||||
isHistogram: false,
|
||||
isPercentage: false,
|
||||
palette: mockPaletteOutput,
|
||||
table: data1,
|
||||
},
|
||||
|
@ -2333,6 +2494,9 @@ describe('XYChart component', () => {
|
|||
columnToLabel: '',
|
||||
xScaleType: 'ordinal',
|
||||
isHistogram: false,
|
||||
isStacked: false,
|
||||
isHorizontal: false,
|
||||
isPercentage: false,
|
||||
palette: mockPaletteOutput,
|
||||
table: data2,
|
||||
},
|
||||
|
@ -2363,45 +2527,51 @@ describe('XYChart component', () => {
|
|||
};
|
||||
|
||||
const args: XYProps = {
|
||||
xTitle: '',
|
||||
yTitle: '',
|
||||
yRightTitle: '',
|
||||
legend: { type: 'legendConfig', isVisible: false, position: Position.Top },
|
||||
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,
|
||||
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,
|
||||
yLeftScale: 'linear',
|
||||
yRightScale: 'linear',
|
||||
layers: [
|
||||
{
|
||||
layerId: 'first',
|
||||
|
@ -2415,6 +2585,9 @@ describe('XYChart component', () => {
|
|||
columnToLabel: '',
|
||||
xScaleType: 'ordinal',
|
||||
isHistogram: false,
|
||||
isStacked: false,
|
||||
isHorizontal: false,
|
||||
isPercentage: false,
|
||||
palette: mockPaletteOutput,
|
||||
table: data,
|
||||
},
|
||||
|
@ -2443,45 +2616,51 @@ describe('XYChart component', () => {
|
|||
};
|
||||
|
||||
const args: XYProps = {
|
||||
xTitle: '',
|
||||
yTitle: '',
|
||||
yRightTitle: '',
|
||||
showTooltip: true,
|
||||
legend: { type: 'legendConfig', isVisible: true, position: Position.Top },
|
||||
valueLabels: 'hide',
|
||||
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',
|
||||
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',
|
||||
showLabels: true,
|
||||
showGridLines: true,
|
||||
labelsOrientation: 0,
|
||||
title: '',
|
||||
position: 'bottom',
|
||||
extent: {
|
||||
mode: 'dataBounds',
|
||||
type: 'axisExtentConfig',
|
||||
},
|
||||
},
|
||||
markSizeRatio: 1,
|
||||
yLeftScale: 'linear',
|
||||
yRightScale: 'linear',
|
||||
layers: [
|
||||
{
|
||||
layerId: 'first',
|
||||
|
@ -2495,6 +2674,9 @@ describe('XYChart component', () => {
|
|||
columnToLabel: '',
|
||||
xScaleType: 'ordinal',
|
||||
isHistogram: false,
|
||||
isStacked: false,
|
||||
isHorizontal: false,
|
||||
isPercentage: false,
|
||||
palette: mockPaletteOutput,
|
||||
table: data,
|
||||
},
|
||||
|
@ -2631,7 +2813,7 @@ describe('XYChart component', () => {
|
|||
{ ...sampleLayer, accessors: ['a'], table: data },
|
||||
{ ...sampleLayer, seriesType: 'bar', 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(
|
||||
|
@ -2661,7 +2843,13 @@ describe('XYChart component', () => {
|
|||
test('it should apply the xTitle if is specified', () => {
|
||||
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 }} />);
|
||||
|
||||
|
@ -2671,11 +2859,26 @@ describe('XYChart component', () => {
|
|||
test('it should hide the X axis title if the corresponding switch is off', () => {
|
||||
const { args } = sampleArgs();
|
||||
|
||||
args.axisTitlesVisibilitySettings = {
|
||||
x: false,
|
||||
yLeft: true,
|
||||
yRight: true,
|
||||
type: 'axisTitlesVisibilityConfig',
|
||||
args.yAxisConfigs = [
|
||||
{
|
||||
type: 'yAxisConfig',
|
||||
position: 'left',
|
||||
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 }} />);
|
||||
|
@ -2692,11 +2895,26 @@ describe('XYChart component', () => {
|
|||
test('it should show the X axis gridlines if the setting is on', () => {
|
||||
const { args } = sampleArgs();
|
||||
|
||||
args.gridlinesVisibilitySettings = {
|
||||
x: true,
|
||||
yLeft: false,
|
||||
yRight: false,
|
||||
type: 'gridlinesConfig',
|
||||
args.yAxisConfigs = [
|
||||
{
|
||||
type: 'yAxisConfig',
|
||||
position: 'left',
|
||||
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 }} />);
|
||||
|
@ -2741,10 +2959,13 @@ describe('XYChart component', () => {
|
|||
layerType: LayerTypes.DATA,
|
||||
showLines: true,
|
||||
seriesType: 'line',
|
||||
isStacked: false,
|
||||
isHorizontal: false,
|
||||
xAccessor: 'c',
|
||||
accessors: ['a', 'b'],
|
||||
xScaleType: 'ordinal',
|
||||
isHistogram: false,
|
||||
isPercentage: false,
|
||||
palette: mockPaletteOutput,
|
||||
table: data,
|
||||
};
|
||||
|
|
|
@ -47,20 +47,21 @@ import type { FilterEvent, BrushEvent, FormatFactory } from '../types';
|
|||
import { isTimeChart } from '../../common/helpers';
|
||||
import type {
|
||||
CommonXYDataLayerConfig,
|
||||
ExtendedYConfig,
|
||||
ReferenceLineYConfig,
|
||||
SeriesType,
|
||||
ReferenceLineDecorationConfig,
|
||||
ExtendedReferenceLineDecorationConfig,
|
||||
XYChartProps,
|
||||
AxisExtentConfigResult,
|
||||
} from '../../common/types';
|
||||
import {
|
||||
isHorizontalChart,
|
||||
getAnnotationsLayers,
|
||||
getDataLayers,
|
||||
Series,
|
||||
AxisConfiguration,
|
||||
getAxisPosition,
|
||||
getFormattedTablesByLayers,
|
||||
getLayersFormats,
|
||||
getLayersTitles,
|
||||
isReferenceLineYConfig,
|
||||
isReferenceLineDecorationConfig,
|
||||
getFilteredLayers,
|
||||
getReferenceLayers,
|
||||
isDataLayer,
|
||||
|
@ -68,10 +69,16 @@ import {
|
|||
GroupsConfiguration,
|
||||
getLinesCausedPaddings,
|
||||
validateExtent,
|
||||
Series,
|
||||
getOriginalAxisPosition,
|
||||
} from '../helpers';
|
||||
import { getXDomain, XyEndzones } from './x_domain';
|
||||
import { getLegendAction } from './legend_action';
|
||||
import { ReferenceLines, computeChartMargins } from './reference_lines';
|
||||
import {
|
||||
ReferenceLines,
|
||||
computeChartMargins,
|
||||
getAxisGroupForReferenceLine,
|
||||
} from './reference_lines';
|
||||
import { visualizationDefinitions } from '../definitions';
|
||||
import { CommonXYLayerConfig } from '../../common/types';
|
||||
import { SplitChart } from './split_chart';
|
||||
|
@ -138,8 +145,16 @@ function getValueLabelsStyling(isHorizontal: boolean): {
|
|||
};
|
||||
}
|
||||
|
||||
function getIconForSeriesType(seriesType: SeriesType): IconType {
|
||||
return visualizationDefinitions.find((c) => c.id === seriesType)!.icon || 'empty';
|
||||
function getIconForSeriesType(layer: CommonXYDataLayerConfig): IconType {
|
||||
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);
|
||||
|
@ -166,15 +181,11 @@ export function XYChart({
|
|||
fittingFunction,
|
||||
endValue,
|
||||
emphasizeFitting,
|
||||
gridlinesVisibilitySettings,
|
||||
valueLabels,
|
||||
hideEndzones,
|
||||
xExtent,
|
||||
yLeftExtent,
|
||||
yRightExtent,
|
||||
valuesInLegend,
|
||||
yLeftScale,
|
||||
yRightScale,
|
||||
yAxisConfigs,
|
||||
xAxisConfig,
|
||||
splitColumnAccessor,
|
||||
splitRowAccessor,
|
||||
} = args;
|
||||
|
@ -204,9 +215,7 @@ export function XYChart({
|
|||
);
|
||||
|
||||
if (dataLayers.length === 0) {
|
||||
const icon: IconType = getIconForSeriesType(
|
||||
getDataLayers(layers)?.[0]?.seriesType || SeriesTypes.BAR
|
||||
);
|
||||
const icon: IconType = getIconForSeriesType(getDataLayers(layers)?.[0]);
|
||||
return <EmptyPlaceholder className="xyChart__empty" icon={icon} />;
|
||||
}
|
||||
|
||||
|
@ -236,37 +245,35 @@ export function XYChart({
|
|||
shouldRotate,
|
||||
formatFactory,
|
||||
fieldFormats,
|
||||
yLeftScale,
|
||||
yRightScale
|
||||
yAxisConfigs
|
||||
);
|
||||
|
||||
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 = {
|
||||
left: yAxesConfiguration.find(({ groupId }) => groupId === 'left'),
|
||||
right: yAxesConfiguration.find(({ groupId }) => groupId === 'right'),
|
||||
left: yAxesConfiguration.find(
|
||||
({ position }) => position === getAxisPosition(Position.Left, shouldRotate)
|
||||
),
|
||||
right: yAxesConfiguration.find(
|
||||
({ position }) => position === getAxisPosition(Position.Right, shouldRotate)
|
||||
),
|
||||
};
|
||||
|
||||
const titles = getLayersTitles(
|
||||
dataLayers,
|
||||
{ splitColumnAccessor, splitRowAccessor },
|
||||
{ xTitle: args.xTitle, yTitle: args.yTitle, yRightTitle: args.yRightTitle },
|
||||
{ xTitle },
|
||||
yAxesConfiguration
|
||||
);
|
||||
|
||||
const axisTitlesVisibilitySettings = args.axisTitlesVisibilitySettings || {
|
||||
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 filteredBarLayers = dataLayers.filter(({ seriesType }) => seriesType === SeriesTypes.BAR);
|
||||
|
||||
const chartHasMoreThanOneBarSeries =
|
||||
filteredBarLayers.length > 1 ||
|
||||
|
@ -285,9 +292,18 @@ export function XYChart({
|
|||
minInterval,
|
||||
isTimeViz,
|
||||
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[]) => {
|
||||
return axisSeries
|
||||
.map(({ layer, accessor }) => titles?.[layer]?.yTitles?.[accessor])
|
||||
|
@ -312,45 +328,48 @@ export function XYChart({
|
|||
const rangeAnnotations = getRangeAnnotations(annotationsLayers);
|
||||
|
||||
const visualConfigs = [
|
||||
...referenceLineLayers.flatMap<ExtendedYConfig | ReferenceLineYConfig | undefined>(
|
||||
({ yConfig }) => yConfig
|
||||
),
|
||||
...referenceLineLayers
|
||||
.flatMap<ReferenceLineDecorationConfig | ExtendedReferenceLineDecorationConfig | undefined>(
|
||||
({ decorations }) => decorations
|
||||
)
|
||||
.map((config) => ({
|
||||
...config,
|
||||
position: config
|
||||
? getAxisGroupForReferenceLine(axesConfiguration, config, shouldRotate)?.position ??
|
||||
Position.Left
|
||||
: Position.Bottom,
|
||||
})),
|
||||
...groupedLineAnnotations,
|
||||
].filter(Boolean);
|
||||
|
||||
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 tickVisible =
|
||||
groupId === 'right'
|
||||
? tickLabelsVisibilitySettings?.yRight
|
||||
: tickLabelsVisibilitySettings?.yLeft;
|
||||
const getYAxesStyle = (axis: AxisConfiguration) => {
|
||||
const tickVisible = axis.showLabels;
|
||||
const position = getOriginalAxisPosition(axis.position, shouldRotate);
|
||||
|
||||
const style = {
|
||||
tickLabel: {
|
||||
fill: axis.labelColor,
|
||||
visible: tickVisible,
|
||||
rotation:
|
||||
groupId === 'right'
|
||||
? args.labelsOrientation?.yRight || 0
|
||||
: args.labelsOrientation?.yLeft || 0,
|
||||
rotation: axis.labelsOrientation,
|
||||
padding:
|
||||
linesPaddings[groupId] != null
|
||||
linesPaddings[position] != null
|
||||
? {
|
||||
inner: linesPaddings[groupId],
|
||||
inner: linesPaddings[position],
|
||||
}
|
||||
: undefined,
|
||||
},
|
||||
axisTitle: {
|
||||
visible:
|
||||
groupId === 'right'
|
||||
? axisTitlesVisibilitySettings?.yRight
|
||||
: axisTitlesVisibilitySettings?.yLeft,
|
||||
visible: axis.showTitle,
|
||||
// if labels are not visible add the padding to the title
|
||||
padding:
|
||||
!tickVisible && linesPaddings[groupId] != null
|
||||
!tickVisible && linesPaddings[position] != null
|
||||
? {
|
||||
inner: linesPaddings[groupId],
|
||||
inner: linesPaddings[position],
|
||||
}
|
||||
: undefined,
|
||||
},
|
||||
|
@ -359,7 +378,10 @@ export function XYChart({
|
|||
};
|
||||
|
||||
const getYAxisDomain = (axis: GroupsConfiguration[number]) => {
|
||||
const extent = axis.groupId === 'left' ? yLeftExtent : yRightExtent;
|
||||
const extent: AxisExtentConfigResult = axis.extent || {
|
||||
type: 'axisExtentConfig',
|
||||
mode: 'full',
|
||||
};
|
||||
const hasBarOrArea = Boolean(
|
||||
axis.series.some((series) => {
|
||||
const layer = layersById[series.layer];
|
||||
|
@ -367,11 +389,12 @@ export function XYChart({
|
|||
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 padding = axis.boundsMargin || undefined;
|
||||
|
||||
let min: number = NaN;
|
||||
let max: number = NaN;
|
||||
|
@ -387,22 +410,31 @@ export function XYChart({
|
|||
fit,
|
||||
min,
|
||||
max,
|
||||
padding,
|
||||
includeDataFromIds: referenceLineLayers
|
||||
.flatMap((l) =>
|
||||
l.yConfig ? l.yConfig.map((yConfig) => ({ layerId: l.layerId, yConfig })) : []
|
||||
.flatMap(
|
||||
(l) => l.decorations?.map((decoration) => ({ layerId: l.layerId, decoration })) || []
|
||||
)
|
||||
.filter(({ yConfig }) => yConfig.axisMode === axis.groupId)
|
||||
.map(({ layerId, yConfig }) =>
|
||||
isReferenceLineYConfig(yConfig)
|
||||
? `${layerId}-${yConfig.value}-${yConfig.fill !== 'none' ? 'rect' : 'line'}`
|
||||
: `${layerId}-${yConfig.forAccessor}-${yConfig.fill !== 'none' ? 'rect' : 'line'}`
|
||||
.filter(({ decoration }) => {
|
||||
if (decoration.axisId) {
|
||||
return axis.groupId.includes(decoration.axisId);
|
||||
}
|
||||
|
||||
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 =
|
||||
// No stacked bar charts
|
||||
dataLayers.every((layer) => !layer.seriesType.includes('stacked')) &&
|
||||
dataLayers.every((layer) => !layer.isStacked) &&
|
||||
// No histogram charts
|
||||
!isHistogramViz;
|
||||
|
||||
|
@ -516,18 +548,17 @@ export function XYChart({
|
|||
};
|
||||
|
||||
const isHistogramModeEnabled = dataLayers.some(
|
||||
({ isHistogram, seriesType }) =>
|
||||
isHistogram &&
|
||||
(seriesType.includes('stacked') ||
|
||||
!seriesType.includes('bar') ||
|
||||
!chartHasMoreThanOneBarSeries)
|
||||
({ isHistogram, seriesType, isStacked }) =>
|
||||
isHistogram && (isStacked || seriesType !== SeriesTypes.BAR || !chartHasMoreThanOneBarSeries)
|
||||
);
|
||||
|
||||
const shouldUseNewTimeAxis =
|
||||
isTimeViz && isHistogramModeEnabled && !useLegacyTimeAxis && !shouldRotate;
|
||||
|
||||
const defaultXAxisPosition = shouldRotate ? Position.Left : Position.Bottom;
|
||||
|
||||
const gridLineStyle = {
|
||||
visible: gridlinesVisibilitySettings?.x,
|
||||
visible: xAxisConfig?.showGridLines,
|
||||
strokeWidth: 1,
|
||||
};
|
||||
const xAxisStyle: RecursivePartial<AxisStyle> = shouldUseNewTimeAxis
|
||||
|
@ -535,26 +566,28 @@ export function XYChart({
|
|||
...MULTILAYER_TIME_AXIS_STYLE,
|
||||
tickLabel: {
|
||||
...MULTILAYER_TIME_AXIS_STYLE.tickLabel,
|
||||
visible: Boolean(tickLabelsVisibilitySettings?.x),
|
||||
visible: Boolean(xAxisConfig?.showLabels),
|
||||
fill: xAxisConfig?.labelColor,
|
||||
},
|
||||
tickLine: {
|
||||
...MULTILAYER_TIME_AXIS_STYLE.tickLine,
|
||||
visible: Boolean(tickLabelsVisibilitySettings?.x),
|
||||
visible: Boolean(xAxisConfig?.showLabels),
|
||||
},
|
||||
axisTitle: {
|
||||
visible: axisTitlesVisibilitySettings.x,
|
||||
visible: xAxisConfig?.showTitle,
|
||||
},
|
||||
}
|
||||
: {
|
||||
tickLabel: {
|
||||
visible: tickLabelsVisibilitySettings?.x,
|
||||
rotation: labelsOrientation?.x,
|
||||
visible: xAxisConfig?.showLabels,
|
||||
rotation: xAxisConfig?.labelsOrientation,
|
||||
padding: linesPaddings.bottom != null ? { inner: linesPaddings.bottom } : undefined,
|
||||
fill: xAxisConfig?.labelColor,
|
||||
},
|
||||
axisTitle: {
|
||||
visible: axisTitlesVisibilitySettings.x,
|
||||
visible: xAxisConfig?.showTitle,
|
||||
padding:
|
||||
!tickLabelsVisibilitySettings?.x && linesPaddings.bottom != null
|
||||
!xAxisConfig?.showLabels && linesPaddings.bottom != null
|
||||
? { inner: linesPaddings.bottom }
|
||||
: undefined,
|
||||
},
|
||||
|
@ -610,8 +643,8 @@ export function XYChart({
|
|||
...chartTheme.chartPaddings,
|
||||
...computeChartMargins(
|
||||
linesPaddings,
|
||||
tickLabelsVisibilitySettings,
|
||||
axisTitlesVisibilitySettings,
|
||||
{ ...tickLabelsVisibilitySettings, x: xAxisConfig?.showLabels },
|
||||
{ ...axisTitlesVisibilitySettings, x: xAxisConfig?.showTitle },
|
||||
yAxesMap,
|
||||
shouldRotate
|
||||
),
|
||||
|
@ -678,12 +711,24 @@ export function XYChart({
|
|||
|
||||
<Axis
|
||||
id="x"
|
||||
position={shouldRotate ? Position.Left : Position.Bottom}
|
||||
position={
|
||||
xAxisConfig?.position
|
||||
? getOriginalAxisPosition(xAxisConfig?.position, shouldRotate)
|
||||
: defaultXAxisPosition
|
||||
}
|
||||
title={xTitle}
|
||||
gridLine={gridLineStyle}
|
||||
hide={dataLayers[0]?.hide || !dataLayers[0]?.xAccessor}
|
||||
tickFormat={(d) => safeXAccessorLabelRenderer(d)}
|
||||
hide={xAxisConfig?.hide || dataLayers[0]?.hide || !dataLayers[0]?.xAccessor}
|
||||
tickFormat={(d) => {
|
||||
let value = safeXAccessorLabelRenderer(d) || '';
|
||||
if (xAxisConfig?.truncate && value.length > xAxisConfig.truncate) {
|
||||
value = `${value.slice(0, xAxisConfig.truncate)}...`;
|
||||
}
|
||||
return value;
|
||||
}}
|
||||
style={xAxisStyle}
|
||||
showOverlappingLabels={xAxisConfig?.showOverlappingLabels}
|
||||
showDuplicatedTicks={xAxisConfig?.showDuplicates}
|
||||
timeAxisLayerCount={shouldUseNewTimeAxis ? 3 : 0}
|
||||
/>
|
||||
{isSplitChart && splitTable && (
|
||||
|
@ -704,15 +749,20 @@ export function XYChart({
|
|||
position={axis.position}
|
||||
title={getYAxesTitles(axis.series)}
|
||||
gridLine={{
|
||||
visible:
|
||||
axis.groupId === 'right'
|
||||
? gridlinesVisibilitySettings?.yRight
|
||||
: gridlinesVisibilitySettings?.yLeft,
|
||||
visible: axis.showGridLines,
|
||||
}}
|
||||
hide={dataLayers[0]?.hide}
|
||||
tickFormat={(d) => axis.formatter?.convert(d) || ''}
|
||||
style={getYAxesStyle(axis.groupId)}
|
||||
hide={axis.hide || dataLayers[0]?.hide}
|
||||
tickFormat={(d) => {
|
||||
let value = axis.formatter?.convert(d) || '';
|
||||
if (axis.truncate && value.length > axis.truncate) {
|
||||
value = `${value.slice(0, axis.truncate)}...`;
|
||||
}
|
||||
return value;
|
||||
}}
|
||||
style={getYAxesStyle(axis)}
|
||||
domain={getYAxisDomain(axis)}
|
||||
showOverlappingLabels={axis.showOverlappingLabels}
|
||||
showDuplicatedTicks={axis.showDuplicates}
|
||||
ticks={5}
|
||||
/>
|
||||
);
|
||||
|
@ -726,9 +776,9 @@ export function XYChart({
|
|||
histogramMode={dataLayers.every(
|
||||
(layer) =>
|
||||
layer.isHistogram &&
|
||||
(layer.seriesType.includes('stacked') || !layer.splitAccessor) &&
|
||||
(layer.seriesType.includes('stacked') ||
|
||||
!layer.seriesType.includes('bar') ||
|
||||
(layer.isStacked || !layer.splitAccessor) &&
|
||||
(layer.isStacked ||
|
||||
layer.seriesType !== SeriesTypes.BAR ||
|
||||
!chartHasMoreThanOneBarSeries)
|
||||
)}
|
||||
/>
|
||||
|
@ -758,18 +808,12 @@ export function XYChart({
|
|||
{referenceLineLayers.length ? (
|
||||
<ReferenceLines
|
||||
layers={referenceLineLayers}
|
||||
formatters={{
|
||||
left: yAxesMap.left?.formatter,
|
||||
right: yAxesMap.right?.formatter,
|
||||
bottom: xAxisFormatter,
|
||||
}}
|
||||
axesMap={{
|
||||
left: Boolean(yAxesMap.left),
|
||||
right: Boolean(yAxesMap.right),
|
||||
}}
|
||||
xAxisFormatter={xAxisFormatter}
|
||||
axesConfiguration={axesConfiguration}
|
||||
isHorizontal={shouldRotate}
|
||||
paddingMap={linesPaddings}
|
||||
titles={titles}
|
||||
yAxesMap={yAxesMap}
|
||||
/>
|
||||
) : null}
|
||||
{rangeAnnotations.length || groupedLineAnnotations.length ? (
|
||||
|
|
|
@ -22,13 +22,13 @@ import {
|
|||
|
||||
export const visualizationDefinitions = [
|
||||
{ id: SeriesTypes.BAR, icon: BarIcon },
|
||||
{ id: SeriesTypes.BAR_STACKED, icon: BarStackedIcon },
|
||||
{ id: SeriesTypes.BAR_HORIZONTAL, icon: BarHorizontalIcon },
|
||||
{ id: SeriesTypes.BAR_PERCENTAGE_STACKED, icon: BarPercentageIcon },
|
||||
{ id: SeriesTypes.BAR_HORIZONTAL_STACKED, icon: BarHorizontalStackedIcon },
|
||||
{ id: SeriesTypes.BAR_HORIZONTAL_PERCENTAGE_STACKED, icon: BarHorizontalPercentageIcon },
|
||||
{ id: `${SeriesTypes.BAR}_stacked`, icon: BarStackedIcon },
|
||||
{ id: `${SeriesTypes.BAR}_horizontal`, icon: BarHorizontalIcon },
|
||||
{ id: `${SeriesTypes.BAR}_percentage_stacked`, icon: BarPercentageIcon },
|
||||
{ id: `${SeriesTypes.BAR}_horizontal_stacked`, icon: BarHorizontalStackedIcon },
|
||||
{ id: `${SeriesTypes.BAR}_horizontal_percentage_stacked`, icon: BarHorizontalPercentageIcon },
|
||||
{ id: SeriesTypes.LINE, icon: LineIcon },
|
||||
{ id: SeriesTypes.AREA, icon: AreaIcon },
|
||||
{ id: SeriesTypes.AREA_STACKED, icon: AreaStackedIcon },
|
||||
{ id: SeriesTypes.AREA_PERCENTAGE_STACKED, icon: AreaPercentageIcon },
|
||||
{ id: `${SeriesTypes.AREA}_stacked`, icon: AreaStackedIcon },
|
||||
{ id: `${SeriesTypes.AREA}_percentage_stacked`, icon: AreaPercentageIcon },
|
||||
];
|
||||
|
|
|
@ -11,31 +11,34 @@ import { EuiFlexGroup, EuiIcon, EuiIconProps, EuiText } from '@elastic/eui';
|
|||
import classnames from 'classnames';
|
||||
import type {
|
||||
IconPosition,
|
||||
YAxisMode,
|
||||
ExtendedYConfig,
|
||||
ReferenceLineDecorationConfig,
|
||||
CollectiveConfig,
|
||||
} from '../../common/types';
|
||||
import { getBaseIconPlacement } from '../components';
|
||||
import { hasIcon, iconSet } from './icon';
|
||||
import { AxesMap, getOriginalAxisPosition } from './axes_configuration';
|
||||
|
||||
export const LINES_MARKER_SIZE = 20;
|
||||
|
||||
type PartialExtendedYConfig = Pick<
|
||||
ExtendedYConfig,
|
||||
'axisMode' | 'icon' | 'iconPosition' | 'textVisibility'
|
||||
>;
|
||||
type PartialReferenceLineDecorationConfig = Pick<
|
||||
ReferenceLineDecorationConfig,
|
||||
'icon' | 'iconPosition' | 'textVisibility'
|
||||
> & {
|
||||
position?: Position;
|
||||
};
|
||||
|
||||
type PartialCollectiveConfig = Pick<CollectiveConfig, 'axisMode' | 'icon' | 'textVisibility'>;
|
||||
type PartialCollectiveConfig = Pick<CollectiveConfig, 'position' | 'icon' | 'textVisibility'>;
|
||||
|
||||
const isExtendedYConfig = (
|
||||
config: PartialExtendedYConfig | PartialCollectiveConfig | undefined
|
||||
): config is PartialExtendedYConfig =>
|
||||
(config as PartialExtendedYConfig)?.iconPosition ? true : false;
|
||||
const isExtendedDecorationConfig = (
|
||||
config: PartialReferenceLineDecorationConfig | PartialCollectiveConfig | undefined
|
||||
): config is PartialReferenceLineDecorationConfig =>
|
||||
(config as PartialReferenceLineDecorationConfig)?.iconPosition ? true : false;
|
||||
|
||||
// Note: it does not take into consideration whether the reference line is in view or not
|
||||
export const getLinesCausedPaddings = (
|
||||
visualConfigs: Array<PartialExtendedYConfig | PartialCollectiveConfig | undefined>,
|
||||
axesMap: Record<'left' | 'right', unknown>
|
||||
visualConfigs: Array<PartialReferenceLineDecorationConfig | PartialCollectiveConfig | undefined>,
|
||||
axesMap: AxesMap,
|
||||
shouldRotate: boolean
|
||||
) => {
|
||||
// collect all paddings for the 4 axis: if any text is detected double it.
|
||||
const paddings: Partial<Record<Position, number>> = {};
|
||||
|
@ -44,11 +47,15 @@ export const getLinesCausedPaddings = (
|
|||
if (!config) {
|
||||
return;
|
||||
}
|
||||
const { axisMode, icon, textVisibility } = config;
|
||||
const iconPosition = isExtendedYConfig(config) ? config.iconPosition : undefined;
|
||||
const { position, icon, textVisibility } = config;
|
||||
const iconPosition = isExtendedDecorationConfig(config) ? config.iconPosition : undefined;
|
||||
|
||||
if (axisMode && (hasIcon(icon) || textVisibility)) {
|
||||
const placement = getBaseIconPlacement(iconPosition, axesMap, axisMode);
|
||||
if (position && (hasIcon(icon) || textVisibility)) {
|
||||
const placement = getBaseIconPlacement(
|
||||
iconPosition,
|
||||
axesMap,
|
||||
getOriginalAxisPosition(position, shouldRotate)
|
||||
);
|
||||
paddings[placement] = Math.max(
|
||||
paddings[placement] || 0,
|
||||
LINES_MARKER_SIZE * (textVisibility ? 2 : 1) // double the padding size if there's text
|
||||
|
@ -174,7 +181,7 @@ export const AnnotationIcon = ({
|
|||
};
|
||||
|
||||
interface MarkerConfig {
|
||||
axisMode?: YAxisMode;
|
||||
position?: Position;
|
||||
icon?: string;
|
||||
textVisibility?: boolean;
|
||||
iconPosition?: IconPosition;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { DataLayerConfig } from '../../common';
|
||||
import { DataLayerConfig, YAxisConfigResult } from '../../common';
|
||||
import { LayerTypes } from '../../common/constants';
|
||||
import { Datatable } from '@kbn/expressions-plugin/public';
|
||||
import { getAxesConfiguration } from './axes_configuration';
|
||||
|
@ -221,6 +221,14 @@ describe('axes_configuration', () => {
|
|||
},
|
||||
};
|
||||
|
||||
const yAxisConfigs: YAxisConfigResult[] = [
|
||||
{
|
||||
id: '1',
|
||||
position: 'right',
|
||||
type: 'yAxisConfig',
|
||||
},
|
||||
];
|
||||
|
||||
const sampleLayer: DataLayerConfig = {
|
||||
layerId: 'first',
|
||||
type: 'dataLayer',
|
||||
|
@ -233,6 +241,9 @@ describe('axes_configuration', () => {
|
|||
columnToLabel: '{"a": "Label A", "b": "Label B", "d": "Label D"}',
|
||||
xScaleType: 'ordinal',
|
||||
isHistogram: false,
|
||||
isPercentage: false,
|
||||
isStacked: false,
|
||||
isHorizontal: false,
|
||||
palette: { type: 'palette', name: 'default' },
|
||||
table: tables.first,
|
||||
};
|
||||
|
@ -253,7 +264,7 @@ describe('axes_configuration', () => {
|
|||
|
||||
it('should map auto series to left axis', () => {
|
||||
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[0].position).toEqual('left');
|
||||
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', () => {
|
||||
const formatFactory = jest.fn();
|
||||
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[0].position).toEqual('left');
|
||||
expect(groups[1].position).toEqual('right');
|
||||
|
@ -277,7 +288,7 @@ describe('axes_configuration', () => {
|
|||
...sampleLayer,
|
||||
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[0].position).toEqual('left');
|
||||
expect(groups[1].position).toEqual('right');
|
||||
|
@ -292,12 +303,13 @@ describe('axes_configuration', () => {
|
|||
[
|
||||
{
|
||||
...sampleLayer,
|
||||
yConfig: [{ type: 'yConfig', forAccessor: 'yAccessorId', axisMode: 'right' }],
|
||||
decorations: [{ type: 'dataDecorationConfig', forAccessor: 'yAccessorId', axisId: '1' }],
|
||||
},
|
||||
],
|
||||
false,
|
||||
formatFactory,
|
||||
fieldFormats
|
||||
fieldFormats,
|
||||
yAxisConfigs
|
||||
);
|
||||
expect(groups.length).toEqual(1);
|
||||
expect(groups[0].position).toEqual('right');
|
||||
|
@ -312,19 +324,20 @@ describe('axes_configuration', () => {
|
|||
{
|
||||
...sampleLayer,
|
||||
accessors: ['yAccessorId', 'yAccessorId3', 'yAccessorId4'],
|
||||
yConfig: [{ type: 'yConfig', forAccessor: 'yAccessorId', axisMode: 'right' }],
|
||||
decorations: [{ type: 'dataDecorationConfig', forAccessor: 'yAccessorId', axisId: '1' }],
|
||||
},
|
||||
],
|
||||
false,
|
||||
formatFactory,
|
||||
fieldFormats
|
||||
fieldFormats,
|
||||
yAxisConfigs
|
||||
);
|
||||
expect(groups.length).toEqual(2);
|
||||
expect(groups[0].position).toEqual('left');
|
||||
expect(groups[0].series[0].accessor).toEqual('yAccessorId3');
|
||||
expect(groups[0].series[1].accessor).toEqual('yAccessorId4');
|
||||
expect(groups[1].position).toEqual('right');
|
||||
expect(groups[1].series[0].accessor).toEqual('yAccessorId');
|
||||
expect(groups[0].position).toEqual('right');
|
||||
expect(groups[0].series[0].accessor).toEqual('yAccessorId');
|
||||
expect(groups[1].position).toEqual('left');
|
||||
expect(groups[1].series[0].accessor).toEqual('yAccessorId3');
|
||||
expect(groups[1].series[1].accessor).toEqual('yAccessorId4');
|
||||
expect(formatFactory).toHaveBeenCalledWith({ id: 'number', params: {} });
|
||||
expect(formatFactory).toHaveBeenCalledWith({ id: 'currency', params: {} });
|
||||
});
|
||||
|
@ -336,12 +349,13 @@ describe('axes_configuration', () => {
|
|||
{
|
||||
...sampleLayer,
|
||||
accessors: ['yAccessorId', 'yAccessorId3', 'yAccessorId4'],
|
||||
yConfig: [{ type: 'yConfig', forAccessor: 'yAccessorId', axisMode: 'right' }],
|
||||
decorations: [{ type: 'dataDecorationConfig', forAccessor: 'yAccessorId', axisId: '1' }],
|
||||
},
|
||||
],
|
||||
false,
|
||||
formatFactory,
|
||||
fieldFormats
|
||||
fieldFormats,
|
||||
yAxisConfigs
|
||||
);
|
||||
expect(formatFactory).toHaveBeenCalledTimes(2);
|
||||
expect(formatFactory).toHaveBeenCalledWith({ id: 'number', params: {} });
|
||||
|
|
|
@ -6,15 +6,18 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { Position } from '@elastic/charts';
|
||||
import type { IFieldFormat, SerializedFieldFormat } from '@kbn/field-formats-plugin/common';
|
||||
import { getAccessorByDimension } from '@kbn/visualizations-plugin/common/utils';
|
||||
import { FormatFactory } from '../types';
|
||||
import {
|
||||
AxisExtentConfig,
|
||||
CommonXYDataLayerConfig,
|
||||
ExtendedYConfig,
|
||||
YConfig,
|
||||
YScaleType,
|
||||
DataDecorationConfig,
|
||||
YAxisConfig,
|
||||
ReferenceLineDecorationConfig,
|
||||
YAxisConfigResult,
|
||||
XAxisConfigResult,
|
||||
} from '../../common';
|
||||
import { LayersFieldFormats } from './layers';
|
||||
|
||||
|
@ -25,15 +28,26 @@ export interface Series {
|
|||
|
||||
interface FormattedMetric extends Series {
|
||||
fieldFormat: SerializedFieldFormat;
|
||||
axisId?: string;
|
||||
}
|
||||
|
||||
export type GroupsConfiguration = Array<{
|
||||
groupId: 'left' | 'right';
|
||||
position: 'left' | 'right' | 'bottom' | 'top';
|
||||
interface AxesSeries {
|
||||
[key: string]: FormattedMetric[];
|
||||
}
|
||||
|
||||
export interface AxisConfiguration extends Omit<YAxisConfig, 'id'> {
|
||||
/**
|
||||
* Axis group identificator. Format: `axis-${axis.id}` or just `left`/`right`.
|
||||
*/
|
||||
groupId: string;
|
||||
position: Position;
|
||||
formatter?: IFieldFormat;
|
||||
series: Series[];
|
||||
scale?: YScaleType;
|
||||
}>;
|
||||
}
|
||||
|
||||
export type GroupsConfiguration = AxisConfiguration[];
|
||||
|
||||
export type AxesMap = Record<'left' | 'right', AxisConfiguration | undefined>;
|
||||
|
||||
export function isFormatterCompatible(
|
||||
formatter1: SerializedFieldFormat,
|
||||
|
@ -42,91 +56,203 @@ export function isFormatterCompatible(
|
|||
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(
|
||||
layers: CommonXYDataLayerConfig[],
|
||||
fieldFormats: LayersFieldFormats
|
||||
fieldFormats: LayersFieldFormats,
|
||||
yAxisConfigs?: YAxisConfig[]
|
||||
) {
|
||||
const series: {
|
||||
auto: FormattedMetric[];
|
||||
left: FormattedMetric[];
|
||||
right: FormattedMetric[];
|
||||
bottom: FormattedMetric[];
|
||||
} = {
|
||||
const series: AxesSeries = {
|
||||
auto: [],
|
||||
left: [],
|
||||
right: [],
|
||||
bottom: [],
|
||||
};
|
||||
|
||||
const leftSeriesKeys: string[] = [];
|
||||
const rightSeriesKeys: string[] = [];
|
||||
|
||||
layers.forEach((layer) => {
|
||||
const { layerId, table } = layer;
|
||||
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 mode =
|
||||
yConfig?.find(({ forAccessor }) => forAccessor === yAccessor)?.axisMode || 'auto';
|
||||
const decorationByAccessor = dataDecorations?.find(
|
||||
(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]!;
|
||||
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;
|
||||
|
||||
leftSeriesKeys.push(LEFT_GLOBAL_AXIS_ID);
|
||||
rightSeriesKeys.push(RIGHT_GLOBAL_AXIS_ID);
|
||||
|
||||
series.auto.forEach((currentSeries) => {
|
||||
if (
|
||||
series.left.length === 0 ||
|
||||
(tablesExist &&
|
||||
series.left.every((leftSeries) =>
|
||||
isFormatterCompatible(leftSeries.fieldFormat, currentSeries.fieldFormat)
|
||||
))
|
||||
) {
|
||||
series.left.push(currentSeries);
|
||||
} else if (
|
||||
series.right.length === 0 ||
|
||||
(tablesExist &&
|
||||
series.left.every((leftSeries) =>
|
||||
isFormatterCompatible(leftSeries.fieldFormat, currentSeries.fieldFormat)
|
||||
))
|
||||
) {
|
||||
series.right.push(currentSeries);
|
||||
} else if (series.right.length >= series.left.length) {
|
||||
series.left.push(currentSeries);
|
||||
const leftAxisGroupId = tablesExist
|
||||
? leftSeriesKeys.find((leftSeriesKey) =>
|
||||
isAxisSeriesAppliedForFormatter(series[leftSeriesKey], currentSeries)
|
||||
)
|
||||
: undefined;
|
||||
|
||||
const rightAxisGroupId = tablesExist
|
||||
? rightSeriesKeys.find((rightSeriesKey) =>
|
||||
isAxisSeriesAppliedForFormatter(series[rightSeriesKey], currentSeries)
|
||||
)
|
||||
: undefined;
|
||||
|
||||
let axisGroupId = LEFT_GLOBAL_AXIS_ID;
|
||||
|
||||
if (series[LEFT_GLOBAL_AXIS_ID].length === 0 || leftAxisGroupId) {
|
||||
axisGroupId = leftAxisGroupId || LEFT_GLOBAL_AXIS_ID;
|
||||
} else if (series[RIGHT_GLOBAL_AXIS_ID].length === 0 || rightAxisGroupId) {
|
||||
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 {
|
||||
series.right.push(currentSeries);
|
||||
axisGroupId = RIGHT_GLOBAL_AXIS_ID;
|
||||
}
|
||||
|
||||
series[axisGroupId].push(currentSeries);
|
||||
});
|
||||
|
||||
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(
|
||||
layers: CommonXYDataLayerConfig[],
|
||||
shouldRotate: boolean,
|
||||
formatFactory: FormatFactory | undefined,
|
||||
fieldFormats: LayersFieldFormats,
|
||||
yLeftScale?: YScaleType,
|
||||
yRightScale?: YScaleType
|
||||
axisConfigs?: Array<XAxisConfigResult | YAxisConfigResult>
|
||||
): GroupsConfiguration {
|
||||
const series = groupAxesByType(layers, fieldFormats);
|
||||
const series = groupAxesByType(layers, fieldFormats, axisConfigs);
|
||||
|
||||
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({
|
||||
groupId: 'left',
|
||||
position: shouldRotate ? 'bottom' : 'left',
|
||||
groupId: LEFT_GLOBAL_AXIS_ID,
|
||||
formatter: formatFactory?.(series.left[0].fieldFormat),
|
||||
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({
|
||||
groupId: 'right',
|
||||
position: shouldRotate ? 'top' : 'right',
|
||||
groupId: RIGHT_GLOBAL_AXIS_ID,
|
||||
formatter: formatFactory?.(series.right[0].fieldFormat),
|
||||
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',
|
||||
showLines: true,
|
||||
isHistogram: true,
|
||||
isPercentage: false,
|
||||
xScaleType: 'linear',
|
||||
seriesType: 'bar',
|
||||
isStacked: false,
|
||||
isHorizontal: false,
|
||||
palette: { type: 'palette', name: 'palette1' },
|
||||
layerType: LayerTypes.DATA,
|
||||
splitAccessor: 'split1',
|
||||
|
@ -68,7 +71,10 @@ describe('color_assignment', () => {
|
|||
showLines: true,
|
||||
xScaleType: 'linear',
|
||||
isHistogram: true,
|
||||
isPercentage: false,
|
||||
seriesType: 'bar',
|
||||
isStacked: false,
|
||||
isHorizontal: false,
|
||||
palette: { type: 'palette', name: 'palette2' },
|
||||
layerType: LayerTypes.DATA,
|
||||
splitAccessor: 'split2',
|
||||
|
|
|
@ -27,6 +27,7 @@ import {
|
|||
import type { ExpressionValueVisDimension } from '@kbn/visualizations-plugin/common/expression_functions';
|
||||
import { PaletteRegistry, SeriesLayer } from '@kbn/coloring';
|
||||
import { CommonXYDataLayerConfig, XScaleType } from '../../common';
|
||||
import { AxisModes, SeriesTypes } from '../../common/constants';
|
||||
import { FormatFactory } from '../types';
|
||||
import { getSeriesColor } from './state';
|
||||
import { ColorAssignments } from './color_assignment';
|
||||
|
@ -350,10 +351,14 @@ export const getSeriesProps: GetSeriesPropsFn = ({
|
|||
formattedDatatableInfo,
|
||||
defaultXScaleType,
|
||||
}): SeriesSpec => {
|
||||
const { table, markSizeAccessor } = layer;
|
||||
const isStacked = layer.seriesType.includes('stacked');
|
||||
const isPercentage = layer.seriesType.includes('percentage');
|
||||
const isBarChart = layer.seriesType.includes('bar');
|
||||
const { table, isStacked, markSizeAccessor } = layer;
|
||||
const isPercentage = layer.isPercentage;
|
||||
let stackMode: StackMode | undefined = isPercentage ? AxisModes.PERCENTAGE : undefined;
|
||||
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 splitColumnId =
|
||||
layer.splitAccessor && getAccessorByDimension(layer.splitAccessor, table.columns);
|
||||
|
@ -413,9 +418,9 @@ export const getSeriesProps: GetSeriesPropsFn = ({
|
|||
data: rows,
|
||||
xScaleType: xColumnId ? layer.xScaleType ?? defaultXScaleType : 'ordinal',
|
||||
yScaleType:
|
||||
formatter?.id === 'bytes' && yAxis?.scale === ScaleType.Linear
|
||||
formatter?.id === 'bytes' && scaleType === ScaleType.Linear
|
||||
? ScaleType.LinearBinary
|
||||
: yAxis?.scale || ScaleType.Linear,
|
||||
: scaleType,
|
||||
color: (series) =>
|
||||
getColor(
|
||||
series,
|
||||
|
@ -431,7 +436,7 @@ export const getSeriesProps: GetSeriesPropsFn = ({
|
|||
),
|
||||
groupId: yAxis?.groupId,
|
||||
enableHistogramMode,
|
||||
stackMode: isPercentage ? StackMode.Percentage : undefined,
|
||||
stackMode,
|
||||
timeZone,
|
||||
areaSeriesStyle: {
|
||||
point: getPointConfig({
|
||||
|
|
|
@ -17,7 +17,6 @@ import {
|
|||
CommonXYDataLayerConfig,
|
||||
CommonXYLayerConfig,
|
||||
ReferenceLineLayerConfig,
|
||||
SeriesType,
|
||||
} from '../../common/types';
|
||||
import { GroupsConfiguration } from './axes_configuration';
|
||||
import { getFormat } from './format';
|
||||
|
@ -110,7 +109,7 @@ const getAccessorWithFieldFormat = (
|
|||
const getYAccessorWithFieldFormat = (
|
||||
dimension: string | ExpressionValueVisDimension | undefined,
|
||||
columns: Datatable['columns'],
|
||||
seriesType: SeriesType
|
||||
isPercentage: boolean
|
||||
) => {
|
||||
if (!dimension) {
|
||||
return {};
|
||||
|
@ -118,7 +117,7 @@ const getYAccessorWithFieldFormat = (
|
|||
|
||||
const accessor = getAccessorByDimension(dimension, columns);
|
||||
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]%' } };
|
||||
}
|
||||
|
||||
|
@ -126,7 +125,7 @@ const getYAccessorWithFieldFormat = (
|
|||
};
|
||||
|
||||
export const getLayerFormats = (
|
||||
{ xAccessor, accessors, splitAccessor, table, seriesType }: CommonXYDataLayerConfig,
|
||||
{ xAccessor, accessors, splitAccessor, table, isPercentage }: CommonXYDataLayerConfig,
|
||||
{ splitColumnAccessor, splitRowAccessor }: SplitAccessors
|
||||
): LayerFieldFormats => {
|
||||
const yAccessors: Array<string | ExpressionValueVisDimension> = accessors;
|
||||
|
@ -135,7 +134,7 @@ export const getLayerFormats = (
|
|||
yAccessors: yAccessors.reduce(
|
||||
(formatters, a) => ({
|
||||
...formatters,
|
||||
...getYAccessorWithFieldFormat(a, table.columns, seriesType),
|
||||
...getYAccessorWithFieldFormat(a, table.columns, isPercentage),
|
||||
}),
|
||||
{}
|
||||
),
|
||||
|
@ -160,28 +159,21 @@ export const getLayersFormats = (
|
|||
const getTitleForYAccessor = (
|
||||
layerId: string,
|
||||
yAccessor: string | ExpressionValueVisDimension,
|
||||
{ yTitle, yRightTitle }: Omit<CustomTitles, 'xTitle'>,
|
||||
groups: GroupsConfiguration,
|
||||
columns: Datatable['columns']
|
||||
) => {
|
||||
const column = getColumnByAccessor(yAccessor, columns);
|
||||
const isRight = groups.some((group) =>
|
||||
group.series.some(
|
||||
({ accessor, layer }) =>
|
||||
accessor === yAccessor && layer === layerId && group.groupId === 'right'
|
||||
)
|
||||
const axisGroup = groups.find((group) =>
|
||||
group.series.some(({ accessor, layer }) => accessor === yAccessor && layer === layerId)
|
||||
);
|
||||
if (isRight) {
|
||||
return yRightTitle || column!.name;
|
||||
}
|
||||
|
||||
return yTitle || column!.name;
|
||||
return axisGroup?.title || column!.name;
|
||||
};
|
||||
|
||||
export const getLayerTitles = (
|
||||
{ xAccessor, accessors, splitAccessor, table, layerId }: CommonXYDataLayerConfig,
|
||||
{ splitColumnAccessor, splitRowAccessor }: SplitAccessors,
|
||||
{ xTitle, yTitle, yRightTitle }: CustomTitles,
|
||||
{ xTitle }: CustomTitles,
|
||||
groups: GroupsConfiguration
|
||||
): LayerAccessorsTitles => {
|
||||
const mapTitle = (dimension?: string | ExpressionValueVisDimension) => {
|
||||
|
@ -194,13 +186,7 @@ export const getLayerTitles = (
|
|||
};
|
||||
|
||||
const getYTitle = (accessor: string) => ({
|
||||
[accessor]: getTitleForYAccessor(
|
||||
layerId,
|
||||
accessor,
|
||||
{ yTitle, yRightTitle },
|
||||
groups,
|
||||
table.columns
|
||||
),
|
||||
[accessor]: getTitleForYAccessor(layerId, accessor, groups, table.columns),
|
||||
});
|
||||
|
||||
const xColumnId = xAccessor && getAccessorByDimension(xAccessor, table.columns);
|
||||
|
|
|
@ -6,23 +6,15 @@
|
|||
* 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';
|
||||
|
||||
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[]) {
|
||||
return getDataLayers(layers).every((l) => isHorizontalSeries(l.seriesType));
|
||||
return getDataLayers(layers).every((l) => l.isHorizontal);
|
||||
}
|
||||
|
||||
export const getSeriesColor = (layer: CommonXYLayerConfig, accessor: string) => {
|
||||
|
@ -33,6 +25,10 @@ export const getSeriesColor = (layer: CommonXYLayerConfig, accessor: string) =>
|
|||
) {
|
||||
return null;
|
||||
}
|
||||
const yConfig: Array<YConfig | ExtendedYConfig> | undefined = layer?.yConfig;
|
||||
return yConfig?.find((yConf) => yConf.forAccessor === accessor)?.color || null;
|
||||
const decorations: Array<DataDecorationConfig | ReferenceLineDecorationConfig> | undefined =
|
||||
layer?.decorations;
|
||||
return (
|
||||
decorations?.find((decorationConfig) => decorationConfig.forAccessor === accessor)?.color ||
|
||||
null
|
||||
);
|
||||
};
|
||||
|
|
|
@ -10,7 +10,7 @@ import {
|
|||
LayerTypes,
|
||||
REFERENCE_LINE,
|
||||
REFERENCE_LINE_LAYER,
|
||||
REFERENCE_LINE_Y_CONFIG,
|
||||
EXTENDED_REFERENCE_LINE_DECORATION_CONFIG,
|
||||
} from '../../common/constants';
|
||||
import {
|
||||
CommonXYLayerConfig,
|
||||
|
@ -19,8 +19,8 @@ import {
|
|||
CommonXYAnnotationLayerConfig,
|
||||
ReferenceLineLayerConfig,
|
||||
ReferenceLineConfig,
|
||||
ExtendedYConfigResult,
|
||||
ReferenceLineYConfig,
|
||||
ReferenceLineDecorationConfigResult,
|
||||
ExtendedReferenceLineDecorationConfig,
|
||||
} from '../../common/types';
|
||||
|
||||
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 =>
|
||||
layer.type === REFERENCE_LINE;
|
||||
|
||||
export const isReferenceLineYConfig = (
|
||||
yConfig: ReferenceLineYConfig | ExtendedYConfigResult
|
||||
): yConfig is ReferenceLineYConfig => yConfig.type === REFERENCE_LINE_Y_CONFIG;
|
||||
export const isReferenceLineDecorationConfig = (
|
||||
decoration: ExtendedReferenceLineDecorationConfig | ReferenceLineDecorationConfigResult
|
||||
): decoration is ExtendedReferenceLineDecorationConfig =>
|
||||
decoration.type === EXTENDED_REFERENCE_LINE_DECORATION_CONFIG;
|
||||
|
||||
export const isReferenceLineOrLayer = (
|
||||
layer: CommonXYLayerConfig
|
||||
|
|
|
@ -18,18 +18,16 @@ import {
|
|||
xyVisFunction,
|
||||
layeredXyVisFunction,
|
||||
extendedDataLayerFunction,
|
||||
dataDecorationConfigFunction,
|
||||
xAxisConfigFunction,
|
||||
yAxisConfigFunction,
|
||||
extendedYAxisConfigFunction,
|
||||
legendConfigFunction,
|
||||
gridlinesConfigFunction,
|
||||
axisExtentConfigFunction,
|
||||
tickLabelsConfigFunction,
|
||||
referenceLineFunction,
|
||||
referenceLineLayerFunction,
|
||||
annotationLayerFunction,
|
||||
labelsOrientationConfigFunction,
|
||||
axisTitlesVisibilityConfigFunction,
|
||||
extendedAnnotationLayerFunction,
|
||||
referenceLineDecorationConfigFunction,
|
||||
} from '../common/expression_functions';
|
||||
import { GetStartDepsFn, getXyChartRenderer } from './expression_renderers';
|
||||
|
||||
|
@ -55,18 +53,16 @@ export class ExpressionXyPlugin {
|
|||
{ expressions, charts }: SetupDeps
|
||||
): ExpressionXyPluginSetup {
|
||||
expressions.registerFunction(yAxisConfigFunction);
|
||||
expressions.registerFunction(extendedYAxisConfigFunction);
|
||||
expressions.registerFunction(dataDecorationConfigFunction);
|
||||
expressions.registerFunction(referenceLineDecorationConfigFunction);
|
||||
expressions.registerFunction(legendConfigFunction);
|
||||
expressions.registerFunction(gridlinesConfigFunction);
|
||||
expressions.registerFunction(extendedDataLayerFunction);
|
||||
expressions.registerFunction(axisExtentConfigFunction);
|
||||
expressions.registerFunction(tickLabelsConfigFunction);
|
||||
expressions.registerFunction(xAxisConfigFunction);
|
||||
expressions.registerFunction(annotationLayerFunction);
|
||||
expressions.registerFunction(extendedAnnotationLayerFunction);
|
||||
expressions.registerFunction(labelsOrientationConfigFunction);
|
||||
expressions.registerFunction(referenceLineFunction);
|
||||
expressions.registerFunction(referenceLineLayerFunction);
|
||||
expressions.registerFunction(axisTitlesVisibilityConfigFunction);
|
||||
expressions.registerFunction(xyVisFunction);
|
||||
expressions.registerFunction(layeredXyVisFunction);
|
||||
|
||||
|
|
|
@ -11,16 +11,14 @@ import { CoreSetup, CoreStart, Plugin } from '@kbn/core/server';
|
|||
import { ExpressionXyPluginSetup, ExpressionXyPluginStart } from './types';
|
||||
import {
|
||||
xyVisFunction,
|
||||
yAxisConfigFunction,
|
||||
extendedYAxisConfigFunction,
|
||||
legendConfigFunction,
|
||||
gridlinesConfigFunction,
|
||||
dataDecorationConfigFunction,
|
||||
xAxisConfigFunction,
|
||||
yAxisConfigFunction,
|
||||
referenceLineDecorationConfigFunction,
|
||||
axisExtentConfigFunction,
|
||||
tickLabelsConfigFunction,
|
||||
annotationLayerFunction,
|
||||
labelsOrientationConfigFunction,
|
||||
referenceLineFunction,
|
||||
axisTitlesVisibilityConfigFunction,
|
||||
extendedDataLayerFunction,
|
||||
referenceLineLayerFunction,
|
||||
layeredXyVisFunction,
|
||||
|
@ -33,18 +31,16 @@ export class ExpressionXyPlugin
|
|||
{
|
||||
public setup(core: CoreSetup, { expressions }: SetupDeps) {
|
||||
expressions.registerFunction(yAxisConfigFunction);
|
||||
expressions.registerFunction(extendedYAxisConfigFunction);
|
||||
expressions.registerFunction(dataDecorationConfigFunction);
|
||||
expressions.registerFunction(xAxisConfigFunction);
|
||||
expressions.registerFunction(referenceLineDecorationConfigFunction);
|
||||
expressions.registerFunction(legendConfigFunction);
|
||||
expressions.registerFunction(gridlinesConfigFunction);
|
||||
expressions.registerFunction(extendedDataLayerFunction);
|
||||
expressions.registerFunction(axisExtentConfigFunction);
|
||||
expressions.registerFunction(tickLabelsConfigFunction);
|
||||
expressions.registerFunction(annotationLayerFunction);
|
||||
expressions.registerFunction(extendedAnnotationLayerFunction);
|
||||
expressions.registerFunction(labelsOrientationConfigFunction);
|
||||
expressions.registerFunction(referenceLineFunction);
|
||||
expressions.registerFunction(referenceLineLayerFunction);
|
||||
expressions.registerFunction(axisTitlesVisibilityConfigFunction);
|
||||
expressions.registerFunction(xyVisFunction);
|
||||
expressions.registerFunction(layeredXyVisFunction);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,9 @@ export type {
|
|||
ValidLayer,
|
||||
XYDataLayerConfig,
|
||||
XYAnnotationLayerConfig,
|
||||
YAxisMode,
|
||||
SeriesType,
|
||||
YConfig,
|
||||
} from './xy_visualization/types';
|
||||
export type {
|
||||
DatasourcePublicAPI,
|
||||
|
@ -74,13 +77,10 @@ export type {
|
|||
} from './indexpattern_datasource/types';
|
||||
export type {
|
||||
XYArgs,
|
||||
ExtendedYConfig,
|
||||
XYRender,
|
||||
LayerType,
|
||||
YAxisMode,
|
||||
LineStyle,
|
||||
FillStyle,
|
||||
SeriesType,
|
||||
YScaleType,
|
||||
XScaleType,
|
||||
AxisConfig,
|
||||
|
@ -88,7 +88,6 @@ export type {
|
|||
XYChartProps,
|
||||
LegendConfig,
|
||||
IconPosition,
|
||||
ExtendedYConfigResult,
|
||||
DataLayerArgs,
|
||||
ValueLabelMode,
|
||||
AxisExtentMode,
|
||||
|
@ -97,14 +96,9 @@ export type {
|
|||
AxisExtentConfig,
|
||||
LegendConfigResult,
|
||||
AxesSettingsConfig,
|
||||
GridlinesConfigResult,
|
||||
TickLabelsConfigResult,
|
||||
AxisExtentConfigResult,
|
||||
ReferenceLineLayerArgs,
|
||||
LabelsOrientationConfig,
|
||||
ReferenceLineLayerConfig,
|
||||
LabelsOrientationConfigResult,
|
||||
AxisTitlesVisibilityConfigResult,
|
||||
} from '@kbn/expression-xy-plugin/common';
|
||||
export type { LensEmbeddableInput, LensSavedObjectAttributes, Embeddable } from './embeddable';
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import React, { useCallback, useMemo } from 'react';
|
||||
import { EuiSpacer, EuiFormRow } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { AxesSettingsConfig } from '@kbn/expression-xy-plugin/common';
|
||||
import { AxesSettingsConfig } from '../xy_visualization/types';
|
||||
import { LabelMode, useDebouncedValue, VisLabel } from '.';
|
||||
|
||||
type AxesSettingsConfigKeys = keyof AxesSettingsConfig;
|
||||
|
|
|
@ -5,28 +5,6 @@ Object {
|
|||
"chain": Array [
|
||||
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 [
|
||||
"LINEAR",
|
||||
],
|
||||
|
@ -42,53 +20,9 @@ Object {
|
|||
"fittingFunction": Array [
|
||||
"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 [
|
||||
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 [
|
||||
Object {
|
||||
"chain": Array [
|
||||
|
@ -101,12 +35,16 @@ Object {
|
|||
"columnToLabel": Array [
|
||||
"{\\"b\\":\\"col_b\\",\\"c\\":\\"col_c\\",\\"d\\":\\"col_d\\"}",
|
||||
],
|
||||
"decorations": Array [],
|
||||
"hide": Array [
|
||||
false,
|
||||
],
|
||||
"isHistogram": Array [
|
||||
false,
|
||||
],
|
||||
"isHorizontal": Array [],
|
||||
"isPercentage": Array [],
|
||||
"isStacked": Array [],
|
||||
"layerId": Array [
|
||||
"first",
|
||||
],
|
||||
|
@ -144,7 +82,6 @@ Object {
|
|||
"xScaleType": Array [
|
||||
"linear",
|
||||
],
|
||||
"yConfig": Array [],
|
||||
},
|
||||
"function": "extendedDataLayer",
|
||||
"type": "function",
|
||||
|
@ -182,103 +119,138 @@ Object {
|
|||
"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 [
|
||||
"hide",
|
||||
],
|
||||
"valuesInLegend": Array [
|
||||
false,
|
||||
],
|
||||
"xExtent": Array [
|
||||
"xAxisConfig": Array [
|
||||
Object {
|
||||
"chain": Array [
|
||||
Object {
|
||||
"arguments": Object {
|
||||
"lowerBound": Array [],
|
||||
"mode": Array [],
|
||||
"upperBound": Array [],
|
||||
"extent": Array [],
|
||||
"id": 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": "expression",
|
||||
},
|
||||
],
|
||||
"xTitle": Array [
|
||||
"",
|
||||
],
|
||||
"yLeftExtent": Array [
|
||||
"yAxisConfigs": Array [
|
||||
Object {
|
||||
"chain": Array [
|
||||
Object {
|
||||
"arguments": Object {
|
||||
"lowerBound": Array [],
|
||||
"mode": Array [],
|
||||
"upperBound": Array [],
|
||||
"extent": Array [],
|
||||
"id": 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": "expression",
|
||||
},
|
||||
],
|
||||
"yLeftScale": Array [
|
||||
"linear",
|
||||
],
|
||||
"yRightExtent": Array [
|
||||
Object {
|
||||
"chain": Array [
|
||||
Object {
|
||||
"arguments": Object {
|
||||
"lowerBound": Array [
|
||||
123,
|
||||
"extent": Array [
|
||||
Object {
|
||||
"chain": Array [
|
||||
Object {
|
||||
"arguments": Object {
|
||||
"lowerBound": Array [
|
||||
123,
|
||||
],
|
||||
"mode": Array [
|
||||
"custom",
|
||||
],
|
||||
"upperBound": Array [
|
||||
456,
|
||||
],
|
||||
},
|
||||
"function": "axisExtentConfig",
|
||||
"type": "function",
|
||||
},
|
||||
],
|
||||
"type": "expression",
|
||||
},
|
||||
],
|
||||
"mode": Array [
|
||||
"custom",
|
||||
"id": Array [],
|
||||
"labelsOrientation": Array [
|
||||
-45,
|
||||
],
|
||||
"upperBound": Array [
|
||||
456,
|
||||
"position": Array [
|
||||
"right",
|
||||
],
|
||||
"scaleType": Array [
|
||||
"linear",
|
||||
],
|
||||
"showGridLines": Array [
|
||||
true,
|
||||
],
|
||||
"showLabels": Array [
|
||||
true,
|
||||
],
|
||||
"showTitle": Array [
|
||||
true,
|
||||
],
|
||||
"title": Array [
|
||||
"",
|
||||
],
|
||||
},
|
||||
"function": "axisExtentConfig",
|
||||
"function": "yAxisConfig",
|
||||
"type": "function",
|
||||
},
|
||||
],
|
||||
"type": "expression",
|
||||
},
|
||||
],
|
||||
"yRightScale": Array [
|
||||
"linear",
|
||||
],
|
||||
"yRightTitle": Array [
|
||||
"",
|
||||
],
|
||||
"yTitle": Array [
|
||||
"",
|
||||
],
|
||||
},
|
||||
"function": "layeredXyVis",
|
||||
"type": "function",
|
||||
|
|
|
@ -7,13 +7,18 @@
|
|||
|
||||
import { groupBy, partition } from 'lodash';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import type { YAxisMode, ExtendedYConfig } from '@kbn/expression-xy-plugin/common';
|
||||
import { Datatable } from '@kbn/expressions-plugin/public';
|
||||
import { layerTypes } from '../../common';
|
||||
import type { DatasourceLayers, FramePublicAPI, Visualization } from '../types';
|
||||
import { groupAxesByType } from './axes_configuration';
|
||||
import { isHorizontalChart, isPercentageSeries, isStackedChart } from './state_helpers';
|
||||
import type { XYState, XYDataLayerConfig, XYReferenceLineLayerConfig } from './types';
|
||||
import type {
|
||||
XYState,
|
||||
XYDataLayerConfig,
|
||||
XYReferenceLineLayerConfig,
|
||||
YAxisMode,
|
||||
YConfig,
|
||||
} from './types';
|
||||
import {
|
||||
checkScaleOperation,
|
||||
getAxisName,
|
||||
|
@ -35,7 +40,7 @@ export interface ReferenceLineBase {
|
|||
* * what groups are current defined in data 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[],
|
||||
state: XYState | undefined,
|
||||
datasourceLayers: DatasourceLayers,
|
||||
|
|
|
@ -6,13 +6,14 @@
|
|||
*/
|
||||
|
||||
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 {
|
||||
visualizationTypes,
|
||||
XYLayerConfig,
|
||||
XYDataLayerConfig,
|
||||
XYReferenceLineLayerConfig,
|
||||
SeriesType,
|
||||
YConfig,
|
||||
} from './types';
|
||||
import { getDataLayers, isAnnotationsLayer, isDataLayer } from './visualization_helpers';
|
||||
|
||||
|
@ -58,8 +59,7 @@ export const getSeriesColor = (layer: XYLayerConfig, accessor: string) => {
|
|||
return null;
|
||||
}
|
||||
return (
|
||||
layer?.yConfig?.find((yConfig: ExtendedYConfig) => yConfig.forAccessor === accessor)?.color ||
|
||||
null
|
||||
layer?.yConfig?.find((yConfig: YConfig) => yConfig.forAccessor === accessor)?.color || null
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -159,13 +159,23 @@ describe('#toExpression', () => {
|
|||
undefined,
|
||||
datasourceExpressionsByLayers
|
||||
) as Ast;
|
||||
expect(
|
||||
(expression.chain[0].arguments.axisTitlesVisibilitySettings[0] as Ast).chain[0].arguments
|
||||
).toEqual({
|
||||
x: [true],
|
||||
yLeft: [true],
|
||||
yRight: [true],
|
||||
});
|
||||
expect((expression.chain[0].arguments.yAxisConfigs[0] as Ast).chain[0].arguments).toEqual(
|
||||
expect.objectContaining({
|
||||
showTitle: [true],
|
||||
position: ['left'],
|
||||
})
|
||||
);
|
||||
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', () => {
|
||||
|
@ -244,9 +254,6 @@ describe('#toExpression', () => {
|
|||
expect(mockDatasource.publicAPIMock.getOperationForColumnId).toHaveBeenCalledWith('b');
|
||||
expect(mockDatasource.publicAPIMock.getOperationForColumnId).toHaveBeenCalledWith('c');
|
||||
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(
|
||||
(expression.chain[0].arguments.layers[0] as Ast).chain[0].arguments.columnToLabel
|
||||
).toEqual([
|
||||
|
@ -279,13 +286,23 @@ describe('#toExpression', () => {
|
|||
undefined,
|
||||
datasourceExpressionsByLayers
|
||||
) as Ast;
|
||||
expect(
|
||||
(expression.chain[0].arguments.tickLabelsVisibilitySettings[0] as Ast).chain[0].arguments
|
||||
).toEqual({
|
||||
x: [true],
|
||||
yLeft: [true],
|
||||
yRight: [true],
|
||||
});
|
||||
expect((expression.chain[0].arguments.yAxisConfigs[0] as Ast).chain[0].arguments).toEqual(
|
||||
expect.objectContaining({
|
||||
showLabels: [true],
|
||||
position: ['left'],
|
||||
})
|
||||
);
|
||||
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', () => {
|
||||
|
@ -309,11 +326,23 @@ describe('#toExpression', () => {
|
|||
undefined,
|
||||
datasourceExpressionsByLayers
|
||||
) as Ast;
|
||||
expect((expression.chain[0].arguments.labelsOrientation[0] as Ast).chain[0].arguments).toEqual({
|
||||
x: [0],
|
||||
yLeft: [0],
|
||||
yRight: [0],
|
||||
});
|
||||
expect((expression.chain[0].arguments.yAxisConfigs[0] as Ast).chain[0].arguments).toEqual(
|
||||
expect.objectContaining({
|
||||
labelsOrientation: [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', () => {
|
||||
|
@ -337,13 +366,23 @@ describe('#toExpression', () => {
|
|||
undefined,
|
||||
datasourceExpressionsByLayers
|
||||
) as Ast;
|
||||
expect(
|
||||
(expression.chain[0].arguments.gridlinesVisibilitySettings[0] as Ast).chain[0].arguments
|
||||
).toEqual({
|
||||
x: [true],
|
||||
yLeft: [true],
|
||||
yRight: [true],
|
||||
});
|
||||
expect((expression.chain[0].arguments.yAxisConfigs[0] as Ast).chain[0].arguments).toEqual(
|
||||
expect.objectContaining({
|
||||
showGridLines: [true],
|
||||
position: ['left'],
|
||||
})
|
||||
);
|
||||
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', () => {
|
||||
|
@ -488,8 +527,9 @@ describe('#toExpression', () => {
|
|||
) as Ast;
|
||||
|
||||
function getYConfigColorForLayer(ast: Ast, index: number) {
|
||||
return ((ast.chain[0].arguments.layers[index] as Ast).chain[0].arguments.yConfig[0] as Ast)
|
||||
.chain[0].arguments.color;
|
||||
return (
|
||||
(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, 1)).toEqual([defaultReferenceLineColor]);
|
||||
|
|
|
@ -8,15 +8,15 @@
|
|||
import { Ast, AstFunction } from '@kbn/interpreter';
|
||||
import { Position, ScaleType } from '@elastic/charts';
|
||||
import type { PaletteRegistry } from '@kbn/coloring';
|
||||
|
||||
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 {
|
||||
State,
|
||||
YConfig,
|
||||
XYDataLayerConfig,
|
||||
XYReferenceLineLayerConfig,
|
||||
XYAnnotationLayerConfig,
|
||||
AxisConfig,
|
||||
} from './types';
|
||||
import type { ValidXYDataLayerConfig } from './types';
|
||||
import { OperationMetadata, DatasourcePublicAPI, DatasourceLayers } from '../types';
|
||||
|
@ -191,6 +191,54 @@ export const buildExpression = (
|
|||
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 {
|
||||
type: 'expression',
|
||||
chain: [
|
||||
|
@ -198,9 +246,6 @@ export const buildExpression = (
|
|||
type: 'function',
|
||||
function: 'layeredXyVis',
|
||||
arguments: {
|
||||
xTitle: [state.xTitle || ''],
|
||||
yTitle: [state.yTitle || ''],
|
||||
yRightTitle: [state.yRightTitle || ''],
|
||||
legend: [
|
||||
{
|
||||
type: 'expression',
|
||||
|
@ -252,82 +297,36 @@ export const buildExpression = (
|
|||
emphasizeFitting: [state.emphasizeFitting || false],
|
||||
curveType: [state.curveType || 'LINEAR'],
|
||||
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'],
|
||||
hideEndzones: [state?.hideEndzones || 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: [
|
||||
...validDataLayers.map((layer) =>
|
||||
dataLayerToExpression(
|
||||
layer,
|
||||
yAxisConfigs,
|
||||
datasourceLayers[layer.layerId],
|
||||
metadata,
|
||||
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 = (
|
||||
layer: XYReferenceLineLayerConfig,
|
||||
datasourceLayer: DatasourcePublicAPI,
|
||||
|
@ -364,9 +386,9 @@ const referenceLineLayerToExpression = (
|
|||
function: 'referenceLineLayer',
|
||||
arguments: {
|
||||
layerId: [layer.layerId],
|
||||
yConfig: layer.yConfig
|
||||
decorations: layer.yConfig
|
||||
? layer.yConfig.map((yConfig) =>
|
||||
extendedYConfigToExpression(yConfig, defaultReferenceLineColor)
|
||||
extendedYConfigToRLDecorationConfigExpression(yConfig, defaultReferenceLineColor)
|
||||
)
|
||||
: [],
|
||||
accessors: layer.accessors,
|
||||
|
@ -402,6 +424,7 @@ const annotationLayerToExpression = (
|
|||
|
||||
const dataLayerToExpression = (
|
||||
layer: ValidXYDataLayerConfig,
|
||||
yAxisConfigs: AxisConfig[],
|
||||
datasourceLayer: DatasourcePublicAPI,
|
||||
metadata: Record<string, Record<string, OperationMetadata | null>>,
|
||||
paletteService: PaletteRegistry,
|
||||
|
@ -418,6 +441,12 @@ const dataLayerToExpression = (
|
|||
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 {
|
||||
type: 'expression',
|
||||
chain: [
|
||||
|
@ -430,11 +459,16 @@ const dataLayerToExpression = (
|
|||
xAccessor: layer.xAccessor ? [layer.xAccessor] : [],
|
||||
xScaleType: [getScaleType(metadata[layer.layerId][layer.xAccessor], ScaleType.Linear)],
|
||||
isHistogram: [isHistogramDimension],
|
||||
isPercentage: isPercentage ? [isPercentage] : [],
|
||||
isStacked: isStacked ? [isStacked] : [],
|
||||
isHorizontal: isHorizontal ? [isHorizontal] : [],
|
||||
splitAccessor: layer.collapseFn || !layer.splitAccessor ? [] : [layer.splitAccessor],
|
||||
yConfig: layer.yConfig
|
||||
? layer.yConfig.map((yConfig) => yConfigToExpression(yConfig))
|
||||
decorations: layer.yConfig
|
||||
? layer.yConfig.map((yConfig) =>
|
||||
yConfigToDataDecorationConfigExpression(yConfig, yAxisConfigs)
|
||||
)
|
||||
: [],
|
||||
seriesType: [layer.seriesType],
|
||||
seriesType: [seriesType],
|
||||
accessors: layer.accessors,
|
||||
columnToLabel: [JSON.stringify(columnToLabel)],
|
||||
...(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 {
|
||||
type: 'expression',
|
||||
chain: [
|
||||
{
|
||||
type: 'function',
|
||||
function: 'yConfig',
|
||||
function: 'dataDecorationConfig',
|
||||
arguments: {
|
||||
axisId: axisId ? [axisId] : [],
|
||||
forAccessor: [yConfig.forAccessor],
|
||||
axisMode: yConfig.axisMode ? [yConfig.axisMode] : [],
|
||||
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 {
|
||||
type: 'expression',
|
||||
chain: [
|
||||
{
|
||||
type: 'function',
|
||||
function: 'extendedYConfig',
|
||||
function: 'referenceLineDecorationConfig',
|
||||
arguments: {
|
||||
forAccessor: [yConfig.forAccessor],
|
||||
axisMode: yConfig.axisMode ? [yConfig.axisMode] : [],
|
||||
position: yConfig.axisMode ? [yConfig.axisMode] : [],
|
||||
color: yConfig.color ? [yConfig.color] : defaultColor ? [defaultColor] : [],
|
||||
lineStyle: [yConfig.lineStyle || 'solid'],
|
||||
lineWidth: [yConfig.lineWidth || 1],
|
||||
|
|
|
@ -6,20 +6,20 @@
|
|||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { $Values } from '@kbn/utility-types';
|
||||
import type { PaletteOutput } from '@kbn/coloring';
|
||||
import type {
|
||||
SeriesType,
|
||||
LegendConfig,
|
||||
AxisExtentConfig,
|
||||
XYCurveType,
|
||||
AxesSettingsConfig,
|
||||
FittingFunction,
|
||||
LabelsOrientationConfig,
|
||||
EndValue,
|
||||
ExtendedYConfig,
|
||||
YConfig,
|
||||
YScaleType,
|
||||
XScaleType,
|
||||
LineStyle,
|
||||
IconPosition,
|
||||
FillStyle,
|
||||
YAxisConfig,
|
||||
} from '@kbn/expression-xy-plugin/common';
|
||||
import { EventAnnotationConfig } from '@kbn/event-annotation-plugin/common';
|
||||
import { LensIconChartArea } from '../assets/chart_area';
|
||||
|
@ -36,6 +36,56 @@ import { LensIconChartLine } from '../assets/chart_line';
|
|||
import type { VisualizationType, Suggestion } from '../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 {
|
||||
layerId: string;
|
||||
accessors: string[];
|
||||
|
@ -55,7 +105,7 @@ export interface XYDataLayerConfig {
|
|||
export interface XYReferenceLineLayerConfig {
|
||||
layerId: string;
|
||||
accessors: string[];
|
||||
yConfig?: ExtendedYConfig[];
|
||||
yConfig?: YConfig[];
|
||||
layerType: 'referenceLine';
|
||||
}
|
||||
|
||||
|
|
|
@ -15,9 +15,9 @@ import type {
|
|||
XYLayerConfig,
|
||||
XYDataLayerConfig,
|
||||
XYReferenceLineLayerConfig,
|
||||
SeriesType,
|
||||
} from './types';
|
||||
import { createDatatableUtilitiesMock } from '@kbn/data-plugin/common/mocks';
|
||||
import type { SeriesType } from '@kbn/expression-xy-plugin/common';
|
||||
import { layerTypes } from '../../common';
|
||||
import { createMockDatasource, createMockFramePublicAPI } from '../mocks';
|
||||
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 { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public';
|
||||
import { VIS_EVENT_TO_TRIGGER } from '@kbn/visualizations-plugin/public';
|
||||
import {
|
||||
FillStyle,
|
||||
SeriesType,
|
||||
YAxisMode,
|
||||
ExtendedYConfig,
|
||||
} from '@kbn/expression-xy-plugin/common';
|
||||
import { FillStyle } from '@kbn/expression-xy-plugin/common';
|
||||
import { getSuggestions } from './xy_suggestions';
|
||||
import { XyToolbar } from './xy_config_panel';
|
||||
import { DimensionEditor } from './xy_config_panel/dimension_editor';
|
||||
import { LayerHeader } from './xy_config_panel/layer_header';
|
||||
import { Visualization, AccessorConfig, FramePublicAPI } from '../types';
|
||||
import { State, visualizationTypes, XYSuggestion, XYLayerConfig, XYDataLayerConfig } from './types';
|
||||
import type { Visualization, AccessorConfig, FramePublicAPI } from '../types';
|
||||
import {
|
||||
State,
|
||||
visualizationTypes,
|
||||
XYSuggestion,
|
||||
XYLayerConfig,
|
||||
XYDataLayerConfig,
|
||||
YConfig,
|
||||
YAxisMode,
|
||||
SeriesType,
|
||||
} from './types';
|
||||
import { layerTypes } from '../../common';
|
||||
import { isHorizontalChart } from './state_helpers';
|
||||
import { toExpression, toPreviewExpression, getSortedAccessors } from './to_expression';
|
||||
|
@ -360,7 +364,7 @@ export const getXyVisualization = ({
|
|||
}
|
||||
const isReferenceLine = metrics.some((metric) => metric.agg === 'static_value');
|
||||
const axisMode = axisPosition as YAxisMode;
|
||||
const yConfig = metrics.map<ExtendedYConfig>((metric, idx) => {
|
||||
const yConfig = metrics.map<YConfig>((metric, idx) => {
|
||||
return {
|
||||
color: metric.color,
|
||||
forAccessor: metric.accessor ?? foundLayer.accessors[idx],
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { uniq } from 'lodash';
|
||||
import { SeriesType } from '@kbn/expression-xy-plugin/common';
|
||||
import { DatasourceLayers, OperationMetadata, VisualizationType } from '../types';
|
||||
import {
|
||||
State,
|
||||
|
@ -17,6 +16,7 @@ import {
|
|||
XYLayerConfig,
|
||||
XYDataLayerConfig,
|
||||
XYReferenceLineLayerConfig,
|
||||
SeriesType,
|
||||
} from './types';
|
||||
import { isHorizontalChart } from './state_helpers';
|
||||
import { layerTypes } from '..';
|
||||
|
|
|
@ -16,9 +16,9 @@ import {
|
|||
} from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
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 { XYLayerConfig } from '../types';
|
||||
import { XYLayerConfig, AxesSettingsConfig } from '../types';
|
||||
import {
|
||||
ToolbarPopover,
|
||||
useDebouncedValue,
|
||||
|
|
|
@ -10,9 +10,8 @@ import { i18n } from '@kbn/i18n';
|
|||
import { EuiButtonGroup, EuiFormRow, htmlIdGenerator } from '@elastic/eui';
|
||||
import type { PaletteRegistry } from '@kbn/coloring';
|
||||
import type { DatatableUtilitiesService } from '@kbn/data-plugin/common';
|
||||
import { YAxisMode, ExtendedYConfig } from '@kbn/expression-xy-plugin/common';
|
||||
import type { VisualizationDimensionEditorProps } from '../../types';
|
||||
import { State, XYState, XYDataLayerConfig } from '../types';
|
||||
import { State, XYState, XYDataLayerConfig, YConfig, YAxisMode } from '../types';
|
||||
import { FormatFactory } from '../../../common';
|
||||
import { getSeriesColor, isHorizontalChart } from '../state_helpers';
|
||||
import { ColorPicker } from './color_picker';
|
||||
|
@ -81,7 +80,7 @@ export function DataDimensionEditor(
|
|||
const axisMode = localYConfig?.axisMode || 'auto';
|
||||
|
||||
const setConfig = useCallback(
|
||||
(yConfig: Partial<ExtendedYConfig> | undefined) => {
|
||||
(yConfig: Partial<YConfig> | undefined) => {
|
||||
if (yConfig == null) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -9,10 +9,10 @@ import React, { memo, useCallback, useMemo, useState } from 'react';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { Position, ScaleType } from '@elastic/charts';
|
||||
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 type { VisualizationToolbarProps, FramePublicAPI } from '../../types';
|
||||
import { State, XYState } from '../types';
|
||||
import { State, XYState, AxesSettingsConfig } from '../types';
|
||||
import { isHorizontalChart } from '../state_helpers';
|
||||
import { hasNumericHistogramDimension, LegendSettingsPopover } from '../../shared_components';
|
||||
import { AxisSettingsPopover } from './axis_settings_popover';
|
||||
|
|
|
@ -8,10 +8,9 @@
|
|||
import React, { useState } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
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 type { VisualizationLayerWidgetProps, VisualizationType } from '../../types';
|
||||
import { State, visualizationTypes } from '../types';
|
||||
import { State, visualizationTypes, SeriesType } from '../types';
|
||||
import { isHorizontalChart, isHorizontalSeries } from '../state_helpers';
|
||||
import { trackUiEvent } from '../../lens_ui_telemetry';
|
||||
import { StaticHeader } from '../../shared_components';
|
||||
|
|
|
@ -9,9 +9,9 @@ import React, { useCallback } from 'react';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { EuiButtonGroup, EuiFormRow } from '@elastic/eui';
|
||||
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 { State, XYState, XYReferenceLineLayerConfig } from '../../types';
|
||||
import { State, XYState, XYReferenceLineLayerConfig, YConfig } from '../../types';
|
||||
import { FormatFactory } from '../../../../common';
|
||||
|
||||
import { ColorPicker } from '../color_picker';
|
||||
|
@ -52,7 +52,7 @@ export const ReferenceLinePanel = (
|
|||
);
|
||||
|
||||
const setConfig = useCallback(
|
||||
(yConfig: Partial<ExtendedYConfig> | undefined) => {
|
||||
(yConfig: Partial<YConfig> | undefined) => {
|
||||
if (yConfig == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ export const ReferenceLinePanel = (
|
|||
|
||||
interface LabelConfigurationOptions {
|
||||
isHorizontal: boolean;
|
||||
axisMode: ExtendedYConfig['axisMode'];
|
||||
axisMode: YConfig['axisMode'];
|
||||
}
|
||||
|
||||
function getFillPositionOptions({ isHorizontal, axisMode }: LabelConfigurationOptions) {
|
||||
|
@ -154,8 +154,8 @@ export const FillSetting = ({
|
|||
setConfig,
|
||||
isHorizontal,
|
||||
}: {
|
||||
currentConfig?: ExtendedYConfig;
|
||||
setConfig: (yConfig: Partial<ExtendedYConfig> | undefined) => void;
|
||||
currentConfig?: YConfig;
|
||||
setConfig: (yConfig: Partial<YConfig> | undefined) => void;
|
||||
isHorizontal: boolean;
|
||||
}) => {
|
||||
return (
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
import React from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
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 { hasIcon, IconSelect, IconSet } from './icon_select';
|
||||
|
|
|
@ -9,7 +9,6 @@ import { i18n } from '@kbn/i18n';
|
|||
import { partition } from 'lodash';
|
||||
import { Position } from '@elastic/charts';
|
||||
import type { PaletteOutput } from '@kbn/coloring';
|
||||
import type { SeriesType } from '@kbn/expression-xy-plugin/common';
|
||||
import {
|
||||
SuggestionRequest,
|
||||
VisualizationSuggestion,
|
||||
|
@ -17,7 +16,14 @@ import {
|
|||
TableSuggestion,
|
||||
TableChangeType,
|
||||
} from '../types';
|
||||
import { State, XYState, visualizationTypes, XYLayerConfig, XYDataLayerConfig } from './types';
|
||||
import {
|
||||
State,
|
||||
XYState,
|
||||
visualizationTypes,
|
||||
XYLayerConfig,
|
||||
XYDataLayerConfig,
|
||||
SeriesType,
|
||||
} from './types';
|
||||
import { layerTypes } from '../../common';
|
||||
import { getIconForSeries } from './state_helpers';
|
||||
import { getDataLayers, isDataLayer } from './visualization_helpers';
|
||||
|
|
|
@ -29,6 +29,7 @@ import {
|
|||
TypedLensByValueInput,
|
||||
XYCurveType,
|
||||
XYState,
|
||||
YAxisMode,
|
||||
} from '@kbn/lens-plugin/public';
|
||||
import type { DataView } from '@kbn/data-views-plugin/common';
|
||||
import { PersistableFilter } from '@kbn/lens-plugin/common';
|
||||
|
@ -900,8 +901,8 @@ export class LensAttributes {
|
|||
this.layerConfigs[0].indexPattern.fieldFormatMap[
|
||||
this.layerConfigs[0].selectedMetricField
|
||||
]?.id
|
||||
? 'left'
|
||||
: 'right',
|
||||
? ('left' as YAxisMode)
|
||||
: ('right' as YAxisMode),
|
||||
},
|
||||
],
|
||||
xAccessor: `x-axis-column-layer${index}`,
|
||||
|
|
|
@ -13,7 +13,7 @@ import type {
|
|||
FieldBasedIndexPatternColumn,
|
||||
SeriesType,
|
||||
OperationType,
|
||||
ExtendedYConfig,
|
||||
YConfig,
|
||||
} from '@kbn/lens-plugin/public';
|
||||
|
||||
import type { PersistableFilter } from '@kbn/lens-plugin/common';
|
||||
|
@ -84,7 +84,7 @@ export interface SeriesConfig {
|
|||
hasOperationType: boolean;
|
||||
palette?: PaletteOutput;
|
||||
yTitle?: string;
|
||||
yConfig?: ExtendedYConfig[];
|
||||
yConfig?: YConfig[];
|
||||
query?: { query: string; language: 'kuery' };
|
||||
}
|
||||
|
||||
|
|
|
@ -3402,10 +3402,6 @@
|
|||
"expressionXY.axisExtentConfig.help": "Configurer les étendues d’axe du graphique xy",
|
||||
"expressionXY.axisExtentConfig.lowerBound.help": "Limite infé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.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",
|
||||
|
@ -3417,15 +3413,6 @@
|
|||
"expressionXY.dataLayer.splitAccessor.help": "Colonne selon laquelle effectuer la division",
|
||||
"expressionXY.dataLayer.xAccessor.help": "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.filterOptionsLegend": "{legendDataLabel}, options de filtre",
|
||||
"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.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.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.iconSelect.alertIconLabel": "Alerte",
|
||||
"expressionXY.xyChart.iconSelect.asteriskIconLabel": "Astérisque",
|
||||
|
@ -3463,39 +3445,20 @@
|
|||
"expressionXY.xyChart.iconSelect.tagIconLabel": "Balise",
|
||||
"expressionXY.xyChart.iconSelect.triangleIconLabel": "Triangle",
|
||||
"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.endValue.help": "Valeur de fin",
|
||||
"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.gridlinesVisibilitySettings.help": "Afficher le quadrillage des axes X et 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.labelsOrientation.help": "Définit la rotation des étiquettes des axes",
|
||||
"expressionXY.layeredXyVis.layers.help": "Calques de série visuelle",
|
||||
"expressionXY.xyVis.legend.help": "Configurez la légende du graphique.",
|
||||
"expressionXY.xyVis.logDatatable.breakDown": "Répartir par",
|
||||
"expressionXY.xyVis.logDatatable.metric": "Axe vertical",
|
||||
"expressionXY.xyVis.logDatatable.x": "Axe horizontal",
|
||||
"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.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.bytesFormatText": "{numeralFormatLink} par défaut pour le format \"octets\"",
|
||||
"fieldFormats.advancedSettings.format.bytesFormatTitle": "Format octets",
|
||||
|
|
|
@ -3501,10 +3501,6 @@
|
|||
"expressionXY.axisExtentConfig.help": "xyグラフの軸範囲を構成",
|
||||
"expressionXY.axisExtentConfig.lowerBound.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.layer.columnToLabel.help": "ラベリングする列IDのJSONキー値のペア",
|
||||
"expressionXY.dataLayer.help": "xyグラフでレイヤーを構成",
|
||||
|
@ -3516,15 +3512,6 @@
|
|||
"expressionXY.dataLayer.splitAccessor.help": "分割の基準となる列",
|
||||
"expressionXY.dataLayer.xAccessor.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.filterOptionsLegend": "{legendDataLabel}、フィルターオプション",
|
||||
"expressionXY.legend.filterOutValueButtonAriaLabel": "値を除外",
|
||||
|
@ -3541,11 +3528,6 @@
|
|||
"expressionXY.legendConfig.verticalAlignment.help": "凡例がグラフ内に表示されるときに凡例の縦の配置を指定します。",
|
||||
"expressionXY.referenceLineLayer.accessors.help": "y軸に表示する列。",
|
||||
"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.iconSelect.alertIconLabel": "アラート",
|
||||
"expressionXY.xyChart.iconSelect.asteriskIconLabel": "アスタリスク",
|
||||
|
@ -3562,39 +3544,20 @@
|
|||
"expressionXY.xyChart.iconSelect.tagIconLabel": "タグ",
|
||||
"expressionXY.xyChart.iconSelect.triangleIconLabel": "三角形",
|
||||
"expressionXY.xyVis.ariaLabel.help": "xyグラフのariaラベルを指定します",
|
||||
"expressionXY.xyVis.axisTitlesVisibilitySettings.help": "xおよびy軸のタイトルを表示",
|
||||
"expressionXY.xyVis.curveType.help": "折れ線グラフで曲線タイプをレンダリングする方法を定義します",
|
||||
"expressionXY.xyVis.endValue.help": "終了値",
|
||||
"expressionXY.xyVis.fillOpacity.help": "エリアグラフの塗りつぶしの透明度を定義",
|
||||
"expressionXY.xyVis.fittingFunction.help": "欠測値の処理方法を定義",
|
||||
"expressionXY.xyVis.gridlinesVisibilitySettings.help": "xおよびy軸のグリッド線を表示",
|
||||
"expressionXY.xyVis.help": "X/Y チャート",
|
||||
"expressionXY.xyVis.hideEndzones.help": "部分データの終了ゾーンマーカーを非表示",
|
||||
"expressionXY.xyVis.labelsOrientation.help": "軸ラベルの回転を定義します",
|
||||
"expressionXY.layeredXyVis.layers.help": "視覚的な系列のレイヤー",
|
||||
"expressionXY.xyVis.legend.help": "チャートの凡例を構成します。",
|
||||
"expressionXY.xyVis.logDatatable.breakDown": "内訳の基準",
|
||||
"expressionXY.xyVis.logDatatable.metric": "縦軸",
|
||||
"expressionXY.xyVis.logDatatable.x": "横軸",
|
||||
"expressionXY.xyVis.renderer.help": "X/Y チャートを再レンダリング",
|
||||
"expressionXY.xyVis.tickLabelsVisibilitySettings.help": "xおよびy軸の目盛ラベルを表示",
|
||||
"expressionXY.xyVis.valueLabels.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.bytesFormatText": "「バイト」フォーマットのデフォルト{numeralFormatLink}です",
|
||||
"fieldFormats.advancedSettings.format.bytesFormatTitle": "バイトフォーマット",
|
||||
|
|
|
@ -3506,10 +3506,6 @@
|
|||
"expressionXY.axisExtentConfig.help": "配置 xy 图表的轴范围",
|
||||
"expressionXY.axisExtentConfig.lowerBound.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.layer.columnToLabel.help": "要标记的列 ID 的 JSON 键值对",
|
||||
"expressionXY.dataLayer.help": "配置 xy 图表中的图层",
|
||||
|
@ -3521,15 +3517,6 @@
|
|||
"expressionXY.dataLayer.splitAccessor.help": "拆分要依据的列",
|
||||
"expressionXY.dataLayer.xAccessor.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.filterOptionsLegend": "{legendDataLabel}, 筛选选项",
|
||||
"expressionXY.legend.filterOutValueButtonAriaLabel": "筛除值",
|
||||
|
@ -3546,11 +3533,6 @@
|
|||
"expressionXY.legendConfig.verticalAlignment.help": "指定图例显示在图表内时垂直对齐。",
|
||||
"expressionXY.referenceLineLayer.accessors.help": "要在 y 轴上显示的列。",
|
||||
"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.iconSelect.alertIconLabel": "告警",
|
||||
"expressionXY.xyChart.iconSelect.asteriskIconLabel": "星号",
|
||||
|
@ -3567,39 +3549,20 @@
|
|||
"expressionXY.xyChart.iconSelect.tagIconLabel": "标签",
|
||||
"expressionXY.xyChart.iconSelect.triangleIconLabel": "三角形",
|
||||
"expressionXY.xyVis.ariaLabel.help": "指定 xy 图表的 aria 标签",
|
||||
"expressionXY.xyVis.axisTitlesVisibilitySettings.help": "显示 x 和 y 轴标题",
|
||||
"expressionXY.xyVis.curveType.help": "定义为折线图渲染曲线类型的方式",
|
||||
"expressionXY.xyVis.endValue.help": "结束值",
|
||||
"expressionXY.xyVis.fillOpacity.help": "定义面积图填充透明度",
|
||||
"expressionXY.xyVis.fittingFunction.help": "定义处理缺失值的方式",
|
||||
"expressionXY.xyVis.gridlinesVisibilitySettings.help": "显示 x 和 y 轴网格线",
|
||||
"expressionXY.xyVis.help": "X/Y 图表",
|
||||
"expressionXY.xyVis.hideEndzones.help": "隐藏部分数据的末日区域标记",
|
||||
"expressionXY.xyVis.labelsOrientation.help": "定义轴标签的旋转",
|
||||
"expressionXY.layeredXyVis.layers.help": "可视序列的图层",
|
||||
"expressionXY.xyVis.legend.help": "配置图表图例。",
|
||||
"expressionXY.xyVis.logDatatable.breakDown": "细分方式",
|
||||
"expressionXY.xyVis.logDatatable.metric": "垂直轴",
|
||||
"expressionXY.xyVis.logDatatable.x": "水平轴",
|
||||
"expressionXY.xyVis.renderer.help": "X/Y 图表呈现器",
|
||||
"expressionXY.xyVis.tickLabelsVisibilitySettings.help": "显示 x 和 y 轴刻度标签",
|
||||
"expressionXY.xyVis.valueLabels.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.bytesFormatText": "“字节”格式的默认{numeralFormatLink}",
|
||||
"fieldFormats.advancedSettings.format.bytesFormatTitle": "字节格式",
|
||||
|
|
|
@ -274,13 +274,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
});
|
||||
|
||||
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
|
||||
await testSubjects.click('lnsshowyLeftAxisGridlines');
|
||||
|
||||
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 () => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue