mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[XY] Support vis_dimension
type for accessors (#129612)
* added xy plugin. * Added expressionXY limits. * Added xy expression functions to the expression_xy plugin. * Moved xy to a separate plugin. * Small refactoring. * Fixed types. * Fixed import of scss. * Fixed imports. * Added required plugins. * Fixed import * Fixed types. * Changed expression names. * Fixed bugs, caused by the refactoring process. * Fixed lens snapshots. * Removed new line. * Fixed xy_chart tests. * Added lazy loading for xy chart. * Fixed xy chart test. * Fixed broken chart selectors. * Fixed dashboard tests. * dashboard test fixed. * Fixed heatmap vis. * Smokescreen test fixed. * more fixes. * async dashboard tests fixed. * Fixed xy smokescreen tests selectors. * fixed show_underlying_data tests. * Updated snapshots. * updated limits. * Fixed more selectors * Fixed persistent context test. * Fixed some more test at ml. * Fixed types and imports * Fixed handlers.inspectorAdapters.tables.logDatatable * Fixed logDatatable * Translations fixed. * Fixed "Visualize App ... cleans filters and query" test. cleans filters and query * Fixed "lens disable auto-apply tests" test. * Updated dashboard tests. * Fixed translations. * Expression tests fixed. * Cleaned up expression_xy. * cleaned up lens xy_visualization. * fixed more tests. * Fix of tsvb. * Fixed more tests. * Fixed xy chart limits. * Fixed new tests. * Fixed types. * Added extended layers expressions. * Added support of tables at layers. * Fixed tests. * Fixed more tests. * Fixed lens types. * Added tables to layers. * Checks fixed. * updated tests. * Fixed types. * First try to fix merge conflicts. * Fixed annotatations. * Fixed types. * Updated snapshots * Fixed tests. * Fixed dependencies. * Fixed i18n. * Moved XY state types to lens. * Fixed more types. * Update src/plugins/chart_expressions/expression_xy/README.md Co-authored-by: Marta Bondyra <marta.bondyra@gmail.com> * [CI] Auto-commit changed files from 'node scripts/build_plugin_list_docs' * Removed yConfig from *Layers types * Fixed styles. * Fixed types. * Removed not used utils and styles. * Fixed types and tests. * updated size. * Added right behavior, related to the tables, comming from the expression. * Fixed reference lines. * Fixed jsdoc. * Added annotations to layeredXyVIs. * Fixed limits. * Refactored the implementation to be reusable. * Fixed undefined layers. * Fixed empty arrays problems. * Fixed input translations and removed not used arguments. * Fixed missing required args error, and added required to arguments. * Simplified expression configuration. * Added strict to all the expressions. * refactored code, according to the nit. * Support visdimension type for accessors in data_layer and reference_line_layer * Fix checks * Moved dataLayer to the separate component. * Fixed jest tests. * Fixed tests. * Some updates * Refactored dataLayers helpers and xy_chart. * More fixes of the expression Added extendedYConfig for dataLayers. Added yConfig for referenceLineLayers. Fixed undefined id at tooltip. * Fixed tests and snapshots. * Icons at annotations and reference lines are strict. * Fix CI * axis extent validation added. * Added checks to the legend config. * fillOpacity usage validation is added. * Fixed valueLabels argument options. Removed not used. Added validation for usage. * Removed not used tests and imports. * Fixed valueLabels and added migrations. * Fixed type checks. * Added test for the migrations. * Fixed imports. * Fixed types * Fixed i18n checks. # Conflicts: # src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx * Fixed imports and types. * [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' * Update src/plugins/chart_expressions/expression_xy/common/expression_functions/extended_annotation_layer.ts Co-authored-by: Marta Bondyra <marta.bondyra@gmail.com> * Removed extra extends. * Update src/plugins/chart_expressions/expression_xy/common/expression_functions/annotation_layer.ts Co-authored-by: Marta Bondyra <marta.bondyra@gmail.com> * Added guard. * Fixed the code duplication. * Removed table from the annotation layer. * Changed the `convertActiveDataFromIndexesToLayers` location. * Added tests for convertActiveDataFromIndexesToLayers * Reduced the bundle size a little bit. * Reused strings and args. * Refactored expression functions. Added asynchronous behavior. * Fixed tests. * Updated limits. * Updated the limit. * Fixed types. * fixed types. * Turned back layerIds. * Removed convertActiveData from Lens. * Added test to the layerIds generator. * Fixed types. * Fixed problems with resetting of the inspector. * Fixed migrations. * Removed types. * Removed tones of `areFormatted` calculations. * Fixed `isTimeViz` and `isHistogramViz` by replacing filteredLayers with dataLayers. * Removed referenceLineLayers from the `groupAxesByType` fn. * Added validation to the layeredXyVis. * Fixed extent validation. * Removed comments. * Reduced limit. * Added optimizations. * Fixed floatingColumns error. * Fixed types. * Updated limits. * Turned back extent validation. * Fixed stacked error. * Parallelized async import of functions. * Decreased the complexity of the algorithm. * Fixed snapshot. * Some fixes * Fix checks * Fixed types * Fix types * [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' * Added validation to the accessors. * Validated accessors at the referenceLineLayer and extendedReferenceLineLayer. * Fixed some style issues. * Fixed imports. * One more fix of import. * [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' * Move extended data layer fn in async file * Some improvements * Fix checks * Fix validation 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
3177d0ec22
commit
dd2a9b5425
22 changed files with 299 additions and 132 deletions
|
@ -16,16 +16,15 @@ type CommonDataLayerFnArgs = {
|
|||
[key in keyof CommonDataLayerArgs]: ArgumentType<CommonDataLayerArgs[key]>;
|
||||
};
|
||||
|
||||
export const commonDataLayerArgs: CommonDataLayerFnArgs = {
|
||||
export const commonDataLayerArgs: Omit<
|
||||
CommonDataLayerFnArgs,
|
||||
'accessors' | 'xAccessor' | 'splitAccessor'
|
||||
> = {
|
||||
hide: {
|
||||
types: ['boolean'],
|
||||
default: false,
|
||||
help: strings.getHideHelp(),
|
||||
},
|
||||
xAccessor: {
|
||||
types: ['string'],
|
||||
help: strings.getXAccessorHelp(),
|
||||
},
|
||||
seriesType: {
|
||||
aliases: ['_'],
|
||||
types: ['string'],
|
||||
|
@ -51,15 +50,6 @@ export const commonDataLayerArgs: CommonDataLayerFnArgs = {
|
|||
default: YScaleTypes.LINEAR,
|
||||
strict: true,
|
||||
},
|
||||
splitAccessor: {
|
||||
types: ['string'],
|
||||
help: strings.getSplitAccessorHelp(),
|
||||
},
|
||||
accessors: {
|
||||
types: ['string'],
|
||||
help: strings.getAccessorsHelp(),
|
||||
multi: true,
|
||||
},
|
||||
yConfig: {
|
||||
types: [Y_CONFIG],
|
||||
help: strings.getYConfigHelp(),
|
||||
|
|
|
@ -12,12 +12,7 @@ import { ReferenceLineLayerFn, ExtendedReferenceLineLayerFn } from '../types';
|
|||
|
||||
type CommonReferenceLineLayerFn = ReferenceLineLayerFn | ExtendedReferenceLineLayerFn;
|
||||
|
||||
export const commonReferenceLineLayerArgs: CommonReferenceLineLayerFn['args'] = {
|
||||
accessors: {
|
||||
types: ['string'],
|
||||
help: strings.getRLAccessorsHelp(),
|
||||
multi: true,
|
||||
},
|
||||
export const commonReferenceLineLayerArgs: Omit<CommonReferenceLineLayerFn['args'], 'accessors'> = {
|
||||
yConfig: {
|
||||
types: [EXTENDED_Y_CONFIG],
|
||||
help: strings.getRLYConfigHelp(),
|
||||
|
|
|
@ -7,10 +7,9 @@
|
|||
*/
|
||||
|
||||
import { ExtendedDataLayerFn } from '../types';
|
||||
import { EXTENDED_DATA_LAYER, LayerTypes } from '../constants';
|
||||
import { EXTENDED_DATA_LAYER } from '../constants';
|
||||
import { strings } from '../i18n';
|
||||
import { commonDataLayerArgs } from './common_data_layer_args';
|
||||
import { getAccessors } from '../helpers';
|
||||
|
||||
export const extendedDataLayerFunction: ExtendedDataLayerFn = {
|
||||
name: EXTENDED_DATA_LAYER,
|
||||
|
@ -20,6 +19,19 @@ export const extendedDataLayerFunction: ExtendedDataLayerFn = {
|
|||
inputTypes: ['datatable'],
|
||||
args: {
|
||||
...commonDataLayerArgs,
|
||||
xAccessor: {
|
||||
types: ['string'],
|
||||
help: strings.getXAccessorHelp(),
|
||||
},
|
||||
splitAccessor: {
|
||||
types: ['string'],
|
||||
help: strings.getSplitAccessorHelp(),
|
||||
},
|
||||
accessors: {
|
||||
types: ['string'],
|
||||
help: strings.getAccessorsHelp(),
|
||||
multi: true,
|
||||
},
|
||||
table: {
|
||||
types: ['datatable'],
|
||||
help: strings.getTableHelp(),
|
||||
|
@ -29,14 +41,8 @@ export const extendedDataLayerFunction: ExtendedDataLayerFn = {
|
|||
help: strings.getLayerIdHelp(),
|
||||
},
|
||||
},
|
||||
fn(input, args) {
|
||||
const table = args.table ?? input;
|
||||
return {
|
||||
type: EXTENDED_DATA_LAYER,
|
||||
...args,
|
||||
...getAccessors(args, table),
|
||||
layerType: LayerTypes.DATA,
|
||||
table,
|
||||
};
|
||||
async fn(input, args, context) {
|
||||
const { extendedDataLayerFn } = await import('./extended_data_layer_fn');
|
||||
return await extendedDataLayerFn(input, args, context);
|
||||
},
|
||||
};
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* 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 { validateAccessor } from '@kbn/visualizations-plugin/common/utils';
|
||||
import { ExtendedDataLayerArgs, ExtendedDataLayerFn } from '../types';
|
||||
import { EXTENDED_DATA_LAYER, LayerTypes } from '../constants';
|
||||
import { getAccessors } from '../helpers';
|
||||
|
||||
export const extendedDataLayerFn: ExtendedDataLayerFn['fn'] = async (data, args, context) => {
|
||||
const table = args.table ?? data;
|
||||
const accessors = getAccessors<string, ExtendedDataLayerArgs>(args, table);
|
||||
|
||||
validateAccessor(accessors.xAccessor, table.columns);
|
||||
validateAccessor(accessors.splitAccessor, table.columns);
|
||||
accessors.accessors.forEach((accessor) => validateAccessor(accessor, table.columns));
|
||||
|
||||
return {
|
||||
type: EXTENDED_DATA_LAYER,
|
||||
...args,
|
||||
layerType: LayerTypes.DATA,
|
||||
...accessors,
|
||||
table,
|
||||
};
|
||||
};
|
|
@ -6,6 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { validateAccessor } from '@kbn/visualizations-plugin/common/utils';
|
||||
import { LayerTypes, EXTENDED_REFERENCE_LINE_LAYER } from '../constants';
|
||||
import { ExtendedReferenceLineLayerFn } from '../types';
|
||||
import { strings } from '../i18n';
|
||||
|
@ -19,6 +20,11 @@ export const extendedReferenceLineLayerFunction: ExtendedReferenceLineLayerFn =
|
|||
inputTypes: ['datatable'],
|
||||
args: {
|
||||
...commonReferenceLineLayerArgs,
|
||||
accessors: {
|
||||
types: ['string'],
|
||||
help: strings.getRLAccessorsHelp(),
|
||||
multi: true,
|
||||
},
|
||||
table: {
|
||||
types: ['datatable'],
|
||||
help: strings.getTableHelp(),
|
||||
|
@ -29,12 +35,16 @@ export const extendedReferenceLineLayerFunction: ExtendedReferenceLineLayerFn =
|
|||
},
|
||||
},
|
||||
fn(input, args) {
|
||||
const table = args.table ?? input;
|
||||
const accessors = args.accessors ?? [];
|
||||
accessors.forEach((accessor) => validateAccessor(accessor, table.columns));
|
||||
|
||||
return {
|
||||
type: EXTENDED_REFERENCE_LINE_LAYER,
|
||||
...args,
|
||||
accessors: args.accessors ?? [],
|
||||
layerType: LayerTypes.REFERENCELINE,
|
||||
table: args.table ?? input,
|
||||
table,
|
||||
};
|
||||
},
|
||||
};
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { validateAccessor } from '@kbn/visualizations-plugin/common/utils';
|
||||
import { LayerTypes, REFERENCE_LINE_LAYER } from '../constants';
|
||||
import { ReferenceLineLayerFn } from '../types';
|
||||
import { strings } from '../i18n';
|
||||
|
@ -17,13 +18,23 @@ export const referenceLineLayerFunction: ReferenceLineLayerFn = {
|
|||
type: REFERENCE_LINE_LAYER,
|
||||
help: strings.getRLHelp(),
|
||||
inputTypes: ['datatable'],
|
||||
args: { ...commonReferenceLineLayerArgs },
|
||||
args: {
|
||||
...commonReferenceLineLayerArgs,
|
||||
accessors: {
|
||||
types: ['string', 'vis_dimension'],
|
||||
help: strings.getRLAccessorsHelp(),
|
||||
multi: true,
|
||||
},
|
||||
},
|
||||
fn(table, args) {
|
||||
const accessors = args.accessors ?? [];
|
||||
accessors.forEach((accessor) => validateAccessor(accessor, table.columns));
|
||||
|
||||
return {
|
||||
type: REFERENCE_LINE_LAYER,
|
||||
...args,
|
||||
accessors: args.accessors ?? [],
|
||||
layerType: LayerTypes.REFERENCELINE,
|
||||
accessors,
|
||||
table,
|
||||
};
|
||||
},
|
||||
|
|
|
@ -20,6 +20,19 @@ export const xyVisFunction: XyVisFn = {
|
|||
args: {
|
||||
...commonXYArgs,
|
||||
...commonDataLayerArgs,
|
||||
xAccessor: {
|
||||
types: ['string', 'vis_dimension'],
|
||||
help: strings.getXAccessorHelp(),
|
||||
},
|
||||
splitAccessor: {
|
||||
types: ['string', 'vis_dimension'],
|
||||
help: strings.getSplitAccessorHelp(),
|
||||
},
|
||||
accessors: {
|
||||
types: ['string', 'vis_dimension'],
|
||||
help: strings.getAccessorsHelp(),
|
||||
multi: true,
|
||||
},
|
||||
referenceLineLayers: {
|
||||
types: [REFERENCE_LINE_LAYER],
|
||||
help: strings.getReferenceLineLayerHelp(),
|
||||
|
|
|
@ -12,6 +12,7 @@ import {
|
|||
validateAccessor,
|
||||
} from '@kbn/visualizations-plugin/common/utils';
|
||||
import type { Datatable } from '@kbn/expressions-plugin/common';
|
||||
import { ExpressionValueVisDimension } from '@kbn/visualizations-plugin/common/expression_functions';
|
||||
import { LayerTypes, XY_VIS_RENDERER, DATA_LAYER } from '../constants';
|
||||
import { appendLayerIds, getAccessors } from '../helpers';
|
||||
import { DataLayerConfigResult, XYLayerConfig, XyVisFn, XYArgs } from '../types';
|
||||
|
@ -37,7 +38,7 @@ const createDataLayer = (args: XYArgs, table: Datatable): DataLayerConfigResult
|
|||
yConfig: args.yConfig,
|
||||
layerType: LayerTypes.DATA,
|
||||
table,
|
||||
...getAccessors(args, table),
|
||||
...getAccessors<string | ExpressionValueVisDimension, XYArgs>(args, table),
|
||||
});
|
||||
|
||||
export const xyVisFn: XyVisFn['fn'] = async (data, args, handlers) => {
|
||||
|
@ -64,6 +65,10 @@ export const xyVisFn: XyVisFn['fn'] = async (data, args, handlers) => {
|
|||
|
||||
const dataLayers: DataLayerConfigResult[] = [createDataLayer(args, data)];
|
||||
|
||||
validateAccessor(dataLayers[0].xAccessor, data.columns);
|
||||
validateAccessor(dataLayers[0].splitAccessor, data.columns);
|
||||
dataLayers[0].accessors.forEach((accessor) => validateAccessor(accessor, data.columns));
|
||||
|
||||
const layers: XYLayerConfig[] = [
|
||||
...appendLayerIds(dataLayers, 'dataLayers'),
|
||||
...appendLayerIds(referenceLineLayers, 'referenceLineLayers'),
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
import { Datatable, PointSeriesColumnNames } from '@kbn/expressions-plugin/common';
|
||||
import { WithLayerId, DataLayerArgs } from '../types';
|
||||
import { WithLayerId } from '../types';
|
||||
|
||||
function isWithLayerId<T>(layer: T): layer is T & WithLayerId {
|
||||
return (layer as T & WithLayerId).layerId ? true : false;
|
||||
|
@ -27,10 +27,13 @@ export function appendLayerIds<T>(
|
|||
}));
|
||||
}
|
||||
|
||||
export function getAccessors(args: DataLayerArgs, table: Datatable) {
|
||||
let splitAccessor = args.splitAccessor;
|
||||
let xAccessor = args.xAccessor;
|
||||
let accessors = args.accessors ?? [];
|
||||
export function getAccessors<T, U extends { splitAccessor?: T; xAccessor?: T; accessors: T[] }>(
|
||||
args: U,
|
||||
table: Datatable
|
||||
) {
|
||||
let splitAccessor: T | string | undefined = args.splitAccessor;
|
||||
let xAccessor: T | string | undefined = args.xAccessor;
|
||||
let accessors: Array<T | string> = args.accessors ?? [];
|
||||
if (!splitAccessor && !xAccessor && !(accessors && accessors.length)) {
|
||||
const y = table.columns.find((column) => column.id === PointSeriesColumnNames.Y)?.id;
|
||||
xAccessor = table.columns.find((column) => column.id === PointSeriesColumnNames.X)?.id;
|
||||
|
|
|
@ -12,8 +12,7 @@ import type { PaletteOutput } from '@kbn/coloring';
|
|||
import { Datatable, ExpressionFunctionDefinition } from '@kbn/expressions-plugin';
|
||||
import { LegendSize } from '@kbn/visualizations-plugin/public';
|
||||
import { EventAnnotationOutput } from '@kbn/event-annotation-plugin/common';
|
||||
import { ExpressionValueVisDimension } from '@kbn/visualizations-plugin/common';
|
||||
|
||||
import type { ExpressionValueVisDimension } from '@kbn/visualizations-plugin/common/expression_functions';
|
||||
import {
|
||||
AxisExtentModes,
|
||||
FillStyles,
|
||||
|
@ -96,11 +95,11 @@ export interface YConfig {
|
|||
}
|
||||
|
||||
export interface DataLayerArgs {
|
||||
accessors: string[];
|
||||
accessors: Array<ExpressionValueVisDimension | string>;
|
||||
seriesType: SeriesType;
|
||||
xAccessor?: string;
|
||||
xAccessor?: string | ExpressionValueVisDimension;
|
||||
hide?: boolean;
|
||||
splitAccessor?: string;
|
||||
splitAccessor?: string | ExpressionValueVisDimension;
|
||||
columnToLabel?: string; // Actually a JSON key-value pair
|
||||
yScaleType: YScaleType;
|
||||
xScaleType: XScaleType;
|
||||
|
@ -276,7 +275,7 @@ export type ExtendedAnnotationLayerConfigResult = ExtendedAnnotationLayerArgs &
|
|||
};
|
||||
|
||||
export interface ReferenceLineLayerArgs {
|
||||
accessors: string[];
|
||||
accessors: Array<ExpressionValueVisDimension | string>;
|
||||
columnToLabel?: string;
|
||||
yConfig?: ExtendedYConfigResult[];
|
||||
}
|
||||
|
@ -385,7 +384,7 @@ export type ExtendedDataLayerFn = ExpressionFunctionDefinition<
|
|||
typeof EXTENDED_DATA_LAYER,
|
||||
Datatable,
|
||||
ExtendedDataLayerArgs,
|
||||
ExtendedDataLayerConfigResult
|
||||
Promise<ExtendedDataLayerConfigResult>
|
||||
>;
|
||||
|
||||
export type ReferenceLineLayerFn = ExpressionFunctionDefinition<
|
||||
|
|
|
@ -34,7 +34,6 @@ import type {
|
|||
CommonXYAnnotationLayerConfig,
|
||||
CollectiveConfig,
|
||||
} from '../../common';
|
||||
|
||||
import { AnnotationIcon, hasIcon, Marker, MarkerBody } from '../helpers';
|
||||
import { mapVerticalToHorizontalPlacement, LINES_MARKER_SIZE } from '../helpers';
|
||||
|
||||
|
|
|
@ -15,6 +15,8 @@ import {
|
|||
import React, { FC } from 'react';
|
||||
import { PaletteRegistry } from '@kbn/coloring';
|
||||
import { FormatFactory } from '@kbn/field-formats-plugin/common';
|
||||
import { getAccessorByDimension } from '@kbn/visualizations-plugin/common/utils';
|
||||
|
||||
import {
|
||||
CommonXYDataLayerConfig,
|
||||
EndValue,
|
||||
|
@ -71,7 +73,8 @@ export const DataLayers: FC<Props> = ({
|
|||
<>
|
||||
{layers.flatMap((layer) =>
|
||||
layer.accessors.map((accessor, accessorIndex) => {
|
||||
const { seriesType, columnToLabel, layerId } = layer;
|
||||
const { seriesType, columnToLabel, layerId, table } = layer;
|
||||
const yColumnId = getAccessorByDimension(accessor, table.columns);
|
||||
const columnToLabelMap: Record<string, string> = columnToLabel
|
||||
? JSON.parse(columnToLabel)
|
||||
: {};
|
||||
|
@ -84,12 +87,12 @@ export const DataLayers: FC<Props> = ({
|
|||
const isPercentage = seriesType.includes('percentage');
|
||||
|
||||
const yAxis = yAxesConfiguration.find((axisConfiguration) =>
|
||||
axisConfiguration.series.find((currentSeries) => currentSeries.accessor === accessor)
|
||||
axisConfiguration.series.find((currentSeries) => currentSeries.accessor === yColumnId)
|
||||
);
|
||||
|
||||
const seriesProps = getSeriesProps({
|
||||
layer,
|
||||
accessor,
|
||||
accessor: yColumnId,
|
||||
chartHasMoreThanOneBarSeries,
|
||||
colorAssignments,
|
||||
formatFactory,
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
import React from 'react';
|
||||
import type { LegendAction, XYChartSeriesIdentifier } from '@elastic/charts';
|
||||
import { getAccessorByDimension } from '@kbn/visualizations-plugin/common/utils';
|
||||
import type { FilterEvent } from '../types';
|
||||
import type { CommonXYDataLayerConfig } from '../../common';
|
||||
import type { FormatFactory } from '../types';
|
||||
|
@ -23,7 +24,11 @@ export const getLegendAction = (
|
|||
React.memo(({ series: [xySeries] }) => {
|
||||
const series = xySeries as XYChartSeriesIdentifier;
|
||||
const layerIndex = dataLayers.findIndex((l) =>
|
||||
series.seriesKeys.some((key: string | number) => l.accessors.includes(key.toString()))
|
||||
series.seriesKeys.some((key: string | number) =>
|
||||
l.accessors.some(
|
||||
(accessor) => getAccessorByDimension(accessor, l.table.columns) === key.toString()
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
if (layerIndex === -1) {
|
||||
|
@ -36,11 +41,12 @@ export const getLegendAction = (
|
|||
}
|
||||
|
||||
const splitLabel = series.seriesKeys[0] as string;
|
||||
const accessor = layer.splitAccessor;
|
||||
|
||||
const { table } = layer;
|
||||
const splitColumn = table.columns.find(({ id }) => id === layer.splitAccessor);
|
||||
const formatter = formatFactory(splitColumn && getFormat(splitColumn.meta));
|
||||
const accessor = getAccessorByDimension(layer.splitAccessor, table.columns);
|
||||
const formatter = formatFactory(
|
||||
accessor ? getFormat(table.columns, layer.splitAccessor) : undefined
|
||||
);
|
||||
|
||||
const rowIndex = table.rows.findIndex((row) => {
|
||||
if (formattedDatatables[layer.layerId]?.formattedColumns[accessor]) {
|
||||
|
|
|
@ -6,11 +6,15 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { uniq } from 'lodash';
|
||||
import { isUndefined, uniq } from 'lodash';
|
||||
import React from 'react';
|
||||
import moment from 'moment';
|
||||
import { Endzones } from '@kbn/charts-plugin/public';
|
||||
import { search } from '@kbn/data-plugin/public';
|
||||
import {
|
||||
getAccessorByDimension,
|
||||
getColumnByAccessor,
|
||||
} from '@kbn/visualizations-plugin/common/utils';
|
||||
import type { CommonXYDataLayerConfig } from '../../common';
|
||||
|
||||
export interface XDomain {
|
||||
|
@ -22,7 +26,7 @@ export interface XDomain {
|
|||
export const getAppliedTimeRange = (layers: CommonXYDataLayerConfig[]) => {
|
||||
return layers
|
||||
.map(({ xAccessor, table }) => {
|
||||
const xColumn = table.columns.find((col) => col.id === xAccessor);
|
||||
const xColumn = xAccessor ? getColumnByAccessor(xAccessor, table.columns) : null;
|
||||
const timeRange =
|
||||
xColumn && search.aggs.getDateHistogramMetaDataByDatatableColumn(xColumn)?.timeRange;
|
||||
if (timeRange) {
|
||||
|
@ -57,9 +61,11 @@ export const getXDomain = (
|
|||
if (isHistogram && isFullyQualified(baseDomain)) {
|
||||
const xValues = uniq(
|
||||
layers
|
||||
.flatMap<number>(({ table, xAccessor }) =>
|
||||
table.rows.map((row) => row[xAccessor!].valueOf())
|
||||
)
|
||||
.flatMap<number>(({ table, xAccessor }) => {
|
||||
const accessor = xAccessor && getAccessorByDimension(xAccessor, table.columns);
|
||||
return table.rows.map((row) => accessor && row[accessor] && row[accessor].valueOf());
|
||||
})
|
||||
.filter((v) => !isUndefined(v))
|
||||
.sort()
|
||||
);
|
||||
|
||||
|
|
|
@ -33,6 +33,10 @@ import { EmptyPlaceholder } from '@kbn/charts-plugin/public';
|
|||
import { EventAnnotationServiceType } from '@kbn/event-annotation-plugin/public';
|
||||
import { ChartsPluginSetup, ChartsPluginStart, useActiveCursor } from '@kbn/charts-plugin/public';
|
||||
import { MULTILAYER_TIME_AXIS_STYLE } from '@kbn/charts-plugin/common';
|
||||
import {
|
||||
getAccessorByDimension,
|
||||
getColumnByAccessor,
|
||||
} from '@kbn/visualizations-plugin/common/utils';
|
||||
import {
|
||||
DEFAULT_LEGEND_SIZE,
|
||||
LegendSizeToPixels,
|
||||
|
@ -184,9 +188,15 @@ export function XYChart({
|
|||
}
|
||||
|
||||
// use formatting hint of first x axis column to format ticks
|
||||
const xAxisColumn = dataLayers[0]?.table.columns.find(({ id }) => id === dataLayers[0].xAccessor);
|
||||
const xAxisColumn = dataLayers[0].xAccessor
|
||||
? getColumnByAccessor(dataLayers[0].xAccessor, dataLayers[0]?.table.columns)
|
||||
: undefined;
|
||||
|
||||
const xAxisFormatter = formatFactory(xAxisColumn && getFormat(xAxisColumn.meta));
|
||||
const xAxisFormatter = formatFactory(
|
||||
dataLayers[0].xAccessor
|
||||
? getFormat(dataLayers[0].table.columns, dataLayers[0].xAccessor)
|
||||
: undefined
|
||||
);
|
||||
|
||||
// This is a safe formatter for the xAccessor that abstracts the knowledge of already formatted layers
|
||||
const safeXAccessorLabelRenderer = (value: unknown): string =>
|
||||
|
@ -257,12 +267,14 @@ export function XYChart({
|
|||
const annotationsLayers = getAnnotationsLayers(layers);
|
||||
const firstTable = dataLayers[0]?.table;
|
||||
|
||||
const xColumnId = firstTable?.columns.find((col) => col.id === dataLayers[0]?.xAccessor)?.id;
|
||||
const columnId = dataLayers[0]?.xAccessor
|
||||
? getColumnByAccessor(dataLayers[0]?.xAccessor, firstTable.columns)?.id
|
||||
: null;
|
||||
|
||||
const groupedLineAnnotations = getAnnotationsGroupedByInterval(
|
||||
annotationsLayers,
|
||||
minInterval,
|
||||
xColumnId ? firstTable.rows[0]?.[xColumnId] : undefined,
|
||||
columnId ? firstTable.rows[0]?.[columnId] : undefined,
|
||||
xAxisFormatter
|
||||
);
|
||||
const rangeAnnotations = getRangeAnnotations(annotationsLayers);
|
||||
|
@ -370,7 +382,11 @@ export function XYChart({
|
|||
const xyGeometry = geometry as GeometryValue;
|
||||
|
||||
const layerIndex = dataLayers.findIndex((l) =>
|
||||
xySeries.seriesKeys.some((key: string | number) => l.accessors.includes(key.toString()))
|
||||
xySeries.seriesKeys.some((key: string | number) =>
|
||||
l.accessors.some(
|
||||
(accessor) => getAccessorByDimension(accessor, l.table.columns) === key.toString()
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
if (layerIndex === -1) {
|
||||
|
@ -380,48 +396,53 @@ export function XYChart({
|
|||
const layer = dataLayers[layerIndex];
|
||||
const { table } = layer;
|
||||
|
||||
const xColumn = table.columns.find((col) => col.id === layer.xAccessor);
|
||||
const xColumn = layer.xAccessor && getColumnByAccessor(layer.xAccessor, table.columns);
|
||||
const xAccessor = layer.xAccessor
|
||||
? getAccessorByDimension(layer.xAccessor, table.columns)
|
||||
: undefined;
|
||||
const currentXFormatter =
|
||||
layer.xAccessor &&
|
||||
formattedDatatables[layer.layerId]?.formattedColumns[layer.xAccessor] &&
|
||||
xColumn
|
||||
? formatFactory(getFormat(xColumn.meta))
|
||||
xAccessor && formattedDatatables[layer.layerId]?.formattedColumns[xAccessor] && xColumn
|
||||
? formatFactory(layer.xAccessor ? getFormat(table.columns, layer.xAccessor) : undefined)
|
||||
: xAxisFormatter;
|
||||
|
||||
const rowIndex = table.rows.findIndex((row) => {
|
||||
if (layer.xAccessor) {
|
||||
if (formattedDatatables[layer.layerId]?.formattedColumns[layer.xAccessor]) {
|
||||
if (xAccessor) {
|
||||
if (formattedDatatables[layer.layerId]?.formattedColumns[xAccessor]) {
|
||||
// stringify the value to compare with the chart value
|
||||
return currentXFormatter.convert(row[layer.xAccessor]) === xyGeometry.x;
|
||||
return currentXFormatter.convert(row[xAccessor]) === xyGeometry.x;
|
||||
}
|
||||
return row[layer.xAccessor] === xyGeometry.x;
|
||||
return row[xAccessor] === xyGeometry.x;
|
||||
}
|
||||
});
|
||||
|
||||
const points = [
|
||||
{
|
||||
row: rowIndex,
|
||||
column: table.columns.findIndex((col) => col.id === layer.xAccessor),
|
||||
value: layer.xAccessor ? table.rows[rowIndex][layer.xAccessor] : xyGeometry.x,
|
||||
column: table.columns.findIndex((col) => col.id === xAccessor),
|
||||
value: xAccessor ? table.rows[rowIndex][xAccessor] : xyGeometry.x,
|
||||
},
|
||||
];
|
||||
|
||||
if (xySeries.seriesKeys.length > 1) {
|
||||
const pointValue = xySeries.seriesKeys[0];
|
||||
const splitAccessor = layer.splitAccessor
|
||||
? getAccessorByDimension(layer.splitAccessor, table.columns)
|
||||
: undefined;
|
||||
|
||||
const splitColumn = table.columns.find(({ id }) => id === layer.splitAccessor);
|
||||
const splitFormatter = formatFactory(splitColumn && getFormat(splitColumn.meta));
|
||||
const splitFormatter = formatFactory(
|
||||
layer.splitAccessor ? getFormat(table.columns, layer.splitAccessor) : undefined
|
||||
);
|
||||
|
||||
points.push({
|
||||
row: table.rows.findIndex((row) => {
|
||||
if (layer.splitAccessor) {
|
||||
if (formattedDatatables[layer.layerId]?.formattedColumns[layer.splitAccessor]) {
|
||||
return splitFormatter.convert(row[layer.splitAccessor]) === pointValue;
|
||||
if (splitAccessor) {
|
||||
if (formattedDatatables[layer.layerId]?.formattedColumns[splitAccessor]) {
|
||||
return splitFormatter.convert(row[splitAccessor]) === pointValue;
|
||||
}
|
||||
return row[layer.splitAccessor] === pointValue;
|
||||
return row[splitAccessor] === pointValue;
|
||||
}
|
||||
}),
|
||||
column: table.columns.findIndex((col) => col.id === layer.splitAccessor),
|
||||
column: table.columns.findIndex((col) => col.id === splitAccessor),
|
||||
value: pointValue,
|
||||
});
|
||||
}
|
||||
|
@ -441,8 +462,9 @@ export function XYChart({
|
|||
}
|
||||
|
||||
const { table } = dataLayers[0];
|
||||
|
||||
const xAxisColumnIndex = table.columns.findIndex((el) => el.id === dataLayers[0].xAccessor);
|
||||
const xAccessor =
|
||||
dataLayers[0].xAccessor && getAccessorByDimension(dataLayers[0].xAccessor, table.columns);
|
||||
const xAxisColumnIndex = table.columns.findIndex((el) => el.id === xAccessor);
|
||||
|
||||
const context: BrushEvent['data'] = { range: [min, max], table, column: xAxisColumnIndex };
|
||||
onSelectRange(context);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
*/
|
||||
|
||||
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 } from '../../common';
|
||||
import { isDataLayer } from './visualization';
|
||||
|
@ -52,10 +53,12 @@ export function groupAxesByType(layers: CommonXYDataLayerConfig[]) {
|
|||
const { table } = layer;
|
||||
layer.accessors.forEach((accessor) => {
|
||||
const yConfig: Array<YConfig | ExtendedYConfig> | undefined = layer.yConfig;
|
||||
const yAccessor = getAccessorByDimension(accessor, table?.columns || []);
|
||||
const mode =
|
||||
yConfig?.find((yAxisConfig) => yAxisConfig.forAccessor === accessor)?.axisMode || 'auto';
|
||||
const col = table.columns?.find((column) => column.id === accessor);
|
||||
let formatter: SerializedFieldFormat = col?.meta ? getFormat(col.meta) : { id: 'number' };
|
||||
yConfig?.find((yAxisConfig) => yAxisConfig.forAccessor === yAccessor)?.axisMode || 'auto';
|
||||
let formatter: SerializedFieldFormat = getFormat(table.columns, accessor) || {
|
||||
id: 'number',
|
||||
};
|
||||
if (
|
||||
isDataLayer(layer) &&
|
||||
layer.seriesType.includes('percentage') &&
|
||||
|
@ -70,7 +73,7 @@ export function groupAxesByType(layers: CommonXYDataLayerConfig[]) {
|
|||
}
|
||||
series[mode].push({
|
||||
layer: layer.layerId,
|
||||
accessor,
|
||||
accessor: yAccessor,
|
||||
fieldFormat: formatter,
|
||||
});
|
||||
});
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
import { uniq, mapValues } from 'lodash';
|
||||
import { euiLightVars } from '@kbn/ui-theme';
|
||||
import { getAccessorByDimension } from '@kbn/visualizations-plugin/common/utils';
|
||||
import { FormatFactory } from '../types';
|
||||
import { isDataLayer } from './visualization';
|
||||
import { CommonXYDataLayerConfig, CommonXYLayerConfig } from '../../common';
|
||||
|
@ -48,9 +49,10 @@ export function getColorAssignments(
|
|||
if (!layer.splitAccessor) {
|
||||
return { numberOfSeries: layer.accessors.length, splits: [] };
|
||||
}
|
||||
const splitAccessor = layer.splitAccessor;
|
||||
const splitAccessor = getAccessorByDimension(layer.splitAccessor, layer.table.columns);
|
||||
const column = layer.table.columns?.find(({ id }) => id === splitAccessor);
|
||||
const columnFormatter = column && formatFactory(getFormat(column.meta));
|
||||
const columnFormatter =
|
||||
column && formatFactory(getFormat(layer.table.columns, layer.splitAccessor));
|
||||
const splits =
|
||||
!column || !layer.table
|
||||
? []
|
||||
|
@ -88,7 +90,9 @@ export function getColorAssignments(
|
|||
(sortedLayer.splitAccessor && splitRank !== -1
|
||||
? splitRank * sortedLayer.accessors.length
|
||||
: 0) +
|
||||
sortedLayer.accessors.indexOf(yAccessor)
|
||||
sortedLayer.accessors.findIndex(
|
||||
(accessor) => getAccessorByDimension(accessor, sortedLayer.table.columns) === yAccessor
|
||||
)
|
||||
);
|
||||
},
|
||||
};
|
||||
|
|
|
@ -24,6 +24,11 @@ import {
|
|||
SerializedFieldFormat,
|
||||
} from '@kbn/field-formats-plugin/common';
|
||||
import { Datatable } from '@kbn/expressions-plugin';
|
||||
import {
|
||||
getFormatByAccessor,
|
||||
getAccessorByDimension,
|
||||
} from '@kbn/visualizations-plugin/common/utils';
|
||||
import type { ExpressionValueVisDimension } from '@kbn/visualizations-plugin/common/expression_functions';
|
||||
import { PaletteRegistry, SeriesLayer } from '@kbn/coloring';
|
||||
import { CommonXYDataLayerConfig, XScaleType } from '../../common';
|
||||
import { FormatFactory } from '../types';
|
||||
|
@ -53,7 +58,8 @@ type GetSeriesPropsFn = (config: {
|
|||
type GetSeriesNameFn = (
|
||||
data: XYChartSeriesIdentifier,
|
||||
config: {
|
||||
layer: CommonXYDataLayerConfig;
|
||||
splitColumnId?: string;
|
||||
accessorsCount: number;
|
||||
splitHint: SerializedFieldFormat<FieldFormatParams> | undefined;
|
||||
splitFormatter: FieldFormat;
|
||||
alreadyFormattedColumns: Record<string, boolean>;
|
||||
|
@ -112,11 +118,21 @@ export const getFormattedRow = (
|
|||
export const getFormattedTable = (
|
||||
table: Datatable,
|
||||
formatFactory: FormatFactory,
|
||||
xAccessor: string | undefined,
|
||||
xAccessor: string | ExpressionValueVisDimension | undefined,
|
||||
accessors: Array<string | ExpressionValueVisDimension>,
|
||||
xScaleType: XScaleType
|
||||
): { table: Datatable; formattedColumns: Record<string, true> } => {
|
||||
const columnsFormatters = table.columns.reduce<Record<string, IFieldFormat>>(
|
||||
(formatters, { id, meta }) => ({ ...formatters, [id]: formatFactory(getFormat(meta)) }),
|
||||
(formatters, { id, meta }) => {
|
||||
const accessor: string | ExpressionValueVisDimension | undefined = accessors.find(
|
||||
(a) => getAccessorByDimension(a, table.columns) === id
|
||||
);
|
||||
|
||||
return {
|
||||
...formatters,
|
||||
[id]: formatFactory(accessor ? getFormat(table.columns, accessor) : meta.params),
|
||||
};
|
||||
},
|
||||
{}
|
||||
);
|
||||
|
||||
|
@ -129,7 +145,7 @@ export const getFormattedTable = (
|
|||
row,
|
||||
table.columns,
|
||||
columnsFormatters,
|
||||
xAccessor,
|
||||
xAccessor ? getAccessorByDimension(xAccessor, table.columns) : undefined,
|
||||
xScaleType
|
||||
);
|
||||
return {
|
||||
|
@ -154,28 +170,43 @@ export const getFormattedTablesByLayers = (
|
|||
formatFactory: FormatFactory
|
||||
): DatatablesWithFormatInfo =>
|
||||
layers.reduce(
|
||||
(formattedDatatables, { layerId, table, xAccessor, xScaleType }) => ({
|
||||
(formattedDatatables, { layerId, table, xAccessor, splitAccessor, accessors, xScaleType }) => ({
|
||||
...formattedDatatables,
|
||||
[layerId]: getFormattedTable(table, formatFactory, xAccessor, xScaleType),
|
||||
[layerId]: getFormattedTable(
|
||||
table,
|
||||
formatFactory,
|
||||
xAccessor,
|
||||
[xAccessor, splitAccessor, ...accessors].filter<string | ExpressionValueVisDimension>(
|
||||
(a): a is string | ExpressionValueVisDimension => a !== undefined
|
||||
),
|
||||
xScaleType
|
||||
),
|
||||
}),
|
||||
{}
|
||||
);
|
||||
|
||||
const getSeriesName: GetSeriesNameFn = (
|
||||
data,
|
||||
{ layer, splitHint, splitFormatter, alreadyFormattedColumns, columnToLabelMap }
|
||||
{
|
||||
splitColumnId,
|
||||
accessorsCount,
|
||||
splitHint,
|
||||
splitFormatter,
|
||||
alreadyFormattedColumns,
|
||||
columnToLabelMap,
|
||||
}
|
||||
) => {
|
||||
// For multiple y series, the name of the operation is used on each, either:
|
||||
// * Key - Y name
|
||||
// * Formatted value - Y name
|
||||
if (layer.splitAccessor && layer.accessors.length > 1) {
|
||||
const formatted = alreadyFormattedColumns[layer.splitAccessor];
|
||||
if (splitColumnId && accessorsCount > 1) {
|
||||
const formatted = alreadyFormattedColumns[splitColumnId];
|
||||
const result = data.seriesKeys
|
||||
.map((key: string | number, i) => {
|
||||
if (i === 0 && splitHint && layer.splitAccessor && !formatted) {
|
||||
if (i === 0 && splitHint && splitColumnId && !formatted) {
|
||||
return splitFormatter.convert(key);
|
||||
}
|
||||
return layer.splitAccessor && i === 0 ? key : columnToLabelMap[key] ?? null;
|
||||
return splitColumnId && i === 0 ? key : columnToLabelMap[key] ?? null;
|
||||
})
|
||||
.join(' - ');
|
||||
return result;
|
||||
|
@ -184,7 +215,7 @@ const getSeriesName: GetSeriesNameFn = (
|
|||
// For formatted split series, format the key
|
||||
// This handles splitting by dates, for example
|
||||
if (splitHint) {
|
||||
if (layer.splitAccessor && alreadyFormattedColumns[layer.splitAccessor]) {
|
||||
if (splitColumnId && alreadyFormattedColumns[splitColumnId]) {
|
||||
return data.seriesKeys[0];
|
||||
}
|
||||
return splitFormatter.convert(data.seriesKeys[0]);
|
||||
|
@ -192,7 +223,7 @@ const getSeriesName: GetSeriesNameFn = (
|
|||
// This handles both split and single-y cases:
|
||||
// * If split series without formatting, show the value literally
|
||||
// * If single Y, the seriesKey will be the accessor, so we show the human-readable name
|
||||
return layer.splitAccessor ? data.seriesKeys[0] : columnToLabelMap[data.seriesKeys[0]] ?? null;
|
||||
return splitColumnId ? data.seriesKeys[0] : columnToLabelMap[data.seriesKeys[0]] ?? null;
|
||||
};
|
||||
|
||||
const getPointConfig = (xAccessor?: string, emphasizeFitting?: boolean) => ({
|
||||
|
@ -249,13 +280,18 @@ export const getSeriesProps: GetSeriesPropsFn = ({
|
|||
const isStacked = layer.seriesType.includes('stacked');
|
||||
const isPercentage = layer.seriesType.includes('percentage');
|
||||
const isBarChart = layer.seriesType.includes('bar');
|
||||
const xColumnId = layer.xAccessor && getAccessorByDimension(layer.xAccessor, table.columns);
|
||||
const splitColumnId =
|
||||
layer.splitAccessor && getAccessorByDimension(layer.splitAccessor, table.columns);
|
||||
const enableHistogramMode =
|
||||
layer.isHistogram &&
|
||||
(isStacked || !layer.splitAccessor) &&
|
||||
(isStacked || !isBarChart || !chartHasMoreThanOneBarSeries);
|
||||
|
||||
const formatter = table?.columns.find((column) => column.id === accessor)?.meta?.params;
|
||||
const splitHint = table?.columns.find((col) => col.id === layer.splitAccessor)?.meta?.params;
|
||||
const splitHint = layer.splitAccessor
|
||||
? getFormatByAccessor(layer.splitAccessor, table.columns)
|
||||
: undefined;
|
||||
const splitFormatter = formatFactory(splitHint);
|
||||
|
||||
// what if row values are not primitive? That is the case of, for instance, Ranges
|
||||
|
@ -267,15 +303,15 @@ export const getSeriesProps: GetSeriesPropsFn = ({
|
|||
// To not display them in the legend, they need to be filtered out.
|
||||
let rows = formattedTable.rows.filter(
|
||||
(row) =>
|
||||
!(layer.xAccessor && typeof row[layer.xAccessor] === 'undefined') &&
|
||||
!(xColumnId && typeof row[xColumnId] === 'undefined') &&
|
||||
!(
|
||||
layer.splitAccessor &&
|
||||
typeof row[layer.splitAccessor] === 'undefined' &&
|
||||
splitColumnId &&
|
||||
typeof row[splitColumnId] === 'undefined' &&
|
||||
typeof row[accessor] === 'undefined'
|
||||
)
|
||||
);
|
||||
|
||||
if (!layer.xAccessor) {
|
||||
if (!xColumnId) {
|
||||
rows = rows.map((row) => ({
|
||||
...row,
|
||||
unifiedX: i18n.translate('expressionXY.xyChart.emptyXLabel', {
|
||||
|
@ -285,13 +321,13 @@ export const getSeriesProps: GetSeriesPropsFn = ({
|
|||
}
|
||||
|
||||
return {
|
||||
splitSeriesAccessors: layer.splitAccessor ? [layer.splitAccessor] : [],
|
||||
stackAccessors: isStacked ? [layer.xAccessor as string] : [],
|
||||
id: layer.splitAccessor ? `${layer.splitAccessor}-${accessor}` : `${accessor}`,
|
||||
xAccessor: layer.xAccessor || 'unifiedX',
|
||||
splitSeriesAccessors: splitColumnId ? [splitColumnId] : [],
|
||||
stackAccessors: isStacked ? [xColumnId as string] : [],
|
||||
id: splitColumnId ? `${splitColumnId}-${accessor}` : accessor,
|
||||
xAccessor: xColumnId || 'unifiedX',
|
||||
yAccessors: [accessor],
|
||||
data: rows,
|
||||
xScaleType: layer.xAccessor ? layer.xScaleType : 'ordinal',
|
||||
xScaleType: xColumnId ? layer.xScaleType : 'ordinal',
|
||||
yScaleType:
|
||||
formatter?.id === 'bytes' && layer.yScaleType === ScaleType.Linear
|
||||
? ScaleType.LinearBinary
|
||||
|
@ -310,19 +346,20 @@ export const getSeriesProps: GetSeriesPropsFn = ({
|
|||
stackMode: isPercentage ? StackMode.Percentage : undefined,
|
||||
timeZone,
|
||||
areaSeriesStyle: {
|
||||
point: getPointConfig(layer.xAccessor, emphasizeFitting),
|
||||
point: getPointConfig(xColumnId, emphasizeFitting),
|
||||
...(fillOpacity && { area: { opacity: fillOpacity } }),
|
||||
...(emphasizeFitting && {
|
||||
fit: { area: { opacity: fillOpacity || 0.5 }, line: getLineConfig() },
|
||||
}),
|
||||
},
|
||||
lineSeriesStyle: {
|
||||
point: getPointConfig(layer.xAccessor, emphasizeFitting),
|
||||
point: getPointConfig(xColumnId, emphasizeFitting),
|
||||
...(emphasizeFitting && { fit: { line: getLineConfig() } }),
|
||||
},
|
||||
name(d) {
|
||||
return getSeriesName(d, {
|
||||
layer,
|
||||
splitColumnId,
|
||||
accessorsCount: layer.accessors.length,
|
||||
splitHint,
|
||||
splitFormatter,
|
||||
alreadyFormattedColumns: formattedColumns,
|
||||
|
|
|
@ -6,6 +6,22 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { DatatableColumnMeta } from '@kbn/expressions-plugin';
|
||||
import { DatatableColumn } from '@kbn/expressions-plugin';
|
||||
import { ExpressionValueVisDimension } from '@kbn/visualizations-plugin/common/expression_functions';
|
||||
import { getFormatByAccessor, getColumnByAccessor } from '@kbn/visualizations-plugin/common/utils';
|
||||
|
||||
export const getFormat = (meta?: DatatableColumnMeta) => meta?.params || { id: meta?.type };
|
||||
export const getFormat = (
|
||||
columns: DatatableColumn[],
|
||||
accessor: string | ExpressionValueVisDimension
|
||||
) => {
|
||||
const type = getColumnByAccessor(accessor, columns)?.meta.type;
|
||||
return getFormatByAccessor(
|
||||
accessor,
|
||||
columns,
|
||||
type
|
||||
? {
|
||||
id: type,
|
||||
}
|
||||
: undefined
|
||||
);
|
||||
};
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
*/
|
||||
|
||||
import { search } from '@kbn/data-plugin/public';
|
||||
import { getColumnByAccessor } from '@kbn/visualizations-plugin/common/utils';
|
||||
import { XYChartProps } from '../../common';
|
||||
import { getFilteredLayers } from './layers';
|
||||
import { isDataLayer } from './visualization';
|
||||
|
@ -15,9 +16,10 @@ export function calculateMinInterval({ args: { layers } }: XYChartProps) {
|
|||
const filteredLayers = getFilteredLayers(layers);
|
||||
if (filteredLayers.length === 0) return;
|
||||
const isTimeViz = filteredLayers.every((l) => isDataLayer(l) && l.xScaleType === 'time');
|
||||
const xColumn = filteredLayers[0].table.columns.find(
|
||||
(column) => isDataLayer(filteredLayers[0]) && column.id === filteredLayers[0].xAccessor
|
||||
);
|
||||
const xColumn =
|
||||
isDataLayer(filteredLayers[0]) &&
|
||||
filteredLayers[0].xAccessor &&
|
||||
getColumnByAccessor(filteredLayers[0].xAccessor, filteredLayers[0].table.columns);
|
||||
|
||||
if (!xColumn) return;
|
||||
if (!isTimeViz) {
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
*/
|
||||
|
||||
import { Datatable } from '@kbn/expressions-plugin/common';
|
||||
import { getAccessorByDimension } from '@kbn/visualizations-plugin/common/utils';
|
||||
import type { ExpressionValueVisDimension } from '@kbn/visualizations-plugin/common/expression_functions';
|
||||
import {
|
||||
CommonXYDataLayerConfig,
|
||||
CommonXYLayerConfig,
|
||||
|
@ -18,20 +20,24 @@ export function getFilteredLayers(layers: CommonXYLayerConfig[]) {
|
|||
return layers.filter<CommonXYReferenceLineLayerConfig | CommonXYDataLayerConfig>(
|
||||
(layer): layer is CommonXYReferenceLineLayerConfig | CommonXYDataLayerConfig => {
|
||||
let table: Datatable | undefined;
|
||||
let accessors: string[] = [];
|
||||
let accessors: Array<ExpressionValueVisDimension | string> = [];
|
||||
let xAccessor: undefined | string | number;
|
||||
let splitAccessor: undefined | string | number;
|
||||
|
||||
if (isDataLayer(layer)) {
|
||||
xAccessor = layer.xAccessor;
|
||||
splitAccessor = layer.splitAccessor;
|
||||
}
|
||||
|
||||
if (isDataLayer(layer) || isReferenceLayer(layer)) {
|
||||
table = layer.table;
|
||||
accessors = layer.accessors;
|
||||
}
|
||||
|
||||
if (isDataLayer(layer)) {
|
||||
xAccessor =
|
||||
layer.xAccessor && table && getAccessorByDimension(layer.xAccessor, table.columns);
|
||||
splitAccessor =
|
||||
layer.splitAccessor &&
|
||||
table &&
|
||||
getAccessorByDimension(layer.splitAccessor, table.columns);
|
||||
}
|
||||
|
||||
return !(
|
||||
!accessors.length ||
|
||||
!table ||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
*/
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { Datatable, DatatableColumn } from '@kbn/expressions-plugin/common';
|
||||
import { FieldFormatParams, SerializedFieldFormat } from '@kbn/field-formats-plugin/common/types';
|
||||
import { ExpressionValueVisDimension } from '../expression_functions';
|
||||
|
||||
const getAccessorByIndex = (accessor: number, columns: Datatable['columns']) =>
|
||||
|
@ -66,11 +67,12 @@ export function getAccessor(dimension: string | ExpressionValueVisDimension) {
|
|||
|
||||
export function getFormatByAccessor(
|
||||
dimension: string | ExpressionValueVisDimension,
|
||||
columns: DatatableColumn[]
|
||||
columns: DatatableColumn[],
|
||||
defaultColumnFormat?: SerializedFieldFormat<FieldFormatParams>
|
||||
) {
|
||||
return typeof dimension === 'string'
|
||||
? getColumnByAccessor(dimension, columns)?.meta.params
|
||||
: dimension.format;
|
||||
? getColumnByAccessor(dimension, columns)?.meta.params || defaultColumnFormat
|
||||
: dimension.format || defaultColumnFormat;
|
||||
}
|
||||
|
||||
export const getColumnByAccessor = (
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue