mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
parent
b02858b20d
commit
86bb03d6f9
14 changed files with 552 additions and 17 deletions
|
@ -161,7 +161,7 @@ export function WorkspacePanel({
|
|||
|
||||
const expression = useMemo(
|
||||
() => {
|
||||
if (!configurationValidationError) {
|
||||
if (!configurationValidationError || configurationValidationError.length === 0) {
|
||||
try {
|
||||
return buildExpression({
|
||||
visualization: activeVisualization,
|
||||
|
|
|
@ -37,12 +37,14 @@ export class IndexPatternDatasource {
|
|||
getIndexPatternDatasource,
|
||||
renameColumns,
|
||||
formatColumn,
|
||||
counterRate,
|
||||
getTimeScaleFunction,
|
||||
getSuffixFormatter,
|
||||
} = await import('../async_services');
|
||||
return core.getStartServices().then(([coreStart, { data }]) => {
|
||||
data.fieldFormats.register([getSuffixFormatter(data.fieldFormats.deserialize)]);
|
||||
expressions.registerFunction(getTimeScaleFunction(data));
|
||||
expressions.registerFunction(counterRate);
|
||||
expressions.registerFunction(renameColumns);
|
||||
expressions.registerFunction(formatColumn);
|
||||
return getIndexPatternDatasource({
|
||||
|
|
|
@ -661,19 +661,30 @@ describe('IndexPattern Data Source', () => {
|
|||
it('should skip columns that are being referenced', () => {
|
||||
publicAPI = indexPatternDatasource.getPublicAPI({
|
||||
state: {
|
||||
...enrichBaseState(baseState),
|
||||
layers: {
|
||||
first: {
|
||||
indexPatternId: '1',
|
||||
columnOrder: ['col1', 'col2'],
|
||||
columns: {
|
||||
// @ts-ignore this is too little information for a real column
|
||||
col1: {
|
||||
label: 'Sum',
|
||||
dataType: 'number',
|
||||
},
|
||||
isBucketed: false,
|
||||
|
||||
operationType: 'sum',
|
||||
sourceField: 'test',
|
||||
params: {},
|
||||
} as IndexPatternColumn,
|
||||
col2: {
|
||||
// @ts-expect-error update once we have a reference operation outside tests
|
||||
label: 'Cumulative sum',
|
||||
dataType: 'number',
|
||||
isBucketed: false,
|
||||
|
||||
operationType: 'cumulative_sum',
|
||||
references: ['col1'],
|
||||
},
|
||||
params: {},
|
||||
} as IndexPatternColumn,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -78,6 +78,7 @@ export function columnToOperation(column: IndexPatternColumn, uniqueLabel?: stri
|
|||
export * from './rename_columns';
|
||||
export * from './format_column';
|
||||
export * from './time_scale';
|
||||
export * from './counter_rate';
|
||||
export * from './suffix_formatter';
|
||||
|
||||
export function getIndexPatternDatasource({
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedIndexPatternColumn, ReferenceBasedIndexPatternColumn } from '../column_types';
|
||||
import { IndexPatternLayer } from '../../../types';
|
||||
import { checkForDateHistogram, dateBasedOperationToExpression, hasDateField } from './utils';
|
||||
import { OperationDefinition } from '..';
|
||||
|
||||
const ofName = (name?: string) => {
|
||||
return i18n.translate('xpack.lens.indexPattern.CounterRateOf', {
|
||||
defaultMessage: 'Counter rate of {name}',
|
||||
values: {
|
||||
name:
|
||||
name ??
|
||||
i18n.translate('xpack.lens.indexPattern.incompleteOperation', {
|
||||
defaultMessage: '(incomplete)',
|
||||
}),
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export type CounterRateIndexPatternColumn = FormattedIndexPatternColumn &
|
||||
ReferenceBasedIndexPatternColumn & {
|
||||
operationType: 'counter_rate';
|
||||
};
|
||||
|
||||
export const counterRateOperation: OperationDefinition<
|
||||
CounterRateIndexPatternColumn,
|
||||
'fullReference'
|
||||
> = {
|
||||
type: 'counter_rate',
|
||||
priority: 1,
|
||||
displayName: i18n.translate('xpack.lens.indexPattern.counterRate', {
|
||||
defaultMessage: 'Counter rate',
|
||||
}),
|
||||
input: 'fullReference',
|
||||
selectionStyle: 'field',
|
||||
requiredReferences: [
|
||||
{
|
||||
input: ['field'],
|
||||
specificOperations: ['max'],
|
||||
validateMetadata: (meta) => meta.dataType === 'number' && !meta.isBucketed,
|
||||
},
|
||||
],
|
||||
getPossibleOperation: () => {
|
||||
return {
|
||||
dataType: 'number',
|
||||
isBucketed: false,
|
||||
scale: 'ratio',
|
||||
};
|
||||
},
|
||||
getDefaultLabel: (column, indexPattern, columns) => {
|
||||
return ofName(columns[column.references[0]]?.label);
|
||||
},
|
||||
toExpression: (layer, columnId) => {
|
||||
return dateBasedOperationToExpression(layer, columnId, 'lens_counter_rate');
|
||||
},
|
||||
buildColumn: ({ referenceIds, previousColumn, layer }) => {
|
||||
const metric = layer.columns[referenceIds[0]];
|
||||
return {
|
||||
label: ofName(metric?.label),
|
||||
dataType: 'number',
|
||||
operationType: 'counter_rate',
|
||||
isBucketed: false,
|
||||
scale: 'ratio',
|
||||
references: referenceIds,
|
||||
params:
|
||||
previousColumn?.dataType === 'number' &&
|
||||
previousColumn.params &&
|
||||
'format' in previousColumn.params &&
|
||||
previousColumn.params.format
|
||||
? { format: previousColumn.params.format }
|
||||
: undefined,
|
||||
};
|
||||
},
|
||||
isTransferable: (column, newIndexPattern) => {
|
||||
return hasDateField(newIndexPattern);
|
||||
},
|
||||
getErrorMessage: (layer: IndexPatternLayer) => {
|
||||
return checkForDateHistogram(
|
||||
layer,
|
||||
i18n.translate('xpack.lens.indexPattern.counterRate', {
|
||||
defaultMessage: 'Counter rate',
|
||||
})
|
||||
);
|
||||
},
|
||||
};
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedIndexPatternColumn, ReferenceBasedIndexPatternColumn } from '../column_types';
|
||||
import { IndexPatternLayer } from '../../../types';
|
||||
import { checkForDateHistogram, dateBasedOperationToExpression } from './utils';
|
||||
import { OperationDefinition } from '..';
|
||||
|
||||
const ofName = (name?: string) => {
|
||||
return i18n.translate('xpack.lens.indexPattern.cumulativeSumOf', {
|
||||
defaultMessage: 'Cumulative sum rate of {name}',
|
||||
values: {
|
||||
name:
|
||||
name ??
|
||||
i18n.translate('xpack.lens.indexPattern.incompleteOperation', {
|
||||
defaultMessage: '(incomplete)',
|
||||
}),
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export type CumulativeSumIndexPatternColumn = FormattedIndexPatternColumn &
|
||||
ReferenceBasedIndexPatternColumn & {
|
||||
operationType: 'cumulative_sum';
|
||||
};
|
||||
|
||||
export const cumulativeSumOperation: OperationDefinition<
|
||||
CumulativeSumIndexPatternColumn,
|
||||
'fullReference'
|
||||
> = {
|
||||
type: 'cumulative_sum',
|
||||
priority: 1,
|
||||
displayName: i18n.translate('xpack.lens.indexPattern.cumulativeSum', {
|
||||
defaultMessage: 'Cumulative sum',
|
||||
}),
|
||||
input: 'fullReference',
|
||||
selectionStyle: 'field',
|
||||
requiredReferences: [
|
||||
{
|
||||
input: ['field'],
|
||||
specificOperations: ['count', 'sum'],
|
||||
validateMetadata: (meta) => meta.dataType === 'number' && !meta.isBucketed,
|
||||
},
|
||||
],
|
||||
getPossibleOperation: () => {
|
||||
return {
|
||||
dataType: 'number',
|
||||
isBucketed: false,
|
||||
scale: 'ratio',
|
||||
};
|
||||
},
|
||||
getDefaultLabel: (column, indexPattern, columns) => {
|
||||
return ofName(columns[column.references[0]]?.label);
|
||||
},
|
||||
toExpression: (layer, columnId) => {
|
||||
return dateBasedOperationToExpression(layer, columnId, 'cumulative_sum');
|
||||
},
|
||||
buildColumn: ({ referenceIds, previousColumn, layer }) => {
|
||||
const metric = layer.columns[referenceIds[0]];
|
||||
return {
|
||||
label: ofName(metric?.label),
|
||||
dataType: 'number',
|
||||
operationType: 'cumulative_sum',
|
||||
isBucketed: false,
|
||||
scale: 'ratio',
|
||||
references: referenceIds,
|
||||
params:
|
||||
previousColumn?.dataType === 'number' &&
|
||||
previousColumn.params &&
|
||||
'format' in previousColumn.params &&
|
||||
previousColumn.params.format
|
||||
? { format: previousColumn.params.format }
|
||||
: undefined,
|
||||
};
|
||||
},
|
||||
isTransferable: () => {
|
||||
return true;
|
||||
},
|
||||
getErrorMessage: (layer: IndexPatternLayer) => {
|
||||
return checkForDateHistogram(
|
||||
layer,
|
||||
i18n.translate('xpack.lens.indexPattern.cumulativeSum', {
|
||||
defaultMessage: 'Cumulative sum',
|
||||
})
|
||||
);
|
||||
},
|
||||
};
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedIndexPatternColumn, ReferenceBasedIndexPatternColumn } from '../column_types';
|
||||
import { IndexPatternLayer } from '../../../types';
|
||||
import { checkForDateHistogram, dateBasedOperationToExpression, hasDateField } from './utils';
|
||||
import { OperationDefinition } from '..';
|
||||
|
||||
const ofName = (name?: string) => {
|
||||
return i18n.translate('xpack.lens.indexPattern.derivativeOf', {
|
||||
defaultMessage: 'Differences of {name}',
|
||||
values: {
|
||||
name:
|
||||
name ??
|
||||
i18n.translate('xpack.lens.indexPattern.incompleteOperation', {
|
||||
defaultMessage: '(incomplete)',
|
||||
}),
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export type DerivativeIndexPatternColumn = FormattedIndexPatternColumn &
|
||||
ReferenceBasedIndexPatternColumn & {
|
||||
operationType: 'derivative';
|
||||
};
|
||||
|
||||
export const derivativeOperation: OperationDefinition<
|
||||
DerivativeIndexPatternColumn,
|
||||
'fullReference'
|
||||
> = {
|
||||
type: 'derivative',
|
||||
priority: 1,
|
||||
displayName: i18n.translate('xpack.lens.indexPattern.derivative', {
|
||||
defaultMessage: 'Differences',
|
||||
}),
|
||||
input: 'fullReference',
|
||||
selectionStyle: 'full',
|
||||
requiredReferences: [
|
||||
{
|
||||
input: ['field'],
|
||||
validateMetadata: (meta) => meta.dataType === 'number' && !meta.isBucketed,
|
||||
},
|
||||
],
|
||||
getPossibleOperation: () => {
|
||||
return {
|
||||
dataType: 'number',
|
||||
isBucketed: false,
|
||||
scale: 'ratio',
|
||||
};
|
||||
},
|
||||
getDefaultLabel: (column, indexPattern, columns) => {
|
||||
return ofName(columns[column.references[0]]?.label);
|
||||
},
|
||||
toExpression: (layer, columnId) => {
|
||||
return dateBasedOperationToExpression(layer, columnId, 'derivative');
|
||||
},
|
||||
buildColumn: ({ referenceIds, previousColumn, layer }) => {
|
||||
const metric = layer.columns[referenceIds[0]];
|
||||
return {
|
||||
label: ofName(metric?.label),
|
||||
dataType: 'number',
|
||||
operationType: 'derivative',
|
||||
isBucketed: false,
|
||||
scale: 'ratio',
|
||||
references: referenceIds,
|
||||
params:
|
||||
previousColumn?.dataType === 'number' &&
|
||||
previousColumn.params &&
|
||||
'format' in previousColumn.params &&
|
||||
previousColumn.params.format
|
||||
? { format: previousColumn.params.format }
|
||||
: undefined,
|
||||
};
|
||||
},
|
||||
isTransferable: (column, newIndexPattern) => {
|
||||
return hasDateField(newIndexPattern);
|
||||
},
|
||||
getErrorMessage: (layer: IndexPatternLayer) => {
|
||||
return checkForDateHistogram(
|
||||
layer,
|
||||
i18n.translate('xpack.lens.indexPattern.derivative', {
|
||||
defaultMessage: 'Differences',
|
||||
})
|
||||
);
|
||||
},
|
||||
};
|
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export { counterRateOperation, CounterRateIndexPatternColumn } from './counter_rate';
|
||||
export { cumulativeSumOperation, CumulativeSumIndexPatternColumn } from './cumulative_sum';
|
||||
export { derivativeOperation, DerivativeIndexPatternColumn } from './derivative';
|
||||
export { movingAverageOperation, MovingAverageIndexPatternColumn } from './moving_average';
|
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { useState } from 'react';
|
||||
import React from 'react';
|
||||
import { EuiFormRow } from '@elastic/eui';
|
||||
import { EuiFieldNumber } from '@elastic/eui';
|
||||
import { FormattedIndexPatternColumn, ReferenceBasedIndexPatternColumn } from '../column_types';
|
||||
import { IndexPatternLayer } from '../../../types';
|
||||
import { checkForDateHistogram, dateBasedOperationToExpression, hasDateField } from './utils';
|
||||
import { updateColumnParam } from '../../layer_helpers';
|
||||
import { useDebounceWithOptions } from '../helpers';
|
||||
import type { OperationDefinition, ParamEditorProps } from '..';
|
||||
|
||||
const ofName = (name?: string) => {
|
||||
return i18n.translate('xpack.lens.indexPattern.movingAverageOf', {
|
||||
defaultMessage: 'Moving average of {name}',
|
||||
values: {
|
||||
name:
|
||||
name ??
|
||||
i18n.translate('xpack.lens.indexPattern.incompleteOperation', {
|
||||
defaultMessage: '(incomplete)',
|
||||
}),
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export type MovingAverageIndexPatternColumn = FormattedIndexPatternColumn &
|
||||
ReferenceBasedIndexPatternColumn & {
|
||||
operationType: 'moving_average';
|
||||
params: {
|
||||
window: number;
|
||||
};
|
||||
};
|
||||
|
||||
export const movingAverageOperation: OperationDefinition<
|
||||
MovingAverageIndexPatternColumn,
|
||||
'fullReference'
|
||||
> = {
|
||||
type: 'moving_average',
|
||||
priority: 1,
|
||||
displayName: i18n.translate('xpack.lens.indexPattern.movingAverage', {
|
||||
defaultMessage: 'Moving Average',
|
||||
}),
|
||||
input: 'fullReference',
|
||||
selectionStyle: 'full',
|
||||
requiredReferences: [
|
||||
{
|
||||
input: ['field'],
|
||||
validateMetadata: (meta) => meta.dataType === 'number' && !meta.isBucketed,
|
||||
},
|
||||
],
|
||||
getPossibleOperation: () => {
|
||||
return {
|
||||
dataType: 'number',
|
||||
isBucketed: false,
|
||||
scale: 'ratio',
|
||||
};
|
||||
},
|
||||
getDefaultLabel: (column, indexPattern, columns) => {
|
||||
return ofName(columns[column.references[0]]?.label);
|
||||
},
|
||||
toExpression: (layer, columnId) => {
|
||||
return dateBasedOperationToExpression(layer, columnId, 'moving_average', {
|
||||
window: [(layer.columns[columnId] as MovingAverageIndexPatternColumn).params.window],
|
||||
});
|
||||
},
|
||||
buildColumn: ({ referenceIds, previousColumn, layer }) => {
|
||||
const metric = layer.columns[referenceIds[0]];
|
||||
return {
|
||||
label: ofName(metric?.label),
|
||||
dataType: 'number',
|
||||
operationType: 'moving_average',
|
||||
isBucketed: false,
|
||||
scale: 'ratio',
|
||||
references: referenceIds,
|
||||
params:
|
||||
previousColumn?.dataType === 'number' &&
|
||||
previousColumn.params &&
|
||||
'format' in previousColumn.params &&
|
||||
previousColumn.params.format
|
||||
? { format: previousColumn.params.format, window: 5 }
|
||||
: { window: 5 },
|
||||
};
|
||||
},
|
||||
paramEditor: MovingAverageParamEditor,
|
||||
isTransferable: (column, newIndexPattern) => {
|
||||
return hasDateField(newIndexPattern);
|
||||
},
|
||||
getErrorMessage: (layer: IndexPatternLayer) => {
|
||||
return checkForDateHistogram(
|
||||
layer,
|
||||
i18n.translate('xpack.lens.indexPattern.movingAverage', {
|
||||
defaultMessage: 'Moving Average',
|
||||
})
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
function MovingAverageParamEditor({
|
||||
state,
|
||||
setState,
|
||||
currentColumn,
|
||||
layerId,
|
||||
}: ParamEditorProps<MovingAverageIndexPatternColumn>) {
|
||||
const [inputValue, setInputValue] = useState(String(currentColumn.params.window));
|
||||
|
||||
useDebounceWithOptions(
|
||||
() => {
|
||||
if (inputValue === '') {
|
||||
return;
|
||||
}
|
||||
const inputNumber = Number(inputValue);
|
||||
setState(
|
||||
updateColumnParam({
|
||||
state,
|
||||
layerId,
|
||||
currentColumn,
|
||||
paramName: 'window',
|
||||
value: inputNumber,
|
||||
})
|
||||
);
|
||||
},
|
||||
{ skipFirstRender: true },
|
||||
256,
|
||||
[inputValue]
|
||||
);
|
||||
return (
|
||||
<EuiFormRow
|
||||
label={i18n.translate('xpack.lens.indexPattern.movingAverage.window', {
|
||||
defaultMessage: 'Window size',
|
||||
})}
|
||||
display="columnCompressed"
|
||||
fullWidth
|
||||
>
|
||||
<EuiFieldNumber
|
||||
compressed
|
||||
value={inputValue}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setInputValue(e.target.value)}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { ExpressionFunctionAST } from '@kbn/interpreter/common';
|
||||
import { IndexPattern, IndexPatternLayer } from '../../../types';
|
||||
import { ReferenceBasedIndexPatternColumn } from '../column_types';
|
||||
|
||||
/**
|
||||
* Checks whether the current layer includes a date histogram and returns an error otherwise
|
||||
*/
|
||||
export function checkForDateHistogram(layer: IndexPatternLayer, name: string) {
|
||||
const buckets = layer.columnOrder.filter((colId) => layer.columns[colId].isBucketed);
|
||||
const hasDateHistogram = buckets.some(
|
||||
(colId) => layer.columns[colId].operationType === 'date_histogram'
|
||||
);
|
||||
if (hasDateHistogram) {
|
||||
return undefined;
|
||||
}
|
||||
return [
|
||||
i18n.translate('xpack.lens.indexPattern.calculations.dateHistogramErrorMessage', {
|
||||
defaultMessage:
|
||||
'{name} requires a date histogram to work. Choose a different function or add a date histogram.',
|
||||
values: {
|
||||
name,
|
||||
},
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
export function hasDateField(indexPattern: IndexPattern) {
|
||||
return indexPattern.fields.some((field) => field.type === 'date');
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an expression ast for a date based operation (cumulative sum, derivative, moving average, counter rate)
|
||||
*/
|
||||
export function dateBasedOperationToExpression(
|
||||
layer: IndexPatternLayer,
|
||||
columnId: string,
|
||||
functionName: string,
|
||||
additionalArgs: Record<string, unknown[]> = {}
|
||||
): ExpressionFunctionAST[] {
|
||||
const currentColumn = (layer.columns[columnId] as unknown) as ReferenceBasedIndexPatternColumn;
|
||||
const buckets = layer.columnOrder.filter((colId) => layer.columns[colId].isBucketed);
|
||||
const dateColumnIndex = buckets.findIndex(
|
||||
(colId) => layer.columns[colId].operationType === 'date_histogram'
|
||||
)!;
|
||||
buckets.splice(dateColumnIndex, 1);
|
||||
|
||||
return [
|
||||
{
|
||||
type: 'function',
|
||||
function: functionName,
|
||||
arguments: {
|
||||
by: buckets,
|
||||
inputColumnId: [currentColumn.references[0]],
|
||||
outputColumnId: [columnId],
|
||||
outputColumnName: [currentColumn.label],
|
||||
...additionalArgs,
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
|
@ -16,7 +16,7 @@ export interface BaseIndexPatternColumn extends Operation {
|
|||
// export interface FormattedIndexPatternColumn extends BaseIndexPatternColumn {
|
||||
export type FormattedIndexPatternColumn = BaseIndexPatternColumn & {
|
||||
params?: {
|
||||
format: {
|
||||
format?: {
|
||||
id: string;
|
||||
params?: {
|
||||
decimals: number;
|
||||
|
|
|
@ -23,6 +23,16 @@ import {
|
|||
MedianIndexPatternColumn,
|
||||
} from './metrics';
|
||||
import { dateHistogramOperation, DateHistogramIndexPatternColumn } from './date_histogram';
|
||||
import {
|
||||
cumulativeSumOperation,
|
||||
CumulativeSumIndexPatternColumn,
|
||||
counterRateOperation,
|
||||
CounterRateIndexPatternColumn,
|
||||
derivativeOperation,
|
||||
DerivativeIndexPatternColumn,
|
||||
movingAverageOperation,
|
||||
MovingAverageIndexPatternColumn,
|
||||
} from './calculations';
|
||||
import { countOperation, CountIndexPatternColumn } from './count';
|
||||
import { StateSetter, OperationMetadata } from '../../../types';
|
||||
import type { BaseIndexPatternColumn, ReferenceBasedIndexPatternColumn } from './column_types';
|
||||
|
@ -52,7 +62,11 @@ export type IndexPatternColumn =
|
|||
| CardinalityIndexPatternColumn
|
||||
| SumIndexPatternColumn
|
||||
| MedianIndexPatternColumn
|
||||
| CountIndexPatternColumn;
|
||||
| CountIndexPatternColumn
|
||||
| CumulativeSumIndexPatternColumn
|
||||
| CounterRateIndexPatternColumn
|
||||
| DerivativeIndexPatternColumn
|
||||
| MovingAverageIndexPatternColumn;
|
||||
|
||||
export type FieldBasedIndexPatternColumn = Extract<IndexPatternColumn, { sourceField: string }>;
|
||||
|
||||
|
@ -73,6 +87,10 @@ const internalOperationDefinitions = [
|
|||
medianOperation,
|
||||
countOperation,
|
||||
rangeOperation,
|
||||
cumulativeSumOperation,
|
||||
counterRateOperation,
|
||||
derivativeOperation,
|
||||
movingAverageOperation,
|
||||
];
|
||||
|
||||
export { termsOperation } from './terms';
|
||||
|
|
|
@ -424,7 +424,6 @@ export function deleteColumn({
|
|||
};
|
||||
}
|
||||
|
||||
// @ts-expect-error this fails statically because there are no references added
|
||||
const extraDeletions: string[] = 'references' in column ? column.references : [];
|
||||
|
||||
const hypotheticalColumns = { ...layer.columns };
|
||||
|
@ -452,11 +451,9 @@ export function getColumnOrder(layer: IndexPatternLayer): string[] {
|
|||
);
|
||||
// If a reference has another reference as input, put it last in sort order
|
||||
referenceBased.sort(([idA, a], [idB, b]) => {
|
||||
// @ts-expect-error not statically analyzed
|
||||
if ('references' in a && a.references.includes(idB)) {
|
||||
return 1;
|
||||
}
|
||||
// @ts-expect-error not statically analyzed
|
||||
if ('references' in b && b.references.includes(idA)) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -517,14 +514,12 @@ export function getErrorMessages(layer: IndexPatternLayer): string[] | undefined
|
|||
}
|
||||
|
||||
if ('references' in column) {
|
||||
// @ts-expect-error references are not statically analyzed yet
|
||||
column.references.forEach((referenceId, index) => {
|
||||
if (!layer.columns[referenceId]) {
|
||||
errors.push(
|
||||
i18n.translate('xpack.lens.indexPattern.missingReferenceError', {
|
||||
defaultMessage: 'Dimension {dimensionLabel} is incomplete',
|
||||
values: {
|
||||
// @ts-expect-error references are not statically analyzed yet
|
||||
dimensionLabel: column.label,
|
||||
},
|
||||
})
|
||||
|
@ -544,7 +539,6 @@ export function getErrorMessages(layer: IndexPatternLayer): string[] | undefined
|
|||
i18n.translate('xpack.lens.indexPattern.invalidReferenceConfiguration', {
|
||||
defaultMessage: 'Dimension {dimensionLabel} does not have a valid configuration',
|
||||
values: {
|
||||
// @ts-expect-error references are not statically analyzed yet
|
||||
dimensionLabel: column.label,
|
||||
},
|
||||
})
|
||||
|
@ -560,10 +554,7 @@ export function getErrorMessages(layer: IndexPatternLayer): string[] | undefined
|
|||
|
||||
export function isReferenced(layer: IndexPatternLayer, columnId: string): boolean {
|
||||
const allReferences = Object.values(layer.columns).flatMap((col) =>
|
||||
'references' in col
|
||||
? // @ts-expect-error not statically analyzed
|
||||
col.references
|
||||
: []
|
||||
'references' in col ? col.references : []
|
||||
);
|
||||
return allReferences.includes(columnId);
|
||||
}
|
||||
|
|
|
@ -247,6 +247,22 @@ describe('getOperationTypesForField', () => {
|
|||
"operationType": "sum",
|
||||
"type": "field",
|
||||
},
|
||||
Object {
|
||||
"operationType": "cumulative_sum",
|
||||
"type": "fullReference",
|
||||
},
|
||||
Object {
|
||||
"operationType": "counter_rate",
|
||||
"type": "fullReference",
|
||||
},
|
||||
Object {
|
||||
"operationType": "derivative",
|
||||
"type": "fullReference",
|
||||
},
|
||||
Object {
|
||||
"operationType": "moving_average",
|
||||
"type": "fullReference",
|
||||
},
|
||||
Object {
|
||||
"field": "bytes",
|
||||
"operationType": "min",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue