mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[Gauge] Visdimensions support. (#124927)
* Shape argument turned to required. * Added checks for the gauge arguments. * Moved (metric/min/max/goal)Accessor arguments to (metric/min/max/goal). * Split gauge and lens state. * Added support of vis_dimensions. * Some fixes for uniformity. * Moved findAccessor out of dimensions. * Made accessors/vis_dimension functionality reusable for other plugins. * Fixed test snapshots. * Fixed snapshots. Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
b7b5088244
commit
47ec1039ea
38 changed files with 516 additions and 324 deletions
|
@ -10,22 +10,22 @@ export const EXPRESSION_GAUGE_NAME = 'gauge';
|
|||
export const GAUGE_FUNCTION_RENDERER_NAME = 'gauge_renderer';
|
||||
|
||||
export const GaugeShapes = {
|
||||
horizontalBullet: 'horizontalBullet',
|
||||
verticalBullet: 'verticalBullet',
|
||||
HORIZONTAL_BULLET: 'horizontalBullet',
|
||||
VERTICAL_BULLET: 'verticalBullet',
|
||||
} as const;
|
||||
|
||||
export const GaugeTicksPositions = {
|
||||
auto: 'auto',
|
||||
bands: 'bands',
|
||||
AUTO: 'auto',
|
||||
BANDS: 'bands',
|
||||
} as const;
|
||||
|
||||
export const GaugeLabelMajorModes = {
|
||||
auto: 'auto',
|
||||
custom: 'custom',
|
||||
none: 'none',
|
||||
AUTO: 'auto',
|
||||
CUSTOM: 'custom',
|
||||
NONE: 'none',
|
||||
} as const;
|
||||
|
||||
export const GaugeColorModes = {
|
||||
palette: 'palette',
|
||||
none: 'none',
|
||||
PALETTE: 'palette',
|
||||
NONE: 'none',
|
||||
} as const;
|
||||
|
|
|
@ -8,13 +8,13 @@ Object {
|
|||
"args": Object {
|
||||
"ariaLabel": undefined,
|
||||
"colorMode": "none",
|
||||
"goalAccessor": undefined,
|
||||
"goal": undefined,
|
||||
"labelMajor": "title",
|
||||
"labelMajorMode": "custom",
|
||||
"labelMinor": undefined,
|
||||
"maxAccessor": undefined,
|
||||
"metricAccessor": "col-0-1",
|
||||
"minAccessor": "col-1-2",
|
||||
"max": undefined,
|
||||
"metric": "col-0-1",
|
||||
"min": "col-1-2",
|
||||
"palette": undefined,
|
||||
"shape": "horizontalBullet",
|
||||
"ticksPosition": "auto",
|
||||
|
|
|
@ -7,9 +7,10 @@
|
|||
*/
|
||||
|
||||
import { gaugeFunction } from './gauge_function';
|
||||
import type { GaugeArguments } from '..';
|
||||
import { GaugeArguments, GaugeShapes } from '..';
|
||||
import { functionWrapper } from '../../../../expressions/common/expression_functions/specs/tests/utils';
|
||||
import { Datatable } from '../../../../expressions/common/expression_types/specs';
|
||||
import { GaugeColorModes, GaugeLabelMajorModes, GaugeTicksPositions } from '../constants';
|
||||
|
||||
describe('interpreter/functions#gauge', () => {
|
||||
const fn = functionWrapper(gaugeFunction());
|
||||
|
@ -22,13 +23,13 @@ describe('interpreter/functions#gauge', () => {
|
|||
],
|
||||
};
|
||||
const args: GaugeArguments = {
|
||||
ticksPosition: 'auto',
|
||||
labelMajorMode: 'custom',
|
||||
ticksPosition: GaugeTicksPositions.AUTO,
|
||||
labelMajorMode: GaugeLabelMajorModes.CUSTOM,
|
||||
labelMajor: 'title',
|
||||
shape: 'horizontalBullet',
|
||||
colorMode: 'none',
|
||||
minAccessor: 'col-1-2',
|
||||
metricAccessor: 'col-0-1',
|
||||
shape: GaugeShapes.HORIZONTAL_BULLET,
|
||||
colorMode: GaugeColorModes.NONE,
|
||||
min: 'col-1-2',
|
||||
metric: 'col-0-1',
|
||||
};
|
||||
|
||||
it('returns an object with the correct structure', () => {
|
||||
|
|
|
@ -7,101 +7,161 @@
|
|||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { findAccessorOrFail } from '../../../../visualizations/common/utils';
|
||||
import type { ExpressionValueVisDimension } from '../../../../visualizations/common';
|
||||
import type { DatatableColumn } from '../../../../expressions';
|
||||
import { GaugeExpressionFunctionDefinition } from '../types';
|
||||
import { EXPRESSION_GAUGE_NAME } from '../constants';
|
||||
import {
|
||||
EXPRESSION_GAUGE_NAME,
|
||||
GaugeColorModes,
|
||||
GaugeLabelMajorModes,
|
||||
GaugeShapes,
|
||||
GaugeTicksPositions,
|
||||
} from '../constants';
|
||||
|
||||
export const errors = {
|
||||
invalidShapeError: () =>
|
||||
i18n.translate('expressionGauge.functions.gauge.errors.invalidShapeError', {
|
||||
defaultMessage: `Invalid shape is specified. Supported shapes: {shapes}`,
|
||||
values: { shapes: Object.values(GaugeShapes).join(', ') },
|
||||
}),
|
||||
invalidColorModeError: () =>
|
||||
i18n.translate('expressionGauge.functions.gauge.errors.invalidColorModeError', {
|
||||
defaultMessage: `Invalid color mode is specified. Supported color modes: {colorModes}`,
|
||||
values: { colorModes: Object.values(GaugeColorModes).join(', ') },
|
||||
}),
|
||||
invalidTicksPositionError: () =>
|
||||
i18n.translate('expressionGauge.functions.gauge.errors.invalidTicksPositionError', {
|
||||
defaultMessage: `Invalid ticks position is specified. Supported ticks positions: {ticksPositions}`,
|
||||
values: { ticksPositions: Object.values(GaugeTicksPositions).join(', ') },
|
||||
}),
|
||||
invalidLabelMajorModeError: () =>
|
||||
i18n.translate('expressionGauge.functions.gauge.errors.invalidLabelMajorModeError', {
|
||||
defaultMessage: `Invalid label major mode is specified. Supported label major modes: {labelMajorModes}`,
|
||||
values: { labelMajorModes: Object.values(GaugeLabelMajorModes).join(', ') },
|
||||
}),
|
||||
};
|
||||
|
||||
const validateAccessor = (
|
||||
accessor: string | undefined | ExpressionValueVisDimension,
|
||||
columns: DatatableColumn[]
|
||||
) => {
|
||||
if (accessor && typeof accessor === 'string') {
|
||||
findAccessorOrFail(accessor, columns);
|
||||
}
|
||||
};
|
||||
|
||||
const validateOptions = (
|
||||
value: string,
|
||||
availableOptions: Record<string, string>,
|
||||
getErrorMessage: () => string
|
||||
) => {
|
||||
if (!Object.values(availableOptions).includes(value)) {
|
||||
throw new Error(getErrorMessage());
|
||||
}
|
||||
};
|
||||
|
||||
export const gaugeFunction = (): GaugeExpressionFunctionDefinition => ({
|
||||
name: EXPRESSION_GAUGE_NAME,
|
||||
type: 'render',
|
||||
inputTypes: ['datatable'],
|
||||
help: i18n.translate('expressionGauge.functions.help', {
|
||||
help: i18n.translate('expressionGauge.functions.gauge.help', {
|
||||
defaultMessage: 'Gauge visualization',
|
||||
}),
|
||||
args: {
|
||||
shape: {
|
||||
types: ['string'],
|
||||
options: ['horizontalBullet', 'verticalBullet'],
|
||||
help: i18n.translate('expressionGauge.functions.shape.help', {
|
||||
options: [GaugeShapes.HORIZONTAL_BULLET, GaugeShapes.VERTICAL_BULLET],
|
||||
help: i18n.translate('expressionGauge.functions.gauge.args.shape.help', {
|
||||
defaultMessage: 'Type of gauge chart',
|
||||
}),
|
||||
required: true,
|
||||
},
|
||||
metricAccessor: {
|
||||
types: ['string'],
|
||||
help: i18n.translate('expressionGauge.functions.metricAccessor.help', {
|
||||
metric: {
|
||||
types: ['string', 'vis_dimension'],
|
||||
help: i18n.translate('expressionGauge.functions.gauge.args.metric.help', {
|
||||
defaultMessage: 'Current value',
|
||||
}),
|
||||
},
|
||||
minAccessor: {
|
||||
types: ['string'],
|
||||
help: i18n.translate('expressionGauge.functions.minAccessor.help', {
|
||||
min: {
|
||||
types: ['string', 'vis_dimension'],
|
||||
help: i18n.translate('expressionGauge.functions.gauge.args.min.help', {
|
||||
defaultMessage: 'Minimum value',
|
||||
}),
|
||||
},
|
||||
maxAccessor: {
|
||||
types: ['string'],
|
||||
help: i18n.translate('expressionGauge.functions.maxAccessor.help', {
|
||||
max: {
|
||||
types: ['string', 'vis_dimension'],
|
||||
help: i18n.translate('expressionGauge.functions.gauge.args.max.help', {
|
||||
defaultMessage: 'Maximum value',
|
||||
}),
|
||||
},
|
||||
goalAccessor: {
|
||||
types: ['string'],
|
||||
help: i18n.translate('expressionGauge.functions.goalAccessor.help', {
|
||||
goal: {
|
||||
types: ['string', 'vis_dimension'],
|
||||
help: i18n.translate('expressionGauge.functions.gauge.args.goal.help', {
|
||||
defaultMessage: 'Goal Value',
|
||||
}),
|
||||
},
|
||||
colorMode: {
|
||||
types: ['string'],
|
||||
default: 'none',
|
||||
options: ['none', 'palette'],
|
||||
help: i18n.translate('expressionGauge.functions.colorMode.help', {
|
||||
default: GaugeColorModes.NONE,
|
||||
options: [GaugeColorModes.NONE, GaugeColorModes.PALETTE],
|
||||
help: i18n.translate('expressionGauge.functions.gauge.args.colorMode.help', {
|
||||
defaultMessage: 'If set to palette, the palette colors will be applied to the bands',
|
||||
}),
|
||||
},
|
||||
palette: {
|
||||
types: ['palette'],
|
||||
help: i18n.translate('expressionGauge.functions..metric.palette.help', {
|
||||
help: i18n.translate('expressionGauge.functions.gauge.args.palette.help', {
|
||||
defaultMessage: 'Provides colors for the values',
|
||||
}),
|
||||
},
|
||||
ticksPosition: {
|
||||
types: ['string'],
|
||||
options: ['auto', 'bands'],
|
||||
help: i18n.translate('expressionGauge.functions..gaugeChart.config.ticksPosition.help', {
|
||||
default: GaugeTicksPositions.AUTO,
|
||||
options: [GaugeTicksPositions.AUTO, GaugeTicksPositions.BANDS],
|
||||
help: i18n.translate('expressionGauge.functions.gauge.args.ticksPosition.help', {
|
||||
defaultMessage: 'Specifies the placement of ticks',
|
||||
}),
|
||||
required: true,
|
||||
},
|
||||
labelMajor: {
|
||||
types: ['string'],
|
||||
help: i18n.translate('expressionGauge.functions..gaugeChart.config.labelMajor.help', {
|
||||
help: i18n.translate('expressionGauge.functions.gauge.args.labelMajor.help', {
|
||||
defaultMessage: 'Specifies the labelMajor of the gauge chart displayed inside the chart.',
|
||||
}),
|
||||
required: false,
|
||||
},
|
||||
labelMajorMode: {
|
||||
types: ['string'],
|
||||
options: ['none', 'auto', 'custom'],
|
||||
help: i18n.translate('expressionGauge.functions..gaugeChart.config.labelMajorMode.help', {
|
||||
options: [GaugeLabelMajorModes.NONE, GaugeLabelMajorModes.AUTO, GaugeLabelMajorModes.CUSTOM],
|
||||
help: i18n.translate('expressionGauge.functions.gauge.args.labelMajorMode.help', {
|
||||
defaultMessage: 'Specifies the mode of labelMajor',
|
||||
}),
|
||||
required: true,
|
||||
default: GaugeLabelMajorModes.AUTO,
|
||||
},
|
||||
labelMinor: {
|
||||
types: ['string'],
|
||||
help: i18n.translate('expressionGauge.functions..gaugeChart.config.labelMinor.help', {
|
||||
help: i18n.translate('expressionGauge.functions.gauge.args.labelMinor.help', {
|
||||
defaultMessage: 'Specifies the labelMinor of the gauge chart',
|
||||
}),
|
||||
required: false,
|
||||
},
|
||||
ariaLabel: {
|
||||
types: ['string'],
|
||||
help: i18n.translate('expressionGauge.functions.gaugeChart.config.ariaLabel.help', {
|
||||
defaultMessage: 'Specifies the aria label of the gauge chart',
|
||||
}),
|
||||
required: false,
|
||||
},
|
||||
},
|
||||
|
||||
fn(data, args, handlers) {
|
||||
validateOptions(args.shape, GaugeShapes, errors.invalidShapeError);
|
||||
validateOptions(args.colorMode, GaugeColorModes, errors.invalidColorModeError);
|
||||
validateOptions(args.ticksPosition, GaugeTicksPositions, errors.invalidTicksPositionError);
|
||||
validateOptions(args.labelMajorMode, GaugeLabelMajorModes, errors.invalidLabelMajorModeError);
|
||||
|
||||
validateAccessor(args.metric, data.columns);
|
||||
validateAccessor(args.min, data.columns);
|
||||
validateAccessor(args.max, data.columns);
|
||||
validateAccessor(args.goal, data.columns);
|
||||
|
||||
return {
|
||||
type: 'render',
|
||||
as: EXPRESSION_GAUGE_NAME,
|
||||
|
|
|
@ -21,6 +21,7 @@ export type {
|
|||
GaugeLabelMajorMode,
|
||||
GaugeTicksPosition,
|
||||
GaugeState,
|
||||
Accessors,
|
||||
} from './types';
|
||||
|
||||
export { gaugeFunction } from './expression_functions';
|
||||
|
|
|
@ -6,11 +6,13 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { $Values } from '@kbn/utility-types';
|
||||
import {
|
||||
Datatable,
|
||||
ExpressionFunctionDefinition,
|
||||
ExpressionValueRender,
|
||||
} from '../../../../expressions';
|
||||
import { ExpressionValueVisDimension } from '../../../../visualizations/public';
|
||||
import { CustomPaletteState, PaletteOutput } from '../../../../charts/common';
|
||||
import {
|
||||
EXPRESSION_GAUGE_NAME,
|
||||
|
@ -22,17 +24,16 @@ import {
|
|||
} from '../constants';
|
||||
import { CustomPaletteParams } from '.';
|
||||
|
||||
export type GaugeType = 'gauge';
|
||||
export type GaugeColorMode = keyof typeof GaugeColorModes;
|
||||
export type GaugeShape = keyof typeof GaugeShapes;
|
||||
export type GaugeLabelMajorMode = keyof typeof GaugeLabelMajorModes;
|
||||
export type GaugeTicksPosition = keyof typeof GaugeTicksPositions;
|
||||
export type GaugeColorMode = $Values<typeof GaugeColorModes>;
|
||||
export type GaugeShape = $Values<typeof GaugeShapes>;
|
||||
export type GaugeLabelMajorMode = $Values<typeof GaugeLabelMajorModes>;
|
||||
export type GaugeTicksPosition = $Values<typeof GaugeTicksPositions>;
|
||||
|
||||
export interface GaugeState {
|
||||
metricAccessor?: string;
|
||||
minAccessor?: string;
|
||||
maxAccessor?: string;
|
||||
goalAccessor?: string;
|
||||
metric?: string | ExpressionValueVisDimension;
|
||||
min?: string | ExpressionValueVisDimension;
|
||||
max?: string | ExpressionValueVisDimension;
|
||||
goal?: string | ExpressionValueVisDimension;
|
||||
ticksPosition: GaugeTicksPosition;
|
||||
labelMajorMode: GaugeLabelMajorMode;
|
||||
labelMajor?: string;
|
||||
|
@ -68,3 +69,10 @@ export type GaugeExpressionFunctionDefinition = ExpressionFunctionDefinition<
|
|||
GaugeArguments,
|
||||
ExpressionValueRender<GaugeExpressionProps>
|
||||
>;
|
||||
|
||||
export interface Accessors {
|
||||
min?: string;
|
||||
max?: string;
|
||||
metric?: string;
|
||||
goal?: string;
|
||||
}
|
||||
|
|
|
@ -12,7 +12,14 @@ import { fieldFormatsServiceMock } from '../../../../field_formats/public/mocks'
|
|||
import type { Datatable } from '../../../../expressions/public';
|
||||
import { DatatableColumn, DatatableRow } from 'src/plugins/expressions/common';
|
||||
import { shallowWithIntl } from '@kbn/test-jest-helpers';
|
||||
import { GaugeRenderProps, GaugeArguments, GaugeLabelMajorMode, ColorStop } from '../../common';
|
||||
import {
|
||||
GaugeRenderProps,
|
||||
GaugeArguments,
|
||||
ColorStop,
|
||||
GaugeLabelMajorModes,
|
||||
GaugeTicksPositions,
|
||||
GaugeColorModes,
|
||||
} from '../../common';
|
||||
import GaugeComponent from './gauge_component';
|
||||
import { Chart, Goal } from '@elastic/charts';
|
||||
|
||||
|
@ -50,14 +57,14 @@ const chartsThemeService = chartPluginMock.createSetupContract().theme;
|
|||
const formatService = fieldFormatsServiceMock.createStartContract();
|
||||
const args: GaugeArguments = {
|
||||
labelMajor: 'Gauge',
|
||||
metricAccessor: 'metric-accessor',
|
||||
minAccessor: '',
|
||||
maxAccessor: '',
|
||||
goalAccessor: '',
|
||||
metric: 'metric-accessor',
|
||||
min: '',
|
||||
max: '',
|
||||
goal: '',
|
||||
shape: 'verticalBullet',
|
||||
colorMode: 'none',
|
||||
ticksPosition: 'auto',
|
||||
labelMajorMode: 'auto',
|
||||
colorMode: GaugeColorModes.NONE,
|
||||
ticksPosition: GaugeTicksPositions.AUTO,
|
||||
labelMajorMode: GaugeLabelMajorModes.AUTO,
|
||||
};
|
||||
|
||||
const createData = (
|
||||
|
@ -87,14 +94,14 @@ describe('GaugeComponent', function () {
|
|||
expect(component.find(Chart)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('returns null when metricAccessor is not provided', async () => {
|
||||
it('returns null when metric is not provided', async () => {
|
||||
const customProps = {
|
||||
...wrapperProps,
|
||||
args: {
|
||||
...wrapperProps.args,
|
||||
metricAccessor: undefined,
|
||||
minAccessor: 'min-accessor',
|
||||
maxAccessor: 'max-accessor',
|
||||
metric: undefined,
|
||||
min: 'min-accessor',
|
||||
max: 'max-accessor',
|
||||
},
|
||||
data: createData({ 'min-accessor': 0, 'max-accessor': 10 }),
|
||||
};
|
||||
|
@ -107,9 +114,9 @@ describe('GaugeComponent', function () {
|
|||
...wrapperProps,
|
||||
args: {
|
||||
...wrapperProps.args,
|
||||
metricAccessor: 'metric-accessor',
|
||||
minAccessor: 'min-accessor',
|
||||
maxAccessor: 'max-accessor',
|
||||
metric: 'metric-accessor',
|
||||
min: 'min-accessor',
|
||||
max: 'max-accessor',
|
||||
},
|
||||
data: createData({ 'metric-accessor': 0, 'min-accessor': 0, 'max-accessor': 0 }),
|
||||
};
|
||||
|
@ -121,9 +128,9 @@ describe('GaugeComponent', function () {
|
|||
...wrapperProps,
|
||||
args: {
|
||||
...wrapperProps.args,
|
||||
metricAccessor: 'metric-accessor',
|
||||
minAccessor: 'min-accessor',
|
||||
maxAccessor: 'max-accessor',
|
||||
metric: 'metric-accessor',
|
||||
min: 'min-accessor',
|
||||
max: 'max-accessor',
|
||||
},
|
||||
data: createData({ 'metric-accessor': 0, 'min-accessor': 0, 'max-accessor': -10 }),
|
||||
};
|
||||
|
@ -135,10 +142,10 @@ describe('GaugeComponent', function () {
|
|||
...wrapperProps,
|
||||
args: {
|
||||
...wrapperProps.args,
|
||||
ticksPosition: 'bands',
|
||||
metricAccessor: 'metric-accessor',
|
||||
minAccessor: 'min-accessor',
|
||||
maxAccessor: 'max-accessor',
|
||||
ticksPosition: GaugeTicksPositions.BANDS,
|
||||
metric: 'metric-accessor',
|
||||
min: 'min-accessor',
|
||||
max: 'max-accessor',
|
||||
},
|
||||
data: createData({ 'metric-accessor': 12, 'min-accessor': 0, 'max-accessor': 10 }),
|
||||
} as GaugeRenderProps;
|
||||
|
@ -152,7 +159,7 @@ describe('GaugeComponent', function () {
|
|||
...wrapperProps,
|
||||
args: {
|
||||
...wrapperProps.args,
|
||||
labelMajorMode: 'none' as GaugeLabelMajorMode,
|
||||
labelMajorMode: GaugeLabelMajorModes.NONE,
|
||||
labelMinor: '',
|
||||
},
|
||||
};
|
||||
|
@ -165,7 +172,7 @@ describe('GaugeComponent', function () {
|
|||
...wrapperProps,
|
||||
args: {
|
||||
...wrapperProps.args,
|
||||
labelMajorMode: 'custom' as GaugeLabelMajorMode,
|
||||
labelMajorMode: GaugeLabelMajorModes.CUSTOM,
|
||||
labelMajor: 'custom labelMajor',
|
||||
labelMinor: 'custom labelMinor',
|
||||
},
|
||||
|
@ -179,7 +186,7 @@ describe('GaugeComponent', function () {
|
|||
...wrapperProps,
|
||||
args: {
|
||||
...wrapperProps.args,
|
||||
labelMajorMode: 'auto' as GaugeLabelMajorMode,
|
||||
labelMajorMode: GaugeLabelMajorModes.AUTO,
|
||||
labelMajor: '',
|
||||
},
|
||||
};
|
||||
|
@ -194,9 +201,9 @@ describe('GaugeComponent', function () {
|
|||
...wrapperProps,
|
||||
args: {
|
||||
...wrapperProps.args,
|
||||
metricAccessor: 'metric-accessor',
|
||||
minAccessor: 'min-accessor',
|
||||
maxAccessor: 'max-accessor',
|
||||
metric: 'metric-accessor',
|
||||
min: 'min-accessor',
|
||||
max: 'max-accessor',
|
||||
},
|
||||
};
|
||||
const goal = shallowWithIntl(<GaugeComponent {...customProps} />).find(Goal);
|
||||
|
@ -219,9 +226,9 @@ describe('GaugeComponent', function () {
|
|||
...wrapperProps,
|
||||
args: {
|
||||
...wrapperProps.args,
|
||||
metricAccessor: 'metric-accessor',
|
||||
minAccessor: 'min-accessor',
|
||||
maxAccessor: 'max-accessor',
|
||||
metric: 'metric-accessor',
|
||||
min: 'min-accessor',
|
||||
max: 'max-accessor',
|
||||
palette,
|
||||
},
|
||||
} as GaugeRenderProps;
|
||||
|
@ -245,11 +252,11 @@ describe('GaugeComponent', function () {
|
|||
...wrapperProps,
|
||||
args: {
|
||||
...wrapperProps.args,
|
||||
metricAccessor: 'metric-accessor',
|
||||
minAccessor: 'min-accessor',
|
||||
maxAccessor: 'max-accessor',
|
||||
metric: 'metric-accessor',
|
||||
min: 'min-accessor',
|
||||
max: 'max-accessor',
|
||||
palette,
|
||||
ticksPosition: 'bands',
|
||||
ticksPosition: GaugeTicksPositions.BANDS,
|
||||
},
|
||||
} as GaugeRenderProps;
|
||||
const goal = shallowWithIntl(<GaugeComponent {...customProps} />).find(Goal);
|
||||
|
@ -273,11 +280,11 @@ describe('GaugeComponent', function () {
|
|||
...wrapperProps,
|
||||
args: {
|
||||
...wrapperProps.args,
|
||||
metricAccessor: 'metric-accessor',
|
||||
minAccessor: 'min-accessor',
|
||||
maxAccessor: 'max-accessor',
|
||||
metric: 'metric-accessor',
|
||||
min: 'min-accessor',
|
||||
max: 'max-accessor',
|
||||
palette,
|
||||
ticksPosition: 'bands',
|
||||
ticksPosition: GaugeTicksPositions.BANDS,
|
||||
},
|
||||
} as GaugeRenderProps;
|
||||
const goal = shallowWithIntl(<GaugeComponent {...customProps} />).find(Goal);
|
||||
|
@ -301,11 +308,11 @@ describe('GaugeComponent', function () {
|
|||
...wrapperProps,
|
||||
args: {
|
||||
...wrapperProps.args,
|
||||
metricAccessor: 'metric-accessor',
|
||||
minAccessor: 'min-accessor',
|
||||
maxAccessor: 'max-accessor',
|
||||
metric: 'metric-accessor',
|
||||
min: 'min-accessor',
|
||||
max: 'max-accessor',
|
||||
palette,
|
||||
ticksPosition: 'bands',
|
||||
ticksPosition: GaugeTicksPositions.BANDS,
|
||||
},
|
||||
} as GaugeRenderProps;
|
||||
const goal = shallowWithIntl(<GaugeComponent {...customProps} />).find(Goal);
|
||||
|
@ -329,11 +336,11 @@ describe('GaugeComponent', function () {
|
|||
...wrapperProps,
|
||||
args: {
|
||||
...wrapperProps.args,
|
||||
metricAccessor: 'metric-accessor',
|
||||
minAccessor: 'min-accessor',
|
||||
maxAccessor: 'max-accessor',
|
||||
metric: 'metric-accessor',
|
||||
min: 'min-accessor',
|
||||
max: 'max-accessor',
|
||||
palette,
|
||||
ticksPosition: 'bands',
|
||||
ticksPosition: GaugeTicksPositions.BANDS,
|
||||
},
|
||||
} as GaugeRenderProps;
|
||||
const goal = shallowWithIntl(<GaugeComponent {...customProps} />).find(Goal);
|
||||
|
@ -357,11 +364,11 @@ describe('GaugeComponent', function () {
|
|||
...wrapperProps,
|
||||
args: {
|
||||
...wrapperProps.args,
|
||||
metricAccessor: 'metric-accessor',
|
||||
minAccessor: 'min-accessor',
|
||||
maxAccessor: 'max-accessor',
|
||||
metric: 'metric-accessor',
|
||||
min: 'min-accessor',
|
||||
max: 'max-accessor',
|
||||
palette,
|
||||
ticksPosition: 'bands',
|
||||
ticksPosition: GaugeTicksPositions.BANDS,
|
||||
},
|
||||
} as GaugeRenderProps;
|
||||
const goal = shallowWithIntl(<GaugeComponent {...customProps} />).find(Goal);
|
||||
|
@ -385,12 +392,12 @@ describe('GaugeComponent', function () {
|
|||
...wrapperProps,
|
||||
args: {
|
||||
...wrapperProps.args,
|
||||
colorMode: 'palette',
|
||||
colorMode: GaugeColorModes.PALETTE,
|
||||
palette,
|
||||
ticksPosition: 'bands',
|
||||
metricAccessor: 'metric-accessor',
|
||||
minAccessor: 'min-accessor',
|
||||
maxAccessor: 'max-accessor',
|
||||
ticksPosition: GaugeTicksPositions.BANDS,
|
||||
metric: 'metric-accessor',
|
||||
min: 'min-accessor',
|
||||
max: 'max-accessor',
|
||||
},
|
||||
} as GaugeRenderProps;
|
||||
const goal = shallowWithIntl(<GaugeComponent {...customProps} />).find(Goal);
|
||||
|
@ -414,12 +421,12 @@ describe('GaugeComponent', function () {
|
|||
...wrapperProps,
|
||||
args: {
|
||||
...wrapperProps.args,
|
||||
colorMode: 'palette',
|
||||
colorMode: GaugeColorModes.PALETTE,
|
||||
palette,
|
||||
ticksPosition: 'bands',
|
||||
metricAccessor: 'metric-accessor',
|
||||
minAccessor: 'min-accessor',
|
||||
maxAccessor: 'max-accessor',
|
||||
ticksPosition: GaugeTicksPositions.BANDS,
|
||||
metric: 'metric-accessor',
|
||||
min: 'min-accessor',
|
||||
max: 'max-accessor',
|
||||
},
|
||||
} as GaugeRenderProps;
|
||||
const goal = shallowWithIntl(<GaugeComponent {...customProps} />).find(Goal);
|
||||
|
|
|
@ -15,10 +15,11 @@ import {
|
|||
GaugeLabelMajorMode,
|
||||
GaugeTicksPosition,
|
||||
GaugeLabelMajorModes,
|
||||
GaugeColorModes,
|
||||
} from '../../common';
|
||||
import { GaugeShapes, GaugeTicksPositions } from '../../common';
|
||||
import { GaugeIconVertical, GaugeIconHorizontal } from './gauge_icon';
|
||||
import { getMaxValue, getMinValue, getValueFromAccessor } from './utils';
|
||||
import { getAccessorsFromArgs, getMaxValue, getMinValue, getValueFromAccessor } from './utils';
|
||||
import './index.scss';
|
||||
declare global {
|
||||
interface Window {
|
||||
|
@ -103,9 +104,11 @@ function getTitle(
|
|||
labelMajor?: string,
|
||||
fallbackTitle?: string
|
||||
) {
|
||||
if (labelMajorMode === GaugeLabelMajorModes.none) {
|
||||
if (labelMajorMode === GaugeLabelMajorModes.NONE) {
|
||||
return '';
|
||||
} else if (labelMajorMode === GaugeLabelMajorModes.auto) {
|
||||
}
|
||||
|
||||
if (labelMajorMode === GaugeLabelMajorModes.AUTO) {
|
||||
return `${fallbackTitle || ''} `; // added extra space for nice rendering
|
||||
}
|
||||
return `${labelMajor || fallbackTitle || ''} `; // added extra space for nice rendering
|
||||
|
@ -131,7 +134,7 @@ function getTicks(
|
|||
range: [number, number],
|
||||
colorBands?: number[]
|
||||
) {
|
||||
if (ticksPosition === GaugeTicksPositions.bands && colorBands) {
|
||||
if (ticksPosition === GaugeTicksPositions.BANDS && colorBands) {
|
||||
return colorBands && getTicksLabels(colorBands);
|
||||
}
|
||||
const TICKS_NO = 3;
|
||||
|
@ -150,7 +153,6 @@ export const GaugeComponent: FC<GaugeRenderProps> = memo(
|
|||
({ data, args, formatFactory, chartsThemeService }) => {
|
||||
const {
|
||||
shape: subtype,
|
||||
metricAccessor,
|
||||
palette,
|
||||
colorMode,
|
||||
labelMinor,
|
||||
|
@ -158,32 +160,35 @@ export const GaugeComponent: FC<GaugeRenderProps> = memo(
|
|||
labelMajorMode,
|
||||
ticksPosition,
|
||||
} = args;
|
||||
if (!metricAccessor) {
|
||||
const table = data;
|
||||
const accessors = getAccessorsFromArgs(args, table.columns);
|
||||
|
||||
if (!accessors || !accessors.metric) {
|
||||
// Chart is not ready
|
||||
return null;
|
||||
}
|
||||
|
||||
const chartTheme = chartsThemeService.useChartsTheme();
|
||||
|
||||
const table = data;
|
||||
const metricColumn = table.columns.find((col) => col.id === metricAccessor);
|
||||
const metricColumn = table.columns.find((col) => col.id === accessors.metric);
|
||||
|
||||
const chartData = table.rows.filter(
|
||||
(v) => typeof v[metricAccessor!] === 'number' || Array.isArray(v[metricAccessor!])
|
||||
(v) => typeof v[accessors.metric!] === 'number' || Array.isArray(v[accessors.metric!])
|
||||
);
|
||||
const row = chartData?.[0];
|
||||
|
||||
const metricValue = getValueFromAccessor('metricAccessor', row, args);
|
||||
const metricValue = args.metric ? getValueFromAccessor(accessors.metric, row) : undefined;
|
||||
|
||||
const icon = subtype === GaugeShapes.horizontalBullet ? GaugeIconHorizontal : GaugeIconVertical;
|
||||
const icon =
|
||||
subtype === GaugeShapes.HORIZONTAL_BULLET ? GaugeIconHorizontal : GaugeIconVertical;
|
||||
|
||||
if (typeof metricValue !== 'number') {
|
||||
return <EmptyPlaceholder icon={icon} />;
|
||||
}
|
||||
|
||||
const goal = getValueFromAccessor('goalAccessor', row, args);
|
||||
const min = getMinValue(row, args);
|
||||
const max = getMaxValue(row, args);
|
||||
const goal = accessors.goal ? getValueFromAccessor(accessors.goal, row) : undefined;
|
||||
const min = getMinValue(row, accessors);
|
||||
const max = getMaxValue(row, accessors);
|
||||
|
||||
if (min === max) {
|
||||
return (
|
||||
|
@ -197,7 +202,9 @@ export const GaugeComponent: FC<GaugeRenderProps> = memo(
|
|||
}
|
||||
/>
|
||||
);
|
||||
} else if (min > max) {
|
||||
}
|
||||
|
||||
if (min > max) {
|
||||
return (
|
||||
<EmptyPlaceholder
|
||||
icon={icon}
|
||||
|
@ -247,7 +254,7 @@ export const GaugeComponent: FC<GaugeRenderProps> = memo(
|
|||
bands={bands}
|
||||
ticks={getTicks(ticksPosition, [min, max], bands)}
|
||||
bandFillColor={
|
||||
colorMode === 'palette' && colors
|
||||
colorMode === GaugeColorModes.PALETTE && colors
|
||||
? (val) => {
|
||||
const index = bands && bands.indexOf(val.value) - 1;
|
||||
return colors && index >= 0 && colors[index]
|
||||
|
|
|
@ -14,78 +14,78 @@ describe('expression gauge utils', () => {
|
|||
metric: 2,
|
||||
min: [10, 20],
|
||||
};
|
||||
const state = {
|
||||
metricAccessor: 'metric',
|
||||
minAccessor: 'min',
|
||||
const accessors = {
|
||||
metric: 'metric',
|
||||
min: 'min',
|
||||
};
|
||||
it('returns accessor value for number', () => {
|
||||
expect(getValueFromAccessor('metricAccessor', row, state)).toEqual(2);
|
||||
expect(getValueFromAccessor(accessors.metric, row)).toEqual(2);
|
||||
});
|
||||
it('returns accessor value for array', () => {
|
||||
expect(getValueFromAccessor('minAccessor', row, state)).toEqual(20);
|
||||
expect(getValueFromAccessor(accessors.min, row)).toEqual(20);
|
||||
});
|
||||
it('returns undefined for not number', () => {
|
||||
expect(getValueFromAccessor('maxAccessor', row, state)).toEqual(undefined);
|
||||
expect(getValueFromAccessor('max', row)).toEqual(undefined);
|
||||
});
|
||||
});
|
||||
describe('getMaxValue', () => {
|
||||
const state = {
|
||||
metricAccessor: 'metric',
|
||||
minAccessor: 'min',
|
||||
const accessors = {
|
||||
metric: 'metric',
|
||||
min: 'min',
|
||||
};
|
||||
it('returns correct value for existing maxAccessor', () => {
|
||||
it('returns correct value for existing max', () => {
|
||||
const row = {
|
||||
metric: 2,
|
||||
min: 0,
|
||||
max: 5,
|
||||
};
|
||||
expect(getMaxValue(row, { ...state, maxAccessor: 'max' })).toEqual(5);
|
||||
expect(getMaxValue(row, { ...accessors, max: 'max' })).toEqual(5);
|
||||
});
|
||||
it('returns fallback value', () => {
|
||||
const localState = { ...state, maxAccessor: 'max' };
|
||||
expect(getMaxValue({ min: 0 }, localState)).toEqual(100);
|
||||
expect(getMaxValue({}, localState)).toEqual(100);
|
||||
const localAccessors = { ...accessors, max: 'max' };
|
||||
expect(getMaxValue({ min: 0 }, localAccessors)).toEqual(100);
|
||||
expect(getMaxValue({}, localAccessors)).toEqual(100);
|
||||
});
|
||||
it('returns correct value for multiple cases', () => {
|
||||
const localState = { ...state, maxAccessor: 'max' };
|
||||
expect(getMaxValue({ metric: 10 }, localState)).toEqual(15);
|
||||
expect(getMaxValue({ min: 0, metric: 2 }, localState)).toEqual(4);
|
||||
expect(getMaxValue({ min: -100, metric: 2 }, localState)).toEqual(50);
|
||||
expect(getMaxValue({ min: -0.001, metric: 0 }, localState)).toEqual(1);
|
||||
expect(getMaxValue({ min: -2000, metric: -1000 }, localState)).toEqual(-500);
|
||||
expect(getMaxValue({ min: 0.5, metric: 1.5 }, localState)).toEqual(2);
|
||||
const localAccessors = { ...accessors, max: 'max' };
|
||||
expect(getMaxValue({ metric: 10 }, localAccessors)).toEqual(15);
|
||||
expect(getMaxValue({ min: 0, metric: 2 }, localAccessors)).toEqual(4);
|
||||
expect(getMaxValue({ min: -100, metric: 2 }, localAccessors)).toEqual(50);
|
||||
expect(getMaxValue({ min: -0.001, metric: 0 }, localAccessors)).toEqual(1);
|
||||
expect(getMaxValue({ min: -2000, metric: -1000 }, localAccessors)).toEqual(-500);
|
||||
expect(getMaxValue({ min: 0.5, metric: 1.5 }, localAccessors)).toEqual(2);
|
||||
});
|
||||
});
|
||||
describe('getMinValue', () => {
|
||||
it('returns 0 for max values greater than 0', () => {
|
||||
const state = {
|
||||
metricAccessor: 'metric',
|
||||
minAccessor: 'min',
|
||||
const accessors = {
|
||||
metric: 'metric',
|
||||
min: 'min',
|
||||
};
|
||||
const localState = { ...state, maxAccessor: 'max' };
|
||||
expect(getMinValue({ max: 1000, metric: 1.5 }, localState)).toEqual(0);
|
||||
expect(getMinValue({ max: 5, metric: 2 }, localState)).toEqual(0);
|
||||
const localAccessors = { ...accessors, max: 'max' };
|
||||
expect(getMinValue({ max: 1000, metric: 1.5 }, localAccessors)).toEqual(0);
|
||||
expect(getMinValue({ max: 5, metric: 2 }, localAccessors)).toEqual(0);
|
||||
});
|
||||
it('returns correct value for negative values', () => {
|
||||
const state = {
|
||||
metricAccessor: 'metric',
|
||||
minAccessor: 'min',
|
||||
const accessors = {
|
||||
metric: 'metric',
|
||||
min: 'min',
|
||||
};
|
||||
const localState = { ...state, maxAccessor: 'max' };
|
||||
expect(getMinValue({ metric: 0 }, localState)).toEqual(-10);
|
||||
expect(getMinValue({ metric: -1000 }, localState)).toEqual(-1010);
|
||||
expect(getMinValue({ max: 1000, metric: 1.5 }, localState)).toEqual(0);
|
||||
const localAccessors = { ...accessors, max: 'max' };
|
||||
expect(getMinValue({ metric: 0 }, localAccessors)).toEqual(-10);
|
||||
expect(getMinValue({ metric: -1000 }, localAccessors)).toEqual(-1010);
|
||||
expect(getMinValue({ max: 1000, metric: 1.5 }, localAccessors)).toEqual(0);
|
||||
});
|
||||
});
|
||||
describe('getGoalValue', () => {
|
||||
it('returns correct value', () => {
|
||||
const state = {
|
||||
metricAccessor: 'metric',
|
||||
minAccessor: 'min',
|
||||
maxAccessor: 'max',
|
||||
const accessors = {
|
||||
metric: 'metric',
|
||||
min: 'min',
|
||||
max: 'max',
|
||||
};
|
||||
expect(getGoalValue({ max: 1000, min: 0 }, state)).toEqual(750);
|
||||
expect(getGoalValue({ min: 3, max: 6 }, state)).toEqual(5);
|
||||
expect(getGoalValue({ max: 1000, min: 0 }, accessors)).toEqual(750);
|
||||
expect(getGoalValue({ min: 3, max: 6 }, accessors)).toEqual(5);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -6,29 +6,27 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import type { DatatableRow } from 'src/plugins/expressions';
|
||||
import type { GaugeState } from '../../common/types/expression_functions';
|
||||
|
||||
type GaugeAccessors = 'maxAccessor' | 'minAccessor' | 'goalAccessor' | 'metricAccessor';
|
||||
|
||||
type GaugeAccessorsType = Pick<GaugeState, GaugeAccessors>;
|
||||
import type { DatatableColumn, DatatableRow } from 'src/plugins/expressions';
|
||||
import { getAccessorByDimension } from '../../../../visualizations/common/utils';
|
||||
import { Accessors, GaugeArguments } from '../../common';
|
||||
|
||||
export const getValueFromAccessor = (
|
||||
accessorName: GaugeAccessors,
|
||||
row?: DatatableRow,
|
||||
state?: GaugeAccessorsType
|
||||
) => {
|
||||
if (row && state) {
|
||||
const accessor = state[accessorName];
|
||||
const value = accessor && row[accessor];
|
||||
if (typeof value === 'number') {
|
||||
return value;
|
||||
}
|
||||
if (value?.length) {
|
||||
if (typeof value[value.length - 1] === 'number') {
|
||||
return value[value.length - 1];
|
||||
}
|
||||
}
|
||||
accessor: string,
|
||||
row?: DatatableRow
|
||||
): DatatableRow[string] | number | undefined => {
|
||||
if (!row || !accessor) return;
|
||||
|
||||
const value = accessor && row[accessor];
|
||||
if (value === null || (Array.isArray(value) && !value.length)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof value === 'number') {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (Array.isArray(value) && typeof value[value.length - 1] === 'number') {
|
||||
return value[value.length - 1];
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -56,17 +54,17 @@ function getNiceNumber(localRange: number) {
|
|||
return niceFraction * Math.pow(10, exponent);
|
||||
}
|
||||
|
||||
export const getMaxValue = (row?: DatatableRow, state?: GaugeAccessorsType): number => {
|
||||
export const getMaxValue = (row?: DatatableRow, accessors?: Accessors): number => {
|
||||
const FALLBACK_VALUE = 100;
|
||||
const currentValue = getValueFromAccessor('maxAccessor', row, state);
|
||||
if (currentValue != null) {
|
||||
const currentValue = accessors?.max ? getValueFromAccessor(accessors.max, row) : undefined;
|
||||
if (currentValue !== undefined && currentValue !== null) {
|
||||
return currentValue;
|
||||
}
|
||||
if (row && state) {
|
||||
const { metricAccessor, goalAccessor } = state;
|
||||
const metricValue = metricAccessor && row[metricAccessor];
|
||||
const goalValue = goalAccessor && row[goalAccessor];
|
||||
const minValue = getMinValue(row, state);
|
||||
if (row && accessors) {
|
||||
const { metric, goal } = accessors;
|
||||
const metricValue = metric && row[metric];
|
||||
const goalValue = goal && row[goal];
|
||||
const minValue = getMinValue(row, accessors);
|
||||
if (metricValue != null) {
|
||||
const numberValues = [minValue, goalValue, metricValue].filter((v) => typeof v === 'number');
|
||||
const maxValue = Math.max(...numberValues);
|
||||
|
@ -76,16 +74,16 @@ export const getMaxValue = (row?: DatatableRow, state?: GaugeAccessorsType): num
|
|||
return FALLBACK_VALUE;
|
||||
};
|
||||
|
||||
export const getMinValue = (row?: DatatableRow, state?: GaugeAccessorsType) => {
|
||||
const currentValue = getValueFromAccessor('minAccessor', row, state);
|
||||
if (currentValue != null) {
|
||||
export const getMinValue = (row?: DatatableRow, accessors?: Accessors) => {
|
||||
const currentValue = accessors?.min ? getValueFromAccessor(accessors.min, row) : undefined;
|
||||
if (currentValue !== undefined && currentValue !== null) {
|
||||
return currentValue;
|
||||
}
|
||||
const FALLBACK_VALUE = 0;
|
||||
if (row && state) {
|
||||
const { metricAccessor, maxAccessor } = state;
|
||||
const metricValue = metricAccessor && row[metricAccessor];
|
||||
const maxValue = maxAccessor && row[maxAccessor];
|
||||
if (row && accessors) {
|
||||
const { metric, max } = accessors;
|
||||
const metricValue = metric && row[metric];
|
||||
const maxValue = max && row[max];
|
||||
const numberValues = [metricValue, maxValue].filter((v) => typeof v === 'number');
|
||||
if (Math.min(...numberValues) <= 0) {
|
||||
return Math.min(...numberValues) - 10; // TODO: TO THINK THROUGH
|
||||
|
@ -94,12 +92,30 @@ export const getMinValue = (row?: DatatableRow, state?: GaugeAccessorsType) => {
|
|||
return FALLBACK_VALUE;
|
||||
};
|
||||
|
||||
export const getGoalValue = (row?: DatatableRow, state?: GaugeAccessorsType) => {
|
||||
const currentValue = getValueFromAccessor('goalAccessor', row, state);
|
||||
if (currentValue != null) {
|
||||
export const getGoalValue = (row?: DatatableRow, accessors?: Accessors) => {
|
||||
const currentValue = accessors?.goal ? getValueFromAccessor(accessors.goal, row) : undefined;
|
||||
if (currentValue !== undefined && currentValue !== null) {
|
||||
return currentValue;
|
||||
}
|
||||
const minValue = getMinValue(row, state);
|
||||
const maxValue = getMaxValue(row, state);
|
||||
|
||||
const minValue = getMinValue(row, accessors);
|
||||
const maxValue = getMaxValue(row, accessors);
|
||||
return Math.round((maxValue - minValue) * 0.75 + minValue);
|
||||
};
|
||||
|
||||
export const getAccessorsFromArgs = (
|
||||
args: GaugeArguments,
|
||||
columns: DatatableColumn[]
|
||||
): Accessors | undefined => {
|
||||
const { metric, min, max, goal } = args;
|
||||
if (!metric && !min && !max && !goal) {
|
||||
return;
|
||||
}
|
||||
|
||||
return {
|
||||
min: min ? getAccessorByDimension(min, columns) : undefined,
|
||||
max: max ? getAccessorByDimension(max, columns) : undefined,
|
||||
goal: goal ? getAccessorByDimension(goal, columns) : undefined,
|
||||
metric: metric ? getAccessorByDimension(metric, columns) : undefined,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import type { DatatableColumn } from '../../../../expressions/public';
|
||||
import { ExpressionValueVisDimension } from '../../../../visualizations/common';
|
||||
import { prepareLogTable, Dimension } from '../../../../visualizations/common/prepare_log_table';
|
||||
import { prepareLogTable, Dimension } from '../../../../visualizations/common/utils';
|
||||
import { HeatmapExpressionFunctionDefinition } from '../types';
|
||||
import {
|
||||
EXPRESSION_HEATMAP_NAME,
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { visType } from '../types';
|
||||
import { prepareLogTable, Dimension } from '../../../../visualizations/common/prepare_log_table';
|
||||
import { prepareLogTable, Dimension } from '../../../../visualizations/common/utils';
|
||||
import { ColorMode } from '../../../../charts/common';
|
||||
import { MetricVisExpressionFunctionDefinition } from '../types';
|
||||
import { EXPRESSION_METRIC_NAME, LabelPosition } from '../constants';
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
import { LegendDisplay, PartitionVisParams } from '../types/expression_renderers';
|
||||
import { prepareLogTable } from '../../../../visualizations/common/prepare_log_table';
|
||||
import { prepareLogTable } from '../../../../visualizations/common/utils';
|
||||
import { ChartTypes, MosaicVisExpressionFunctionDefinition } from '../types';
|
||||
import {
|
||||
PARTITION_LABELS_FUNCTION,
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
import { Position } from '@elastic/charts';
|
||||
import { EmptySizeRatios, LegendDisplay, PartitionVisParams } from '../types/expression_renderers';
|
||||
import { prepareLogTable } from '../../../../visualizations/common/prepare_log_table';
|
||||
import { prepareLogTable } from '../../../../visualizations/common/utils';
|
||||
import { ChartTypes, PieVisExpressionFunctionDefinition } from '../types';
|
||||
import {
|
||||
PARTITION_LABELS_FUNCTION,
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
import { LegendDisplay, PartitionVisParams } from '../types/expression_renderers';
|
||||
import { prepareLogTable } from '../../../../visualizations/common/prepare_log_table';
|
||||
import { prepareLogTable } from '../../../../visualizations/common/utils';
|
||||
import { ChartTypes, TreemapVisExpressionFunctionDefinition } from '../types';
|
||||
import {
|
||||
PARTITION_LABELS_FUNCTION,
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
import { LegendDisplay, PartitionVisParams } from '../types/expression_renderers';
|
||||
import { prepareLogTable } from '../../../../visualizations/common/prepare_log_table';
|
||||
import { prepareLogTable } from '../../../../visualizations/common/utils';
|
||||
import { ChartTypes, WaffleVisExpressionFunctionDefinition } from '../types';
|
||||
import {
|
||||
PARTITION_LABELS_FUNCTION,
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { prepareLogTable, Dimension } from '../../../../visualizations/common/prepare_log_table';
|
||||
import { prepareLogTable, Dimension } from '../../../../visualizations/common/utils';
|
||||
import { TagCloudRendererParams } from '../types';
|
||||
import { ExpressionTagcloudFunction } from '../types';
|
||||
import { EXPRESSION_NAME } from '../constants';
|
||||
|
|
|
@ -58,13 +58,15 @@ describe('interpreter/functions#vis_dimension', () => {
|
|||
const accessor = input.columns.length;
|
||||
const args: Arguments = { accessor };
|
||||
|
||||
expect(() => fn(input, args)).toThrowError('Column name or index provided is invalid');
|
||||
expect(() => fn(input, args)).toThrowError('Provided column name or index is invalid: 2');
|
||||
});
|
||||
|
||||
it("should throw error when the passed column doesn't exist in columns", () => {
|
||||
const accessor = column1 + '_modified';
|
||||
const args: Arguments = { accessor };
|
||||
|
||||
expect(() => fn(input, args)).toThrowError('Column name or index provided is invalid');
|
||||
expect(() => fn(input, args)).toThrowError(
|
||||
'Provided column name or index is invalid: username_modified'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -13,6 +13,7 @@ import {
|
|||
Datatable,
|
||||
DatatableColumn,
|
||||
} from '../../../expressions/common';
|
||||
import { findAccessorOrFail } from '../utils/accessors';
|
||||
|
||||
export interface Arguments {
|
||||
accessor: string | number;
|
||||
|
@ -31,12 +32,6 @@ export type ExpressionValueVisDimension = ExpressionValueBoxed<
|
|||
}
|
||||
>;
|
||||
|
||||
const getAccessorByIndex = (accessor: number, columns: Datatable['columns']) =>
|
||||
columns.length > accessor ? accessor : undefined;
|
||||
|
||||
const getAccessorById = (accessor: DatatableColumn['id'], columns: Datatable['columns']) =>
|
||||
columns.find((c) => c.id === accessor);
|
||||
|
||||
export const visDimension = (): ExpressionFunctionDefinition<
|
||||
'visdimension',
|
||||
Datatable,
|
||||
|
@ -73,19 +68,7 @@ export const visDimension = (): ExpressionFunctionDefinition<
|
|||
},
|
||||
},
|
||||
fn: (input, args) => {
|
||||
const accessor =
|
||||
typeof args.accessor === 'number'
|
||||
? getAccessorByIndex(args.accessor, input.columns)
|
||||
: getAccessorById(args.accessor, input.columns);
|
||||
|
||||
if (accessor === undefined) {
|
||||
throw new Error(
|
||||
i18n.translate('visualizations.function.visDimension.error.accessor', {
|
||||
defaultMessage: 'Column name or index provided is invalid',
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
const accessor = findAccessorOrFail(args.accessor, input.columns);
|
||||
return {
|
||||
type: 'vis_dimension',
|
||||
accessor,
|
||||
|
|
|
@ -11,5 +11,5 @@
|
|||
|
||||
/** @public types */
|
||||
export * from './types';
|
||||
export * from './prepare_log_table';
|
||||
export * from './utils';
|
||||
export * from './expression_functions';
|
||||
|
|
50
src/plugins/visualizations/common/utils/accessors.ts
Normal file
50
src/plugins/visualizations/common/utils/accessors.ts
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* 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 { Datatable, DatatableColumn } from '../../../expressions/common';
|
||||
import { ExpressionValueVisDimension } from '../expression_functions';
|
||||
|
||||
const getAccessorByIndex = (accessor: number, columns: Datatable['columns']) =>
|
||||
columns.length > accessor ? accessor : undefined;
|
||||
|
||||
const getAccessorById = (accessor: DatatableColumn['id'], columns: Datatable['columns']) =>
|
||||
columns.find((c) => c.id === accessor);
|
||||
|
||||
export const findAccessorOrFail = (accessor: string | number, columns: DatatableColumn[]) => {
|
||||
const foundAccessor =
|
||||
typeof accessor === 'number'
|
||||
? getAccessorByIndex(accessor, columns)
|
||||
: getAccessorById(accessor, columns);
|
||||
|
||||
if (foundAccessor === undefined) {
|
||||
throw new Error(
|
||||
i18n.translate('visualizations.function.findAccessorOrFail.error.accessor', {
|
||||
defaultMessage: 'Provided column name or index is invalid: {accessor}',
|
||||
values: { accessor },
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
return foundAccessor;
|
||||
};
|
||||
|
||||
export const getAccessorByDimension = (
|
||||
dimension: string | ExpressionValueVisDimension,
|
||||
columns: DatatableColumn[]
|
||||
) => {
|
||||
if (typeof dimension === 'string') {
|
||||
return dimension;
|
||||
}
|
||||
|
||||
const accessor = dimension.accessor;
|
||||
if (typeof accessor === 'number') {
|
||||
return columns[accessor].id;
|
||||
}
|
||||
|
||||
return accessor.id;
|
||||
};
|
11
src/plugins/visualizations/common/utils/index.ts
Normal file
11
src/plugins/visualizations/common/utils/index.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { prepareLogTable } from './prepare_log_table';
|
||||
export type { Dimension } from './prepare_log_table';
|
||||
export { findAccessorOrFail, getAccessorByDimension } from './accessors';
|
|
@ -6,9 +6,9 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { ExpressionValueVisDimension } from './expression_functions/vis_dimension';
|
||||
import { ExpressionValueXYDimension } from './expression_functions/xy_dimension';
|
||||
import { Datatable, DatatableColumn } from '../../expressions/common/expression_types/specs';
|
||||
import { ExpressionValueVisDimension } from '../expression_functions/vis_dimension';
|
||||
import { ExpressionValueXYDimension } from '../expression_functions/xy_dimension';
|
||||
import { Datatable, DatatableColumn } from '../../../expressions/common/expression_types/specs';
|
||||
|
||||
export type Dimension = [
|
||||
Array<ExpressionValueVisDimension | ExpressionValueXYDimension> | undefined,
|
|
@ -16,7 +16,7 @@
|
|||
],
|
||||
"optionalPlugins": [ "home", "share", "usageCollection", "spaces", "savedObjectsTaggingOss"],
|
||||
"requiredBundles": ["kibanaUtils", "discover", "kibanaReact", "home"],
|
||||
"extraPublicDirs": ["common/constants", "common/prepare_log_table", "common/expression_functions"],
|
||||
"extraPublicDirs": ["common/constants", "common/utils", "common/expression_functions"],
|
||||
"owner": {
|
||||
"name": "Vis Editors",
|
||||
"githubTeam": "kibana-vis-editors"
|
||||
|
|
|
@ -1 +1 @@
|
|||
"[metricVis] > [visdimension] > Column name or index provided is invalid"
|
||||
"[metricVis] > [visdimension] > Provided column name or index is invalid: 0"
|
|
@ -1 +1 @@
|
|||
"[tagcloud] > [visdimension] > Column name or index provided is invalid"
|
||||
"[tagcloud] > [visdimension] > Provided column name or index is invalid: 0"
|
|
@ -0,0 +1 @@
|
|||
"[metricVis] > [visdimension] > Provided column name or index is invalid: 0"
|
|
@ -0,0 +1 @@
|
|||
"[tagcloud] > [visdimension] > Provided column name or index is invalid: 0"
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { GaugeState } from '../../../../../../src/plugins/chart_expressions/expression_gauge/common';
|
||||
import { GaugeState as GaugeStateOriginal } from '../../../../../../src/plugins/chart_expressions/expression_gauge/common';
|
||||
import { LayerType } from '../../../common/';
|
||||
|
||||
export const LENS_GAUGE_ID = 'lnsGauge';
|
||||
|
@ -17,7 +17,19 @@ export const GROUP_ID = {
|
|||
GOAL: 'goal',
|
||||
} as const;
|
||||
|
||||
type GaugeState = Omit<GaugeStateOriginal, 'metric' | 'goal' | 'min' | 'max'> & {
|
||||
metricAccessor?: string;
|
||||
minAccessor?: string;
|
||||
maxAccessor?: string;
|
||||
goalAccessor?: string;
|
||||
};
|
||||
|
||||
export type GaugeVisualizationState = GaugeState & {
|
||||
layerId: string;
|
||||
layerType: LayerType;
|
||||
};
|
||||
|
||||
export type GaugeExpressionState = GaugeStateOriginal & {
|
||||
layerId: string;
|
||||
layerType: LayerType;
|
||||
};
|
||||
|
|
|
@ -39,6 +39,7 @@ import type { VisualizationDimensionEditorProps } from '../../types';
|
|||
import './dimension_editor.scss';
|
||||
import { GaugeVisualizationState } from './constants';
|
||||
import { defaultPaletteParams } from './palette_config';
|
||||
import { getAccessorsFromState } from './utils';
|
||||
|
||||
export function GaugeDimensionEditor(
|
||||
props: VisualizationDimensionEditorProps<GaugeVisualizationState> & {
|
||||
|
@ -57,11 +58,13 @@ export function GaugeDimensionEditor(
|
|||
return null;
|
||||
}
|
||||
|
||||
const accessors = getAccessorsFromState(state);
|
||||
|
||||
const hasDynamicColoring = state?.colorMode === 'palette';
|
||||
|
||||
const currentMinMax = {
|
||||
min: getMinValue(firstRow, state),
|
||||
max: getMaxValue(firstRow, state),
|
||||
min: getMinValue(firstRow, accessors),
|
||||
max: getMaxValue(firstRow, accessors),
|
||||
};
|
||||
|
||||
const activePalette = state?.palette || {
|
||||
|
@ -107,12 +110,12 @@ export function GaugeDimensionEditor(
|
|||
stops: displayStops,
|
||||
},
|
||||
},
|
||||
ticksPosition: GaugeTicksPositions.bands,
|
||||
colorMode: GaugeColorModes.palette,
|
||||
ticksPosition: GaugeTicksPositions.BANDS,
|
||||
colorMode: GaugeColorModes.PALETTE,
|
||||
}
|
||||
: {
|
||||
ticksPosition: GaugeTicksPositions.auto,
|
||||
colorMode: GaugeColorModes.none,
|
||||
ticksPosition: GaugeTicksPositions.AUTO,
|
||||
colorMode: GaugeColorModes.NONE,
|
||||
};
|
||||
|
||||
setState({
|
||||
|
@ -221,14 +224,14 @@ export function GaugeDimensionEditor(
|
|||
})}
|
||||
data-test-subj="lens-toolbar-gauge-ticks-position-switch"
|
||||
showLabel={false}
|
||||
checked={state.ticksPosition === GaugeTicksPositions.bands}
|
||||
checked={state.ticksPosition === GaugeTicksPositions.BANDS}
|
||||
onChange={() => {
|
||||
setState({
|
||||
...state,
|
||||
ticksPosition:
|
||||
state.ticksPosition === GaugeTicksPositions.bands
|
||||
? GaugeTicksPositions.auto
|
||||
: GaugeTicksPositions.bands,
|
||||
state.ticksPosition === GaugeTicksPositions.BANDS
|
||||
? GaugeTicksPositions.AUTO
|
||||
: GaugeTicksPositions.BANDS,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
|
|
|
@ -41,7 +41,7 @@ describe('gauge suggestions', () => {
|
|||
changeType: 'unchanged' as const,
|
||||
},
|
||||
state: {
|
||||
shape: GaugeShapes.horizontalBullet,
|
||||
shape: GaugeShapes.HORIZONTAL_BULLET,
|
||||
layerId: 'first',
|
||||
layerType: layerTypes.DATA,
|
||||
} as GaugeVisualizationState,
|
||||
|
@ -75,7 +75,7 @@ describe('gauge suggestions', () => {
|
|||
changeType: 'initial',
|
||||
},
|
||||
state: {
|
||||
shape: GaugeShapes.horizontalBullet,
|
||||
shape: GaugeShapes.HORIZONTAL_BULLET,
|
||||
layerId: 'first',
|
||||
layerType: layerTypes.DATA,
|
||||
minAccessor: 'some-field',
|
||||
|
@ -150,7 +150,7 @@ describe('shows suggestions', () => {
|
|||
state: {
|
||||
layerId: 'first',
|
||||
layerType: layerTypes.DATA,
|
||||
shape: GaugeShapes.horizontalBullet,
|
||||
shape: GaugeShapes.HORIZONTAL_BULLET,
|
||||
metricAccessor: 'metric-column',
|
||||
labelMajorMode: 'auto',
|
||||
ticksPosition: 'auto',
|
||||
|
@ -169,7 +169,7 @@ describe('shows suggestions', () => {
|
|||
layerId: 'first',
|
||||
layerType: 'data',
|
||||
metricAccessor: 'metric-column',
|
||||
shape: GaugeShapes.verticalBullet,
|
||||
shape: GaugeShapes.VERTICAL_BULLET,
|
||||
ticksPosition: 'auto',
|
||||
labelMajorMode: 'auto',
|
||||
},
|
||||
|
@ -188,17 +188,17 @@ describe('shows suggestions', () => {
|
|||
state: {
|
||||
layerId: 'first',
|
||||
layerType: layerTypes.DATA,
|
||||
shape: GaugeShapes.horizontalBullet,
|
||||
shape: GaugeShapes.HORIZONTAL_BULLET,
|
||||
metricAccessor: 'metric-column',
|
||||
} as GaugeVisualizationState,
|
||||
keptLayerIds: ['first'],
|
||||
subVisualizationId: GaugeShapes.verticalBullet,
|
||||
subVisualizationId: GaugeShapes.VERTICAL_BULLET,
|
||||
})
|
||||
).toEqual([
|
||||
{
|
||||
state: {
|
||||
layerType: layerTypes.DATA,
|
||||
shape: GaugeShapes.verticalBullet,
|
||||
shape: GaugeShapes.VERTICAL_BULLET,
|
||||
metricAccessor: 'metric-column',
|
||||
labelMajorMode: 'auto',
|
||||
ticksPosition: 'auto',
|
||||
|
|
|
@ -48,9 +48,9 @@ export const getSuggestions: Visualization<GaugeVisualizationState>['getSuggesti
|
|||
}
|
||||
|
||||
const shape: GaugeShape =
|
||||
state?.shape === GaugeShapes.verticalBullet
|
||||
? GaugeShapes.verticalBullet
|
||||
: GaugeShapes.horizontalBullet;
|
||||
state?.shape === GaugeShapes.VERTICAL_BULLET
|
||||
? GaugeShapes.VERTICAL_BULLET
|
||||
: GaugeShapes.HORIZONTAL_BULLET;
|
||||
|
||||
const baseSuggestion = {
|
||||
state: {
|
||||
|
@ -58,8 +58,8 @@ export const getSuggestions: Visualization<GaugeVisualizationState>['getSuggesti
|
|||
shape,
|
||||
layerId: table.layerId,
|
||||
layerType: layerTypes.DATA,
|
||||
ticksPosition: GaugeTicksPositions.auto,
|
||||
labelMajorMode: GaugeLabelMajorModes.auto,
|
||||
ticksPosition: GaugeTicksPositions.AUTO,
|
||||
labelMajorMode: GaugeLabelMajorModes.AUTO,
|
||||
},
|
||||
title: i18n.translate('xpack.lens.gauge.gaugeLabel', {
|
||||
defaultMessage: 'Gauge',
|
||||
|
@ -77,9 +77,9 @@ export const getSuggestions: Visualization<GaugeVisualizationState>['getSuggesti
|
|||
...baseSuggestion.state,
|
||||
...state,
|
||||
shape:
|
||||
state?.shape === GaugeShapes.verticalBullet
|
||||
? GaugeShapes.horizontalBullet
|
||||
: GaugeShapes.verticalBullet,
|
||||
state?.shape === GaugeShapes.VERTICAL_BULLET
|
||||
? GaugeShapes.HORIZONTAL_BULLET
|
||||
: GaugeShapes.VERTICAL_BULLET,
|
||||
},
|
||||
},
|
||||
]
|
||||
|
@ -97,9 +97,9 @@ export const getSuggestions: Visualization<GaugeVisualizationState>['getSuggesti
|
|||
...baseSuggestion.state,
|
||||
metricAccessor: table.columns[0].columnId,
|
||||
shape:
|
||||
state?.shape === GaugeShapes.verticalBullet
|
||||
? GaugeShapes.horizontalBullet
|
||||
: GaugeShapes.verticalBullet,
|
||||
state?.shape === GaugeShapes.VERTICAL_BULLET
|
||||
? GaugeShapes.HORIZONTAL_BULLET
|
||||
: GaugeShapes.VERTICAL_BULLET,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
|
16
x-pack/plugins/lens/public/visualizations/gauge/utils.ts
Normal file
16
x-pack/plugins/lens/public/visualizations/gauge/utils.ts
Normal file
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* 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; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import type { Accessors } from '../../../../../../src/plugins/chart_expressions/expression_gauge/common';
|
||||
import { GaugeVisualizationState } from './constants';
|
||||
|
||||
export const getAccessorsFromState = (state?: GaugeVisualizationState): Accessors | undefined => {
|
||||
const { minAccessor, maxAccessor, goalAccessor, metricAccessor } = state ?? {};
|
||||
if (!metricAccessor && !maxAccessor && !goalAccessor && !metricAccessor) {
|
||||
return;
|
||||
}
|
||||
return { min: minAccessor, max: maxAccessor, goal: goalAccessor, metric: metricAccessor };
|
||||
};
|
|
@ -396,7 +396,7 @@ describe('gauge', () => {
|
|||
colorMode: 'palette',
|
||||
ticksPosition: 'bands',
|
||||
};
|
||||
test('removes metricAccessor correctly', () => {
|
||||
test('removes metric correctly', () => {
|
||||
expect(
|
||||
getGaugeVisualization({
|
||||
paletteService,
|
||||
|
@ -411,7 +411,7 @@ describe('gauge', () => {
|
|||
minAccessor: 'min-accessor',
|
||||
});
|
||||
});
|
||||
test('removes minAccessor correctly', () => {
|
||||
test('removes min correctly', () => {
|
||||
expect(
|
||||
getGaugeVisualization({
|
||||
paletteService,
|
||||
|
@ -443,7 +443,7 @@ describe('gauge', () => {
|
|||
it('should return the type only if the layer is in the state', () => {
|
||||
const state: GaugeVisualizationState = {
|
||||
...exampleState(),
|
||||
minAccessor: 'minAccessor',
|
||||
minAccessor: 'min-accessor',
|
||||
goalAccessor: 'value-accessor',
|
||||
};
|
||||
const instance = getGaugeVisualization({
|
||||
|
@ -487,10 +487,10 @@ describe('gauge', () => {
|
|||
type: 'function',
|
||||
function: 'gauge',
|
||||
arguments: {
|
||||
metricAccessor: ['metric-accessor'],
|
||||
minAccessor: ['min-accessor'],
|
||||
maxAccessor: ['max-accessor'],
|
||||
goalAccessor: ['goal-accessor'],
|
||||
metric: ['metric-accessor'],
|
||||
min: ['min-accessor'],
|
||||
max: ['max-accessor'],
|
||||
goal: ['goal-accessor'],
|
||||
colorMode: ['none'],
|
||||
ticksPosition: ['auto'],
|
||||
labelMajorMode: ['auto'],
|
||||
|
@ -507,7 +507,7 @@ describe('gauge', () => {
|
|||
const state: GaugeVisualizationState = {
|
||||
...exampleState(),
|
||||
layerId: 'first',
|
||||
minAccessor: 'minAccessor',
|
||||
minAccessor: 'min-accessor',
|
||||
};
|
||||
expect(
|
||||
getGaugeVisualization({
|
||||
|
|
|
@ -27,12 +27,18 @@ import {
|
|||
import { PaletteRegistry } from '../../../../../../src/plugins/charts/public';
|
||||
import type { DatasourcePublicAPI, OperationMetadata, Visualization } from '../../types';
|
||||
import { getSuggestions } from './suggestions';
|
||||
import { GROUP_ID, LENS_GAUGE_ID, GaugeVisualizationState } from './constants';
|
||||
import {
|
||||
GROUP_ID,
|
||||
LENS_GAUGE_ID,
|
||||
GaugeVisualizationState,
|
||||
GaugeExpressionState,
|
||||
} from './constants';
|
||||
import { GaugeToolbar } from './toolbar_component';
|
||||
import { applyPaletteParams, CUSTOM_PALETTE } from '../../shared_components';
|
||||
import { GaugeDimensionEditor } from './dimension_editor';
|
||||
import { CustomPaletteParams, layerTypes } from '../../../common';
|
||||
import { generateId } from '../../id_generator';
|
||||
import { getAccessorsFromState } from './utils';
|
||||
|
||||
const groupLabelForGauge = i18n.translate('xpack.lens.metric.groupLabel', {
|
||||
defaultMessage: 'Goal and single value',
|
||||
|
@ -79,9 +85,11 @@ const checkInvalidConfiguration = (row?: DatatableRow, state?: GaugeVisualizatio
|
|||
if (!row || !state) {
|
||||
return;
|
||||
}
|
||||
const minValue = getValueFromAccessor('minAccessor', row, state);
|
||||
const maxValue = getValueFromAccessor('maxAccessor', row, state);
|
||||
if (maxValue != null && minValue != null) {
|
||||
const minAccessor = state?.minAccessor;
|
||||
const maxAccessor = state?.maxAccessor;
|
||||
const minValue = minAccessor ? getValueFromAccessor(minAccessor, row) : undefined;
|
||||
const maxValue = maxAccessor ? getValueFromAccessor(maxAccessor, row) : undefined;
|
||||
if (maxValue !== null && maxValue !== undefined && minValue != null && minValue !== undefined) {
|
||||
if (maxValue < minValue) {
|
||||
return {
|
||||
invalid: true,
|
||||
|
@ -108,7 +116,7 @@ const toExpression = (
|
|||
paletteService: PaletteRegistry,
|
||||
state: GaugeVisualizationState,
|
||||
datasourceLayers: Record<string, DatasourcePublicAPI>,
|
||||
attributes?: Partial<Omit<GaugeArguments, keyof GaugeVisualizationState | 'ariaLabel'>>
|
||||
attributes?: Partial<Omit<GaugeArguments, keyof GaugeExpressionState | 'ariaLabel'>>
|
||||
): Ast | null => {
|
||||
const datasource = datasourceLayers[state.layerId];
|
||||
|
||||
|
@ -124,11 +132,11 @@ const toExpression = (
|
|||
type: 'function',
|
||||
function: EXPRESSION_GAUGE_NAME,
|
||||
arguments: {
|
||||
metricAccessor: [state.metricAccessor ?? ''],
|
||||
minAccessor: [state.minAccessor ?? ''],
|
||||
maxAccessor: [state.maxAccessor ?? ''],
|
||||
goalAccessor: [state.goalAccessor ?? ''],
|
||||
shape: [state.shape ?? GaugeShapes.horizontalBullet],
|
||||
metric: state.metricAccessor ? [state.metricAccessor] : [],
|
||||
min: state.minAccessor ? [state.minAccessor] : [],
|
||||
max: state.maxAccessor ? [state.maxAccessor] : [],
|
||||
goal: state.goalAccessor ? [state.goalAccessor] : [],
|
||||
shape: [state.shape ?? GaugeShapes.HORIZONTAL_BULLET],
|
||||
colorMode: [state?.colorMode ?? 'none'],
|
||||
palette: state.palette?.params
|
||||
? [
|
||||
|
@ -157,12 +165,12 @@ export const getGaugeVisualization = ({
|
|||
visualizationTypes: [
|
||||
{
|
||||
...CHART_NAMES.horizontalBullet,
|
||||
id: GaugeShapes.horizontalBullet,
|
||||
id: GaugeShapes.HORIZONTAL_BULLET,
|
||||
showExperimentalBadge: true,
|
||||
},
|
||||
{
|
||||
...CHART_NAMES.verticalBullet,
|
||||
id: GaugeShapes.verticalBullet,
|
||||
id: GaugeShapes.VERTICAL_BULLET,
|
||||
showExperimentalBadge: true,
|
||||
},
|
||||
],
|
||||
|
@ -184,7 +192,7 @@ export const getGaugeVisualization = ({
|
|||
},
|
||||
|
||||
getDescription(state) {
|
||||
if (state.shape === GaugeShapes.horizontalBullet) {
|
||||
if (state.shape === GaugeShapes.HORIZONTAL_BULLET) {
|
||||
return CHART_NAMES.horizontalBullet;
|
||||
}
|
||||
return CHART_NAMES.verticalBullet;
|
||||
|
@ -194,9 +202,9 @@ export const getGaugeVisualization = ({
|
|||
return {
|
||||
...state,
|
||||
shape:
|
||||
visualizationTypeId === GaugeShapes.horizontalBullet
|
||||
? GaugeShapes.horizontalBullet
|
||||
: GaugeShapes.verticalBullet,
|
||||
visualizationTypeId === GaugeShapes.HORIZONTAL_BULLET
|
||||
? GaugeShapes.HORIZONTAL_BULLET
|
||||
: GaugeShapes.VERTICAL_BULLET,
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -205,7 +213,7 @@ export const getGaugeVisualization = ({
|
|||
state || {
|
||||
layerId: addNewLayer(),
|
||||
layerType: layerTypes.DATA,
|
||||
shape: GaugeShapes.horizontalBullet,
|
||||
shape: GaugeShapes.HORIZONTAL_BULLET,
|
||||
palette: mainPalette,
|
||||
ticksPosition: 'auto',
|
||||
labelMajorMode: 'auto',
|
||||
|
@ -218,9 +226,16 @@ export const getGaugeVisualization = ({
|
|||
const hasColoring = Boolean(state.colorMode !== 'none' && state.palette?.params?.stops);
|
||||
|
||||
const row = state?.layerId ? frame?.activeData?.[state?.layerId]?.rows?.[0] : undefined;
|
||||
const { metricAccessor } = state ?? {};
|
||||
|
||||
const accessors = getAccessorsFromState(state);
|
||||
|
||||
let palette;
|
||||
if (!(row == null || state?.metricAccessor == null || state?.palette == null || !hasColoring)) {
|
||||
const currentMinMax = { min: getMinValue(row, state), max: getMaxValue(row, state) };
|
||||
if (!(row == null || metricAccessor == null || state?.palette == null || !hasColoring)) {
|
||||
const currentMinMax = {
|
||||
min: getMinValue(row, accessors),
|
||||
max: getMaxValue(row, accessors),
|
||||
};
|
||||
|
||||
const displayStops = applyPaletteParams(paletteService, state?.palette, currentMinMax);
|
||||
palette = displayStops.map(({ color }) => color);
|
||||
|
@ -236,22 +251,22 @@ export const getGaugeVisualization = ({
|
|||
groupLabel: i18n.translate('xpack.lens.gauge.metricLabel', {
|
||||
defaultMessage: 'Metric',
|
||||
}),
|
||||
accessors: state.metricAccessor
|
||||
accessors: metricAccessor
|
||||
? [
|
||||
palette
|
||||
? {
|
||||
columnId: state.metricAccessor,
|
||||
columnId: metricAccessor,
|
||||
triggerIcon: 'colorBy',
|
||||
palette,
|
||||
}
|
||||
: {
|
||||
columnId: state.metricAccessor,
|
||||
columnId: metricAccessor,
|
||||
triggerIcon: 'none',
|
||||
},
|
||||
]
|
||||
: [],
|
||||
filterOperations: isNumericDynamicMetric,
|
||||
supportsMoreColumns: !state.metricAccessor,
|
||||
supportsMoreColumns: !metricAccessor,
|
||||
required: true,
|
||||
dataTestSubj: 'lnsGauge_metricDimensionPanel',
|
||||
enableDimensionEditor: true,
|
||||
|
@ -269,7 +284,7 @@ export const getGaugeVisualization = ({
|
|||
supportsMoreColumns: !state.minAccessor,
|
||||
dataTestSubj: 'lnsGauge_minDimensionPanel',
|
||||
prioritizedOperation: 'min',
|
||||
suggestedValue: () => (state.metricAccessor ? getMinValue(row, state) : undefined),
|
||||
suggestedValue: () => (state.metricAccessor ? getMinValue(row, accessors) : undefined),
|
||||
...invalidProps,
|
||||
},
|
||||
{
|
||||
|
@ -285,7 +300,7 @@ export const getGaugeVisualization = ({
|
|||
supportsMoreColumns: !state.maxAccessor,
|
||||
dataTestSubj: 'lnsGauge_maxDimensionPanel',
|
||||
prioritizedOperation: 'max',
|
||||
suggestedValue: () => (state.metricAccessor ? getMaxValue(row, state) : undefined),
|
||||
suggestedValue: () => (state.metricAccessor ? getMaxValue(row, accessors) : undefined),
|
||||
...invalidProps,
|
||||
},
|
||||
{
|
||||
|
@ -368,10 +383,10 @@ export const getGaugeVisualization = ({
|
|||
|
||||
getSupportedLayers(state, frame) {
|
||||
const row = state?.layerId ? frame?.activeData?.[state?.layerId]?.rows?.[0] : undefined;
|
||||
|
||||
const minAccessorValue = getMinValue(row, state);
|
||||
const maxAccessorValue = getMaxValue(row, state);
|
||||
const goalAccessorValue = getGoalValue(row, state);
|
||||
const accessors = getAccessorsFromState(state);
|
||||
const minValue = getMinValue(row, accessors);
|
||||
const maxValue = getMaxValue(row, accessors);
|
||||
const goalValue = getGoalValue(row, accessors);
|
||||
|
||||
return [
|
||||
{
|
||||
|
@ -386,21 +401,21 @@ export const getGaugeVisualization = ({
|
|||
columnId: generateId(),
|
||||
dataType: 'number',
|
||||
label: 'minAccessor',
|
||||
staticValue: minAccessorValue,
|
||||
staticValue: minValue,
|
||||
},
|
||||
{
|
||||
groupId: 'max',
|
||||
columnId: generateId(),
|
||||
dataType: 'number',
|
||||
label: 'maxAccessor',
|
||||
staticValue: maxAccessorValue,
|
||||
staticValue: maxValue,
|
||||
},
|
||||
{
|
||||
groupId: 'goal',
|
||||
columnId: generateId(),
|
||||
dataType: 'number',
|
||||
label: 'goalAccessor',
|
||||
staticValue: goalAccessorValue,
|
||||
staticValue: goalValue,
|
||||
},
|
||||
]
|
||||
: undefined,
|
||||
|
|
|
@ -6152,7 +6152,6 @@
|
|||
"visualizations.function.range.help": "範囲オブジェクトを生成します",
|
||||
"visualizations.function.range.to.help": "範囲の終了",
|
||||
"visualizations.function.visDimension.accessor.help": "使用するデータセット内の列(列インデックスまたは列名)",
|
||||
"visualizations.function.visDimension.error.accessor": "入力された列名またはインデックスが無効です",
|
||||
"visualizations.function.visDimension.format.help": "フォーマット",
|
||||
"visualizations.function.visDimension.formatParams.help": "フォーマットパラメーター",
|
||||
"visualizations.function.visDimension.help": "visConfig ディメンションオブジェクトを生成します",
|
||||
|
|
|
@ -5953,7 +5953,6 @@
|
|||
"visualizations.function.range.help": "生成范围对象",
|
||||
"visualizations.function.range.to.help": "范围结束",
|
||||
"visualizations.function.visDimension.accessor.help": "要使用的数据集列(列索引或列名称)",
|
||||
"visualizations.function.visDimension.error.accessor": "提供的列名称或索引无效",
|
||||
"visualizations.function.visDimension.format.help": "格式",
|
||||
"visualizations.function.visDimension.formatParams.help": "格式参数",
|
||||
"visualizations.function.visDimension.help": "生成 visConfig 维度对象",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue