From 6eeeddb332c0beed25d0dee794f6d42badb3261b Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Tue, 23 Feb 2021 15:49:05 +0300 Subject: [PATCH 01/39] [TSVB] Enable `dual mode`, support index patterns and strings --- .../common/extract_index_patterns.ts | 6 +- .../vis_type_timeseries/common/types.ts | 3 +- .../vis_type_timeseries/common/vis_schema.ts | 16 +++- .../application/components/index_pattern.js | 20 +++-- .../index_pattern_select/combo_box_select.tsx | 80 +++++++++++++++++++ .../field_text_select.tsx | 49 ++++++++++++ .../components/index_pattern_select/index.ts | 9 +++ .../index_pattern_select.tsx | 72 +++++++++++++++++ .../legacy_mode_popover.tsx | 47 +++++++++++ .../switch_mode_popover.tsx | 57 +++++++++++++ .../components/index_pattern_select/types.ts | 18 +++++ .../application/components/panel_config.js | 17 ++-- .../components/panel_config/gauge.js | 1 + .../components/panel_config/markdown.js | 1 + .../components/panel_config/metric.js | 1 + .../components/panel_config/table.js | 1 + .../components/panel_config/timeseries.js | 4 +- .../components/panel_config/top_n.js | 1 + .../components/vis_types/timeseries/config.js | 2 +- .../contexts/panel_model_context.ts | 12 +++ .../public/metrics_type.ts | 1 + .../lib/get_index_pattern.ts | 20 +++-- 22 files changed, 407 insertions(+), 31 deletions(-) create mode 100644 src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/combo_box_select.tsx create mode 100644 src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/field_text_select.tsx create mode 100644 src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/index.ts create mode 100644 src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/index_pattern_select.tsx create mode 100644 src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/legacy_mode_popover.tsx create mode 100644 src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/switch_mode_popover.tsx create mode 100644 src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/types.ts create mode 100644 src/plugins/vis_type_timeseries/public/application/contexts/panel_model_context.ts diff --git a/src/plugins/vis_type_timeseries/common/extract_index_patterns.ts b/src/plugins/vis_type_timeseries/common/extract_index_patterns.ts index c716ae7abb821..9c417e69f7608 100644 --- a/src/plugins/vis_type_timeseries/common/extract_index_patterns.ts +++ b/src/plugins/vis_type_timeseries/common/extract_index_patterns.ts @@ -7,13 +7,13 @@ */ import { uniq } from 'lodash'; -import { PanelSchema } from '../common/types'; +import { PanelSchema, IndexPatternObject } from '../common/types'; export function extractIndexPatterns( panel: PanelSchema, defaultIndex?: PanelSchema['default_index_pattern'] ) { - const patterns: string[] = []; + const patterns: IndexPatternObject[] = []; if (panel.index_pattern) { patterns.push(panel.index_pattern); @@ -39,5 +39,5 @@ export function extractIndexPatterns( patterns.push(defaultIndex); } - return uniq(patterns).sort(); + return uniq(patterns).sort(); } diff --git a/src/plugins/vis_type_timeseries/common/types.ts b/src/plugins/vis_type_timeseries/common/types.ts index d72a50f667a70..4139de8403c59 100644 --- a/src/plugins/vis_type_timeseries/common/types.ts +++ b/src/plugins/vis_type_timeseries/common/types.ts @@ -7,7 +7,7 @@ */ import { TypeOf } from '@kbn/config-schema'; -import { metricsItems, panel, seriesItems, visPayloadSchema, fieldObject } from './vis_schema'; +import { metricsItems, panel, seriesItems, visPayloadSchema, fieldObject, indexPattern } from './vis_schema'; import { PANEL_TYPES } from './panel_types'; import { TimeseriesUIRestrictions } from './ui_restrictions'; @@ -16,6 +16,7 @@ export type MetricsItemsSchema = TypeOf; export type PanelSchema = TypeOf; export type VisPayload = TypeOf; export type FieldObject = TypeOf; +export type IndexPatternObject = TypeOf; interface PanelData { id: string; diff --git a/src/plugins/vis_type_timeseries/common/vis_schema.ts b/src/plugins/vis_type_timeseries/common/vis_schema.ts index 2ab8cea39ab5d..1f4c2c4910181 100644 --- a/src/plugins/vis_type_timeseries/common/vis_schema.ts +++ b/src/plugins/vis_type_timeseries/common/vis_schema.ts @@ -36,6 +36,14 @@ const numberOptionalOrEmptyString = schema.maybe( schema.oneOf([numberOptional, schema.literal('')]) ); +export const indexPattern = schema.oneOf([ + schema.maybe(schema.string()), + schema.object({ + id: schema.string(), + title: schema.maybe(schema.string()), + }), +]); + export const fieldObject = stringOptionalNullable; const annotationsItems = schema.object({ @@ -46,7 +54,7 @@ const annotationsItems = schema.object({ id: stringOptionalNullable, ignore_global_filters: numberIntegerOptional, ignore_panel_filters: numberIntegerOptional, - index_pattern: stringOptionalNullable, + index_pattern: indexPattern, query_string: schema.maybe(queryObject), template: stringOptionalNullable, time_field: fieldObject, @@ -67,6 +75,7 @@ const gaugeColorRulesItems = schema.object({ operator: stringOptionalNullable, value: schema.maybe(schema.nullable(schema.number())), }); + export const metricsItems = schema.object({ field: fieldObject, id: stringRequired, @@ -166,7 +175,7 @@ export const seriesItems = schema.object({ point_size: numberOptionalOrEmptyString, separate_axis: numberIntegerOptional, seperate_axis: numberIntegerOptional, - series_index_pattern: stringOptionalNullable, + series_index_pattern: indexPattern, series_max_bars: numberIntegerOptional, series_time_field: fieldObject, series_interval: stringOptionalNullable, @@ -190,6 +199,7 @@ export const seriesItems = schema.object({ }); export const panel = schema.object({ + use_kibana_indexes: schema.maybe(schema.boolean()), annotations: schema.maybe(schema.arrayOf(annotationsItems)), axis_formatter: stringRequired, axis_position: stringRequired, @@ -221,7 +231,7 @@ export const panel = schema.object({ id: stringRequired, ignore_global_filters: numberOptional, ignore_global_filter: numberOptional, - index_pattern: stringRequired, + index_pattern: indexPattern, max_bars: numberIntegerOptional, interval: stringRequired, isModelInvalid: schema.maybe(schema.boolean()), diff --git a/src/plugins/vis_type_timeseries/public/application/components/index_pattern.js b/src/plugins/vis_type_timeseries/public/application/components/index_pattern.js index d36cea80bffff..a7cb2e0bbbe64 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/index_pattern.js +++ b/src/plugins/vis_type_timeseries/public/application/components/index_pattern.js @@ -37,6 +37,7 @@ import { VisDataContext } from '../contexts/vis_data_context'; import { getUISettings } from '../../services'; import { AUTO_INTERVAL } from '../../../common/constants'; import { UI_SETTINGS } from '../../../../data/common'; +import { IndexPatternSelect } from './index_pattern_select'; const RESTRICT_FIELDS = [KBN_FIELD_TYPES.DATE]; const LEVEL_OF_DETAIL_STEPS = 10; @@ -64,7 +65,8 @@ export const IndexPattern = ({ onChange, disabled, model: _model, - allowLevelofDetail, + allowLevelOfDetail, + allowSwitchUseKibanaIndexesMode, }) => { const config = getUISettings(); const timeFieldName = `${prefix}time_field`; @@ -175,12 +177,13 @@ export const IndexPattern = ({ }) } > - @@ -243,7 +246,7 @@ export const IndexPattern = ({ - {allowLevelofDetail && ( + {allowLevelOfDetail && ( >; + +const toSelectedOptions = ( + v: IndexPatternObject +): EuiComboBoxProps['selectedOptions'] => { + if (!v) { + return []; + } + if (typeof v === 'string') { + return [{ label: v ?? '' }]; + } + return [ + { + id: v.id ?? '', + label: v.title ?? '', + }, + ]; +}; + +export const ComboBoxSelect = ({ + onIndexChange, + onModeChange, + disabled, + value, + placeholder, + allowSwitchUseKibanaIndexesMode, +}: SelectIndexComponentProps) => { + const [availableIndexes, setAvailableIndexes] = useState([]); + + const onComboBoxChange: EuiComboBoxProps['onChange'] = useCallback( + ([selected]) => { + onIndexChange(selected ? { id: selected.id, title: selected.label } : ''); + }, + [onIndexChange] + ); + + const toComboBoxOptions = (options: IdsWithTitle) => + options.map(({ title, id }) => ({ label: title, id })); + + useEffect(() => { + async function fetchIndexes() { + setAvailableIndexes(await getDataStart().indexPatterns.getIdsWithTitle()); + } + + fetchIndexes(); + }, []); + + return ( + , + })} + /> + ); +}; diff --git a/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/field_text_select.tsx b/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/field_text_select.tsx new file mode 100644 index 0000000000000..2102110ed4d62 --- /dev/null +++ b/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/field_text_select.tsx @@ -0,0 +1,49 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { useCallback } from 'react'; +import { EuiFieldText, EuiFieldTextProps } from '@elastic/eui'; +import { LegacyModePopover } from './legacy_mode_popover'; +import { SwitchModePopover } from './switch_mode_popover'; + +import type { SelectIndexComponentProps } from './types'; +import type { IndexPatternObject } from '../../../../common/types'; + +const toTextValue = (v: IndexPatternObject) => (typeof v === 'string' ? v : v?.title ?? ''); + +export const FieldTextSelect = ({ + onIndexChange, + disabled, + value, + placeholder, + onModeChange, + allowSwitchUseKibanaIndexesMode, +}: SelectIndexComponentProps) => { + const onFieldTextChange: EuiFieldTextProps['onChange'] = useCallback( + (e) => { + onIndexChange(e.target.value); + }, + [onIndexChange] + ); + + const append = []; + + if (allowSwitchUseKibanaIndexesMode) { + append.push(); + } + + return ( + + ); +}; diff --git a/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/index.ts b/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/index.ts new file mode 100644 index 0000000000000..584f13e7a025b --- /dev/null +++ b/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export { IndexPatternSelect } from './index_pattern_select'; diff --git a/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/index_pattern_select.tsx b/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/index_pattern_select.tsx new file mode 100644 index 0000000000000..d545f3f69cb02 --- /dev/null +++ b/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/index_pattern_select.tsx @@ -0,0 +1,72 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { useState, useContext, useCallback } from 'react'; +import useDebounce from 'react-use/lib/useDebounce'; +import { FieldTextSelect } from './field_text_select'; +import { ComboBoxSelect } from './combo_box_select'; +import { PanelModelContext } from '../../contexts/panel_model_context'; +import type { IndexPatternObject } from '../../../../common/types'; + +const USE_KIBANA_INDEXES_KEY = 'use_kibana_indexes'; + +interface IndexPatternSelectProps { + value: IndexPatternObject; + indexPatternName: string; + defaultIndexPattern: string; + onChange: Function; + disabled?: boolean; + allowSwitchUseKibanaIndexesMode?: boolean; +} + +export const IndexPatternSelect = ({ + value, + indexPatternName, + onChange, + disabled, + defaultIndexPattern, + allowSwitchUseKibanaIndexesMode, +}: IndexPatternSelectProps) => { + const panelModel = useContext(PanelModelContext); + const useFieldTextControl = !Boolean(panelModel?.[USE_KIBANA_INDEXES_KEY]); + const [inputValue, setInputValue] = useState(value); + const Component = useFieldTextControl ? FieldTextSelect : ComboBoxSelect; + + useDebounce( + () => { + if (inputValue !== value) { + onChange({ + [indexPatternName]: inputValue, + }); + } + }, + 300, + [onChange, inputValue, indexPatternName, value] + ); + + const onModeChange = useCallback( + (useKibanaIndexes: boolean) => { + onChange({ + [USE_KIBANA_INDEXES_KEY]: useKibanaIndexes, + }); + }, + [onChange] + ); + + return ( + + ); +}; diff --git a/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/legacy_mode_popover.tsx b/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/legacy_mode_popover.tsx new file mode 100644 index 0000000000000..ddf9625d85490 --- /dev/null +++ b/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/legacy_mode_popover.tsx @@ -0,0 +1,47 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { useState, useCallback } from 'react'; +import { EuiButtonIcon, EuiPopover, EuiButton, EuiCallOut } from '@elastic/eui'; +import { getCoreStart } from '../../../services'; + +export const LegacyModePopover = () => { + const [isPopoverOpen, setIsPopoverOpen] = useState(false); + + const closePopover = useCallback(() => setIsPopoverOpen(false), []); + const onButtonClick = useCallback(() => setIsPopoverOpen((isOpen) => !isOpen), []); + + const navigateToCreateIndexPatterns = () => { + const core = getCoreStart(); + core.application.navigateToApp('management', { + path: `/kibana/indexPatterns/create`, + }); + }; + + return ( + + } + isOpen={isPopoverOpen} + closePopover={closePopover} + > + +

To support all features, we recommend using Kibana Index Pattern.

+ + Create index pattern + +
+
+ ); +}; diff --git a/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/switch_mode_popover.tsx b/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/switch_mode_popover.tsx new file mode 100644 index 0000000000000..29950794d2c44 --- /dev/null +++ b/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/switch_mode_popover.tsx @@ -0,0 +1,57 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { useState, useCallback } from 'react'; +import { EuiButtonEmpty, EuiPopover, EuiFormRow, EuiSwitch } from '@elastic/eui'; +import { SelectIndexComponentProps } from './types'; + +type SwitchModePopoverProps = Pick & { + isKibanaIndexesModeOn: boolean; +}; + +export const SwitchModePopover = ({ + isKibanaIndexesModeOn, + onModeChange, +}: SwitchModePopoverProps) => { + const [isPopoverOpen, setIsPopoverOpen] = useState(false); + + const closePopover = useCallback(() => setIsPopoverOpen(false), []); + const onButtonClick = useCallback(() => setIsPopoverOpen((isOpen) => !isOpen), []); + + const onChange = useCallback( + (e) => { + onModeChange(e.target.checked); + }, + [onModeChange] + ); + + return ( + + } + isOpen={isPopoverOpen} + closePopover={closePopover} + style={{ height: 'auto' }} + > + + + + + ); +}; diff --git a/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/types.ts b/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/types.ts new file mode 100644 index 0000000000000..ea231ef0d6788 --- /dev/null +++ b/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/types.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +import type { IndexPatternObject } from '../../../../common/types'; + +export interface SelectIndexComponentProps { + value: IndexPatternObject; + onIndexChange: (value: IndexPatternObject) => void; + onModeChange: (useKibanaIndexes: boolean) => void; + 'data-test-subj': string; + placeholder?: string; + disabled?: boolean; + allowSwitchUseKibanaIndexesMode?: boolean; +} diff --git a/src/plugins/vis_type_timeseries/public/application/components/panel_config.js b/src/plugins/vis_type_timeseries/public/application/components/panel_config.js index 2e6e97f868fd9..aac09da69c39f 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/panel_config.js +++ b/src/plugins/vis_type_timeseries/public/application/components/panel_config.js @@ -18,6 +18,7 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { FormValidationContext } from '../contexts/form_validation_context'; import { VisDataContext } from '../contexts/vis_data_context'; +import { PanelModelContext } from '../contexts/panel_model_context'; const types = { timeseries, @@ -55,13 +56,15 @@ export function PanelConfig(props) { if (Component) { return ( - - -
- -
-
-
+ + + +
+ +
+
+
+
); } diff --git a/src/plugins/vis_type_timeseries/public/application/components/panel_config/gauge.js b/src/plugins/vis_type_timeseries/public/application/components/panel_config/gauge.js index ef986a2f2111b..fce782eb0ad01 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/panel_config/gauge.js +++ b/src/plugins/vis_type_timeseries/public/application/components/panel_config/gauge.js @@ -126,6 +126,7 @@ class GaugePanelConfigUi extends Component { fields={this.props.fields} model={this.props.model} onChange={this.props.onChange} + allowSwitchUseKibanaIndexesMode={true} /> diff --git a/src/plugins/vis_type_timeseries/public/application/components/panel_config/markdown.js b/src/plugins/vis_type_timeseries/public/application/components/panel_config/markdown.js index dfbcb288cbde4..cfd5824b22006 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/panel_config/markdown.js +++ b/src/plugins/vis_type_timeseries/public/application/components/panel_config/markdown.js @@ -132,6 +132,7 @@ class MarkdownPanelConfigUi extends Component { fields={this.props.fields} model={this.props.model} onChange={this.props.onChange} + allowSwitchUseKibanaIndexesMode={true} /> diff --git a/src/plugins/vis_type_timeseries/public/application/components/panel_config/metric.js b/src/plugins/vis_type_timeseries/public/application/components/panel_config/metric.js index 8fea3d89fc054..f0c00e65759d1 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/panel_config/metric.js +++ b/src/plugins/vis_type_timeseries/public/application/components/panel_config/metric.js @@ -90,6 +90,7 @@ export class MetricPanelConfig extends Component { fields={this.props.fields} model={this.props.model} onChange={this.props.onChange} + allowSwitchUseKibanaIndexesMode={true} /> diff --git a/src/plugins/vis_type_timeseries/public/application/components/panel_config/table.js b/src/plugins/vis_type_timeseries/public/application/components/panel_config/table.js index 7a8b919c25db8..07219e70692b8 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/panel_config/table.js +++ b/src/plugins/vis_type_timeseries/public/application/components/panel_config/table.js @@ -214,6 +214,7 @@ export class TablePanelConfig extends Component { fields={this.props.fields} model={this.props.model} onChange={this.props.onChange} + allowSwitchUseKibanaIndexesMode={true} /> diff --git a/src/plugins/vis_type_timeseries/public/application/components/panel_config/timeseries.js b/src/plugins/vis_type_timeseries/public/application/components/panel_config/timeseries.js index 205f8efdf1911..3e94110a9ec44 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/panel_config/timeseries.js +++ b/src/plugins/vis_type_timeseries/public/application/components/panel_config/timeseries.js @@ -182,9 +182,9 @@ class TimeseriesPanelConfigUi extends Component { fields={this.props.fields} model={this.props.model} onChange={this.props.onChange} - allowLevelofDetail={true} + allowLevelOfDetail={true} + allowSwitchUseKibanaIndexesMode={true} /> - diff --git a/src/plugins/vis_type_timeseries/public/application/components/panel_config/top_n.js b/src/plugins/vis_type_timeseries/public/application/components/panel_config/top_n.js index 2e98422ab06a6..5b4fd47e9bf8b 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/panel_config/top_n.js +++ b/src/plugins/vis_type_timeseries/public/application/components/panel_config/top_n.js @@ -116,6 +116,7 @@ export class TopNPanelConfig extends Component { fields={this.props.fields} model={this.props.model} onChange={this.props.onChange} + allowSwitchUseKibanaIndexesMode={true} /> diff --git a/src/plugins/vis_type_timeseries/public/application/components/vis_types/timeseries/config.js b/src/plugins/vis_type_timeseries/public/application/components/vis_types/timeseries/config.js index b0dd5ea4572af..d3944adb41719 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/vis_types/timeseries/config.js +++ b/src/plugins/vis_type_timeseries/public/application/components/vis_types/timeseries/config.js @@ -543,7 +543,7 @@ export const TimeseriesConfig = injectI18n(function (props) { {...props} prefix="series_" disabled={!model.override_index_pattern} - allowLevelofDetail={true} + allowLevelOfDetail={true} />
diff --git a/src/plugins/vis_type_timeseries/public/application/contexts/panel_model_context.ts b/src/plugins/vis_type_timeseries/public/application/contexts/panel_model_context.ts new file mode 100644 index 0000000000000..534f686ca13fc --- /dev/null +++ b/src/plugins/vis_type_timeseries/public/application/contexts/panel_model_context.ts @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React from 'react'; +import { PanelSchema } from '../../../common/types'; + +export const PanelModelContext = React.createContext(null); diff --git a/src/plugins/vis_type_timeseries/public/metrics_type.ts b/src/plugins/vis_type_timeseries/public/metrics_type.ts index a19d664a94927..fbdff218e2d65 100644 --- a/src/plugins/vis_type_timeseries/public/metrics_type.ts +++ b/src/plugins/vis_type_timeseries/public/metrics_type.ts @@ -50,6 +50,7 @@ export const metricsVisDefinition = { ], time_field: '', index_pattern: '', + use_kibana_indexes: true, interval: '', axis_position: 'left', axis_formatter: 'number', diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/get_index_pattern.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/get_index_pattern.ts index 512494de290fd..776c799295ded 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/get_index_pattern.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/get_index_pattern.ts @@ -7,26 +7,34 @@ */ import { IndexPatternsService, IndexPattern } from '../../../../../data/server'; +import { IndexPatternObject } from '../../../../common/types'; interface IndexPatternObjectDependencies { indexPatternsService: IndexPatternsService; } export async function getIndexPatternObject( - indexPatternString: string, + indexPattern: IndexPatternObject, { indexPatternsService }: IndexPatternObjectDependencies ) { let indexPatternObject: IndexPattern | undefined | null; - if (!indexPatternString) { + const getIndexPatternFromString = async (v: string) => + (await indexPatternsService.find(v)).find((index) => index.title === indexPattern); + + if (!indexPattern) { indexPatternObject = await indexPatternsService.getDefault(); } else { - indexPatternObject = (await indexPatternsService.find(indexPatternString)).find( - (index) => index.title === indexPatternString - ); + if (typeof indexPattern === 'string') { + indexPatternObject = await getIndexPatternFromString(indexPattern); + } else if (indexPattern.id) { + indexPatternObject = await indexPatternsService.get(indexPattern.id); + } else if (indexPattern.title) { + indexPatternObject = await getIndexPatternFromString(indexPattern.title); + } } return { indexPatternObject, - indexPatternString: indexPatternObject?.title || indexPatternString || '', + indexPatternString: indexPatternObject?.title ?? '', }; } From 9218ccc141ed702e8876406c7f4dc97945f25489 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Fri, 26 Feb 2021 14:28:19 +0300 Subject: [PATCH 02/39] modify UI --- .../index_pattern_select/combo_box_select.tsx | 26 ++-- .../field_text_select.tsx | 9 +- .../index_pattern_select.tsx | 1 + .../legacy_mode_popover.tsx | 123 +++++++++++++++--- .../switch_mode_popover.tsx | 34 ++++- .../application/components/series_config.js | 2 +- ...fig_query_bar_with_ignore_global_filter.js | 2 +- .../components/vis_types/gauge/series.js | 2 +- .../components/vis_types/markdown/series.js | 2 +- .../components/vis_types/metric/series.js | 2 +- .../components/vis_types/table/config.js | 2 +- .../components/vis_types/table/series.js | 2 +- .../components/vis_types/timeseries/config.js | 2 +- .../components/vis_types/timeseries/series.js | 2 +- .../components/vis_types/top_n/series.js | 2 +- 15 files changed, 164 insertions(+), 49 deletions(-) diff --git a/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/combo_box_select.tsx b/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/combo_box_select.tsx index 96e0f86e62bf1..1a047ac946e76 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/combo_box_select.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/combo_box_select.tsx @@ -20,20 +20,20 @@ import { SwitchModePopover } from './switch_mode_popover'; type IdsWithTitle = UnwrapPromise>; const toSelectedOptions = ( - v: IndexPatternObject + value: IndexPatternObject ): EuiComboBoxProps['selectedOptions'] => { - if (!v) { - return []; - } - if (typeof v === 'string') { - return [{ label: v ?? '' }]; + if (value) { + if (typeof value === 'string') { + return [{ label: value ?? '' }]; + } + return [ + { + id: value.id ?? '', + label: value.title ?? '', + }, + ]; } - return [ - { - id: v.id ?? '', - label: v.title ?? '', - }, - ]; + return []; }; export const ComboBoxSelect = ({ @@ -73,7 +73,7 @@ export const ComboBoxSelect = ({ isDisabled={disabled} placeholder={placeholder} {...(allowSwitchUseKibanaIndexesMode && { - append: , + append: , })} /> ); diff --git a/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/field_text_select.tsx b/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/field_text_select.tsx index 2102110ed4d62..61d109e4bb822 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/field_text_select.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/field_text_select.tsx @@ -24,6 +24,9 @@ export const FieldTextSelect = ({ onModeChange, allowSwitchUseKibanaIndexesMode, }: SelectIndexComponentProps) => { + const textualValue = toTextValue(value); + const append = []; + const onFieldTextChange: EuiFieldTextProps['onChange'] = useCallback( (e) => { onIndexChange(e.target.value); @@ -31,17 +34,15 @@ export const FieldTextSelect = ({ [onIndexChange] ); - const append = []; - if (allowSwitchUseKibanaIndexesMode) { - append.push(); + append.push(); } return ( diff --git a/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/index_pattern_select.tsx b/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/index_pattern_select.tsx index d545f3f69cb02..003f8299c18c4 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/index_pattern_select.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/index_pattern_select.tsx @@ -54,6 +54,7 @@ export const IndexPatternSelect = ({ onChange({ [USE_KIBANA_INDEXES_KEY]: useKibanaIndexes, }); + setInputValue(''); }, [onChange] ); diff --git a/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/legacy_mode_popover.tsx b/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/legacy_mode_popover.tsx index ddf9625d85490..fd09cde7ec11e 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/legacy_mode_popover.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/legacy_mode_popover.tsx @@ -6,42 +6,133 @@ * Side Public License, v 1. */ -import React, { useState, useCallback } from 'react'; -import { EuiButtonIcon, EuiPopover, EuiButton, EuiCallOut } from '@elastic/eui'; -import { getCoreStart } from '../../../services'; +import React, { useState, useCallback, useEffect } from 'react'; +import { EuiTextColor, EuiButtonIcon, EuiPopover, EuiButton, EuiCallOut } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { i18n } from '@kbn/i18n'; +import { getCoreStart, getDataStart } from '../../../services'; -export const LegacyModePopover = () => { +interface LegacyModePopoverProps { + index: string; +} + +const getDeprecationCallOut = () => ( + +

+ +

+
+); + +const getReadyToMigrateCallOut = (index: string) => ( + +

+ {index}, + }} + /> +

+
+); + +const getNoMatchedIndicesCallOut = (index: string, onCreateIndexClick: () => void) => ( + +

+ {index}, + }} + /> +

+ + + +
+); + +export const LegacyModePopover = ({ index }: LegacyModePopoverProps) => { const [isPopoverOpen, setIsPopoverOpen] = useState(false); + const [showReadyToMigrateCallOut, setShowReadyToMigrateCallOut] = useState(false); + const [showNoMatchedIndicesCallOut, setNoMatchedIndicesCallOut] = useState(false); const closePopover = useCallback(() => setIsPopoverOpen(false), []); const onButtonClick = useCallback(() => setIsPopoverOpen((isOpen) => !isOpen), []); - - const navigateToCreateIndexPatterns = () => { + const navigateToCreateIndexPatterns = useCallback(() => { const core = getCoreStart(); core.application.navigateToApp('management', { path: `/kibana/indexPatterns/create`, }); - }; + }, []); + + useEffect(() => { + async function retrieveIndex() { + let hasIndex = false; + if (index) { + const { indexPatterns } = getDataStart(); + hasIndex = Boolean((await indexPatterns.find(index)).find((i) => i.title === index)); + } + + setShowReadyToMigrateCallOut(Boolean(index) && hasIndex); + setNoMatchedIndicesCallOut(Boolean(index) && !hasIndex); + } + + retrieveIndex(); + }, [index]); return ( } isOpen={isPopoverOpen} closePopover={closePopover} > - -

To support all features, we recommend using Kibana Index Pattern.

- - Create index pattern - -
+ {getDeprecationCallOut()} + {showReadyToMigrateCallOut && getReadyToMigrateCallOut(index)} + {showNoMatchedIndicesCallOut && + getNoMatchedIndicesCallOut(index, navigateToCreateIndexPatterns)}
); }; diff --git a/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/switch_mode_popover.tsx b/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/switch_mode_popover.tsx index 29950794d2c44..c21f3a15425c1 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/switch_mode_popover.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/switch_mode_popover.tsx @@ -8,14 +8,15 @@ import React, { useState, useCallback } from 'react'; import { EuiButtonEmpty, EuiPopover, EuiFormRow, EuiSwitch } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { SelectIndexComponentProps } from './types'; type SwitchModePopoverProps = Pick & { - isKibanaIndexesModeOn: boolean; + isKibanaIndicesModeOn: boolean; }; export const SwitchModePopover = ({ - isKibanaIndexesModeOn, + isKibanaIndicesModeOn, onModeChange, }: SwitchModePopoverProps) => { const [isPopoverOpen, setIsPopoverOpen] = useState(false); @@ -36,7 +37,12 @@ export const SwitchModePopover = ({ } @@ -44,11 +50,27 @@ export const SwitchModePopover = ({ closePopover={closePopover} style={{ height: 'auto' }} > - + diff --git a/src/plugins/vis_type_timeseries/public/application/components/series_config.js b/src/plugins/vis_type_timeseries/public/application/components/series_config.js index 4e48ed4406ea5..3185503acb569 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/series_config.js +++ b/src/plugins/vis_type_timeseries/public/application/components/series_config.js @@ -137,5 +137,5 @@ SeriesConfig.propTypes = { panel: PropTypes.object, model: PropTypes.object, onChange: PropTypes.func, - indexPatternForQuery: PropTypes.string, + indexPatternForQuery: PropTypes.oneOfType([PropTypes.object, PropTypes.string]), }; diff --git a/src/plugins/vis_type_timeseries/public/application/components/series_config_query_bar_with_ignore_global_filter.js b/src/plugins/vis_type_timeseries/public/application/components/series_config_query_bar_with_ignore_global_filter.js index 0b67d52c23cd2..950101103b3a5 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/series_config_query_bar_with_ignore_global_filter.js +++ b/src/plugins/vis_type_timeseries/public/application/components/series_config_query_bar_with_ignore_global_filter.js @@ -90,5 +90,5 @@ SeriesConfigQueryBarWithIgnoreGlobalFilter.propTypes = { onChange: PropTypes.func, model: PropTypes.object, panel: PropTypes.object, - indexPatternForQuery: PropTypes.string, + indexPatternForQuery: PropTypes.oneOfType([PropTypes.object, PropTypes.string]), }; diff --git a/src/plugins/vis_type_timeseries/public/application/components/vis_types/gauge/series.js b/src/plugins/vis_type_timeseries/public/application/components/vis_types/gauge/series.js index 2909167031d08..46cc8b6ebe635 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/vis_types/gauge/series.js +++ b/src/plugins/vis_type_timeseries/public/application/components/vis_types/gauge/series.js @@ -198,7 +198,7 @@ GaugeSeriesUi.propTypes = { visible: PropTypes.bool, uiRestrictions: PropTypes.object, dragHandleProps: PropTypes.object, - indexPatternForQuery: PropTypes.string, + indexPatternForQuery: PropTypes.oneOfType([PropTypes.object, PropTypes.string]), }; export const GaugeSeries = injectI18n(GaugeSeriesUi); diff --git a/src/plugins/vis_type_timeseries/public/application/components/vis_types/markdown/series.js b/src/plugins/vis_type_timeseries/public/application/components/vis_types/markdown/series.js index 6f00abe5aa2c0..f9817242a101a 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/vis_types/markdown/series.js +++ b/src/plugins/vis_type_timeseries/public/application/components/vis_types/markdown/series.js @@ -200,7 +200,7 @@ MarkdownSeriesUi.propTypes = { visible: PropTypes.bool, uiRestrictions: PropTypes.object, dragHandleProps: PropTypes.object, - indexPatternForQuery: PropTypes.string, + indexPatternForQuery: PropTypes.oneOfType([PropTypes.object, PropTypes.string]), }; export const MarkdownSeries = injectI18n(MarkdownSeriesUi); diff --git a/src/plugins/vis_type_timeseries/public/application/components/vis_types/metric/series.js b/src/plugins/vis_type_timeseries/public/application/components/vis_types/metric/series.js index 64425cf534226..5ec2378792812 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/vis_types/metric/series.js +++ b/src/plugins/vis_type_timeseries/public/application/components/vis_types/metric/series.js @@ -211,7 +211,7 @@ MetricSeriesUi.propTypes = { togglePanelActivation: PropTypes.func, uiRestrictions: PropTypes.object, dragHandleProps: PropTypes.object, - indexPatternForQuery: PropTypes.string, + indexPatternForQuery: PropTypes.oneOfType([PropTypes.object, PropTypes.string]), }; export const MetricSeries = injectI18n(MetricSeriesUi); diff --git a/src/plugins/vis_type_timeseries/public/application/components/vis_types/table/config.js b/src/plugins/vis_type_timeseries/public/application/components/vis_types/table/config.js index fecd6cde1dca8..8855522e1938a 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/vis_types/table/config.js +++ b/src/plugins/vis_type_timeseries/public/application/components/vis_types/table/config.js @@ -263,7 +263,7 @@ TableSeriesConfigUI.propTypes = { fields: PropTypes.object, model: PropTypes.object, onChange: PropTypes.func, - indexPatternForQuery: PropTypes.string, + indexPatternForQuery: PropTypes.oneOfType([PropTypes.object, PropTypes.string]), }; export const TableSeriesConfig = injectI18n(TableSeriesConfigUI); diff --git a/src/plugins/vis_type_timeseries/public/application/components/vis_types/table/series.js b/src/plugins/vis_type_timeseries/public/application/components/vis_types/table/series.js index a56afd1f817b3..acd2f4cc17d4a 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/vis_types/table/series.js +++ b/src/plugins/vis_type_timeseries/public/application/components/vis_types/table/series.js @@ -186,7 +186,7 @@ TableSeriesUI.propTypes = { togglePanelActivation: PropTypes.func, uiRestrictions: PropTypes.object, dragHandleProps: PropTypes.object, - indexPatternForQuery: PropTypes.string, + indexPatternForQuery: PropTypes.oneOfType([PropTypes.object, PropTypes.string]), }; export const TableSeries = injectI18n(TableSeriesUI); diff --git a/src/plugins/vis_type_timeseries/public/application/components/vis_types/timeseries/config.js b/src/plugins/vis_type_timeseries/public/application/components/vis_types/timeseries/config.js index d3944adb41719..794f9493dc9d5 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/vis_types/timeseries/config.js +++ b/src/plugins/vis_type_timeseries/public/application/components/vis_types/timeseries/config.js @@ -556,6 +556,6 @@ TimeseriesConfig.propTypes = { model: PropTypes.object, panel: PropTypes.object, onChange: PropTypes.func, - indexPatternForQuery: PropTypes.string, + indexPatternForQuery: PropTypes.oneOfType([PropTypes.object, PropTypes.string]), seriesQuantity: PropTypes.object, }; diff --git a/src/plugins/vis_type_timeseries/public/application/components/vis_types/timeseries/series.js b/src/plugins/vis_type_timeseries/public/application/components/vis_types/timeseries/series.js index 76df07ce7c8c4..bb10ac57c5ae9 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/vis_types/timeseries/series.js +++ b/src/plugins/vis_type_timeseries/public/application/components/vis_types/timeseries/series.js @@ -209,7 +209,7 @@ TimeseriesSeriesUI.propTypes = { togglePanelActivation: PropTypes.func, uiRestrictions: PropTypes.object, dragHandleProps: PropTypes.object, - indexPatternForQuery: PropTypes.string, + indexPatternForQuery: PropTypes.oneOfType([PropTypes.object, PropTypes.string]), seriesQuantity: PropTypes.object, }; diff --git a/src/plugins/vis_type_timeseries/public/application/components/vis_types/top_n/series.js b/src/plugins/vis_type_timeseries/public/application/components/vis_types/top_n/series.js index bfe446a8226e8..61bb7e2473dd9 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/vis_types/top_n/series.js +++ b/src/plugins/vis_type_timeseries/public/application/components/vis_types/top_n/series.js @@ -200,5 +200,5 @@ TopNSeries.propTypes = { togglePanelActivation: PropTypes.func, uiRestrictions: PropTypes.object, dragHandleProps: PropTypes.object, - indexPatternForQuery: PropTypes.string, + indexPatternForQuery: PropTypes.oneOfType([PropTypes.object, PropTypes.string]), }; From f8cc3894dcf89daa676f995bcb23e1fbdce4b5db Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Fri, 26 Feb 2021 15:01:23 +0300 Subject: [PATCH 03/39] add migration script --- .../index_pattern_select/combo_box_select.tsx | 6 ++-- .../legacy_mode_popover.tsx | 8 +++-- .../saved_objects/visualization_migrations.ts | 30 +++++++++++++++++++ 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/combo_box_select.tsx b/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/combo_box_select.tsx index 1a047ac946e76..4371ab6ad90b6 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/combo_box_select.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/combo_box_select.tsx @@ -36,6 +36,9 @@ const toSelectedOptions = ( return []; }; +const toComboBoxOptions = (options: IdsWithTitle) => + options.map(({ title, id }) => ({ label: title, id })); + export const ComboBoxSelect = ({ onIndexChange, onModeChange, @@ -53,9 +56,6 @@ export const ComboBoxSelect = ({ [onIndexChange] ); - const toComboBoxOptions = (options: IdsWithTitle) => - options.map(({ title, id }) => ({ label: title, id })); - useEffect(() => { async function fetchIndexes() { setAvailableIndexes(await getDataStart().indexPatterns.getIdsWithTitle()); diff --git a/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/legacy_mode_popover.tsx b/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/legacy_mode_popover.tsx index fd09cde7ec11e..f3948ba4374bc 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/legacy_mode_popover.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/legacy_mode_popover.tsx @@ -98,14 +98,16 @@ export const LegacyModePopover = ({ index }: LegacyModePopoverProps) => { useEffect(() => { async function retrieveIndex() { + const shouldShowExtraCallOuts = Boolean(index); let hasIndex = false; - if (index) { + + if (shouldShowExtraCallOuts) { const { indexPatterns } = getDataStart(); hasIndex = Boolean((await indexPatterns.find(index)).find((i) => i.title === index)); } - setShowReadyToMigrateCallOut(Boolean(index) && hasIndex); - setNoMatchedIndicesCallOut(Boolean(index) && !hasIndex); + setShowReadyToMigrateCallOut(shouldShowExtraCallOuts && hasIndex); + setNoMatchedIndicesCallOut(shouldShowExtraCallOuts && !hasIndex); } retrieveIndex(); diff --git a/src/plugins/visualizations/server/saved_objects/visualization_migrations.ts b/src/plugins/visualizations/server/saved_objects/visualization_migrations.ts index 89df7aec8d8e6..d2c16f527b1ca 100644 --- a/src/plugins/visualizations/server/saved_objects/visualization_migrations.ts +++ b/src/plugins/visualizations/server/saved_objects/visualization_migrations.ts @@ -748,6 +748,35 @@ const removeTSVBSearchSource: SavedObjectMigrationFn = (doc) => { return doc; }; +const addSupportOfDualIndexSelectionModeInTSVB: SavedObjectMigrationFn = (doc) => { + const visStateJSON = get(doc, 'attributes.visState'); + let visState; + + if (visStateJSON) { + try { + visState = JSON.parse(visStateJSON); + } catch (e) { + // Let it go, the data is invalid and we'll leave it as is + } + if (visState && visState.type === 'metrics') { + const { params } = visState; + + if (typeof params?.index_pattern === 'string') { + params.use_kibana_indexes = false; + } + + return { + ...doc, + attributes: { + ...doc.attributes, + visState: JSON.stringify(visState), + }, + }; + } + } + return doc; +}; + // [Data table visualization] Enable toolbar by default const enableDataTableVisToolbar: SavedObjectMigrationFn = (doc) => { let visState; @@ -884,4 +913,5 @@ export const visualizationSavedObjectTypeMigrations = { '7.10.0': flow(migrateFilterRatioQuery, removeTSVBSearchSource), '7.11.0': flow(enableDataTableVisToolbar), '7.12.0': flow(migrateVislibAreaLineBarTypes), + '7.13.0': flow(addSupportOfDualIndexSelectionModeInTSVB), }; From 725d5e8fb8a4e15684b7be559eaa65fc71e65299 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Mon, 1 Mar 2021 12:57:14 +0300 Subject: [PATCH 04/39] refactoring --- ...s.test.ts => index_patterns_utils.test.ts} | 2 +- ...ex_patterns.ts => index_patterns_utils.ts} | 8 +++++ .../vis_type_timeseries/common/types.ts | 9 +++++- .../components/aggs/field_select.tsx | 10 +++--- .../components/annotations_editor.js | 9 +++--- .../application/components/index_pattern.js | 2 +- .../index_pattern_select/combo_box_select.tsx | 6 ++-- .../field_text_select.tsx | 6 ++-- .../{ => lib}/index_pattern_select/index.ts | 0 .../index_pattern_select.tsx | 4 +-- .../legacy_mode_popover.tsx | 2 +- .../switch_mode_popover.tsx | 0 .../{ => lib}/index_pattern_select/types.ts | 2 +- .../components/panel_config/table.js | 5 ++- .../components/query_bar_wrapper.js | 17 ---------- .../components/query_bar_wrapper.tsx | 32 +++++++++++++++++++ .../application/components/vis_editor.js | 2 +- .../public/application/lib/fetch_fields.ts | 23 +++++++------ .../search_strategy_registry.ts | 2 +- 19 files changed, 90 insertions(+), 51 deletions(-) rename src/plugins/vis_type_timeseries/common/{extract_index_patterns.test.ts => index_patterns_utils.test.ts} (94%) rename src/plugins/vis_type_timeseries/common/{extract_index_patterns.ts => index_patterns_utils.ts} (75%) rename src/plugins/vis_type_timeseries/public/application/components/{ => lib}/index_pattern_select/combo_box_select.tsx (92%) rename src/plugins/vis_type_timeseries/public/application/components/{ => lib}/index_pattern_select/field_text_select.tsx (86%) rename src/plugins/vis_type_timeseries/public/application/components/{ => lib}/index_pattern_select/index.ts (100%) rename src/plugins/vis_type_timeseries/public/application/components/{ => lib}/index_pattern_select/index_pattern_select.tsx (93%) rename src/plugins/vis_type_timeseries/public/application/components/{ => lib}/index_pattern_select/legacy_mode_popover.tsx (98%) rename src/plugins/vis_type_timeseries/public/application/components/{ => lib}/index_pattern_select/switch_mode_popover.tsx (100%) rename src/plugins/vis_type_timeseries/public/application/components/{ => lib}/index_pattern_select/types.ts (90%) delete mode 100644 src/plugins/vis_type_timeseries/public/application/components/query_bar_wrapper.js create mode 100644 src/plugins/vis_type_timeseries/public/application/components/query_bar_wrapper.tsx diff --git a/src/plugins/vis_type_timeseries/common/extract_index_patterns.test.ts b/src/plugins/vis_type_timeseries/common/index_patterns_utils.test.ts similarity index 94% rename from src/plugins/vis_type_timeseries/common/extract_index_patterns.test.ts rename to src/plugins/vis_type_timeseries/common/index_patterns_utils.test.ts index c4da2085855e6..cd8ecd54a2e90 100644 --- a/src/plugins/vis_type_timeseries/common/extract_index_patterns.test.ts +++ b/src/plugins/vis_type_timeseries/common/index_patterns_utils.test.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { extractIndexPatterns } from './extract_index_patterns'; +import { extractIndexPatterns } from './index_patterns_utils'; import { PanelSchema } from './types'; describe('extractIndexPatterns(vis)', () => { diff --git a/src/plugins/vis_type_timeseries/common/extract_index_patterns.ts b/src/plugins/vis_type_timeseries/common/index_patterns_utils.ts similarity index 75% rename from src/plugins/vis_type_timeseries/common/extract_index_patterns.ts rename to src/plugins/vis_type_timeseries/common/index_patterns_utils.ts index 9c417e69f7608..6da8cb4252711 100644 --- a/src/plugins/vis_type_timeseries/common/extract_index_patterns.ts +++ b/src/plugins/vis_type_timeseries/common/index_patterns_utils.ts @@ -41,3 +41,11 @@ export function extractIndexPatterns( return uniq(patterns).sort(); } + +export const convertIndexPatternObjectToStringRepresentation = ( + indexPatternObject: IndexPatternObject +) => + typeof indexPatternObject === 'string' ? indexPatternObject : indexPatternObject?.title ?? ''; + +export const getIndexPatternObjectKey = (indexPatternObject: IndexPatternObject) => + typeof indexPatternObject === 'string' ? indexPatternObject : indexPatternObject?.id ?? ''; diff --git a/src/plugins/vis_type_timeseries/common/types.ts b/src/plugins/vis_type_timeseries/common/types.ts index 4139de8403c59..f13e9e1f7d97f 100644 --- a/src/plugins/vis_type_timeseries/common/types.ts +++ b/src/plugins/vis_type_timeseries/common/types.ts @@ -7,7 +7,14 @@ */ import { TypeOf } from '@kbn/config-schema'; -import { metricsItems, panel, seriesItems, visPayloadSchema, fieldObject, indexPattern } from './vis_schema'; +import { + metricsItems, + panel, + seriesItems, + visPayloadSchema, + fieldObject, + indexPattern, +} from './vis_schema'; import { PANEL_TYPES } from './panel_types'; import { TimeseriesUIRestrictions } from './ui_restrictions'; diff --git a/src/plugins/vis_type_timeseries/public/application/components/aggs/field_select.tsx b/src/plugins/vis_type_timeseries/public/application/components/aggs/field_select.tsx index 7d9d81a8a966e..dcdb706f1299b 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/aggs/field_select.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/aggs/field_select.tsx @@ -10,8 +10,8 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import { EuiComboBox, EuiComboBoxProps, EuiComboBoxOptionOption } from '@elastic/eui'; import { METRIC_TYPES } from '../../../../common/metric_types'; - -import type { SanitizedFieldType } from '../../../../common/types'; +import { getIndexPatternObjectKey } from '../../../../common/index_patterns_utils'; +import type { SanitizedFieldType, IndexPatternObject } from '../../../../common/types'; import type { TimeseriesUIRestrictions } from '../../../../common/ui_restrictions'; // @ts-ignore @@ -20,7 +20,7 @@ import { isFieldEnabled } from '../../lib/check_ui_restrictions'; interface FieldSelectProps { type: string; fields: Record; - indexPattern: string; + indexPattern: IndexPatternObject; value: string; onChange: (options: Array>) => void; disabled?: boolean; @@ -62,8 +62,10 @@ export function FieldSelect({ const selectedOptions: Array> = []; let newPlaceholder = placeholder; + const fieldsSelector = getIndexPatternObjectKey(indexPattern); + const groupedOptions: EuiComboBoxProps['options'] = Object.values( - (fields[indexPattern] || []).reduce>>( + (fields[fieldsSelector] || []).reduce>>( (acc, field) => { if (placeholder === field?.name) { newPlaceholder = field.label ?? field.name; diff --git a/src/plugins/vis_type_timeseries/public/application/components/annotations_editor.js b/src/plugins/vis_type_timeseries/public/application/components/annotations_editor.js index f95eeb4816128..0130e636c28b5 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/annotations_editor.js +++ b/src/plugins/vis_type_timeseries/public/application/components/annotations_editor.js @@ -34,6 +34,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; +import { IndexPatternSelect } from './lib/index_pattern_select'; function newAnnotation() { return { @@ -125,11 +126,11 @@ export class AnnotationsEditor extends Component { } fullWidth > - diff --git a/src/plugins/vis_type_timeseries/public/application/components/index_pattern.js b/src/plugins/vis_type_timeseries/public/application/components/index_pattern.js index a7cb2e0bbbe64..a9bde15120dab 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/index_pattern.js +++ b/src/plugins/vis_type_timeseries/public/application/components/index_pattern.js @@ -24,6 +24,7 @@ import { import { FieldSelect } from './aggs/field_select'; import { createSelectHandler } from './lib/create_select_handler'; import { createTextHandler } from './lib/create_text_handler'; +import { IndexPatternSelect } from './lib/index_pattern_select'; import { YesNo } from './yes_no'; import { KBN_FIELD_TYPES } from '../../../../../plugins/data/public'; import { FormValidationContext } from '../contexts/form_validation_context'; @@ -37,7 +38,6 @@ import { VisDataContext } from '../contexts/vis_data_context'; import { getUISettings } from '../../services'; import { AUTO_INTERVAL } from '../../../common/constants'; import { UI_SETTINGS } from '../../../../data/common'; -import { IndexPatternSelect } from './index_pattern_select'; const RESTRICT_FIELDS = [KBN_FIELD_TYPES.DATE]; const LEVEL_OF_DETAIL_STEPS = 10; diff --git a/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/combo_box_select.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/combo_box_select.tsx similarity index 92% rename from src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/combo_box_select.tsx rename to src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/combo_box_select.tsx index 4371ab6ad90b6..a564d5aacd573 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/combo_box_select.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/combo_box_select.tsx @@ -9,11 +9,11 @@ import React, { useCallback, useState, useEffect } from 'react'; import type { UnwrapPromise } from '@kbn/utility-types'; import { EuiComboBox, EuiComboBoxProps } from '@elastic/eui'; -import { getDataStart } from '../../../services'; +import { getDataStart } from '../../../../services'; import type { SelectIndexComponentProps } from './types'; -import type { IndexPatternObject } from '../../../../common/types'; -import type { IndexPatternsService } from '../../../../../data/public'; +import type { IndexPatternObject } from '../../../../../common/types'; +import type { IndexPatternsService } from '../../../../../../data/public'; import { SwitchModePopover } from './switch_mode_popover'; /** @internal **/ diff --git a/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/field_text_select.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/field_text_select.tsx similarity index 86% rename from src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/field_text_select.tsx rename to src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/field_text_select.tsx index 61d109e4bb822..22e2bb31d6d3d 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/field_text_select.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/field_text_select.tsx @@ -10,11 +10,9 @@ import React, { useCallback } from 'react'; import { EuiFieldText, EuiFieldTextProps } from '@elastic/eui'; import { LegacyModePopover } from './legacy_mode_popover'; import { SwitchModePopover } from './switch_mode_popover'; +import { convertIndexPatternObjectToStringRepresentation } from '../../../../../common/index_patterns_utils'; import type { SelectIndexComponentProps } from './types'; -import type { IndexPatternObject } from '../../../../common/types'; - -const toTextValue = (v: IndexPatternObject) => (typeof v === 'string' ? v : v?.title ?? ''); export const FieldTextSelect = ({ onIndexChange, @@ -24,7 +22,7 @@ export const FieldTextSelect = ({ onModeChange, allowSwitchUseKibanaIndexesMode, }: SelectIndexComponentProps) => { - const textualValue = toTextValue(value); + const textualValue = convertIndexPatternObjectToStringRepresentation(value); const append = []; const onFieldTextChange: EuiFieldTextProps['onChange'] = useCallback( diff --git a/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/index.ts b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/index.ts similarity index 100% rename from src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/index.ts rename to src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/index.ts diff --git a/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/index_pattern_select.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/index_pattern_select.tsx similarity index 93% rename from src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/index_pattern_select.tsx rename to src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/index_pattern_select.tsx index 003f8299c18c4..39069af85f134 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/index_pattern_select.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/index_pattern_select.tsx @@ -10,8 +10,8 @@ import React, { useState, useContext, useCallback } from 'react'; import useDebounce from 'react-use/lib/useDebounce'; import { FieldTextSelect } from './field_text_select'; import { ComboBoxSelect } from './combo_box_select'; -import { PanelModelContext } from '../../contexts/panel_model_context'; -import type { IndexPatternObject } from '../../../../common/types'; +import { PanelModelContext } from '../../../contexts/panel_model_context'; +import type { IndexPatternObject } from '../../../../../common/types'; const USE_KIBANA_INDEXES_KEY = 'use_kibana_indexes'; diff --git a/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/legacy_mode_popover.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/legacy_mode_popover.tsx similarity index 98% rename from src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/legacy_mode_popover.tsx rename to src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/legacy_mode_popover.tsx index f3948ba4374bc..e932f465a2207 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/legacy_mode_popover.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/legacy_mode_popover.tsx @@ -10,7 +10,7 @@ import React, { useState, useCallback, useEffect } from 'react'; import { EuiTextColor, EuiButtonIcon, EuiPopover, EuiButton, EuiCallOut } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; -import { getCoreStart, getDataStart } from '../../../services'; +import { getCoreStart, getDataStart } from '../../../../services'; interface LegacyModePopoverProps { index: string; diff --git a/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/switch_mode_popover.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/switch_mode_popover.tsx similarity index 100% rename from src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/switch_mode_popover.tsx rename to src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/switch_mode_popover.tsx diff --git a/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/types.ts b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/types.ts similarity index 90% rename from src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/types.ts rename to src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/types.ts index ea231ef0d6788..6ed6f183d4e42 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/index_pattern_select/types.ts +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/types.ts @@ -5,7 +5,7 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import type { IndexPatternObject } from '../../../../common/types'; +import type { IndexPatternObject } from '../../../../../common/types'; export interface SelectIndexComponentProps { value: IndexPatternObject; diff --git a/src/plugins/vis_type_timeseries/public/application/components/panel_config/table.js b/src/plugins/vis_type_timeseries/public/application/components/panel_config/table.js index 07219e70692b8..65c4a86753da0 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/panel_config/table.js +++ b/src/plugins/vis_type_timeseries/public/application/components/panel_config/table.js @@ -36,6 +36,7 @@ import { QueryBarWrapper } from '../query_bar_wrapper'; import { getDefaultQueryLanguage } from '../lib/get_default_query_language'; import { VisDataContext } from '../../contexts/vis_data_context'; import { BUCKET_TYPES } from '../../../../common/metric_types'; +import { getIndexPatternObjectKey } from '../../../../common/index_patterns_utils'; export class TablePanelConfig extends Component { static contextType = VisDataContext; constructor(props) { @@ -59,7 +60,9 @@ export class TablePanelConfig extends Component { handlePivotChange = (selectedOption) => { const { fields, model } = this.props; const pivotId = get(selectedOption, '[0].value', null); - const field = fields[model.index_pattern].find((field) => field.name === pivotId); + const field = fields[getIndexPatternObjectKey(model.index_pattern)].find( + (field) => field.name === pivotId + ); const pivotType = get(field, 'type', model.pivot_type); this.props.onChange({ diff --git a/src/plugins/vis_type_timeseries/public/application/components/query_bar_wrapper.js b/src/plugins/vis_type_timeseries/public/application/components/query_bar_wrapper.js deleted file mode 100644 index af8404eb6da92..0000000000000 --- a/src/plugins/vis_type_timeseries/public/application/components/query_bar_wrapper.js +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import React, { useContext } from 'react'; -import { CoreStartContext } from '../contexts/query_input_bar_context'; -import { QueryStringInput } from '../../../../../plugins/data/public'; - -export function QueryBarWrapper(props) { - const coreStartContext = useContext(CoreStartContext); - - return ; -} diff --git a/src/plugins/vis_type_timeseries/public/application/components/query_bar_wrapper.tsx b/src/plugins/vis_type_timeseries/public/application/components/query_bar_wrapper.tsx new file mode 100644 index 0000000000000..c74f37ce58c84 --- /dev/null +++ b/src/plugins/vis_type_timeseries/public/application/components/query_bar_wrapper.tsx @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { useContext } from 'react'; + +import { CoreStartContext } from '../contexts/query_input_bar_context'; +import { IndexPatternObject } from '../../../common/types'; +import { convertIndexPatternObjectToStringRepresentation } from '../../../common/index_patterns_utils'; + +import { QueryStringInput, QueryStringInputProps } from '../../../../../plugins/data/public'; + +type QueryBarWrapperProps = Pick & { + indexPatterns: IndexPatternObject[]; +}; + +export function QueryBarWrapper({ query, onChange, indexPatterns }: QueryBarWrapperProps) { + const coreStartContext = useContext(CoreStartContext); + + return ( + + ); +} diff --git a/src/plugins/vis_type_timeseries/public/application/components/vis_editor.js b/src/plugins/vis_type_timeseries/public/application/components/vis_editor.js index 11586628ea005..cabe6798fbed0 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/vis_editor.js +++ b/src/plugins/vis_type_timeseries/public/application/components/vis_editor.js @@ -15,7 +15,7 @@ import { VisEditorVisualization } from './vis_editor_visualization'; import { VisPicker } from './vis_picker'; import { PanelConfig } from './panel_config'; import { fetchFields } from '../lib/fetch_fields'; -import { extractIndexPatterns } from '../../../common/extract_index_patterns'; +import { extractIndexPatterns } from '../../../common/index_patterns_utils'; import { getSavedObjectsClient, getUISettings, getDataStart, getCoreStart } from '../../services'; import { CoreStartContextProvider } from '../contexts/query_input_bar_context'; diff --git a/src/plugins/vis_type_timeseries/public/application/lib/fetch_fields.ts b/src/plugins/vis_type_timeseries/public/application/lib/fetch_fields.ts index 4b41747f23c79..0f87069a08b7f 100644 --- a/src/plugins/vis_type_timeseries/public/application/lib/fetch_fields.ts +++ b/src/plugins/vis_type_timeseries/public/application/lib/fetch_fields.ts @@ -9,10 +9,11 @@ import { i18n } from '@kbn/i18n'; import { getCoreStart, getDataStart } from '../../services'; import { ROUTES } from '../../../common/constants'; -import { SanitizedFieldType } from '../../../common/types'; +import { SanitizedFieldType, IndexPatternObject } from '../../../common/types'; +import { getIndexPatternObjectKey } from '../../../common/index_patterns_utils'; export async function fetchFields( - indexes: string[] = [], + indexes: IndexPatternObject[] = [], signal?: AbortSignal ): Promise> { const patterns = Array.isArray(indexes) ? indexes : [indexes]; @@ -23,19 +24,23 @@ export async function fetchFields( const defaultIndexPattern = await dataStart.indexPatterns.getDefault(); const indexFields = await Promise.all( patterns.map(async (pattern) => { - return coreStart.http.get(ROUTES.FIELDS, { - query: { - index: pattern, - }, - signal, - }); + if (typeof pattern !== 'string' && pattern?.id) { + return (await dataStart.indexPatterns.get(pattern.id)).getNonScriptedFields(); + } else { + return coreStart.http.get(ROUTES.FIELDS, { + query: { + index: `${pattern ?? ''}`, + }, + signal, + }); + } }) ); const fields: Record = patterns.reduce( (cumulatedFields, currentPattern, index) => ({ ...cumulatedFields, - [currentPattern]: indexFields[index], + [getIndexPatternObjectKey(currentPattern)]: indexFields[index], }), {} ); diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_strategy_registry.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_strategy_registry.ts index 83688cded3776..c77c422c77687 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_strategy_registry.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_strategy_registry.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { extractIndexPatterns } from '../../../common/extract_index_patterns'; +import { extractIndexPatterns } from '../../../common/index_patterns_utils'; import { PanelSchema } from '../../../common/types'; import { AbstractSearchStrategy, ReqFacade } from './strategies'; From 0f9d8add1450e74e3560f361cfa424dfebe069cb Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Mon, 1 Mar 2021 15:25:59 +0300 Subject: [PATCH 05/39] fix CI --- .../components/lib/index_pattern_select/combo_box_select.tsx | 2 ++ .../lib/index_pattern_select/field_text_select.tsx | 2 ++ test/functional/page_objects/visual_builder_page.ts | 5 ++--- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/combo_box_select.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/combo_box_select.tsx index a564d5aacd573..e6787df50e3e0 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/combo_box_select.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/combo_box_select.tsx @@ -46,6 +46,7 @@ export const ComboBoxSelect = ({ value, placeholder, allowSwitchUseKibanaIndexesMode, + 'data-test-subj': dataTestSubj, }: SelectIndexComponentProps) => { const [availableIndexes, setAvailableIndexes] = useState([]); @@ -72,6 +73,7 @@ export const ComboBoxSelect = ({ selectedOptions={toSelectedOptions(value)} isDisabled={disabled} placeholder={placeholder} + data-test-subj={dataTestSubj} {...(allowSwitchUseKibanaIndexesMode && { append: , })} diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/field_text_select.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/field_text_select.tsx index 22e2bb31d6d3d..1a3edb6231176 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/field_text_select.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/field_text_select.tsx @@ -21,6 +21,7 @@ export const FieldTextSelect = ({ placeholder, onModeChange, allowSwitchUseKibanaIndexesMode, + 'data-test-subj': dataTestSubj, }: SelectIndexComponentProps) => { const textualValue = convertIndexPatternObjectToStringRepresentation(value); const append = []; @@ -43,6 +44,7 @@ export const FieldTextSelect = ({ value={textualValue} placeholder={placeholder} append={append} + data-test-subj={dataTestSubj} /> ); }; diff --git a/test/functional/page_objects/visual_builder_page.ts b/test/functional/page_objects/visual_builder_page.ts index 963a6bff0cd0b..865eaf9a7c232 100644 --- a/test/functional/page_objects/visual_builder_page.ts +++ b/test/functional/page_objects/visual_builder_page.ts @@ -432,9 +432,8 @@ export function VisualBuilderPageProvider({ getService, getPageObjects }: FtrPro } public async setIndexPatternValue(value: string) { - const el = await testSubjects.find('metricsIndexPatternInput'); - await el.clearValue(); - await el.type(value, { charByChar: true }); + await comboBox.clearInputField('metricsIndexPatternInput'); + await comboBox.setCustom('metricsIndexPatternInput', value); await PageObjects.header.waitUntilLoadingHasFinished(); } From 6fcdda5f05e399828690049c71e19408716e41e3 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Mon, 1 Mar 2021 15:44:56 +0300 Subject: [PATCH 06/39] prefill the index pattern name --- .../create_index_pattern_wizard.tsx | 3 ++- .../lib/index_pattern_select/legacy_mode_popover.tsx | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/create_index_pattern_wizard.tsx b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/create_index_pattern_wizard.tsx index 9ff26decc1c6e..633906feb785b 100644 --- a/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/create_index_pattern_wizard.tsx +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/create_index_pattern_wizard.tsx @@ -57,10 +57,11 @@ export class CreateIndexPatternWizard extends Component< context.services.setBreadcrumbs(getCreateBreadcrumbs()); const type = new URLSearchParams(props.location.search).get('type') || undefined; + const indexPattern = new URLSearchParams(props.location.search).get('name') || ''; this.state = { step: 1, - indexPattern: '', + indexPattern, allIndices: [], remoteClustersExist: false, isInitiallyLoadingIndices: true, diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/legacy_mode_popover.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/legacy_mode_popover.tsx index e932f465a2207..caca9fa933a1e 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/legacy_mode_popover.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/legacy_mode_popover.tsx @@ -92,9 +92,9 @@ export const LegacyModePopover = ({ index }: LegacyModePopoverProps) => { const navigateToCreateIndexPatterns = useCallback(() => { const core = getCoreStart(); core.application.navigateToApp('management', { - path: `/kibana/indexPatterns/create`, + path: `/kibana/indexPatterns/create?name=${index}`, }); - }, []); + }, [index]); useEffect(() => { async function retrieveIndex() { From 8a9113d6bc24e47c032894aeff9266855c45158c Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Mon, 1 Mar 2021 16:47:40 +0300 Subject: [PATCH 07/39] modify UI --- .../field_text_select.tsx | 2 +- .../index_pattern_select.tsx | 4 +- .../legacy_mode_popover.tsx | 41 +++++++++++-------- .../lib/index_pattern_select/types.ts | 2 +- 4 files changed, 28 insertions(+), 21 deletions(-) diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/field_text_select.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/field_text_select.tsx index 1a3edb6231176..df0d3c4529ac0 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/field_text_select.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/field_text_select.tsx @@ -24,7 +24,7 @@ export const FieldTextSelect = ({ 'data-test-subj': dataTestSubj, }: SelectIndexComponentProps) => { const textualValue = convertIndexPatternObjectToStringRepresentation(value); - const append = []; + const append = []; const onFieldTextChange: EuiFieldTextProps['onChange'] = useCallback( (e) => { diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/index_pattern_select.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/index_pattern_select.tsx index 39069af85f134..526cefc05ba7b 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/index_pattern_select.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/index_pattern_select.tsx @@ -50,11 +50,11 @@ export const IndexPatternSelect = ({ ); const onModeChange = useCallback( - (useKibanaIndexes: boolean) => { + (useKibanaIndexes: boolean, index?: IndexPatternObject) => { onChange({ [USE_KIBANA_INDEXES_KEY]: useKibanaIndexes, }); - setInputValue(''); + setInputValue(index ?? ''); }, [onChange] ); diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/legacy_mode_popover.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/legacy_mode_popover.tsx index caca9fa933a1e..8f25522ad3f76 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/legacy_mode_popover.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/legacy_mode_popover.tsx @@ -11,10 +11,12 @@ import { EuiTextColor, EuiButtonIcon, EuiPopover, EuiButton, EuiCallOut } from ' import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; import { getCoreStart, getDataStart } from '../../../../services'; +import type { IndexPatternObject } from '../../../../../common/types'; +import { SelectIndexComponentProps } from './types'; -interface LegacyModePopoverProps { +type LegacyModePopoverProps = Pick & { index: string; -} +}; const getDeprecationCallOut = () => ( ( ); -const getReadyToMigrateCallOut = (index: string) => ( +const getReadyToMigrateCallOut = (index: string, switchToUseKibanaIndices: () => void) => ( ( }} />

+ + +
); @@ -82,13 +90,13 @@ const getNoMatchedIndicesCallOut = (index: string, onCreateIndexClick: () => voi ); -export const LegacyModePopover = ({ index }: LegacyModePopoverProps) => { +export const LegacyModePopover = ({ index, onModeChange }: LegacyModePopoverProps) => { const [isPopoverOpen, setIsPopoverOpen] = useState(false); - const [showReadyToMigrateCallOut, setShowReadyToMigrateCallOut] = useState(false); - const [showNoMatchedIndicesCallOut, setNoMatchedIndicesCallOut] = useState(false); + const [matchedIndex, setMatchedIndex] = useState(); const closePopover = useCallback(() => setIsPopoverOpen(false), []); const onButtonClick = useCallback(() => setIsPopoverOpen((isOpen) => !isOpen), []); + const navigateToCreateIndexPatterns = useCallback(() => { const core = getCoreStart(); core.application.navigateToApp('management', { @@ -96,18 +104,18 @@ export const LegacyModePopover = ({ index }: LegacyModePopoverProps) => { }); }, [index]); + const switchToUseKibanaIndices = useCallback(() => { + onModeChange(true, index); + }, [onModeChange, index]); + useEffect(() => { async function retrieveIndex() { - const shouldShowExtraCallOuts = Boolean(index); - let hasIndex = false; - - if (shouldShowExtraCallOuts) { + if (index) { const { indexPatterns } = getDataStart(); - hasIndex = Boolean((await indexPatterns.find(index)).find((i) => i.title === index)); - } + const mIndex = (await indexPatterns.find(index)).find((i) => i.title === index); - setShowReadyToMigrateCallOut(shouldShowExtraCallOuts && hasIndex); - setNoMatchedIndicesCallOut(shouldShowExtraCallOuts && !hasIndex); + setMatchedIndex(mIndex ? { id: mIndex.id!, title: mIndex.title } : undefined); + } } retrieveIndex(); @@ -132,9 +140,8 @@ export const LegacyModePopover = ({ index }: LegacyModePopoverProps) => { closePopover={closePopover} > {getDeprecationCallOut()} - {showReadyToMigrateCallOut && getReadyToMigrateCallOut(index)} - {showNoMatchedIndicesCallOut && - getNoMatchedIndicesCallOut(index, navigateToCreateIndexPatterns)} + {index && matchedIndex && getReadyToMigrateCallOut(index, switchToUseKibanaIndices)} + {index && !matchedIndex && getNoMatchedIndicesCallOut(index, navigateToCreateIndexPatterns)} ); }; diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/types.ts b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/types.ts index 6ed6f183d4e42..d109d6ee5056f 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/types.ts +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/types.ts @@ -10,7 +10,7 @@ import type { IndexPatternObject } from '../../../../../common/types'; export interface SelectIndexComponentProps { value: IndexPatternObject; onIndexChange: (value: IndexPatternObject) => void; - onModeChange: (useKibanaIndexes: boolean) => void; + onModeChange: (useKibanaIndexes: boolean, value?: IndexPatternObject) => void; 'data-test-subj': string; placeholder?: string; disabled?: boolean; From eea56c61e4c1cfe8989763be5b570e36fb12984f Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Tue, 2 Mar 2021 14:11:24 +0300 Subject: [PATCH 08/39] modify UI --- .../common/index_patterns_utils.ts | 28 ++-- .../index_pattern_select/combo_box_select.tsx | 29 ++-- .../field_text_select.tsx | 12 +- .../index_pattern_select.tsx | 4 +- .../legacy_mode_popover.tsx | 147 ------------------ .../migration_callout.tsx | 92 +++++++++++ .../switch_mode_popover.tsx | 108 ++++++++----- 7 files changed, 205 insertions(+), 215 deletions(-) delete mode 100644 src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/legacy_mode_popover.tsx create mode 100644 src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/migration_callout.tsx diff --git a/src/plugins/vis_type_timeseries/common/index_patterns_utils.ts b/src/plugins/vis_type_timeseries/common/index_patterns_utils.ts index 6da8cb4252711..2dc1f135c6559 100644 --- a/src/plugins/vis_type_timeseries/common/index_patterns_utils.ts +++ b/src/plugins/vis_type_timeseries/common/index_patterns_utils.ts @@ -9,10 +9,24 @@ import { uniq } from 'lodash'; import { PanelSchema, IndexPatternObject } from '../common/types'; -export function extractIndexPatterns( +export const isStringTypeIndexPattern = ( + indexPatternObject: IndexPatternObject +): indexPatternObject is string => typeof indexPatternObject === 'string'; + +export const convertIndexPatternObjectToStringRepresentation = ( + indexPatternObject: IndexPatternObject +) => + isStringTypeIndexPattern(indexPatternObject) + ? indexPatternObject + : indexPatternObject?.title ?? ''; + +export const getIndexPatternObjectKey = (indexPatternObject: IndexPatternObject) => + isStringTypeIndexPattern(indexPatternObject) ? indexPatternObject : indexPatternObject?.id ?? ''; + +export const extractIndexPatterns = ( panel: PanelSchema, defaultIndex?: PanelSchema['default_index_pattern'] -) { +) => { const patterns: IndexPatternObject[] = []; if (panel.index_pattern) { @@ -40,12 +54,4 @@ export function extractIndexPatterns( } return uniq(patterns).sort(); -} - -export const convertIndexPatternObjectToStringRepresentation = ( - indexPatternObject: IndexPatternObject -) => - typeof indexPatternObject === 'string' ? indexPatternObject : indexPatternObject?.title ?? ''; - -export const getIndexPatternObjectKey = (indexPatternObject: IndexPatternObject) => - typeof indexPatternObject === 'string' ? indexPatternObject : indexPatternObject?.id ?? ''; +}; diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/combo_box_select.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/combo_box_select.tsx index e6787df50e3e0..36aa76977c2a4 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/combo_box_select.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/combo_box_select.tsx @@ -11,10 +11,12 @@ import type { UnwrapPromise } from '@kbn/utility-types'; import { EuiComboBox, EuiComboBoxProps } from '@elastic/eui'; import { getDataStart } from '../../../../services'; +import { SwitchModePopover } from './switch_mode_popover'; +import { isStringTypeIndexPattern } from '../../../../../common/index_patterns_utils'; + import type { SelectIndexComponentProps } from './types'; import type { IndexPatternObject } from '../../../../../common/types'; import type { IndexPatternsService } from '../../../../../../data/public'; -import { SwitchModePopover } from './switch_mode_popover'; /** @internal **/ type IdsWithTitle = UnwrapPromise>; @@ -22,18 +24,17 @@ type IdsWithTitle = UnwrapPromise['selectedOptions'] => { - if (value) { - if (typeof value === 'string') { - return [{ label: value ?? '' }]; - } - return [ - { - id: value.id ?? '', - label: value.title ?? '', - }, - ]; + if (!value) { + return []; } - return []; + return isStringTypeIndexPattern(value) + ? [{ label: value ?? '' }] + : [ + { + id: value.id ?? '', + label: value.title ?? '', + }, + ]; }; const toComboBoxOptions = (options: IdsWithTitle) => @@ -75,7 +76,9 @@ export const ComboBoxSelect = ({ placeholder={placeholder} data-test-subj={dataTestSubj} {...(allowSwitchUseKibanaIndexesMode && { - append: , + append: ( + + ), })} /> ); diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/field_text_select.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/field_text_select.tsx index df0d3c4529ac0..39724e31b4f46 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/field_text_select.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/field_text_select.tsx @@ -8,7 +8,6 @@ import React, { useCallback } from 'react'; import { EuiFieldText, EuiFieldTextProps } from '@elastic/eui'; -import { LegacyModePopover } from './legacy_mode_popover'; import { SwitchModePopover } from './switch_mode_popover'; import { convertIndexPatternObjectToStringRepresentation } from '../../../../../common/index_patterns_utils'; @@ -24,7 +23,6 @@ export const FieldTextSelect = ({ 'data-test-subj': dataTestSubj, }: SelectIndexComponentProps) => { const textualValue = convertIndexPatternObjectToStringRepresentation(value); - const append = []; const onFieldTextChange: EuiFieldTextProps['onChange'] = useCallback( (e) => { @@ -33,18 +31,18 @@ export const FieldTextSelect = ({ [onIndexChange] ); - if (allowSwitchUseKibanaIndexesMode) { - append.push(); - } - return ( + ), + })} /> ); }; diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/index_pattern_select.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/index_pattern_select.tsx index 526cefc05ba7b..86e26e6f700de 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/index_pattern_select.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/index_pattern_select.tsx @@ -33,9 +33,9 @@ export const IndexPatternSelect = ({ allowSwitchUseKibanaIndexesMode, }: IndexPatternSelectProps) => { const panelModel = useContext(PanelModelContext); - const useFieldTextControl = !Boolean(panelModel?.[USE_KIBANA_INDEXES_KEY]); + const useKibanaIndices = Boolean(panelModel?.[USE_KIBANA_INDEXES_KEY]); const [inputValue, setInputValue] = useState(value); - const Component = useFieldTextControl ? FieldTextSelect : ComboBoxSelect; + const Component = useKibanaIndices ? ComboBoxSelect : FieldTextSelect; useDebounce( () => { diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/legacy_mode_popover.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/legacy_mode_popover.tsx deleted file mode 100644 index 8f25522ad3f76..0000000000000 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/legacy_mode_popover.tsx +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import React, { useState, useCallback, useEffect } from 'react'; -import { EuiTextColor, EuiButtonIcon, EuiPopover, EuiButton, EuiCallOut } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { i18n } from '@kbn/i18n'; -import { getCoreStart, getDataStart } from '../../../../services'; -import type { IndexPatternObject } from '../../../../../common/types'; -import { SelectIndexComponentProps } from './types'; - -type LegacyModePopoverProps = Pick & { - index: string; -}; - -const getDeprecationCallOut = () => ( - -

- -

-
-); - -const getReadyToMigrateCallOut = (index: string, switchToUseKibanaIndices: () => void) => ( - -

- {index}, - }} - /> -

- - - -
-); - -const getNoMatchedIndicesCallOut = (index: string, onCreateIndexClick: () => void) => ( - -

- {index}, - }} - /> -

- - - -
-); - -export const LegacyModePopover = ({ index, onModeChange }: LegacyModePopoverProps) => { - const [isPopoverOpen, setIsPopoverOpen] = useState(false); - const [matchedIndex, setMatchedIndex] = useState(); - - const closePopover = useCallback(() => setIsPopoverOpen(false), []); - const onButtonClick = useCallback(() => setIsPopoverOpen((isOpen) => !isOpen), []); - - const navigateToCreateIndexPatterns = useCallback(() => { - const core = getCoreStart(); - core.application.navigateToApp('management', { - path: `/kibana/indexPatterns/create?name=${index}`, - }); - }, [index]); - - const switchToUseKibanaIndices = useCallback(() => { - onModeChange(true, index); - }, [onModeChange, index]); - - useEffect(() => { - async function retrieveIndex() { - if (index) { - const { indexPatterns } = getDataStart(); - const mIndex = (await indexPatterns.find(index)).find((i) => i.title === index); - - setMatchedIndex(mIndex ? { id: mIndex.id!, title: mIndex.title } : undefined); - } - } - - retrieveIndex(); - }, [index]); - - return ( - - } - isOpen={isPopoverOpen} - closePopover={closePopover} - > - {getDeprecationCallOut()} - {index && matchedIndex && getReadyToMigrateCallOut(index, switchToUseKibanaIndices)} - {index && !matchedIndex && getNoMatchedIndicesCallOut(index, navigateToCreateIndexPatterns)} - - ); -}; diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/migration_callout.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/migration_callout.tsx new file mode 100644 index 0000000000000..2dddf27e00464 --- /dev/null +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/migration_callout.tsx @@ -0,0 +1,92 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { useCallback } from 'react'; +import { EuiTextColor, EuiButton, EuiCallOut, EuiSpacer } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { i18n } from '@kbn/i18n'; +import { getCoreStart } from '../../../../services'; +import type { IndexPatternObject } from '../../../../../common/types'; + +interface LegacyModePopoverProps { + switchMode: () => void; + value: string; + matchedIndex?: IndexPatternObject; +} + +const getReadyToMigrateCallOut = ( + value: LegacyModePopoverProps['value'], + onModeChange: LegacyModePopoverProps['switchMode'] +) => ( + + {value}, + }} + /> + + + + +); + +const getNoMatchedIndicesCallOut = ( + value: LegacyModePopoverProps['value'], + onCreateIndexClick: () => void +) => ( + + {value}, + }} + /> + + + + +); + +export const MigrationCallout = ({ value, switchMode, matchedIndex }: LegacyModePopoverProps) => { + const navigateToCreateIndexPatterns = useCallback(() => { + getCoreStart().application.navigateToApp('management', { + path: `/kibana/indexPatterns/create?name=${value}`, + }); + }, [value]); + + return ( + <> + {matchedIndex && getReadyToMigrateCallOut(value, switchMode)} + {!matchedIndex && getNoMatchedIndicesCallOut(value, navigateToCreateIndexPatterns)} + + + ); +}; diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/switch_mode_popover.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/switch_mode_popover.tsx index c21f3a15425c1..a7a66d014b7ec 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/switch_mode_popover.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/switch_mode_popover.tsx @@ -6,41 +6,73 @@ * Side Public License, v 1. */ -import React, { useState, useCallback } from 'react'; -import { EuiButtonEmpty, EuiPopover, EuiFormRow, EuiSwitch } from '@elastic/eui'; +import React, { useState, useCallback, useEffect } from 'react'; +import { + EuiButtonIcon, + EuiPopover, + EuiPopoverTitle, + EuiSpacer, + EuiSwitch, + EuiText, +} from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { Assign } from '@kbn/utility-types'; +import { FormattedMessage } from '@kbn/i18n/react'; import { SelectIndexComponentProps } from './types'; +import { MigrationCallout } from './migration_callout'; +import { isStringTypeIndexPattern } from '../../../../../common/index_patterns_utils'; +import { IndexPatternObject } from '../../../../../common/types'; +import { getDataStart } from '../../../../services'; -type SwitchModePopoverProps = Pick & { - isKibanaIndicesModeOn: boolean; -}; +type SwitchModePopoverProps = Assign< + Pick, + { + useKibanaIndices: boolean; + } +>; export const SwitchModePopover = ({ - isKibanaIndicesModeOn, onModeChange, + value, + useKibanaIndices, }: SwitchModePopoverProps) => { const [isPopoverOpen, setIsPopoverOpen] = useState(false); + const [matchedIndex, setMatchedIndex] = useState(); const closePopover = useCallback(() => setIsPopoverOpen(false), []); const onButtonClick = useCallback(() => setIsPopoverOpen((isOpen) => !isOpen), []); - const onChange = useCallback( - (e) => { - onModeChange(e.target.checked); - }, - [onModeChange] - ); + const switchMode = useCallback(() => { + onModeChange(!useKibanaIndices, matchedIndex); + }, [onModeChange, matchedIndex, useKibanaIndices]); + + useEffect(() => { + async function retrieveIndex() { + const { indexPatterns } = getDataStart(); + + if (isStringTypeIndexPattern(value)) { + const index = (await indexPatterns.find(value)).find((i) => i.title === value); + + if (index) { + return setMatchedIndex({ id: index.id!, title: index.title }); + } + } + + setMatchedIndex(undefined); + } + + retrieveIndex(); + }, [value]); return ( - + + {i18n.translate('visTypeTimeseries.indexPatternSelect.switchModePopover.title', { + defaultMessage: 'Index pattern selection mode', + })} + + + + + + {value && isStringTypeIndexPattern(value) && ( + )} - hasChildLabel={false} - > - + ); }; From 50465456233cc9a75f59697429b79f81c7369977 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Tue, 2 Mar 2021 15:34:50 +0300 Subject: [PATCH 09/39] update UI --- .../lib/index_pattern_select/migration_callout.tsx | 2 +- .../lib/index_pattern_select/switch_mode_popover.tsx | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/migration_callout.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/migration_callout.tsx index 2dddf27e00464..2cd9713bafe8a 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/migration_callout.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/migration_callout.tsx @@ -84,9 +84,9 @@ export const MigrationCallout = ({ value, switchMode, matchedIndex }: LegacyMode return ( <> + {matchedIndex && getReadyToMigrateCallOut(value, switchMode)} {!matchedIndex && getNoMatchedIndicesCallOut(value, navigateToCreateIndexPatterns)} - ); }; diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/switch_mode_popover.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/switch_mode_popover.tsx index a7a66d014b7ec..ac9e895f11906 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/switch_mode_popover.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/switch_mode_popover.tsx @@ -97,9 +97,6 @@ export const SwitchModePopover = ({ /> - {value && isStringTypeIndexPattern(value) && ( - - )} + {value && isStringTypeIndexPattern(value) && ( + + )} ); From c41765de7bb4e818544fec6f815d057465029a38 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Tue, 2 Mar 2021 16:26:39 +0300 Subject: [PATCH 10/39] fix functional test --- .../switch_mode_popover.tsx | 2 ++ test/functional/apps/visualize/_tsvb_chart.ts | 2 +- .../page_objects/visual_builder_page.ts | 27 ++++++++++++++++--- .../test/functional/apps/rollup_job/tsvb.js | 2 +- 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/switch_mode_popover.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/switch_mode_popover.tsx index ac9e895f11906..89eb0eed54235 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/switch_mode_popover.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/switch_mode_popover.tsx @@ -76,6 +76,7 @@ export const SwitchModePopover = ({ } )} onClick={onButtonClick} + data-test-subj="switchIndexPatternSelectionModePopover" /> } isOpen={isPopoverOpen} @@ -107,6 +108,7 @@ export const SwitchModePopover = ({ } )} onChange={switchMode} + data-test-subj="switchIndexPatternSelectionMode" /> {value && isStringTypeIndexPattern(value) && ( diff --git a/test/functional/apps/visualize/_tsvb_chart.ts b/test/functional/apps/visualize/_tsvb_chart.ts index ba500904d75c7..fa84f31f421fd 100644 --- a/test/functional/apps/visualize/_tsvb_chart.ts +++ b/test/functional/apps/visualize/_tsvb_chart.ts @@ -128,7 +128,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); // Sometimes popovers take some time to appear in Firefox (#71979) await retry.tryForTime(20000, async () => { - await PageObjects.visualBuilder.setIndexPatternValue('kibana_sample_data_flights'); + await PageObjects.visualBuilder.setIndexPatternValue('kibana_sample_data_flights', false); await PageObjects.visualBuilder.waitForIndexPatternTimeFieldOptionsLoaded(); await PageObjects.visualBuilder.selectIndexPatternTimeField('timestamp'); }); diff --git a/test/functional/page_objects/visual_builder_page.ts b/test/functional/page_objects/visual_builder_page.ts index 865eaf9a7c232..499999c10dcb5 100644 --- a/test/functional/page_objects/visual_builder_page.ts +++ b/test/functional/page_objects/visual_builder_page.ts @@ -431,9 +431,30 @@ export function VisualBuilderPageProvider({ getService, getPageObjects }: FtrPro await PageObjects.header.waitUntilLoadingHasFinished(); } - public async setIndexPatternValue(value: string) { - await comboBox.clearInputField('metricsIndexPatternInput'); - await comboBox.setCustom('metricsIndexPatternInput', value); + public async switchIndexPatternSelectionMode(useKibanaIndices: boolean) { + await testSubjects.click('switchIndexPatternSelectionModePopover'); + await testSubjects.setEuiSwitch( + 'switchIndexPatternSelectionMode', + useKibanaIndices ? 'check' : 'uncheck' + ); + } + + public async setIndexPatternValue(value: string, useKibanaIndices?: boolean) { + const metricsIndexPatternInput = 'metricsIndexPatternInput'; + + if (useKibanaIndices !== undefined) { + await this.switchIndexPatternSelectionMode(useKibanaIndices); + } + + if (useKibanaIndices === false) { + const el = await testSubjects.find(metricsIndexPatternInput); + await el.clearValue(); + await el.type(value, { charByChar: true }); + } else { + await comboBox.clearInputField(metricsIndexPatternInput); + await comboBox.setCustom(metricsIndexPatternInput, value); + } + await PageObjects.header.waitUntilLoadingHasFinished(); } diff --git a/x-pack/test/functional/apps/rollup_job/tsvb.js b/x-pack/test/functional/apps/rollup_job/tsvb.js index 2172a149de6f7..9c4eae268d4a8 100644 --- a/x-pack/test/functional/apps/rollup_job/tsvb.js +++ b/x-pack/test/functional/apps/rollup_job/tsvb.js @@ -83,7 +83,7 @@ export default function ({ getService, getPageObjects }) { 'Oct 15, 2019 @ 19:31:44.000' ); await PageObjects.visualBuilder.clickPanelOptions('metric'); - await PageObjects.visualBuilder.setIndexPatternValue(rollupTargetIndexName); + await PageObjects.visualBuilder.setIndexPatternValue(rollupTargetIndexName, false); await PageObjects.visualBuilder.setIntervalValue('1d'); await PageObjects.visualBuilder.setDropLastBucket(false); await PageObjects.common.sleep(3000); From 47fc806094e8869de0dbe787cecca4c4d68cc25d Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Wed, 3 Mar 2021 12:55:31 +0300 Subject: [PATCH 11/39] some work --- .../search_strategy_registry.ts | 9 ++++++-- .../server/lib/vis_data/get_table_data.js | 15 +++++++------ .../test/functional/apps/rollup_job/tsvb.js | 22 ++++++++++--------- 3 files changed, 27 insertions(+), 19 deletions(-) diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_strategy_registry.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_strategy_registry.ts index c77c422c77687..f10cf6a4fe7b8 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_strategy_registry.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_strategy_registry.ts @@ -6,7 +6,10 @@ * Side Public License, v 1. */ -import { extractIndexPatterns } from '../../../common/index_patterns_utils'; +import { + extractIndexPatterns, + convertIndexPatternObjectToStringRepresentation, +} from '../../../common/index_patterns_utils'; import { PanelSchema } from '../../../common/types'; import { AbstractSearchStrategy, ReqFacade } from './strategies'; @@ -36,7 +39,9 @@ export class SearchStrategyRegistry { } async getViableStrategyForPanel(req: RequestFacade, panel: PanelSchema) { - const indexPattern = extractIndexPatterns(panel, panel.default_index_pattern).join(','); + const indexPattern = extractIndexPatterns(panel, panel.default_index_pattern) + .map(convertIndexPatternObjectToStringRepresentation) + .join(','); return this.getViableStrategy(req, indexPattern); } diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/get_table_data.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/get_table_data.js index e0604145eef33..c76765118e13b 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/get_table_data.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/get_table_data.js @@ -16,16 +16,17 @@ import { createFieldsFetcher } from './helpers/fields_fetcher'; import { extractFieldLabel } from '../../../common/calculate_label'; export async function getTableData(req, panel) { - const panelIndexPattern = panel.index_pattern; - + const { indexPatternObject, indexPatternString } = await getIndexPatternObject( + panel.index_pattern, + { + indexPatternsService: await req.getIndexPatternsService(), + } + ); const { searchStrategy, capabilities, - } = await req.framework.searchStrategyRegistry.getViableStrategy(req, panelIndexPattern); + } = await req.framework.searchStrategyRegistry.getViableStrategy(req, indexPatternString); const esQueryConfig = await getEsQueryConfig(req); - const { indexPatternObject } = await getIndexPatternObject(panelIndexPattern, { - indexPatternsService: await req.getIndexPatternsService(), - }); const extractFields = createFieldsFetcher(req, searchStrategy, capabilities); @@ -58,7 +59,7 @@ export async function getTableData(req, panel) { const [resp] = await searchStrategy.search(req, [ { body, - index: panelIndexPattern, + index: indexPatternString, }, ]); diff --git a/x-pack/test/functional/apps/rollup_job/tsvb.js b/x-pack/test/functional/apps/rollup_job/tsvb.js index 9c4eae268d4a8..7aa31118a26ea 100644 --- a/x-pack/test/functional/apps/rollup_job/tsvb.js +++ b/x-pack/test/functional/apps/rollup_job/tsvb.js @@ -6,7 +6,6 @@ */ import expect from '@kbn/expect'; -import mockRolledUpData from './hybrid_index_helper'; export default function ({ getService, getPageObjects }) { const es = getService('legacyEs'); @@ -40,12 +39,14 @@ export default function ({ getService, getPageObjects }) { it('create rollup tsvb', async () => { //Create data for rollup job so it doesn't fail - await es.index({ - index: rollupSourceIndexName, - body: { - '@timestamp': new Date().toISOString(), - }, - }); + for (const date of pastDates) { + await es.index({ + index: rollupSourceIndexName, + body: { + '@timestamp': date.toISOString(), + }, + }); + } await retry.try(async () => { //Create a rollup for kibana to recognize @@ -67,10 +68,11 @@ export default function ({ getService, getPageObjects }) { page_size: 1000, }, }); - }); - await pastDates.map(async (day) => { - await es.index(mockRolledUpData(rollupJobName, rollupTargetIndexName, day)); + await es.transport.request({ + path: `/_rollup/job/${rollupJobName}/_start`, + method: 'POST', + }); }); await PageObjects.visualize.navigateToNewVisualization(); From fd0d2a194c66c62fdb1ecefe649148c9795b7983 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Wed, 3 Mar 2021 15:34:57 +0300 Subject: [PATCH 12/39] remove callouts --- .../create_index_pattern_wizard.tsx | 3 +- .../application/components/index_pattern.js | 6 +- .../index_pattern_select/combo_box_select.tsx | 4 +- .../field_text_select.tsx | 4 +- .../index_pattern_select.tsx | 6 +- .../migration_callout.tsx | 92 ------------------- .../switch_mode_popover.tsx | 5 - .../lib/index_pattern_select/types.ts | 2 +- .../components/panel_config/gauge.js | 2 +- .../components/panel_config/markdown.js | 2 +- .../components/panel_config/metric.js | 2 +- .../components/panel_config/table.js | 2 +- .../components/panel_config/timeseries.js | 2 +- .../components/panel_config/top_n.js | 2 +- 14 files changed, 18 insertions(+), 116 deletions(-) delete mode 100644 src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/migration_callout.tsx diff --git a/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/create_index_pattern_wizard.tsx b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/create_index_pattern_wizard.tsx index 633906feb785b..9ff26decc1c6e 100644 --- a/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/create_index_pattern_wizard.tsx +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/create_index_pattern_wizard.tsx @@ -57,11 +57,10 @@ export class CreateIndexPatternWizard extends Component< context.services.setBreadcrumbs(getCreateBreadcrumbs()); const type = new URLSearchParams(props.location.search).get('type') || undefined; - const indexPattern = new URLSearchParams(props.location.search).get('name') || ''; this.state = { step: 1, - indexPattern, + indexPattern: '', allIndices: [], remoteClustersExist: false, isInitiallyLoadingIndices: true, diff --git a/src/plugins/vis_type_timeseries/public/application/components/index_pattern.js b/src/plugins/vis_type_timeseries/public/application/components/index_pattern.js index a9bde15120dab..4c91cb1b9e036 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/index_pattern.js +++ b/src/plugins/vis_type_timeseries/public/application/components/index_pattern.js @@ -66,7 +66,7 @@ export const IndexPattern = ({ disabled, model: _model, allowLevelOfDetail, - allowSwitchUseKibanaIndexesMode, + allowIndexSwitchingMode, }) => { const config = getUISettings(); const timeFieldName = `${prefix}time_field`; @@ -183,7 +183,7 @@ export const IndexPattern = ({ onChange={onChange} defaultIndexPattern={model.default_index_pattern} disabled={disabled} - allowSwitchUseKibanaIndexesMode={allowSwitchUseKibanaIndexesMode} + allowIndexSwitchingMode={allowIndexSwitchingMode} /> @@ -334,5 +334,5 @@ IndexPattern.propTypes = { disabled: PropTypes.bool, className: PropTypes.string, allowLevelOfDetail: PropTypes.bool, - allowSwitchUseKibanaIndexesMode: PropTypes.bool, + allowIndexSwitchingMode: PropTypes.bool, }; diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/combo_box_select.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/combo_box_select.tsx index 36aa76977c2a4..533fc14e595c5 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/combo_box_select.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/combo_box_select.tsx @@ -46,7 +46,7 @@ export const ComboBoxSelect = ({ disabled, value, placeholder, - allowSwitchUseKibanaIndexesMode, + allowSwitchMode, 'data-test-subj': dataTestSubj, }: SelectIndexComponentProps) => { const [availableIndexes, setAvailableIndexes] = useState([]); @@ -75,7 +75,7 @@ export const ComboBoxSelect = ({ isDisabled={disabled} placeholder={placeholder} data-test-subj={dataTestSubj} - {...(allowSwitchUseKibanaIndexesMode && { + {...(allowSwitchMode && { append: ( ), diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/field_text_select.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/field_text_select.tsx index 39724e31b4f46..7bed524487068 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/field_text_select.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/field_text_select.tsx @@ -19,7 +19,7 @@ export const FieldTextSelect = ({ value, placeholder, onModeChange, - allowSwitchUseKibanaIndexesMode, + allowSwitchMode, 'data-test-subj': dataTestSubj, }: SelectIndexComponentProps) => { const textualValue = convertIndexPatternObjectToStringRepresentation(value); @@ -38,7 +38,7 @@ export const FieldTextSelect = ({ value={textualValue} placeholder={placeholder} data-test-subj={dataTestSubj} - {...(allowSwitchUseKibanaIndexesMode && { + {...(allowSwitchMode && { append: ( ), diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/index_pattern_select.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/index_pattern_select.tsx index 86e26e6f700de..35512f76e4574 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/index_pattern_select.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/index_pattern_select.tsx @@ -21,7 +21,7 @@ interface IndexPatternSelectProps { defaultIndexPattern: string; onChange: Function; disabled?: boolean; - allowSwitchUseKibanaIndexesMode?: boolean; + allowIndexSwitchingMode?: boolean; } export const IndexPatternSelect = ({ @@ -30,7 +30,7 @@ export const IndexPatternSelect = ({ onChange, disabled, defaultIndexPattern, - allowSwitchUseKibanaIndexesMode, + allowIndexSwitchingMode, }: IndexPatternSelectProps) => { const panelModel = useContext(PanelModelContext); const useKibanaIndices = Boolean(panelModel?.[USE_KIBANA_INDEXES_KEY]); @@ -67,7 +67,7 @@ export const IndexPatternSelect = ({ placeholder={defaultIndexPattern} onIndexChange={setInputValue} onModeChange={onModeChange} - allowSwitchUseKibanaIndexesMode={allowSwitchUseKibanaIndexesMode} + allowSwitchMode={allowIndexSwitchingMode} /> ); }; diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/migration_callout.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/migration_callout.tsx deleted file mode 100644 index 2cd9713bafe8a..0000000000000 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/migration_callout.tsx +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import React, { useCallback } from 'react'; -import { EuiTextColor, EuiButton, EuiCallOut, EuiSpacer } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { i18n } from '@kbn/i18n'; -import { getCoreStart } from '../../../../services'; -import type { IndexPatternObject } from '../../../../../common/types'; - -interface LegacyModePopoverProps { - switchMode: () => void; - value: string; - matchedIndex?: IndexPatternObject; -} - -const getReadyToMigrateCallOut = ( - value: LegacyModePopoverProps['value'], - onModeChange: LegacyModePopoverProps['switchMode'] -) => ( - - {value}, - }} - /> - - - - -); - -const getNoMatchedIndicesCallOut = ( - value: LegacyModePopoverProps['value'], - onCreateIndexClick: () => void -) => ( - - {value}, - }} - /> - - - - -); - -export const MigrationCallout = ({ value, switchMode, matchedIndex }: LegacyModePopoverProps) => { - const navigateToCreateIndexPatterns = useCallback(() => { - getCoreStart().application.navigateToApp('management', { - path: `/kibana/indexPatterns/create?name=${value}`, - }); - }, [value]); - - return ( - <> - - {matchedIndex && getReadyToMigrateCallOut(value, switchMode)} - {!matchedIndex && getNoMatchedIndicesCallOut(value, navigateToCreateIndexPatterns)} - - ); -}; diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/switch_mode_popover.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/switch_mode_popover.tsx index 89eb0eed54235..7ebea5aaba3b6 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/switch_mode_popover.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/switch_mode_popover.tsx @@ -19,7 +19,6 @@ import { i18n } from '@kbn/i18n'; import { Assign } from '@kbn/utility-types'; import { FormattedMessage } from '@kbn/i18n/react'; import { SelectIndexComponentProps } from './types'; -import { MigrationCallout } from './migration_callout'; import { isStringTypeIndexPattern } from '../../../../../common/index_patterns_utils'; import { IndexPatternObject } from '../../../../../common/types'; import { getDataStart } from '../../../../services'; @@ -99,7 +98,6 @@ export const SwitchModePopover = ({ - {value && isStringTypeIndexPattern(value) && ( - - )} ); diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/types.ts b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/types.ts index d109d6ee5056f..0a0e434ee1b77 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/types.ts +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/types.ts @@ -14,5 +14,5 @@ export interface SelectIndexComponentProps { 'data-test-subj': string; placeholder?: string; disabled?: boolean; - allowSwitchUseKibanaIndexesMode?: boolean; + allowSwitchMode?: boolean; } diff --git a/src/plugins/vis_type_timeseries/public/application/components/panel_config/gauge.js b/src/plugins/vis_type_timeseries/public/application/components/panel_config/gauge.js index fce782eb0ad01..1180c0e3fe866 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/panel_config/gauge.js +++ b/src/plugins/vis_type_timeseries/public/application/components/panel_config/gauge.js @@ -126,7 +126,7 @@ class GaugePanelConfigUi extends Component { fields={this.props.fields} model={this.props.model} onChange={this.props.onChange} - allowSwitchUseKibanaIndexesMode={true} + allowIndexSwitchingMode={true} /> diff --git a/src/plugins/vis_type_timeseries/public/application/components/panel_config/markdown.js b/src/plugins/vis_type_timeseries/public/application/components/panel_config/markdown.js index cfd5824b22006..023220c9ee5df 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/panel_config/markdown.js +++ b/src/plugins/vis_type_timeseries/public/application/components/panel_config/markdown.js @@ -132,7 +132,7 @@ class MarkdownPanelConfigUi extends Component { fields={this.props.fields} model={this.props.model} onChange={this.props.onChange} - allowSwitchUseKibanaIndexesMode={true} + allowIndexSwitchingMode={true} /> diff --git a/src/plugins/vis_type_timeseries/public/application/components/panel_config/metric.js b/src/plugins/vis_type_timeseries/public/application/components/panel_config/metric.js index f0c00e65759d1..5e89745d28f7b 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/panel_config/metric.js +++ b/src/plugins/vis_type_timeseries/public/application/components/panel_config/metric.js @@ -90,7 +90,7 @@ export class MetricPanelConfig extends Component { fields={this.props.fields} model={this.props.model} onChange={this.props.onChange} - allowSwitchUseKibanaIndexesMode={true} + allowIndexSwitchingMode={true} /> diff --git a/src/plugins/vis_type_timeseries/public/application/components/panel_config/table.js b/src/plugins/vis_type_timeseries/public/application/components/panel_config/table.js index 65c4a86753da0..35830e637b9ee 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/panel_config/table.js +++ b/src/plugins/vis_type_timeseries/public/application/components/panel_config/table.js @@ -217,7 +217,7 @@ export class TablePanelConfig extends Component { fields={this.props.fields} model={this.props.model} onChange={this.props.onChange} - allowSwitchUseKibanaIndexesMode={true} + allowIndexSwitchingMode={true} /> diff --git a/src/plugins/vis_type_timeseries/public/application/components/panel_config/timeseries.js b/src/plugins/vis_type_timeseries/public/application/components/panel_config/timeseries.js index 3e94110a9ec44..9695483464845 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/panel_config/timeseries.js +++ b/src/plugins/vis_type_timeseries/public/application/components/panel_config/timeseries.js @@ -183,7 +183,7 @@ class TimeseriesPanelConfigUi extends Component { model={this.props.model} onChange={this.props.onChange} allowLevelOfDetail={true} - allowSwitchUseKibanaIndexesMode={true} + allowIndexSwitchingMode={true} /> diff --git a/src/plugins/vis_type_timeseries/public/application/components/panel_config/top_n.js b/src/plugins/vis_type_timeseries/public/application/components/panel_config/top_n.js index 5b4fd47e9bf8b..bca3f1a829ec5 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/panel_config/top_n.js +++ b/src/plugins/vis_type_timeseries/public/application/components/panel_config/top_n.js @@ -116,7 +116,7 @@ export class TopNPanelConfig extends Component { fields={this.props.fields} model={this.props.model} onChange={this.props.onChange} - allowSwitchUseKibanaIndexesMode={true} + allowIndexSwitchingMode={true} /> From 79343e0905fc49ab4dbbaac1552dc22453d3cf8a Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Wed, 3 Mar 2021 16:37:00 +0300 Subject: [PATCH 13/39] fix rollup test --- .../lib/get_index_pattern.ts | 13 ++++++++--- .../test/functional/apps/rollup_job/tsvb.js | 22 +++++++++---------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/get_index_pattern.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/get_index_pattern.ts index 776c799295ded..a09a7cc63b814 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/get_index_pattern.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/get_index_pattern.ts @@ -17,6 +17,7 @@ export async function getIndexPatternObject( { indexPatternsService }: IndexPatternObjectDependencies ) { let indexPatternObject: IndexPattern | undefined | null; + let indexPatternString: string = ''; const getIndexPatternFromString = async (v: string) => (await indexPatternsService.find(v)).find((index) => index.title === indexPattern); @@ -26,15 +27,21 @@ export async function getIndexPatternObject( } else { if (typeof indexPattern === 'string') { indexPatternObject = await getIndexPatternFromString(indexPattern); + + if (!indexPatternObject) { + indexPatternString = indexPattern; + } } else if (indexPattern.id) { indexPatternObject = await indexPatternsService.get(indexPattern.id); - } else if (indexPattern.title) { - indexPatternObject = await getIndexPatternFromString(indexPattern.title); + + if (!indexPatternObject && indexPattern.title) { + indexPatternString = indexPattern.title; + } } } return { indexPatternObject, - indexPatternString: indexPatternObject?.title ?? '', + indexPatternString: indexPatternObject?.title ?? indexPatternString, }; } diff --git a/x-pack/test/functional/apps/rollup_job/tsvb.js b/x-pack/test/functional/apps/rollup_job/tsvb.js index 7aa31118a26ea..9c4eae268d4a8 100644 --- a/x-pack/test/functional/apps/rollup_job/tsvb.js +++ b/x-pack/test/functional/apps/rollup_job/tsvb.js @@ -6,6 +6,7 @@ */ import expect from '@kbn/expect'; +import mockRolledUpData from './hybrid_index_helper'; export default function ({ getService, getPageObjects }) { const es = getService('legacyEs'); @@ -39,14 +40,12 @@ export default function ({ getService, getPageObjects }) { it('create rollup tsvb', async () => { //Create data for rollup job so it doesn't fail - for (const date of pastDates) { - await es.index({ - index: rollupSourceIndexName, - body: { - '@timestamp': date.toISOString(), - }, - }); - } + await es.index({ + index: rollupSourceIndexName, + body: { + '@timestamp': new Date().toISOString(), + }, + }); await retry.try(async () => { //Create a rollup for kibana to recognize @@ -68,11 +67,10 @@ export default function ({ getService, getPageObjects }) { page_size: 1000, }, }); + }); - await es.transport.request({ - path: `/_rollup/job/${rollupJobName}/_start`, - method: 'POST', - }); + await pastDates.map(async (day) => { + await es.index(mockRolledUpData(rollupJobName, rollupTargetIndexName, day)); }); await PageObjects.visualize.navigateToNewVisualization(); From b438e5743dfce80ffe5638a4cd8c3d779fc6b6c5 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Thu, 4 Mar 2021 14:52:08 +0300 Subject: [PATCH 14/39] update UI --- .../create_index_pattern_wizard.tsx | 3 +- .../components/annotations_editor.js | 31 +---- .../application/components/index_pattern.js | 28 ++--- .../index_pattern_select.tsx | 105 ++++++++++++++--- .../index_pattern_select/migrate_popover.tsx | 111 ++++++++++++++++++ .../switch_mode_popover.tsx | 45 +------ .../lib/index_pattern_select/types.ts | 13 +- .../translations/translations/ja-JP.json | 4 - .../translations/translations/zh-CN.json | 4 - 9 files changed, 231 insertions(+), 113 deletions(-) create mode 100644 src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/migrate_popover.tsx diff --git a/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/create_index_pattern_wizard.tsx b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/create_index_pattern_wizard.tsx index 9ff26decc1c6e..633906feb785b 100644 --- a/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/create_index_pattern_wizard.tsx +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/create_index_pattern_wizard.tsx @@ -57,10 +57,11 @@ export class CreateIndexPatternWizard extends Component< context.services.setBreadcrumbs(getCreateBreadcrumbs()); const type = new URLSearchParams(props.location.search).get('type') || undefined; + const indexPattern = new URLSearchParams(props.location.search).get('name') || ''; this.state = { step: 1, - indexPattern: '', + indexPattern, allIndices: [], remoteClustersExist: false, isInitiallyLoadingIndices: true, diff --git a/src/plugins/vis_type_timeseries/public/application/components/annotations_editor.js b/src/plugins/vis_type_timeseries/public/application/components/annotations_editor.js index 0130e636c28b5..ab0db6daae18a 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/annotations_editor.js +++ b/src/plugins/vis_type_timeseries/public/application/components/annotations_editor.js @@ -32,7 +32,6 @@ import { EuiCode, EuiText, } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { IndexPatternSelect } from './lib/index_pattern_select'; @@ -92,7 +91,6 @@ export class AnnotationsEditor extends Component { const htmlId = htmlIdGenerator(model.id); const handleAdd = collectionActions.handleAdd.bind(null, this.props, newAnnotation); const handleDelete = collectionActions.handleDelete.bind(null, this.props, model); - const defaultIndexPattern = this.props.model.default_index_pattern; return (
@@ -109,30 +107,11 @@ export class AnnotationsEditor extends Component { - - } - helpText={ - defaultIndexPattern && - !model.index_pattern && - i18n.translate('visTypeTimeseries.annotationsEditor.searchByDefaultIndex', { - defaultMessage: 'Default index pattern is used. To query all indexes use *', - }) - } - fullWidth - > - - + - - - + ({ + id: index.id!, + title: index.title, +}); + export const IndexPatternSelect = ({ value, indexPatternName, onChange, disabled, - defaultIndexPattern, allowIndexSwitchingMode, }: IndexPatternSelectProps) => { + const htmlId = htmlIdGenerator(); + const panelModel = useContext(PanelModelContext); - const useKibanaIndices = Boolean(panelModel?.[USE_KIBANA_INDEXES_KEY]); + const [defaultIndex, setDefaultIndex] = useState(); + const [matchedIndex, setMatchedIndex] = useState(); const [inputValue, setInputValue] = useState(value); + + const useKibanaIndices = Boolean(panelModel?.[USE_KIBANA_INDEXES_KEY]); const Component = useKibanaIndices ? ComboBoxSelect : FieldTextSelect; useDebounce( @@ -49,25 +67,80 @@ export const IndexPatternSelect = ({ [onChange, inputValue, indexPatternName, value] ); + useEffect(() => { + async function retrieveIndex() { + const { indexPatterns } = getDataStart(); + + if (isStringTypeIndexPattern(value)) { + const index = (await indexPatterns.find(value)).find((i) => i.title === value); + + if (index) { + return setMatchedIndex(toIndexPatternObject(index)); + } + } + + setMatchedIndex(undefined); + } + + retrieveIndex(); + }, [value]); + + useEffect(() => { + async function getDefaultIndex() { + const { indexPatterns } = getDataStart(); + const index = await indexPatterns.getDefault(); + + if (index) { + return setDefaultIndex(toIndexPatternObject(index)); + } + } + + getDefaultIndex(); + }, []); + const onModeChange = useCallback( - (useKibanaIndexes: boolean, index?: IndexPatternObject) => { + (useKibanaIndexes: boolean) => { onChange({ [USE_KIBANA_INDEXES_KEY]: useKibanaIndexes, }); - setInputValue(index ?? ''); + setInputValue(matchedIndex ?? ''); }, - [onChange] + [onChange, matchedIndex] ); return ( - + + ) + } + > + + ); }; diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/migrate_popover.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/migrate_popover.tsx new file mode 100644 index 0000000000000..1ab5d99317ad3 --- /dev/null +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/migrate_popover.tsx @@ -0,0 +1,111 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { useCallback, useState } from 'react'; +import { + EuiTextColor, + EuiButton, + EuiPopover, + EuiLink, + EuiText, + EuiSpacer, + EuiPopoverTitle, +} from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { i18n } from '@kbn/i18n'; +import { getCoreStart } from '../../../../services'; +import { PopoverProps } from './types'; + +const availabilityForMigration = i18n.translate( + 'visTypeTimeseries.indexPatternSelect.migrationPopover.availabilityForMigration', + { + defaultMessage: 'Availability for migration', + } +); + +const getReadyToMigrateCallOut = (value: PopoverProps['value'], onModeChange: () => void) => ( + <> + +

+ {value}, + }} + /> +

+
+ + + + + +); + +const getNoMatchedIndicesCallOut = ( + value: PopoverProps['value'], + onCreateIndexClick: () => void +) => ( + <> + +

+ {value}, + }} + /> +

+
+ + + + + +); + +export const MigrationPopover = ({ value, onModeChange, matchedIndex }: PopoverProps) => { + const [isPopoverOpen, setIsPopoverOpen] = useState(false); + const closePopover = useCallback(() => setIsPopoverOpen(false), []); + const onButtonClick = useCallback(() => setIsPopoverOpen((isOpen) => !isOpen), []); + + const switchMode = useCallback(() => { + onModeChange(true); + }, [onModeChange]); + + const navigateToCreateIndexPatterns = useCallback(() => { + getCoreStart().application.navigateToApp('management', { + path: `/kibana/indexPatterns/create?name=${value}`, + }); + }, [value]); + + return ( + + {availabilityForMigration} + + } + isOpen={isPopoverOpen} + closePopover={closePopover} + > + {availabilityForMigration} + {matchedIndex && getReadyToMigrateCallOut(value, switchMode)} + {!matchedIndex && getNoMatchedIndicesCallOut(value, navigateToCreateIndexPatterns)} + + ); +}; diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/switch_mode_popover.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/switch_mode_popover.tsx index 7ebea5aaba3b6..8cf7dca6d176e 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/switch_mode_popover.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/switch_mode_popover.tsx @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import React, { useState, useCallback, useEffect } from 'react'; +import React, { useState, useCallback } from 'react'; import { EuiButtonIcon, EuiPopover, @@ -16,52 +16,17 @@ import { EuiText, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { Assign } from '@kbn/utility-types'; import { FormattedMessage } from '@kbn/i18n/react'; -import { SelectIndexComponentProps } from './types'; -import { isStringTypeIndexPattern } from '../../../../../common/index_patterns_utils'; -import { IndexPatternObject } from '../../../../../common/types'; -import { getDataStart } from '../../../../services'; +import { PopoverProps } from './types'; -type SwitchModePopoverProps = Assign< - Pick, - { - useKibanaIndices: boolean; - } ->; - -export const SwitchModePopover = ({ - onModeChange, - value, - useKibanaIndices, -}: SwitchModePopoverProps) => { +export const SwitchModePopover = ({ onModeChange, useKibanaIndices }: PopoverProps) => { const [isPopoverOpen, setIsPopoverOpen] = useState(false); - const [matchedIndex, setMatchedIndex] = useState(); - const closePopover = useCallback(() => setIsPopoverOpen(false), []); const onButtonClick = useCallback(() => setIsPopoverOpen((isOpen) => !isOpen), []); const switchMode = useCallback(() => { - onModeChange(!useKibanaIndices, matchedIndex); - }, [onModeChange, matchedIndex, useKibanaIndices]); - - useEffect(() => { - async function retrieveIndex() { - const { indexPatterns } = getDataStart(); - - if (isStringTypeIndexPattern(value)) { - const index = (await indexPatterns.find(value)).find((i) => i.title === value); - - if (index) { - return setMatchedIndex({ id: index.id!, title: index.title }); - } - } - - setMatchedIndex(undefined); - } - - retrieveIndex(); - }, [value]); + onModeChange(!useKibanaIndices); + }, [onModeChange, useKibanaIndices]); return ( void; - onModeChange: (useKibanaIndexes: boolean, value?: IndexPatternObject) => void; + onModeChange: (useKibanaIndexes: boolean) => void; 'data-test-subj': string; placeholder?: string; disabled?: boolean; allowSwitchMode?: boolean; } + +/** @internal **/ +export type PopoverProps = Assign< + Pick, + { + useKibanaIndices: boolean; + matchedIndex?: IndexPatternObject; + } +>; diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 6e1f96e80b573..ef32d5f9ff6b7 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -4029,11 +4029,9 @@ "visTypeTimeseries.annotationsEditor.iconLabel": "アイコン (必須)", "visTypeTimeseries.annotationsEditor.ignoreGlobalFiltersLabel": "グローバルフィルターを無視しますか?", "visTypeTimeseries.annotationsEditor.ignorePanelFiltersLabel": "パネルフィルターを無視しますか?", - "visTypeTimeseries.annotationsEditor.indexPatternLabel": "インデックスパターン", "visTypeTimeseries.annotationsEditor.queryStringLabel": "クエリ文字列", "visTypeTimeseries.annotationsEditor.rowTemplateHelpText": "eg.{rowTemplateExample}", "visTypeTimeseries.annotationsEditor.rowTemplateLabel": "行テンプレート(必須)", - "visTypeTimeseries.annotationsEditor.searchByDefaultIndex": "デフォルトのインデックスパターンが使用されています。すべてのインデックスにクエリを実行するには * を使用します", "visTypeTimeseries.annotationsEditor.timeFieldLabel": "時間フィールド(必須)", "visTypeTimeseries.axisLabelOptions.axisLabel": "per {unitValue} {unitString}", "visTypeTimeseries.calculateLabel.bucketScriptsLabel": "バケットスクリプト", @@ -4153,7 +4151,6 @@ "visTypeTimeseries.indexPattern.finest": "最も細かい", "visTypeTimeseries.indexPattern.intervalHelpText": "例:auto、1m、1d、7d、1y、>=1m", "visTypeTimeseries.indexPattern.intervalLabel": "間隔", - "visTypeTimeseries.indexPattern.searchByDefaultIndex": "デフォルトのインデックスパターンが使用されています。すべてのインデックスにクエリを実行するには * を使用します", "visTypeTimeseries.indexPattern.timeFieldLabel": "時間フィールド", "visTypeTimeseries.indexPattern.timeRange.entireTimeRange": "時間範囲全体", "visTypeTimeseries.indexPattern.timeRange.hint": "この設定は、一致するドキュメントに使用される期間をコントロールします。\n 「時間範囲全体」は、タイムピッカーで選択されたすべてのドキュメントと照会します。\n 「最終値」は、期間の終了時から指定期間のドキュメントのみと照会します。", @@ -4161,7 +4158,6 @@ "visTypeTimeseries.indexPattern.timeRange.lastValue": "最終値", "visTypeTimeseries.indexPattern.timeRange.selectTimeRange": "選択してください", "visTypeTimeseries.indexPattern.сoarse": "粗い", - "visTypeTimeseries.indexPatternLabel": "インデックスパターン", "visTypeTimeseries.kbnVisTypes.metricsDescription": "時系列データの高度な分析を実行します。", "visTypeTimeseries.kbnVisTypes.metricsTitle": "TSVB", "visTypeTimeseries.markdown.alignOptions.bottomLabel": "一番下", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index b5a4b8a708513..08e610a602d66 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -4033,11 +4033,9 @@ "visTypeTimeseries.annotationsEditor.iconLabel": "图标(必需)", "visTypeTimeseries.annotationsEditor.ignoreGlobalFiltersLabel": "忽略全局筛选?", "visTypeTimeseries.annotationsEditor.ignorePanelFiltersLabel": "忽略面板筛选?", - "visTypeTimeseries.annotationsEditor.indexPatternLabel": "索引模式", "visTypeTimeseries.annotationsEditor.queryStringLabel": "查询字符串", "visTypeTimeseries.annotationsEditor.rowTemplateHelpText": "如 {rowTemplateExample}", "visTypeTimeseries.annotationsEditor.rowTemplateLabel": "行模板(必需)", - "visTypeTimeseries.annotationsEditor.searchByDefaultIndex": "将使用默认索引模式。要查询所有索引,请使用 *", "visTypeTimeseries.annotationsEditor.timeFieldLabel": "时间字段(必需)", "visTypeTimeseries.axisLabelOptions.axisLabel": "每 {unitValue} {unitString}", "visTypeTimeseries.calculateLabel.bucketScriptsLabel": "存储桶脚本", @@ -4157,7 +4155,6 @@ "visTypeTimeseries.indexPattern.finest": "最精细", "visTypeTimeseries.indexPattern.intervalHelpText": "示例:auto、1m、1d、7d、1y、>=1m", "visTypeTimeseries.indexPattern.intervalLabel": "时间间隔", - "visTypeTimeseries.indexPattern.searchByDefaultIndex": "将使用默认索引模式。要查询所有索引,请使用 *", "visTypeTimeseries.indexPattern.timeFieldLabel": "时间字段", "visTypeTimeseries.indexPattern.timeRange.entireTimeRange": "整个时间范围", "visTypeTimeseries.indexPattern.timeRange.hint": "此设置控制用于匹配文档的时间跨度。\n “整个时间范围”将匹配时间选取器中选择的所有文档。\n “最后值”将仅匹配时间范围结尾的指定时间间隔的文档。", @@ -4165,7 +4162,6 @@ "visTypeTimeseries.indexPattern.timeRange.lastValue": "最后值", "visTypeTimeseries.indexPattern.timeRange.selectTimeRange": "选择", "visTypeTimeseries.indexPattern.сoarse": "粗糙", - "visTypeTimeseries.indexPatternLabel": "索引模式", "visTypeTimeseries.kbnVisTypes.metricsDescription": "对时间序列数据执行高级分析。", "visTypeTimeseries.kbnVisTypes.metricsTitle": "TSVB", "visTypeTimeseries.markdown.alignOptions.bottomLabel": "底", From f41635bb884b232ed30f0877c4691dd712063312 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Thu, 4 Mar 2021 15:46:37 +0300 Subject: [PATCH 15/39] fix typo --- .../components/lib/index_pattern_select/migrate_popover.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/migrate_popover.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/migrate_popover.tsx index 1ab5d99317ad3..0436196c2fbff 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/migrate_popover.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/migrate_popover.tsx @@ -34,7 +34,7 @@ const getReadyToMigrateCallOut = (value: PopoverProps['value'], onModeChange: ()

{value}, }} From 041a73fcec130ffb7b8a7df3fe6a86c687e25e64 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Tue, 9 Mar 2021 13:28:51 +0300 Subject: [PATCH 16/39] add some unit tests --- .../common/index_patterns_utils.test.ts | 28 ++++- .../lib/get_index_pattern.test.ts | 111 ++++++++++++++++++ .../lib/get_index_pattern.ts | 8 +- 3 files changed, 140 insertions(+), 7 deletions(-) create mode 100644 src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/get_index_pattern.test.ts diff --git a/src/plugins/vis_type_timeseries/common/index_patterns_utils.test.ts b/src/plugins/vis_type_timeseries/common/index_patterns_utils.test.ts index cd8ecd54a2e90..2ffd45b01f4bf 100644 --- a/src/plugins/vis_type_timeseries/common/index_patterns_utils.test.ts +++ b/src/plugins/vis_type_timeseries/common/index_patterns_utils.test.ts @@ -6,10 +6,34 @@ * Side Public License, v 1. */ -import { extractIndexPatterns } from './index_patterns_utils'; +import { + extractIndexPatterns, + isStringTypeIndexPattern, + convertIndexPatternObjectToStringRepresentation, +} from './index_patterns_utils'; import { PanelSchema } from './types'; -describe('extractIndexPatterns(vis)', () => { +describe('isStringTypeIndexPattern', () => { + test('should returns true on string-based index', () => { + expect(isStringTypeIndexPattern('index')).toBeTruthy(); + }); + test('should returns false on object-based index', () => { + expect(isStringTypeIndexPattern({ title: 'title', id: 'id' })).toBeFalsy(); + }); +}); + +describe('convertIndexPatternObjectToStringRepresentation', () => { + test('should return the correct title on getting string-based index', () => { + expect(convertIndexPatternObjectToStringRepresentation('index')).toBe('index'); + }); + test('should return the correct title on getting object-based index', () => { + expect(convertIndexPatternObjectToStringRepresentation({ title: 'title', id: 'id' })).toBe( + 'title' + ); + }); +}); + +describe('extractIndexPatterns', () => { let panel: PanelSchema; beforeEach(() => { diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/get_index_pattern.test.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/get_index_pattern.test.ts new file mode 100644 index 0000000000000..5a3d9aaf7c663 --- /dev/null +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/get_index_pattern.test.ts @@ -0,0 +1,111 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { IndexPattern, IndexPatternsService } from 'src/plugins/data/server'; +import { getIndexPatternObject } from './get_index_pattern'; + +describe('getIndexPatternObject', () => { + let mockedIndices: IndexPattern[] | []; + + const indexPatternsService = ({ + getDefault: jest.fn(() => Promise.resolve({ id: 'default', title: 'index' })), + get: jest.fn(() => Promise.resolve(mockedIndices[0])), + find: jest.fn(() => Promise.resolve(mockedIndices || [])), + } as unknown) as IndexPatternsService; + + beforeEach(() => { + mockedIndices = []; + }); + + test('should return default index on no input value', async () => { + const value = await getIndexPatternObject('', { indexPatternsService }); + expect(value).toMatchInlineSnapshot(` + Object { + "indexPatternObject": Object { + "id": "default", + "title": "index", + }, + "indexPatternString": "index", + } + `); + }); + + describe('text-based index', () => { + test('should return the Kibana index if it exists', async () => { + mockedIndices = [ + { + id: 'indexId', + title: 'indexTitle', + }, + ] as IndexPattern[]; + + const value = await getIndexPatternObject('indexTitle', { indexPatternsService }); + + expect(value).toMatchInlineSnapshot(` + Object { + "indexPatternObject": Object { + "id": "indexId", + "title": "indexTitle", + }, + "indexPatternString": "indexTitle", + } + `); + }); + + test('should return only indexPatternString if Kibana index does not exist', async () => { + const value = await getIndexPatternObject('indexTitle', { indexPatternsService }); + + expect(value).toMatchInlineSnapshot(` + Object { + "indexPatternObject": undefined, + "indexPatternString": "indexTitle", + } + `); + }); + }); + + describe('object-based index', () => { + test('should return the Kibana index if it exists', async () => { + mockedIndices = [ + { + id: 'indexId', + title: 'indexTitle', + }, + ] as IndexPattern[]; + + const value = await getIndexPatternObject({ id: 'indexId' }, { indexPatternsService }); + + expect(value).toMatchInlineSnapshot(` + Object { + "indexPatternObject": Object { + "id": "indexId", + "title": "indexTitle", + }, + "indexPatternString": "indexTitle", + } + `); + }); + + test('should return default index if Kibana index not found', async () => { + const value = await getIndexPatternObject( + { id: 'indexId', title: 'title' }, + { indexPatternsService } + ); + + expect(value).toMatchInlineSnapshot(` + Object { + "indexPatternObject": Object { + "id": "default", + "title": "index", + }, + "indexPatternString": "index", + } + `); + }); + }); +}); diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/get_index_pattern.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/get_index_pattern.ts index a09a7cc63b814..e3b86f44d30a9 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/get_index_pattern.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/get_index_pattern.ts @@ -32,11 +32,9 @@ export async function getIndexPatternObject( indexPatternString = indexPattern; } } else if (indexPattern.id) { - indexPatternObject = await indexPatternsService.get(indexPattern.id); - - if (!indexPatternObject && indexPattern.title) { - indexPatternString = indexPattern.title; - } + indexPatternObject = + (await indexPatternsService.get(indexPattern.id)) ?? + (await indexPatternsService.getDefault()); } } From d9271bfb17814415a8c32f2e7ec7710adcc2c9c9 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Tue, 9 Mar 2021 16:28:58 +0300 Subject: [PATCH 17/39] add functional test --- test/functional/apps/visualize/_tsvb_chart.ts | 37 +++++++++++++------ .../page_objects/visual_builder_page.ts | 8 +++- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/test/functional/apps/visualize/_tsvb_chart.ts b/test/functional/apps/visualize/_tsvb_chart.ts index fa84f31f421fd..512eaec27fa94 100644 --- a/test/functional/apps/visualize/_tsvb_chart.ts +++ b/test/functional/apps/visualize/_tsvb_chart.ts @@ -108,32 +108,47 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { describe('switch index patterns', () => { beforeEach(async () => { - log.debug('Load kibana_sample_data_flights data'); - await esArchiver.loadIfNeeded('kibana_sample_data_flights'); + await esArchiver.loadIfNeeded('logstash_functional'); + await esArchiver.loadIfNeeded('index_pattern_without_timefield'); + await PageObjects.visualBuilder.resetPage(); await PageObjects.visualBuilder.clickMetric(); await PageObjects.visualBuilder.checkMetricTabIsPresent(); + await PageObjects.timePicker.setAbsoluteRange( + 'Sep 22, 2019 @ 00:00:00.000', + 'Sep 23, 2019 @ 00:00:00.000' + ); }); + after(async () => { await security.testUser.restoreDefaults(); - await esArchiver.unload('kibana_sample_data_flights'); + await esArchiver.unload('logstash_functional'); + await esArchiver.unload('index_pattern_without_timefield'); }); - it('should be able to switch between index patterns', async () => { - const value = await PageObjects.visualBuilder.getMetricValue(); - expect(value).to.eql('156'); + const switchIndexTest = async (useKibanaIndicies: boolean) => { await PageObjects.visualBuilder.clickPanelOptions('metric'); - const fromTime = 'Oct 22, 2018 @ 00:00:00.000'; - const toTime = 'Oct 28, 2018 @ 23:59:59.999'; - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await PageObjects.visualBuilder.setIndexPatternValue('', false); + + const value = await PageObjects.visualBuilder.getMetricValue(); + expect(value).to.eql('0'); + // Sometimes popovers take some time to appear in Firefox (#71979) await retry.tryForTime(20000, async () => { - await PageObjects.visualBuilder.setIndexPatternValue('kibana_sample_data_flights', false); + await PageObjects.visualBuilder.setIndexPatternValue('with-timefield', useKibanaIndicies); await PageObjects.visualBuilder.waitForIndexPatternTimeFieldOptionsLoaded(); await PageObjects.visualBuilder.selectIndexPatternTimeField('timestamp'); }); const newValue = await PageObjects.visualBuilder.getMetricValue(); - expect(newValue).to.eql('18'); + expect(newValue).to.eql('1'); + }; + + it('should be able to switch using text mode selection', async () => { + await switchIndexTest(false); + }); + + it('should be able to switch combo box mode selection', async () => { + await switchIndexTest(true); }); }); diff --git a/test/functional/page_objects/visual_builder_page.ts b/test/functional/page_objects/visual_builder_page.ts index 499999c10dcb5..57ad5dc4c10db 100644 --- a/test/functional/page_objects/visual_builder_page.ts +++ b/test/functional/page_objects/visual_builder_page.ts @@ -449,10 +449,14 @@ export function VisualBuilderPageProvider({ getService, getPageObjects }: FtrPro if (useKibanaIndices === false) { const el = await testSubjects.find(metricsIndexPatternInput); await el.clearValue(); - await el.type(value, { charByChar: true }); + if (value) { + await el.type(value, { charByChar: true }); + } } else { await comboBox.clearInputField(metricsIndexPatternInput); - await comboBox.setCustom(metricsIndexPatternInput, value); + if (value) { + await comboBox.setCustom(metricsIndexPatternInput, value); + } } await PageObjects.header.waitUntilLoadingHasFinished(); From ab38dc367fde7f65764e1234655b5986ba1c3ffc Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Tue, 9 Mar 2021 20:07:18 +0300 Subject: [PATCH 18/39] fix CI --- test/functional/apps/visualize/_tsvb_chart.ts | 92 +++++++++---------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/test/functional/apps/visualize/_tsvb_chart.ts b/test/functional/apps/visualize/_tsvb_chart.ts index 512eaec27fa94..fff863053b227 100644 --- a/test/functional/apps/visualize/_tsvb_chart.ts +++ b/test/functional/apps/visualize/_tsvb_chart.ts @@ -106,52 +106,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); }); - describe('switch index patterns', () => { - beforeEach(async () => { - await esArchiver.loadIfNeeded('logstash_functional'); - await esArchiver.loadIfNeeded('index_pattern_without_timefield'); - - await PageObjects.visualBuilder.resetPage(); - await PageObjects.visualBuilder.clickMetric(); - await PageObjects.visualBuilder.checkMetricTabIsPresent(); - await PageObjects.timePicker.setAbsoluteRange( - 'Sep 22, 2019 @ 00:00:00.000', - 'Sep 23, 2019 @ 00:00:00.000' - ); - }); - - after(async () => { - await security.testUser.restoreDefaults(); - await esArchiver.unload('logstash_functional'); - await esArchiver.unload('index_pattern_without_timefield'); - }); - - const switchIndexTest = async (useKibanaIndicies: boolean) => { - await PageObjects.visualBuilder.clickPanelOptions('metric'); - await PageObjects.visualBuilder.setIndexPatternValue('', false); - - const value = await PageObjects.visualBuilder.getMetricValue(); - expect(value).to.eql('0'); - - // Sometimes popovers take some time to appear in Firefox (#71979) - await retry.tryForTime(20000, async () => { - await PageObjects.visualBuilder.setIndexPatternValue('with-timefield', useKibanaIndicies); - await PageObjects.visualBuilder.waitForIndexPatternTimeFieldOptionsLoaded(); - await PageObjects.visualBuilder.selectIndexPatternTimeField('timestamp'); - }); - const newValue = await PageObjects.visualBuilder.getMetricValue(); - expect(newValue).to.eql('1'); - }; - - it('should be able to switch using text mode selection', async () => { - await switchIndexTest(false); - }); - - it('should be able to switch combo box mode selection', async () => { - await switchIndexTest(true); - }); - }); - describe('browser history changes', () => { it('should activate previous/next chart tab and panel config', async () => { await PageObjects.visualBuilder.resetPage(); @@ -227,5 +181,51 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(legendItems3).to.eql(finalLegendItems); }); }); + + describe('switch index patterns', () => { + beforeEach(async () => { + await esArchiver.loadIfNeeded('logstash_functional'); + await esArchiver.loadIfNeeded('index_pattern_without_timefield'); + + await PageObjects.visualBuilder.resetPage(); + await PageObjects.visualBuilder.clickMetric(); + await PageObjects.visualBuilder.checkMetricTabIsPresent(); + await PageObjects.timePicker.setAbsoluteRange( + 'Sep 22, 2019 @ 00:00:00.000', + 'Sep 23, 2019 @ 00:00:00.000' + ); + }); + + after(async () => { + await security.testUser.restoreDefaults(); + await esArchiver.unload('logstash_functional'); + await esArchiver.unload('index_pattern_without_timefield'); + }); + + const switchIndexTest = async (useKibanaIndicies: boolean) => { + await PageObjects.visualBuilder.clickPanelOptions('metric'); + await PageObjects.visualBuilder.setIndexPatternValue('', false); + + const value = await PageObjects.visualBuilder.getMetricValue(); + expect(value).to.eql('0'); + + // Sometimes popovers take some time to appear in Firefox (#71979) + await retry.tryForTime(20000, async () => { + await PageObjects.visualBuilder.setIndexPatternValue('with-timefield', useKibanaIndicies); + await PageObjects.visualBuilder.waitForIndexPatternTimeFieldOptionsLoaded(); + await PageObjects.visualBuilder.selectIndexPatternTimeField('timestamp'); + }); + const newValue = await PageObjects.visualBuilder.getMetricValue(); + expect(newValue).to.eql('1'); + }; + + it('should be able to switch using text mode selection', async () => { + await switchIndexTest(false); + }); + + it('should be able to switch combo box mode selection', async () => { + await switchIndexTest(true); + }); + }); }); } From 357af2f6ddae229bf9325f51fac4bdc5cddbb6a6 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Wed, 10 Mar 2021 11:36:44 +0300 Subject: [PATCH 19/39] correct labels --- .../index_pattern_select/migrate_popover.tsx | 20 +++++++++---------- .../switch_mode_popover.tsx | 5 ++--- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/migrate_popover.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/migrate_popover.tsx index 0436196c2fbff..260e063848095 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/migrate_popover.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/migrate_popover.tsx @@ -21,20 +21,20 @@ import { i18n } from '@kbn/i18n'; import { getCoreStart } from '../../../../services'; import { PopoverProps } from './types'; -const availabilityForMigration = i18n.translate( - 'visTypeTimeseries.indexPatternSelect.migrationPopover.availabilityForMigration', +const switchModeLabel = i18n.translate( + 'visTypeTimeseries.indexPatternSelect.migrationPopover.switchMode', { - defaultMessage: 'Availability for migration', + defaultMessage: 'Switch mode', } ); -const getReadyToMigrateCallOut = (value: PopoverProps['value'], onModeChange: () => void) => ( +const getReadyToSwitchCallOut = (value: PopoverProps['value'], onModeChange: () => void) => ( <>

{value}, }} @@ -60,7 +60,7 @@ const getNoMatchedIndicesCallOut = (

{value}, }} @@ -97,14 +97,14 @@ export const MigrationPopover = ({ value, onModeChange, matchedIndex }: PopoverP ownFocus button={ - {availabilityForMigration} + {switchModeLabel} } isOpen={isPopoverOpen} closePopover={closePopover} > - {availabilityForMigration} - {matchedIndex && getReadyToMigrateCallOut(value, switchMode)} + {switchModeLabel} + {matchedIndex && getReadyToSwitchCallOut(value, switchMode)} {!matchedIndex && getNoMatchedIndicesCallOut(value, navigateToCreateIndexPatterns)} ); diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/switch_mode_popover.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/switch_mode_popover.tsx index 8cf7dca6d176e..3b186af65336b 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/switch_mode_popover.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/switch_mode_popover.tsx @@ -57,8 +57,7 @@ export const SwitchModePopover = ({ onModeChange, useKibanaIndices }: PopoverPro @@ -67,7 +66,7 @@ export const SwitchModePopover = ({ onModeChange, useKibanaIndices }: PopoverPro label={i18n.translate( 'visTypeTimeseries.indexPatternSelect.switchModePopover.useKibanaIndices', { - defaultMessage: 'Use Kibana indices?', + defaultMessage: 'Use only Kibana index patterns', } )} onChange={switchMode} From be8ce17bff6c79342f51f1492b13b5214c2e37ae Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Thu, 11 Mar 2021 13:04:40 +0300 Subject: [PATCH 20/39] fix ci group 12 --- test/functional/apps/visualize/_tsvb_chart.ts | 92 +++++++++---------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/test/functional/apps/visualize/_tsvb_chart.ts b/test/functional/apps/visualize/_tsvb_chart.ts index fff863053b227..0908b7b8ff6bb 100644 --- a/test/functional/apps/visualize/_tsvb_chart.ts +++ b/test/functional/apps/visualize/_tsvb_chart.ts @@ -106,6 +106,52 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); }); + describe('switch index patterns', () => { + before(async () => { + await esArchiver.loadIfNeeded('index_pattern_without_timefield'); + }); + + beforeEach(async () => { + await PageObjects.visualBuilder.resetPage(); + await PageObjects.visualBuilder.clickMetric(); + await PageObjects.visualBuilder.checkMetricTabIsPresent(); + await PageObjects.timePicker.setAbsoluteRange( + 'Sep 22, 2019 @ 00:00:00.000', + 'Sep 23, 2019 @ 00:00:00.000' + ); + }); + + after(async () => { + await security.testUser.restoreDefaults(); + await esArchiver.unload('index_pattern_without_timefield'); + }); + + const switchIndexTest = async (useKibanaIndicies: boolean) => { + await PageObjects.visualBuilder.clickPanelOptions('metric'); + await PageObjects.visualBuilder.setIndexPatternValue('', false); + + const value = await PageObjects.visualBuilder.getMetricValue(); + expect(value).to.eql('0'); + + // Sometimes popovers take some time to appear in Firefox (#71979) + await retry.tryForTime(20000, async () => { + await PageObjects.visualBuilder.setIndexPatternValue('with-timefield', useKibanaIndicies); + await PageObjects.visualBuilder.waitForIndexPatternTimeFieldOptionsLoaded(); + await PageObjects.visualBuilder.selectIndexPatternTimeField('timestamp'); + }); + const newValue = await PageObjects.visualBuilder.getMetricValue(); + expect(newValue).to.eql('1'); + }; + + it('should be able to switch using text mode selection', async () => { + await switchIndexTest(false); + }); + + it('should be able to switch combo box mode selection', async () => { + await switchIndexTest(true); + }); + }); + describe('browser history changes', () => { it('should activate previous/next chart tab and panel config', async () => { await PageObjects.visualBuilder.resetPage(); @@ -181,51 +227,5 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(legendItems3).to.eql(finalLegendItems); }); }); - - describe('switch index patterns', () => { - beforeEach(async () => { - await esArchiver.loadIfNeeded('logstash_functional'); - await esArchiver.loadIfNeeded('index_pattern_without_timefield'); - - await PageObjects.visualBuilder.resetPage(); - await PageObjects.visualBuilder.clickMetric(); - await PageObjects.visualBuilder.checkMetricTabIsPresent(); - await PageObjects.timePicker.setAbsoluteRange( - 'Sep 22, 2019 @ 00:00:00.000', - 'Sep 23, 2019 @ 00:00:00.000' - ); - }); - - after(async () => { - await security.testUser.restoreDefaults(); - await esArchiver.unload('logstash_functional'); - await esArchiver.unload('index_pattern_without_timefield'); - }); - - const switchIndexTest = async (useKibanaIndicies: boolean) => { - await PageObjects.visualBuilder.clickPanelOptions('metric'); - await PageObjects.visualBuilder.setIndexPatternValue('', false); - - const value = await PageObjects.visualBuilder.getMetricValue(); - expect(value).to.eql('0'); - - // Sometimes popovers take some time to appear in Firefox (#71979) - await retry.tryForTime(20000, async () => { - await PageObjects.visualBuilder.setIndexPatternValue('with-timefield', useKibanaIndicies); - await PageObjects.visualBuilder.waitForIndexPatternTimeFieldOptionsLoaded(); - await PageObjects.visualBuilder.selectIndexPatternTimeField('timestamp'); - }); - const newValue = await PageObjects.visualBuilder.getMetricValue(); - expect(newValue).to.eql('1'); - }; - - it('should be able to switch using text mode selection', async () => { - await switchIndexTest(false); - }); - - it('should be able to switch combo box mode selection', async () => { - await switchIndexTest(true); - }); - }); }); } From 204b652e463a83a800c6e6058a0f70af28cfc09d Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Thu, 11 Mar 2021 15:54:43 +0300 Subject: [PATCH 21/39] cleanup interface --- .../server/lib/get_fields.ts | 6 +-- .../search_strategies_registry.test.ts | 8 ++-- .../search_strategy_registry.ts | 27 ++---------- .../abstract_search_strategy.test.ts | 42 +++---------------- .../strategies/abstract_search_strategy.ts | 22 ++++------ .../default_search_strategy.test.ts | 4 +- .../strategies/default_search_strategy.ts | 6 +-- .../strategies/rollup_search_strategy.test.ts | 14 +++---- .../strategies/rollup_search_strategy.ts | 30 +++++++------ .../server/lib/vis_data/get_series_data.ts | 18 ++++++-- .../server/lib/vis_data/get_table_data.ts | 6 ++- .../lib/vis_data/helpers/fields_fetcher.ts | 13 +++--- .../vis_type_timeseries/server/plugin.ts | 4 +- 13 files changed, 77 insertions(+), 123 deletions(-) diff --git a/src/plugins/vis_type_timeseries/server/lib/get_fields.ts b/src/plugins/vis_type_timeseries/server/lib/get_fields.ts index f1bc5a11550e9..45af424f827b6 100644 --- a/src/plugins/vis_type_timeseries/server/lib/get_fields.ts +++ b/src/plugins/vis_type_timeseries/server/lib/get_fields.ts @@ -17,8 +17,9 @@ export async function getFields( framework: Framework, indexPatternString: string ) { + const indexPatternsService = await framework.getIndexPatternsService(requestContext); + if (!indexPatternString) { - const indexPatternsService = await framework.getIndexPatternsService(requestContext); const defaultIndexPattern = await indexPatternsService.getDefault(); indexPatternString = defaultIndexPattern?.title ?? ''; @@ -34,9 +35,8 @@ export async function getFields( ))!; const fields = await searchStrategy.getFieldsForWildcard( - requestContext, - request, indexPatternString, + indexPatternsService, capabilities ); diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_strategies_registry.test.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_strategies_registry.test.ts index f9a49bc322a29..d47bab848835e 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_strategies_registry.test.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_strategies_registry.test.ts @@ -10,7 +10,6 @@ import { get } from 'lodash'; import { SearchStrategyRegistry } from './search_strategy_registry'; import { AbstractSearchStrategy, DefaultSearchStrategy } from './strategies'; import { DefaultSearchCapabilities } from './capabilities/default_search_capabilities'; -import { Framework } from '../../plugin'; import { VisTypeTimeseriesRequest, VisTypeTimeseriesRequestHandlerContext } from '../../types'; const getPrivateField = (registry: SearchStrategyRegistry, field: string) => @@ -26,13 +25,12 @@ class MockSearchStrategy extends AbstractSearchStrategy { } describe('SearchStrategyRegister', () => { - const framework = {} as Framework; const requestContext = {} as VisTypeTimeseriesRequestHandlerContext; let registry: SearchStrategyRegistry; beforeAll(() => { registry = new SearchStrategyRegistry(); - registry.addStrategy(new DefaultSearchStrategy(framework)); + registry.addStrategy(new DefaultSearchStrategy()); }); test('should init strategies register', () => { @@ -60,7 +58,7 @@ describe('SearchStrategyRegister', () => { }); test('should add a strategy if it is an instance of AbstractSearchStrategy', () => { - const anotherSearchStrategy = new MockSearchStrategy(framework); + const anotherSearchStrategy = new MockSearchStrategy(); const addedStrategies = registry.addStrategy(anotherSearchStrategy); expect(addedStrategies.length).toEqual(2); @@ -70,7 +68,7 @@ describe('SearchStrategyRegister', () => { test('should return a MockSearchStrategy instance', async () => { const req = {} as VisTypeTimeseriesRequest; const indexPattern = '*'; - const anotherSearchStrategy = new MockSearchStrategy(framework); + const anotherSearchStrategy = new MockSearchStrategy(); registry.addStrategy(anotherSearchStrategy); const { searchStrategy, capabilities } = (await registry.getViableStrategy( diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_strategy_registry.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_strategy_registry.ts index 424eeae3898a3..8a0278f3942f1 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_strategy_registry.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_strategy_registry.ts @@ -6,17 +6,10 @@ * Side Public License, v 1. */ -import { - extractIndexPatterns, - convertIndexPatternObjectToStringRepresentation, -} from '../../../common/index_patterns_utils'; -import { PanelSchema } from '../../../common/types'; -import { - VisTypeTimeseriesRequest, - VisTypeTimeseriesRequestHandlerContext, - VisTypeTimeseriesVisDataRequest, -} from '../../types'; +import { VisTypeTimeseriesRequest, VisTypeTimeseriesRequestHandlerContext } from '../../types'; import { AbstractSearchStrategy } from './strategies'; +import { IndexPatternObject } from '../../../common/types'; + export class SearchStrategyRegistry { private strategies: AbstractSearchStrategy[] = []; @@ -30,7 +23,7 @@ export class SearchStrategyRegistry { async getViableStrategy( requestContext: VisTypeTimeseriesRequestHandlerContext, req: VisTypeTimeseriesRequest, - indexPattern: string + indexPattern: string | IndexPatternObject ) { for (const searchStrategy of this.strategies) { const { isViable, capabilities } = await searchStrategy.checkForViability( @@ -47,16 +40,4 @@ export class SearchStrategyRegistry { } } } - - async getViableStrategyForPanel( - requestContext: VisTypeTimeseriesRequestHandlerContext, - req: VisTypeTimeseriesVisDataRequest, - panel: PanelSchema - ) { - const indexPattern = extractIndexPatterns(panel, panel.default_index_pattern) - .map(convertIndexPatternObjectToStringRepresentation) - .join(','); - - return this.getViableStrategy(requestContext, req, indexPattern); - } } diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.test.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.test.ts index e7282eba58ec7..ae7295184a2b5 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.test.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.test.ts @@ -6,28 +6,16 @@ * Side Public License, v 1. */ -const mockGetFieldsForWildcard = jest.fn(() => []); - -jest.mock('../../../../../data/server', () => ({ - indexPatterns: { - isNestedField: jest.fn(() => false), - }, - IndexPatternsFetcher: jest.fn().mockImplementation(() => ({ - getFieldsForWildcard: mockGetFieldsForWildcard, - })), -})); +import { IndexPatternsService } from '../../../../../data/common'; import { from } from 'rxjs'; import { AbstractSearchStrategy, toSanitizedFieldType } from './abstract_search_strategy'; import type { IFieldType } from '../../../../../data/common'; import type { FieldSpec, RuntimeField } from '../../../../../data/common'; import { - VisTypeTimeseriesRequest, VisTypeTimeseriesRequestHandlerContext, VisTypeTimeseriesVisDataRequest, } from '../../../types'; -import { Framework } from '../../../plugin'; -import { indexPatterns } from '../../../../../data/server'; class FooSearchStrategy extends AbstractSearchStrategy {} @@ -36,18 +24,9 @@ describe('AbstractSearchStrategy', () => { let mockedFields: IFieldType[]; let indexPattern: string; let requestContext: VisTypeTimeseriesRequestHandlerContext; - let framework: Framework; beforeEach(() => { mockedFields = []; - framework = ({ - getIndexPatternsService: jest.fn(() => - Promise.resolve({ - find: jest.fn(() => []), - getDefault: jest.fn(() => {}), - }) - ), - } as unknown) as Framework; requestContext = ({ core: { elasticsearch: { @@ -60,7 +39,7 @@ describe('AbstractSearchStrategy', () => { search: jest.fn().mockReturnValue(from(Promise.resolve({}))), }, } as unknown) as VisTypeTimeseriesRequestHandlerContext; - abstractSearchStrategy = new FooSearchStrategy(framework); + abstractSearchStrategy = new FooSearchStrategy(); }); test('should init an AbstractSearchStrategy instance', () => { @@ -70,18 +49,12 @@ describe('AbstractSearchStrategy', () => { }); test('should return fields for wildcard', async () => { - const fields = await abstractSearchStrategy.getFieldsForWildcard( - requestContext, - {} as VisTypeTimeseriesRequest, - indexPattern - ); + const fields = await abstractSearchStrategy.getFieldsForWildcard(indexPattern, ({ + getDefault: jest.fn(), + getFieldsForWildcard: jest.fn(() => Promise.resolve(mockedFields)), + } as unknown) as IndexPatternsService); expect(fields).toEqual(mockedFields); - expect(mockGetFieldsForWildcard).toHaveBeenCalledWith({ - pattern: indexPattern, - metaFields: [], - fieldCapsOptions: { allow_no_indices: true }, - }); }); test('should return response', async () => { @@ -175,9 +148,6 @@ describe('AbstractSearchStrategy', () => { }, }, ]; - // @ts-expect-error - indexPatterns.isNestedField.mockReturnValue(true); - expect(toSanitizedFieldType(fields)).toMatchInlineSnapshot(`Array []`); }); }); diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts index 5bc008091627f..ca5ad1c693808 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts @@ -6,11 +6,10 @@ * Side Public License, v 1. */ -import { indexPatterns, IndexPatternsFetcher } from '../../../../../data/server'; +import { indexPatterns, IndexPatternsService } from '../../../../../data/server'; -import type { Framework } from '../../../plugin'; import type { FieldSpec } from '../../../../../data/common'; -import type { SanitizedFieldType } from '../../../../common/types'; +import type { IndexPatternObject, SanitizedFieldType } from '../../../../common/types'; import type { VisTypeTimeseriesRequest, VisTypeTimeseriesRequestHandlerContext, @@ -36,7 +35,6 @@ export const toSanitizedFieldType = (fields: FieldSpec[]) => { }; export abstract class AbstractSearchStrategy { - constructor(private framework: Framework) {} async search( requestContext: VisTypeTimeseriesRequestHandlerContext, req: VisTypeTimeseriesVisDataRequest, @@ -66,35 +64,29 @@ export abstract class AbstractSearchStrategy { checkForViability( requestContext: VisTypeTimeseriesRequestHandlerContext, req: VisTypeTimeseriesRequest, - indexPattern: string + indexPattern: string | IndexPatternObject ): Promise<{ isViable: boolean; capabilities: any }> { throw new TypeError('Must override method'); } async getFieldsForWildcard( - requestContext: VisTypeTimeseriesRequestHandlerContext, - req: VisTypeTimeseriesRequest, indexPattern: string, + indexPatternsService: IndexPatternsService, capabilities?: unknown, options?: Partial<{ type: string; rollupIndex: string; }> ) { - const indexPatternsFetcher = new IndexPatternsFetcher( - requestContext.core.elasticsearch.client.asCurrentUser - ); - const indexPatternsService = await this.framework.getIndexPatternsService(requestContext); - const { indexPatternObject } = await getIndexPatternObject(indexPattern, { + const { indexPatternObject, indexPatternString } = await getIndexPatternObject(indexPattern, { indexPatternsService, }); return toSanitizedFieldType( indexPatternObject ? indexPatternObject.getNonScriptedFields() - : await indexPatternsFetcher!.getFieldsForWildcard({ - pattern: indexPattern, - fieldCapsOptions: { allow_no_indices: true }, + : await indexPatternsService.getFieldsForWildcard({ + pattern: indexPatternString, metaFields: [], ...options, }) diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/default_search_strategy.test.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/default_search_strategy.test.ts index b9824355374e1..d7a4e6ddedc89 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/default_search_strategy.test.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/default_search_strategy.test.ts @@ -6,7 +6,6 @@ * Side Public License, v 1. */ -import { Framework } from '../../../plugin'; import { VisTypeTimeseriesRequestHandlerContext, VisTypeTimeseriesVisDataRequest, @@ -14,14 +13,13 @@ import { import { DefaultSearchStrategy } from './default_search_strategy'; describe('DefaultSearchStrategy', () => { - const framework = {} as Framework; const requestContext = {} as VisTypeTimeseriesRequestHandlerContext; let defaultSearchStrategy: DefaultSearchStrategy; let req: VisTypeTimeseriesVisDataRequest; beforeEach(() => { req = {} as VisTypeTimeseriesVisDataRequest; - defaultSearchStrategy = new DefaultSearchStrategy(framework); + defaultSearchStrategy = new DefaultSearchStrategy(); }); test('should init an DefaultSearchStrategy instance', () => { diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/default_search_strategy.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/default_search_strategy.ts index c925d8fcbb7c3..d7ded7d107ca9 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/default_search_strategy.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/default_search_strategy.ts @@ -9,6 +9,7 @@ import { AbstractSearchStrategy } from './abstract_search_strategy'; import { DefaultSearchCapabilities } from '../capabilities/default_search_capabilities'; import { VisTypeTimeseriesRequestHandlerContext, VisTypeTimeseriesRequest } from '../../../types'; +import { IndexPatternsService } from '../../../../../data/server'; export class DefaultSearchStrategy extends AbstractSearchStrategy { checkForViability( @@ -22,11 +23,10 @@ export class DefaultSearchStrategy extends AbstractSearchStrategy { } async getFieldsForWildcard( - requestContext: VisTypeTimeseriesRequestHandlerContext, - req: VisTypeTimeseriesRequest, indexPattern: string, + indexPatternsService: IndexPatternsService, capabilities?: unknown ) { - return super.getFieldsForWildcard(requestContext, req, indexPattern, capabilities); + return super.getFieldsForWildcard(indexPattern, indexPatternsService, capabilities); } } diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.test.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.test.ts index 403013cfb9e10..bd3e846919485 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.test.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.test.ts @@ -7,11 +7,11 @@ */ import { RollupSearchStrategy } from './rollup_search_strategy'; -import { Framework } from '../../../plugin'; import { VisTypeTimeseriesRequestHandlerContext, VisTypeTimeseriesVisDataRequest, } from '../../../types'; +import { IndexPatternsService } from '../../../../../data/common'; jest.mock('./abstract_search_strategy', () => { class AbstractSearchStrategyMock { @@ -49,12 +49,11 @@ describe('Rollup Search Strategy', () => { }, }, } as unknown) as VisTypeTimeseriesRequestHandlerContext; - const framework = {} as Framework; const indexPattern = 'indexPattern'; test('should create instance of RollupSearchRequest', () => { - const rollupSearchStrategy = new RollupSearchStrategy(framework); + const rollupSearchStrategy = new RollupSearchStrategy(); expect(rollupSearchStrategy).toBeDefined(); }); @@ -64,7 +63,7 @@ describe('Rollup Search Strategy', () => { const rollupIndex = 'rollupIndex'; beforeEach(() => { - rollupSearchStrategy = new RollupSearchStrategy(framework); + rollupSearchStrategy = new RollupSearchStrategy(); rollupSearchStrategy.getRollupData = jest.fn(() => Promise.resolve({ [rollupIndex]: { @@ -113,7 +112,7 @@ describe('Rollup Search Strategy', () => { let rollupSearchStrategy: RollupSearchStrategy; beforeEach(() => { - rollupSearchStrategy = new RollupSearchStrategy(framework); + rollupSearchStrategy = new RollupSearchStrategy(); }); test('should return rollup data', async () => { @@ -140,7 +139,7 @@ describe('Rollup Search Strategy', () => { const rollupIndex = 'rollupIndex'; beforeEach(() => { - rollupSearchStrategy = new RollupSearchStrategy(framework); + rollupSearchStrategy = new RollupSearchStrategy(); fieldsCapabilities = { [rollupIndex]: { aggs: { @@ -154,9 +153,8 @@ describe('Rollup Search Strategy', () => { test('should return fields for wildcard', async () => { const fields = await rollupSearchStrategy.getFieldsForWildcard( - requestContext, - {} as VisTypeTimeseriesVisDataRequest, indexPattern, + {} as IndexPatternsService, { fieldsCapabilities, rollupIndex, diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.ts index 376d551624c8a..d4bf04eb268c3 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { getCapabilitiesForRollupIndices } from '../../../../../data/server'; +import { getCapabilitiesForRollupIndices, IndexPatternsService } from '../../../../../data/server'; import { VisTypeTimeseriesRequest, VisTypeTimeseriesRequestHandlerContext, @@ -14,6 +14,7 @@ import { } from '../../../types'; import { AbstractSearchStrategy } from './abstract_search_strategy'; import { RollupSearchCapabilities } from '../capabilities/rollup_search_capabilities'; +import { IndexPatternObject } from '../../../../common/types'; const getRollupIndices = (rollupData: { [key: string]: any }) => Object.keys(rollupData); const isIndexPatternContainsWildcard = (indexPattern: string) => indexPattern.includes('*'); @@ -33,24 +34,30 @@ export class RollupSearchStrategy extends AbstractSearchStrategy { requestContext: VisTypeTimeseriesRequestHandlerContext, indexPattern: string ) { - return requestContext.core.elasticsearch.client.asCurrentUser.rollup - .getRollupIndexCaps({ + try { + const { getRollupIndexCaps } = requestContext.core.elasticsearch.client.asCurrentUser.rollup; + const { body } = await getRollupIndexCaps({ index: indexPattern, - }) - .then((data) => data.body) - .catch(() => Promise.resolve({})); + }); + + return body; + } catch (e) { + return {}; + } } async checkForViability( requestContext: VisTypeTimeseriesRequestHandlerContext, req: VisTypeTimeseriesRequest, - indexPattern: string + indexPattern: string | IndexPatternObject ) { let isViable = false; let capabilities = null; - if (isIndexPatternValid(indexPattern)) { - const rollupData = await this.getRollupData(requestContext, indexPattern); + const index = typeof indexPattern === 'string' ? indexPattern : indexPattern?.title ?? ''; + + if (isIndexPatternValid(index)) { + const rollupData = await this.getRollupData(requestContext, index); const rollupIndices = getRollupIndices(rollupData); isViable = rollupIndices.length === 1; @@ -70,12 +77,11 @@ export class RollupSearchStrategy extends AbstractSearchStrategy { } async getFieldsForWildcard( - requestContext: VisTypeTimeseriesRequestHandlerContext, - req: VisTypeTimeseriesRequest, indexPattern: string, + indexPatternsService: IndexPatternsService, capabilities?: unknown ) { - return super.getFieldsForWildcard(requestContext, req, indexPattern, capabilities, { + return super.getFieldsForWildcard(indexPattern, indexPatternsService, capabilities, { type: 'rollup', rollupIndex: indexPattern, }); diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/get_series_data.ts b/src/plugins/vis_type_timeseries/server/lib/vis_data/get_series_data.ts index f521de632b1f8..efe9777f48a4f 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/get_series_data.ts +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/get_series_data.ts @@ -21,6 +21,12 @@ import type { VisTypeTimeseriesRequestServices, } from '../../types'; import type { PanelSchema } from '../../../common/types'; +import { PANEL_TYPES } from '../../../common/panel_types'; + +import { + convertIndexPatternObjectToStringRepresentation, + extractIndexPatterns, +} from '../../../common/index_patterns_utils'; export async function getSeriesData( requestContext: VisTypeTimeseriesRequestHandlerContext, @@ -28,10 +34,14 @@ export async function getSeriesData( panel: PanelSchema, services: VisTypeTimeseriesRequestServices ) { - const strategy = await services.searchStrategyRegistry.getViableStrategyForPanel( + const indexPattern = extractIndexPatterns(panel, panel.default_index_pattern) + .map(convertIndexPatternObjectToStringRepresentation) + .join(','); + + const strategy = await services.searchStrategyRegistry.getViableStrategy( requestContext, req, - panel + indexPattern ); if (!strategy) { @@ -57,7 +67,7 @@ export async function getSeriesData( const data = await searchStrategy.search(requestContext, req, searches); const handleResponseBodyFn = handleResponseBody(panel, req, { - requestContext, + indexPatternsService: services.indexPatternsService, searchStrategy, capabilities, }); @@ -70,7 +80,7 @@ export async function getSeriesData( let annotations = null; - if (panel.annotations && panel.annotations.length) { + if (panel.type === PANEL_TYPES.TIMESERIES && panel.annotations && panel.annotations.length) { annotations = await getAnnotations({ req, panel, diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/get_table_data.ts b/src/plugins/vis_type_timeseries/server/lib/vis_data/get_table_data.ts index efab5e4497d58..44a78de6ced1b 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/get_table_data.ts +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/get_table_data.ts @@ -55,7 +55,11 @@ export async function getTableData( const { searchStrategy, capabilities } = strategy; - const extractFields = createFieldsFetcher(req, { requestContext, searchStrategy, capabilities }); + const extractFields = createFieldsFetcher(req, { + indexPatternsService: services.indexPatternsService, + searchStrategy, + capabilities, + }); const calculatePivotLabel = async () => { if (panel.pivot_id && indexPatternObject?.title) { diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/fields_fetcher.ts b/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/fields_fetcher.ts index f95667612efa4..936997527606c 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/fields_fetcher.ts +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/fields_fetcher.ts @@ -6,21 +6,19 @@ * Side Public License, v 1. */ -import { - VisTypeTimeseriesRequestHandlerContext, - VisTypeTimeseriesVisDataRequest, -} from '../../../types'; +import { VisTypeTimeseriesVisDataRequest } from '../../../types'; import { AbstractSearchStrategy, DefaultSearchCapabilities } from '../../search_strategies'; +import { IndexPatternsService } from '../../../../../data/common'; export interface FieldsFetcherServices { - requestContext: VisTypeTimeseriesRequestHandlerContext; + indexPatternsService: IndexPatternsService; searchStrategy: AbstractSearchStrategy; capabilities: DefaultSearchCapabilities; } export const createFieldsFetcher = ( req: VisTypeTimeseriesVisDataRequest, - { capabilities, requestContext, searchStrategy }: FieldsFetcherServices + { capabilities, indexPatternsService, searchStrategy }: FieldsFetcherServices ) => { const fieldsCacheMap = new Map(); @@ -30,9 +28,8 @@ export const createFieldsFetcher = ( } const fields = await searchStrategy.getFieldsForWildcard( - requestContext, - req, index, + indexPatternsService, capabilities ); diff --git a/src/plugins/vis_type_timeseries/server/plugin.ts b/src/plugins/vis_type_timeseries/server/plugin.ts index 71b76dddbca6a..95fdc59ceb232 100644 --- a/src/plugins/vis_type_timeseries/server/plugin.ts +++ b/src/plugins/vis_type_timeseries/server/plugin.ts @@ -111,8 +111,8 @@ export class VisTypeTimeseriesPlugin implements Plugin { }, }; - searchStrategyRegistry.addStrategy(new DefaultSearchStrategy(framework)); - searchStrategyRegistry.addStrategy(new RollupSearchStrategy(framework)); + searchStrategyRegistry.addStrategy(new DefaultSearchStrategy()); + searchStrategyRegistry.addStrategy(new RollupSearchStrategy()); visDataRoutes(router, framework); fieldsRoutes(router, framework); From e290edf92617b8a9352e60101143c6cacbfc02ec Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Fri, 12 Mar 2021 15:52:35 +0300 Subject: [PATCH 22/39] fix CI --- .../search_strategies/strategies/rollup_search_strategy.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.ts index d4bf04eb268c3..c4e91e8a85ea7 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.ts @@ -35,8 +35,9 @@ export class RollupSearchStrategy extends AbstractSearchStrategy { indexPattern: string ) { try { - const { getRollupIndexCaps } = requestContext.core.elasticsearch.client.asCurrentUser.rollup; - const { body } = await getRollupIndexCaps({ + const { + body, + } = await requestContext.core.elasticsearch.client.asCurrentUser.rollup.getRollupIndexCaps({ index: indexPattern, }); From 6823b85831fe441f3990cd8f3e3e255c1e6cb616 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Fri, 12 Mar 2021 17:39:11 +0300 Subject: [PATCH 23/39] cleanup API --- .../server/lib/get_fields.ts | 3 + .../server/lib/get_vis_data.ts | 3 + .../lib/get_index_pattern.test.ts | 40 +++++----- .../lib/get_index_pattern.ts | 73 +++++++++++-------- .../search_strategies_registry.test.ts | 6 +- .../search_strategy_registry.ts | 4 +- .../abstract_search_strategy.test.ts | 13 +++- .../strategies/abstract_search_strategy.ts | 17 +++-- .../strategies/default_search_strategy.ts | 9 ++- .../strategies/rollup_search_strategy.test.ts | 2 + .../strategies/rollup_search_strategy.ts | 23 ++++-- .../annotations/get_request_params.ts | 12 ++- .../vis_data/get_interval_and_timefield.js | 4 +- .../server/lib/vis_data/get_series_data.ts | 1 + .../server/lib/vis_data/get_table_data.ts | 16 ++-- .../lib/vis_data/helpers/fields_fetcher.ts | 10 ++- .../annotations/date_histogram.js | 2 +- .../series/date_histogram.js | 10 +-- .../series/date_histogram.test.js | 26 +++---- .../series/filter_ratios.js | 6 +- .../series/filter_ratios.test.js | 10 +-- .../series/metric_buckets.js | 4 +- .../series/positive_rate.js | 4 +- .../request_processors/series/query.js | 10 +-- .../series/sibling_buckets.js | 4 +- .../table/date_histogram.js | 13 +--- .../request_processors/table/filter_ratios.js | 6 +- .../table/metric_buckets.js | 11 +-- .../request_processors/table/positive_rate.js | 11 +-- .../request_processors/table/query.js | 8 +- .../table/sibling_buckets.js | 11 +-- .../series/build_request_body.test.ts | 4 +- .../lib/vis_data/series/get_request_params.ts | 14 ++-- .../vis_type_timeseries/server/types.ts | 6 +- 34 files changed, 203 insertions(+), 193 deletions(-) diff --git a/src/plugins/vis_type_timeseries/server/lib/get_fields.ts b/src/plugins/vis_type_timeseries/server/lib/get_fields.ts index 45af424f827b6..055a20a308890 100644 --- a/src/plugins/vis_type_timeseries/server/lib/get_fields.ts +++ b/src/plugins/vis_type_timeseries/server/lib/get_fields.ts @@ -10,6 +10,7 @@ import { uniqBy } from 'lodash'; import { Framework } from '../plugin'; import { VisTypeTimeseriesFieldsRequest, VisTypeTimeseriesRequestHandlerContext } from '../types'; +import { getCachedIndexPatternFetcher } from './search_strategies/lib/get_index_pattern'; export async function getFields( requestContext: VisTypeTimeseriesRequestHandlerContext, @@ -18,6 +19,7 @@ export async function getFields( indexPatternString: string ) { const indexPatternsService = await framework.getIndexPatternsService(requestContext); + const cachedIndexPatternFetcher = getCachedIndexPatternFetcher(indexPatternsService); if (!indexPatternString) { const defaultIndexPattern = await indexPatternsService.getDefault(); @@ -37,6 +39,7 @@ export async function getFields( const fields = await searchStrategy.getFieldsForWildcard( indexPatternString, indexPatternsService, + cachedIndexPatternFetcher, capabilities ); diff --git a/src/plugins/vis_type_timeseries/server/lib/get_vis_data.ts b/src/plugins/vis_type_timeseries/server/lib/get_vis_data.ts index 0ad50a296b481..f0623e3bce6a4 100644 --- a/src/plugins/vis_type_timeseries/server/lib/get_vis_data.ts +++ b/src/plugins/vis_type_timeseries/server/lib/get_vis_data.ts @@ -19,6 +19,7 @@ import type { import { getSeriesData } from './vis_data/get_series_data'; import { getTableData } from './vis_data/get_table_data'; import { getEsQueryConfig } from './vis_data/helpers/get_es_query_uisettings'; +import { getCachedIndexPatternFetcher } from './search_strategies/lib/get_index_pattern'; export async function getVisData( requestContext: VisTypeTimeseriesRequestHandlerContext, @@ -29,12 +30,14 @@ export async function getVisData( const esShardTimeout = await framework.getEsShardTimeout(); const indexPatternsService = await framework.getIndexPatternsService(requestContext); const esQueryConfig = await getEsQueryConfig(uiSettings); + const services: VisTypeTimeseriesRequestServices = { esQueryConfig, esShardTimeout, indexPatternsService, uiSettings, searchStrategyRegistry: framework.searchStrategyRegistry, + cachedIndexPatternFetcher: getCachedIndexPatternFetcher(indexPatternsService), }; const promises = request.body.panels.map((panel) => { diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/get_index_pattern.test.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/get_index_pattern.test.ts index 5a3d9aaf7c663..7ac894345c4c4 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/get_index_pattern.test.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/get_index_pattern.test.ts @@ -7,26 +7,29 @@ */ import { IndexPattern, IndexPatternsService } from 'src/plugins/data/server'; -import { getIndexPatternObject } from './get_index_pattern'; +import { getCachedIndexPatternFetcher, CachedIndexPatternFetcher } from './get_index_pattern'; describe('getIndexPatternObject', () => { let mockedIndices: IndexPattern[] | []; - - const indexPatternsService = ({ - getDefault: jest.fn(() => Promise.resolve({ id: 'default', title: 'index' })), - get: jest.fn(() => Promise.resolve(mockedIndices[0])), - find: jest.fn(() => Promise.resolve(mockedIndices || [])), - } as unknown) as IndexPatternsService; + let cachedIndexPatternFetcher: CachedIndexPatternFetcher; beforeEach(() => { mockedIndices = []; + + const indexPatternsService = ({ + getDefault: jest.fn(() => Promise.resolve({ id: 'default', title: 'index' })), + get: jest.fn(() => Promise.resolve(mockedIndices[0])), + find: jest.fn(() => Promise.resolve(mockedIndices || [])), + } as unknown) as IndexPatternsService; + + cachedIndexPatternFetcher = getCachedIndexPatternFetcher(indexPatternsService); }); test('should return default index on no input value', async () => { - const value = await getIndexPatternObject('', { indexPatternsService }); + const value = await cachedIndexPatternFetcher(''); expect(value).toMatchInlineSnapshot(` Object { - "indexPatternObject": Object { + "indexPattern": Object { "id": "default", "title": "index", }, @@ -44,11 +47,11 @@ describe('getIndexPatternObject', () => { }, ] as IndexPattern[]; - const value = await getIndexPatternObject('indexTitle', { indexPatternsService }); + const value = await cachedIndexPatternFetcher('indexTitle'); expect(value).toMatchInlineSnapshot(` Object { - "indexPatternObject": Object { + "indexPattern": Object { "id": "indexId", "title": "indexTitle", }, @@ -58,11 +61,11 @@ describe('getIndexPatternObject', () => { }); test('should return only indexPatternString if Kibana index does not exist', async () => { - const value = await getIndexPatternObject('indexTitle', { indexPatternsService }); + const value = await cachedIndexPatternFetcher('indexTitle'); expect(value).toMatchInlineSnapshot(` Object { - "indexPatternObject": undefined, + "indexPattern": undefined, "indexPatternString": "indexTitle", } `); @@ -78,11 +81,11 @@ describe('getIndexPatternObject', () => { }, ] as IndexPattern[]; - const value = await getIndexPatternObject({ id: 'indexId' }, { indexPatternsService }); + const value = await cachedIndexPatternFetcher({ id: 'indexId' }); expect(value).toMatchInlineSnapshot(` Object { - "indexPatternObject": Object { + "indexPattern": Object { "id": "indexId", "title": "indexTitle", }, @@ -92,14 +95,11 @@ describe('getIndexPatternObject', () => { }); test('should return default index if Kibana index not found', async () => { - const value = await getIndexPatternObject( - { id: 'indexId', title: 'title' }, - { indexPatternsService } - ); + const value = await cachedIndexPatternFetcher({ id: 'indexId', title: 'title' }); expect(value).toMatchInlineSnapshot(` Object { - "indexPatternObject": Object { + "indexPattern": Object { "id": "default", "title": "index", }, diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/get_index_pattern.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/get_index_pattern.ts index e3b86f44d30a9..8674df44baac1 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/get_index_pattern.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/get_index_pattern.ts @@ -8,38 +8,53 @@ import { IndexPatternsService, IndexPattern } from '../../../../../data/server'; import { IndexPatternObject } from '../../../../common/types'; +import { convertIndexPatternObjectToStringRepresentation } from '../../../../common/index_patterns_utils'; -interface IndexPatternObjectDependencies { - indexPatternsService: IndexPatternsService; +interface ParsedIndexPattern { + indexPattern: IndexPattern | undefined | null; + indexPatternString: string; } -export async function getIndexPatternObject( - indexPattern: IndexPatternObject, - { indexPatternsService }: IndexPatternObjectDependencies -) { - let indexPatternObject: IndexPattern | undefined | null; - let indexPatternString: string = ''; - - const getIndexPatternFromString = async (v: string) => - (await indexPatternsService.find(v)).find((index) => index.title === indexPattern); - - if (!indexPattern) { - indexPatternObject = await indexPatternsService.getDefault(); - } else { - if (typeof indexPattern === 'string') { - indexPatternObject = await getIndexPatternFromString(indexPattern); - - if (!indexPatternObject) { - indexPatternString = indexPattern; + +export const getCachedIndexPatternFetcher = (indexPatternsService: IndexPatternsService) => { + const cache = new Map(); + + return async (indexPatternObject: IndexPatternObject): Promise => { + const key = convertIndexPatternObjectToStringRepresentation(indexPatternObject); + + if (cache.has(key)) { + return cache.get(key); + } + + let indexPattern: ParsedIndexPattern['indexPattern']; + let indexPatternString: string = ''; + + if (!indexPatternObject) { + indexPattern = await indexPatternsService.getDefault(); + } else { + if (typeof indexPatternObject === 'string') { + indexPattern = (await indexPatternsService.find(indexPatternObject)).find( + (index) => index.title === indexPatternObject + ); + + if (!indexPattern) { + indexPatternString = indexPatternObject; + } + } else if (indexPatternObject.id) { + indexPattern = + (await indexPatternsService.get(indexPatternObject.id)) ?? + (await indexPatternsService.getDefault()); } - } else if (indexPattern.id) { - indexPatternObject = - (await indexPatternsService.get(indexPattern.id)) ?? - (await indexPatternsService.getDefault()); } - } - return { - indexPatternObject, - indexPatternString: indexPatternObject?.title ?? indexPatternString, + const returnObject = { + indexPattern, + indexPatternString: indexPattern?.title ?? indexPatternString, + }; + + cache.set(indexPatternObject, returnObject); + + return returnObject; }; -} +}; + +export type CachedIndexPatternFetcher = ReturnType; diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_strategies_registry.test.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_strategies_registry.test.ts index d47bab848835e..7b3e6a2888431 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_strategies_registry.test.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_strategies_registry.test.ts @@ -16,11 +16,11 @@ const getPrivateField = (registry: SearchStrategyRegistry, field: string) => get(registry, field) as T; class MockSearchStrategy extends AbstractSearchStrategy { - checkForViability() { - return Promise.resolve({ + async checkForViability() { + return { isViable: true, capabilities: {}, - }); + }; } } diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_strategy_registry.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_strategy_registry.ts index 8a0278f3942f1..6445b3099a8cb 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_strategy_registry.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_strategy_registry.ts @@ -23,13 +23,13 @@ export class SearchStrategyRegistry { async getViableStrategy( requestContext: VisTypeTimeseriesRequestHandlerContext, req: VisTypeTimeseriesRequest, - indexPattern: string | IndexPatternObject + indexPatternObject: IndexPatternObject ) { for (const searchStrategy of this.strategies) { const { isViable, capabilities } = await searchStrategy.checkForViability( requestContext, req, - indexPattern + indexPatternObject ); if (isViable) { diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.test.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.test.ts index ae7295184a2b5..efced5e3182e9 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.test.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.test.ts @@ -16,6 +16,7 @@ import { VisTypeTimeseriesRequestHandlerContext, VisTypeTimeseriesVisDataRequest, } from '../../../types'; +import { CachedIndexPatternFetcher } from '../lib/get_index_pattern'; class FooSearchStrategy extends AbstractSearchStrategy {} @@ -49,10 +50,14 @@ describe('AbstractSearchStrategy', () => { }); test('should return fields for wildcard', async () => { - const fields = await abstractSearchStrategy.getFieldsForWildcard(indexPattern, ({ - getDefault: jest.fn(), - getFieldsForWildcard: jest.fn(() => Promise.resolve(mockedFields)), - } as unknown) as IndexPatternsService); + const fields = await abstractSearchStrategy.getFieldsForWildcard( + indexPattern, + ({ + getDefault: jest.fn(), + getFieldsForWildcard: jest.fn(() => Promise.resolve(mockedFields)), + } as unknown) as IndexPatternsService, + (() => Promise.resolve({}) as unknown) as CachedIndexPatternFetcher + ); expect(fields).toEqual(mockedFields); }); diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts index ca5ad1c693808..b844337f4d46a 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts @@ -15,7 +15,7 @@ import type { VisTypeTimeseriesRequestHandlerContext, VisTypeTimeseriesVisDataRequest, } from '../../../types'; -import { getIndexPatternObject } from '../lib/get_index_pattern'; +import { CachedIndexPatternFetcher } from '../lib/get_index_pattern'; export const toSanitizedFieldType = (fields: FieldSpec[]) => { return fields @@ -64,27 +64,28 @@ export abstract class AbstractSearchStrategy { checkForViability( requestContext: VisTypeTimeseriesRequestHandlerContext, req: VisTypeTimeseriesRequest, - indexPattern: string | IndexPatternObject + indexPatternObject: IndexPatternObject ): Promise<{ isViable: boolean; capabilities: any }> { throw new TypeError('Must override method'); } async getFieldsForWildcard( - indexPattern: string, + indexPatternObject: IndexPatternObject, indexPatternsService: IndexPatternsService, + cachedIndexPatternFetcher: CachedIndexPatternFetcher, capabilities?: unknown, options?: Partial<{ type: string; rollupIndex: string; }> ) { - const { indexPatternObject, indexPatternString } = await getIndexPatternObject(indexPattern, { - indexPatternsService, - }); + const { indexPattern, indexPatternString } = await cachedIndexPatternFetcher( + indexPatternObject + ); return toSanitizedFieldType( - indexPatternObject - ? indexPatternObject.getNonScriptedFields() + indexPattern + ? indexPattern.getNonScriptedFields() : await indexPatternsService.getFieldsForWildcard({ pattern: indexPatternString, metaFields: [], diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/default_search_strategy.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/default_search_strategy.ts index d7ded7d107ca9..8c1d76eb5cc86 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/default_search_strategy.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/default_search_strategy.ts @@ -10,6 +10,7 @@ import { AbstractSearchStrategy } from './abstract_search_strategy'; import { DefaultSearchCapabilities } from '../capabilities/default_search_capabilities'; import { VisTypeTimeseriesRequestHandlerContext, VisTypeTimeseriesRequest } from '../../../types'; import { IndexPatternsService } from '../../../../../data/server'; +import { CachedIndexPatternFetcher } from '../lib/get_index_pattern'; export class DefaultSearchStrategy extends AbstractSearchStrategy { checkForViability( @@ -25,8 +26,14 @@ export class DefaultSearchStrategy extends AbstractSearchStrategy { async getFieldsForWildcard( indexPattern: string, indexPatternsService: IndexPatternsService, + getCachedIndexPatternFetcher: CachedIndexPatternFetcher, capabilities?: unknown ) { - return super.getFieldsForWildcard(indexPattern, indexPatternsService, capabilities); + return super.getFieldsForWildcard( + indexPattern, + indexPatternsService, + getCachedIndexPatternFetcher, + capabilities + ); } } diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.test.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.test.ts index bd3e846919485..d954341b12865 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.test.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.test.ts @@ -12,6 +12,7 @@ import { VisTypeTimeseriesVisDataRequest, } from '../../../types'; import { IndexPatternsService } from '../../../../../data/common'; +import { CachedIndexPatternFetcher } from '../lib/get_index_pattern'; jest.mock('./abstract_search_strategy', () => { class AbstractSearchStrategyMock { @@ -155,6 +156,7 @@ describe('Rollup Search Strategy', () => { const fields = await rollupSearchStrategy.getFieldsForWildcard( indexPattern, {} as IndexPatternsService, + (() => Promise.resolve({}) as unknown) as CachedIndexPatternFetcher, { fieldsCapabilities, rollupIndex, diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.ts index c4e91e8a85ea7..ba8d972b76b6b 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.ts @@ -15,6 +15,8 @@ import { import { AbstractSearchStrategy } from './abstract_search_strategy'; import { RollupSearchCapabilities } from '../capabilities/rollup_search_capabilities'; import { IndexPatternObject } from '../../../../common/types'; +import { CachedIndexPatternFetcher } from '../lib/get_index_pattern'; +import { convertIndexPatternObjectToStringRepresentation } from '../../../../common/index_patterns_utils'; const getRollupIndices = (rollupData: { [key: string]: any }) => Object.keys(rollupData); const isIndexPatternContainsWildcard = (indexPattern: string) => indexPattern.includes('*'); @@ -50,12 +52,12 @@ export class RollupSearchStrategy extends AbstractSearchStrategy { async checkForViability( requestContext: VisTypeTimeseriesRequestHandlerContext, req: VisTypeTimeseriesRequest, - indexPattern: string | IndexPatternObject + indexPatternObject: IndexPatternObject ) { let isViable = false; let capabilities = null; - const index = typeof indexPattern === 'string' ? indexPattern : indexPattern?.title ?? ''; + const index = convertIndexPatternObjectToStringRepresentation(indexPatternObject); if (isIndexPatternValid(index)) { const rollupData = await this.getRollupData(requestContext, index); @@ -78,13 +80,20 @@ export class RollupSearchStrategy extends AbstractSearchStrategy { } async getFieldsForWildcard( - indexPattern: string, + indexPatternObject: IndexPatternObject, indexPatternsService: IndexPatternsService, + getCachedIndexPatternFetcher: CachedIndexPatternFetcher, capabilities?: unknown ) { - return super.getFieldsForWildcard(indexPattern, indexPatternsService, capabilities, { - type: 'rollup', - rollupIndex: indexPattern, - }); + return super.getFieldsForWildcard( + indexPatternObject, + indexPatternsService, + getCachedIndexPatternFetcher, + capabilities, + { + type: 'rollup', + rollupIndex: convertIndexPatternObjectToStringRepresentation(indexPatternObject), + } + ); } } diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/annotations/get_request_params.ts b/src/plugins/vis_type_timeseries/server/lib/vis_data/annotations/get_request_params.ts index c489a8d20b071..32086fbf4f5b4 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/annotations/get_request_params.ts +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/annotations/get_request_params.ts @@ -8,7 +8,6 @@ import { AnnotationItemsSchema, PanelSchema } from 'src/plugins/vis_type_timeseries/common/types'; import { buildAnnotationRequest } from './build_request_body'; -import { getIndexPatternObject } from '../../search_strategies/lib/get_index_pattern'; import { VisTypeTimeseriesRequestHandlerContext, VisTypeTimeseriesRequestServices, @@ -30,21 +29,20 @@ export async function getAnnotationRequestParams( esShardTimeout, esQueryConfig, capabilities, - indexPatternsService, uiSettings, + cachedIndexPatternFetcher, }: AnnotationServices ) { - const { - indexPatternObject, - indexPatternString, - } = await getIndexPatternObject(annotation.index_pattern!, { indexPatternsService }); + const { indexPattern, indexPatternString } = await cachedIndexPatternFetcher( + annotation.index_pattern + ); const request = await buildAnnotationRequest( req, panel, annotation, esQueryConfig, - indexPatternObject, + indexPattern, capabilities, uiSettings ); diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/get_interval_and_timefield.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/get_interval_and_timefield.js index 9b371a8901e81..ebab984ff25aa 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/get_interval_and_timefield.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/get_interval_and_timefield.js @@ -10,8 +10,8 @@ import { AUTO_INTERVAL } from '../../../common/constants'; const DEFAULT_TIME_FIELD = '@timestamp'; -export function getIntervalAndTimefield(panel, series = {}, indexPatternObject) { - const getDefaultTimeField = () => indexPatternObject?.timeFieldName ?? DEFAULT_TIME_FIELD; +export function getIntervalAndTimefield(panel, series = {}, indexPattern) { + const getDefaultTimeField = () => indexPattern?.timeFieldName ?? DEFAULT_TIME_FIELD; const timeField = (series.override_index_pattern && series.series_time_field) || diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/get_series_data.ts b/src/plugins/vis_type_timeseries/server/lib/vis_data/get_series_data.ts index efe9777f48a4f..c3932e0516365 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/get_series_data.ts +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/get_series_data.ts @@ -68,6 +68,7 @@ export async function getSeriesData( const handleResponseBodyFn = handleResponseBody(panel, req, { indexPatternsService: services.indexPatternsService, + cachedIndexPatternFetcher: services.cachedIndexPatternFetcher, searchStrategy, capabilities, }); diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/get_table_data.ts b/src/plugins/vis_type_timeseries/server/lib/vis_data/get_table_data.ts index 44a78de6ced1b..b882d8b529d76 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/get_table_data.ts +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/get_table_data.ts @@ -16,7 +16,7 @@ import { buildRequestBody } from './table/build_request_body'; import { handleErrorResponse } from './handle_error_response'; // @ts-expect-error import { processBucket } from './table/process_bucket'; -import { getIndexPatternObject } from '../search_strategies/lib/get_index_pattern'; + import { createFieldsFetcher } from './helpers/fields_fetcher'; import { extractFieldLabel } from '../../../common/calculate_label'; import type { @@ -32,11 +32,8 @@ export async function getTableData( panel: PanelSchema, services: VisTypeTimeseriesRequestServices ) { - const { indexPatternObject, indexPatternString } = await getIndexPatternObject( - panel.index_pattern, - { - indexPatternsService: services.indexPatternsService, - } + const { indexPattern, indexPatternString } = await services.cachedIndexPatternFetcher( + panel.index_pattern ); const strategy = await services.searchStrategyRegistry.getViableStrategy( @@ -57,13 +54,14 @@ export async function getTableData( const extractFields = createFieldsFetcher(req, { indexPatternsService: services.indexPatternsService, + cachedIndexPatternFetcher: services.cachedIndexPatternFetcher, searchStrategy, capabilities, }); const calculatePivotLabel = async () => { - if (panel.pivot_id && indexPatternObject?.title) { - const fields = await extractFields(indexPatternObject.title); + if (panel.pivot_id && indexPattern?.title) { + const fields = await extractFields(indexPattern.title); return extractFieldLabel(fields, panel.pivot_id); } @@ -81,7 +79,7 @@ export async function getTableData( req, panel, services.esQueryConfig, - indexPatternObject, + indexPattern, capabilities, services.uiSettings ); diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/fields_fetcher.ts b/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/fields_fetcher.ts index 936997527606c..59c9da403b11a 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/fields_fetcher.ts +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/fields_fetcher.ts @@ -9,16 +9,23 @@ import { VisTypeTimeseriesVisDataRequest } from '../../../types'; import { AbstractSearchStrategy, DefaultSearchCapabilities } from '../../search_strategies'; import { IndexPatternsService } from '../../../../../data/common'; +import { CachedIndexPatternFetcher } from '../../search_strategies/lib/get_index_pattern'; export interface FieldsFetcherServices { indexPatternsService: IndexPatternsService; + cachedIndexPatternFetcher: CachedIndexPatternFetcher; searchStrategy: AbstractSearchStrategy; capabilities: DefaultSearchCapabilities; } export const createFieldsFetcher = ( req: VisTypeTimeseriesVisDataRequest, - { capabilities, indexPatternsService, searchStrategy }: FieldsFetcherServices + { + capabilities, + indexPatternsService, + searchStrategy, + cachedIndexPatternFetcher, + }: FieldsFetcherServices ) => { const fieldsCacheMap = new Map(); @@ -30,6 +37,7 @@ export const createFieldsFetcher = ( const fields = await searchStrategy.getFieldsForWildcard( index, indexPatternsService, + cachedIndexPatternFetcher, capabilities ); diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/annotations/date_histogram.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/annotations/date_histogram.js index 0d100f6310b99..48b33c1e787e9 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/annotations/date_histogram.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/annotations/date_histogram.js @@ -18,7 +18,7 @@ export function dateHistogram( panel, annotation, esQueryConfig, - indexPatternObject, + indexPattern, capabilities, uiSettings ) { diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/date_histogram.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/date_histogram.js index 9ff0325b60e82..dab9a24d06c0f 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/date_histogram.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/date_histogram.js @@ -19,7 +19,7 @@ export function dateHistogram( panel, series, esQueryConfig, - indexPatternObject, + indexPattern, capabilities, uiSettings ) { @@ -27,11 +27,7 @@ export function dateHistogram( const maxBarsUiSettings = await uiSettings.get(UI_SETTINGS.HISTOGRAM_MAX_BARS); const barTargetUiSettings = await uiSettings.get(UI_SETTINGS.HISTOGRAM_BAR_TARGET); - const { timeField, interval, maxBars } = getIntervalAndTimefield( - panel, - series, - indexPatternObject - ); + const { timeField, interval, maxBars } = getIntervalAndTimefield(panel, series, indexPattern); const { bucketSize, intervalString } = getBucketSize( req, interval, @@ -68,7 +64,7 @@ export function dateHistogram( overwrite(doc, `aggs.${series.id}.meta`, { timeField, intervalString, - index: indexPatternObject?.title, + index: indexPattern?.title, bucketSize, seriesId: series.id, }); diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/date_histogram.test.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/date_histogram.test.js index d653f6acf6f3e..945c57b2341f3 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/date_histogram.test.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/date_histogram.test.js @@ -16,7 +16,7 @@ describe('dateHistogram(req, panel, series)', () => { let req; let capabilities; let config; - let indexPatternObject; + let indexPattern; let uiSettings; beforeEach(() => { @@ -39,7 +39,7 @@ describe('dateHistogram(req, panel, series)', () => { allowLeadingWildcards: true, queryStringOptions: {}, }; - indexPatternObject = {}; + indexPattern = {}; capabilities = new DefaultSearchCapabilities(req); uiSettings = { get: async (key) => (key === UI_SETTINGS.HISTOGRAM_MAX_BARS ? 100 : 50), @@ -49,15 +49,9 @@ describe('dateHistogram(req, panel, series)', () => { test('calls next when finished', async () => { const next = jest.fn(); - await dateHistogram( - req, - panel, - series, - config, - indexPatternObject, - capabilities, - uiSettings - )(next)({}); + await dateHistogram(req, panel, series, config, indexPattern, capabilities, uiSettings)(next)( + {} + ); expect(next.mock.calls.length).toEqual(1); }); @@ -69,7 +63,7 @@ describe('dateHistogram(req, panel, series)', () => { panel, series, config, - indexPatternObject, + indexPattern, capabilities, uiSettings )(next)({}); @@ -110,7 +104,7 @@ describe('dateHistogram(req, panel, series)', () => { panel, series, config, - indexPatternObject, + indexPattern, capabilities, uiSettings )(next)({}); @@ -154,7 +148,7 @@ describe('dateHistogram(req, panel, series)', () => { panel, series, config, - indexPatternObject, + indexPattern, capabilities, uiSettings )(next)({}); @@ -198,7 +192,7 @@ describe('dateHistogram(req, panel, series)', () => { panel, series, config, - indexPatternObject, + indexPattern, capabilities, uiSettings )(next)({}); @@ -216,7 +210,7 @@ describe('dateHistogram(req, panel, series)', () => { panel, series, config, - indexPatternObject, + indexPattern, capabilities, uiSettings )(next)({}); diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/filter_ratios.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/filter_ratios.js index 31ae988718a27..4639af9db83b8 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/filter_ratios.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/filter_ratios.js @@ -12,19 +12,19 @@ import { esQuery } from '../../../../../../data/server'; const filter = (metric) => metric.type === 'filter_ratio'; -export function ratios(req, panel, series, esQueryConfig, indexPatternObject) { +export function ratios(req, panel, series, esQueryConfig, indexPattern) { return (next) => (doc) => { if (series.metrics.some(filter)) { series.metrics.filter(filter).forEach((metric) => { overwrite( doc, `aggs.${series.id}.aggs.timeseries.aggs.${metric.id}-numerator.filter`, - esQuery.buildEsQuery(indexPatternObject, metric.numerator, [], esQueryConfig) + esQuery.buildEsQuery(indexPattern, metric.numerator, [], esQueryConfig) ); overwrite( doc, `aggs.${series.id}.aggs.timeseries.aggs.${metric.id}-denominator.filter`, - esQuery.buildEsQuery(indexPatternObject, metric.denominator, [], esQueryConfig) + esQuery.buildEsQuery(indexPattern, metric.denominator, [], esQueryConfig) ); let numeratorPath = `${metric.id}-numerator>_count`; diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/filter_ratios.test.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/filter_ratios.test.js index 9e0dd4f76c13f..345488ec01d5e 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/filter_ratios.test.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/filter_ratios.test.js @@ -13,7 +13,7 @@ describe('ratios(req, panel, series, esQueryConfig, indexPatternObject)', () => let series; let req; let esQueryConfig; - let indexPatternObject; + let indexPattern; beforeEach(() => { panel = { time_field: 'timestamp', @@ -47,18 +47,18 @@ describe('ratios(req, panel, series, esQueryConfig, indexPatternObject)', () => queryStringOptions: { analyze_wildcard: true }, ignoreFilterIfFieldNotInIndex: false, }; - indexPatternObject = {}; + indexPattern = {}; }); test('calls next when finished', () => { const next = jest.fn(); - ratios(req, panel, series, esQueryConfig, indexPatternObject)(next)({}); + ratios(req, panel, series, esQueryConfig, indexPattern)(next)({}); expect(next.mock.calls.length).toEqual(1); }); test('returns filter ratio aggs', () => { const next = (doc) => doc; - const doc = ratios(req, panel, series, esQueryConfig, indexPatternObject)(next)({}); + const doc = ratios(req, panel, series, esQueryConfig, indexPattern)(next)({}); expect(doc).toEqual({ aggs: { test: { @@ -135,7 +135,7 @@ describe('ratios(req, panel, series, esQueryConfig, indexPatternObject)', () => test('returns empty object when field is not set', () => { delete series.metrics[0].field; const next = (doc) => doc; - const doc = ratios(req, panel, series, esQueryConfig, indexPatternObject)(next)({}); + const doc = ratios(req, panel, series, esQueryConfig, indexPattern)(next)({}); expect(doc).toEqual({ aggs: { test: { diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/metric_buckets.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/metric_buckets.js index 649b3cee6ea3e..86b691f6496c9 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/metric_buckets.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/metric_buckets.js @@ -17,14 +17,14 @@ export function metricBuckets( panel, series, esQueryConfig, - indexPatternObject, + indexPattern, capabilities, uiSettings ) { return (next) => async (doc) => { const barTargetUiSettings = await uiSettings.get(UI_SETTINGS.HISTOGRAM_BAR_TARGET); - const { interval } = getIntervalAndTimefield(panel, series, indexPatternObject); + const { interval } = getIntervalAndTimefield(panel, series, indexPattern); const { intervalString } = getBucketSize(req, interval, capabilities, barTargetUiSettings); series.metrics diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/positive_rate.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/positive_rate.js index 1d67df7c92eb6..ce61374c0b124 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/positive_rate.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/positive_rate.js @@ -56,14 +56,14 @@ export function positiveRate( panel, series, esQueryConfig, - indexPatternObject, + indexPattern, capabilities, uiSettings ) { return (next) => async (doc) => { const barTargetUiSettings = await uiSettings.get(UI_SETTINGS.HISTOGRAM_BAR_TARGET); - const { interval } = getIntervalAndTimefield(panel, series, indexPatternObject); + const { interval } = getIntervalAndTimefield(panel, series, indexPattern); const { intervalString } = getBucketSize(req, interval, capabilities, barTargetUiSettings); if (series.metrics.some(filter)) { diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/query.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/query.js index cb12aa3513b91..d0e92c9157cb5 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/query.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/query.js @@ -10,16 +10,16 @@ import { offsetTime } from '../../offset_time'; import { getIntervalAndTimefield } from '../../get_interval_and_timefield'; import { esQuery } from '../../../../../../data/server'; -export function query(req, panel, series, esQueryConfig, indexPatternObject) { +export function query(req, panel, series, esQueryConfig, indexPattern) { return (next) => (doc) => { - const { timeField } = getIntervalAndTimefield(panel, series, indexPatternObject); + const { timeField } = getIntervalAndTimefield(panel, series, indexPattern); const { from, to } = offsetTime(req, series.offset_time); doc.size = 0; const ignoreGlobalFilter = panel.ignore_global_filter || series.ignore_global_filter; const queries = !ignoreGlobalFilter ? req.body.query : []; const filters = !ignoreGlobalFilter ? req.body.filters : []; - doc.query = esQuery.buildEsQuery(indexPatternObject, queries, filters, esQueryConfig); + doc.query = esQuery.buildEsQuery(indexPattern, queries, filters, esQueryConfig); const timerange = { range: { @@ -34,13 +34,13 @@ export function query(req, panel, series, esQueryConfig, indexPatternObject) { if (panel.filter) { doc.query.bool.must.push( - esQuery.buildEsQuery(indexPatternObject, [panel.filter], [], esQueryConfig) + esQuery.buildEsQuery(indexPattern, [panel.filter], [], esQueryConfig) ); } if (series.filter) { doc.query.bool.must.push( - esQuery.buildEsQuery(indexPatternObject, [series.filter], [], esQueryConfig) + esQuery.buildEsQuery(indexPattern, [series.filter], [], esQueryConfig) ); } diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/sibling_buckets.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/sibling_buckets.js index 315ccdfc13a47..401344d48f865 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/sibling_buckets.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/sibling_buckets.js @@ -17,13 +17,13 @@ export function siblingBuckets( panel, series, esQueryConfig, - indexPatternObject, + indexPattern, capabilities, uiSettings ) { return (next) => async (doc) => { const barTargetUiSettings = await uiSettings.get(UI_SETTINGS.HISTOGRAM_BAR_TARGET); - const { interval } = getIntervalAndTimefield(panel, series, indexPatternObject); + const { interval } = getIntervalAndTimefield(panel, series, indexPattern); const { bucketSize } = getBucketSize(req, interval, capabilities, barTargetUiSettings); series.metrics diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/date_histogram.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/date_histogram.js index 0ae6d113e28e4..5518065643172 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/date_histogram.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/date_histogram.js @@ -15,20 +15,13 @@ import { calculateAggRoot } from './calculate_agg_root'; import { search, UI_SETTINGS } from '../../../../../../../plugins/data/server'; const { dateHistogramInterval } = search.aggs; -export function dateHistogram( - req, - panel, - esQueryConfig, - indexPatternObject, - capabilities, - uiSettings -) { +export function dateHistogram(req, panel, esQueryConfig, indexPattern, capabilities, uiSettings) { return (next) => async (doc) => { const barTargetUiSettings = await uiSettings.get(UI_SETTINGS.HISTOGRAM_BAR_TARGET); - const { timeField, interval } = getIntervalAndTimefield(panel, {}, indexPatternObject); + const { timeField, interval } = getIntervalAndTimefield(panel, {}, indexPattern); const meta = { timeField, - index: indexPatternObject?.title, + index: indexPattern?.title, }; const getDateHistogramForLastBucketMode = () => { diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/filter_ratios.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/filter_ratios.js index 7b3ac16cd6561..abb5971908771 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/filter_ratios.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/filter_ratios.js @@ -13,7 +13,7 @@ import { calculateAggRoot } from './calculate_agg_root'; const filter = (metric) => metric.type === 'filter_ratio'; -export function ratios(req, panel, esQueryConfig, indexPatternObject) { +export function ratios(req, panel, esQueryConfig, indexPattern) { return (next) => (doc) => { panel.series.forEach((column) => { const aggRoot = calculateAggRoot(doc, column); @@ -22,12 +22,12 @@ export function ratios(req, panel, esQueryConfig, indexPatternObject) { overwrite( doc, `${aggRoot}.timeseries.aggs.${metric.id}-numerator.filter`, - esQuery.buildEsQuery(indexPatternObject, metric.numerator, [], esQueryConfig) + esQuery.buildEsQuery(indexPattern, metric.numerator, [], esQueryConfig) ); overwrite( doc, `${aggRoot}.timeseries.aggs.${metric.id}-denominator.filter`, - esQuery.buildEsQuery(indexPatternObject, metric.denominator, [], esQueryConfig) + esQuery.buildEsQuery(indexPattern, metric.denominator, [], esQueryConfig) ); let numeratorPath = `${metric.id}-numerator>_count`; diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/metric_buckets.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/metric_buckets.js index 53149a31603ef..5ce508bd9b279 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/metric_buckets.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/metric_buckets.js @@ -13,17 +13,10 @@ import { getIntervalAndTimefield } from '../../get_interval_and_timefield'; import { calculateAggRoot } from './calculate_agg_root'; import { UI_SETTINGS } from '../../../../../../data/common'; -export function metricBuckets( - req, - panel, - esQueryConfig, - indexPatternObject, - capabilities, - uiSettings -) { +export function metricBuckets(req, panel, esQueryConfig, indexPattern, capabilities, uiSettings) { return (next) => async (doc) => { const barTargetUiSettings = await uiSettings.get(UI_SETTINGS.HISTOGRAM_BAR_TARGET); - const { interval } = getIntervalAndTimefield(panel, {}, indexPatternObject); + const { interval } = getIntervalAndTimefield(panel, {}, indexPattern); const { intervalString } = getBucketSize(req, interval, capabilities, barTargetUiSettings); panel.series.forEach((column) => { diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/positive_rate.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/positive_rate.js index 8c7a0f5e2367f..176721e7b563a 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/positive_rate.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/positive_rate.js @@ -12,17 +12,10 @@ import { calculateAggRoot } from './calculate_agg_root'; import { createPositiveRate, filter } from '../series/positive_rate'; import { UI_SETTINGS } from '../../../../../../data/common'; -export function positiveRate( - req, - panel, - esQueryConfig, - indexPatternObject, - capabilities, - uiSettings -) { +export function positiveRate(req, panel, esQueryConfig, indexPattern, capabilities, uiSettings) { return (next) => async (doc) => { const barTargetUiSettings = await uiSettings.get(UI_SETTINGS.HISTOGRAM_BAR_TARGET); - const { interval } = getIntervalAndTimefield(panel, {}, indexPatternObject); + const { interval } = getIntervalAndTimefield(panel, {}, indexPattern); const { intervalString } = getBucketSize(req, interval, capabilities, barTargetUiSettings); panel.series.forEach((column) => { diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/query.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/query.js index a0118c5037d34..76df07b76e80e 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/query.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/query.js @@ -10,16 +10,16 @@ import { getTimerange } from '../../helpers/get_timerange'; import { getIntervalAndTimefield } from '../../get_interval_and_timefield'; import { esQuery } from '../../../../../../data/server'; -export function query(req, panel, esQueryConfig, indexPatternObject) { +export function query(req, panel, esQueryConfig, indexPattern) { return (next) => (doc) => { - const { timeField } = getIntervalAndTimefield(panel, {}, indexPatternObject); + const { timeField } = getIntervalAndTimefield(panel, {}, indexPattern); const { from, to } = getTimerange(req); doc.size = 0; const queries = !panel.ignore_global_filter ? req.body.query : []; const filters = !panel.ignore_global_filter ? req.body.filters : []; - doc.query = esQuery.buildEsQuery(indexPatternObject, queries, filters, esQueryConfig); + doc.query = esQuery.buildEsQuery(indexPattern, queries, filters, esQueryConfig); const timerange = { range: { @@ -33,7 +33,7 @@ export function query(req, panel, esQueryConfig, indexPatternObject) { doc.query.bool.must.push(timerange); if (panel.filter) { doc.query.bool.must.push( - esQuery.buildEsQuery(indexPatternObject, [panel.filter], [], esQueryConfig) + esQuery.buildEsQuery(indexPattern, [panel.filter], [], esQueryConfig) ); } diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/sibling_buckets.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/sibling_buckets.js index d205f0679a908..5539f16df41e0 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/sibling_buckets.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/request_processors/table/sibling_buckets.js @@ -13,17 +13,10 @@ import { getIntervalAndTimefield } from '../../get_interval_and_timefield'; import { calculateAggRoot } from './calculate_agg_root'; import { UI_SETTINGS } from '../../../../../../data/common'; -export function siblingBuckets( - req, - panel, - esQueryConfig, - indexPatternObject, - capabilities, - uiSettings -) { +export function siblingBuckets(req, panel, esQueryConfig, indexPattern, capabilities, uiSettings) { return (next) => async (doc) => { const barTargetUiSettings = await uiSettings.get(UI_SETTINGS.HISTOGRAM_BAR_TARGET); - const { interval } = getIntervalAndTimefield(panel, {}, indexPatternObject); + const { interval } = getIntervalAndTimefield(panel, {}, indexPattern); const { bucketSize } = getBucketSize(req, interval, capabilities, barTargetUiSettings); panel.series.forEach((column) => { diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/series/build_request_body.test.ts b/src/plugins/vis_type_timeseries/server/lib/vis_data/series/build_request_body.test.ts index 968fe01565b04..d97af8ac748f4 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/series/build_request_body.test.ts +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/series/build_request_body.test.ts @@ -79,13 +79,13 @@ describe('buildRequestBody(req)', () => { allowLeadingWildcards: true, queryStringOptions: {}, }; - const indexPatternObject = {}; + const indexPattern = {}; const doc = await buildRequestBody( { body }, panel, series, config, - indexPatternObject, + indexPattern, capabilities, { get: async () => 50, diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/series/get_request_params.ts b/src/plugins/vis_type_timeseries/server/lib/vis_data/series/get_request_params.ts index ae846b5b4b817..f9443324ac054 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/series/get_request_params.ts +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/series/get_request_params.ts @@ -8,7 +8,6 @@ import { PanelSchema, SeriesItemsSchema } from '../../../../common/types'; import { buildRequestBody } from './build_request_body'; -import { getIndexPatternObject } from '../../../lib/search_strategies/lib/get_index_pattern'; import { VisTypeTimeseriesRequestServices, VisTypeTimeseriesVisDataRequest } from '../../../types'; import { DefaultSearchCapabilities } from '../../search_strategies'; @@ -21,22 +20,19 @@ export async function getSeriesRequestParams( esQueryConfig, esShardTimeout, uiSettings, - indexPatternsService, + cachedIndexPatternFetcher, }: VisTypeTimeseriesRequestServices ) { - const indexPattern = - (series.override_index_pattern && series.series_index_pattern) || panel.index_pattern; - - const { indexPatternObject, indexPatternString } = await getIndexPatternObject(indexPattern, { - indexPatternsService, - }); + const { indexPattern, indexPatternString } = await cachedIndexPatternFetcher( + (series.override_index_pattern && series.series_index_pattern) || panel.index_pattern + ); const request = await buildRequestBody( req, panel, series, esQueryConfig, - indexPatternObject, + indexPattern, capabilities, uiSettings ); diff --git a/src/plugins/vis_type_timeseries/server/types.ts b/src/plugins/vis_type_timeseries/server/types.ts index da32669b3855d..54e84715fba21 100644 --- a/src/plugins/vis_type_timeseries/server/types.ts +++ b/src/plugins/vis_type_timeseries/server/types.ts @@ -12,8 +12,9 @@ import type { EsQueryConfig, IndexPatternsService, } from '../../data/server'; -import { VisPayload } from '../common/types'; -import { SearchStrategyRegistry } from './lib/search_strategies'; +import type { VisPayload } from '../common/types'; +import type { SearchStrategyRegistry } from './lib/search_strategies'; +import type { CachedIndexPatternFetcher } from './lib/search_strategies/lib/get_index_pattern'; export type VisTypeTimeseriesRequestHandlerContext = DataRequestHandlerContext; export type VisTypeTimeseriesRouter = IRouter; @@ -29,4 +30,5 @@ export interface VisTypeTimeseriesRequestServices { uiSettings: IUiSettingsClient; indexPatternsService: IndexPatternsService; searchStrategyRegistry: SearchStrategyRegistry; + cachedIndexPatternFetcher: CachedIndexPatternFetcher; } From d6643129b46ee557f49893cd4d73abd00b4d57d6 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Tue, 16 Mar 2021 17:33:07 +0300 Subject: [PATCH 24/39] fix some of PR comments --- .../common/index_patterns_utils.test.ts | 113 +++++++++++++++++- .../common/index_patterns_utils.ts | 36 +++++- .../vis_type_timeseries/common/types.ts | 6 + .../index_pattern_select.tsx | 27 +++-- .../application/components/vis_editor.tsx | 6 +- .../public/metrics_type.ts | 9 +- .../server/lib/get_fields.ts | 2 +- .../server/lib/get_vis_data.ts | 2 +- ...s => cached_index_pattern_fetcher.test.ts} | 7 +- .../lib/cached_index_pattern_fetcher.ts | 34 ++++++ .../lib/get_index_pattern.ts | 60 ---------- .../abstract_search_strategy.test.ts | 2 +- .../strategies/abstract_search_strategy.ts | 2 +- .../strategies/default_search_strategy.ts | 2 +- .../strategies/rollup_search_strategy.test.ts | 2 +- .../strategies/rollup_search_strategy.ts | 2 +- .../server/lib/vis_data/get_series_data.ts | 4 +- .../lib/vis_data/helpers/fields_fetcher.ts | 2 +- .../vis_type_timeseries/server/types.ts | 2 +- 19 files changed, 232 insertions(+), 88 deletions(-) rename src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/{get_index_pattern.test.ts => cached_index_pattern_fetcher.test.ts} (95%) create mode 100644 src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/cached_index_pattern_fetcher.ts delete mode 100644 src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/get_index_pattern.ts diff --git a/src/plugins/vis_type_timeseries/common/index_patterns_utils.test.ts b/src/plugins/vis_type_timeseries/common/index_patterns_utils.test.ts index 2ffd45b01f4bf..608d7337787cb 100644 --- a/src/plugins/vis_type_timeseries/common/index_patterns_utils.test.ts +++ b/src/plugins/vis_type_timeseries/common/index_patterns_utils.test.ts @@ -7,11 +7,13 @@ */ import { - extractIndexPatterns, + extractIndexPatternObjects, isStringTypeIndexPattern, convertIndexPatternObjectToStringRepresentation, + fetchIndexPattern, } from './index_patterns_utils'; import { PanelSchema } from './types'; +import { IndexPattern, IndexPatternsService } from '../../data/common'; describe('isStringTypeIndexPattern', () => { test('should returns true on string-based index', () => { @@ -54,6 +56,113 @@ describe('extractIndexPatterns', () => { }); test('should return index patterns', () => { - expect(extractIndexPatterns(panel, '')).toEqual(['*', 'example-1-*', 'example-2-*', 'notes-*']); + expect(extractIndexPatternObjects(panel, '')).toEqual([ + '*', + 'example-1-*', + 'example-2-*', + 'notes-*', + ]); + }); +}); + +describe('fetchIndexPattern', () => { + let mockedIndices: IndexPattern[] | []; + let indexPatternsService: IndexPatternsService; + + beforeEach(() => { + mockedIndices = []; + + indexPatternsService = ({ + getDefault: jest.fn(() => Promise.resolve({ id: 'default', title: 'index' })), + get: jest.fn(() => Promise.resolve(mockedIndices[0])), + find: jest.fn(() => Promise.resolve(mockedIndices || [])), + } as unknown) as IndexPatternsService; + }); + + test('should return default index on no input value', async () => { + const value = await fetchIndexPattern('', indexPatternsService); + expect(value).toMatchInlineSnapshot(` + Object { + "indexPattern": Object { + "id": "default", + "title": "index", + }, + "indexPatternString": "index", + } + `); + }); + + describe('text-based index', () => { + test('should return the Kibana index if it exists', async () => { + mockedIndices = [ + { + id: 'indexId', + title: 'indexTitle', + }, + ] as IndexPattern[]; + + const value = await fetchIndexPattern('indexTitle', indexPatternsService); + + expect(value).toMatchInlineSnapshot(` + Object { + "indexPattern": Object { + "id": "indexId", + "title": "indexTitle", + }, + "indexPatternString": "indexTitle", + } + `); + }); + + test('should return only indexPatternString if Kibana index does not exist', async () => { + const value = await fetchIndexPattern('indexTitle', indexPatternsService); + + expect(value).toMatchInlineSnapshot(` + Object { + "indexPattern": undefined, + "indexPatternString": "indexTitle", + } + `); + }); + }); + + describe('object-based index', () => { + test('should return the Kibana index if it exists', async () => { + mockedIndices = [ + { + id: 'indexId', + title: 'indexTitle', + }, + ] as IndexPattern[]; + + const value = await fetchIndexPattern({ id: 'indexId' }, indexPatternsService); + + expect(value).toMatchInlineSnapshot(` + Object { + "indexPattern": Object { + "id": "indexId", + "title": "indexTitle", + }, + "indexPatternString": "indexTitle", + } + `); + }); + + test('should return default index if Kibana index not found', async () => { + const value = await fetchIndexPattern( + { id: 'indexId', title: 'title' }, + indexPatternsService + ); + + expect(value).toMatchInlineSnapshot(` + Object { + "indexPattern": Object { + "id": "default", + "title": "index", + }, + "indexPatternString": "index", + } + `); + }); }); }); diff --git a/src/plugins/vis_type_timeseries/common/index_patterns_utils.ts b/src/plugins/vis_type_timeseries/common/index_patterns_utils.ts index 2dc1f135c6559..6ac4e661cb5c1 100644 --- a/src/plugins/vis_type_timeseries/common/index_patterns_utils.ts +++ b/src/plugins/vis_type_timeseries/common/index_patterns_utils.ts @@ -7,7 +7,8 @@ */ import { uniq } from 'lodash'; -import { PanelSchema, IndexPatternObject } from '../common/types'; +import { PanelSchema, IndexPatternObject, FetchedIndexPattern } from '../common/types'; +import { IndexPatternsService } from '../../data/common'; export const isStringTypeIndexPattern = ( indexPatternObject: IndexPatternObject @@ -23,7 +24,7 @@ export const convertIndexPatternObjectToStringRepresentation = ( export const getIndexPatternObjectKey = (indexPatternObject: IndexPatternObject) => isStringTypeIndexPattern(indexPatternObject) ? indexPatternObject : indexPatternObject?.id ?? ''; -export const extractIndexPatterns = ( +export const extractIndexPatternObjects = ( panel: PanelSchema, defaultIndex?: PanelSchema['default_index_pattern'] ) => { @@ -55,3 +56,34 @@ export const extractIndexPatterns = ( return uniq(patterns).sort(); }; + +export const fetchIndexPattern = async ( + indexPatternObject: IndexPatternObject, + indexPatternsService: Pick +): Promise => { + let indexPattern: FetchedIndexPattern['indexPattern']; + let indexPatternString: string = ''; + + if (!indexPatternObject) { + indexPattern = await indexPatternsService.getDefault(); + } else { + if (typeof indexPatternObject === 'string') { + indexPattern = (await indexPatternsService.find(indexPatternObject)).find( + (index) => index.title === indexPatternObject + ); + + if (!indexPattern) { + indexPatternString = indexPatternObject; + } + } else if (indexPatternObject.id) { + indexPattern = + (await indexPatternsService.get(indexPatternObject.id)) ?? + (await indexPatternsService.getDefault()); + } + } + + return { + indexPattern, + indexPatternString: indexPattern?.title ?? indexPatternString, + }; +}; diff --git a/src/plugins/vis_type_timeseries/common/types.ts b/src/plugins/vis_type_timeseries/common/types.ts index a97dcf6968c5f..82563d8748553 100644 --- a/src/plugins/vis_type_timeseries/common/types.ts +++ b/src/plugins/vis_type_timeseries/common/types.ts @@ -18,6 +18,7 @@ import { } from './vis_schema'; import { PANEL_TYPES } from './panel_types'; import { TimeseriesUIRestrictions } from './ui_restrictions'; +import { IndexPattern } from '../../data/common'; export type AnnotationItemsSchema = TypeOf; export type SeriesItemsSchema = TypeOf; @@ -27,6 +28,11 @@ export type VisPayload = TypeOf; export type FieldObject = TypeOf; export type IndexPatternObject = TypeOf; +export interface FetchedIndexPattern { + indexPattern: IndexPattern | undefined | null; + indexPatternString: string; +} + interface PanelData { id: string; label: string; diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/index_pattern_select.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/index_pattern_select.tsx index 67c499af5478a..32015568c042d 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/index_pattern_select.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/index_pattern_select.tsx @@ -38,6 +38,24 @@ const toIndexPatternObject = (index: IIndexPattern): IndexPatternObject => ({ title: index.title, }); +const defaultIndexPatternHelpText = i18n.translate( + 'visTypeTimeseries.indexPatternSelect.defaultIndexPatternText', + { + defaultMessage: 'Default index pattern is used.', + } +); + +const queryAllIndexesHelpText = i18n.translate( + 'visTypeTimeseries.indexPatternSelect.queryAllIndexesText', + { + defaultMessage: 'To query all indexes use *', + } +); + +const indexPatternLabel = i18n.translate('visTypeTimeseries.indexPatternSelect.label', { + defaultMessage: 'Index pattern', +}); + export const IndexPatternSelect = ({ value, indexPatternName, @@ -111,14 +129,9 @@ export const IndexPatternSelect = ({ return ( { const defaultIndexTitle = index?.title ?? ''; - const indexPatterns = extractIndexPatterns(this.props.vis.params, defaultIndexTitle); + const indexPatterns = extractIndexPatternObjects(this.props.vis.params, defaultIndexTitle); const visFields = await fetchFields(indexPatterns); this.setState((state) => ({ diff --git a/src/plugins/vis_type_timeseries/public/metrics_type.ts b/src/plugins/vis_type_timeseries/public/metrics_type.ts index fbdff218e2d65..6c821b384051f 100644 --- a/src/plugins/vis_type_timeseries/public/metrics_type.ts +++ b/src/plugins/vis_type_timeseries/public/metrics_type.ts @@ -10,6 +10,7 @@ import { i18n } from '@kbn/i18n'; import { TSVB_EDITOR_NAME } from './application'; import { PANEL_TYPES } from '../common/panel_types'; +import { fetchIndexPattern } from '../common/index_patterns_utils'; import { toExpressionAst } from './to_ast'; import { VIS_EVENT_TO_TRIGGER, VisGroups, VisParams } from '../../visualizations/public'; import { getDataStart } from './services'; @@ -76,6 +77,12 @@ export const metricsVisDefinition = { getUsedIndexPattern: async (params: VisParams) => { const { indexPatterns } = getDataStart(); - return params.index_pattern ? await indexPatterns.find(params.index_pattern) : []; + if (params.index_pattern) { + const { indexPattern } = await fetchIndexPattern(params.index_pattern, indexPatterns); + if (indexPattern) { + return [indexPattern]; + } + } + return []; }, }; diff --git a/src/plugins/vis_type_timeseries/server/lib/get_fields.ts b/src/plugins/vis_type_timeseries/server/lib/get_fields.ts index 055a20a308890..ccece62586e24 100644 --- a/src/plugins/vis_type_timeseries/server/lib/get_fields.ts +++ b/src/plugins/vis_type_timeseries/server/lib/get_fields.ts @@ -10,7 +10,7 @@ import { uniqBy } from 'lodash'; import { Framework } from '../plugin'; import { VisTypeTimeseriesFieldsRequest, VisTypeTimeseriesRequestHandlerContext } from '../types'; -import { getCachedIndexPatternFetcher } from './search_strategies/lib/get_index_pattern'; +import { getCachedIndexPatternFetcher } from './search_strategies/lib/cached_index_pattern_fetcher'; export async function getFields( requestContext: VisTypeTimeseriesRequestHandlerContext, diff --git a/src/plugins/vis_type_timeseries/server/lib/get_vis_data.ts b/src/plugins/vis_type_timeseries/server/lib/get_vis_data.ts index f0623e3bce6a4..d91104fb299d7 100644 --- a/src/plugins/vis_type_timeseries/server/lib/get_vis_data.ts +++ b/src/plugins/vis_type_timeseries/server/lib/get_vis_data.ts @@ -19,7 +19,7 @@ import type { import { getSeriesData } from './vis_data/get_series_data'; import { getTableData } from './vis_data/get_table_data'; import { getEsQueryConfig } from './vis_data/helpers/get_es_query_uisettings'; -import { getCachedIndexPatternFetcher } from './search_strategies/lib/get_index_pattern'; +import { getCachedIndexPatternFetcher } from './search_strategies/lib/cached_index_pattern_fetcher'; export async function getVisData( requestContext: VisTypeTimeseriesRequestHandlerContext, diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/get_index_pattern.test.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/cached_index_pattern_fetcher.test.ts similarity index 95% rename from src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/get_index_pattern.test.ts rename to src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/cached_index_pattern_fetcher.test.ts index 7ac894345c4c4..e94b871fb2c79 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/get_index_pattern.test.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/cached_index_pattern_fetcher.test.ts @@ -7,9 +7,12 @@ */ import { IndexPattern, IndexPatternsService } from 'src/plugins/data/server'; -import { getCachedIndexPatternFetcher, CachedIndexPatternFetcher } from './get_index_pattern'; +import { + getCachedIndexPatternFetcher, + CachedIndexPatternFetcher, +} from './cached_index_pattern_fetcher'; -describe('getIndexPatternObject', () => { +describe('CachedIndexPatternFetcher', () => { let mockedIndices: IndexPattern[] | []; let cachedIndexPatternFetcher: CachedIndexPatternFetcher; diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/cached_index_pattern_fetcher.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/cached_index_pattern_fetcher.ts new file mode 100644 index 0000000000000..0277d5d70a3f7 --- /dev/null +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/cached_index_pattern_fetcher.ts @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { IndexPatternsService } from '../../../../../data/server'; +import { IndexPatternObject, FetchedIndexPattern } from '../../../../common/types'; +import { + getIndexPatternObjectKey, + fetchIndexPattern, +} from '../../../../common/index_patterns_utils'; + +export const getCachedIndexPatternFetcher = (indexPatternsService: IndexPatternsService) => { + const cache = new Map(); + + return async (indexPatternObject: IndexPatternObject): Promise => { + const key = getIndexPatternObjectKey(indexPatternObject); + + if (cache.has(key)) { + return cache.get(key); + } + + const fetchedIndex = fetchIndexPattern(indexPatternObject, indexPatternsService); + + cache.set(indexPatternObject, fetchedIndex); + + return fetchedIndex; + }; +}; + +export type CachedIndexPatternFetcher = ReturnType; diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/get_index_pattern.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/get_index_pattern.ts deleted file mode 100644 index 8674df44baac1..0000000000000 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/get_index_pattern.ts +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { IndexPatternsService, IndexPattern } from '../../../../../data/server'; -import { IndexPatternObject } from '../../../../common/types'; -import { convertIndexPatternObjectToStringRepresentation } from '../../../../common/index_patterns_utils'; - -interface ParsedIndexPattern { - indexPattern: IndexPattern | undefined | null; - indexPatternString: string; -} - -export const getCachedIndexPatternFetcher = (indexPatternsService: IndexPatternsService) => { - const cache = new Map(); - - return async (indexPatternObject: IndexPatternObject): Promise => { - const key = convertIndexPatternObjectToStringRepresentation(indexPatternObject); - - if (cache.has(key)) { - return cache.get(key); - } - - let indexPattern: ParsedIndexPattern['indexPattern']; - let indexPatternString: string = ''; - - if (!indexPatternObject) { - indexPattern = await indexPatternsService.getDefault(); - } else { - if (typeof indexPatternObject === 'string') { - indexPattern = (await indexPatternsService.find(indexPatternObject)).find( - (index) => index.title === indexPatternObject - ); - - if (!indexPattern) { - indexPatternString = indexPatternObject; - } - } else if (indexPatternObject.id) { - indexPattern = - (await indexPatternsService.get(indexPatternObject.id)) ?? - (await indexPatternsService.getDefault()); - } - } - - const returnObject = { - indexPattern, - indexPatternString: indexPattern?.title ?? indexPatternString, - }; - - cache.set(indexPatternObject, returnObject); - - return returnObject; - }; -}; - -export type CachedIndexPatternFetcher = ReturnType; diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.test.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.test.ts index efced5e3182e9..757b2919c8a25 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.test.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.test.ts @@ -16,7 +16,7 @@ import { VisTypeTimeseriesRequestHandlerContext, VisTypeTimeseriesVisDataRequest, } from '../../../types'; -import { CachedIndexPatternFetcher } from '../lib/get_index_pattern'; +import { CachedIndexPatternFetcher } from '../lib/cached_index_pattern_fetcher'; class FooSearchStrategy extends AbstractSearchStrategy {} diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts index b844337f4d46a..f27a4ceeaa68d 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts @@ -15,7 +15,7 @@ import type { VisTypeTimeseriesRequestHandlerContext, VisTypeTimeseriesVisDataRequest, } from '../../../types'; -import { CachedIndexPatternFetcher } from '../lib/get_index_pattern'; +import { CachedIndexPatternFetcher } from '../lib/cached_index_pattern_fetcher'; export const toSanitizedFieldType = (fields: FieldSpec[]) => { return fields diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/default_search_strategy.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/default_search_strategy.ts index 8c1d76eb5cc86..de18809f6ded2 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/default_search_strategy.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/default_search_strategy.ts @@ -10,7 +10,7 @@ import { AbstractSearchStrategy } from './abstract_search_strategy'; import { DefaultSearchCapabilities } from '../capabilities/default_search_capabilities'; import { VisTypeTimeseriesRequestHandlerContext, VisTypeTimeseriesRequest } from '../../../types'; import { IndexPatternsService } from '../../../../../data/server'; -import { CachedIndexPatternFetcher } from '../lib/get_index_pattern'; +import { CachedIndexPatternFetcher } from '../lib/cached_index_pattern_fetcher'; export class DefaultSearchStrategy extends AbstractSearchStrategy { checkForViability( diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.test.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.test.ts index d954341b12865..bed4ecef5a7a6 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.test.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.test.ts @@ -12,7 +12,7 @@ import { VisTypeTimeseriesVisDataRequest, } from '../../../types'; import { IndexPatternsService } from '../../../../../data/common'; -import { CachedIndexPatternFetcher } from '../lib/get_index_pattern'; +import { CachedIndexPatternFetcher } from '../lib/cached_index_pattern_fetcher'; jest.mock('./abstract_search_strategy', () => { class AbstractSearchStrategyMock { diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.ts index ba8d972b76b6b..e7a2fc722731a 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.ts @@ -15,7 +15,7 @@ import { import { AbstractSearchStrategy } from './abstract_search_strategy'; import { RollupSearchCapabilities } from '../capabilities/rollup_search_capabilities'; import { IndexPatternObject } from '../../../../common/types'; -import { CachedIndexPatternFetcher } from '../lib/get_index_pattern'; +import { CachedIndexPatternFetcher } from '../lib/cached_index_pattern_fetcher'; import { convertIndexPatternObjectToStringRepresentation } from '../../../../common/index_patterns_utils'; const getRollupIndices = (rollupData: { [key: string]: any }) => Object.keys(rollupData); diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/get_series_data.ts b/src/plugins/vis_type_timeseries/server/lib/vis_data/get_series_data.ts index c3932e0516365..e1bc9c29ecf61 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/get_series_data.ts +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/get_series_data.ts @@ -25,7 +25,7 @@ import { PANEL_TYPES } from '../../../common/panel_types'; import { convertIndexPatternObjectToStringRepresentation, - extractIndexPatterns, + extractIndexPatternObjects, } from '../../../common/index_patterns_utils'; export async function getSeriesData( @@ -34,7 +34,7 @@ export async function getSeriesData( panel: PanelSchema, services: VisTypeTimeseriesRequestServices ) { - const indexPattern = extractIndexPatterns(panel, panel.default_index_pattern) + const indexPattern = extractIndexPatternObjects(panel, panel.default_index_pattern) .map(convertIndexPatternObjectToStringRepresentation) .join(','); diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/fields_fetcher.ts b/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/fields_fetcher.ts index 59c9da403b11a..0444c33055cee 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/fields_fetcher.ts +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/fields_fetcher.ts @@ -9,7 +9,7 @@ import { VisTypeTimeseriesVisDataRequest } from '../../../types'; import { AbstractSearchStrategy, DefaultSearchCapabilities } from '../../search_strategies'; import { IndexPatternsService } from '../../../../../data/common'; -import { CachedIndexPatternFetcher } from '../../search_strategies/lib/get_index_pattern'; +import { CachedIndexPatternFetcher } from '../../search_strategies/lib/cached_index_pattern_fetcher'; export interface FieldsFetcherServices { indexPatternsService: IndexPatternsService; diff --git a/src/plugins/vis_type_timeseries/server/types.ts b/src/plugins/vis_type_timeseries/server/types.ts index 54e84715fba21..3ab5d8ac6ea7a 100644 --- a/src/plugins/vis_type_timeseries/server/types.ts +++ b/src/plugins/vis_type_timeseries/server/types.ts @@ -14,7 +14,7 @@ import type { } from '../../data/server'; import type { VisPayload } from '../common/types'; import type { SearchStrategyRegistry } from './lib/search_strategies'; -import type { CachedIndexPatternFetcher } from './lib/search_strategies/lib/get_index_pattern'; +import type { CachedIndexPatternFetcher } from './lib/search_strategies/lib/cached_index_pattern_fetcher'; export type VisTypeTimeseriesRequestHandlerContext = DataRequestHandlerContext; export type VisTypeTimeseriesRouter = IRouter; From 61ad5538ab0222b95eb5dd0306f4df3a11cbf488 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Thu, 18 Mar 2021 14:12:38 +0300 Subject: [PATCH 25/39] move index patterns into so references --- .../common/index_patterns_utils.test.ts | 19 +---- .../common/index_patterns_utils.ts | 9 +- .../vis_type_timeseries/common/vis_schema.ts | 1 - .../index_pattern_select/combo_box_select.tsx | 49 ++++++----- .../field_text_select.tsx | 32 +++++--- .../index_pattern_select.tsx | 82 ++++++------------- .../index_pattern_select/migrate_popover.tsx | 24 +++--- .../lib/index_pattern_select/types.ts | 7 +- .../components/query_bar_wrapper.tsx | 31 ++++++- .../server/lib/get_fields.ts | 7 +- .../lib/cached_index_pattern_fetcher.test.ts | 2 +- .../lib}/fields_fetcher.ts | 12 +-- .../search_strategy_registry.ts | 6 +- .../abstract_search_strategy.test.ts | 3 +- .../strategies/abstract_search_strategy.ts | 18 ++-- .../strategies/default_search_strategy.ts | 24 +++--- .../strategies/rollup_search_strategy.test.ts | 4 +- .../strategies/rollup_search_strategy.ts | 42 ++++------ .../server/lib/vis_data/get_series_data.ts | 11 +-- .../server/lib/vis_data/get_table_data.ts | 16 ++-- .../vis_data/series/handle_response_body.ts | 5 +- .../controls_references.ts | 48 +++++++++++ .../saved_visualization_references/index.ts | 9 ++ .../saved_visualization_references.test.ts | 4 +- .../saved_visualization_references.ts | 43 ++++------ .../timeseries_references.ts | 82 +++++++++++++++++++ 26 files changed, 345 insertions(+), 245 deletions(-) rename src/plugins/vis_type_timeseries/server/lib/{vis_data/helpers => search_strategies/lib}/fields_fetcher.ts (74%) create mode 100644 src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/controls_references.ts create mode 100644 src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/index.ts rename src/plugins/visualizations/public/saved_visualizations/{ => saved_visualization_references}/saved_visualization_references.test.ts (97%) rename src/plugins/visualizations/public/saved_visualizations/{ => saved_visualization_references}/saved_visualization_references.ts (68%) create mode 100644 src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/timeseries_references.ts diff --git a/src/plugins/vis_type_timeseries/common/index_patterns_utils.test.ts b/src/plugins/vis_type_timeseries/common/index_patterns_utils.test.ts index 608d7337787cb..a541288e07d36 100644 --- a/src/plugins/vis_type_timeseries/common/index_patterns_utils.test.ts +++ b/src/plugins/vis_type_timeseries/common/index_patterns_utils.test.ts @@ -9,7 +9,6 @@ import { extractIndexPatternObjects, isStringTypeIndexPattern, - convertIndexPatternObjectToStringRepresentation, fetchIndexPattern, } from './index_patterns_utils'; import { PanelSchema } from './types'; @@ -20,18 +19,7 @@ describe('isStringTypeIndexPattern', () => { expect(isStringTypeIndexPattern('index')).toBeTruthy(); }); test('should returns false on object-based index', () => { - expect(isStringTypeIndexPattern({ title: 'title', id: 'id' })).toBeFalsy(); - }); -}); - -describe('convertIndexPatternObjectToStringRepresentation', () => { - test('should return the correct title on getting string-based index', () => { - expect(convertIndexPatternObjectToStringRepresentation('index')).toBe('index'); - }); - test('should return the correct title on getting object-based index', () => { - expect(convertIndexPatternObjectToStringRepresentation({ title: 'title', id: 'id' })).toBe( - 'title' - ); + expect(isStringTypeIndexPattern({ id: 'id' })).toBeFalsy(); }); }); @@ -149,10 +137,7 @@ describe('fetchIndexPattern', () => { }); test('should return default index if Kibana index not found', async () => { - const value = await fetchIndexPattern( - { id: 'indexId', title: 'title' }, - indexPatternsService - ); + const value = await fetchIndexPattern({ id: 'indexId' }, indexPatternsService); expect(value).toMatchInlineSnapshot(` Object { diff --git a/src/plugins/vis_type_timeseries/common/index_patterns_utils.ts b/src/plugins/vis_type_timeseries/common/index_patterns_utils.ts index 6ac4e661cb5c1..4905b0cfc287d 100644 --- a/src/plugins/vis_type_timeseries/common/index_patterns_utils.ts +++ b/src/plugins/vis_type_timeseries/common/index_patterns_utils.ts @@ -14,13 +14,6 @@ export const isStringTypeIndexPattern = ( indexPatternObject: IndexPatternObject ): indexPatternObject is string => typeof indexPatternObject === 'string'; -export const convertIndexPatternObjectToStringRepresentation = ( - indexPatternObject: IndexPatternObject -) => - isStringTypeIndexPattern(indexPatternObject) - ? indexPatternObject - : indexPatternObject?.title ?? ''; - export const getIndexPatternObjectKey = (indexPatternObject: IndexPatternObject) => isStringTypeIndexPattern(indexPatternObject) ? indexPatternObject : indexPatternObject?.id ?? ''; @@ -67,7 +60,7 @@ export const fetchIndexPattern = async ( if (!indexPatternObject) { indexPattern = await indexPatternsService.getDefault(); } else { - if (typeof indexPatternObject === 'string') { + if (isStringTypeIndexPattern(indexPatternObject)) { indexPattern = (await indexPatternsService.find(indexPatternObject)).find( (index) => index.title === indexPatternObject ); diff --git a/src/plugins/vis_type_timeseries/common/vis_schema.ts b/src/plugins/vis_type_timeseries/common/vis_schema.ts index ccb3c858d3cba..ff7b3fe69a411 100644 --- a/src/plugins/vis_type_timeseries/common/vis_schema.ts +++ b/src/plugins/vis_type_timeseries/common/vis_schema.ts @@ -40,7 +40,6 @@ export const indexPattern = schema.oneOf([ schema.maybe(schema.string()), schema.object({ id: schema.string(), - title: schema.maybe(schema.string()), }), ]); diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/combo_box_select.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/combo_box_select.tsx index 533fc14e595c5..8a7314134a77a 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/combo_box_select.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/combo_box_select.tsx @@ -12,7 +12,6 @@ import { EuiComboBox, EuiComboBoxProps } from '@elastic/eui'; import { getDataStart } from '../../../../services'; import { SwitchModePopover } from './switch_mode_popover'; -import { isStringTypeIndexPattern } from '../../../../../common/index_patterns_utils'; import type { SelectIndexComponentProps } from './types'; import type { IndexPatternObject } from '../../../../../common/types'; @@ -21,39 +20,45 @@ import type { IndexPatternsService } from '../../../../../../data/public'; /** @internal **/ type IdsWithTitle = UnwrapPromise>; -const toSelectedOptions = ( - value: IndexPatternObject -): EuiComboBoxProps['selectedOptions'] => { - if (!value) { - return []; - } - return isStringTypeIndexPattern(value) - ? [{ label: value ?? '' }] - : [ - { - id: value.id ?? '', - label: value.title ?? '', - }, - ]; -}; +/** @internal **/ +type SelectedOptions = EuiComboBoxProps['selectedOptions']; const toComboBoxOptions = (options: IdsWithTitle) => options.map(({ title, id }) => ({ label: title, id })); export const ComboBoxSelect = ({ + fetchedIndex, onIndexChange, onModeChange, disabled, - value, placeholder, allowSwitchMode, 'data-test-subj': dataTestSubj, }: SelectIndexComponentProps) => { const [availableIndexes, setAvailableIndexes] = useState([]); + const [selectedOptions, setSelectedOptions] = useState([]); + + useEffect(() => { + let options: SelectedOptions = []; + + if (fetchedIndex) { + if (!fetchedIndex.indexPattern) { + options = [{ label: fetchedIndex.indexPatternString ?? '' }]; + } else { + options = [ + { + id: fetchedIndex.indexPattern.id, + label: fetchedIndex.indexPattern.title, + }, + ]; + } + } + setSelectedOptions(options); + }, [fetchedIndex]); const onComboBoxChange: EuiComboBoxProps['onChange'] = useCallback( ([selected]) => { - onIndexChange(selected ? { id: selected.id, title: selected.label } : ''); + onIndexChange(selected ? { id: selected.id } : ''); }, [onIndexChange] ); @@ -71,13 +76,17 @@ export const ComboBoxSelect = ({ singleSelection={{ asPlainText: true }} onChange={onComboBoxChange} options={toComboBoxOptions(availableIndexes)} - selectedOptions={toSelectedOptions(value)} + selectedOptions={selectedOptions} isDisabled={disabled} placeholder={placeholder} data-test-subj={dataTestSubj} {...(allowSwitchMode && { append: ( - + ), })} /> diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/field_text_select.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/field_text_select.tsx index 7bed524487068..5e176eeeaec74 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/field_text_select.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/field_text_select.tsx @@ -5,42 +5,54 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ +import React, { useCallback, useState } from 'react'; +import useDebounce from 'react-use/lib/useDebounce'; -import React, { useCallback } from 'react'; import { EuiFieldText, EuiFieldTextProps } from '@elastic/eui'; import { SwitchModePopover } from './switch_mode_popover'; -import { convertIndexPatternObjectToStringRepresentation } from '../../../../../common/index_patterns_utils'; import type { SelectIndexComponentProps } from './types'; export const FieldTextSelect = ({ + fetchedIndex, onIndexChange, disabled, - value, placeholder, onModeChange, allowSwitchMode, 'data-test-subj': dataTestSubj, }: SelectIndexComponentProps) => { - const textualValue = convertIndexPatternObjectToStringRepresentation(value); + const textualValue = fetchedIndex?.indexPatternString ?? ''; + const [inputValue, setInputValue] = useState(textualValue); - const onFieldTextChange: EuiFieldTextProps['onChange'] = useCallback( - (e) => { - onIndexChange(e.target.value); + const onFieldTextChange: EuiFieldTextProps['onChange'] = useCallback((e) => { + setInputValue(e.target.value); + }, []); + + useDebounce( + () => { + if (inputValue !== textualValue) { + onIndexChange(inputValue); + } }, - [onIndexChange] + 150, + [inputValue, onIndexChange] ); return ( + ), })} /> diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/index_pattern_select.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/index_pattern_select.tsx index 32015568c042d..c76a7f4bd8bab 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/index_pattern_select.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/index_pattern_select.tsx @@ -7,7 +7,7 @@ */ import React, { useState, useContext, useCallback, useEffect } from 'react'; -import useDebounce from 'react-use/lib/useDebounce'; + import { EuiFormRow, htmlIdGenerator } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FieldTextSelect } from './field_text_select'; @@ -17,11 +17,10 @@ import { PanelModelContext } from '../../../contexts/panel_model_context'; import { getDataStart } from '../../../../services'; import { isStringTypeIndexPattern, - convertIndexPatternObjectToStringRepresentation, + fetchIndexPattern, } from '../../../../../common/index_patterns_utils'; -import type { IIndexPattern } from '../../../../../../data/public'; -import type { IndexPatternObject } from '../../../../../common/types'; +import type { IndexPatternObject, FetchedIndexPattern } from '../../../../../common/types'; const USE_KIBANA_INDEXES_KEY = 'use_kibana_indexes'; @@ -33,11 +32,6 @@ interface IndexPatternSelectProps { allowIndexSwitchingMode?: boolean; } -const toIndexPatternObject = (index: IIndexPattern): IndexPatternObject => ({ - id: index.id!, - title: index.title, -}); - const defaultIndexPatternHelpText = i18n.translate( 'visTypeTimeseries.indexPatternSelect.defaultIndexPatternText', { @@ -64,66 +58,43 @@ export const IndexPatternSelect = ({ allowIndexSwitchingMode, }: IndexPatternSelectProps) => { const htmlId = htmlIdGenerator(); - const panelModel = useContext(PanelModelContext); - const [defaultIndex, setDefaultIndex] = useState(); - const [matchedIndex, setMatchedIndex] = useState(); - const [inputValue, setInputValue] = useState(value); + const [fetchedIndex, setFetchedIndex] = useState(); const useKibanaIndices = Boolean(panelModel?.[USE_KIBANA_INDEXES_KEY]); const Component = useKibanaIndices ? ComboBoxSelect : FieldTextSelect; - useDebounce( - () => { - if (inputValue !== value) { - onChange({ - [indexPatternName]: inputValue, - }); - } - }, - 300, - [onChange, inputValue, indexPatternName, value] - ); - useEffect(() => { - async function retrieveIndex() { + async function fetchIndex() { const { indexPatterns } = getDataStart(); - if (isStringTypeIndexPattern(value)) { - const index = (await indexPatterns.find(value)).find((i) => i.title === value); - - if (index) { - return setMatchedIndex(toIndexPatternObject(index)); - } - } - - setMatchedIndex(undefined); + setFetchedIndex(value ? await fetchIndexPattern(value, indexPatterns) : undefined); } - retrieveIndex(); + fetchIndex(); }, [value]); - useEffect(() => { - async function getDefaultIndex() { - const { indexPatterns } = getDataStart(); - const index = await indexPatterns.getDefault(); - - if (index) { - return setDefaultIndex(toIndexPatternObject(index)); - } - } - - getDefaultIndex(); - }, []); - const onModeChange = useCallback( (useKibanaIndexes: boolean) => { onChange({ [USE_KIBANA_INDEXES_KEY]: useKibanaIndexes, + [indexPatternName]: fetchedIndex?.indexPattern + ? { + id: fetchedIndex.indexPattern.id!, + } + : '', + }); + }, + [onChange, fetchedIndex, indexPatternName] + ); + + const onIndexChange = useCallback( + (index: IndexPatternObject) => { + onChange({ + [indexPatternName]: index, }); - setInputValue(matchedIndex ?? ''); }, - [onChange, matchedIndex] + [indexPatternName, onChange] ); return ( @@ -138,20 +109,19 @@ export const IndexPatternSelect = ({ isStringTypeIndexPattern(value) && ( ) } > diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/migrate_popover.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/migrate_popover.tsx index 260e063848095..4effba0eb62c8 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/migrate_popover.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/migrate_popover.tsx @@ -28,7 +28,7 @@ const switchModeLabel = i18n.translate( } ); -const getReadyToSwitchCallOut = (value: PopoverProps['value'], onModeChange: () => void) => ( +const getReadyToSwitchCallOut = (value: string, onModeChange: () => void) => ( <>

@@ -51,10 +51,7 @@ const getReadyToSwitchCallOut = (value: PopoverProps['value'], onModeChange: () ); -const getNoMatchedIndicesCallOut = ( - value: PopoverProps['value'], - onCreateIndexClick: () => void -) => ( +const getNoMatchedIndicesCallOut = (value: string, onCreateIndexClick: () => void) => ( <>

@@ -77,7 +74,7 @@ const getNoMatchedIndicesCallOut = ( ); -export const MigrationPopover = ({ value, onModeChange, matchedIndex }: PopoverProps) => { +export const MigrationPopover = ({ fetchedIndex, onModeChange }: PopoverProps) => { const [isPopoverOpen, setIsPopoverOpen] = useState(false); const closePopover = useCallback(() => setIsPopoverOpen(false), []); const onButtonClick = useCallback(() => setIsPopoverOpen((isOpen) => !isOpen), []); @@ -88,9 +85,13 @@ export const MigrationPopover = ({ value, onModeChange, matchedIndex }: PopoverP const navigateToCreateIndexPatterns = useCallback(() => { getCoreStart().application.navigateToApp('management', { - path: `/kibana/indexPatterns/create?name=${value}`, + path: `/kibana/indexPatterns/create?name=${fetchedIndex?.indexPatternString ?? ''}`, }); - }, [value]); + }, [fetchedIndex]); + + if (!fetchedIndex) { + return null; + } return ( {switchModeLabel} - {matchedIndex && getReadyToSwitchCallOut(value, switchMode)} - {!matchedIndex && getNoMatchedIndicesCallOut(value, navigateToCreateIndexPatterns)} + {fetchedIndex.indexPattern && + getReadyToSwitchCallOut(fetchedIndex.indexPatternString, switchMode)} + + {!fetchedIndex.indexPattern && + getNoMatchedIndicesCallOut(fetchedIndex.indexPatternString, navigateToCreateIndexPatterns)} ); }; diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/types.ts b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/types.ts index 43574ce84ab85..58a9e6dadb60d 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/types.ts +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/types.ts @@ -6,11 +6,11 @@ * Side Public License, v 1. */ import { Assign } from '@kbn/utility-types'; -import type { IndexPatternObject } from '../../../../../common/types'; +import type { FetchedIndexPattern, IndexPatternObject } from '../../../../../common/types'; /** @internal **/ export interface SelectIndexComponentProps { - value: IndexPatternObject; + fetchedIndex: FetchedIndexPattern | undefined; onIndexChange: (value: IndexPatternObject) => void; onModeChange: (useKibanaIndexes: boolean) => void; 'data-test-subj': string; @@ -21,9 +21,8 @@ export interface SelectIndexComponentProps { /** @internal **/ export type PopoverProps = Assign< - Pick, + Pick, { useKibanaIndices: boolean; - matchedIndex?: IndexPatternObject; } >; diff --git a/src/plugins/vis_type_timeseries/public/application/components/query_bar_wrapper.tsx b/src/plugins/vis_type_timeseries/public/application/components/query_bar_wrapper.tsx index c74f37ce58c84..ddee08b6a12b7 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/query_bar_wrapper.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/query_bar_wrapper.tsx @@ -6,26 +6,51 @@ * Side Public License, v 1. */ -import React, { useContext } from 'react'; +import React, { useContext, useEffect, useState } from 'react'; import { CoreStartContext } from '../contexts/query_input_bar_context'; import { IndexPatternObject } from '../../../common/types'; -import { convertIndexPatternObjectToStringRepresentation } from '../../../common/index_patterns_utils'; import { QueryStringInput, QueryStringInputProps } from '../../../../../plugins/data/public'; +import { getDataStart } from '../../services'; +import { fetchIndexPattern, isStringTypeIndexPattern } from '../../../common/index_patterns_utils'; type QueryBarWrapperProps = Pick & { indexPatterns: IndexPatternObject[]; }; export function QueryBarWrapper({ query, onChange, indexPatterns }: QueryBarWrapperProps) { + const { indexPatterns: indexPatternsService } = getDataStart(); + const [indexes, setIndexes] = useState([]); + const coreStartContext = useContext(CoreStartContext); + useEffect(() => { + async function fetchIndexes() { + const i: QueryStringInputProps['indexPatterns'] = []; + + for (const index of indexPatterns) { + if (isStringTypeIndexPattern(index)) { + i.push(index); + } else if (index?.id) { + const fetchedIndex = await fetchIndexPattern(index, indexPatternsService); + + if (fetchedIndex.indexPattern) { + i.push(fetchedIndex.indexPattern); + } + } + } + setIndexes(i); + } + + fetchIndexes(); + }, [indexPatterns, indexPatternsService]); + return ( ); diff --git a/src/plugins/vis_type_timeseries/server/lib/get_fields.ts b/src/plugins/vis_type_timeseries/server/lib/get_fields.ts index ccece62586e24..b0e85f8e44fbe 100644 --- a/src/plugins/vis_type_timeseries/server/lib/get_fields.ts +++ b/src/plugins/vis_type_timeseries/server/lib/get_fields.ts @@ -27,19 +27,20 @@ export async function getFields( indexPatternString = defaultIndexPattern?.title ?? ''; } + const fetchedIndex = await cachedIndexPatternFetcher(indexPatternString); + const { searchStrategy, capabilities, } = (await framework.searchStrategyRegistry.getViableStrategy( requestContext, request, - indexPatternString + fetchedIndex ))!; const fields = await searchStrategy.getFieldsForWildcard( - indexPatternString, + fetchedIndex, indexPatternsService, - cachedIndexPatternFetcher, capabilities ); diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/cached_index_pattern_fetcher.test.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/cached_index_pattern_fetcher.test.ts index e94b871fb2c79..016960691dd83 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/cached_index_pattern_fetcher.test.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/cached_index_pattern_fetcher.test.ts @@ -98,7 +98,7 @@ describe('CachedIndexPatternFetcher', () => { }); test('should return default index if Kibana index not found', async () => { - const value = await cachedIndexPatternFetcher({ id: 'indexId', title: 'title' }); + const value = await cachedIndexPatternFetcher({ id: 'indexId' }); expect(value).toMatchInlineSnapshot(` Object { diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/fields_fetcher.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/fields_fetcher.ts similarity index 74% rename from src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/fields_fetcher.ts rename to src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/fields_fetcher.ts index 0444c33055cee..9003eb7fc2ced 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/fields_fetcher.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/fields_fetcher.ts @@ -6,10 +6,10 @@ * Side Public License, v 1. */ -import { VisTypeTimeseriesVisDataRequest } from '../../../types'; -import { AbstractSearchStrategy, DefaultSearchCapabilities } from '../../search_strategies'; -import { IndexPatternsService } from '../../../../../data/common'; -import { CachedIndexPatternFetcher } from '../../search_strategies/lib/cached_index_pattern_fetcher'; +import type { VisTypeTimeseriesVisDataRequest } from '../../../types'; +import type { AbstractSearchStrategy, DefaultSearchCapabilities } from '../index'; +import type { IndexPatternsService } from '../../../../../data/common'; +import type { CachedIndexPatternFetcher } from './cached_index_pattern_fetcher'; export interface FieldsFetcherServices { indexPatternsService: IndexPatternsService; @@ -33,11 +33,11 @@ export const createFieldsFetcher = ( if (fieldsCacheMap.has(index)) { return fieldsCacheMap.get(index); } + const fetchedIndex = await cachedIndexPatternFetcher(index); const fields = await searchStrategy.getFieldsForWildcard( - index, + fetchedIndex, indexPatternsService, - cachedIndexPatternFetcher, capabilities ); diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_strategy_registry.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_strategy_registry.ts index 6445b3099a8cb..4a013fd89735d 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_strategy_registry.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_strategy_registry.ts @@ -8,7 +8,7 @@ import { VisTypeTimeseriesRequest, VisTypeTimeseriesRequestHandlerContext } from '../../types'; import { AbstractSearchStrategy } from './strategies'; -import { IndexPatternObject } from '../../../common/types'; +import { FetchedIndexPattern } from '../../../common/types'; export class SearchStrategyRegistry { private strategies: AbstractSearchStrategy[] = []; @@ -23,13 +23,13 @@ export class SearchStrategyRegistry { async getViableStrategy( requestContext: VisTypeTimeseriesRequestHandlerContext, req: VisTypeTimeseriesRequest, - indexPatternObject: IndexPatternObject + fetchedIndexPattern: FetchedIndexPattern ) { for (const searchStrategy of this.strategies) { const { isViable, capabilities } = await searchStrategy.checkForViability( requestContext, req, - indexPatternObject + fetchedIndexPattern ); if (isViable) { diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.test.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.test.ts index 757b2919c8a25..b6d7dc2aff31b 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.test.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.test.ts @@ -23,7 +23,6 @@ class FooSearchStrategy extends AbstractSearchStrategy {} describe('AbstractSearchStrategy', () => { let abstractSearchStrategy: AbstractSearchStrategy; let mockedFields: IFieldType[]; - let indexPattern: string; let requestContext: VisTypeTimeseriesRequestHandlerContext; beforeEach(() => { @@ -51,7 +50,7 @@ describe('AbstractSearchStrategy', () => { test('should return fields for wildcard', async () => { const fields = await abstractSearchStrategy.getFieldsForWildcard( - indexPattern, + { indexPatternString: '', indexPattern: undefined }, ({ getDefault: jest.fn(), getFieldsForWildcard: jest.fn(() => Promise.resolve(mockedFields)), diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts index f27a4ceeaa68d..f27533f1f3ebb 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts @@ -9,13 +9,12 @@ import { indexPatterns, IndexPatternsService } from '../../../../../data/server'; import type { FieldSpec } from '../../../../../data/common'; -import type { IndexPatternObject, SanitizedFieldType } from '../../../../common/types'; +import type { SanitizedFieldType, FetchedIndexPattern } from '../../../../common/types'; import type { VisTypeTimeseriesRequest, VisTypeTimeseriesRequestHandlerContext, VisTypeTimeseriesVisDataRequest, } from '../../../types'; -import { CachedIndexPatternFetcher } from '../lib/cached_index_pattern_fetcher'; export const toSanitizedFieldType = (fields: FieldSpec[]) => { return fields @@ -64,30 +63,25 @@ export abstract class AbstractSearchStrategy { checkForViability( requestContext: VisTypeTimeseriesRequestHandlerContext, req: VisTypeTimeseriesRequest, - indexPatternObject: IndexPatternObject + fetchedIndexPattern: FetchedIndexPattern ): Promise<{ isViable: boolean; capabilities: any }> { throw new TypeError('Must override method'); } async getFieldsForWildcard( - indexPatternObject: IndexPatternObject, + fetchedIndexPattern: FetchedIndexPattern, indexPatternsService: IndexPatternsService, - cachedIndexPatternFetcher: CachedIndexPatternFetcher, capabilities?: unknown, options?: Partial<{ type: string; rollupIndex: string; }> ) { - const { indexPattern, indexPatternString } = await cachedIndexPatternFetcher( - indexPatternObject - ); - return toSanitizedFieldType( - indexPattern - ? indexPattern.getNonScriptedFields() + fetchedIndexPattern.indexPattern + ? fetchedIndexPattern.indexPattern.getNonScriptedFields() : await indexPatternsService.getFieldsForWildcard({ - pattern: indexPatternString, + pattern: fetchedIndexPattern.indexPatternString, metaFields: [], ...options, }) diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/default_search_strategy.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/default_search_strategy.ts index de18809f6ded2..90915fca5401e 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/default_search_strategy.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/default_search_strategy.ts @@ -8,32 +8,30 @@ import { AbstractSearchStrategy } from './abstract_search_strategy'; import { DefaultSearchCapabilities } from '../capabilities/default_search_capabilities'; -import { VisTypeTimeseriesRequestHandlerContext, VisTypeTimeseriesRequest } from '../../../types'; import { IndexPatternsService } from '../../../../../data/server'; -import { CachedIndexPatternFetcher } from '../lib/cached_index_pattern_fetcher'; + +import type { FetchedIndexPattern } from '../../../../common/types'; +import type { + VisTypeTimeseriesRequestHandlerContext, + VisTypeTimeseriesRequest, +} from '../../../types'; export class DefaultSearchStrategy extends AbstractSearchStrategy { - checkForViability( + async checkForViability( requestContext: VisTypeTimeseriesRequestHandlerContext, req: VisTypeTimeseriesRequest ) { - return Promise.resolve({ + return { isViable: true, capabilities: new DefaultSearchCapabilities(req), - }); + }; } async getFieldsForWildcard( - indexPattern: string, + fetchedIndexPattern: FetchedIndexPattern, indexPatternsService: IndexPatternsService, - getCachedIndexPatternFetcher: CachedIndexPatternFetcher, capabilities?: unknown ) { - return super.getFieldsForWildcard( - indexPattern, - indexPatternsService, - getCachedIndexPatternFetcher, - capabilities - ); + return super.getFieldsForWildcard(fetchedIndexPattern, indexPatternsService, capabilities); } } diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.test.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.test.ts index bed4ecef5a7a6..4b2b9aebb21dc 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.test.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.test.ts @@ -99,7 +99,7 @@ describe('Rollup Search Strategy', () => { const result = await rollupSearchStrategy.checkForViability( requestContext, {} as VisTypeTimeseriesVisDataRequest, - (null as unknown) as string + { indexPatternString: (null as unknown) as string, indexPattern: undefined } ); expect(result).toEqual({ @@ -154,7 +154,7 @@ describe('Rollup Search Strategy', () => { test('should return fields for wildcard', async () => { const fields = await rollupSearchStrategy.getFieldsForWildcard( - indexPattern, + { indexPatternString: 'indexPattern', indexPattern: undefined }, {} as IndexPatternsService, (() => Promise.resolve({}) as unknown) as CachedIndexPatternFetcher, { diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.ts index e7a2fc722731a..e6333ca420e0d 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.ts @@ -7,21 +7,19 @@ */ import { getCapabilitiesForRollupIndices, IndexPatternsService } from '../../../../../data/server'; -import { +import { AbstractSearchStrategy } from './abstract_search_strategy'; +import { RollupSearchCapabilities } from '../capabilities/rollup_search_capabilities'; + +import type { FetchedIndexPattern } from '../../../../common/types'; +import type { CachedIndexPatternFetcher } from '../lib/cached_index_pattern_fetcher'; +import type { VisTypeTimeseriesRequest, VisTypeTimeseriesRequestHandlerContext, VisTypeTimeseriesVisDataRequest, } from '../../../types'; -import { AbstractSearchStrategy } from './abstract_search_strategy'; -import { RollupSearchCapabilities } from '../capabilities/rollup_search_capabilities'; -import { IndexPatternObject } from '../../../../common/types'; -import { CachedIndexPatternFetcher } from '../lib/cached_index_pattern_fetcher'; -import { convertIndexPatternObjectToStringRepresentation } from '../../../../common/index_patterns_utils'; const getRollupIndices = (rollupData: { [key: string]: any }) => Object.keys(rollupData); const isIndexPatternContainsWildcard = (indexPattern: string) => indexPattern.includes('*'); -const isIndexPatternValid = (indexPattern: string) => - indexPattern && typeof indexPattern === 'string' && !isIndexPatternContainsWildcard(indexPattern); export class RollupSearchStrategy extends AbstractSearchStrategy { async search( @@ -52,15 +50,17 @@ export class RollupSearchStrategy extends AbstractSearchStrategy { async checkForViability( requestContext: VisTypeTimeseriesRequestHandlerContext, req: VisTypeTimeseriesRequest, - indexPatternObject: IndexPatternObject + { indexPatternString, indexPattern }: FetchedIndexPattern ) { let isViable = false; let capabilities = null; - const index = convertIndexPatternObjectToStringRepresentation(indexPatternObject); - - if (isIndexPatternValid(index)) { - const rollupData = await this.getRollupData(requestContext, index); + if ( + indexPatternString && + !isIndexPatternContainsWildcard(indexPatternString) && + (!indexPattern || indexPattern.type === 'rollup') + ) { + const rollupData = await this.getRollupData(requestContext, indexPatternString); const rollupIndices = getRollupIndices(rollupData); isViable = rollupIndices.length === 1; @@ -80,20 +80,14 @@ export class RollupSearchStrategy extends AbstractSearchStrategy { } async getFieldsForWildcard( - indexPatternObject: IndexPatternObject, + fetchedIndexPattern: FetchedIndexPattern, indexPatternsService: IndexPatternsService, getCachedIndexPatternFetcher: CachedIndexPatternFetcher, capabilities?: unknown ) { - return super.getFieldsForWildcard( - indexPatternObject, - indexPatternsService, - getCachedIndexPatternFetcher, - capabilities, - { - type: 'rollup', - rollupIndex: convertIndexPatternObjectToStringRepresentation(indexPatternObject), - } - ); + return super.getFieldsForWildcard(fetchedIndexPattern, indexPatternsService, capabilities, { + type: 'rollup', + rollupIndex: fetchedIndexPattern.indexPatternString, + }); } } diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/get_series_data.ts b/src/plugins/vis_type_timeseries/server/lib/vis_data/get_series_data.ts index e1bc9c29ecf61..d6c6a24f98709 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/get_series_data.ts +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/get_series_data.ts @@ -23,25 +23,18 @@ import type { import type { PanelSchema } from '../../../common/types'; import { PANEL_TYPES } from '../../../common/panel_types'; -import { - convertIndexPatternObjectToStringRepresentation, - extractIndexPatternObjects, -} from '../../../common/index_patterns_utils'; - export async function getSeriesData( requestContext: VisTypeTimeseriesRequestHandlerContext, req: VisTypeTimeseriesVisDataRequest, panel: PanelSchema, services: VisTypeTimeseriesRequestServices ) { - const indexPattern = extractIndexPatternObjects(panel, panel.default_index_pattern) - .map(convertIndexPatternObjectToStringRepresentation) - .join(','); + const fetchedIndex = await services.cachedIndexPatternFetcher(panel.index_pattern); const strategy = await services.searchStrategyRegistry.getViableStrategy( requestContext, req, - indexPattern + fetchedIndex ); if (!strategy) { diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/get_table_data.ts b/src/plugins/vis_type_timeseries/server/lib/vis_data/get_table_data.ts index b882d8b529d76..8f9916bab5e92 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/get_table_data.ts +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/get_table_data.ts @@ -17,7 +17,7 @@ import { handleErrorResponse } from './handle_error_response'; // @ts-expect-error import { processBucket } from './table/process_bucket'; -import { createFieldsFetcher } from './helpers/fields_fetcher'; +import { createFieldsFetcher } from '../search_strategies/lib/fields_fetcher'; import { extractFieldLabel } from '../../../common/calculate_label'; import type { VisTypeTimeseriesRequestHandlerContext, @@ -32,14 +32,12 @@ export async function getTableData( panel: PanelSchema, services: VisTypeTimeseriesRequestServices ) { - const { indexPattern, indexPatternString } = await services.cachedIndexPatternFetcher( - panel.index_pattern - ); + const fetchedIndex = await services.cachedIndexPatternFetcher(panel.index_pattern); const strategy = await services.searchStrategyRegistry.getViableStrategy( requestContext, req, - indexPatternString + fetchedIndex ); if (!strategy) { @@ -60,8 +58,8 @@ export async function getTableData( }); const calculatePivotLabel = async () => { - if (panel.pivot_id && indexPattern?.title) { - const fields = await extractFields(indexPattern.title); + if (panel.pivot_id && fetchedIndex.indexPattern?.title) { + const fields = await extractFields(fetchedIndex.indexPattern.title); return extractFieldLabel(fields, panel.pivot_id); } @@ -79,7 +77,7 @@ export async function getTableData( req, panel, services.esQueryConfig, - indexPattern, + fetchedIndex.indexPattern, capabilities, services.uiSettings ); @@ -87,7 +85,7 @@ export async function getTableData( const [resp] = await searchStrategy.search(requestContext, req, [ { body, - index: indexPatternString, + index: fetchedIndex.indexPatternString, }, ]); diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/series/handle_response_body.ts b/src/plugins/vis_type_timeseries/server/lib/vis_data/series/handle_response_body.ts index 22e0372c23526..49f1ec0f93de5 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/series/handle_response_body.ts +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/series/handle_response_body.ts @@ -12,7 +12,10 @@ import { PanelSchema } from '../../../../common/types'; import { buildProcessorFunction } from '../build_processor_function'; // @ts-expect-error import { processors } from '../response_processors/series'; -import { createFieldsFetcher, FieldsFetcherServices } from './../helpers/fields_fetcher'; +import { + createFieldsFetcher, + FieldsFetcherServices, +} from '../../search_strategies/lib/fields_fetcher'; import { VisTypeTimeseriesVisDataRequest } from '../../../types'; export function handleResponseBody( diff --git a/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/controls_references.ts b/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/controls_references.ts new file mode 100644 index 0000000000000..9419efad41b83 --- /dev/null +++ b/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/controls_references.ts @@ -0,0 +1,48 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { SavedObjectReference } from '../../../../../core/types'; + +export const extractControlsReferences = ( + visState: Record, + references: SavedObjectReference[] = [] +) => { + const controls = visState.params?.controls ?? []; + + controls.forEach((control: Record, i: number) => { + if (!control.indexPattern) { + return; + } + control.indexPatternRefName = `control_${i}_index_pattern`; + references.push({ + name: control.indexPatternRefName, + type: 'index-pattern', + id: control.indexPattern, + }); + delete control.indexPattern; + }); +}; + +export const injectControlsReferences = ( + visState: Record, + references: SavedObjectReference[] +) => { + const controls = visState.params?.controls ?? []; + + controls.forEach((control: Record) => { + if (!control.indexPatternRefName) { + return; + } + const reference = references.find((ref) => ref.name === control.indexPatternRefName); + if (!reference) { + throw new Error(`Could not find index pattern reference "${control.indexPatternRefName}"`); + } + control.indexPattern = reference.id; + delete control.indexPatternRefName; + }); +}; diff --git a/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/index.ts b/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/index.ts new file mode 100644 index 0000000000000..727005b7f1836 --- /dev/null +++ b/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export { extractReferences, injectReferences } from './saved_visualization_references'; diff --git a/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references.test.ts b/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/saved_visualization_references.test.ts similarity index 97% rename from src/plugins/visualizations/public/saved_visualizations/saved_visualization_references.test.ts rename to src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/saved_visualization_references.test.ts index f81054febcc44..3961d303382f0 100644 --- a/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references.test.ts +++ b/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/saved_visualization_references.test.ts @@ -7,8 +7,8 @@ */ import { extractReferences, injectReferences } from './saved_visualization_references'; -import { VisSavedObject } from '../types'; -import { SavedVisState } from '../../common'; +import { VisSavedObject } from '../../types'; +import { SavedVisState } from '../../../common'; describe('extractReferences', () => { test('extracts nothing if savedSearchId is empty', () => { diff --git a/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references.ts b/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/saved_visualization_references.ts similarity index 68% rename from src/plugins/visualizations/public/saved_visualizations/saved_visualization_references.ts rename to src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/saved_visualization_references.ts index 27b5a4542036b..4afd1bf5980a9 100644 --- a/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references.ts +++ b/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/saved_visualization_references.ts @@ -10,13 +10,16 @@ import { SavedObjectAttribute, SavedObjectAttributes, SavedObjectReference, -} from '../../../../core/public'; -import { VisSavedObject } from '../types'; +} from '../../../../../core/public'; +import { VisSavedObject } from '../../types'; import { extractSearchSourceReferences, injectSearchSourceReferences, SearchSourceFields, -} from '../../../data/public'; +} from '../../../../data/public'; + +import { extractTimeSeriesReferences, injectTimeSeriesReferences } from './timeseries_references'; +import { extractControlsReferences, injectControlsReferences } from './controls_references'; export function extractReferences({ attributes, @@ -50,19 +53,10 @@ export function extractReferences({ // Extract index patterns from controls if (updatedAttributes.visState) { const visState = JSON.parse(String(updatedAttributes.visState)); - const controls = (visState.params && visState.params.controls) || []; - controls.forEach((control: Record, i: number) => { - if (!control.indexPattern) { - return; - } - control.indexPatternRefName = `control_${i}_index_pattern`; - updatedReferences.push({ - name: control.indexPatternRefName, - type: 'index-pattern', - id: control.indexPattern, - }); - delete control.indexPattern; - }); + + extractControlsReferences(visState, updatedReferences); + extractTimeSeriesReferences(visState, updatedReferences); + updatedAttributes.visState = JSON.stringify(visState); } @@ -89,18 +83,9 @@ export function injectReferences(savedObject: VisSavedObject, references: SavedO savedObject.savedSearchId = savedSearchReference.id; delete savedObject.savedSearchRefName; } - if (savedObject.visState) { - const controls = (savedObject.visState.params && savedObject.visState.params.controls) || []; - controls.forEach((control: Record) => { - if (!control.indexPatternRefName) { - return; - } - const reference = references.find((ref) => ref.name === control.indexPatternRefName); - if (!reference) { - throw new Error(`Could not find index pattern reference "${control.indexPatternRefName}"`); - } - control.indexPattern = reference.id; - delete control.indexPatternRefName; - }); + + if (savedObject.visState?.params) { + injectControlsReferences(savedObject.visState, references); + injectTimeSeriesReferences(savedObject.visState, references); } } diff --git a/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/timeseries_references.ts b/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/timeseries_references.ts new file mode 100644 index 0000000000000..c825972bcc096 --- /dev/null +++ b/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/timeseries_references.ts @@ -0,0 +1,82 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { SavedObjectReference } from '../../../../../core/types'; + +/** @internal **/ +const REF_NAME_POSTFIX = '_ref_name'; + +/** @internal **/ +enum INDEX_TYPE { + KIBANA_INDEX_PATTERN = 'index-pattern', + STRING_INDEX_PATTERN = 'string-index-pattern', +} + +/** @internal **/ +type Action = (object: Record, key: string) => void; + +const doForExtractedIndices = (action: Action, visState: Record) => { + if (visState.type !== 'metrics') { + return; + } + + action(visState.params, 'index_pattern'); + + visState.params.series.forEach((series: any) => { + if (series.override_index_pattern) { + action(series, 'series_index_pattern'); + } + }); + + if (visState.params.annotations) { + visState.params.annotations.forEach((annotation: any) => { + action(annotation, 'index_pattern'); + }); + } +}; + +export const extractTimeSeriesReferences = ( + visState: Record, + references: SavedObjectReference[] = [] +) => { + let i = 0; + + doForExtractedIndices((object, key) => { + if (object[key]) { + const name = `ref_${++i}_index_pattern`; + + object[key + REF_NAME_POSTFIX] = name; + references.push({ + name, + type: object[key].id ? INDEX_TYPE.KIBANA_INDEX_PATTERN : INDEX_TYPE.STRING_INDEX_PATTERN, + id: object[key].id || object[key], + }); + delete object[key]; + } + }, visState); +}; + +export const injectTimeSeriesReferences = ( + visState: Record, + references: SavedObjectReference[] +) => { + doForExtractedIndices((object, key) => { + const refKey = key + REF_NAME_POSTFIX; + + if (object[refKey]) { + const refValue = references.find((ref) => ref.name === object[refKey]); + + if (refValue) { + object[key] = + refValue.type === INDEX_TYPE.KIBANA_INDEX_PATTERN ? { id: refValue.id } : refValue.id; + } + + delete object[refKey]; + } + }, visState); +}; From 4df3d13580a497cdf702b7ed03fdfb663474dab8 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Thu, 18 Mar 2021 16:13:20 +0300 Subject: [PATCH 26/39] remove wrong logic --- .../common/index_patterns_utils.test.ts | 14 -------------- .../common/index_patterns_utils.ts | 4 +--- 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/src/plugins/vis_type_timeseries/common/index_patterns_utils.test.ts b/src/plugins/vis_type_timeseries/common/index_patterns_utils.test.ts index a541288e07d36..929391662468e 100644 --- a/src/plugins/vis_type_timeseries/common/index_patterns_utils.test.ts +++ b/src/plugins/vis_type_timeseries/common/index_patterns_utils.test.ts @@ -135,19 +135,5 @@ describe('fetchIndexPattern', () => { } `); }); - - test('should return default index if Kibana index not found', async () => { - const value = await fetchIndexPattern({ id: 'indexId' }, indexPatternsService); - - expect(value).toMatchInlineSnapshot(` - Object { - "indexPattern": Object { - "id": "default", - "title": "index", - }, - "indexPatternString": "index", - } - `); - }); }); }); diff --git a/src/plugins/vis_type_timeseries/common/index_patterns_utils.ts b/src/plugins/vis_type_timeseries/common/index_patterns_utils.ts index 4905b0cfc287d..d07dc977cac1a 100644 --- a/src/plugins/vis_type_timeseries/common/index_patterns_utils.ts +++ b/src/plugins/vis_type_timeseries/common/index_patterns_utils.ts @@ -69,9 +69,7 @@ export const fetchIndexPattern = async ( indexPatternString = indexPatternObject; } } else if (indexPatternObject.id) { - indexPattern = - (await indexPatternsService.get(indexPatternObject.id)) ?? - (await indexPatternsService.getDefault()); + indexPattern = await indexPatternsService.get(indexPatternObject.id); } } From ecdb580e19393a843cb722d3d380ea8687429c37 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Fri, 19 Mar 2021 12:57:46 +0300 Subject: [PATCH 27/39] fix JEST --- .../lib/cached_index_pattern_fetcher.test.ts | 7 ++----- .../search_strategies/search_strategies_registry.test.ts | 6 ++---- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/cached_index_pattern_fetcher.test.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/cached_index_pattern_fetcher.test.ts index 016960691dd83..aeaf3ca2cd327 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/cached_index_pattern_fetcher.test.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/cached_index_pattern_fetcher.test.ts @@ -102,11 +102,8 @@ describe('CachedIndexPatternFetcher', () => { expect(value).toMatchInlineSnapshot(` Object { - "indexPattern": Object { - "id": "default", - "title": "index", - }, - "indexPatternString": "index", + "indexPattern": undefined, + "indexPatternString": "", } `); }); diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_strategies_registry.test.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_strategies_registry.test.ts index 7b3e6a2888431..a6e7c5b11ee64 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_strategies_registry.test.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/search_strategies_registry.test.ts @@ -45,12 +45,11 @@ describe('SearchStrategyRegister', () => { test('should return a DefaultSearchStrategy instance', async () => { const req = {} as VisTypeTimeseriesRequest; - const indexPattern = '*'; const { searchStrategy, capabilities } = (await registry.getViableStrategy( requestContext, req, - indexPattern + { indexPatternString: '*', indexPattern: undefined } ))!; expect(searchStrategy instanceof DefaultSearchStrategy).toBe(true); @@ -67,14 +66,13 @@ describe('SearchStrategyRegister', () => { test('should return a MockSearchStrategy instance', async () => { const req = {} as VisTypeTimeseriesRequest; - const indexPattern = '*'; const anotherSearchStrategy = new MockSearchStrategy(); registry.addStrategy(anotherSearchStrategy); const { searchStrategy, capabilities } = (await registry.getViableStrategy( requestContext, req, - indexPattern + { indexPatternString: '*', indexPattern: undefined } ))!; expect(searchStrategy instanceof MockSearchStrategy).toBe(true); From 83d958de93b41c074cfd9fd21f019a22b80559f8 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Fri, 19 Mar 2021 17:13:17 +0300 Subject: [PATCH 28/39] fix some ui issues --- .../vis_type_timeseries/common/types.ts | 2 +- .../index_pattern_select/combo_box_select.tsx | 25 +++---- .../field_text_select.tsx | 14 ++-- .../index_pattern_select.tsx | 71 +++++++++++-------- .../index_pattern_select/migrate_popover.tsx | 20 +++--- .../switch_mode_popover.tsx | 8 ++- .../lib/index_pattern_select/types.ts | 6 +- .../timeseries_references.ts | 14 ++-- 8 files changed, 90 insertions(+), 70 deletions(-) diff --git a/src/plugins/vis_type_timeseries/common/types.ts b/src/plugins/vis_type_timeseries/common/types.ts index 82563d8748553..0aa1d0e22cdbe 100644 --- a/src/plugins/vis_type_timeseries/common/types.ts +++ b/src/plugins/vis_type_timeseries/common/types.ts @@ -30,7 +30,7 @@ export type IndexPatternObject = TypeOf; export interface FetchedIndexPattern { indexPattern: IndexPattern | undefined | null; - indexPatternString: string; + indexPatternString: string | undefined; } interface PanelData { diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/combo_box_select.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/combo_box_select.tsx index 8a7314134a77a..0e1713d6c05f7 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/combo_box_select.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/combo_box_select.tsx @@ -38,17 +38,25 @@ export const ComboBoxSelect = ({ const [availableIndexes, setAvailableIndexes] = useState([]); const [selectedOptions, setSelectedOptions] = useState([]); + const onComboBoxChange: EuiComboBoxProps['onChange'] = useCallback( + ([selected]) => { + onIndexChange(selected ? { id: selected.id } : ''); + }, + [onIndexChange] + ); + useEffect(() => { let options: SelectedOptions = []; + const { indexPattern, indexPatternString } = fetchedIndex; - if (fetchedIndex) { - if (!fetchedIndex.indexPattern) { - options = [{ label: fetchedIndex.indexPatternString ?? '' }]; + if (indexPattern || indexPatternString) { + if (!indexPattern) { + options = [{ label: indexPatternString ?? '' }]; } else { options = [ { - id: fetchedIndex.indexPattern.id, - label: fetchedIndex.indexPattern.title, + id: indexPattern.id, + label: indexPattern.title, }, ]; } @@ -56,13 +64,6 @@ export const ComboBoxSelect = ({ setSelectedOptions(options); }, [fetchedIndex]); - const onComboBoxChange: EuiComboBoxProps['onChange'] = useCallback( - ([selected]) => { - onIndexChange(selected ? { id: selected.id } : ''); - }, - [onIndexChange] - ); - useEffect(() => { async function fetchIndexes() { setAvailableIndexes(await getDataStart().indexPatterns.getIdsWithTitle()); diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/field_text_select.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/field_text_select.tsx index 5e176eeeaec74..fff5e86395273 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/field_text_select.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/field_text_select.tsx @@ -5,7 +5,7 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import React, { useCallback, useState } from 'react'; +import React, { useCallback, useState, useEffect } from 'react'; import useDebounce from 'react-use/lib/useDebounce'; import { EuiFieldText, EuiFieldTextProps } from '@elastic/eui'; @@ -22,16 +22,20 @@ export const FieldTextSelect = ({ allowSwitchMode, 'data-test-subj': dataTestSubj, }: SelectIndexComponentProps) => { - const textualValue = fetchedIndex?.indexPatternString ?? ''; - const [inputValue, setInputValue] = useState(textualValue); + const [inputValue, setInputValue] = useState(); + const { indexPatternString } = fetchedIndex; const onFieldTextChange: EuiFieldTextProps['onChange'] = useCallback((e) => { setInputValue(e.target.value); }, []); + useEffect(() => { + setInputValue(indexPatternString ?? ''); + }, [indexPatternString]); + useDebounce( () => { - if (inputValue !== textualValue) { + if (inputValue !== indexPatternString) { onIndexChange(inputValue); } }, @@ -43,7 +47,7 @@ export const FieldTextSelect = ({ { const htmlId = htmlIdGenerator(); const panelModel = useContext(PanelModelContext); - const [fetchedIndex, setFetchedIndex] = useState(); - + const [fetchedIndex, setFetchedIndex] = useState(); const useKibanaIndices = Boolean(panelModel?.[USE_KIBANA_INDEXES_KEY]); const Component = useKibanaIndices ? ComboBoxSelect : FieldTextSelect; - useEffect(() => { - async function fetchIndex() { - const { indexPatterns } = getDataStart(); - - setFetchedIndex(value ? await fetchIndexPattern(value, indexPatterns) : undefined); - } - - fetchIndex(); - }, [value]); + const onIndexChange = useCallback( + (index: IndexPatternObject) => { + onChange({ + [indexPatternName]: index, + }); + }, + [indexPatternName, onChange] + ); const onModeChange = useCallback( - (useKibanaIndexes: boolean) => { + (useKibanaIndexes: boolean, index?: FetchedIndexPattern) => { onChange({ [USE_KIBANA_INDEXES_KEY]: useKibanaIndexes, - [indexPatternName]: fetchedIndex?.indexPattern + [indexPatternName]: index?.indexPattern?.id ? { - id: fetchedIndex.indexPattern.id!, + id: index.indexPattern.id, } : '', }); }, - [onChange, fetchedIndex, indexPatternName] + [onChange, indexPatternName] ); - const onIndexChange = useCallback( - (index: IndexPatternObject) => { - onChange({ - [indexPatternName]: index, - }); - }, - [indexPatternName, onChange] - ); + useEffect(() => { + async function fetchIndex() { + const { indexPatterns } = getDataStart(); + + setFetchedIndex( + value + ? await fetchIndexPattern(value, indexPatterns) + : { + indexPattern: undefined, + indexPatternString: undefined, + } + ); + } + + fetchIndex(); + }, [value]); + + if (!fetchedIndex) { + return null; + } return ( setIsPopoverOpen((isOpen) => !isOpen), []); const switchMode = useCallback(() => { - onModeChange(true); - }, [onModeChange]); + onModeChange(true, fetchedIndex); + }, [onModeChange, fetchedIndex]); const navigateToCreateIndexPatterns = useCallback(() => { - getCoreStart().application.navigateToApp('management', { - path: `/kibana/indexPatterns/create?name=${fetchedIndex?.indexPatternString ?? ''}`, + const coreStart = getCoreStart(); + + coreStart.application.navigateToApp('management', { + path: `/kibana/indexPatterns/create?name=${fetchedIndex.indexPatternString ?? ''}`, }); }, [fetchedIndex]); - if (!fetchedIndex) { + if (!fetchedIndex.indexPatternString) { return null; } diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/switch_mode_popover.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/switch_mode_popover.tsx index 3b186af65336b..5f5506ce4a332 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/switch_mode_popover.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/switch_mode_popover.tsx @@ -7,6 +7,9 @@ */ import React, { useState, useCallback } from 'react'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; + import { EuiButtonIcon, EuiPopover, @@ -15,9 +18,8 @@ import { EuiSwitch, EuiText, } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { PopoverProps } from './types'; + +import type { PopoverProps } from './types'; export const SwitchModePopover = ({ onModeChange, useKibanaIndices }: PopoverProps) => { const [isPopoverOpen, setIsPopoverOpen] = useState(false); diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/types.ts b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/types.ts index 58a9e6dadb60d..0e7eed0d16654 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/types.ts +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/types.ts @@ -5,14 +5,14 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import { Assign } from '@kbn/utility-types'; +import type { Assign } from '@kbn/utility-types'; import type { FetchedIndexPattern, IndexPatternObject } from '../../../../../common/types'; /** @internal **/ export interface SelectIndexComponentProps { - fetchedIndex: FetchedIndexPattern | undefined; + fetchedIndex: FetchedIndexPattern; onIndexChange: (value: IndexPatternObject) => void; - onModeChange: (useKibanaIndexes: boolean) => void; + onModeChange: (useKibanaIndexes: boolean, index?: FetchedIndexPattern) => void; 'data-test-subj': string; placeholder?: string; disabled?: boolean; diff --git a/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/timeseries_references.ts b/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/timeseries_references.ts index c825972bcc096..2a3fccb797799 100644 --- a/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/timeseries_references.ts +++ b/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/timeseries_references.ts @@ -12,10 +12,7 @@ import { SavedObjectReference } from '../../../../../core/types'; const REF_NAME_POSTFIX = '_ref_name'; /** @internal **/ -enum INDEX_TYPE { - KIBANA_INDEX_PATTERN = 'index-pattern', - STRING_INDEX_PATTERN = 'string-index-pattern', -} +const INDEX_PATTERN_REF_TYPE = 'index_pattern'; /** @internal **/ type Action = (object: Record, key: string) => void; @@ -47,14 +44,14 @@ export const extractTimeSeriesReferences = ( let i = 0; doForExtractedIndices((object, key) => { - if (object[key]) { + if (object[key] && object[key].id) { const name = `ref_${++i}_index_pattern`; object[key + REF_NAME_POSTFIX] = name; references.push({ name, - type: object[key].id ? INDEX_TYPE.KIBANA_INDEX_PATTERN : INDEX_TYPE.STRING_INDEX_PATTERN, - id: object[key].id || object[key], + type: INDEX_PATTERN_REF_TYPE, + id: object[key].id, }); delete object[key]; } @@ -72,8 +69,7 @@ export const injectTimeSeriesReferences = ( const refValue = references.find((ref) => ref.name === object[refKey]); if (refValue) { - object[key] = - refValue.type === INDEX_TYPE.KIBANA_INDEX_PATTERN ? { id: refValue.id } : refValue.id; + object[key] = { id: refValue.id }; } delete object[refKey]; From 9fd52a932d989d6e764a530735e71e4187fbcbdb Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Fri, 19 Mar 2021 17:56:25 +0300 Subject: [PATCH 29/39] update sample data --- .../data_sets/ecommerce/saved_objects.ts | 25 ++++++++++++++++--- .../data_sets/flights/saved_objects.ts | 15 +++++++++-- .../data_sets/logs/saved_objects.ts | 25 ++++++++++++++++--- .../lib/cached_index_pattern_fetcher.ts | 5 ++-- .../strategies/abstract_search_strategy.ts | 2 +- .../strategies/default_search_strategy.ts | 2 +- .../strategies/rollup_search_strategy.test.ts | 7 +++--- .../server/lib/vis_data/get_series_data.ts | 6 ++--- .../server/lib/vis_data/get_table_data.ts | 12 ++++----- .../lib/vis_data/series/get_request_params.ts | 23 +++++++++++------ 10 files changed, 88 insertions(+), 34 deletions(-) diff --git a/src/plugins/home/server/services/sample_data/data_sets/ecommerce/saved_objects.ts b/src/plugins/home/server/services/sample_data/data_sets/ecommerce/saved_objects.ts index 9b69dacd8fdb5..cfac42b97c686 100644 --- a/src/plugins/home/server/services/sample_data/data_sets/ecommerce/saved_objects.ts +++ b/src/plugins/home/server/services/sample_data/data_sets/ecommerce/saved_objects.ts @@ -109,7 +109,7 @@ export const getSavedObjects = (): SavedObject[] => [ defaultMessage: '[eCommerce] Promotion Tracking', }), visState: - '{"title":"[eCommerce] Promotion Tracking","type":"metrics","params":{"id":"61ca57f0-469d-11e7-af02-69e470af7417","type":"timeseries","series":[{"id":"ea20ae70-b88d-11e8-a451-f37365e9f268","color":"rgba(240,138,217,1)","split_mode":"everything","metrics":[{"id":"ea20ae71-b88d-11e8-a451-f37365e9f268","type":"sum","field":"taxful_total_price"}],"separate_axis":0,"axis_position":"right","formatter":"number","chart_type":"line","line_width":1,"point_size":1,"fill":"0.7","stacked":"none","filter":"products.product_name:*trouser*","label":"Revenue Trousers","value_template":"${{value}}"},{"id":"062d77b0-b88e-11e8-a451-f37365e9f268","color":"rgba(191,240,129,1)","split_mode":"everything","metrics":[{"id":"062d77b1-b88e-11e8-a451-f37365e9f268","type":"sum","field":"taxful_total_price"}],"separate_axis":0,"axis_position":"right","formatter":"number","chart_type":"line","line_width":1,"point_size":1,"fill":"0.7","stacked":"none","filter":"products.product_name:*watch*","label":"Revenue Watches","value_template":"${{value}}"},{"id":"61ca57f1-469d-11e7-af02-69e470af7417","color":"rgba(23,233,230,1)","split_mode":"everything","metrics":[{"id":"61ca57f2-469d-11e7-af02-69e470af7417","type":"sum","field":"taxful_total_price"}],"separate_axis":0,"axis_position":"right","formatter":"number","chart_type":"line","line_width":1,"point_size":1,"fill":"0.7","stacked":"none","filter":"products.product_name:*bag*","label":"Revenue Bags","value_template":"${{value}}"},{"id":"faa2c170-b88d-11e8-a451-f37365e9f268","color":"rgba(235,186,180,1)","split_mode":"everything","metrics":[{"id":"faa2c171-b88d-11e8-a451-f37365e9f268","type":"sum","field":"taxful_total_price"}],"separate_axis":0,"axis_position":"right","formatter":"number","chart_type":"line","line_width":1,"point_size":1,"fill":"0.7","stacked":"none","filter":"products.product_name:*cocktail dress*","label":"Revenue Cocktail Dresses","value_template":"${{value}}"}],"time_field":"order_date","index_pattern":"kibana_sample_data_ecommerce","interval":">=12h","axis_position":"left","axis_formatter":"number","axis_scale":"normal","show_legend":1,"show_grid":1,"legend_position":"bottom","annotations":[{"fields":"taxful_total_price","template":"Ring the bell! ${{taxful_total_price}}","index_pattern":"kibana_sample_data_ecommerce","query_string":"taxful_total_price:>250","id":"c8c30be0-b88f-11e8-a451-f37365e9f268","color":"rgba(25,77,51,1)","time_field":"order_date","icon":"fa-bell","ignore_global_filters":1,"ignore_panel_filters":1}]},"aggs":[]}', + '{"title":"[eCommerce] Promotion Tracking","type":"metrics","params":{"id":"61ca57f0-469d-11e7-af02-69e470af7417","type":"timeseries","series":[{"id":"ea20ae70-b88d-11e8-a451-f37365e9f268","color":"rgba(240,138,217,1)","split_mode":"everything","metrics":[{"id":"ea20ae71-b88d-11e8-a451-f37365e9f268","type":"sum","field":"taxful_total_price"}],"separate_axis":0,"axis_position":"right","formatter":"number","chart_type":"line","line_width":1,"point_size":1,"fill":"0.7","stacked":"none","filter":"products.product_name:*trouser*","label":"Revenue Trousers","value_template":"${{value}}"},{"id":"062d77b0-b88e-11e8-a451-f37365e9f268","color":"rgba(191,240,129,1)","split_mode":"everything","metrics":[{"id":"062d77b1-b88e-11e8-a451-f37365e9f268","type":"sum","field":"taxful_total_price"}],"separate_axis":0,"axis_position":"right","formatter":"number","chart_type":"line","line_width":1,"point_size":1,"fill":"0.7","stacked":"none","filter":"products.product_name:*watch*","label":"Revenue Watches","value_template":"${{value}}"},{"id":"61ca57f1-469d-11e7-af02-69e470af7417","color":"rgba(23,233,230,1)","split_mode":"everything","metrics":[{"id":"61ca57f2-469d-11e7-af02-69e470af7417","type":"sum","field":"taxful_total_price"}],"separate_axis":0,"axis_position":"right","formatter":"number","chart_type":"line","line_width":1,"point_size":1,"fill":"0.7","stacked":"none","filter":"products.product_name:*bag*","label":"Revenue Bags","value_template":"${{value}}"},{"id":"faa2c170-b88d-11e8-a451-f37365e9f268","color":"rgba(235,186,180,1)","split_mode":"everything","metrics":[{"id":"faa2c171-b88d-11e8-a451-f37365e9f268","type":"sum","field":"taxful_total_price"}],"separate_axis":0,"axis_position":"right","formatter":"number","chart_type":"line","line_width":1,"point_size":1,"fill":"0.7","stacked":"none","filter":"products.product_name:*cocktail dress*","label":"Revenue Cocktail Dresses","value_template":"${{value}}"}],"time_field":"order_date","index_pattern_ref_name":"ref_1_index_pattern","interval":">=12h","use_kibana_indexes":true,"axis_position":"left","axis_formatter":"number","axis_scale":"normal","show_legend":1,"show_grid":1,"legend_position":"bottom","annotations":[{"fields":"taxful_total_price","template":"Ring the bell! ${{taxful_total_price}}","index_pattern_ref_name":"ref_2_index_pattern","query_string":"taxful_total_price:>250","id":"c8c30be0-b88f-11e8-a451-f37365e9f268","color":"rgba(25,77,51,1)","time_field":"order_date","icon":"fa-bell","ignore_global_filters":1,"ignore_panel_filters":1}]},"aggs":[]}', uiStateJSON: '{}', description: '', version: 1, @@ -117,7 +117,18 @@ export const getSavedObjects = (): SavedObject[] => [ searchSourceJSON: '{"query":{"query":"","language":"kuery"},"filter":[]}', }, }, - references: [], + references: [ + { + name: 'ref_1_index_pattern', + type: 'index_pattern', + id: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', + }, + { + name: 'ref_2_index_pattern', + type: 'index_pattern', + id: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', + }, + ], }, { id: '10f1a240-b891-11e8-a6d9-e546fe2bba5f', @@ -152,7 +163,7 @@ export const getSavedObjects = (): SavedObject[] => [ defaultMessage: '[eCommerce] Sold Products per Day', }), visState: - '{"title":"[eCommerce] Sold Products per Day","type":"metrics","params":{"id":"61ca57f0-469d-11e7-af02-69e470af7417","type":"gauge","series":[{"id":"61ca57f1-469d-11e7-af02-69e470af7417","color":"#68BC00","split_mode":"everything","metrics":[{"id":"61ca57f2-469d-11e7-af02-69e470af7417","type":"count"}],"separate_axis":0,"axis_position":"right","formatter":"number","chart_type":"line","line_width":1,"point_size":1,"fill":0.5,"stacked":"none","label":"Trxns / day"}],"time_field":"order_date","index_pattern":"kibana_sample_data_ecommerce","interval":"1d","axis_position":"left","axis_formatter":"number","axis_scale":"normal","show_legend":1,"show_grid":1,"gauge_color_rules":[{"value":150,"id":"6da070c0-b891-11e8-b645-195edeb9de84","gauge":"rgba(104,188,0,1)","operator":"gte"},{"value":150,"id":"9b0cdbc0-b891-11e8-b645-195edeb9de84","gauge":"rgba(244,78,59,1)","operator":"lt"}],"gauge_width":"15","gauge_inner_width":10,"gauge_style":"half","filter":"","gauge_max":"300"},"aggs":[]}', + '{"title":"[eCommerce] Sold Products per Day","type":"metrics","params":{"id":"61ca57f0-469d-11e7-af02-69e470af7417","type":"gauge","series":[{"id":"61ca57f1-469d-11e7-af02-69e470af7417","color":"#68BC00","split_mode":"everything","metrics":[{"id":"61ca57f2-469d-11e7-af02-69e470af7417","type":"count"}],"separate_axis":0,"axis_position":"right","formatter":"number","chart_type":"line","line_width":1,"point_size":1,"fill":0.5,"stacked":"none","label":"Trxns / day"}],"time_field":"order_date","index_pattern_ref_name":"ref_1_index_pattern","interval":"1d","axis_position":"left","axis_formatter":"number","axis_scale":"normal","show_legend":1,"show_grid":1,"gauge_color_rules":[{"value":150,"id":"6da070c0-b891-11e8-b645-195edeb9de84","gauge":"rgba(104,188,0,1)","operator":"gte"},{"value":150,"id":"9b0cdbc0-b891-11e8-b645-195edeb9de84","gauge":"rgba(244,78,59,1)","operator":"lt"}],"gauge_width":"15","gauge_inner_width":10,"gauge_style":"half","filter":"","gauge_max":"300","use_kibana_indexes":true},"aggs":[]}', uiStateJSON: '{}', description: '', version: 1, @@ -160,7 +171,13 @@ export const getSavedObjects = (): SavedObject[] => [ searchSourceJSON: '{"query":{"query":"","language":"kuery"},"filter":[]}', }, }, - references: [], + references: [ + { + name: 'ref_1_index_pattern', + type: 'index_pattern', + id: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', + }, + ], }, { id: '4b3ec120-b892-11e8-a6d9-e546fe2bba5f', diff --git a/src/plugins/home/server/services/sample_data/data_sets/flights/saved_objects.ts b/src/plugins/home/server/services/sample_data/data_sets/flights/saved_objects.ts index b316835029d7c..f16c1c7104417 100644 --- a/src/plugins/home/server/services/sample_data/data_sets/flights/saved_objects.ts +++ b/src/plugins/home/server/services/sample_data/data_sets/flights/saved_objects.ts @@ -144,7 +144,7 @@ export const getSavedObjects = (): SavedObject[] => [ defaultMessage: '[Flights] Delays & Cancellations', }), visState: - '{"title":"[Flights] Delays & Cancellations","type":"metrics","params":{"id":"61ca57f0-469d-11e7-af02-69e470af7417","type":"timeseries","series":[{"id":"61ca57f1-469d-11e7-af02-69e470af7417","color":"rgba(0,156,224,1)","split_mode":"everything","metrics":[{"id":"61ca57f2-469d-11e7-af02-69e470af7417","type":"filter_ratio","numerator":"FlightDelay:true"}],"separate_axis":0,"axis_position":"right","formatter":"percent","chart_type":"line","line_width":"2","point_size":"0","fill":0.5,"stacked":"none","label":"Percent Delays"}],"time_field":"timestamp","index_pattern":"kibana_sample_data_flights","interval":">=1h","axis_position":"left","axis_formatter":"number","show_legend":1,"show_grid":1,"annotations":[{"fields":"FlightDelay,Cancelled,Carrier","template":"{{Carrier}}: Flight Delayed and Cancelled!","index_pattern":"kibana_sample_data_flights","query_string":"FlightDelay:true AND Cancelled:true","id":"53b7dff0-4c89-11e8-a66a-6989ad5a0a39","color":"rgba(0,98,177,1)","time_field":"timestamp","icon":"fa-exclamation-triangle","ignore_global_filters":1,"ignore_panel_filters":1}],"legend_position":"bottom"},"aggs":[]}', + '{"title":"[Flights] Delays & Cancellations","type":"metrics","params":{"id":"61ca57f0-469d-11e7-af02-69e470af7417","type":"timeseries","series":[{"id":"61ca57f1-469d-11e7-af02-69e470af7417","color":"rgba(0,156,224,1)","split_mode":"everything","metrics":[{"id":"61ca57f2-469d-11e7-af02-69e470af7417","type":"filter_ratio","numerator":"FlightDelay:true"}],"separate_axis":0,"axis_position":"right","formatter":"percent","chart_type":"line","line_width":"2","point_size":"0","fill":0.5,"stacked":"none","label":"Percent Delays"}],"time_field":"timestamp","index_pattern_ref_name":"ref_1_index_pattern","interval":">=1h","axis_position":"left","axis_formatter":"number","show_legend":1,"show_grid":1,"annotations":[{"fields":"FlightDelay,Cancelled,Carrier","template":"{{Carrier}}: Flight Delayed and Cancelled!","index_pattern_ref_name":"ref_2_index_pattern","query_string":"FlightDelay:true AND Cancelled:true","id":"53b7dff0-4c89-11e8-a66a-6989ad5a0a39","color":"rgba(0,98,177,1)","time_field":"timestamp","icon":"fa-exclamation-triangle","ignore_global_filters":1,"ignore_panel_filters":1}],"legend_position":"bottom","use_kibana_indexes":true},"aggs":[]}', uiStateJSON: '{}', description: '', version: 1, @@ -152,7 +152,18 @@ export const getSavedObjects = (): SavedObject[] => [ searchSourceJSON: '{}', }, }, - references: [], + references: [ + { + name: 'ref_1_index_pattern', + type: 'index_pattern', + id: 'd3d7af60-4c81-11e8-b3d7-01146121b73d' + }, + { + name: 'ref_2_index_pattern', + type: 'index_pattern', + id: 'd3d7af60-4c81-11e8-b3d7-01146121b73d' + } + ] }, { id: '9886b410-4c8b-11e8-b3d7-01146121b73d', diff --git a/src/plugins/home/server/services/sample_data/data_sets/logs/saved_objects.ts b/src/plugins/home/server/services/sample_data/data_sets/logs/saved_objects.ts index 0396cb58d3692..8a3469fe4f3c0 100644 --- a/src/plugins/home/server/services/sample_data/data_sets/logs/saved_objects.ts +++ b/src/plugins/home/server/services/sample_data/data_sets/logs/saved_objects.ts @@ -89,7 +89,7 @@ export const getSavedObjects = (): SavedObject[] => [ defaultMessage: '[Logs] Host, Visits and Bytes Table', }), visState: - '{"title":"[Logs] Host, Visits and Bytes Table","type":"metrics","params":{"id":"61ca57f0-469d-11e7-af02-69e470af7417","type":"table","series":[{"id":"bd09d600-e5b1-11e7-bfc2-a1f7e71965a1","color":"#68BC00","split_mode":"everything","metrics":[{"id":"bd09d601-e5b1-11e7-bfc2-a1f7e71965a1","type":"sum","field":"bytes"},{"sigma":"","id":"c9514c90-e5b1-11e7-bfc2-a1f7e71965a1","type":"sum_bucket","field":"bd09d601-e5b1-11e7-bfc2-a1f7e71965a1"}],"seperate_axis":0,"axis_position":"right","formatter":"bytes","chart_type":"line","line_width":1,"point_size":1,"fill":0.5,"stacked":"none","color_rules":[{"id":"c0c668d0-e5b1-11e7-bfc2-a1f7e71965a1"}],"label":"Bytes (Total)"},{"id":"b7672c30-a6df-11e8-8b18-1da1dfc50975","color":"#68BC00","split_mode":"everything","metrics":[{"id":"b7672c31-a6df-11e8-8b18-1da1dfc50975","type":"sum","field":"bytes"}],"seperate_axis":0,"axis_position":"right","formatter":"bytes","chart_type":"line","line_width":1,"point_size":1,"fill":0.5,"stacked":"none","color_rules":[{"id":"c0c668d0-e5b1-11e7-bfc2-a1f7e71965a1"}],"label":"Bytes (Last Hour)"},{"id":"f2c20700-a6df-11e8-8b18-1da1dfc50975","color":"#68BC00","split_mode":"everything","metrics":[{"id":"f2c20701-a6df-11e8-8b18-1da1dfc50975","type":"cardinality","field":"ip"},{"sigma":"","id":"f46333e0-a6df-11e8-8b18-1da1dfc50975","type":"sum_bucket","field":"f2c20701-a6df-11e8-8b18-1da1dfc50975"}],"seperate_axis":0,"axis_position":"right","formatter":"number","chart_type":"line","line_width":1,"point_size":1,"fill":0.5,"stacked":"none","label":"Unique Visits (Total)","color_rules":[{"value":1000,"id":"2e963080-a6e0-11e8-8b18-1da1dfc50975","text":"rgba(211,49,21,1)","operator":"lt"},{"value":1000,"id":"3d4fb880-a6e0-11e8-8b18-1da1dfc50975","text":"rgba(252,196,0,1)","operator":"gte"},{"value":1500,"id":"435f8a20-a6e0-11e8-8b18-1da1dfc50975","text":"rgba(104,188,0,1)","operator":"gte"}],"offset_time":"","value_template":"","trend_arrows":1},{"id":"46fd7fc0-e5b1-11e7-bfc2-a1f7e71965a1","color":"#68BC00","split_mode":"everything","metrics":[{"id":"46fd7fc1-e5b1-11e7-bfc2-a1f7e71965a1","type":"cardinality","field":"ip"}],"seperate_axis":0,"axis_position":"right","formatter":"number","chart_type":"line","line_width":1,"point_size":1,"fill":0.5,"stacked":"none","label":"Unique Visits (Last Hour)","color_rules":[{"value":10,"id":"4e90aeb0-a6e0-11e8-8b18-1da1dfc50975","text":"rgba(211,49,21,1)","operator":"lt"},{"value":10,"id":"6d59b1c0-a6e0-11e8-8b18-1da1dfc50975","text":"rgba(252,196,0,1)","operator":"gte"},{"value":25,"id":"77578670-a6e0-11e8-8b18-1da1dfc50975","text":"rgba(104,188,0,1)","operator":"gte"}],"offset_time":"","value_template":"","trend_arrows":1}],"time_field":"timestamp","index_pattern":"kibana_sample_data_logs","interval":"1h","axis_position":"left","axis_formatter":"number","show_legend":1,"show_grid":1,"bar_color_rules":[{"id":"e9b4e490-e1c6-11e7-b4f6-0f68c45f7387"}],"pivot_id":"extension.keyword","pivot_label":"Type","drilldown_url":"","axis_scale":"normal"},"aggs":[]}', + '{"title":"[Logs] Host, Visits and Bytes Table","type":"metrics","params":{"id":"61ca57f0-469d-11e7-af02-69e470af7417","type":"table","series":[{"id":"bd09d600-e5b1-11e7-bfc2-a1f7e71965a1","color":"#68BC00","split_mode":"everything","metrics":[{"id":"bd09d601-e5b1-11e7-bfc2-a1f7e71965a1","type":"sum","field":"bytes"},{"sigma":"","id":"c9514c90-e5b1-11e7-bfc2-a1f7e71965a1","type":"sum_bucket","field":"bd09d601-e5b1-11e7-bfc2-a1f7e71965a1"}],"seperate_axis":0,"axis_position":"right","formatter":"bytes","chart_type":"line","line_width":1,"point_size":1,"fill":0.5,"stacked":"none","color_rules":[{"id":"c0c668d0-e5b1-11e7-bfc2-a1f7e71965a1"}],"label":"Bytes (Total)"},{"id":"b7672c30-a6df-11e8-8b18-1da1dfc50975","color":"#68BC00","split_mode":"everything","metrics":[{"id":"b7672c31-a6df-11e8-8b18-1da1dfc50975","type":"sum","field":"bytes"}],"seperate_axis":0,"axis_position":"right","formatter":"bytes","chart_type":"line","line_width":1,"point_size":1,"fill":0.5,"stacked":"none","color_rules":[{"id":"c0c668d0-e5b1-11e7-bfc2-a1f7e71965a1"}],"label":"Bytes (Last Hour)"},{"id":"f2c20700-a6df-11e8-8b18-1da1dfc50975","color":"#68BC00","split_mode":"everything","metrics":[{"id":"f2c20701-a6df-11e8-8b18-1da1dfc50975","type":"cardinality","field":"ip"},{"sigma":"","id":"f46333e0-a6df-11e8-8b18-1da1dfc50975","type":"sum_bucket","field":"f2c20701-a6df-11e8-8b18-1da1dfc50975"}],"seperate_axis":0,"axis_position":"right","formatter":"number","chart_type":"line","line_width":1,"point_size":1,"fill":0.5,"stacked":"none","label":"Unique Visits (Total)","color_rules":[{"value":1000,"id":"2e963080-a6e0-11e8-8b18-1da1dfc50975","text":"rgba(211,49,21,1)","operator":"lt"},{"value":1000,"id":"3d4fb880-a6e0-11e8-8b18-1da1dfc50975","text":"rgba(252,196,0,1)","operator":"gte"},{"value":1500,"id":"435f8a20-a6e0-11e8-8b18-1da1dfc50975","text":"rgba(104,188,0,1)","operator":"gte"}],"offset_time":"","value_template":"","trend_arrows":1},{"id":"46fd7fc0-e5b1-11e7-bfc2-a1f7e71965a1","color":"#68BC00","split_mode":"everything","metrics":[{"id":"46fd7fc1-e5b1-11e7-bfc2-a1f7e71965a1","type":"cardinality","field":"ip"}],"seperate_axis":0,"axis_position":"right","formatter":"number","chart_type":"line","line_width":1,"point_size":1,"fill":0.5,"stacked":"none","label":"Unique Visits (Last Hour)","color_rules":[{"value":10,"id":"4e90aeb0-a6e0-11e8-8b18-1da1dfc50975","text":"rgba(211,49,21,1)","operator":"lt"},{"value":10,"id":"6d59b1c0-a6e0-11e8-8b18-1da1dfc50975","text":"rgba(252,196,0,1)","operator":"gte"},{"value":25,"id":"77578670-a6e0-11e8-8b18-1da1dfc50975","text":"rgba(104,188,0,1)","operator":"gte"}],"offset_time":"","value_template":"","trend_arrows":1}],"time_field":"timestamp","index_pattern_ref_name":"ref_1_index_pattern","use_kibana_indexes": true,"interval":"1h","axis_position":"left","axis_formatter":"number","show_legend":1,"show_grid":1,"bar_color_rules":[{"id":"e9b4e490-e1c6-11e7-b4f6-0f68c45f7387"}],"pivot_id":"extension.keyword","pivot_label":"Type","drilldown_url":"","axis_scale":"normal"},"aggs":[]}', uiStateJSON: '{}', description: '', version: 1, @@ -97,7 +97,13 @@ export const getSavedObjects = (): SavedObject[] => [ searchSourceJSON: '{"query":{"query":"","language":"kuery"},"filter":[]}', }, }, - references: [], + references: [ + { + name: 'ref_1_index_pattern', + type: 'index_pattern', + id: '90943e30-9a47-11e8-b64d-95841ca0b247', + }, + ], }, { id: '69a34b00-9ee8-11e7-8711-e7a007dcef99', @@ -175,7 +181,7 @@ export const getSavedObjects = (): SavedObject[] => [ defaultMessage: '[Logs] Response Codes Over Time + Annotations', }), visState: - '{"title":"[Logs] Response Codes Over Time + Annotations","type":"metrics","params":{"id":"61ca57f0-469d-11e7-af02-69e470af7417","type":"timeseries","series":[{"id":"61ca57f1-469d-11e7-af02-69e470af7417","color":"rgba(115,216,255,1)","split_mode":"terms","metrics":[{"id":"61ca57f2-469d-11e7-af02-69e470af7417","type":"cardinality","field":"ip"}],"seperate_axis":0,"axis_position":"right","formatter":"percent","chart_type":"line","line_width":"2","point_size":"0","fill":"0.5","stacked":"percent","terms_field":"response.keyword","terms_order_by":"61ca57f2-469d-11e7-af02-69e470af7417","label":"Response Code Count","split_color_mode":"gradient"}],"time_field":"timestamp","index_pattern":"kibana_sample_data_logs","interval":">=4h","axis_position":"left","axis_formatter":"number","show_legend":1,"show_grid":1,"annotations":[{"fields":"geo.src, host","template":"Security Error from {{geo.src}} on {{host}}","index_pattern":"kibana_sample_data_logs","query_string":"tags:error AND tags:security","id":"bd7548a0-2223-11e8-832f-d5027f3c8a47","color":"rgba(211,49,21,1)","time_field":"timestamp","icon":"fa-asterisk","ignore_global_filters":1,"ignore_panel_filters":1}],"legend_position":"bottom","axis_scale":"normal","drop_last_bucket":0},"aggs":[]}', + '{"title":"[Logs] Response Codes Over Time + Annotations","type":"metrics","params":{"id":"61ca57f0-469d-11e7-af02-69e470af7417","type":"timeseries","series":[{"id":"61ca57f1-469d-11e7-af02-69e470af7417","color":"rgba(115,216,255,1)","split_mode":"terms","metrics":[{"id":"61ca57f2-469d-11e7-af02-69e470af7417","type":"cardinality","field":"ip"}],"seperate_axis":0,"axis_position":"right","formatter":"percent","chart_type":"line","line_width":"2","point_size":"0","fill":"0.5","stacked":"percent","terms_field":"response.keyword","terms_order_by":"61ca57f2-469d-11e7-af02-69e470af7417","label":"Response Code Count","split_color_mode":"gradient"}],"time_field":"timestamp","index_pattern_ref_name":"ref_1_index_pattern","use_kibana_indexes":true,"interval":">=4h","axis_position":"left","axis_formatter":"number","show_legend":1,"show_grid":1,"annotations":[{"fields":"geo.src, host","template":"Security Error from {{geo.src}} on {{host}}","index_pattern_ref_name":"ref_2_index_pattern","query_string":"tags:error AND tags:security","id":"bd7548a0-2223-11e8-832f-d5027f3c8a47","color":"rgba(211,49,21,1)","time_field":"timestamp","icon":"fa-asterisk","ignore_global_filters":1,"ignore_panel_filters":1}],"legend_position":"bottom","axis_scale":"normal","drop_last_bucket":0},"aggs":[]}', uiStateJSON: '{}', description: '', version: 1, @@ -183,7 +189,18 @@ export const getSavedObjects = (): SavedObject[] => [ searchSourceJSON: '{"query":{"query":"","language":"kuery"},"filter":[]}', }, }, - references: [], + references: [ + { + name: 'ref_1_index_pattern', + type: 'index_pattern', + id: '90943e30-9a47-11e8-b64d-95841ca0b247', + }, + { + name: 'ref_2_index_pattern', + type: 'index_pattern', + id: '90943e30-9a47-11e8-b64d-95841ca0b247', + }, + ], }, { id: '24a3e970-4257-11e8-b3aa-73fdaf54bfc9', diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/cached_index_pattern_fetcher.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/cached_index_pattern_fetcher.ts index 0277d5d70a3f7..78b859e1049bb 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/cached_index_pattern_fetcher.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/cached_index_pattern_fetcher.ts @@ -6,13 +6,14 @@ * Side Public License, v 1. */ -import { IndexPatternsService } from '../../../../../data/server'; -import { IndexPatternObject, FetchedIndexPattern } from '../../../../common/types'; import { getIndexPatternObjectKey, fetchIndexPattern, } from '../../../../common/index_patterns_utils'; +import type { IndexPatternsService } from '../../../../../data/server'; +import type { IndexPatternObject, FetchedIndexPattern } from '../../../../common/types'; + export const getCachedIndexPatternFetcher = (indexPatternsService: IndexPatternsService) => { const cache = new Map(); diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts index f27533f1f3ebb..a1fe120b75707 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts @@ -81,7 +81,7 @@ export abstract class AbstractSearchStrategy { fetchedIndexPattern.indexPattern ? fetchedIndexPattern.indexPattern.getNonScriptedFields() : await indexPatternsService.getFieldsForWildcard({ - pattern: fetchedIndexPattern.indexPatternString, + pattern: fetchedIndexPattern.indexPatternString ?? '', metaFields: [], ...options, }) diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/default_search_strategy.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/default_search_strategy.ts index 90915fca5401e..f95bf81b5c1d3 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/default_search_strategy.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/default_search_strategy.ts @@ -8,8 +8,8 @@ import { AbstractSearchStrategy } from './abstract_search_strategy'; import { DefaultSearchCapabilities } from '../capabilities/default_search_capabilities'; -import { IndexPatternsService } from '../../../../../data/server'; +import type { IndexPatternsService } from '../../../../../data/server'; import type { FetchedIndexPattern } from '../../../../common/types'; import type { VisTypeTimeseriesRequestHandlerContext, diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.test.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.test.ts index 4b2b9aebb21dc..c798f58b0b67b 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.test.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/rollup_search_strategy.test.ts @@ -7,12 +7,13 @@ */ import { RollupSearchStrategy } from './rollup_search_strategy'; -import { + +import type { IndexPatternsService } from '../../../../../data/common'; +import type { CachedIndexPatternFetcher } from '../lib/cached_index_pattern_fetcher'; +import type { VisTypeTimeseriesRequestHandlerContext, VisTypeTimeseriesVisDataRequest, } from '../../../types'; -import { IndexPatternsService } from '../../../../../data/common'; -import { CachedIndexPatternFetcher } from '../lib/cached_index_pattern_fetcher'; jest.mock('./abstract_search_strategy', () => { class AbstractSearchStrategyMock { diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/get_series_data.ts b/src/plugins/vis_type_timeseries/server/lib/vis_data/get_series_data.ts index d6c6a24f98709..13dc1207f51de 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/get_series_data.ts +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/get_series_data.ts @@ -29,12 +29,12 @@ export async function getSeriesData( panel: PanelSchema, services: VisTypeTimeseriesRequestServices ) { - const fetchedIndex = await services.cachedIndexPatternFetcher(panel.index_pattern); + const panelIndex = await services.cachedIndexPatternFetcher(panel.index_pattern); const strategy = await services.searchStrategyRegistry.getViableStrategy( requestContext, req, - fetchedIndex + panelIndex ); if (!strategy) { @@ -53,7 +53,7 @@ export async function getSeriesData( try { const bodiesPromises = getActiveSeries(panel).map((series) => - getSeriesRequestParams(req, panel, series, capabilities, services) + getSeriesRequestParams(req, panel, panelIndex, series, capabilities, services) ); const searches = await Promise.all(bodiesPromises); diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/get_table_data.ts b/src/plugins/vis_type_timeseries/server/lib/vis_data/get_table_data.ts index 8f9916bab5e92..0cc1188086b7b 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/get_table_data.ts +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/get_table_data.ts @@ -32,12 +32,12 @@ export async function getTableData( panel: PanelSchema, services: VisTypeTimeseriesRequestServices ) { - const fetchedIndex = await services.cachedIndexPatternFetcher(panel.index_pattern); + const panelIndex = await services.cachedIndexPatternFetcher(panel.index_pattern); const strategy = await services.searchStrategyRegistry.getViableStrategy( requestContext, req, - fetchedIndex + panelIndex ); if (!strategy) { @@ -58,8 +58,8 @@ export async function getTableData( }); const calculatePivotLabel = async () => { - if (panel.pivot_id && fetchedIndex.indexPattern?.title) { - const fields = await extractFields(fetchedIndex.indexPattern.title); + if (panel.pivot_id && panelIndex.indexPattern?.title) { + const fields = await extractFields(panelIndex.indexPattern.title); return extractFieldLabel(fields, panel.pivot_id); } @@ -77,7 +77,7 @@ export async function getTableData( req, panel, services.esQueryConfig, - fetchedIndex.indexPattern, + panelIndex.indexPattern, capabilities, services.uiSettings ); @@ -85,7 +85,7 @@ export async function getTableData( const [resp] = await searchStrategy.search(requestContext, req, [ { body, - index: fetchedIndex.indexPatternString, + index: panelIndex.indexPatternString, }, ]); diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/series/get_request_params.ts b/src/plugins/vis_type_timeseries/server/lib/vis_data/series/get_request_params.ts index f9443324ac054..1f2735da8fb06 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/series/get_request_params.ts +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/series/get_request_params.ts @@ -6,14 +6,19 @@ * Side Public License, v 1. */ -import { PanelSchema, SeriesItemsSchema } from '../../../../common/types'; import { buildRequestBody } from './build_request_body'; -import { VisTypeTimeseriesRequestServices, VisTypeTimeseriesVisDataRequest } from '../../../types'; -import { DefaultSearchCapabilities } from '../../search_strategies'; + +import type { FetchedIndexPattern, PanelSchema, SeriesItemsSchema } from '../../../../common/types'; +import type { + VisTypeTimeseriesRequestServices, + VisTypeTimeseriesVisDataRequest, +} from '../../../types'; +import type { DefaultSearchCapabilities } from '../../search_strategies'; export async function getSeriesRequestParams( req: VisTypeTimeseriesVisDataRequest, panel: PanelSchema, + panelIndex: FetchedIndexPattern, series: SeriesItemsSchema, capabilities: DefaultSearchCapabilities, { @@ -23,22 +28,24 @@ export async function getSeriesRequestParams( cachedIndexPatternFetcher, }: VisTypeTimeseriesRequestServices ) { - const { indexPattern, indexPatternString } = await cachedIndexPatternFetcher( - (series.override_index_pattern && series.series_index_pattern) || panel.index_pattern - ); + let seriesIndex = panelIndex; + + if (series.override_index_pattern) { + seriesIndex = await cachedIndexPatternFetcher(series.series_index_pattern ?? ''); + } const request = await buildRequestBody( req, panel, series, esQueryConfig, - indexPattern, + seriesIndex.indexPattern, capabilities, uiSettings ); return { - index: indexPatternString, + index: seriesIndex.indexPatternString, body: { ...request, timeout: esShardTimeout > 0 ? `${esShardTimeout}ms` : undefined, From 61392d2b975b6d8ecde15df3f47428e86ed81573 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Sat, 20 Mar 2021 17:44:15 +0300 Subject: [PATCH 30/39] indexPatternObject -> indexPatternValue --- .../common/index_patterns_utils.test.ts | 4 +-- .../common/index_patterns_utils.ts | 32 +++++++++---------- .../vis_type_timeseries/common/types.ts | 2 +- .../components/aggs/field_select.tsx | 8 ++--- .../index_pattern_select/combo_box_select.tsx | 4 +-- .../index_pattern_select.tsx | 6 ++-- .../lib/index_pattern_select/types.ts | 4 +-- .../components/panel_config/table.js | 4 +-- .../components/query_bar_wrapper.tsx | 4 +-- .../application/components/vis_editor.tsx | 17 ++++------ .../public/application/lib/fetch_fields.ts | 8 ++--- .../lib/cached_index_pattern_fetcher.ts | 15 ++++----- 12 files changed, 51 insertions(+), 57 deletions(-) diff --git a/src/plugins/vis_type_timeseries/common/index_patterns_utils.test.ts b/src/plugins/vis_type_timeseries/common/index_patterns_utils.test.ts index 929391662468e..515fadffb6b32 100644 --- a/src/plugins/vis_type_timeseries/common/index_patterns_utils.test.ts +++ b/src/plugins/vis_type_timeseries/common/index_patterns_utils.test.ts @@ -7,7 +7,7 @@ */ import { - extractIndexPatternObjects, + extractIndexPatternValues, isStringTypeIndexPattern, fetchIndexPattern, } from './index_patterns_utils'; @@ -44,7 +44,7 @@ describe('extractIndexPatterns', () => { }); test('should return index patterns', () => { - expect(extractIndexPatternObjects(panel, '')).toEqual([ + expect(extractIndexPatternValues(panel, '')).toEqual([ '*', 'example-1-*', 'example-2-*', diff --git a/src/plugins/vis_type_timeseries/common/index_patterns_utils.ts b/src/plugins/vis_type_timeseries/common/index_patterns_utils.ts index d07dc977cac1a..2884440e8f255 100644 --- a/src/plugins/vis_type_timeseries/common/index_patterns_utils.ts +++ b/src/plugins/vis_type_timeseries/common/index_patterns_utils.ts @@ -7,21 +7,21 @@ */ import { uniq } from 'lodash'; -import { PanelSchema, IndexPatternObject, FetchedIndexPattern } from '../common/types'; +import { PanelSchema, IndexPatternValue, FetchedIndexPattern } from '../common/types'; import { IndexPatternsService } from '../../data/common'; export const isStringTypeIndexPattern = ( - indexPatternObject: IndexPatternObject -): indexPatternObject is string => typeof indexPatternObject === 'string'; + indexPatternValue: IndexPatternValue +): indexPatternValue is string => typeof indexPatternValue === 'string'; -export const getIndexPatternObjectKey = (indexPatternObject: IndexPatternObject) => - isStringTypeIndexPattern(indexPatternObject) ? indexPatternObject : indexPatternObject?.id ?? ''; +export const getIndexPatternKey = (indexPatternValue: IndexPatternValue) => + isStringTypeIndexPattern(indexPatternValue) ? indexPatternValue : indexPatternValue?.id ?? ''; -export const extractIndexPatternObjects = ( +export const extractIndexPatternValues = ( panel: PanelSchema, defaultIndex?: PanelSchema['default_index_pattern'] ) => { - const patterns: IndexPatternObject[] = []; + const patterns: IndexPatternValue[] = []; if (panel.index_pattern) { patterns.push(panel.index_pattern); @@ -47,29 +47,29 @@ export const extractIndexPatternObjects = ( patterns.push(defaultIndex); } - return uniq(patterns).sort(); + return uniq(patterns).sort(); }; export const fetchIndexPattern = async ( - indexPatternObject: IndexPatternObject, + indexPatternValue: IndexPatternValue, indexPatternsService: Pick ): Promise => { let indexPattern: FetchedIndexPattern['indexPattern']; let indexPatternString: string = ''; - if (!indexPatternObject) { + if (!indexPatternValue) { indexPattern = await indexPatternsService.getDefault(); } else { - if (isStringTypeIndexPattern(indexPatternObject)) { - indexPattern = (await indexPatternsService.find(indexPatternObject)).find( - (index) => index.title === indexPatternObject + if (isStringTypeIndexPattern(indexPatternValue)) { + indexPattern = (await indexPatternsService.find(indexPatternValue)).find( + (index) => index.title === indexPatternValue ); if (!indexPattern) { - indexPatternString = indexPatternObject; + indexPatternString = indexPatternValue; } - } else if (indexPatternObject.id) { - indexPattern = await indexPatternsService.get(indexPatternObject.id); + } else if (indexPatternValue.id) { + indexPattern = await indexPatternsService.get(indexPatternValue.id); } } diff --git a/src/plugins/vis_type_timeseries/common/types.ts b/src/plugins/vis_type_timeseries/common/types.ts index 0aa1d0e22cdbe..9fe6a162836b4 100644 --- a/src/plugins/vis_type_timeseries/common/types.ts +++ b/src/plugins/vis_type_timeseries/common/types.ts @@ -26,7 +26,7 @@ export type MetricsItemsSchema = TypeOf; export type PanelSchema = TypeOf; export type VisPayload = TypeOf; export type FieldObject = TypeOf; -export type IndexPatternObject = TypeOf; +export type IndexPatternValue = TypeOf; export interface FetchedIndexPattern { indexPattern: IndexPattern | undefined | null; diff --git a/src/plugins/vis_type_timeseries/public/application/components/aggs/field_select.tsx b/src/plugins/vis_type_timeseries/public/application/components/aggs/field_select.tsx index dcdb706f1299b..fb5d420e4ab6e 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/aggs/field_select.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/aggs/field_select.tsx @@ -10,8 +10,8 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import { EuiComboBox, EuiComboBoxProps, EuiComboBoxOptionOption } from '@elastic/eui'; import { METRIC_TYPES } from '../../../../common/metric_types'; -import { getIndexPatternObjectKey } from '../../../../common/index_patterns_utils'; -import type { SanitizedFieldType, IndexPatternObject } from '../../../../common/types'; +import { getIndexPatternKey } from '../../../../common/index_patterns_utils'; +import type { SanitizedFieldType, IndexPatternValue } from '../../../../common/types'; import type { TimeseriesUIRestrictions } from '../../../../common/ui_restrictions'; // @ts-ignore @@ -20,7 +20,7 @@ import { isFieldEnabled } from '../../lib/check_ui_restrictions'; interface FieldSelectProps { type: string; fields: Record; - indexPattern: IndexPatternObject; + indexPattern: IndexPatternValue; value: string; onChange: (options: Array>) => void; disabled?: boolean; @@ -62,7 +62,7 @@ export function FieldSelect({ const selectedOptions: Array> = []; let newPlaceholder = placeholder; - const fieldsSelector = getIndexPatternObjectKey(indexPattern); + const fieldsSelector = getIndexPatternKey(indexPattern); const groupedOptions: EuiComboBoxProps['options'] = Object.values( (fields[fieldsSelector] || []).reduce>>( diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/combo_box_select.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/combo_box_select.tsx index 0e1713d6c05f7..7111a63244c7f 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/combo_box_select.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/combo_box_select.tsx @@ -14,7 +14,7 @@ import { getDataStart } from '../../../../services'; import { SwitchModePopover } from './switch_mode_popover'; import type { SelectIndexComponentProps } from './types'; -import type { IndexPatternObject } from '../../../../../common/types'; +import type { IndexPatternValue } from '../../../../../common/types'; import type { IndexPatternsService } from '../../../../../../data/public'; /** @internal **/ @@ -38,7 +38,7 @@ export const ComboBoxSelect = ({ const [availableIndexes, setAvailableIndexes] = useState([]); const [selectedOptions, setSelectedOptions] = useState([]); - const onComboBoxChange: EuiComboBoxProps['onChange'] = useCallback( + const onComboBoxChange: EuiComboBoxProps['onChange'] = useCallback( ([selected]) => { onIndexChange(selected ? { id: selected.id } : ''); }, diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/index_pattern_select.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/index_pattern_select.tsx index 361bd3e3efcb1..a3854bdc41e76 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/index_pattern_select.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/index_pattern_select.tsx @@ -22,12 +22,12 @@ import { FieldTextSelect } from './field_text_select'; import { ComboBoxSelect } from './combo_box_select'; import { MigrationPopover } from './migrate_popover'; -import type { IndexPatternObject, FetchedIndexPattern } from '../../../../../common/types'; +import type { IndexPatternValue, FetchedIndexPattern } from '../../../../../common/types'; const USE_KIBANA_INDEXES_KEY = 'use_kibana_indexes'; interface IndexPatternSelectProps { - value: IndexPatternObject; + value: IndexPatternValue; indexPatternName: string; onChange: Function; disabled?: boolean; @@ -66,7 +66,7 @@ export const IndexPatternSelect = ({ const Component = useKibanaIndices ? ComboBoxSelect : FieldTextSelect; const onIndexChange = useCallback( - (index: IndexPatternObject) => { + (index: IndexPatternValue) => { onChange({ [indexPatternName]: index, }); diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/types.ts b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/types.ts index 0e7eed0d16654..93b15402e3c24 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/types.ts +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/types.ts @@ -6,12 +6,12 @@ * Side Public License, v 1. */ import type { Assign } from '@kbn/utility-types'; -import type { FetchedIndexPattern, IndexPatternObject } from '../../../../../common/types'; +import type { FetchedIndexPattern, IndexPatternValue } from '../../../../../common/types'; /** @internal **/ export interface SelectIndexComponentProps { fetchedIndex: FetchedIndexPattern; - onIndexChange: (value: IndexPatternObject) => void; + onIndexChange: (value: IndexPatternValue) => void; onModeChange: (useKibanaIndexes: boolean, index?: FetchedIndexPattern) => void; 'data-test-subj': string; placeholder?: string; diff --git a/src/plugins/vis_type_timeseries/public/application/components/panel_config/table.js b/src/plugins/vis_type_timeseries/public/application/components/panel_config/table.js index 35830e637b9ee..93971d5a67a6a 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/panel_config/table.js +++ b/src/plugins/vis_type_timeseries/public/application/components/panel_config/table.js @@ -36,7 +36,7 @@ import { QueryBarWrapper } from '../query_bar_wrapper'; import { getDefaultQueryLanguage } from '../lib/get_default_query_language'; import { VisDataContext } from '../../contexts/vis_data_context'; import { BUCKET_TYPES } from '../../../../common/metric_types'; -import { getIndexPatternObjectKey } from '../../../../common/index_patterns_utils'; +import { getIndexPatternKey } from '../../../../common/index_patterns_utils'; export class TablePanelConfig extends Component { static contextType = VisDataContext; constructor(props) { @@ -60,7 +60,7 @@ export class TablePanelConfig extends Component { handlePivotChange = (selectedOption) => { const { fields, model } = this.props; const pivotId = get(selectedOption, '[0].value', null); - const field = fields[getIndexPatternObjectKey(model.index_pattern)].find( + const field = fields[getIndexPatternKey(model.index_pattern)].find( (field) => field.name === pivotId ); const pivotType = get(field, 'type', model.pivot_type); diff --git a/src/plugins/vis_type_timeseries/public/application/components/query_bar_wrapper.tsx b/src/plugins/vis_type_timeseries/public/application/components/query_bar_wrapper.tsx index ddee08b6a12b7..896caa64820a2 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/query_bar_wrapper.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/query_bar_wrapper.tsx @@ -9,14 +9,14 @@ import React, { useContext, useEffect, useState } from 'react'; import { CoreStartContext } from '../contexts/query_input_bar_context'; -import { IndexPatternObject } from '../../../common/types'; +import { IndexPatternValue } from '../../../common/types'; import { QueryStringInput, QueryStringInputProps } from '../../../../../plugins/data/public'; import { getDataStart } from '../../services'; import { fetchIndexPattern, isStringTypeIndexPattern } from '../../../common/index_patterns_utils'; type QueryBarWrapperProps = Pick & { - indexPatterns: IndexPatternObject[]; + indexPatterns: IndexPatternValue[]; }; export function QueryBarWrapper({ query, onChange, indexPatterns }: QueryBarWrapperProps) { diff --git a/src/plugins/vis_type_timeseries/public/application/components/vis_editor.tsx b/src/plugins/vis_type_timeseries/public/application/components/vis_editor.tsx index 83e0269843c76..aca91f8c830a8 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/vis_editor.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/vis_editor.tsx @@ -15,21 +15,18 @@ import { EventEmitter } from 'events'; import { IUiSettingsClient } from 'kibana/public'; import { TimeRange } from 'src/plugins/data/public'; import { - PersistedState, Vis, + PersistedState, VisualizeEmbeddableContract, } from 'src/plugins/visualizations/public'; -import { - IndexPatternObject, - TimeseriesVisData, -} from 'src/plugins/vis_type_timeseries/common/types'; +import { IndexPatternValue, TimeseriesVisData } from 'src/plugins/vis_type_timeseries/common/types'; import { KibanaContextProvider } from '../../../../../plugins/kibana_react/public'; import { Storage } from '../../../../../plugins/kibana_utils/public'; // @ts-expect-error import { VisEditorVisualization } from './vis_editor_visualization'; import { PanelConfig } from './panel_config'; -import { extractIndexPatternObjects } from '../../../common/index_patterns_utils'; +import { extractIndexPatternValues } from '../../../common/index_patterns_utils'; import { VisPicker } from './vis_picker'; import { fetchFields, VisFields } from '../lib/fetch_fields'; import { getDataStart, getCoreStart } from '../../services'; @@ -50,7 +47,7 @@ export interface TimeseriesEditorProps { interface TimeseriesEditorState { autoApply: boolean; dirty: boolean; - extractedIndexPatterns: IndexPatternObject[]; + extractedIndexPatterns: IndexPatternValue[]; model: TimeseriesVisParams; visFields?: VisFields; } @@ -86,7 +83,7 @@ export class VisEditor extends Component { + abortableFetchFields = (extractedIndexPatterns: IndexPatternValue[]) => { this.abortControllerFetchFields?.abort(); this.abortControllerFetchFields = new AbortController(); @@ -205,7 +202,7 @@ export class VisEditor extends Component { const defaultIndexTitle = index?.title ?? ''; - const indexPatterns = extractIndexPatternObjects(this.props.vis.params, defaultIndexTitle); + const indexPatterns = extractIndexPatternValues(this.props.vis.params, defaultIndexTitle); const visFields = await fetchFields(indexPatterns); this.setState((state) => ({ diff --git a/src/plugins/vis_type_timeseries/public/application/lib/fetch_fields.ts b/src/plugins/vis_type_timeseries/public/application/lib/fetch_fields.ts index 1633b846580e7..df6c7401f0881 100644 --- a/src/plugins/vis_type_timeseries/public/application/lib/fetch_fields.ts +++ b/src/plugins/vis_type_timeseries/public/application/lib/fetch_fields.ts @@ -9,13 +9,13 @@ import { i18n } from '@kbn/i18n'; import { getCoreStart, getDataStart } from '../../services'; import { ROUTES } from '../../../common/constants'; -import { SanitizedFieldType, IndexPatternObject } from '../../../common/types'; -import { getIndexPatternObjectKey } from '../../../common/index_patterns_utils'; +import { SanitizedFieldType, IndexPatternValue } from '../../../common/types'; +import { getIndexPatternKey } from '../../../common/index_patterns_utils'; export type VisFields = Record; export async function fetchFields( - indexes: IndexPatternObject[] = [], + indexes: IndexPatternValue[] = [], signal?: AbortSignal ): Promise { const patterns = Array.isArray(indexes) ? indexes : [indexes]; @@ -42,7 +42,7 @@ export async function fetchFields( const fields: VisFields = patterns.reduce( (cumulatedFields, currentPattern, index) => ({ ...cumulatedFields, - [getIndexPatternObjectKey(currentPattern)]: indexFields[index], + [getIndexPatternKey(currentPattern)]: indexFields[index], }), {} ); diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/cached_index_pattern_fetcher.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/cached_index_pattern_fetcher.ts index 78b859e1049bb..68cbd93cdc614 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/cached_index_pattern_fetcher.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/lib/cached_index_pattern_fetcher.ts @@ -6,27 +6,24 @@ * Side Public License, v 1. */ -import { - getIndexPatternObjectKey, - fetchIndexPattern, -} from '../../../../common/index_patterns_utils'; +import { getIndexPatternKey, fetchIndexPattern } from '../../../../common/index_patterns_utils'; import type { IndexPatternsService } from '../../../../../data/server'; -import type { IndexPatternObject, FetchedIndexPattern } from '../../../../common/types'; +import type { IndexPatternValue, FetchedIndexPattern } from '../../../../common/types'; export const getCachedIndexPatternFetcher = (indexPatternsService: IndexPatternsService) => { const cache = new Map(); - return async (indexPatternObject: IndexPatternObject): Promise => { - const key = getIndexPatternObjectKey(indexPatternObject); + return async (indexPatternValue: IndexPatternValue): Promise => { + const key = getIndexPatternKey(indexPatternValue); if (cache.has(key)) { return cache.get(key); } - const fetchedIndex = fetchIndexPattern(indexPatternObject, indexPatternsService); + const fetchedIndex = fetchIndexPattern(indexPatternValue, indexPatternsService); - cache.set(indexPatternObject, fetchedIndex); + cache.set(indexPatternValue, fetchedIndex); return fetchedIndex; }; From 865477aadf5ec7d1cf9da98930f36ae13e06453d Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Tue, 23 Mar 2021 15:54:40 +0300 Subject: [PATCH 31/39] fix comments --- .../index_pattern_select/migrate_popover.tsx | 32 ++++++++----------- test/functional/apps/visualize/_tsvb_chart.ts | 4 +-- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/migrate_popover.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/migrate_popover.tsx index 8dac89a113a7b..eb7468154883e 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/migrate_popover.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/migrate_popover.tsx @@ -33,15 +33,13 @@ const switchModeLabel = i18n.translate( const getReadyToSwitchCallOut = (value: string, onModeChange: () => void) => ( <> -

- {value}, - }} - /> -

+ {value}, + }} + /> @@ -56,15 +54,13 @@ const getReadyToSwitchCallOut = (value: string, onModeChange: () => void) => ( const getNoMatchedIndicesCallOut = (value: string, onCreateIndexClick: () => void) => ( <> -

- {value}, - }} - /> -

+ {value}, + }} + />
diff --git a/test/functional/apps/visualize/_tsvb_chart.ts b/test/functional/apps/visualize/_tsvb_chart.ts index 0908b7b8ff6bb..80ab33170c396 100644 --- a/test/functional/apps/visualize/_tsvb_chart.ts +++ b/test/functional/apps/visualize/_tsvb_chart.ts @@ -126,7 +126,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await esArchiver.unload('index_pattern_without_timefield'); }); - const switchIndexTest = async (useKibanaIndicies: boolean) => { + const switchIndexTest = async (useKibanaIndexes: boolean) => { await PageObjects.visualBuilder.clickPanelOptions('metric'); await PageObjects.visualBuilder.setIndexPatternValue('', false); @@ -135,7 +135,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // Sometimes popovers take some time to appear in Firefox (#71979) await retry.tryForTime(20000, async () => { - await PageObjects.visualBuilder.setIndexPatternValue('with-timefield', useKibanaIndicies); + await PageObjects.visualBuilder.setIndexPatternValue('with-timefield', useKibanaIndexes); await PageObjects.visualBuilder.waitForIndexPatternTimeFieldOptionsLoaded(); await PageObjects.visualBuilder.selectIndexPatternTimeField('timestamp'); }); From 7f93d810724040e02b406c88fd59f88321be0032 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Tue, 23 Mar 2021 16:06:59 +0300 Subject: [PATCH 32/39] I have a dashboard with two TSVB viz. One with the default (haven't applied it to the combobox) and one with the logs. The filter contains fields only from the logs index pattern --- .../vis_type_timeseries/common/index_patterns_utils.ts | 2 +- src/plugins/vis_type_timeseries/public/metrics_type.ts | 9 ++------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/plugins/vis_type_timeseries/common/index_patterns_utils.ts b/src/plugins/vis_type_timeseries/common/index_patterns_utils.ts index 2884440e8f255..398d1c30ed5a7 100644 --- a/src/plugins/vis_type_timeseries/common/index_patterns_utils.ts +++ b/src/plugins/vis_type_timeseries/common/index_patterns_utils.ts @@ -51,7 +51,7 @@ export const extractIndexPatternValues = ( }; export const fetchIndexPattern = async ( - indexPatternValue: IndexPatternValue, + indexPatternValue: IndexPatternValue | undefined, indexPatternsService: Pick ): Promise => { let indexPattern: FetchedIndexPattern['indexPattern']; diff --git a/src/plugins/vis_type_timeseries/public/metrics_type.ts b/src/plugins/vis_type_timeseries/public/metrics_type.ts index 3c971dc2a5b1e..a89217409c1ff 100644 --- a/src/plugins/vis_type_timeseries/public/metrics_type.ts +++ b/src/plugins/vis_type_timeseries/public/metrics_type.ts @@ -79,13 +79,8 @@ export const metricsVisDefinition = { inspectorAdapters: {}, getUsedIndexPattern: async (params: VisParams) => { const { indexPatterns } = getDataStart(); + const { indexPattern } = await fetchIndexPattern(params.index_pattern, indexPatterns); - if (params.index_pattern) { - const { indexPattern } = await fetchIndexPattern(params.index_pattern, indexPatterns); - if (indexPattern) { - return [indexPattern]; - } - } - return []; + return indexPattern ? [indexPattern] : []; }, }; From 800c0e922f895fe6ff1f331cde890bec895c37f2 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Tue, 23 Mar 2021 16:31:18 +0300 Subject: [PATCH 33/39] When I am on the string mode and try to write my index, sometimes some of the chars are not added or they are deleted while typing, something with the denounce maybe? --- .../lib/index_pattern_select/field_text_select.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/field_text_select.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/field_text_select.tsx index fff5e86395273..86d1758932301 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/field_text_select.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/field_text_select.tsx @@ -30,8 +30,10 @@ export const FieldTextSelect = ({ }, []); useEffect(() => { - setInputValue(indexPatternString ?? ''); - }, [indexPatternString]); + if (inputValue === undefined) { + setInputValue(indexPatternString ?? ''); + } + }, [indexPatternString, inputValue]); useDebounce( () => { From df49b430044c9dacf7aeb55471e17bc640824dec Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Tue, 23 Mar 2021 17:31:02 +0300 Subject: [PATCH 34/39] fix merge conflicts --- .../vis_type_timeseries/common/vis_schema.ts | 2 +- .../components/panel_config/gauge.tsx | 11 ++--- .../components/panel_config/markdown.tsx | 15 +++--- .../components/panel_config/metric.tsx | 16 +++---- .../components/panel_config/table.tsx | 18 ++++--- .../components/panel_config/timeseries.tsx | 17 ++++--- .../components/panel_config/top_n.tsx | 13 +++-- .../components/query_bar_wrapper.tsx | 2 +- .../components/vis_types/table/config.js | 47 +++++++------------ 9 files changed, 60 insertions(+), 81 deletions(-) diff --git a/src/plugins/vis_type_timeseries/common/vis_schema.ts b/src/plugins/vis_type_timeseries/common/vis_schema.ts index 94ca9ef9b1a3e..297b021fa9e77 100644 --- a/src/plugins/vis_type_timeseries/common/vis_schema.ts +++ b/src/plugins/vis_type_timeseries/common/vis_schema.ts @@ -28,7 +28,7 @@ const numberOptional = schema.maybe(schema.number()); const queryObject = schema.object({ language: schema.string(), - query: schema.string(), + query: schema.oneOf([schema.string(), schema.any()]), }); const stringOrNumberOptionalNullable = schema.nullable( schema.oneOf([stringOptionalNullable, numberOptional]) diff --git a/src/plugins/vis_type_timeseries/public/application/components/panel_config/gauge.tsx b/src/plugins/vis_type_timeseries/public/application/components/panel_config/gauge.tsx index 2038905a9ff4a..8a5077fca664c 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/panel_config/gauge.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/panel_config/gauge.tsx @@ -29,12 +29,11 @@ import type { Writable } from '@kbn/utility-types'; // @ts-ignore import { SeriesEditor } from '../series_editor'; -// @ts-ignore should be typed after https://github.com/elastic/kibana/pull/92812 to reduce conflicts +// @ts-expect-error not typed yet import { IndexPattern } from '../index_pattern'; import { createSelectHandler } from '../lib/create_select_handler'; import { ColorRules } from '../color_rules'; import { ColorPicker } from '../color_picker'; -// @ts-ignore this is typed in https://github.com/elastic/kibana/pull/92812, remove ignore after merging import { QueryBarWrapper } from '../query_bar_wrapper'; import { getDefaultQueryLanguage } from '../lib/get_default_query_language'; import { YesNo } from '../yes_no'; @@ -150,10 +149,10 @@ export class GaugePanelConfig extends Component< language: model.filter?.language || getDefaultQueryLanguage(), query: model.filter?.query || '', }} - onChange={(filter: PanelConfigProps['model']['filter']) => - this.props.onChange({ filter }) - } - indexPatterns={[model.index_pattern || model.default_index_pattern]} + onChange={(filter) => { + this.props.onChange({ filter }); + }} + indexPatterns={[model.index_pattern || model.default_index_pattern || '']} />
diff --git a/src/plugins/vis_type_timeseries/public/application/components/panel_config/markdown.tsx b/src/plugins/vis_type_timeseries/public/application/components/panel_config/markdown.tsx index ff30310c84586..a9d9d01376608 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/panel_config/markdown.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/panel_config/markdown.tsx @@ -31,14 +31,13 @@ import type { Writable } from '@kbn/utility-types'; // @ts-expect-error not typed yet import { SeriesEditor } from '../series_editor'; -// @ts-ignore should be typed after https://github.com/elastic/kibana/pull/92812 to reduce conflicts +// @ts-expect-error not typed yet import { IndexPattern } from '../index_pattern'; import { createSelectHandler } from '../lib/create_select_handler'; import { ColorPicker } from '../color_picker'; import { YesNo } from '../yes_no'; // @ts-expect-error not typed yet import { MarkdownEditor } from '../markdown_editor'; -// @ts-ignore this is typed in https://github.com/elastic/kibana/pull/92812, remove ignore after merging import { QueryBarWrapper } from '../query_bar_wrapper'; import { getDefaultQueryLanguage } from '../lib/get_default_query_language'; import { VisDataContext } from '../../contexts/vis_data_context'; @@ -162,13 +161,13 @@ export class MarkdownPanelConfig extends Component< > { + this.props.onChange({ filter }); }} - onChange={(filter: PanelConfigProps['model']['filter']) => - this.props.onChange({ filter }) - } - indexPatterns={[model.index_pattern || model.default_index_pattern]} + indexPatterns={[model.index_pattern || model.default_index_pattern || '']} />
diff --git a/src/plugins/vis_type_timeseries/public/application/components/panel_config/metric.tsx b/src/plugins/vis_type_timeseries/public/application/components/panel_config/metric.tsx index a77a5119472d1..1cc0e48f135c8 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/panel_config/metric.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/panel_config/metric.tsx @@ -25,12 +25,10 @@ import { FormattedMessage } from '@kbn/i18n/react'; // @ts-expect-error import { SeriesEditor } from '../series_editor'; -// @ts-ignore should be typed after https://github.com/elastic/kibana/pull/92812 to reduce conflicts +// @ts-expect-error not typed yet import { IndexPattern } from '../index_pattern'; import { ColorRules } from '../color_rules'; import { YesNo } from '../yes_no'; - -// @ts-ignore this is typed in https://github.com/elastic/kibana/pull/92812, remove ignore after merging import { QueryBarWrapper } from '../query_bar_wrapper'; import { getDefaultQueryLanguage } from '../lib/get_default_query_language'; import { limitOfSeries } from '../../../../common/ui_restrictions'; @@ -112,13 +110,13 @@ export class MetricPanelConfig extends Component< > { + this.props.onChange({ filter }); }} - onChange={(filter: PanelConfigProps['model']['filter']) => - this.props.onChange({ filter }) - } - indexPatterns={[model.index_pattern || model.default_index_pattern]} + indexPatterns={[model.index_pattern || model.default_index_pattern || '']} />
diff --git a/src/plugins/vis_type_timeseries/public/application/components/panel_config/table.tsx b/src/plugins/vis_type_timeseries/public/application/components/panel_config/table.tsx index 0dd2de1c936e7..01828eac74a0f 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/panel_config/table.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/panel_config/table.tsx @@ -31,10 +31,10 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { FieldSelect } from '../aggs/field_select'; // @ts-expect-error not typed yet import { SeriesEditor } from '../series_editor'; -// @ts-ignore should be typed after https://github.com/elastic/kibana/pull/92812 to reduce conflicts +// @ts-expect-error not typed yet import { IndexPattern } from '../index_pattern'; import { YesNo } from '../yes_no'; -// @ts-ignore this is typed in https://github.com/elastic/kibana/pull/92812, remove ignore after merging + import { QueryBarWrapper } from '../query_bar_wrapper'; import { getDefaultQueryLanguage } from '../lib/get_default_query_language'; import { VisDataContext } from '../../contexts/vis_data_context'; @@ -238,15 +238,13 @@ export class TablePanelConfig extends Component< > - this.props.onChange({ filter }) - } - indexPatterns={[model.index_pattern || model.default_index_pattern]} + onChange={(filter) => { + this.props.onChange({ filter }); + }} + indexPatterns={[model.index_pattern || model.default_index_pattern || '']} /> diff --git a/src/plugins/vis_type_timeseries/public/application/components/panel_config/timeseries.tsx b/src/plugins/vis_type_timeseries/public/application/components/panel_config/timeseries.tsx index e972abf24ca6d..2e714b8db480b 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/panel_config/timeseries.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/panel_config/timeseries.tsx @@ -27,15 +27,14 @@ import { i18n } from '@kbn/i18n'; // @ts-expect-error not typed yet import { SeriesEditor } from '../series_editor'; -// @ts-ignore should be typed after https://github.com/elastic/kibana/pull/92812 to reduce conflicts +// @ts-expect-error not typed yet import { AnnotationsEditor } from '../annotations_editor'; -// @ts-ignore should be typed after https://github.com/elastic/kibana/pull/92812 to reduce conflicts +// @ts-expect-error not typed yet import { IndexPattern } from '../index_pattern'; import { createSelectHandler } from '../lib/create_select_handler'; import { ColorPicker } from '../color_picker'; import { YesNo } from '../yes_no'; import { getDefaultQueryLanguage } from '../lib/get_default_query_language'; -// @ts-ignore this is typed in https://github.com/elastic/kibana/pull/92812, remove ignore after merging import { QueryBarWrapper } from '../query_bar_wrapper'; import { PanelConfigProps, PANEL_CONFIG_TABS } from './types'; import { TimeseriesVisParams } from '../../../types'; @@ -202,13 +201,13 @@ export class TimeseriesPanelConfig extends Component< > { + this.props.onChange({ filter }); }} - onChange={(filter: PanelConfigProps['model']['filter']) => - this.props.onChange({ filter }) - } - indexPatterns={[model.index_pattern || model.default_index_pattern]} + indexPatterns={[model.index_pattern || model.default_index_pattern || '']} /> diff --git a/src/plugins/vis_type_timeseries/public/application/components/panel_config/top_n.tsx b/src/plugins/vis_type_timeseries/public/application/components/panel_config/top_n.tsx index f7b9f391b3c03..6252c8f1c31bb 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/panel_config/top_n.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/panel_config/top_n.tsx @@ -33,7 +33,6 @@ import { ColorRules } from '../color_rules'; import { ColorPicker } from '../color_picker'; import { YesNo } from '../yes_no'; import { getDefaultQueryLanguage } from '../lib/get_default_query_language'; -// @ts-ignore this is typed in https://github.com/elastic/kibana/pull/92812, remove ignore after merging import { QueryBarWrapper } from '../query_bar_wrapper'; import { PanelConfigProps, PANEL_CONFIG_TABS } from './types'; import { TimeseriesVisParams } from '../../../types'; @@ -139,13 +138,13 @@ export class TopNPanelConfig extends Component< > - this.props.onChange({ filter }) - } - indexPatterns={[model.index_pattern || model.default_index_pattern]} + onChange={(filter: PanelConfigProps['model']['filter']) => { + this.props.onChange({ filter }); + }} + indexPatterns={[model.index_pattern || model.default_index_pattern || '']} /> diff --git a/src/plugins/vis_type_timeseries/public/application/components/query_bar_wrapper.tsx b/src/plugins/vis_type_timeseries/public/application/components/query_bar_wrapper.tsx index 896caa64820a2..f9a5de313521a 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/query_bar_wrapper.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/query_bar_wrapper.tsx @@ -29,7 +29,7 @@ export function QueryBarWrapper({ query, onChange, indexPatterns }: QueryBarWrap async function fetchIndexes() { const i: QueryStringInputProps['indexPatterns'] = []; - for (const index of indexPatterns) { + for (const index of indexPatterns ?? []) { if (isStringTypeIndexPattern(index)) { i.push(index); } else if (index?.id) { diff --git a/src/plugins/vis_type_timeseries/public/application/components/vis_types/table/config.js b/src/plugins/vis_type_timeseries/public/application/components/vis_types/table/config.js index 8855522e1938a..0ba8d3e855365 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/vis_types/table/config.js +++ b/src/plugins/vis_type_timeseries/public/application/components/vis_types/table/config.js @@ -9,6 +9,8 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import uuid from 'uuid'; +import { i18n } from '@kbn/i18n'; + import { DataFormatPicker } from '../../data_format_picker'; import { createSelectHandler } from '../../lib/create_select_handler'; import { createTextHandler } from '../../lib/create_text_handler'; @@ -28,11 +30,11 @@ import { EuiSpacer, EuiTitle, } from '@elastic/eui'; -import { FormattedMessage, injectI18n } from '@kbn/i18n/react'; +import { FormattedMessage } from '@kbn/i18n/react'; import { getDefaultQueryLanguage } from '../../lib/get_default_query_language'; - import { QueryBarWrapper } from '../../query_bar_wrapper'; -class TableSeriesConfigUI extends Component { + +export class TableSeriesConfig extends Component { UNSAFE_componentWillMount() { const { model } = this.props; if (!model.color_rules || (model.color_rules && model.color_rules.length === 0)) { @@ -48,68 +50,58 @@ class TableSeriesConfigUI extends Component { const handleSelectChange = createSelectHandler(this.props.onChange); const handleTextChange = createTextHandler(this.props.onChange); const htmlId = htmlIdGenerator(); - const { intl } = this.props; const functionOptions = [ { - label: intl.formatMessage({ - id: 'visTypeTimeseries.table.sumLabel', + label: i18n.translate('visTypeTimeseries.table.sumLabel', { defaultMessage: 'Sum', }), value: 'sum', }, { - label: intl.formatMessage({ - id: 'visTypeTimeseries.table.maxLabel', + label: i18n.translate('visTypeTimeseries.table.maxLabel', { defaultMessage: 'Max', }), value: 'max', }, { - label: intl.formatMessage({ - id: 'visTypeTimeseries.table.minLabel', + label: i18n.translate('visTypeTimeseries.table.minLabel', { defaultMessage: 'Min', }), value: 'min', }, { - label: intl.formatMessage({ - id: 'visTypeTimeseries.table.avgLabel', + label: i18n.translate('visTypeTimeseries.table.avgLabel', { defaultMessage: 'Avg', }), value: 'mean', }, { - label: intl.formatMessage({ - id: 'visTypeTimeseries.table.overallSumLabel', + label: i18n.translate('visTypeTimeseries.table.overallSumLabel', { defaultMessage: 'Overall Sum', }), value: 'overall_sum', }, { - label: intl.formatMessage({ - id: 'visTypeTimeseries.table.overallMaxLabel', + label: i18n.translate('visTypeTimeseries.table.overallMaxLabel', { defaultMessage: 'Overall Max', }), value: 'overall_max', }, { - label: intl.formatMessage({ - id: 'visTypeTimeseries.table.overallMinLabel', + label: i18n.translate('visTypeTimeseries.table.overallMinLabel', { defaultMessage: 'Overall Min', }), value: 'overall_min', }, { - label: intl.formatMessage({ - id: 'visTypeTimeseries.table.overallAvgLabel', + label: i18n.translate('visTypeTimeseries.table.overallAvgLabel', { defaultMessage: 'Overall Avg', }), value: 'overall_avg', }, { - label: intl.formatMessage({ - id: 'visTypeTimeseries.table.cumulativeSumLabel', + label: i18n.translate('visTypeTimeseries.table.cumulativeSumLabel', { defaultMessage: 'Cumulative Sum', }), value: 'cumulative_sum', @@ -170,11 +162,8 @@ class TableSeriesConfigUI extends Component { > this.props.onChange({ filter })} indexPatterns={[this.props.indexPatternForQuery]} @@ -259,11 +248,9 @@ class TableSeriesConfigUI extends Component { } } -TableSeriesConfigUI.propTypes = { +TableSeriesConfig.propTypes = { fields: PropTypes.object, model: PropTypes.object, onChange: PropTypes.func, indexPatternForQuery: PropTypes.oneOfType([PropTypes.object, PropTypes.string]), }; - -export const TableSeriesConfig = injectI18n(TableSeriesConfigUI); From 47115a0b1696cac53883a20be7ff7da28eb23f72 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Tue, 23 Mar 2021 18:06:41 +0300 Subject: [PATCH 35/39] Does this PR also supports runtime fields? I created one from the editor and I see that I can select it --- .../vis_type_timeseries/common/field_types.ts | 15 ---- .../common/fields_utils.test.ts | 73 +++++++++++++++++++ .../common/fields_utils.ts | 28 +++++++ .../application/components/splits/terms.js | 4 +- .../public/application/lib/fetch_fields.ts | 5 +- .../abstract_search_strategy.test.ts | 68 +---------------- .../strategies/abstract_search_strategy.ts | 23 +----- 7 files changed, 113 insertions(+), 103 deletions(-) delete mode 100644 src/plugins/vis_type_timeseries/common/field_types.ts create mode 100644 src/plugins/vis_type_timeseries/common/fields_utils.test.ts create mode 100644 src/plugins/vis_type_timeseries/common/fields_utils.ts diff --git a/src/plugins/vis_type_timeseries/common/field_types.ts b/src/plugins/vis_type_timeseries/common/field_types.ts deleted file mode 100644 index f9ebc83b4a5db..0000000000000 --- a/src/plugins/vis_type_timeseries/common/field_types.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -export enum FIELD_TYPES { - BOOLEAN = 'boolean', - DATE = 'date', - GEO = 'geo_point', - NUMBER = 'number', - STRING = 'string', -} diff --git a/src/plugins/vis_type_timeseries/common/fields_utils.test.ts b/src/plugins/vis_type_timeseries/common/fields_utils.test.ts new file mode 100644 index 0000000000000..d1036aab2dc3e --- /dev/null +++ b/src/plugins/vis_type_timeseries/common/fields_utils.test.ts @@ -0,0 +1,73 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { toSanitizedFieldType } from './fields_utils'; +import type { FieldSpec, RuntimeField } from '../../data/common'; + +describe('fields_utils', () => { + describe('toSanitizedFieldType', () => { + const mockedField = { + lang: 'lang', + conflictDescriptions: {}, + aggregatable: true, + name: 'name', + type: 'type', + esTypes: ['long', 'geo'], + } as FieldSpec; + + test('should sanitize fields ', async () => { + const fields = [mockedField] as FieldSpec[]; + + expect(toSanitizedFieldType(fields)).toMatchInlineSnapshot(` + Array [ + Object { + "label": "name", + "name": "name", + "type": "type", + }, + ] + `); + }); + + test('should filter runtime fields', async () => { + const fields: FieldSpec[] = [ + { + ...mockedField, + runtimeField: {} as RuntimeField, + }, + ]; + + expect(toSanitizedFieldType(fields)).toMatchInlineSnapshot(`Array []`); + }); + + test('should filter non-aggregatable fields', async () => { + const fields: FieldSpec[] = [ + { + ...mockedField, + aggregatable: false, + }, + ]; + + expect(toSanitizedFieldType(fields)).toMatchInlineSnapshot(`Array []`); + }); + + test('should filter nested fields', async () => { + const fields: FieldSpec[] = [ + { + ...mockedField, + subType: { + nested: { + path: 'path', + }, + }, + }, + ]; + expect(toSanitizedFieldType(fields)).toMatchInlineSnapshot(`Array []`); + }); + }); +}); diff --git a/src/plugins/vis_type_timeseries/common/fields_utils.ts b/src/plugins/vis_type_timeseries/common/fields_utils.ts new file mode 100644 index 0000000000000..04499d5320ab8 --- /dev/null +++ b/src/plugins/vis_type_timeseries/common/fields_utils.ts @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FieldSpec } from '../../data/common'; +import { isNestedField } from '../../data/common'; +import { SanitizedFieldType } from './types'; + +export const toSanitizedFieldType = (fields: FieldSpec[]) => { + return fields + .filter( + (field) => + // Make sure to only include mapped fields, e.g. no index pattern runtime fields + !field.runtimeField && field.aggregatable && !isNestedField(field) + ) + .map( + (field) => + ({ + name: field.name, + label: field.customLabel ?? field.name, + type: field.type, + } as SanitizedFieldType) + ); +}; diff --git a/src/plugins/vis_type_timeseries/public/application/components/splits/terms.js b/src/plugins/vis_type_timeseries/public/application/components/splits/terms.js index 5891320aa684f..b996abd6373ab 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/splits/terms.js +++ b/src/plugins/vis_type_timeseries/public/application/components/splits/terms.js @@ -25,7 +25,7 @@ import { EuiFieldText, } from '@elastic/eui'; import { injectI18n, FormattedMessage } from '@kbn/i18n/react'; -import { FIELD_TYPES } from '../../../../common/field_types'; +import { KBN_FIELD_TYPES } from '../../../../../data/public'; import { STACKED_OPTIONS } from '../../visualizations/constants'; const DEFAULTS = { terms_direction: 'desc', terms_size: 10, terms_order_by: '_count' }; @@ -133,7 +133,7 @@ export const SplitByTermsUI = ({ - {selectedFieldType === FIELD_TYPES.STRING && ( + {selectedFieldType === KBN_FIELD_TYPES.STRING && ( ; @@ -27,7 +28,9 @@ export async function fetchFields( const indexFields = await Promise.all( patterns.map(async (pattern) => { if (typeof pattern !== 'string' && pattern?.id) { - return (await dataStart.indexPatterns.get(pattern.id)).getNonScriptedFields(); + return toSanitizedFieldType( + (await dataStart.indexPatterns.get(pattern.id)).getNonScriptedFields() + ); } else { return coreStart.http.get(ROUTES.FIELDS, { query: { diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.test.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.test.ts index b6d7dc2aff31b..fb66e32447c22 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.test.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.test.ts @@ -9,14 +9,13 @@ import { IndexPatternsService } from '../../../../../data/common'; import { from } from 'rxjs'; -import { AbstractSearchStrategy, toSanitizedFieldType } from './abstract_search_strategy'; +import { AbstractSearchStrategy } from './abstract_search_strategy'; import type { IFieldType } from '../../../../../data/common'; -import type { FieldSpec, RuntimeField } from '../../../../../data/common'; -import { +import type { CachedIndexPatternFetcher } from '../lib/cached_index_pattern_fetcher'; +import type { VisTypeTimeseriesRequestHandlerContext, VisTypeTimeseriesVisDataRequest, } from '../../../types'; -import { CachedIndexPatternFetcher } from '../lib/cached_index_pattern_fetcher'; class FooSearchStrategy extends AbstractSearchStrategy {} @@ -94,65 +93,4 @@ describe('AbstractSearchStrategy', () => { } ); }); - - describe('toSanitizedFieldType', () => { - const mockedField = { - lang: 'lang', - conflictDescriptions: {}, - aggregatable: true, - name: 'name', - type: 'type', - esTypes: ['long', 'geo'], - } as FieldSpec; - - test('should sanitize fields ', async () => { - const fields = [mockedField] as FieldSpec[]; - - expect(toSanitizedFieldType(fields)).toMatchInlineSnapshot(` - Array [ - Object { - "label": "name", - "name": "name", - "type": "type", - }, - ] - `); - }); - - test('should filter runtime fields', async () => { - const fields: FieldSpec[] = [ - { - ...mockedField, - runtimeField: {} as RuntimeField, - }, - ]; - - expect(toSanitizedFieldType(fields)).toMatchInlineSnapshot(`Array []`); - }); - - test('should filter non-aggregatable fields', async () => { - const fields: FieldSpec[] = [ - { - ...mockedField, - aggregatable: false, - }, - ]; - - expect(toSanitizedFieldType(fields)).toMatchInlineSnapshot(`Array []`); - }); - - test('should filter nested fields', async () => { - const fields: FieldSpec[] = [ - { - ...mockedField, - subType: { - nested: { - path: 'path', - }, - }, - }, - ]; - expect(toSanitizedFieldType(fields)).toMatchInlineSnapshot(`Array []`); - }); - }); }); diff --git a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts index a1fe120b75707..26c3a6c7c8bf7 100644 --- a/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts +++ b/src/plugins/vis_type_timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts @@ -6,33 +6,16 @@ * Side Public License, v 1. */ -import { indexPatterns, IndexPatternsService } from '../../../../../data/server'; +import { IndexPatternsService } from '../../../../../data/server'; +import { toSanitizedFieldType } from '../../../../common/fields_utils'; -import type { FieldSpec } from '../../../../../data/common'; -import type { SanitizedFieldType, FetchedIndexPattern } from '../../../../common/types'; +import type { FetchedIndexPattern } from '../../../../common/types'; import type { VisTypeTimeseriesRequest, VisTypeTimeseriesRequestHandlerContext, VisTypeTimeseriesVisDataRequest, } from '../../../types'; -export const toSanitizedFieldType = (fields: FieldSpec[]) => { - return fields - .filter( - (field) => - // Make sure to only include mapped fields, e.g. no index pattern runtime fields - !field.runtimeField && field.aggregatable && !indexPatterns.isNestedField(field) - ) - .map( - (field) => - ({ - name: field.name, - label: field.customLabel ?? field.name, - type: field.type, - } as SanitizedFieldType) - ); -}; - export abstract class AbstractSearchStrategy { async search( requestContext: VisTypeTimeseriesRequestHandlerContext, From 9715acc438add560cf38f81f54ae092ee04de548 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Thu, 25 Mar 2021 14:16:41 +0300 Subject: [PATCH 36/39] fix UI issue --- .../public/application/lib/fetch_fields.ts | 5 ++-- .../controls_references.ts | 9 ++++---- .../saved_visualization_references/index.ts | 3 +++ .../saved_visualization_references.ts | 18 ++++++++++----- .../timeseries_references.ts | 23 ++++++++----------- 5 files changed, 33 insertions(+), 25 deletions(-) diff --git a/src/plugins/vis_type_timeseries/public/application/lib/fetch_fields.ts b/src/plugins/vis_type_timeseries/public/application/lib/fetch_fields.ts index a9a5f8a0b47c1..af3ddd643cac8 100644 --- a/src/plugins/vis_type_timeseries/public/application/lib/fetch_fields.ts +++ b/src/plugins/vis_type_timeseries/public/application/lib/fetch_fields.ts @@ -50,9 +50,10 @@ export async function fetchFields( {} ); - if (defaultIndexPattern?.title && patterns.includes(defaultIndexPattern.title)) { - fields[''] = fields[defaultIndexPattern.title]; + if (defaultIndexPattern) { + fields[''] = toSanitizedFieldType(await defaultIndexPattern.getNonScriptedFields()); } + return fields; } catch (error) { if (error.name !== 'AbortError') { diff --git a/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/controls_references.ts b/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/controls_references.ts index 9419efad41b83..e584270425ebf 100644 --- a/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/controls_references.ts +++ b/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/controls_references.ts @@ -7,12 +7,13 @@ */ import { SavedObjectReference } from '../../../../../core/types'; +import { VisParams } from '../../../common'; export const extractControlsReferences = ( - visState: Record, + visParams: VisParams, references: SavedObjectReference[] = [] ) => { - const controls = visState.params?.controls ?? []; + const controls = visParams?.controls ?? []; controls.forEach((control: Record, i: number) => { if (!control.indexPattern) { @@ -29,10 +30,10 @@ export const extractControlsReferences = ( }; export const injectControlsReferences = ( - visState: Record, + visParams: VisParams, references: SavedObjectReference[] ) => { - const controls = visState.params?.controls ?? []; + const controls = visParams.controls ?? []; controls.forEach((control: Record) => { if (!control.indexPatternRefName) { diff --git a/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/index.ts b/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/index.ts index 727005b7f1836..0acda1c0a0f80 100644 --- a/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/index.ts +++ b/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/index.ts @@ -6,4 +6,7 @@ * Side Public License, v 1. */ +export { extractControlsReferences, injectControlsReferences } from './controls_references'; +export { extractTimeSeriesReferences, injectTimeSeriesReferences } from './timeseries_references'; + export { extractReferences, injectReferences } from './saved_visualization_references'; diff --git a/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/saved_visualization_references.ts b/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/saved_visualization_references.ts index 4afd1bf5980a9..66ef9a1d7d2dd 100644 --- a/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/saved_visualization_references.ts +++ b/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/saved_visualization_references.ts @@ -11,7 +11,7 @@ import { SavedObjectAttributes, SavedObjectReference, } from '../../../../../core/public'; -import { VisSavedObject } from '../../types'; +import { SavedVisState, VisSavedObject } from '../../types'; import { extractSearchSourceReferences, injectSearchSourceReferences, @@ -52,10 +52,13 @@ export function extractReferences({ // Extract index patterns from controls if (updatedAttributes.visState) { - const visState = JSON.parse(String(updatedAttributes.visState)); + const visState = JSON.parse(String(updatedAttributes.visState)) as SavedVisState; - extractControlsReferences(visState, updatedReferences); - extractTimeSeriesReferences(visState, updatedReferences); + extractControlsReferences(visState.params, updatedReferences); + + if (visState.type === 'metrics') { + extractTimeSeriesReferences(visState.params, updatedReferences); + } updatedAttributes.visState = JSON.stringify(visState); } @@ -85,7 +88,10 @@ export function injectReferences(savedObject: VisSavedObject, references: SavedO } if (savedObject.visState?.params) { - injectControlsReferences(savedObject.visState, references); - injectTimeSeriesReferences(savedObject.visState, references); + injectControlsReferences(savedObject.visState.params, references); + + if (savedObject.visState.type === 'metrics') { + injectTimeSeriesReferences(savedObject.visState.params, references); + } } } diff --git a/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/timeseries_references.ts b/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/timeseries_references.ts index 2a3fccb797799..845da0d011ed7 100644 --- a/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/timeseries_references.ts +++ b/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/timeseries_references.ts @@ -7,6 +7,7 @@ */ import { SavedObjectReference } from '../../../../../core/types'; +import { VisParams } from '../../../common'; /** @internal **/ const REF_NAME_POSTFIX = '_ref_name'; @@ -17,28 +18,24 @@ const INDEX_PATTERN_REF_TYPE = 'index_pattern'; /** @internal **/ type Action = (object: Record, key: string) => void; -const doForExtractedIndices = (action: Action, visState: Record) => { - if (visState.type !== 'metrics') { - return; - } - - action(visState.params, 'index_pattern'); +const doForExtractedIndices = (action: Action, visParams: VisParams) => { + action(visParams, 'index_pattern'); - visState.params.series.forEach((series: any) => { + visParams.series.forEach((series: any) => { if (series.override_index_pattern) { action(series, 'series_index_pattern'); } }); - if (visState.params.annotations) { - visState.params.annotations.forEach((annotation: any) => { + if (visParams.annotations) { + visParams.annotations.forEach((annotation: any) => { action(annotation, 'index_pattern'); }); } }; export const extractTimeSeriesReferences = ( - visState: Record, + visParams: VisParams, references: SavedObjectReference[] = [] ) => { let i = 0; @@ -55,11 +52,11 @@ export const extractTimeSeriesReferences = ( }); delete object[key]; } - }, visState); + }, visParams); }; export const injectTimeSeriesReferences = ( - visState: Record, + visParams: VisParams, references: SavedObjectReference[] ) => { doForExtractedIndices((object, key) => { @@ -74,5 +71,5 @@ export const injectTimeSeriesReferences = ( delete object[refKey]; } - }, visState); + }, visParams); }; From 9d7c237aaef74b98d48934d0db318750df704700 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Thu, 25 Mar 2021 15:57:08 +0300 Subject: [PATCH 37/39] If I create a viz with the string mode and a wildcard e.g. kibana_sample*, the index patterns are not communicated correctly to the dashboard. --- .../vis_type_timeseries/public/metrics_type.ts | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/plugins/vis_type_timeseries/public/metrics_type.ts b/src/plugins/vis_type_timeseries/public/metrics_type.ts index a89217409c1ff..5d5e082b2b7bb 100644 --- a/src/plugins/vis_type_timeseries/public/metrics_type.ts +++ b/src/plugins/vis_type_timeseries/public/metrics_type.ts @@ -10,7 +10,7 @@ import { i18n } from '@kbn/i18n'; import { TSVB_EDITOR_NAME } from './application'; import { PANEL_TYPES } from '../common/panel_types'; -import { fetchIndexPattern } from '../common/index_patterns_utils'; +import { isStringTypeIndexPattern } from '../common/index_patterns_utils'; import { toExpressionAst } from './to_ast'; import { VIS_EVENT_TO_TRIGGER, VisGroups, VisParams } from '../../visualizations/public'; import { getDataStart } from './services'; @@ -79,8 +79,20 @@ export const metricsVisDefinition = { inspectorAdapters: {}, getUsedIndexPattern: async (params: VisParams) => { const { indexPatterns } = getDataStart(); - const { indexPattern } = await fetchIndexPattern(params.index_pattern, indexPatterns); + const indexPatternValue = params.index_pattern; - return indexPattern ? [indexPattern] : []; + if (indexPatternValue) { + if (isStringTypeIndexPattern(indexPatternValue)) { + return await indexPatterns.find(indexPatternValue); + } + + if (indexPatternValue.id) { + return [await indexPatterns.get(indexPatternValue.id)]; + } + } + + const defaultIndex = await indexPatterns.getDefault(); + + return defaultIndex ? [defaultIndex] : []; }, }; From 9ddf39e820ced58b9f7278d68e2792fad1355e21 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Fri, 26 Mar 2021 14:29:48 +0300 Subject: [PATCH 38/39] fix import/export refs for dashboard --- .../visualize_embeddable_factory.tsx | 39 ++++-- .../controls_references.ts | 59 +++++---- .../saved_visualization_references.test.ts | 120 +++++++++--------- .../saved_visualization_references.ts | 16 +-- .../timeseries_references.ts | 56 ++++---- 5 files changed, 159 insertions(+), 131 deletions(-) diff --git a/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx b/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx index 349e024f31c31..c2b9fcd77757a 100644 --- a/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx +++ b/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx @@ -12,6 +12,8 @@ import { first } from 'rxjs/operators'; import { EmbeddableStateWithType } from 'src/plugins/embeddable/common'; import { SavedObjectAttributes } from '../../../../core/public'; import { extractSearchSourceReferences } from '../../../data/public'; +import { SavedObjectReference } from '../../../../core/public'; + import { EmbeddableFactoryDefinition, EmbeddableOutput, @@ -38,6 +40,12 @@ import { } from '../services'; import { showNewVisModal } from '../wizard'; import { convertToSerializedVis } from '../saved_visualizations/_saved_vis'; +import { + extractControlsReferences, + extractTimeSeriesReferences, + injectTimeSeriesReferences, + injectControlsReferences, +} from '../saved_visualizations/saved_visualization_references'; import { createVisEmbeddableFromObject } from './create_vis_embeddable_from_object'; import { StartServicesGetter } from '../../../kibana_utils/public'; import { VisualizationsStartDeps } from '../plugin'; @@ -239,6 +247,19 @@ export class VisualizeEmbeddableFactory ); } + public inject(_state: EmbeddableStateWithType, references: SavedObjectReference[]) { + const state = (_state as unknown) as VisualizeInput; + + const { type, params } = state.savedVis ?? {}; + + if (type && params) { + injectControlsReferences(type, params, references); + injectTimeSeriesReferences(type, params, references); + } + + return _state; + } + public extract(_state: EmbeddableStateWithType) { const state = (_state as unknown) as VisualizeInput; const references = []; @@ -259,19 +280,11 @@ export class VisualizeEmbeddableFactory }); } - if (state.savedVis?.params.controls) { - const controls = state.savedVis.params.controls; - controls.forEach((control: Record, i: number) => { - if (!control.indexPattern) { - return; - } - control.indexPatternRefName = `control_${i}_index_pattern`; - references.push({ - name: control.indexPatternRefName, - type: 'index-pattern', - id: control.indexPattern, - }); - }); + const { type, params } = state.savedVis ?? {}; + + if (type && params) { + extractControlsReferences(type, params, references, `control_${state.id}`); + extractTimeSeriesReferences(type, params, references, `metrics_${state.id}`); } return { state: _state, references }; diff --git a/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/controls_references.ts b/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/controls_references.ts index e584270425ebf..d116fd2e2e9a7 100644 --- a/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/controls_references.ts +++ b/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/controls_references.ts @@ -9,41 +9,46 @@ import { SavedObjectReference } from '../../../../../core/types'; import { VisParams } from '../../../common'; +const isControlsVis = (visType: string) => visType === 'input_control_vis'; + export const extractControlsReferences = ( + visType: string, visParams: VisParams, - references: SavedObjectReference[] = [] + references: SavedObjectReference[] = [], + prefix: string = 'control' ) => { - const controls = visParams?.controls ?? []; - - controls.forEach((control: Record, i: number) => { - if (!control.indexPattern) { - return; - } - control.indexPatternRefName = `control_${i}_index_pattern`; - references.push({ - name: control.indexPatternRefName, - type: 'index-pattern', - id: control.indexPattern, + if (isControlsVis(visType)) { + (visParams?.controls ?? []).forEach((control: Record, i: number) => { + if (!control.indexPattern) { + return; + } + control.indexPatternRefName = `${prefix}_${i}_index_pattern`; + references.push({ + name: control.indexPatternRefName, + type: 'index-pattern', + id: control.indexPattern, + }); + delete control.indexPattern; }); - delete control.indexPattern; - }); + } }; export const injectControlsReferences = ( + visType: string, visParams: VisParams, references: SavedObjectReference[] ) => { - const controls = visParams.controls ?? []; - - controls.forEach((control: Record) => { - if (!control.indexPatternRefName) { - return; - } - const reference = references.find((ref) => ref.name === control.indexPatternRefName); - if (!reference) { - throw new Error(`Could not find index pattern reference "${control.indexPatternRefName}"`); - } - control.indexPattern = reference.id; - delete control.indexPatternRefName; - }); + if (isControlsVis(visType)) { + (visParams.controls ?? []).forEach((control: Record) => { + if (!control.indexPatternRefName) { + return; + } + const reference = references.find((ref) => ref.name === control.indexPatternRefName); + if (!reference) { + throw new Error(`Could not find index pattern reference "${control.indexPatternRefName}"`); + } + control.indexPattern = reference.id; + delete control.indexPatternRefName; + }); + } }; diff --git a/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/saved_visualization_references.test.ts b/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/saved_visualization_references.test.ts index 3961d303382f0..867febd2544b0 100644 --- a/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/saved_visualization_references.test.ts +++ b/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/saved_visualization_references.test.ts @@ -21,13 +21,13 @@ describe('extractReferences', () => { }; const updatedDoc = extractReferences(doc); expect(updatedDoc).toMatchInlineSnapshot(` -Object { - "attributes": Object { - "foo": true, - }, - "references": Array [], -} -`); + Object { + "attributes": Object { + "foo": true, + }, + "references": Array [], + } + `); }); test('extracts references from savedSearchId', () => { @@ -41,20 +41,20 @@ Object { }; const updatedDoc = extractReferences(doc); expect(updatedDoc).toMatchInlineSnapshot(` -Object { - "attributes": Object { - "foo": true, - "savedSearchRefName": "search_0", - }, - "references": Array [ - Object { - "id": "123", - "name": "search_0", - "type": "search", - }, - ], -} -`); + Object { + "attributes": Object { + "foo": true, + "savedSearchRefName": "search_0", + }, + "references": Array [ + Object { + "id": "123", + "name": "search_0", + "type": "search", + }, + ], + } + `); }); test('extracts references from controls', () => { @@ -63,6 +63,7 @@ Object { attributes: { foo: true, visState: JSON.stringify({ + type: 'input_control_vis', params: { controls: [ { @@ -81,20 +82,20 @@ Object { const updatedDoc = extractReferences(doc); expect(updatedDoc).toMatchInlineSnapshot(` -Object { - "attributes": Object { - "foo": true, - "visState": "{\\"params\\":{\\"controls\\":[{\\"bar\\":true,\\"indexPatternRefName\\":\\"control_0_index_pattern\\"},{\\"bar\\":false}]}}", - }, - "references": Array [ - Object { - "id": "pattern*", - "name": "control_0_index_pattern", - "type": "index-pattern", - }, - ], -} -`); + Object { + "attributes": Object { + "foo": true, + "visState": "{\\"type\\":\\"input_control_vis\\",\\"params\\":{\\"controls\\":[{\\"bar\\":true,\\"indexPatternRefName\\":\\"control_0_index_pattern\\"},{\\"bar\\":false}]}}", + }, + "references": Array [ + Object { + "id": "pattern*", + "name": "control_0_index_pattern", + "type": "index-pattern", + }, + ], + } + `); }); }); @@ -106,11 +107,11 @@ describe('injectReferences', () => { } as VisSavedObject; injectReferences(context, []); expect(context).toMatchInlineSnapshot(` -Object { - "id": "1", - "title": "test", -} -`); + Object { + "id": "1", + "title": "test", + } + `); }); test('injects references into context', () => { @@ -119,6 +120,7 @@ Object { title: 'test', savedSearchRefName: 'search_0', visState: ({ + type: 'input_control_vis', params: { controls: [ { @@ -146,25 +148,26 @@ Object { ]; injectReferences(context, references); expect(context).toMatchInlineSnapshot(` -Object { - "id": "1", - "savedSearchId": "123", - "title": "test", - "visState": Object { - "params": Object { - "controls": Array [ - Object { - "foo": true, - "indexPattern": "pattern*", - }, - Object { - "foo": false, + Object { + "id": "1", + "savedSearchId": "123", + "title": "test", + "visState": Object { + "params": Object { + "controls": Array [ + Object { + "foo": true, + "indexPattern": "pattern*", + }, + Object { + "foo": false, + }, + ], + }, + "type": "input_control_vis", }, - ], - }, - }, -} -`); + } + `); }); test(`fails when it can't find the saved search reference in the array`, () => { @@ -183,6 +186,7 @@ Object { id: '1', title: 'test', visState: ({ + type: 'input_control_vis', params: { controls: [ { diff --git a/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/saved_visualization_references.ts b/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/saved_visualization_references.ts index 66ef9a1d7d2dd..6a4f9812db971 100644 --- a/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/saved_visualization_references.ts +++ b/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/saved_visualization_references.ts @@ -54,10 +54,9 @@ export function extractReferences({ if (updatedAttributes.visState) { const visState = JSON.parse(String(updatedAttributes.visState)) as SavedVisState; - extractControlsReferences(visState.params, updatedReferences); - - if (visState.type === 'metrics') { - extractTimeSeriesReferences(visState.params, updatedReferences); + if (visState.type && visState.params) { + extractControlsReferences(visState.type, visState.params, updatedReferences); + extractTimeSeriesReferences(visState.type, visState.params, updatedReferences); } updatedAttributes.visState = JSON.stringify(visState); @@ -87,11 +86,10 @@ export function injectReferences(savedObject: VisSavedObject, references: SavedO delete savedObject.savedSearchRefName; } - if (savedObject.visState?.params) { - injectControlsReferences(savedObject.visState.params, references); + const { type, params } = savedObject.visState ?? {}; - if (savedObject.visState.type === 'metrics') { - injectTimeSeriesReferences(savedObject.visState.params, references); - } + if (type && params) { + injectControlsReferences(type, params, references); + injectTimeSeriesReferences(type, params, references); } } diff --git a/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/timeseries_references.ts b/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/timeseries_references.ts index 845da0d011ed7..57706ee824e8d 100644 --- a/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/timeseries_references.ts +++ b/src/plugins/visualizations/public/saved_visualizations/saved_visualization_references/timeseries_references.ts @@ -18,6 +18,8 @@ const INDEX_PATTERN_REF_TYPE = 'index_pattern'; /** @internal **/ type Action = (object: Record, key: string) => void; +const isMetricsVis = (visType: string) => visType === 'metrics'; + const doForExtractedIndices = (action: Action, visParams: VisParams) => { action(visParams, 'index_pattern'); @@ -35,41 +37,47 @@ const doForExtractedIndices = (action: Action, visParams: VisParams) => { }; export const extractTimeSeriesReferences = ( + visType: string, visParams: VisParams, - references: SavedObjectReference[] = [] + references: SavedObjectReference[] = [], + prefix: string = 'metrics' ) => { let i = 0; + if (isMetricsVis(visType)) { + doForExtractedIndices((object, key) => { + if (object[key] && object[key].id) { + const name = `${prefix}_${i++}_index_pattern`; - doForExtractedIndices((object, key) => { - if (object[key] && object[key].id) { - const name = `ref_${++i}_index_pattern`; - - object[key + REF_NAME_POSTFIX] = name; - references.push({ - name, - type: INDEX_PATTERN_REF_TYPE, - id: object[key].id, - }); - delete object[key]; - } - }, visParams); + object[key + REF_NAME_POSTFIX] = name; + references.push({ + name, + type: INDEX_PATTERN_REF_TYPE, + id: object[key].id, + }); + delete object[key]; + } + }, visParams); + } }; export const injectTimeSeriesReferences = ( + visType: string, visParams: VisParams, references: SavedObjectReference[] ) => { - doForExtractedIndices((object, key) => { - const refKey = key + REF_NAME_POSTFIX; + if (isMetricsVis(visType)) { + doForExtractedIndices((object, key) => { + const refKey = key + REF_NAME_POSTFIX; - if (object[refKey]) { - const refValue = references.find((ref) => ref.name === object[refKey]); + if (object[refKey]) { + const refValue = references.find((ref) => ref.name === object[refKey]); - if (refValue) { - object[key] = { id: refValue.id }; - } + if (refValue) { + object[key] = { id: refValue.id }; + } - delete object[refKey]; - } - }, visParams); + delete object[refKey]; + } + }, visParams); + } }; From f882f11a3f4c47e31337f11d70a36c3498d0fa21 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Fri, 26 Mar 2021 16:20:32 +0300 Subject: [PATCH 39/39] remove MigrationPopover --- .../index_pattern_select.tsx | 32 +++-- .../index_pattern_select/migrate_popover.tsx | 115 ------------------ 2 files changed, 22 insertions(+), 125 deletions(-) delete mode 100644 src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/migrate_popover.tsx diff --git a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/index_pattern_select.tsx b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/index_pattern_select.tsx index a3854bdc41e76..28b9c173a2b1b 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/index_pattern_select.tsx +++ b/src/plugins/vis_type_timeseries/public/application/components/lib/index_pattern_select/index_pattern_select.tsx @@ -8,9 +8,10 @@ import React, { useState, useContext, useCallback, useEffect } from 'react'; import { i18n } from '@kbn/i18n'; -import { EuiFormRow, htmlIdGenerator } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; -import { getDataStart } from '../../../../services'; +import { EuiFormRow, EuiText, EuiLink, htmlIdGenerator } from '@elastic/eui'; +import { getCoreStart, getDataStart } from '../../../../services'; import { PanelModelContext } from '../../../contexts/panel_model_context'; import { @@ -20,7 +21,6 @@ import { import { FieldTextSelect } from './field_text_select'; import { ComboBoxSelect } from './combo_box_select'; -import { MigrationPopover } from './migrate_popover'; import type { IndexPatternValue, FetchedIndexPattern } from '../../../../../common/types'; @@ -88,6 +88,14 @@ export const IndexPatternSelect = ({ [onChange, indexPatternName] ); + const navigateToCreateIndexPatternPage = useCallback(() => { + const coreStart = getCoreStart(); + + coreStart.application.navigateToApp('management', { + path: `/kibana/indexPatterns/create?name=${fetchedIndex!.indexPatternString ?? ''}`, + }); + }, [fetchedIndex]); + useEffect(() => { async function fetchIndex() { const { indexPatterns } = getDataStart(); @@ -119,13 +127,17 @@ export const IndexPatternSelect = ({ labelAppend={ value && allowIndexSwitchingMode && - isStringTypeIndexPattern(value) && ( - - ) + isStringTypeIndexPattern(value) && + !fetchedIndex.indexPattern ? ( + + + + + + ) : null } > void) => ( - <> - - {value}, - }} - /> - - - - - - -); - -const getNoMatchedIndicesCallOut = (value: string, onCreateIndexClick: () => void) => ( - <> - - {value}, - }} - /> - - - - - - -); - -export const MigrationPopover = ({ fetchedIndex, onModeChange }: PopoverProps) => { - const [isPopoverOpen, setIsPopoverOpen] = useState(false); - const closePopover = useCallback(() => setIsPopoverOpen(false), []); - const onButtonClick = useCallback(() => setIsPopoverOpen((isOpen) => !isOpen), []); - - const switchMode = useCallback(() => { - onModeChange(true, fetchedIndex); - }, [onModeChange, fetchedIndex]); - - const navigateToCreateIndexPatterns = useCallback(() => { - const coreStart = getCoreStart(); - - coreStart.application.navigateToApp('management', { - path: `/kibana/indexPatterns/create?name=${fetchedIndex.indexPatternString ?? ''}`, - }); - }, [fetchedIndex]); - - if (!fetchedIndex.indexPatternString) { - return null; - } - - return ( - - {switchModeLabel} - - } - isOpen={isPopoverOpen} - closePopover={closePopover} - > - {switchModeLabel} - {fetchedIndex.indexPattern && - getReadyToSwitchCallOut(fetchedIndex.indexPatternString, switchMode)} - - {!fetchedIndex.indexPattern && - getNoMatchedIndicesCallOut(fetchedIndex.indexPatternString, navigateToCreateIndexPatterns)} - - ); -};