diff --git a/x-pack/plugins/lens/public/index.ts b/x-pack/plugins/lens/public/index.ts index fb7cefb22d175..8a7c089260a39 100644 --- a/x-pack/plugins/lens/public/index.ts +++ b/x-pack/plugins/lens/public/index.ts @@ -31,8 +31,6 @@ export type { DatatableVisualizationState } from './datatable_visualization/visu export type { IndexPatternPersistedState, PersistedIndexPatternLayer, - IndexPatternColumn, - FieldBasedIndexPatternColumn, OperationType, IncompleteColumn, FiltersIndexPatternColumn, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.test.tsx index a6a3cda0ca033..6fe61d3e3c29a 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.test.tsx @@ -26,6 +26,7 @@ import { fieldFormatsServiceMock } from '../../../../../src/plugins/field_format import { indexPatternFieldEditorPluginMock } from '../../../../../src/plugins/index_pattern_field_editor/public/mocks'; import { getFieldByNameFactory } from './pure_helpers'; import { uiActionsPluginMock } from '../../../../../src/plugins/ui_actions/public/mocks'; +import { TermsIndexPatternColumn } from './operations'; const fieldsOne = [ { @@ -173,7 +174,7 @@ const initialState: IndexPatternPrivateState = { type: 'alphabetical', }, }, - }, + } as TermsIndexPatternColumn, col2: { label: 'My Op', dataType: 'number', @@ -200,7 +201,7 @@ const initialState: IndexPatternPrivateState = { type: 'alphabetical', }, }, - }, + } as TermsIndexPatternColumn, col2: { label: 'My Op', dataType: 'number', diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.test.tsx index b48d13d6d3499..fbecfeed0f321 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.test.tsx @@ -8,7 +8,7 @@ import { mount } from 'enzyme'; import React from 'react'; import { BucketNestingEditor } from './bucket_nesting_editor'; -import { IndexPatternColumn } from '../indexpattern'; +import { GenericIndexPatternColumn } from '../indexpattern'; import { IndexPatternField } from '../types'; const fieldMap: Record = { @@ -20,7 +20,7 @@ const fieldMap: Record = { const getFieldByName = (name: string): IndexPatternField | undefined => fieldMap[name]; describe('BucketNestingEditor', () => { - function mockCol(col: Partial = {}): IndexPatternColumn { + function mockCol(col: Partial = {}): GenericIndexPatternColumn { const result = { dataType: 'string', isBucketed: true, @@ -35,7 +35,7 @@ describe('BucketNestingEditor', () => { ...col, }; - return result as IndexPatternColumn; + return result as GenericIndexPatternColumn; } it('should display the top level grouping when at the root', () => { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.tsx index 8456552be8ec6..3979bfb8c9ac4 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.tsx @@ -10,7 +10,7 @@ import { i18n } from '@kbn/i18n'; import { EuiFormRow, EuiSwitch, EuiSelect } from '@elastic/eui'; import { IndexPatternLayer, IndexPatternField } from '../types'; import { hasField } from '../utils'; -import { IndexPatternColumn } from '../operations'; +import { GenericIndexPatternColumn } from '../operations'; function nestColumn(columnOrder: string[], outer: string, inner: string) { const result = columnOrder.filter((c) => c !== inner); @@ -22,7 +22,7 @@ function nestColumn(columnOrder: string[], outer: string, inner: string) { } function getFieldName( - column: IndexPatternColumn, + column: GenericIndexPatternColumn, getFieldByName: (name: string) => IndexPatternField | undefined ) { return hasField(column) diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.tsx index d34430e717e66..c8452340e993a 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.tsx @@ -19,7 +19,7 @@ import { } from '@elastic/eui'; import { IndexPatternDimensionEditorProps } from './dimension_panel'; import { OperationSupportMatrix } from './operation_support'; -import { IndexPatternColumn } from '../indexpattern'; +import { GenericIndexPatternColumn } from '../indexpattern'; import { operationDefinitionMap, getOperationDisplay, @@ -62,7 +62,7 @@ import type { TemporaryState } from './dimensions_editor_helpers'; const operationPanels = getOperationDisplay(); export interface DimensionEditorProps extends IndexPatternDimensionEditorProps { - selectedColumn?: IndexPatternColumn; + selectedColumn?: GenericIndexPatternColumn; layerType: LayerType; operationSupportMatrix: OperationSupportMatrix; currentIndexPattern: IndexPattern; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.test.tsx index 6d9e1ae3fe81b..06c1bb931f730 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.test.tsx @@ -27,7 +27,12 @@ import { IUiSettingsClient, SavedObjectsClientContract, HttpSetup, CoreSetup } f import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; import { generateId } from '../../id_generator'; import { IndexPatternPrivateState } from '../types'; -import { IndexPatternColumn, replaceColumn } from '../operations'; +import { + FiltersIndexPatternColumn, + GenericIndexPatternColumn, + replaceColumn, + TermsIndexPatternColumn, +} from '../operations'; import { documentField } from '../document_field'; import { OperationMetadata } from '../../types'; import { DateHistogramIndexPatternColumn } from '../operations/definitions/date_histogram'; @@ -108,7 +113,7 @@ const expectedIndexPatterns = { }, }; -const bytesColumn: IndexPatternColumn = { +const bytesColumn: GenericIndexPatternColumn = { label: 'Max of bytes', dataType: 'number', isBucketed: false, @@ -133,7 +138,7 @@ describe('IndexPatternDimensionEditorPanel', () => { let setState: jest.Mock; let defaultProps: IndexPatternDimensionEditorProps; - function getStateWithColumns(columns: Record) { + function getStateWithColumns(columns: Record) { return { ...state, layers: { first: { ...state.layers.first, columns, columnOrder: Object.keys(columns) } }, @@ -171,7 +176,7 @@ describe('IndexPatternDimensionEditorPanel', () => { interval: '1d', }, sourceField: 'timestamp', - }, + } as DateHistogramIndexPatternColumn, }, incompleteColumns: {}, }, @@ -264,7 +269,7 @@ describe('IndexPatternDimensionEditorPanel', () => { // Private operationType: 'filters', params: { filters: [] }, - }, + } as FiltersIndexPatternColumn, })} /> ); @@ -427,7 +432,7 @@ describe('IndexPatternDimensionEditorPanel', () => { operationType: 'date_histogram', sourceField: '@timestamp', params: { interval: 'auto' }, - }, + } as DateHistogramIndexPatternColumn, col1: { label: 'Counter rate', dataType: 'number', @@ -464,7 +469,7 @@ describe('IndexPatternDimensionEditorPanel', () => { operationType: 'date_histogram', sourceField: '@timestamp', params: { interval: 'auto' }, - }, + } as DateHistogramIndexPatternColumn, col1: { label: 'Cumulative sum', dataType: 'number', @@ -839,7 +844,7 @@ describe('IndexPatternDimensionEditorPanel', () => { // Private operationType: 'filters', params: { filters: [] }, - }, + } as FiltersIndexPatternColumn, })} /> ); @@ -1066,7 +1071,7 @@ describe('IndexPatternDimensionEditorPanel', () => { }); describe('time scaling', () => { - function getProps(colOverrides: Partial) { + function getProps(colOverrides: Partial) { return { ...defaultProps, state: getStateWithColumns({ @@ -1080,7 +1085,7 @@ describe('IndexPatternDimensionEditorPanel', () => { params: { interval: '1d', }, - }, + } as DateHistogramIndexPatternColumn, col2: { dataType: 'number', isBucketed: false, @@ -1088,7 +1093,7 @@ describe('IndexPatternDimensionEditorPanel', () => { operationType: 'count', sourceField: 'Records', ...colOverrides, - } as IndexPatternColumn, + } as GenericIndexPatternColumn, }), columnId: 'col2', }; @@ -1296,7 +1301,7 @@ describe('IndexPatternDimensionEditorPanel', () => { }); describe('time shift', () => { - function getProps(colOverrides: Partial) { + function getProps(colOverrides: Partial) { return { ...defaultProps, state: getStateWithColumns({ @@ -1310,7 +1315,7 @@ describe('IndexPatternDimensionEditorPanel', () => { params: { interval: '1d', }, - }, + } as DateHistogramIndexPatternColumn, col2: { dataType: 'number', isBucketed: false, @@ -1318,7 +1323,7 @@ describe('IndexPatternDimensionEditorPanel', () => { operationType: 'count', sourceField: 'Records', ...colOverrides, - } as IndexPatternColumn, + } as GenericIndexPatternColumn, }), columnId: 'col2', }; @@ -1334,7 +1339,7 @@ describe('IndexPatternDimensionEditorPanel', () => { label: 'Count of records', operationType: 'count', sourceField: 'Records', - } as IndexPatternColumn, + } as GenericIndexPatternColumn, }), columnId: 'col2', }; @@ -1483,7 +1488,7 @@ describe('IndexPatternDimensionEditorPanel', () => { }); describe('filtering', () => { - function getProps(colOverrides: Partial) { + function getProps(colOverrides: Partial) { return { ...defaultProps, state: getStateWithColumns({ @@ -1497,7 +1502,7 @@ describe('IndexPatternDimensionEditorPanel', () => { params: { interval: '1d', }, - }, + } as DateHistogramIndexPatternColumn, col2: { dataType: 'number', isBucketed: false, @@ -1505,7 +1510,7 @@ describe('IndexPatternDimensionEditorPanel', () => { operationType: 'count', sourceField: 'Records', ...colOverrides, - } as IndexPatternColumn, + } as GenericIndexPatternColumn, }), columnId: 'col2', }; @@ -1522,7 +1527,7 @@ describe('IndexPatternDimensionEditorPanel', () => { orderBy: { type: 'alphabetical' }, size: 5, }, - })} + } as TermsIndexPatternColumn)} /> ); expect( diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.tsx index f27b2c8938b2c..6479fb5b8af4f 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.tsx @@ -12,7 +12,7 @@ import { IUiSettingsClient, SavedObjectsClientContract, HttpSetup } from 'kibana import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; import { DatasourceDimensionTriggerProps, DatasourceDimensionEditorProps } from '../../types'; import { DataPublicPluginStart } from '../../../../../../src/plugins/data/public'; -import { IndexPatternColumn } from '../indexpattern'; +import { GenericIndexPatternColumn } from '../indexpattern'; import { isColumnInvalid } from '../utils'; import { IndexPatternPrivateState } from '../types'; import { DimensionEditor } from './dimension_editor'; @@ -56,7 +56,7 @@ export const IndexPatternDimensionTriggerComponent = function IndexPatternDimens [layer, columnId, currentIndexPattern, invalid] ); - const selectedColumn: IndexPatternColumn | null = layer.columns[props.columnId] ?? null; + const selectedColumn: GenericIndexPatternColumn | null = layer.columns[props.columnId] ?? null; if (!selectedColumn) { return null; @@ -126,7 +126,7 @@ export const IndexPatternDimensionEditorComponent = function IndexPatternDimensi } const operationSupportMatrix = getOperationSupportMatrix(props); - const selectedColumn: IndexPatternColumn | null = + const selectedColumn: GenericIndexPatternColumn | null = props.state.layers[layerId].columns[props.columnId] || null; return ( }; export function getErrorMessage( - selectedColumn: IndexPatternColumn | undefined, + selectedColumn: GenericIndexPatternColumn | undefined, incompleteOperation: boolean, input: 'none' | 'field' | 'fullReference' | 'managedReference' | undefined, fieldInvalid: boolean diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/droppable.test.ts b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/droppable.test.ts index 85807721f80f6..fa200e8b55626 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/droppable.test.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/droppable.test.ts @@ -14,7 +14,12 @@ import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; import { IndexPatternLayer, IndexPatternPrivateState } from '../../types'; import { documentField } from '../../document_field'; import { OperationMetadata, DropType } from '../../../types'; -import { IndexPatternColumn, MedianIndexPatternColumn } from '../../operations'; +import { + DateHistogramIndexPatternColumn, + GenericIndexPatternColumn, + MedianIndexPatternColumn, + TermsIndexPatternColumn, +} from '../../operations'; import { getFieldByNameFactory } from '../../pure_helpers'; import { generateId } from '../../../id_generator'; import { layerTypes } from '../../../../common'; @@ -128,7 +133,7 @@ const oneColumnLayer: IndexPatternLayer = { interval: '1d', }, sourceField: 'timestamp', - }, + } as DateHistogramIndexPatternColumn, }, incompleteColumns: {}, }; @@ -150,7 +155,7 @@ const multipleColumnsLayer: IndexPatternLayer = { size: 10, }, sourceField: 'src', - }, + } as TermsIndexPatternColumn, col3: { label: 'Top values of dest', dataType: 'string', @@ -164,7 +169,7 @@ const multipleColumnsLayer: IndexPatternLayer = { size: 10, }, sourceField: 'dest', - }, + } as TermsIndexPatternColumn, col4: { label: 'Median of bytes', dataType: 'number', @@ -416,7 +421,7 @@ describe('IndexPatternDimensionEditorPanel', () => { interval: '1d', }, sourceField: 'timestamp', - }, + } as DateHistogramIndexPatternColumn, }, }; @@ -771,7 +776,7 @@ describe('IndexPatternDimensionEditorPanel', () => { interval: '1d', }, sourceField: 'timestamp', - }, + } as DateHistogramIndexPatternColumn, col2: { label: 'Top values of bar', dataType: 'number', @@ -783,7 +788,7 @@ describe('IndexPatternDimensionEditorPanel', () => { orderDirection: 'asc', size: 5, }, - }, + } as TermsIndexPatternColumn, col3: { operationType: 'average', sourceField: 'memory', @@ -1158,17 +1163,17 @@ describe('IndexPatternDimensionEditorPanel', () => { label: 'Date histogram of timestamp', dataType: 'date', isBucketed: true, - } as IndexPatternColumn, + } as GenericIndexPatternColumn, col2: { label: 'Top values of bar', dataType: 'number', isBucketed: true, - } as IndexPatternColumn, + } as GenericIndexPatternColumn, col3: { label: 'Top values of memory', dataType: 'number', isBucketed: true, - } as IndexPatternColumn, + } as GenericIndexPatternColumn, }, }, }, @@ -1293,7 +1298,7 @@ describe('IndexPatternDimensionEditorPanel', () => { size: 10, }, sourceField: 'src', - }, + } as TermsIndexPatternColumn, col3: { label: 'Count', dataType: 'number', diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/get_drop_props.ts b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/get_drop_props.ts index 0e87cc680c2f6..08361490cdc2c 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/get_drop_props.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/get_drop_props.ts @@ -16,7 +16,7 @@ import { hasField, isDraggedField } from '../../utils'; import { DragContextState } from '../../../drag_drop/providers'; import { OperationMetadata } from '../../../types'; import { getOperationTypesForField } from '../../operations'; -import { IndexPatternColumn } from '../../indexpattern'; +import { GenericIndexPatternColumn } from '../../indexpattern'; import { IndexPatternPrivateState, IndexPattern, @@ -36,7 +36,7 @@ const operationLabels = getOperationDisplay(); export function getNewOperation( field: IndexPatternField | undefined | false, filterOperations: (meta: OperationMetadata) => boolean, - targetColumn: IndexPatternColumn + targetColumn: GenericIndexPatternColumn ) { if (!field) { return; @@ -50,7 +50,10 @@ export function getNewOperation( return shouldOperationPersist ? targetColumn.operationType : newOperations[0]; } -export function getField(column: IndexPatternColumn | undefined, indexPattern: IndexPattern) { +export function getField( + column: GenericIndexPatternColumn | undefined, + indexPattern: IndexPattern +) { if (!column) { return; } @@ -89,7 +92,10 @@ export function getDropProps(props: GetDropProps) { } } -function hasTheSameField(sourceColumn: IndexPatternColumn, targetColumn?: IndexPatternColumn) { +function hasTheSameField( + sourceColumn: GenericIndexPatternColumn, + targetColumn?: GenericIndexPatternColumn +) { return ( targetColumn && hasField(targetColumn) && @@ -127,11 +133,11 @@ function getDropPropsForField({ return; } -function getDropPropsForSameGroup(targetColumn?: IndexPatternColumn): DropProps { +function getDropPropsForSameGroup(targetColumn?: GenericIndexPatternColumn): DropProps { return targetColumn ? { dropTypes: ['reorder'] } : { dropTypes: ['duplicate_compatible'] }; } -function getDropPropsForCompatibleGroup(targetColumn?: IndexPatternColumn): DropProps { +function getDropPropsForCompatibleGroup(targetColumn?: GenericIndexPatternColumn): DropProps { return { dropTypes: targetColumn ? ['replace_compatible', 'replace_duplicate_compatible', 'swap_compatible'] diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/filtering.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/filtering.tsx index ddd9718839649..d88edff3f0cc3 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/filtering.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/filtering.tsx @@ -18,7 +18,7 @@ import { EuiPopoverProps, } from '@elastic/eui'; import type { Query } from 'src/plugins/data/public'; -import { IndexPatternColumn, operationDefinitionMap } from '../operations'; +import { GenericIndexPatternColumn, operationDefinitionMap } from '../operations'; import { validateQuery } from '../operations/definitions/filters'; import { QueryInput } from '../query_input'; import type { IndexPattern, IndexPatternLayer } from '../types'; @@ -54,7 +54,7 @@ export function Filtering({ indexPattern, isInitiallyOpen, }: { - selectedColumn: IndexPatternColumn; + selectedColumn: GenericIndexPatternColumn; indexPattern: IndexPattern; columnId: string; layer: IndexPatternLayer; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/format_selector.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/format_selector.tsx index ff10810208e70..7ee25a790db62 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/format_selector.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/format_selector.tsx @@ -8,7 +8,7 @@ import React, { useCallback, useMemo, useState } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiFormRow, EuiComboBox, EuiSpacer, EuiRange } from '@elastic/eui'; -import { IndexPatternColumn } from '../indexpattern'; +import { GenericIndexPatternColumn } from '../indexpattern'; const supportedFormats: Record = { number: { @@ -36,7 +36,7 @@ const defaultOption = { }; interface FormatSelectorProps { - selectedColumn: IndexPatternColumn; + selectedColumn: GenericIndexPatternColumn; onChange: (newFormat?: { id: string; params?: Record }) => void; } @@ -136,7 +136,7 @@ export function FormatSelector(props: FormatSelectorProps) { onChange={(e) => { setState({ decimalPlaces: Number(e.currentTarget.value) }); onChange({ - id: (selectedColumn.params as { format: { id: string } }).format.id, + id: currentFormat.id, params: { decimals: Number(e.currentTarget.value), }, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/reference_editor.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/reference_editor.test.tsx index 21251b59d4533..16251654a6355 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/reference_editor.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/reference_editor.test.tsx @@ -17,7 +17,11 @@ import type { DataPublicPluginStart } from 'src/plugins/data/public'; import { OperationMetadata } from '../../types'; import { createMockedIndexPattern, createMockedIndexPatternWithoutType } from '../mocks'; import { ReferenceEditor, ReferenceEditorProps } from './reference_editor'; -import { insertOrReplaceColumn } from '../operations'; +import { + insertOrReplaceColumn, + LastValueIndexPatternColumn, + TermsIndexPatternColumn, +} from '../operations'; import { FieldSelect } from './field_select'; jest.mock('../operations'); @@ -123,7 +127,7 @@ describe('reference editor', () => { operationType: 'terms', sourceField: 'dest', params: { size: 5, orderBy: { type: 'alphabetical' }, orderDirection: 'desc' }, - }, + } as TermsIndexPatternColumn, }, }} validation={{ @@ -490,7 +494,7 @@ describe('reference editor', () => { params: { sortField: 'timestamp', }, - }, + } as LastValueIndexPatternColumn, }, }} validation={{ @@ -522,7 +526,7 @@ describe('reference editor', () => { params: { sortField: 'timestamp', }, - }, + } as LastValueIndexPatternColumn, }, incompleteColumns: { ref: { operationType: 'max' }, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/time_scaling.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/time_scaling.tsx index 8a670e7562573..6e3a43cbb1a03 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/time_scaling.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/time_scaling.tsx @@ -19,7 +19,7 @@ import { i18n } from '@kbn/i18n'; import React from 'react'; import { adjustTimeScaleLabelSuffix, - IndexPatternColumn, + GenericIndexPatternColumn, operationDefinitionMap, } from '../operations'; import type { TimeScaleUnit } from '../../../common/expressions'; @@ -60,7 +60,7 @@ export function TimeScaling({ layer, updateLayer, }: { - selectedColumn: IndexPatternColumn; + selectedColumn: GenericIndexPatternColumn; columnId: string; layer: IndexPatternLayer; updateLayer: (newLayer: IndexPatternLayer) => void; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/time_shift.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/time_shift.tsx index c2415c9c9a75a..36cc4a3c22e44 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/time_shift.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/time_shift.tsx @@ -14,7 +14,7 @@ import { Query } from 'src/plugins/data/public'; import { parseTimeShift } from '../../../../../../src/plugins/data/common'; import { adjustTimeScaleLabelSuffix, - IndexPatternColumn, + GenericIndexPatternColumn, operationDefinitionMap, } from '../operations'; import { IndexPattern, IndexPatternLayer } from '../types'; @@ -70,7 +70,7 @@ export function TimeShift({ activeData, layerId, }: { - selectedColumn: IndexPatternColumn; + selectedColumn: GenericIndexPatternColumn; indexPattern: IndexPattern; columnId: string; layer: IndexPatternLayer; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts index 8f180d4a021e0..e6b9eccbc7da1 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts @@ -8,7 +8,7 @@ import React from 'react'; import 'jest-canvas-mock'; import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; -import { getIndexPatternDatasource, IndexPatternColumn } from './indexpattern'; +import { getIndexPatternDatasource, GenericIndexPatternColumn } from './indexpattern'; import { DatasourcePublicAPI, Operation, Datasource, FramePublicAPI } from '../types'; import { coreMock } from 'src/core/public/mocks'; import { IndexPatternPersistedState, IndexPatternPrivateState } from './types'; @@ -16,11 +16,20 @@ import { dataPluginMock } from '../../../../../src/plugins/data/public/mocks'; import { Ast } from '@kbn/interpreter/common'; import { chartPluginMock } from '../../../../../src/plugins/charts/public/mocks'; import { getFieldByNameFactory } from './pure_helpers'; -import { operationDefinitionMap, getErrorMessages } from './operations'; +import { + operationDefinitionMap, + getErrorMessages, + TermsIndexPatternColumn, + DateHistogramIndexPatternColumn, + MovingAverageIndexPatternColumn, + MathIndexPatternColumn, + FormulaIndexPatternColumn, +} from './operations'; import { createMockedFullReference } from './operations/mocks'; import { indexPatternFieldEditorPluginMock } from 'src/plugins/index_pattern_field_editor/public/mocks'; import { uiActionsPluginMock } from '../../../../../src/plugins/ui_actions/public/mocks'; import { fieldFormatsServiceMock } from '../../../../../src/plugins/field_formats/public/mocks'; +import { TinymathAST } from 'packages/kbn-tinymath'; jest.mock('./loader'); jest.mock('../id_generator'); @@ -200,7 +209,7 @@ describe('IndexPattern Data Source', () => { orderBy: { type: 'alphabetical' }, orderDirection: 'asc', }, - }, + } as TermsIndexPatternColumn, }, }, }, @@ -209,7 +218,7 @@ describe('IndexPattern Data Source', () => { describe('uniqueLabels', () => { it('appends a suffix to duplicates', () => { - const col: IndexPatternColumn = { + const col: GenericIndexPatternColumn = { dataType: 'number', isBucketed: false, label: 'Foo', @@ -355,7 +364,7 @@ describe('IndexPattern Data Source', () => { params: { interval: '1d', }, - }, + } as DateHistogramIndexPatternColumn, }, }, }, @@ -505,7 +514,7 @@ describe('IndexPattern Data Source', () => { params: { interval: 'auto', }, - }, + } as DateHistogramIndexPatternColumn, col3: { label: 'Date 2', dataType: 'date', @@ -515,7 +524,7 @@ describe('IndexPattern Data Source', () => { params: { interval: 'auto', }, - }, + } as DateHistogramIndexPatternColumn, }, }, }, @@ -552,7 +561,7 @@ describe('IndexPattern Data Source', () => { params: { interval: 'auto', }, - }, + } as DateHistogramIndexPatternColumn, }, }, }, @@ -601,7 +610,7 @@ describe('IndexPattern Data Source', () => { params: { interval: 'auto', }, - }, + } as DateHistogramIndexPatternColumn, }, }, }, @@ -727,7 +736,7 @@ describe('IndexPattern Data Source', () => { params: { interval: 'auto', }, - }, + } as DateHistogramIndexPatternColumn, }, }, }, @@ -794,7 +803,7 @@ describe('IndexPattern Data Source', () => { params: { interval: 'auto', }, - }, + } as DateHistogramIndexPatternColumn, metric: { label: 'Count of records', dataType: 'number', @@ -812,7 +821,7 @@ describe('IndexPattern Data Source', () => { params: { window: 5, }, - }, + } as MovingAverageIndexPatternColumn, }, }, }, @@ -850,7 +859,7 @@ describe('IndexPattern Data Source', () => { params: { interval: '1d', }, - }, + } as DateHistogramIndexPatternColumn, bucket2: { label: 'Terms', dataType: 'string', @@ -862,7 +871,7 @@ describe('IndexPattern Data Source', () => { orderDirection: 'asc', size: 10, }, - }, + } as TermsIndexPatternColumn, }, }, }, @@ -902,7 +911,7 @@ describe('IndexPattern Data Source', () => { params: { interval: 'auto', }, - }, + } as DateHistogramIndexPatternColumn, }, }, }, @@ -947,7 +956,6 @@ describe('IndexPattern Data Source', () => { label: 'Reference', dataType: 'number', isBucketed: false, - // @ts-expect-error not a valid type operationType: 'testReference', references: ['col1'], }, @@ -983,7 +991,6 @@ describe('IndexPattern Data Source', () => { label: 'Reference', dataType: 'number', isBucketed: false, - // @ts-expect-error not a valid type operationType: 'testReference', references: ['col1'], }, @@ -1030,7 +1037,7 @@ describe('IndexPattern Data Source', () => { params: { interval: 'auto', }, - }, + } as DateHistogramIndexPatternColumn, formula: { label: 'Formula', dataType: 'number', @@ -1042,7 +1049,7 @@ describe('IndexPattern Data Source', () => { isFormulaBroken: false, }, references: ['math'], - }, + } as FormulaIndexPatternColumn, countX0: { label: 'countX0', dataType: 'number', @@ -1062,8 +1069,7 @@ describe('IndexPattern Data Source', () => { tinymathAst: { type: 'function', name: 'add', - // @ts-expect-error String args are not valid tinymath, but signals something unique to Lens - args: ['countX0', 'count'], + args: ['countX0', 'count'] as unknown as TinymathAST[], location: { min: 0, max: 17, @@ -1073,7 +1079,7 @@ describe('IndexPattern Data Source', () => { }, references: ['countX0', 'count'], customLabel: true, - }, + } as MathIndexPatternColumn, }, }, }, @@ -1217,7 +1223,7 @@ describe('IndexPattern Data Source', () => { operationType: 'sum', sourceField: 'test', params: {}, - } as IndexPatternColumn, + } as GenericIndexPatternColumn, col2: { label: 'Cumulative sum', dataType: 'number', @@ -1226,7 +1232,7 @@ describe('IndexPattern Data Source', () => { operationType: 'cumulative_sum', references: ['col1'], params: {}, - } as IndexPatternColumn, + } as GenericIndexPatternColumn, }, }, }, @@ -1268,7 +1274,7 @@ describe('IndexPattern Data Source', () => { operationType: 'sum', sourceField: 'test', params: {}, - } as IndexPatternColumn, + } as GenericIndexPatternColumn, col2: { label: 'Cumulative sum', dataType: 'number', @@ -1277,7 +1283,7 @@ describe('IndexPattern Data Source', () => { operationType: 'cumulative_sum', references: ['col1'], params: {}, - } as IndexPatternColumn, + } as GenericIndexPatternColumn, }, }, }, @@ -1368,7 +1374,7 @@ describe('IndexPattern Data Source', () => { dataType: 'date', isBucketed: true, sourceField: 'timestamp', - }, + } as DateHistogramIndexPatternColumn, col2: { operationType: 'count', label: '', @@ -1606,7 +1612,7 @@ describe('IndexPattern Data Source', () => { params: { interval: '1d', }, - }, + } as DateHistogramIndexPatternColumn, bucket2: { label: 'Terms', dataType: 'string', @@ -1618,7 +1624,7 @@ describe('IndexPattern Data Source', () => { orderDirection: 'asc', size: 10, }, - }, + } as TermsIndexPatternColumn, }, }, }, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx index b970ad092c7f4..fc9e2c7ed44a8 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx @@ -44,7 +44,7 @@ import { import { isColumnInvalid, isDraggedField, normalizeOperationDataType } from './utils'; import { LayerPanel } from './layerpanel'; -import { IndexPatternColumn, getErrorMessages, insertNewColumn } from './operations'; +import { GenericIndexPatternColumn, getErrorMessages, insertNewColumn } from './operations'; import { IndexPatternField, IndexPatternPrivateState, IndexPatternPersistedState } from './types'; import { KibanaContextProvider } from '../../../../../src/plugins/kibana_react/public'; import { DataPublicPluginStart } from '../../../../../src/plugins/data/public'; @@ -58,10 +58,13 @@ import { GeoFieldWorkspacePanel } from '../editor_frame_service/editor_frame/wor import { DraggingIdentifier } from '../drag_drop'; import { getStateTimeShiftWarningMessages } from './time_shift_utils'; import { getPrecisionErrorWarningMessages } from './utils'; -export type { OperationType, IndexPatternColumn } from './operations'; +export type { OperationType, GenericIndexPatternColumn } from './operations'; export { deleteColumn } from './operations'; -export function columnToOperation(column: IndexPatternColumn, uniqueLabel?: string): Operation { +export function columnToOperation( + column: GenericIndexPatternColumn, + uniqueLabel?: string +): Operation { const { dataType, label, isBucketed, scale } = column; return { dataType: normalizeOperationDataType(dataType), diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.test.tsx index 5df02482a2745..a821dcee29d6d 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.test.tsx @@ -18,6 +18,12 @@ import { import { documentField } from './document_field'; import { getFieldByNameFactory } from './pure_helpers'; import { isEqual } from 'lodash'; +import { DateHistogramIndexPatternColumn, TermsIndexPatternColumn } from './operations'; +import { + MathIndexPatternColumn, + RangeIndexPatternColumn, + StaticValueIndexPatternColumn, +} from './operations/definitions'; jest.mock('./loader'); jest.mock('../id_generator'); @@ -179,7 +185,7 @@ function testInitialState(): IndexPatternPrivateState { orderBy: { type: 'alphabetical' }, orderDirection: 'asc', }, - }, + } as TermsIndexPatternColumn, }, }, }, @@ -733,7 +739,7 @@ describe('IndexPattern Data Source suggestions', () => { orderDirection: 'asc', size: 5, }, - }, + } as TermsIndexPatternColumn, colb: { dataType: 'number', isBucketed: false, @@ -768,7 +774,7 @@ describe('IndexPattern Data Source suggestions', () => { params: { interval: 'w', }, - }, + } as DateHistogramIndexPatternColumn, colb: { dataType: 'number', isBucketed: false, @@ -976,7 +982,7 @@ describe('IndexPattern Data Source suggestions', () => { orderDirection: 'asc', size: 5, }, - }, + } as TermsIndexPatternColumn, }, columnOrder: ['cola'], }, @@ -1086,7 +1092,7 @@ describe('IndexPattern Data Source suggestions', () => { operationType: 'date_histogram', sourceField: 'timestamp', params: { interval: 'auto' }, - }, + } as DateHistogramIndexPatternColumn, metric: { label: '', customLabel: true, @@ -1218,7 +1224,7 @@ describe('IndexPattern Data Source suggestions', () => { params: { value: '0' }, references: [], scale: 'ratio', - }, + } as StaticValueIndexPatternColumn, }, }, currentLayer: { @@ -1506,7 +1512,7 @@ describe('IndexPattern Data Source suggestions', () => { orderBy: { type: 'alphabetical' }, orderDirection: 'asc', }, - }, + } as TermsIndexPatternColumn, }, }, }, @@ -1648,7 +1654,7 @@ describe('IndexPattern Data Source suggestions', () => { orderDirection: 'asc', size: 5, }, - }, + } as TermsIndexPatternColumn, colb: { label: 'My Op', customLabel: true, @@ -1726,7 +1732,7 @@ describe('IndexPattern Data Source suggestions', () => { orderDirection: 'asc', size: 5, }, - }, + } as TermsIndexPatternColumn, colb: { label: 'My Op', customLabel: true, @@ -1830,7 +1836,7 @@ describe('IndexPattern Data Source suggestions', () => { maxBars: 100, ranges: [], }, - }, + } as RangeIndexPatternColumn, }, }, }, @@ -1876,7 +1882,7 @@ describe('IndexPattern Data Source suggestions', () => { maxBars: 100, ranges: [{ from: 1, to: 2, label: '' }], }, - }, + } as RangeIndexPatternColumn, }, }, }, @@ -1954,7 +1960,7 @@ describe('IndexPattern Data Source suggestions', () => { it("should not propose an over time suggestion if there's a top values aggregation with an high size", () => { const initialState = testInitialState(); - (initialState.layers.first.columns.col1 as { params: { size: number } }).params!.size = 6; + (initialState.layers.first.columns.col1 as TermsIndexPatternColumn).params!.size = 6; const suggestions = getDatasourceSuggestionsFromCurrentState({ ...initialState, indexPatterns: { 1: { ...initialState.indexPatterns['1'], timeFieldName: undefined } }, @@ -1995,7 +2001,7 @@ describe('IndexPattern Data Source suggestions', () => { orderBy: { type: 'alphabetical' }, orderDirection: 'asc', }, - }, + } as TermsIndexPatternColumn, }, }, }, @@ -2080,7 +2086,7 @@ describe('IndexPattern Data Source suggestions', () => { orderBy: { type: 'alphabetical' }, orderDirection: 'asc', }, - }, + } as TermsIndexPatternColumn, col2: { label: 'My Op', customLabel: true, @@ -2094,7 +2100,7 @@ describe('IndexPattern Data Source suggestions', () => { orderBy: { type: 'alphabetical' }, orderDirection: 'asc', }, - }, + } as TermsIndexPatternColumn, col3: { label: 'My Op', customLabel: true, @@ -2108,7 +2114,7 @@ describe('IndexPattern Data Source suggestions', () => { orderBy: { type: 'alphabetical' }, orderDirection: 'asc', }, - }, + } as TermsIndexPatternColumn, col4: { label: 'My Op', customLabel: true, @@ -2217,7 +2223,7 @@ describe('IndexPattern Data Source suggestions', () => { params: { interval: 'd', }, - }, + } as DateHistogramIndexPatternColumn, id2: { label: 'Average of field1', dataType: 'number', @@ -2348,7 +2354,7 @@ describe('IndexPattern Data Source suggestions', () => { params: { interval: 'd', }, - }, + } as DateHistogramIndexPatternColumn, id2: { label: 'Top 5', dataType: 'string', @@ -2357,7 +2363,7 @@ describe('IndexPattern Data Source suggestions', () => { operationType: 'terms', sourceField: 'dest', params: { size: 5, orderBy: { type: 'alphabetical' }, orderDirection: 'asc' }, - }, + } as TermsIndexPatternColumn, id3: { label: 'Average of field1', dataType: 'number', @@ -2403,7 +2409,7 @@ describe('IndexPattern Data Source suggestions', () => { operationType: 'terms', sourceField: 'nonExistingField', params: { size: 5, orderBy: { type: 'alphabetical' }, orderDirection: 'asc' }, - }, + } as TermsIndexPatternColumn, }, columnOrder: ['col1', 'col2'], }, @@ -2539,7 +2545,7 @@ describe('IndexPattern Data Source suggestions', () => { operationType: 'date_histogram', sourceField: 'timestamp', params: { interval: 'auto' }, - }, + } as DateHistogramIndexPatternColumn, ref: { label: '', dataType: 'number', @@ -2629,7 +2635,7 @@ describe('IndexPattern Data Source suggestions', () => { operationType: 'date_histogram', sourceField: 'timestamp', params: { interval: 'auto' }, - }, + } as DateHistogramIndexPatternColumn, metric: { label: '', dataType: 'number', @@ -2681,7 +2687,7 @@ describe('IndexPattern Data Source suggestions', () => { params: { tinymathAst: '', }, - }, + } as MathIndexPatternColumn, ref4: { label: '', dataType: 'number', @@ -2691,7 +2697,7 @@ describe('IndexPattern Data Source suggestions', () => { params: { tinymathAst: '', }, - }, + } as MathIndexPatternColumn, }, }, }, @@ -2756,7 +2762,7 @@ describe('IndexPattern Data Source suggestions', () => { operationType: 'date_histogram', sourceField: 'timestamp', params: { interval: 'auto' }, - }, + } as DateHistogramIndexPatternColumn, ref: { label: '', dataType: 'number', @@ -2806,7 +2812,7 @@ describe('IndexPattern Data Source suggestions', () => { tinymathAst: '', }, references: ['metric'], - }, + } as MathIndexPatternColumn, metric: { label: '', dataType: 'number', diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.ts b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.ts index 8b940ec1f05af..6b15a5a8d1daf 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.ts @@ -16,7 +16,7 @@ import { getMetricOperationTypes, getOperationTypesForField, operationDefinitionMap, - IndexPatternColumn, + BaseIndexPatternColumn, OperationType, getExistingColumnGroups, isReferenced, @@ -62,11 +62,11 @@ function buildSuggestion({ // two match up. const layers = mapValues(updatedState.layers, (layer) => ({ ...layer, - columns: pick(layer.columns, layer.columnOrder) as Record, + columns: pick(layer.columns, layer.columnOrder) as Record, })); const columnOrder = layers[layerId].columnOrder; - const columnMap = layers[layerId].columns as Record; + const columnMap = layers[layerId].columns as Record; const isMultiRow = Object.values(columnMap).some((column) => column.isBucketed); return { @@ -221,7 +221,7 @@ function getExistingLayerSuggestionsForField( indexPattern, field, columnId: generateId(), - op: metricOperation.type, + op: metricOperation.type as OperationType, visualizationGroups: [], }); if (layerWithNewMetric) { @@ -243,7 +243,7 @@ function getExistingLayerSuggestionsForField( indexPattern, field, columnId: metrics[0], - op: metricOperation.type, + op: metricOperation.type as OperationType, visualizationGroups: [], }); if (layerWithReplacedMetric) { @@ -336,7 +336,7 @@ function createNewLayerWithMetricAggregation( return insertNewColumn({ op: 'date_histogram', layer: insertNewColumn({ - op: metricOperation.type, + op: metricOperation.type as OperationType, layer: { indexPatternId: indexPattern.id, columns: {}, columnOrder: [] }, columnId: generateId(), field, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/layerpanel.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/layerpanel.test.tsx index 6161bcee4678f..335796442bd8b 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/layerpanel.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/layerpanel.test.tsx @@ -13,6 +13,7 @@ import { ShallowWrapper } from 'enzyme'; import { EuiSelectable } from '@elastic/eui'; import { ChangeIndexPattern } from './change_indexpattern'; import { getFieldByNameFactory } from './pure_helpers'; +import { TermsIndexPatternColumn } from './operations'; interface IndexPatternPickerOption { label: string; @@ -160,7 +161,7 @@ const initialState: IndexPatternPrivateState = { type: 'alphabetical', }, }, - }, + } as TermsIndexPatternColumn, col2: { label: 'My Op', dataType: 'number', diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/loader.test.ts b/x-pack/plugins/lens/public/indexpattern_datasource/loader.test.ts index d731069e6e7eb..431b8a84341e8 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/loader.test.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/loader.test.ts @@ -26,6 +26,7 @@ import { } from './types'; import { createMockedRestrictedIndexPattern, createMockedIndexPattern } from './mocks'; import { documentField } from './document_field'; +import { DateHistogramIndexPatternColumn } from './operations'; const createMockStorage = (lastData?: Record) => { return { @@ -512,7 +513,7 @@ describe('loader', () => { interval: 'm', }, sourceField: 'timestamp', - }, + } as DateHistogramIndexPatternColumn, col2: { dataType: 'number', isBucketed: false, @@ -563,7 +564,7 @@ describe('loader', () => { interval: 'm', }, sourceField: 'timestamp', - }, + } as DateHistogramIndexPatternColumn, col2: { dataType: 'number', isBucketed: false, @@ -650,7 +651,7 @@ describe('loader', () => { interval: 'm', }, sourceField: 'timestamp', - }, + } as DateHistogramIndexPatternColumn, col2: { dataType: 'number', isBucketed: false, @@ -870,7 +871,7 @@ describe('loader', () => { interval: 'm', }, sourceField: 'timestamp', - }, + } as DateHistogramIndexPatternColumn, }, indexPatternId: '1', }, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions.test.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions.test.ts index c131b16512823..974e37c2aea8e 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions.test.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions.test.ts @@ -19,7 +19,8 @@ import { import { getFieldByNameFactory } from '../pure_helpers'; import { documentField } from '../document_field'; import { IndexPattern, IndexPatternLayer, IndexPatternField } from '../types'; -import { IndexPatternColumn } from '.'; +import { GenericIndexPatternColumn } from '.'; +import { DateHistogramIndexPatternColumn } from './definitions/date_histogram'; const indexPatternFields = [ { @@ -77,7 +78,7 @@ const indexPattern = { }; const baseColumnArgs: { - previousColumn: IndexPatternColumn; + previousColumn: GenericIndexPatternColumn; indexPattern: IndexPattern; layer: IndexPatternLayer; field: IndexPatternField; @@ -113,7 +114,7 @@ const layer: IndexPatternLayer = { operationType: 'date_histogram', sourceField: 'timestamp', params: { interval: 'auto' }, - }, + } as DateHistogramIndexPatternColumn, metric: { label: 'metricLabel', customLabel: true, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/utils.test.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/utils.test.ts index 8b1eaeb109d9b..1dacb334413f8 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/utils.test.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/utils.test.ts @@ -9,6 +9,7 @@ import { checkReferences, checkForDataLayerType } from './utils'; import { operationDefinitionMap } from '..'; import { createMockedFullReference } from '../../mocks'; import { layerTypes } from '../../../../../common'; +import { DateHistogramIndexPatternColumn } from '../date_histogram'; // Mock prevents issue with circular loading jest.mock('..'); @@ -35,7 +36,6 @@ describe('utils', () => { columns: { ref: { label: 'Label', - // @ts-expect-error test-only operation type operationType: 'testReference', isBucketed: false, dataType: 'number', @@ -57,7 +57,6 @@ describe('utils', () => { columns: { ref: { label: 'Label', - // @ts-expect-error test-only operation type operationType: 'testReference', isBucketed: false, dataType: 'number', @@ -70,7 +69,7 @@ describe('utils', () => { dataType: 'date', sourceField: 'timestamp', params: { interval: 'auto' }, - }, + } as DateHistogramIndexPatternColumn, }, columnOrder: ['invalid', 'ref'], indexPatternId: '', diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/column_types.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/column_types.ts index 15bd7d4242b92..233138ef4ff0a 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/column_types.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/column_types.ts @@ -42,6 +42,11 @@ export interface ReferenceBasedIndexPatternColumn references: string[]; } +export type GenericIndexPatternColumn = + | BaseIndexPatternColumn + | FieldBasedIndexPatternColumn + | ReferenceBasedIndexPatternColumn; + // Used to store the temporary invalid state export interface IncompleteColumn { operationType?: OperationType; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/count.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/count.tsx index a6134ddc67bc0..6290abac77844 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/count.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/count.tsx @@ -11,7 +11,7 @@ import { buildExpressionFunction } from '../../../../../../../src/plugins/expres import { OperationDefinition } from './index'; import { FormattedIndexPatternColumn, FieldBasedIndexPatternColumn } from './column_types'; import { IndexPatternField } from '../../types'; -import { getInvalidFieldMessage, getFilter } from './helpers'; +import { getInvalidFieldMessage, getFilter, isColumnFormatted } from './helpers'; import { adjustTimeScaleLabelSuffix, adjustTimeScaleOnOtherColumnChange, @@ -84,9 +84,8 @@ export const countOperation: OperationDefinition { interval: '42w', }, sourceField: 'timestamp', - }, + } as DateHistogramIndexPatternColumn, }, }; }); @@ -332,7 +332,7 @@ describe('date_histogram', () => { interval: 'd', }, sourceField: 'other_timestamp', - }, + } as DateHistogramIndexPatternColumn, }, }; const instance = shallow( @@ -366,7 +366,7 @@ describe('date_histogram', () => { interval: 'auto', }, sourceField: 'timestamp', - }, + } as DateHistogramIndexPatternColumn, }, }; @@ -401,7 +401,7 @@ describe('date_histogram', () => { interval: 'auto', }, sourceField: 'timestamp', - }, + } as DateHistogramIndexPatternColumn, }, }; @@ -594,7 +594,7 @@ describe('date_histogram', () => { operationType: 'date_histogram', sourceField: 'missing', params: { interval: 'auto' }, - }, + } as DateHistogramIndexPatternColumn, } ) ).toEqual('Missing field'); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.tsx index ea875c069150d..efc7a10090cfa 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.tsx @@ -71,272 +71,275 @@ function getMultipleDateHistogramsErrorMessage(layer: IndexPatternLayer, columnI }); } -export const dateHistogramOperation: OperationDefinition = - { - type: 'date_histogram', - displayName: i18n.translate('xpack.lens.indexPattern.dateHistogram', { - defaultMessage: 'Date histogram', - }), - input: 'field', - priority: 5, // Highest priority level used - operationParams: [{ name: 'interval', type: 'string', required: false }], - getErrorMessage: (layer, columnId, indexPattern) => - [ - ...(getInvalidFieldMessage( - layer.columns[columnId] as FieldBasedIndexPatternColumn, - indexPattern - ) || []), - getMultipleDateHistogramsErrorMessage(layer, columnId) || '', - ].filter(Boolean), - getHelpMessage: (props) => , - getPossibleOperationForField: ({ aggregationRestrictions, aggregatable, type }) => { - if ( - (type === 'date' || type === 'date_range') && - aggregatable && - (!aggregationRestrictions || aggregationRestrictions.date_histogram) - ) { - return { - dataType: 'date', - isBucketed: true, - scale: 'interval', - }; - } - }, - getDefaultLabel: (column, indexPattern) => getSafeName(column.sourceField, indexPattern), - buildColumn({ field }, columnParams) { +export const dateHistogramOperation: OperationDefinition< + DateHistogramIndexPatternColumn, + 'field', + { interval: string } +> = { + type: 'date_histogram', + displayName: i18n.translate('xpack.lens.indexPattern.dateHistogram', { + defaultMessage: 'Date histogram', + }), + input: 'field', + priority: 5, // Highest priority level used + operationParams: [{ name: 'interval', type: 'string', required: false }], + getErrorMessage: (layer, columnId, indexPattern) => + [ + ...(getInvalidFieldMessage( + layer.columns[columnId] as FieldBasedIndexPatternColumn, + indexPattern + ) || []), + getMultipleDateHistogramsErrorMessage(layer, columnId) || '', + ].filter(Boolean), + getHelpMessage: (props) => , + getPossibleOperationForField: ({ aggregationRestrictions, aggregatable, type }) => { + if ( + (type === 'date' || type === 'date_range') && + aggregatable && + (!aggregationRestrictions || aggregationRestrictions.date_histogram) + ) { return { - label: field.displayName, dataType: 'date', - operationType: 'date_histogram', - sourceField: field.name, isBucketed: true, scale: 'interval', - params: { - interval: columnParams?.interval ?? autoInterval, - }, }; - }, - isTransferable: (column, newIndexPattern) => { - const newField = newIndexPattern.getFieldByName(column.sourceField); + } + }, + getDefaultLabel: (column, indexPattern) => getSafeName(column.sourceField, indexPattern), + buildColumn({ field }, columnParams) { + return { + label: field.displayName, + dataType: 'date', + operationType: 'date_histogram', + sourceField: field.name, + isBucketed: true, + scale: 'interval', + params: { + interval: columnParams?.interval ?? autoInterval, + }, + }; + }, + isTransferable: (column, newIndexPattern) => { + const newField = newIndexPattern.getFieldByName(column.sourceField); - return Boolean( - newField && - newField.type === 'date' && - newField.aggregatable && - (!newField.aggregationRestrictions || newField.aggregationRestrictions.date_histogram) - ); - }, - onFieldChange: (oldColumn, field) => { - return { - ...oldColumn, - label: field.displayName, - sourceField: field.name, - }; - }, - toEsAggsFn: (column, columnId, indexPattern) => { - const usedField = indexPattern.getFieldByName(column.sourceField); - let timeZone: string | undefined; - let interval = column.params?.interval ?? autoInterval; - if ( - usedField && - usedField.aggregationRestrictions && - usedField.aggregationRestrictions.date_histogram - ) { - interval = restrictedInterval(usedField.aggregationRestrictions) as string; - timeZone = usedField.aggregationRestrictions.date_histogram.time_zone; - } - return buildExpressionFunction('aggDateHistogram', { - id: columnId, - enabled: true, - schema: 'segment', - field: column.sourceField, - time_zone: timeZone, - useNormalizedEsInterval: !usedField?.aggregationRestrictions?.date_histogram, - interval, - drop_partials: false, - min_doc_count: 0, - extended_bounds: extendedBoundsToAst({}), - }).toAst(); - }, - paramEditor: function ParamEditor({ - layer, - columnId, - currentColumn, - updateLayer, - dateRange, - data, - indexPattern, - }: ParamEditorProps) { - const field = currentColumn && indexPattern.getFieldByName(currentColumn.sourceField); - const intervalIsRestricted = - field!.aggregationRestrictions && field!.aggregationRestrictions.date_histogram; + return Boolean( + newField && + newField.type === 'date' && + newField.aggregatable && + (!newField.aggregationRestrictions || newField.aggregationRestrictions.date_histogram) + ); + }, + onFieldChange: (oldColumn, field) => { + return { + ...oldColumn, + label: field.displayName, + sourceField: field.name, + }; + }, + toEsAggsFn: (column, columnId, indexPattern) => { + const usedField = indexPattern.getFieldByName(column.sourceField); + let timeZone: string | undefined; + let interval = column.params?.interval ?? autoInterval; + if ( + usedField && + usedField.aggregationRestrictions && + usedField.aggregationRestrictions.date_histogram + ) { + interval = restrictedInterval(usedField.aggregationRestrictions) as string; + timeZone = usedField.aggregationRestrictions.date_histogram.time_zone; + } + return buildExpressionFunction('aggDateHistogram', { + id: columnId, + enabled: true, + schema: 'segment', + field: column.sourceField, + time_zone: timeZone, + useNormalizedEsInterval: !usedField?.aggregationRestrictions?.date_histogram, + interval, + drop_partials: false, + min_doc_count: 0, + extended_bounds: extendedBoundsToAst({}), + }).toAst(); + }, + paramEditor: function ParamEditor({ + layer, + columnId, + currentColumn, + updateLayer, + dateRange, + data, + indexPattern, + }: ParamEditorProps) { + const field = currentColumn && indexPattern.getFieldByName(currentColumn.sourceField); + const intervalIsRestricted = + field!.aggregationRestrictions && field!.aggregationRestrictions.date_histogram; - const interval = parseInterval(currentColumn.params.interval); + const interval = parseInterval(currentColumn.params.interval); - // We force the interval value to 1 if it's empty, since that is the ES behavior, - // and the isValidInterval function doesn't handle the empty case properly. Fixing - // isValidInterval involves breaking changes in other areas. - const isValid = isValidInterval( - `${interval.value === '' ? '1' : interval.value}${interval.unit}`, - restrictedInterval(field!.aggregationRestrictions) - ); + // We force the interval value to 1 if it's empty, since that is the ES behavior, + // and the isValidInterval function doesn't handle the empty case properly. Fixing + // isValidInterval involves breaking changes in other areas. + const isValid = isValidInterval( + `${interval.value === '' ? '1' : interval.value}${interval.unit}`, + restrictedInterval(field!.aggregationRestrictions) + ); - function onChangeAutoInterval(ev: EuiSwitchEvent) { - const { fromDate, toDate } = dateRange; - const value = ev.target.checked - ? data.search.aggs.calculateAutoTimeExpression({ from: fromDate, to: toDate }) || '1h' - : autoInterval; - updateLayer(updateColumnParam({ layer, columnId, paramName: 'interval', value })); - } + function onChangeAutoInterval(ev: EuiSwitchEvent) { + const { fromDate, toDate } = dateRange; + const value = ev.target.checked + ? data.search.aggs.calculateAutoTimeExpression({ from: fromDate, to: toDate }) || '1h' + : autoInterval; + updateLayer(updateColumnParam({ layer, columnId, paramName: 'interval', value })); + } - const setInterval = (newInterval: typeof interval) => { - const isCalendarInterval = calendarOnlyIntervals.has(newInterval.unit); - const value = `${isCalendarInterval ? '1' : newInterval.value}${newInterval.unit || 'd'}`; + const setInterval = (newInterval: typeof interval) => { + const isCalendarInterval = calendarOnlyIntervals.has(newInterval.unit); + const value = `${isCalendarInterval ? '1' : newInterval.value}${newInterval.unit || 'd'}`; - updateLayer(updateColumnParam({ layer, columnId, paramName: 'interval', value })); - }; + updateLayer(updateColumnParam({ layer, columnId, paramName: 'interval', value })); + }; - return ( - <> - {!intervalIsRestricted && ( - - - - )} - {currentColumn.params.interval !== autoInterval && ( - + {!intervalIsRestricted && ( + + - {intervalIsRestricted ? ( - - ) : ( - <> - - - { - const newInterval = { - ...interval, - value: e.target.value, - }; - setInterval(newInterval); - }} - /> - - - { - const newInterval = { - ...interval, - unit: e.target.value, - }; - setInterval(newInterval); - }} - isInvalid={!isValid} - options={[ - { - value: 'ms', - text: i18n.translate( - 'xpack.lens.indexPattern.dateHistogram.milliseconds', - { - defaultMessage: 'milliseconds', - } - ), - }, - { - value: 's', - text: i18n.translate('xpack.lens.indexPattern.dateHistogram.seconds', { - defaultMessage: 'seconds', - }), - }, - { - value: 'm', - text: i18n.translate('xpack.lens.indexPattern.dateHistogram.minutes', { - defaultMessage: 'minutes', - }), - }, - { - value: 'h', - text: i18n.translate('xpack.lens.indexPattern.dateHistogram.hours', { - defaultMessage: 'hours', - }), - }, - { - value: 'd', - text: i18n.translate('xpack.lens.indexPattern.dateHistogram.days', { - defaultMessage: 'days', - }), - }, - { - value: 'w', - text: i18n.translate('xpack.lens.indexPattern.dateHistogram.week', { - defaultMessage: 'week', - }), - }, - { - value: 'M', - text: i18n.translate('xpack.lens.indexPattern.dateHistogram.month', { - defaultMessage: 'month', - }), - }, - // Quarterly intervals appear to be unsupported by esaggs - { - value: 'y', - text: i18n.translate('xpack.lens.indexPattern.dateHistogram.year', { - defaultMessage: 'year', - }), - }, - ]} - /> - - - {!isValid && ( - <> - - - {i18n.translate('xpack.lens.indexPattern.invalidInterval', { - defaultMessage: 'Invalid interval value', - })} - - - )} - - )} - - )} - - ); - }, - }; + checked={currentColumn.params.interval !== autoInterval} + onChange={onChangeAutoInterval} + compressed + /> + + )} + {currentColumn.params.interval !== autoInterval && ( + + {intervalIsRestricted ? ( + + ) : ( + <> + + + { + const newInterval = { + ...interval, + value: e.target.value, + }; + setInterval(newInterval); + }} + /> + + + { + const newInterval = { + ...interval, + unit: e.target.value, + }; + setInterval(newInterval); + }} + isInvalid={!isValid} + options={[ + { + value: 'ms', + text: i18n.translate( + 'xpack.lens.indexPattern.dateHistogram.milliseconds', + { + defaultMessage: 'milliseconds', + } + ), + }, + { + value: 's', + text: i18n.translate('xpack.lens.indexPattern.dateHistogram.seconds', { + defaultMessage: 'seconds', + }), + }, + { + value: 'm', + text: i18n.translate('xpack.lens.indexPattern.dateHistogram.minutes', { + defaultMessage: 'minutes', + }), + }, + { + value: 'h', + text: i18n.translate('xpack.lens.indexPattern.dateHistogram.hours', { + defaultMessage: 'hours', + }), + }, + { + value: 'd', + text: i18n.translate('xpack.lens.indexPattern.dateHistogram.days', { + defaultMessage: 'days', + }), + }, + { + value: 'w', + text: i18n.translate('xpack.lens.indexPattern.dateHistogram.week', { + defaultMessage: 'week', + }), + }, + { + value: 'M', + text: i18n.translate('xpack.lens.indexPattern.dateHistogram.month', { + defaultMessage: 'month', + }), + }, + // Quarterly intervals appear to be unsupported by esaggs + { + value: 'y', + text: i18n.translate('xpack.lens.indexPattern.dateHistogram.year', { + defaultMessage: 'year', + }), + }, + ]} + /> + + + {!isValid && ( + <> + + + {i18n.translate('xpack.lens.indexPattern.invalidInterval', { + defaultMessage: 'Invalid interval value', + })} + + + )} + + )} + + )} + + ); + }, +}; function parseInterval(currentInterval: string) { const interval = currentInterval || ''; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filters.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filters.test.tsx index 640ea3a1a41f6..b215e6ed7e318 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filters.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filters.test.tsx @@ -74,7 +74,7 @@ describe('filters', () => { }, ], }, - }, + } as FiltersIndexPatternColumn, col2: { label: 'Count', dataType: 'number', diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/formula_help.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/formula_help.tsx index 47dd8fbc9c569..203774c6b1561 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/formula_help.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/formula_help.tsx @@ -28,7 +28,7 @@ import { hasFunctionFieldArgument } from '../validation'; import type { GenericOperationDefinition, - IndexPatternColumn, + GenericIndexPatternColumn, OperationDefinition, ParamEditorProps, } from '../../index'; @@ -503,7 +503,7 @@ export function getFunctionSignatureLabel( function getFunctionArgumentsStringified( params: Required< - OperationDefinition + OperationDefinition >['operationParams'] ) { return params diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.test.tsx index d3dc8e95933a3..93df78ec3f5ff 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.test.tsx @@ -6,15 +6,18 @@ */ import { createMockedIndexPattern } from '../../../mocks'; -import { formulaOperation, GenericOperationDefinition, IndexPatternColumn } from '../index'; +import { formulaOperation, GenericOperationDefinition, GenericIndexPatternColumn } from '../index'; import { FormulaIndexPatternColumn } from './formula'; import { regenerateLayerFromAst } from './parse'; import type { IndexPattern, IndexPatternField, IndexPatternLayer } from '../../../types'; import { tinymathFunctions } from './util'; +import { TermsIndexPatternColumn } from '../terms'; +import { MovingAverageIndexPatternColumn } from '../calculations'; +import { StaticValueIndexPatternColumn } from '../static_value'; jest.mock('../../layer_helpers', () => { return { - getColumnOrder: jest.fn(({ columns }: { columns: Record }) => + getColumnOrder: jest.fn(({ columns }: { columns: Record }) => Object.keys(columns) ), getManagedColumnsFrom: jest.fn().mockReturnValue([]), @@ -113,7 +116,7 @@ describe('formula', () => { orderDirection: 'asc', }, sourceField: 'category', - }, + } as TermsIndexPatternColumn, }, }; }); @@ -191,7 +194,7 @@ describe('formula', () => { }, }, }, - } as IndexPatternColumn, + } as GenericIndexPatternColumn, layer, indexPattern, }) @@ -225,7 +228,7 @@ describe('formula', () => { // Need to test with multiple replaces due to string replace query: `category.keyword: "Men's Clothing" or category.keyword: "Men's Shoes"`, }, - } as IndexPatternColumn, + } as GenericIndexPatternColumn, layer, indexPattern, }) @@ -254,7 +257,7 @@ describe('formula', () => { language: 'lucene', query: `*`, }, - } as IndexPatternColumn, + } as GenericIndexPatternColumn, layer, indexPattern, }) @@ -285,7 +288,7 @@ describe('formula', () => { references: ['col2'], timeScale: 'd', params: { window: 3 }, - }, + } as MovingAverageIndexPatternColumn, layer: { indexPatternId: '1', columnOrder: [], @@ -299,7 +302,7 @@ describe('formula', () => { references: ['col2'], timeScale: 'd', params: { window: 3 }, - }, + } as MovingAverageIndexPatternColumn, col2: { dataType: 'number', isBucketed: false, @@ -345,7 +348,7 @@ describe('formula', () => { orderDirection: 'asc', }, sourceField: 'category', - }, + } as TermsIndexPatternColumn, layer: { indexPatternId: '1', columnOrder: [], @@ -361,7 +364,7 @@ describe('formula', () => { orderDirection: 'asc', }, sourceField: 'category', - }, + } as TermsIndexPatternColumn, }, }, indexPattern, @@ -392,7 +395,7 @@ describe('formula', () => { params: { value: '0', }, - }, + } as StaticValueIndexPatternColumn, layer, indexPattern, }) @@ -668,7 +671,7 @@ describe('formula', () => { scale: 'ratio', params: { formula, isFormulaBroken: isBroken }, references: [], - }, + } as FormulaIndexPatternColumn, }, columnOrder: [], indexPatternId: '', diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.tsx index 511f18415272e..5842cde4fea31 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.tsx @@ -15,6 +15,7 @@ import { regenerateLayerFromAst } from './parse'; import { generateFormula } from './generate'; import { filterByVisibleOperation } from './util'; import { getManagedColumnsFrom } from '../../layer_helpers'; +import { isColumnFormatted } from '../helpers'; const defaultLabel = i18n.translate('xpack.lens.indexPattern.formulaLabel', { defaultMessage: 'Formula', @@ -120,8 +121,8 @@ export const formulaOperation: OperationDefinition>; @@ -33,12 +35,12 @@ export function getSafeFieldName({ } export function generateFormula( - previousColumn: ReferenceBasedIndexPatternColumn | IndexPatternColumn, + previousColumn: ReferenceBasedIndexPatternColumn | GenericIndexPatternColumn, layer: IndexPatternLayer, previousFormula: string, operationDefinitionMap: Record | undefined ) { - if (previousColumn.operationType === 'static_value') { + if (isColumnOfType('static_value', previousColumn)) { if (previousColumn.params && 'value' in previousColumn.params) { return String(previousColumn.params.value); // make sure it's a string } @@ -81,17 +83,25 @@ export function generateFormula( return previousFormula; } +interface ParameterizedColumn extends BaseIndexPatternColumn { + params: OperationParams; +} + +function isParameterizedColumn(col: GenericIndexPatternColumn): col is ParameterizedColumn { + return Boolean('params' in col && col.params); +} + function extractParamsForFormula( - column: IndexPatternColumn | ReferenceBasedIndexPatternColumn, + column: GenericIndexPatternColumn, operationDefinitionMap: Record | undefined ) { if (!operationDefinitionMap) { return []; } const def = operationDefinitionMap[column.operationType]; - if ('operationParams' in def && column.params) { + if ('operationParams' in def && isParameterizedColumn(column)) { return (def.operationParams || []).flatMap(({ name, required }) => { - const value = (column.params as OperationParams)![name]; + const value = column.params[name]; if (isObject(value)) { return Object.keys(value).map((subName) => ({ name: `${name}-${subName}`, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/parse.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/parse.ts index adccecc875c22..ead2467416ce2 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/parse.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/parse.ts @@ -8,7 +8,11 @@ import { i18n } from '@kbn/i18n'; import { isObject } from 'lodash'; import type { TinymathAST, TinymathVariable, TinymathLocation } from '@kbn/tinymath'; -import { OperationDefinition, GenericOperationDefinition, IndexPatternColumn } from '../index'; +import { + OperationDefinition, + GenericOperationDefinition, + GenericIndexPatternColumn, +} from '../index'; import { IndexPattern, IndexPatternLayer } from '../../../types'; import { mathOperation } from './math'; import { documentField } from '../../../document_field'; @@ -67,8 +71,8 @@ function extractColumns( layer: IndexPatternLayer, indexPattern: IndexPattern, label: string -): Array<{ column: IndexPatternColumn; location?: TinymathLocation }> { - const columns: Array<{ column: IndexPatternColumn; location?: TinymathLocation }> = []; +): Array<{ column: GenericIndexPatternColumn; location?: TinymathLocation }> { + const columns: Array<{ column: GenericIndexPatternColumn; location?: TinymathLocation }> = []; function parseNode(node: TinymathAST) { if (typeof node === 'number' || node.type !== 'function') { @@ -102,7 +106,7 @@ function extractColumns( const mappedParams = getOperationParams(nodeOperation, namedArguments || []); const newCol = ( - nodeOperation as OperationDefinition + nodeOperation as OperationDefinition ).buildColumn( { layer, @@ -139,7 +143,7 @@ function extractColumns( const mappedParams = getOperationParams(nodeOperation, namedArguments || []); const newCol = ( - nodeOperation as OperationDefinition + nodeOperation as OperationDefinition ).buildColumn( { layer, @@ -227,7 +231,7 @@ export function regenerateLayerFromAst( isFormulaBroken: !isValid, }, references: !isValid ? [] : [getManagedId(columnId, extracted.length - 1)], - }; + } as FormulaIndexPatternColumn; return { newLayer: { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/util.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/util.ts index f1530ba46caef..db267bfb0d564 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/util.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/util.ts @@ -13,7 +13,11 @@ import type { TinymathNamedArgument, TinymathVariable, } from 'packages/kbn-tinymath'; -import type { OperationDefinition, IndexPatternColumn, GenericOperationDefinition } from '../index'; +import type { + OperationDefinition, + GenericIndexPatternColumn, + GenericOperationDefinition, +} from '../index'; import type { GroupedNodes } from './types'; export const unquotedStringRegex = /[^0-9A-Za-z._@\[\]/]/; @@ -46,8 +50,8 @@ export function getValueOrName(node: TinymathAST) { export function getOperationParams( operation: - | OperationDefinition - | OperationDefinition, + | OperationDefinition + | OperationDefinition, params: TinymathNamedArgument[] = [] ): Record { const formalArgs: Record = (operation.operationParams || []).reduce( diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/validation.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/validation.ts index 1a8d8529a9b90..d6b9a1fff8e9d 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/validation.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/validation.ts @@ -20,7 +20,11 @@ import { tinymathFunctions, } from './util'; -import type { OperationDefinition, IndexPatternColumn, GenericOperationDefinition } from '../index'; +import type { + OperationDefinition, + GenericIndexPatternColumn, + GenericOperationDefinition, +} from '../index'; import type { IndexPattern, IndexPatternLayer } from '../../../types'; import type { TinymathNodeTypes } from './types'; import { parseTimeShift } from '../../../../../../../../src/plugins/data/common'; @@ -482,8 +486,8 @@ function checkSingleQuery(namedArguments: TinymathNamedArgument[] | undefined) { function validateNameArguments( node: TinymathFunction, nodeOperation: - | OperationDefinition - | OperationDefinition, + | OperationDefinition + | OperationDefinition, namedArguments: TinymathNamedArgument[] | undefined, indexPattern: IndexPattern ) { @@ -749,16 +753,16 @@ function runFullASTValidation( export function canHaveParams( operation: - | OperationDefinition - | OperationDefinition + | OperationDefinition + | OperationDefinition ) { return Boolean((operation.operationParams || []).length) || operation.filterable; } export function getInvalidParams( operation: - | OperationDefinition - | OperationDefinition, + | OperationDefinition + | OperationDefinition, params: TinymathNamedArgument[] = [] ) { return validateParams(operation, params).filter( @@ -768,8 +772,8 @@ export function getInvalidParams( export function getMissingParams( operation: - | OperationDefinition - | OperationDefinition, + | OperationDefinition + | OperationDefinition, params: TinymathNamedArgument[] = [] ) { return validateParams(operation, params).filter( @@ -779,8 +783,8 @@ export function getMissingParams( export function getWrongTypeParams( operation: - | OperationDefinition - | OperationDefinition, + | OperationDefinition + | OperationDefinition, params: TinymathNamedArgument[] = [] ) { return validateParams(operation, params).filter( @@ -789,7 +793,7 @@ export function getWrongTypeParams( } function getReturnedType( - operation: OperationDefinition, + operation: OperationDefinition, indexPattern: IndexPattern, firstArg: TinymathAST ) { @@ -822,8 +826,8 @@ function getDuplicateParams(params: TinymathNamedArgument[] = []) { export function validateParams( operation: - | OperationDefinition - | OperationDefinition, + | OperationDefinition + | OperationDefinition, params: TinymathNamedArgument[] = [] ) { const paramsObj = getOperationParams(operation, params); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/helpers.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/helpers.tsx index a399183694863..9b22ef02fb3b5 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/helpers.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/helpers.tsx @@ -6,8 +6,12 @@ */ import { i18n } from '@kbn/i18n'; -import { IndexPatternColumn, operationDefinitionMap } from '.'; -import { FieldBasedIndexPatternColumn, ReferenceBasedIndexPatternColumn } from './column_types'; +import { GenericIndexPatternColumn, operationDefinitionMap } from '.'; +import { + FieldBasedIndexPatternColumn, + FormattedIndexPatternColumn, + ReferenceBasedIndexPatternColumn, +} from './column_types'; import { IndexPattern } from '../../types'; export function getInvalidFieldMessage( @@ -36,7 +40,7 @@ export function getInvalidFieldMessage( operationDefinition && field && !operationDefinition.isTransferable( - column as IndexPatternColumn, + column as GenericIndexPatternColumn, indexPattern, operationDefinitionMap ) @@ -90,19 +94,35 @@ export function isValidNumber( ); } +export function isColumnOfType( + type: C['operationType'], + column: GenericIndexPatternColumn +): column is C { + return column.operationType === type; +} + +export function isColumnFormatted( + column: GenericIndexPatternColumn +): column is FormattedIndexPatternColumn { + return Boolean( + 'params' in column && + (column as FormattedIndexPatternColumn).params && + 'format' in (column as FormattedIndexPatternColumn).params! + ); +} + export function getFormatFromPreviousColumn( - previousColumn: IndexPatternColumn | ReferenceBasedIndexPatternColumn | undefined + previousColumn: GenericIndexPatternColumn | ReferenceBasedIndexPatternColumn | undefined ) { return previousColumn?.dataType === 'number' && - previousColumn.params && - 'format' in previousColumn.params && - previousColumn.params.format + isColumnFormatted(previousColumn) && + previousColumn.params ? { format: previousColumn.params.format } : undefined; } export function getFilter( - previousColumn: IndexPatternColumn | undefined, + previousColumn: GenericIndexPatternColumn | undefined, columnParams: { kql?: string | undefined; lucene?: string | undefined } | undefined ) { let filter = previousColumn?.filter; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/index.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/index.ts index 5898cfc26d88c..f18bdb9498f25 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/index.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/index.ts @@ -7,93 +7,51 @@ import { IUiSettingsClient, SavedObjectsClientContract, HttpSetup, CoreStart } from 'kibana/public'; import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; -import { termsOperation, TermsIndexPatternColumn } from './terms'; -import { filtersOperation, FiltersIndexPatternColumn } from './filters'; -import { cardinalityOperation, CardinalityIndexPatternColumn } from './cardinality'; -import { percentileOperation, PercentileIndexPatternColumn } from './percentile'; +import { termsOperation } from './terms'; +import { filtersOperation } from './filters'; +import { cardinalityOperation } from './cardinality'; +import { percentileOperation } from './percentile'; import { minOperation, - MinIndexPatternColumn, averageOperation, - AvgIndexPatternColumn, sumOperation, - SumIndexPatternColumn, maxOperation, - MaxIndexPatternColumn, medianOperation, - MedianIndexPatternColumn, } from './metrics'; -import { dateHistogramOperation, DateHistogramIndexPatternColumn } from './date_histogram'; +import { dateHistogramOperation } from './date_histogram'; import { cumulativeSumOperation, - CumulativeSumIndexPatternColumn, counterRateOperation, - CounterRateIndexPatternColumn, derivativeOperation, - DerivativeIndexPatternColumn, movingAverageOperation, - MovingAverageIndexPatternColumn, - OverallSumIndexPatternColumn, overallSumOperation, - OverallMinIndexPatternColumn, overallMinOperation, - OverallMaxIndexPatternColumn, overallMaxOperation, - OverallAverageIndexPatternColumn, overallAverageOperation, } from './calculations'; -import { countOperation, CountIndexPatternColumn } from './count'; -import { - mathOperation, - MathIndexPatternColumn, - formulaOperation, - FormulaIndexPatternColumn, -} from './formula'; -import { staticValueOperation, StaticValueIndexPatternColumn } from './static_value'; -import { lastValueOperation, LastValueIndexPatternColumn } from './last_value'; +import { countOperation } from './count'; +import { mathOperation, formulaOperation } from './formula'; +import { staticValueOperation } from './static_value'; +import { lastValueOperation } from './last_value'; import { FrameDatasourceAPI, OperationMetadata, ParamEditorCustomProps } from '../../../types'; -import type { BaseIndexPatternColumn, ReferenceBasedIndexPatternColumn } from './column_types'; +import type { + BaseIndexPatternColumn, + GenericIndexPatternColumn, + ReferenceBasedIndexPatternColumn, +} from './column_types'; import { IndexPattern, IndexPatternField, IndexPatternLayer } from '../../types'; import { DateRange, LayerType } from '../../../../common'; import { ExpressionAstFunction } from '../../../../../../../src/plugins/expressions/public'; import { DataPublicPluginStart } from '../../../../../../../src/plugins/data/public'; -import { RangeIndexPatternColumn, rangeOperation } from './ranges'; +import { rangeOperation } from './ranges'; import { IndexPatternDimensionEditorProps } from '../../dimension_panel'; -/** - * A union type of all available column types. If a column is of an unknown type somewhere - * withing the indexpattern data source it should be typed as `IndexPatternColumn` to make - * typeguards possible that consider all available column types. - */ -export type IndexPatternColumn = - | FiltersIndexPatternColumn - | RangeIndexPatternColumn - | TermsIndexPatternColumn - | DateHistogramIndexPatternColumn - | MinIndexPatternColumn - | MaxIndexPatternColumn - | AvgIndexPatternColumn - | CardinalityIndexPatternColumn - | SumIndexPatternColumn - | MedianIndexPatternColumn - | PercentileIndexPatternColumn - | CountIndexPatternColumn - | LastValueIndexPatternColumn - | CumulativeSumIndexPatternColumn - | OverallSumIndexPatternColumn - | OverallMinIndexPatternColumn - | OverallMaxIndexPatternColumn - | OverallAverageIndexPatternColumn - | CounterRateIndexPatternColumn - | DerivativeIndexPatternColumn - | MovingAverageIndexPatternColumn - | MathIndexPatternColumn - | FormulaIndexPatternColumn - | StaticValueIndexPatternColumn; - -export type FieldBasedIndexPatternColumn = Extract; - -export type { IncompleteColumn } from './column_types'; +export type { + IncompleteColumn, + BaseIndexPatternColumn, + GenericIndexPatternColumn, + FieldBasedIndexPatternColumn, +} from './column_types'; export type { TermsIndexPatternColumn } from './terms'; export type { FiltersIndexPatternColumn } from './filters'; @@ -125,7 +83,7 @@ export type { StaticValueIndexPatternColumn } from './static_value'; // List of all operation definitions registered to this data source. // If you want to implement a new operation, add the definition to this array and -// the column type to the `IndexPatternColumn` union type below. +// the column type to the `GenericIndexPatternColumn` union type below. const internalOperationDefinitions = [ filtersOperation, termsOperation, @@ -227,7 +185,7 @@ interface BaseOperationDefinitionProps { getDefaultLabel: ( column: C, indexPattern: IndexPattern, - columns: Record + columns: Record ) => string; /** * This function is called if another column in the same layer changed or got added/removed. @@ -337,7 +295,7 @@ interface OperationParam { defaultValue?: string | number; } -interface FieldlessOperationDefinition { +interface FieldlessOperationDefinition { input: 'none'; /** @@ -350,9 +308,9 @@ interface FieldlessOperationDefinition { */ buildColumn: ( arg: BaseBuildColumnArgs & { - previousColumn?: IndexPatternColumn; + previousColumn?: GenericIndexPatternColumn; }, - columnParams?: (IndexPatternColumn & C)['params'] + columnParams?: P ) => C; /** * Returns the meta data of the operation if applied. Undefined @@ -372,7 +330,7 @@ interface FieldlessOperationDefinition { ) => ExpressionAstFunction; } -interface FieldBasedOperationDefinition { +interface FieldBasedOperationDefinition { input: 'field'; /** @@ -391,9 +349,9 @@ interface FieldBasedOperationDefinition { buildColumn: ( arg: BaseBuildColumnArgs & { field: IndexPatternField; - previousColumn?: IndexPatternColumn; + previousColumn?: GenericIndexPatternColumn; }, - columnParams?: (IndexPatternColumn & C)['params'] & { + columnParams?: P & { kql?: string; lucene?: string; shift?: string; @@ -498,7 +456,7 @@ interface FullReferenceOperationDefinition { buildColumn: ( arg: BaseBuildColumnArgs & { referenceIds: string[]; - previousColumn?: IndexPatternColumn; + previousColumn?: GenericIndexPatternColumn; }, columnParams?: (ReferenceBasedIndexPatternColumn & C)['params'] & { kql?: string; @@ -528,7 +486,7 @@ interface ManagedReferenceOperationDefinition */ buildColumn: ( arg: BaseBuildColumnArgs & { - previousColumn?: IndexPatternColumn | ReferenceBasedIndexPatternColumn; + previousColumn?: GenericIndexPatternColumn; }, columnParams?: (ReferenceBasedIndexPatternColumn & C)['params'], operationDefinitionMap?: Record @@ -559,9 +517,9 @@ interface ManagedReferenceOperationDefinition ) => IndexPatternLayer; } -interface OperationDefinitionMap { - field: FieldBasedOperationDefinition; - none: FieldlessOperationDefinition; +interface OperationDefinitionMap { + field: FieldBasedOperationDefinition; + none: FieldlessOperationDefinition; fullReference: FullReferenceOperationDefinition; managedReference: ManagedReferenceOperationDefinition; } @@ -573,24 +531,25 @@ interface OperationDefinitionMap { */ export type OperationDefinition< C extends BaseIndexPatternColumn, - Input extends keyof OperationDefinitionMap -> = BaseOperationDefinitionProps & OperationDefinitionMap[Input]; + Input extends keyof OperationDefinitionMap, + P = {} +> = BaseOperationDefinitionProps & OperationDefinitionMap[Input]; /** * A union type of all available operation types. The operation type is a unique id of an operation. * Each column is assigned to exactly one operation type. */ -export type OperationType = typeof internalOperationDefinitions[number]['type']; +export type OperationType = string; /** * This is an operation definition of an unspecified column out of all possible * column types. */ export type GenericOperationDefinition = - | OperationDefinition - | OperationDefinition - | OperationDefinition - | OperationDefinition; + | OperationDefinition + | OperationDefinition + | OperationDefinition + | OperationDefinition; /** * List of all available operation definitions diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.test.tsx index 13e16fe1af4d0..26074b47e0f48 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.test.tsx @@ -15,6 +15,7 @@ import { createMockedIndexPattern } from '../../mocks'; import { LastValueIndexPatternColumn } from './last_value'; import { lastValueOperation } from './index'; import type { IndexPattern, IndexPatternLayer } from '../../types'; +import { TermsIndexPatternColumn } from './terms'; const uiSettingsMock = {} as IUiSettingsClient; @@ -56,7 +57,7 @@ describe('last_value', () => { orderDirection: 'asc', }, sourceField: 'category', - }, + } as TermsIndexPatternColumn, col2: { label: 'Last value of a', dataType: 'number', @@ -66,7 +67,7 @@ describe('last_value', () => { params: { sortField: 'datefield', }, - }, + } as LastValueIndexPatternColumn, }, }; }); @@ -467,7 +468,7 @@ describe('last_value', () => { params: { sortField: 'timestamp' }, scale: 'ratio', sourceField: 'bytes', - }, + } as LastValueIndexPatternColumn, }, columnOrder: [], indexPatternId: '', @@ -499,7 +500,7 @@ describe('last_value', () => { col1: { ...errorLayer.columns.col1, params: { - ...errorLayer.columns.col1.params, + ...(errorLayer.columns.col1 as LastValueIndexPatternColumn).params, sortField: 'notExisting', }, } as LastValueIndexPatternColumn, @@ -530,7 +531,7 @@ describe('last_value', () => { col1: { ...errorLayer.columns.col1, params: { - ...errorLayer.columns.col1.params, + ...(errorLayer.columns.col1 as LastValueIndexPatternColumn).params, sortField: 'bytes', }, } as LastValueIndexPatternColumn, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.test.tsx index 61f2390820067..a8851c79be2ae 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.test.tsx @@ -17,6 +17,7 @@ import { PercentileIndexPatternColumn } from './percentile'; import { EuiFieldNumber } from '@elastic/eui'; import { act } from 'react-dom/test-utils'; import { EuiFormRow } from '@elastic/eui'; +import { TermsIndexPatternColumn } from './terms'; const uiSettingsMock = {} as IUiSettingsClient; @@ -58,7 +59,7 @@ describe('percentile', () => { orderDirection: 'asc', }, sourceField: 'category', - }, + } as TermsIndexPatternColumn, col2: { label: '23rd percentile of a', dataType: 'number', @@ -68,7 +69,7 @@ describe('percentile', () => { params: { percentile: 23, }, - }, + } as PercentileIndexPatternColumn, }, }; }); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.tsx index 9c9f7e8b66a1f..3aaeb9d944728 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.tsx @@ -17,6 +17,7 @@ import { getSafeName, isValidNumber, getFilter, + isColumnOfType, } from './helpers'; import { FieldBasedIndexPatternColumn } from './column_types'; import { adjustTimeScaleLabelSuffix } from '../time_scale_utils'; @@ -53,7 +54,11 @@ const DEFAULT_PERCENTILE_VALUE = 95; const supportedFieldTypes = ['number', 'histogram']; -export const percentileOperation: OperationDefinition = { +export const percentileOperation: OperationDefinition< + PercentileIndexPatternColumn, + 'field', + { percentile: number } +> = { type: 'percentile', displayName: i18n.translate('xpack.lens.indexPattern.percentile', { defaultMessage: 'Percentile', @@ -91,9 +96,8 @@ export const percentileOperation: OperationDefinition { const existingPercentileParam = - previousColumn?.operationType === 'percentile' && - previousColumn.params && - 'percentile' in previousColumn.params && + previousColumn && + isColumnOfType('percentile', previousColumn) && previousColumn.params.percentile; const newPercentileParam = columnParams?.percentile ?? (existingPercentileParam || DEFAULT_PERCENTILE_VALUE); @@ -174,7 +178,7 @@ export const percentileOperation: OperationDefinition { ranges: [{ from: 0, to: DEFAULT_INTERVAL, label: '' }], maxBars: 'auto', }, - }, + } as RangeIndexPatternColumn, col2: { label: 'Count', dataType: 'number', @@ -385,10 +385,10 @@ describe('ranges', () => { col1: { ...layer.columns.col1, params: { - ...layer.columns.col1.params, + ...(layer.columns.col1 as RangeIndexPatternColumn).params, maxBars: MAX_HISTOGRAM_VALUE, }, - }, + } as RangeIndexPatternColumn, }, }); }); @@ -424,7 +424,7 @@ describe('ranges', () => { col1: { ...layer.columns.col1, params: { - ...layer.columns.col1.params, + ...(layer.columns.col1 as RangeIndexPatternColumn).params, maxBars: GRANULARITY_DEFAULT_VALUE - GRANULARITY_STEP, }, }, @@ -448,7 +448,7 @@ describe('ranges', () => { col1: { ...layer.columns.col1, params: { - ...layer.columns.col1.params, + ...(layer.columns.col1 as RangeIndexPatternColumn).params, maxBars: GRANULARITY_DEFAULT_VALUE, }, }, @@ -511,7 +511,10 @@ describe('ranges', () => { currentColumn={ { ...layer.columns.col1, - params: { ...layer.columns.col1.params, parentFormat: undefined }, + params: { + ...(layer.columns.col1 as RangeIndexPatternColumn).params, + parentFormat: undefined, + }, } as RangeIndexPatternColumn } /> @@ -565,7 +568,7 @@ describe('ranges', () => { col1: { ...layer.columns.col1, params: { - ...layer.columns.col1.params, + ...(layer.columns.col1 as RangeIndexPatternColumn).params, ranges: [ { from: 0, to: DEFAULT_INTERVAL, label: '' }, { from: 50, to: Infinity, label: '' }, @@ -620,7 +623,7 @@ describe('ranges', () => { col1: { ...layer.columns.col1, params: { - ...layer.columns.col1.params, + ...(layer.columns.col1 as RangeIndexPatternColumn).params, ranges: [ { from: 0, to: DEFAULT_INTERVAL, label: '' }, { from: DEFAULT_INTERVAL, to: Infinity, label: 'customlabel' }, @@ -670,7 +673,7 @@ describe('ranges', () => { col1: { ...layer.columns.col1, params: { - ...layer.columns.col1.params, + ...(layer.columns.col1 as RangeIndexPatternColumn).params, ranges: [{ from: 0, to: 50, label: '' }], }, }, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/ranges.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/ranges.tsx index 6e397a926c7a0..63ec5293ddd79 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/ranges.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/ranges.tsx @@ -244,7 +244,7 @@ export const rangeOperation: OperationDefinition { const original = jest.requireActual('lodash'); @@ -65,7 +66,7 @@ describe('static_value', () => { orderDirection: 'asc', }, sourceField: 'category', - }, + } as TermsIndexPatternColumn, col2: { label: 'Static value: 23', dataType: 'number', @@ -75,7 +76,7 @@ describe('static_value', () => { params: { value: '23', }, - }, + } as StaticValueIndexPatternColumn, }, }; }); @@ -256,7 +257,7 @@ describe('static_value', () => { scale: 'ratio', params: { value: '23' }, references: [], - }, + } as StaticValueIndexPatternColumn, }) ).toEqual({ label: 'Static value: 23', @@ -303,7 +304,7 @@ describe('static_value', () => { scale: 'ratio', params: { value: '23' }, references: [], - }, + } as StaticValueIndexPatternColumn, }, { value: '53' } ) @@ -351,7 +352,7 @@ describe('static_value', () => { params: { value: '0', }, - }, + } as StaticValueIndexPatternColumn, }, } as IndexPatternLayer; const instance = shallow( diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/static_value.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/static_value.tsx index b66092e8a48c3..969ce45ded073 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/static_value.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/static_value.tsx @@ -11,7 +11,7 @@ import { OperationDefinition } from './index'; import { ReferenceBasedIndexPatternColumn } from './column_types'; import type { IndexPattern } from '../../types'; import { useDebouncedValue } from '../../../shared_components'; -import { getFormatFromPreviousColumn, isValidNumber } from './helpers'; +import { getFormatFromPreviousColumn, isColumnOfType, isValidNumber } from './helpers'; const defaultLabel = i18n.translate('xpack.lens.indexPattern.staticValueLabelDefault', { defaultMessage: 'Static value', @@ -102,8 +102,8 @@ export const staticValueOperation: OperationDefinition< }, buildColumn({ previousColumn, layer, indexPattern }, columnParams, operationDefinitionMap) { const existingStaticValue = - previousColumn?.params && - 'value' in previousColumn.params && + previousColumn && + isColumnOfType('static_value', previousColumn) && isValidNumber(previousColumn.params.value) ? previousColumn.params.value : undefined; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/terms.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/terms.test.tsx index 180d5ed5e49b7..9b19ab43473d2 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/terms.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/terms.test.tsx @@ -20,9 +20,10 @@ import { dataPluginMock } from '../../../../../../../../src/plugins/data/public/ import { createMockedIndexPattern } from '../../../mocks'; import { ValuesInput } from './values_input'; import type { TermsIndexPatternColumn } from '.'; -import { termsOperation } from '../index'; +import { termsOperation, LastValueIndexPatternColumn } from '../index'; import { IndexPattern, IndexPatternLayer } from '../../../types'; import { FrameDatasourceAPI } from '../../../../types'; +import { DateHistogramIndexPatternColumn } from '../date_histogram'; const uiSettingsMock = {} as IUiSettingsClient; @@ -61,7 +62,7 @@ describe('terms', () => { orderDirection: 'asc', }, sourceField: 'source', - }, + } as TermsIndexPatternColumn, col2: { label: 'Count', dataType: 'number', @@ -357,7 +358,7 @@ describe('terms', () => { params: { sortField: 'datefield', }, - }, + } as LastValueIndexPatternColumn, }, columnOrder: [], indexPatternId: '', @@ -472,7 +473,7 @@ describe('terms', () => { params: { sortField: 'time', }, - }, + } as LastValueIndexPatternColumn, }, columnOrder: [], indexPatternId: '', @@ -551,7 +552,7 @@ describe('terms', () => { orderDirection: 'asc', }, sourceField: 'category', - }, + } as TermsIndexPatternColumn, }, columnOrder: [], indexPatternId: '', @@ -583,7 +584,7 @@ describe('terms', () => { orderDirection: 'asc', }, sourceField: 'category', - }, + } as TermsIndexPatternColumn, col1: { label: 'Value of timestamp', dataType: 'date', @@ -595,7 +596,7 @@ describe('terms', () => { interval: 'w', }, sourceField: 'timestamp', - }, + } as DateHistogramIndexPatternColumn, }, columnOrder: [], indexPatternId: '', @@ -627,7 +628,7 @@ describe('terms', () => { orderDirection: 'desc', }, sourceField: 'category', - }, + } as TermsIndexPatternColumn, }, columnOrder: [], indexPatternId: '', @@ -755,7 +756,7 @@ describe('terms', () => { { ...layer.columns.col1, params: { - ...layer.columns.col1.params, + ...(layer.columns.col1 as TermsIndexPatternColumn).params, otherBucket: true, }, } as TermsIndexPatternColumn @@ -783,7 +784,7 @@ describe('terms', () => { ...layer.columns.col1, sourceField: 'bytes', params: { - ...layer.columns.col1.params, + ...(layer.columns.col1 as TermsIndexPatternColumn).params, otherBucket: true, }, } as TermsIndexPatternColumn @@ -1018,7 +1019,7 @@ describe('terms', () => { }, scale: 'ordinal', sourceField: 'bytes', - }, + } as TermsIndexPatternColumn, }, columnOrder: [], indexPatternId: '', diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/index.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/index.ts index 86add22b2b8ce..b9d675716c788 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/index.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/index.ts @@ -10,7 +10,9 @@ export * from './layer_helpers'; export * from './time_scale_utils'; export type { OperationType, - IndexPatternColumn, + BaseIndexPatternColumn, + GenericOperationDefinition, + GenericIndexPatternColumn, FieldBasedIndexPatternColumn, IncompleteColumn, RequiredReference, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.test.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.test.ts index 3dc0677f3b9b6..d7728cb5af4ff 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.test.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.test.ts @@ -21,13 +21,21 @@ import { operationDefinitionMap, OperationType } from '../operations'; import { TermsIndexPatternColumn } from './definitions/terms'; import { DateHistogramIndexPatternColumn } from './definitions/date_histogram'; import { AvgIndexPatternColumn } from './definitions/metrics'; -import type { IndexPattern, IndexPatternLayer } from '../types'; +import type { IndexPattern, IndexPatternLayer, IndexPatternPrivateState } from '../types'; import { documentField } from '../document_field'; import { getFieldByNameFactory } from '../pure_helpers'; import { generateId } from '../../id_generator'; import { createMockedFullReference, createMockedManagedReference } from './mocks'; -import { IndexPatternColumn, OperationDefinition } from './definitions'; +import { + FiltersIndexPatternColumn, + FormulaIndexPatternColumn, + GenericIndexPatternColumn, + MathIndexPatternColumn, + MovingAverageIndexPatternColumn, + OperationDefinition, +} from './definitions'; import { TinymathAST } from 'packages/kbn-tinymath'; +import { CoreStart } from 'kibana/public'; jest.mock('../operations'); jest.mock('../../id_generator'); @@ -292,7 +300,7 @@ describe('state_helpers', () => { params: { interval: 'h', }, - }, + } as DateHistogramIndexPatternColumn, }, }; expect( @@ -323,7 +331,7 @@ describe('state_helpers', () => { params: { interval: 'h', }, - }, + } as DateHistogramIndexPatternColumn, col3: { label: 'Reference', dataType: 'number', @@ -362,7 +370,7 @@ describe('state_helpers', () => { params: { interval: 'h', }, - }, + } as DateHistogramIndexPatternColumn, col3: { label: 'Count of records', dataType: 'document', @@ -458,7 +466,7 @@ describe('state_helpers', () => { params: { interval: 'h', }, - }, + } as DateHistogramIndexPatternColumn, }, }, columnId: 'col2', @@ -488,7 +496,7 @@ describe('state_helpers', () => { params: { interval: 'h', }, - }, + } as DateHistogramIndexPatternColumn, }, }, columnId: 'col2', @@ -520,7 +528,7 @@ describe('state_helpers', () => { orderDirection: 'asc', size: 5, }, - }, + } as TermsIndexPatternColumn, }, }, columnId: 'col2', @@ -598,7 +606,7 @@ describe('state_helpers', () => { params: { interval: 'h', }, - }, + } as DateHistogramIndexPatternColumn, }, }, columnId: 'col2', @@ -680,8 +688,8 @@ describe('state_helpers', () => { layer, indexPattern, columnId: 'col1', - // @ts-expect-error invalid type op: 'testReference', + visualizationGroups: [], }); expect(result.columnOrder).toEqual(['id1', 'col1']); expect(result.columns).toEqual( @@ -700,8 +708,8 @@ describe('state_helpers', () => { col1: { dataType: 'number', isBucketed: false, + label: '', - // @ts-expect-error only in test operationType: 'testReference', references: ['ref1'], }, @@ -745,7 +753,7 @@ describe('state_helpers', () => { params: { interval: 'h', }, - }, + } as DateHistogramIndexPatternColumn, }, }, columnId: 'col2', @@ -848,7 +856,7 @@ describe('state_helpers', () => { params: { interval: 'h', }, - }, + } as DateHistogramIndexPatternColumn, }, }, columnId: 'col1', @@ -878,7 +886,7 @@ describe('state_helpers', () => { params: { interval: 'h', }, - }, + } as DateHistogramIndexPatternColumn, }, }, columnId: 'col1', @@ -914,7 +922,7 @@ describe('state_helpers', () => { params: { interval: 'h', }, - }, + } as DateHistogramIndexPatternColumn, }, }, columnId: 'col1', @@ -948,7 +956,7 @@ describe('state_helpers', () => { params: { interval: 'h', }, - }, + } as DateHistogramIndexPatternColumn, }, incompleteColumns: { col1: { operationType: 'terms' }, @@ -986,7 +994,7 @@ describe('state_helpers', () => { params: { filters: [], }, - }, + } as FiltersIndexPatternColumn, }, }, indexPattern, @@ -1022,7 +1030,7 @@ describe('state_helpers', () => { params: { interval: 'h', }, - }, + } as DateHistogramIndexPatternColumn, }, }, indexPattern, @@ -1058,7 +1066,7 @@ describe('state_helpers', () => { params: { interval: 'h', }, - }, + } as DateHistogramIndexPatternColumn, }, }, indexPattern, @@ -1093,7 +1101,7 @@ describe('state_helpers', () => { params: { interval: 'h', }, - }, + } as DateHistogramIndexPatternColumn, }, }, indexPattern, @@ -1128,7 +1136,7 @@ describe('state_helpers', () => { orderDirection: 'asc', size: 5, }, - }, + } as TermsIndexPatternColumn, }, }, indexPattern, @@ -1160,7 +1168,7 @@ describe('state_helpers', () => { orderDirection: 'asc', size: 5, }, - }, + } as TermsIndexPatternColumn, }, }, indexPattern, @@ -1215,7 +1223,7 @@ describe('state_helpers', () => { scale: 'ratio', params: { isFormulaBroken: false, formula: 'average(bytes)' }, references: [], - }, + } as FormulaIndexPatternColumn, }, }, indexPattern, @@ -1244,7 +1252,7 @@ describe('state_helpers', () => { scale: 'ratio', params: { isFormulaBroken: false, formula: 'average(bytes)' }, references: [], - }, + } as FormulaIndexPatternColumn, }, }, indexPattern, @@ -1490,8 +1498,8 @@ describe('state_helpers', () => { layer, indexPattern, columnId: 'col1', - // @ts-expect-error op: 'testReference', + visualizationGroups: [], }); expect(result.columnOrder).toEqual(['id1', 'col1']); @@ -1531,8 +1539,8 @@ describe('state_helpers', () => { layer, indexPattern, columnId: 'col1', - // @ts-expect-error test only op: 'testReference', + visualizationGroups: [], }); expect(result.columnOrder).toEqual(['col1', 'id1']); @@ -1572,8 +1580,8 @@ describe('state_helpers', () => { layer, indexPattern, columnId: 'col1', - // @ts-expect-error op: 'testReference', + visualizationGroups: [], }); expect(result.incompleteColumns).toEqual({ @@ -1612,8 +1620,8 @@ describe('state_helpers', () => { layer, indexPattern, columnId: 'col1', - // @ts-expect-error op: 'testReference', + visualizationGroups: [], }); expect(result.incompleteColumns).toEqual({}); @@ -1631,8 +1639,8 @@ describe('state_helpers', () => { operationDefinitionMap.secondTest = { input: 'fullReference', displayName: 'Reference test 2', - // @ts-expect-error this type is not statically available type: 'secondTest', + selectionStyle: 'full', requiredReferences: [ { // Any numeric metric that isn't also a reference @@ -1641,7 +1649,6 @@ describe('state_helpers', () => { meta.dataType === 'number' && !meta.isBucketed, }, ], - // @ts-expect-error don't want to define valid arguments buildColumn: jest.fn((args) => { return { label: 'Test reference', @@ -1684,7 +1691,6 @@ describe('state_helpers', () => { dataType: 'number', isBucketed: false, - // @ts-expect-error not a valid type operationType: 'testReference', references: [], }, @@ -1693,7 +1699,6 @@ describe('state_helpers', () => { dataType: 'number', isBucketed: false, - // @ts-expect-error not a valid type operationType: 'testReference', references: ['ref1', 'invalid'], }, @@ -1704,8 +1709,8 @@ describe('state_helpers', () => { layer, indexPattern, columnId: 'output', - // @ts-expect-error not statically available op: 'secondTest', + visualizationGroups: [], }) ).toEqual( expect.objectContaining({ @@ -1738,7 +1743,6 @@ describe('state_helpers', () => { dataType: 'number', isBucketed: false, - // @ts-expect-error not a valid type operationType: 'testReference', references: [], }, @@ -1747,7 +1751,6 @@ describe('state_helpers', () => { dataType: 'number', isBucketed: false, - // @ts-expect-error not a valid type operationType: 'testReference', references: ['ref1', 'invalid'], }, @@ -1757,8 +1760,8 @@ describe('state_helpers', () => { layer, indexPattern, columnId: 'output', - // @ts-expect-error not statically available op: 'secondTest', + visualizationGroups: [], }); expect(layer.columns.output).toEqual( expect.objectContaining({ references: ['ref1', 'invalid'] }) @@ -1787,7 +1790,7 @@ describe('state_helpers', () => { isFormulaBroken: false, }, references: ['formulaX3'], - }, + } as FormulaIndexPatternColumn, formulaX0: { customLabel: true, dataType: 'number' as const, @@ -1802,7 +1805,7 @@ describe('state_helpers', () => { label: 'formulaX1', references: ['formulaX0'], params: { tinymathAst: 'formulaX0' }, - }, + } as MathIndexPatternColumn, formulaX2: { customLabel: true, dataType: 'number' as const, @@ -1811,13 +1814,13 @@ describe('state_helpers', () => { operationType: 'moving_average' as const, params: { window: 5 }, references: ['formulaX1'], - }, + } as MovingAverageIndexPatternColumn, formulaX3: { ...math, label: 'formulaX3', references: ['formulaX2'], params: { tinymathAst: 'formulaX2' }, - }, + } as MathIndexPatternColumn, }, }; @@ -1826,8 +1829,8 @@ describe('state_helpers', () => { layer, indexPattern, columnId: 'source', - // @ts-expect-error not statically available op: 'secondTest', + visualizationGroups: [], }) ).toEqual( expect.objectContaining({ @@ -1854,12 +1857,11 @@ describe('state_helpers', () => { operationType: 'date_histogram' as const, sourceField: 'timestamp', params: { interval: 'auto' }, - }, + } as DateHistogramIndexPatternColumn, output: { label: 'Test reference', dataType: 'number', isBucketed: false, - // @ts-expect-error not a valid type operationType: 'testReference', references: ['fieldReused'], }, @@ -1870,8 +1872,8 @@ describe('state_helpers', () => { layer, indexPattern, columnId: 'output', - // @ts-expect-error not statically available op: 'secondTest', + visualizationGroups: [], }) ).toEqual( expect.objectContaining({ @@ -1922,7 +1924,6 @@ describe('state_helpers', () => { dataType: 'number', isBucketed: false, - // @ts-expect-error not a valid type operationType: 'testReference', references: ['col1'], }, @@ -1967,7 +1968,6 @@ describe('state_helpers', () => { dataType: 'number', isBucketed: false, - // @ts-expect-error not a valid type operationType: 'testReference', references: ['col1'], filter: { language: 'kuery', query: 'bytes > 4000' }, @@ -2113,7 +2113,6 @@ describe('state_helpers', () => { dataType: 'number', isBucketed: false, - // @ts-expect-error not a valid type operationType: 'testReference', references: ['col1'], }, @@ -2281,7 +2280,6 @@ describe('state_helpers', () => { dataType: 'number', isBucketed: false, - // @ts-expect-error not a valid type operationType: 'testReference', references: ['col1'], }, @@ -2310,7 +2308,6 @@ describe('state_helpers', () => { dataType: 'number', isBucketed: false, - // @ts-expect-error not a valid type operationType: 'testReference', references: ['col1'], }, @@ -2356,7 +2353,6 @@ describe('state_helpers', () => { dataType: 'number', isBucketed: false, - // @ts-expect-error not a valid type operationType: 'testReference', references: ['col1'], }, @@ -2365,7 +2361,6 @@ describe('state_helpers', () => { dataType: 'number', isBucketed: false, - // @ts-expect-error not a valid type operationType: 'testReference', references: ['col2'], }, @@ -2469,7 +2464,7 @@ describe('state_helpers', () => { params: { interval: 'h', }, - }, + } as DateHistogramIndexPatternColumn, }, }) ).toEqual(['col1']); @@ -2496,7 +2491,7 @@ describe('state_helpers', () => { }, orderDirection: 'asc', }, - }, + } as TermsIndexPatternColumn, col2: { label: 'Average of bytes', dataType: 'number', @@ -2517,7 +2512,7 @@ describe('state_helpers', () => { params: { interval: '1d', }, - }, + } as DateHistogramIndexPatternColumn, }, }) ).toEqual(['col1', 'col3', 'col2']); @@ -2548,7 +2543,7 @@ describe('state_helpers', () => { params: { interval: 'auto', }, - }, + } as DateHistogramIndexPatternColumn, formula: { label: 'Formula', dataType: 'number', @@ -2560,7 +2555,7 @@ describe('state_helpers', () => { isFormulaBroken: false, }, references: ['math'], - }, + } as FormulaIndexPatternColumn, countX0: { label: 'countX0', dataType: 'number', @@ -2580,8 +2575,7 @@ describe('state_helpers', () => { tinymathAst: { type: 'function', name: 'add', - // @ts-expect-error String args are not valid tinymath, but signals something unique to Lens - args: ['countX0', 'count'], + args: ['countX0', 'count'] as unknown as TinymathAST[], location: { min: 0, max: 17, @@ -2591,7 +2585,7 @@ describe('state_helpers', () => { }, references: ['countX0', 'count'], customLabel: true, - }, + } as MathIndexPatternColumn, }, }) ).toEqual(['date', 'count', 'formula', 'countX0', 'math']); @@ -2679,7 +2673,7 @@ describe('state_helpers', () => { orderDirection: 'asc', size: 3, }, - }, + } as TermsIndexPatternColumn, col2: { dataType: 'number', isBucketed: false, @@ -2713,7 +2707,7 @@ describe('state_helpers', () => { params: { window: 7, }, - }, + } as MovingAverageIndexPatternColumn, col2: { dataType: 'number', isBucketed: false, @@ -2742,7 +2736,7 @@ describe('state_helpers', () => { params: { interval: 'd', }, - }, + } as DateHistogramIndexPatternColumn, col2: { dataType: 'number', isBucketed: false, @@ -2765,10 +2759,10 @@ describe('state_helpers', () => { operationDefinitionMap.date_histogram.transfer = ((oldColumn) => ({ ...oldColumn, params: { - ...oldColumn.params, + ...(oldColumn as DateHistogramIndexPatternColumn).params, interval: 'w', }, - })) as OperationDefinition['transfer']; + })) as OperationDefinition['transfer']; const layer: IndexPatternLayer = { columnOrder: ['col1', 'col2'], columns: { @@ -2781,7 +2775,7 @@ describe('state_helpers', () => { params: { interval: 'd', }, - }, + } as DateHistogramIndexPatternColumn, }, indexPatternId: 'original', }; @@ -2813,7 +2807,7 @@ describe('state_helpers', () => { orderDirection: 'asc', size: 3, }, - }, + } as TermsIndexPatternColumn, col2: { dataType: 'number', isBucketed: false, @@ -2846,7 +2840,7 @@ describe('state_helpers', () => { orderDirection: 'asc', size: 3, }, - }, + } as TermsIndexPatternColumn, col2: { dataType: 'number', isBucketed: false, @@ -2895,15 +2889,19 @@ describe('state_helpers', () => { indexPatternId: '1', columnOrder: [], columns: { - col1: - // @ts-expect-error not statically analyzed - { operationType: 'testReference', references: [] }, + col1: { + operationType: 'testReference', + references: [], + label: '', + dataType: 'number', + isBucketed: false, + }, }, }, indexPattern, - {}, + {} as IndexPatternPrivateState, '1', - {} + {} as CoreStart ); expect(mock).toHaveBeenCalled(); expect(errors).toHaveLength(1); @@ -2919,20 +2917,26 @@ describe('state_helpers', () => { indexPatternId: '1', columnOrder: [], columns: { - col1: - // @ts-expect-error not statically analyzed - { operationType: 'managedReference', references: ['col2'] }, + col1: { + operationType: 'managedReference', + references: ['col2'], + label: '', + dataType: 'number', + isBucketed: false, + }, col2: { - // @ts-expect-error not statically analyzed operationType: 'testReference', references: [], + label: '', + dataType: 'number', + isBucketed: false, }, }, }, indexPattern, - {}, + {} as IndexPatternPrivateState, '1', - {} + {} as CoreStart ); expect(notCalledMock).not.toHaveBeenCalled(); expect(mock).toHaveBeenCalledTimes(1); @@ -2953,19 +2957,22 @@ describe('state_helpers', () => { indexPatternId: '1', columnOrder: [], columns: { - col1: - // @ts-expect-error not statically analyzed - { operationType: 'testReference', references: [] }, + col1: { + operationType: 'testReference', + references: [], + label: '', + dataType: 'number', + isBucketed: false, + }, }, incompleteColumns: { - // @ts-expect-error not statically analyzed col1: { operationType: 'testIncompleteReference' }, }, }, indexPattern, - {}, + {} as IndexPatternPrivateState, '1', - {} + {} as CoreStart ); expect(savedRef).toHaveBeenCalled(); expect(incompleteRef).not.toHaveBeenCalled(); @@ -2982,15 +2989,19 @@ describe('state_helpers', () => { indexPatternId: '1', columnOrder: [], columns: { - col1: - // @ts-expect-error not statically analyzed - { operationType: 'testReference', references: [] }, + col1: { + operationType: 'testReference', + references: [], + label: '', + dataType: 'number', + isBucketed: false, + }, }, }, indexPattern, - {}, + {} as IndexPatternPrivateState, '1', - {} + {} as CoreStart ); expect(mock).toHaveBeenCalledWith( { @@ -3021,7 +3032,7 @@ describe('state_helpers', () => { params: { interval: 'd', }, - }, + } as DateHistogramIndexPatternColumn, }, indexPatternId: 'original', }; @@ -3047,7 +3058,7 @@ describe('state_helpers', () => { orderBy: { type: 'alphabetical' }, orderDirection: 'asc', }, - }, + } as TermsIndexPatternColumn, }, indexPatternId: 'original', }; @@ -3073,7 +3084,7 @@ describe('state_helpers', () => { orderBy: { type: 'alphabetical' }, orderDirection: 'asc', }, - }, + } as TermsIndexPatternColumn, }, indexPatternId: 'original', }; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.ts index 67546ca6009cf..289161c9d3e37 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.ts @@ -18,10 +18,10 @@ import { operationDefinitionMap, operationDefinitions, OperationType, - IndexPatternColumn, RequiredReference, OperationDefinition, GenericOperationDefinition, + TermsIndexPatternColumn, } from './definitions'; import type { IndexPattern, @@ -31,9 +31,14 @@ import type { } from '../types'; import { getSortScoreByPriority } from './operations'; import { generateId } from '../../id_generator'; -import { ReferenceBasedIndexPatternColumn } from './definitions/column_types'; +import { + GenericIndexPatternColumn, + ReferenceBasedIndexPatternColumn, + BaseIndexPatternColumn, +} from './definitions/column_types'; import { FormulaIndexPatternColumn, regenerateLayerFromAst } from './definitions/formula'; import type { TimeScaleUnit } from '../../../common/expressions'; +import { isColumnOfType } from './definitions/helpers'; interface ColumnAdvancedParams { filter?: Query | undefined; @@ -57,7 +62,7 @@ interface ColumnChange { interface ColumnCopy { layer: IndexPatternLayer; targetId: string; - sourceColumn: IndexPatternColumn; + sourceColumn: GenericIndexPatternColumn; sourceColumnId: string; indexPattern: IndexPattern; shouldDeleteSource?: boolean; @@ -92,7 +97,7 @@ export function copyColumn({ function copyReferencesRecursively( layer: IndexPatternLayer, - sourceColumn: IndexPatternColumn, + sourceColumn: GenericIndexPatternColumn, sourceId: string, targetId: string, indexPattern: IndexPattern @@ -511,7 +516,7 @@ export function replaceColumn({ if (operationDefinition.input === 'managedReference') { const newColumn = operationDefinition.buildColumn( { ...baseOptions, layer: tempLayer }, - previousColumn.params, + 'params' in previousColumn ? previousColumn.params : undefined, operationDefinitionMap ) as FormulaIndexPatternColumn; @@ -665,11 +670,11 @@ export function replaceColumn({ function removeOrphanedColumns( previousDefinition: - | OperationDefinition - | OperationDefinition - | OperationDefinition - | OperationDefinition, - previousColumn: IndexPatternColumn, + | OperationDefinition + | OperationDefinition + | OperationDefinition + | OperationDefinition, + previousColumn: GenericIndexPatternColumn, tempLayer: IndexPatternLayer, indexPattern: IndexPattern ) { @@ -765,7 +770,7 @@ function applyReferenceTransition({ }: { layer: IndexPatternLayer; columnId: string; - previousColumn: IndexPatternColumn; + previousColumn: GenericIndexPatternColumn; op: OperationType; indexPattern: IndexPattern; visualizationGroups: VisualizationDimensionGroupConfig[]; @@ -962,7 +967,10 @@ function applyReferenceTransition({ ); } -function copyCustomLabel(newColumn: IndexPatternColumn, previousOptions: IndexPatternColumn) { +function copyCustomLabel( + newColumn: GenericIndexPatternColumn, + previousOptions: GenericIndexPatternColumn +) { const adjustedColumn = { ...newColumn }; const operationChanged = newColumn.operationType !== previousOptions.operationType; const fieldChanged = @@ -978,7 +986,7 @@ function copyCustomLabel(newColumn: IndexPatternColumn, previousOptions: IndexPa function addBucket( layer: IndexPatternLayer, - column: IndexPatternColumn, + column: BaseIndexPatternColumn, addedColumnId: string, visualizationGroups: VisualizationDimensionGroupConfig[], targetGroup?: string @@ -1071,7 +1079,7 @@ export function reorderByGroups( function addMetric( layer: IndexPatternLayer, - column: IndexPatternColumn, + column: BaseIndexPatternColumn, addedColumnId: string ): IndexPatternLayer { const tempLayer = { @@ -1096,7 +1104,7 @@ export function getMetricOperationTypes(field: IndexPatternField) { }); } -export function updateColumnParam({ +export function updateColumnParam({ layer, columnId, paramName, @@ -1107,18 +1115,19 @@ export function updateColumnParam({ paramName: string; value: unknown; }): IndexPatternLayer { + const oldColumn = layer.columns[columnId]; return { ...layer, columns: { ...layer.columns, [columnId]: { - ...layer.columns[columnId], + ...oldColumn, params: { - ...layer.columns[columnId].params, + ...('params' in oldColumn ? oldColumn.params : {}), [paramName]: value, }, }, - } as Record, + } as Record, }; } @@ -1228,7 +1237,7 @@ export function getExistingColumnGroups(layer: IndexPatternLayer): [string[], st * Returns true if the given column can be applied to the given index pattern */ export function isColumnTransferable( - column: IndexPatternColumn, + column: GenericIndexPatternColumn, newIndexPattern: IndexPattern, layer: IndexPatternLayer ): boolean { @@ -1373,9 +1382,7 @@ export function hasTermsWithManyBuckets(layer: IndexPatternLayer): boolean { return layer.columnOrder.some((columnId) => { const column = layer.columns[columnId]; if (column) { - return ( - column.isBucketed && column.params && 'size' in column.params && column.params.size > 5 - ); + return isColumnOfType('terms', column) && column.params.size > 5; } }); } @@ -1447,7 +1454,7 @@ function maybeValidateOperations({ column, validation, }: { - column: IndexPatternColumn; + column: GenericIndexPatternColumn; validation: RequiredReference; }) { if (!validation.specificOperations) { @@ -1463,7 +1470,7 @@ export function isColumnValidAsReference({ column, validation, }: { - column: IndexPatternColumn; + column: GenericIndexPatternColumn; validation: RequiredReference; }): boolean { if (!column) return false; @@ -1481,14 +1488,14 @@ export function isColumnValidAsReference({ export function getManagedColumnsFrom( columnId: string, - columns: Record -): Array<[string, IndexPatternColumn]> { + columns: Record +): Array<[string, GenericIndexPatternColumn]> { const allNodes: Record = {}; Object.entries(columns).forEach(([id, col]) => { allNodes[id] = 'references' in col ? [...col.references] : []; }); const queue: string[] = allNodes[columnId]; - const store: Array<[string, IndexPatternColumn]> = []; + const store: Array<[string, GenericIndexPatternColumn]> = []; while (queue.length > 0) { const nextId = queue.shift()!; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/time_scale_utils.test.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/time_scale_utils.test.ts index dbdfd5c564125..30f8c85a81b90 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/time_scale_utils.test.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/time_scale_utils.test.ts @@ -7,7 +7,7 @@ import type { IndexPatternLayer } from '../types'; import type { TimeScaleUnit } from '../../../common/expressions'; -import type { IndexPatternColumn } from './definitions'; +import type { DateHistogramIndexPatternColumn, GenericIndexPatternColumn } from './definitions'; import { adjustTimeScaleLabelSuffix, adjustTimeScaleOnOtherColumnChange } from './time_scale_utils'; export const DEFAULT_TIME_SCALE = 's' as TimeScaleUnit; @@ -97,7 +97,7 @@ describe('time scale utils', () => { }); describe('adjustTimeScaleOnOtherColumnChange', () => { - const baseColumn: IndexPatternColumn = { + const baseColumn: GenericIndexPatternColumn = { operationType: 'count', sourceField: 'Records', label: 'Count of records per second', @@ -135,7 +135,7 @@ describe('time scale utils', () => { label: '', sourceField: 'date', params: { interval: 'auto' }, - }, + } as DateHistogramIndexPatternColumn, }, }, 'col1', diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/time_scale_utils.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/time_scale_utils.ts index a6c056933f022..a8e71c0fd86e5 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/time_scale_utils.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/time_scale_utils.ts @@ -8,7 +8,7 @@ import { unitSuffixesLong } from '../../../common/suffix_formatter'; import type { TimeScaleUnit } from '../../../common/expressions'; import type { IndexPatternLayer } from '../types'; -import type { IndexPatternColumn } from './definitions'; +import type { GenericIndexPatternColumn } from './definitions'; export const DEFAULT_TIME_SCALE = 's' as TimeScaleUnit; @@ -44,7 +44,7 @@ export function adjustTimeScaleLabelSuffix( return `${cleanedLabel}${getSuffix(newTimeScale, newShift)}`; } -export function adjustTimeScaleOnOtherColumnChange( +export function adjustTimeScaleOnOtherColumnChange( layer: IndexPatternLayer, thisColumnId: string, changedColumnId: string diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/time_shift_utils.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/time_shift_utils.tsx index 1258100375a39..d7f238171128d 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/time_shift_utils.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/time_shift_utils.tsx @@ -11,7 +11,7 @@ import { uniq } from 'lodash'; import { FormattedMessage } from '@kbn/i18n/react'; import { IndexPattern, - IndexPatternColumn, + GenericIndexPatternColumn, IndexPatternLayer, IndexPatternPrivateState, } from './types'; @@ -229,7 +229,7 @@ export function getStateTimeShiftWarningMessages( export function getColumnTimeShiftWarnings( dateHistogramInterval: ReturnType, - column: IndexPatternColumn + column: GenericIndexPatternColumn ) { const { isValueTooSmall, isValueNotMultiple } = getLayerTimeShiftChecks(dateHistogramInterval); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/to_expression.ts b/x-pack/plugins/lens/public/indexpattern_datasource/to_expression.ts index 15b9b47d7a565..3470adaa8eb91 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/to_expression.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/to_expression.ts @@ -20,12 +20,13 @@ import { ExpressionAstExpressionBuilder, ExpressionAstFunction, } from '../../../../../src/plugins/expressions/public'; -import { IndexPatternColumn } from './indexpattern'; +import { GenericIndexPatternColumn } from './indexpattern'; import { operationDefinitionMap } from './operations'; import { IndexPattern, IndexPatternPrivateState, IndexPatternLayer } from './types'; -import { dateHistogramOperation } from './operations/definitions'; +import { DateHistogramIndexPatternColumn, RangeIndexPatternColumn } from './operations/definitions'; +import { isColumnOfType } from './operations/definitions/helpers'; -type OriginalColumn = { id: string } & IndexPatternColumn; +type OriginalColumn = { id: string } & GenericIndexPatternColumn; function getExpressionForLayer( layer: IndexPatternLayer, @@ -148,34 +149,16 @@ function getExpressionForLayer( }; }, {} as Record); - type FormattedColumn = Required< - Extract< - IndexPatternColumn, - | { - params?: { - format: unknown; - }; - } - // when formatters are nested there's a slightly different format - | { - params: { - format?: unknown; - parentFormat?: unknown; - }; - } - > - >; const columnsWithFormatters = columnEntries.filter( ([, col]) => - col.params && - (('format' in col.params && col.params.format) || - ('parentFormat' in col.params && col.params.parentFormat)) - ) as Array<[string, FormattedColumn]>; + isColumnOfType('range', col) && + (col.params?.format || col.params?.parentFormat) + ) as Array<[string, RangeIndexPatternColumn]>; const formatterOverrides: ExpressionAstFunction[] = columnsWithFormatters.map( - ([id, col]: [string, FormattedColumn]) => { + ([id, col]: [string, RangeIndexPatternColumn]) => { // TODO: improve the type handling here const parentFormat = 'parentFormat' in col.params ? col.params!.parentFormat! : undefined; - const format = (col as FormattedColumn).params!.format; + const format = col.params!.format; const base: ExpressionAstFunction = { type: 'function', @@ -254,7 +237,9 @@ function getExpressionForLayer( const allDateHistogramFields = Object.values(columns) .map((column) => - column.operationType === dateHistogramOperation.type ? column.sourceField : null + isColumnOfType('date_histogram', column) + ? column.sourceField + : null ) .filter((field): field is string => Boolean(field)); @@ -291,7 +276,7 @@ function getExpressionForLayer( } // Topologically sorts references so that we can execute them in sequence -function sortedReferences(columns: Array) { +function sortedReferences(columns: Array) { const allNodes: Record = {}; columns.forEach(([id, col]) => { allNodes[id] = 'references' in col ? col.references : []; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/types.ts b/x-pack/plugins/lens/public/indexpattern_datasource/types.ts index 515693b4dd5c8..5561d5097e2a7 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/types.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/types.ts @@ -5,15 +5,14 @@ * 2.0. */ -import type { IndexPatternColumn, IncompleteColumn } from './operations'; +import type { IncompleteColumn, GenericIndexPatternColumn } from './operations'; import type { IndexPatternAggRestrictions } from '../../../../../src/plugins/data/public'; import type { FieldSpec } from '../../../../../src/plugins/data/common'; import type { DragDropIdentifier } from '../drag_drop/providers'; import type { FieldFormatParams } from '../../../../../src/plugins/field_formats/common'; export type { - FieldBasedIndexPatternColumn, - IndexPatternColumn, + GenericIndexPatternColumn, OperationType, IncompleteColumn, FiltersIndexPatternColumn, @@ -67,7 +66,7 @@ export type IndexPatternField = FieldSpec & { export interface IndexPatternLayer { columnOrder: string[]; - columns: Record; + columns: Record; // Each layer is tied to the index pattern that created it indexPatternId: string; // Partial columns represent the temporary invalid states diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/utils.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/utils.tsx index 6d3f75a403dd7..f1f8f2cfe3e62 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/utils.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/utils.tsx @@ -24,7 +24,7 @@ import type { ReferenceBasedIndexPatternColumn, } from './operations/definitions/column_types'; -import { operationDefinitionMap, IndexPatternColumn } from './operations'; +import { operationDefinitionMap, GenericIndexPatternColumn } from './operations'; import { getInvalidFieldMessage } from './operations/definitions/helpers'; import { isQueryValid } from './operations/definitions/filters'; @@ -65,7 +65,7 @@ export function isColumnInvalid( columnId: string, indexPattern: IndexPattern ) { - const column: IndexPatternColumn | undefined = layer.columns[columnId]; + const column: GenericIndexPatternColumn | undefined = layer.columns[columnId]; if (!column || !indexPattern) return; const operationDefinition = column.operationType && operationDefinitionMap[column.operationType]; @@ -75,12 +75,9 @@ export function isColumnInvalid( 'references' in column && Boolean(getReferencesErrors(layer, column, indexPattern).filter(Boolean).length); - const operationErrorMessages = operationDefinition.getErrorMessage?.( - layer, - columnId, - indexPattern, - operationDefinitionMap - ); + const operationErrorMessages = + operationDefinition && + operationDefinition.getErrorMessage?.(layer, columnId, indexPattern, operationDefinitionMap); const filterHasError = column.filter ? !isQueryValid(column.filter, indexPattern) : false; @@ -108,7 +105,10 @@ function getReferencesErrors( }); } -export function fieldIsInvalid(column: IndexPatternColumn | undefined, indexPattern: IndexPattern) { +export function fieldIsInvalid( + column: GenericIndexPatternColumn | undefined, + indexPattern: IndexPattern +) { if (!column || !hasField(column)) { return false; }