From 3702412aa90dbadc4c86a7b7fce927eb1d5a5d8f Mon Sep 17 00:00:00 2001 From: Kristen Tian <105667444+kristenTian@users.noreply.github.com> Date: Mon, 8 Aug 2022 21:23:43 -0700 Subject: [PATCH] Add data source step into IndexPattern with Mock switch (#2064) (#2086) Signed-off-by: Kristen Tian --- .../opensearch_dashboards.json | 2 +- .../create_index_pattern_wizard.test.tsx.snap | 6 +- .../components/header/header.tsx | 96 +++++++++++++++++++ .../components/header/index.ts | 6 ++ .../components/step_data_source/index.ts | 6 ++ .../step_data_source/step_data_source.tsx | 43 +++++++++ .../step_index_pattern/step_index_pattern.tsx | 31 +++++- .../create_index_pattern_wizard.test.tsx | 5 +- .../create_index_pattern_wizard.tsx | 68 ++++++++++--- .../lib/creation_flow.ts | 80 ++++++++++++++++ .../create_index_pattern_wizard/lib/index.ts | 2 + .../index_pattern_table.tsx | 23 +++-- .../mount_management_section.tsx | 3 + .../index_pattern_management/public/types.ts | 4 + 14 files changed, 347 insertions(+), 28 deletions(-) create mode 100644 src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_data_source/components/header/header.tsx create mode 100644 src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_data_source/components/header/index.ts create mode 100644 src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_data_source/index.ts create mode 100644 src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_data_source/step_data_source.tsx create mode 100644 src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/lib/creation_flow.ts diff --git a/src/plugins/index_pattern_management/opensearch_dashboards.json b/src/plugins/index_pattern_management/opensearch_dashboards.json index 20bb7b90759..b6b04ab2bf6 100644 --- a/src/plugins/index_pattern_management/opensearch_dashboards.json +++ b/src/plugins/index_pattern_management/opensearch_dashboards.json @@ -4,5 +4,5 @@ "server": true, "ui": true, "requiredPlugins": ["management", "data", "urlForwarding"], - "requiredBundles": ["opensearchDashboardsReact", "opensearchDashboardsUtils"] + "requiredBundles": ["opensearchDashboardsReact", "opensearchDashboardsUtils", "savedObjects"] } diff --git a/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/__snapshots__/create_index_pattern_wizard.test.tsx.snap b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/__snapshots__/create_index_pattern_wizard.test.tsx.snap index 2371b22ff61..28a4ec0e90a 100644 --- a/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/__snapshots__/create_index_pattern_wizard.test.tsx.snap +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/__snapshots__/create_index_pattern_wizard.test.tsx.snap @@ -40,6 +40,7 @@ exports[`CreateIndexPatternWizard renders index pattern step when there are indi ] } goToNextStep={[Function]} + goToPreviousStep={[Function]} indexPatternCreationType={ IndexPatternCreationConfig { "httpClient": null, @@ -84,6 +85,7 @@ exports[`CreateIndexPatternWizard renders the empty state when there are no indi `; -exports[`CreateIndexPatternWizard renders time field step when step is set to 2 1`] = ` +exports[`CreateIndexPatternWizard renders time field step when step is set to TIME_FIELD_STEP 1`] = `
void; + dataSourceRef: DataSourceRef; + goToNextStep: (dataSourceRef: DataSourceRef) => void; + isNextStepDisabled: boolean; +} + +const DATA_SOURCE_PAGE_SIZE = 5; + +export const Header: React.FC = (props: HeaderProps) => { + const { dataSourceRef, onSearchSelected, goToNextStep, isNextStepDisabled } = props; + + const { savedObjects, uiSettings } = useOpenSearchDashboards< + IndexPatternManagmentContext + >().services; + + return ( +
+ +

+ +

+
+ + + + + + 'apps', // todo: #2034 + name: i18n.translate( + 'indexPatternManagement.createIndexPattern.searchSelection.savedObjectType.dataSource', + { + defaultMessage: 'Data Source', + } + ), + }, + ]} + fixedPageSize={DATA_SOURCE_PAGE_SIZE} + uiSettings={uiSettings} + savedObjects={savedObjects} + /> + + goToNextStep(dataSourceRef)} + isDisabled={isNextStepDisabled} + > + + + + +
+ ); +}; diff --git a/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_data_source/components/header/index.ts b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_data_source/components/header/index.ts new file mode 100644 index 00000000000..3c25d4c42f0 --- /dev/null +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_data_source/components/header/index.ts @@ -0,0 +1,6 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +export { Header } from './header'; diff --git a/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_data_source/index.ts b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_data_source/index.ts new file mode 100644 index 00000000000..6cea2c4957b --- /dev/null +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_data_source/index.ts @@ -0,0 +1,6 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +export { StepDataSource } from './step_data_source'; diff --git a/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_data_source/step_data_source.tsx b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_data_source/step_data_source.tsx new file mode 100644 index 00000000000..eccea5be875 --- /dev/null +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_data_source/step_data_source.tsx @@ -0,0 +1,43 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { EuiPageContent } from '@elastic/eui'; +import React, { useState } from 'react'; +import { DataSourceRef } from 'src/plugins/index_pattern_management/public/types'; + +import { Header } from './components/header'; + +interface StepDataSourceProps { + goToNextStep: (dataSourceRef: DataSourceRef) => void; +} + +export const StepDataSource = (props: StepDataSourceProps) => { + const { goToNextStep } = props; + + const [selectedDataSource, setSelectedDataSource] = useState(); + const [isNextStepDisabled, setIsNextStepDisabled] = useState(true); + + const onSearchSelected = (id: string, selectedType: string) => { + const selected = { id, type: selectedType }; + + setSelectedDataSource(selected); + setIsNextStepDisabled(false); + }; + + const renderContent = () => { + return ( + +
goToNextStep(selectedDataSource!)} + isNextStepDisabled={isNextStepDisabled} + /> + + ); + }; + + return <>{renderContent()}; +}; diff --git a/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/step_index_pattern.tsx b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/step_index_pattern.tsx index 0b81d14d0e0..af94ff6f1f0 100644 --- a/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/step_index_pattern.tsx +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/components/step_index_pattern/step_index_pattern.tsx @@ -29,7 +29,14 @@ */ import React, { Component } from 'react'; -import { EuiSpacer, EuiCallOut, EuiSwitchEvent } from '@elastic/eui'; +import { + EuiSpacer, + EuiCallOut, + EuiSwitchEvent, + EuiFlexGroup, + EuiFlexItem, + EuiButtonEmpty, +} from '@elastic/eui'; import { i18n } from '@osd/i18n'; import { FormattedMessage } from '@osd/i18n/react'; import { indexPatterns, IndexPatternAttributes, UI_SETTINGS } from '../../../../../../data/public'; @@ -52,6 +59,7 @@ import { IndexPatternManagmentContextValue } from '../../../../types'; interface StepIndexPatternProps { allIndices: MatchedItem[]; indexPatternCreationType: IndexPatternCreationConfig; + goToPreviousStep: () => void; goToNextStep: (query: string, timestampField?: string) => void; initialQuery?: string; showSystemIndices: boolean; @@ -116,6 +124,8 @@ export class StepIndexPattern extends Component + + + + + + + ); + } + renderStatusMessage(matchedIndices: { allIndices: MatchedItem[]; exactMatchedIndices: MatchedItem[]; @@ -383,6 +411,7 @@ export class StepIndexPattern extends Component {this.renderList(matchedIndices)} + {this.dataSrouceEnabled && this.renderGoToPrevious()} ); } diff --git a/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/create_index_pattern_wizard.test.tsx b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/create_index_pattern_wizard.test.tsx index b4be3a6cb21..7795c20dafd 100644 --- a/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/create_index_pattern_wizard.test.tsx +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/create_index_pattern_wizard.test.tsx @@ -33,6 +33,7 @@ import { IndexPattern } from '../../../../../plugins/data/public'; import { mockManagementPlugin } from '../../mocks'; import { IndexPatternCreationConfig } from '../../'; import { createComponentWithContext } from '../test_utils'; +import { TIME_FIELD_STEP } from './lib'; jest.mock('./components/step_index_pattern', () => ({ StepIndexPattern: 'StepIndexPattern' })); jest.mock('./components/step_time_field', () => ({ StepTimeField: 'StepTimeField' })); @@ -136,7 +137,7 @@ describe('CreateIndexPatternWizard', () => { expect(component).toMatchSnapshot(); }); - test('renders time field step when step is set to 2', async () => { + test('renders time field step when step is set to TIME_FIELD_STEP', async () => { const component = createComponentWithContext( CreateIndexPatternWizard, { ...routeComponentPropsMock }, @@ -146,7 +147,7 @@ describe('CreateIndexPatternWizard', () => { component.setState({ isInitiallyLoadingIndices: false, allIndices: [{ name: 'myIndexPattern' }], - step: 2, + step: TIME_FIELD_STEP, }); await component.update(); 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 59b0e8bfc6a..c10deeed93e 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 @@ -47,14 +47,25 @@ import { LoadingState } from './components/loading_state'; import { context as contextType } from '../../../../opensearch_dashboards_react/public'; import { getCreateBreadcrumbs } from '../breadcrumbs'; -import { ensureMinimumTime, getIndices } from './lib'; +import { + DATA_SOURCE_STEP, + ensureMinimumTime, + getIndices, + getInitialStepName, + getNextStep, + getPrevStep, + INDEX_PATTERN_STEP, + StepType, + TIME_FIELD_STEP, +} from './lib'; import { IndexPatternCreationConfig } from '../..'; -import { IndexPatternManagmentContextValue } from '../../types'; +import { DataSourceRef, IndexPatternManagmentContextValue } from '../../types'; import { MatchedItem } from './types'; import { DuplicateIndexPatternError, IndexPattern } from '../../../../data/public'; +import { StepDataSource } from './components/step_data_source'; interface CreateIndexPatternWizardState { - step: number; + step: StepType; indexPattern: string; allIndices: MatchedItem[]; remoteClustersExist: boolean; @@ -63,6 +74,7 @@ interface CreateIndexPatternWizardState { indexPatternCreationType: IndexPatternCreationConfig; selectedTimeField?: string; docLinks: DocLinksStart; + dataSourceRef?: DataSourceRef; } export class CreateIndexPatternWizard extends Component< @@ -73,6 +85,8 @@ export class CreateIndexPatternWizard extends Component< public readonly context!: IndexPatternManagmentContextValue; + dataSourceEnabled: boolean; + constructor(props: RouteComponentProps, context: IndexPatternManagmentContextValue) { super(props, context); @@ -80,8 +94,10 @@ export class CreateIndexPatternWizard extends Component< const type = new URLSearchParams(props.location.search).get('type') || undefined; + this.dataSourceEnabled = context.services.dataSourceEnabled; + this.state = { - step: 1, + step: getInitialStepName(this.dataSourceEnabled), indexPattern: '', allIndices: [], remoteClustersExist: false, @@ -209,12 +225,26 @@ export class CreateIndexPatternWizard extends Component< history.push(`/patterns/${emptyPattern.id}`); }; - goToTimeFieldStep = (indexPattern: string, selectedTimeField?: string) => { - this.setState({ step: 2, indexPattern, selectedTimeField }); + goToNextFromIndexPattern = (indexPattern: string, selectedTimeField?: string) => { + this.setState({ indexPattern, selectedTimeField }); + this.goToNextStep(); + }; + + goToNextFromDataSource = (dataSourceRef: DataSourceRef) => { + this.setState({ dataSourceRef }); + this.goToNextStep(); }; - goToIndexPatternStep = () => { - this.setState({ step: 1 }); + goToNextStep = () => { + this.setState((prevState) => ({ + step: getNextStep(prevState.step, this.dataSourceEnabled)!, + })); + }; + + goToPreviousStep = () => { + this.setState((prevState) => ({ + step: getPrevStep(prevState.step, this.dataSourceEnabled)!, + })); }; renderHeader() { @@ -238,7 +268,17 @@ export class CreateIndexPatternWizard extends Component< const header = this.renderHeader(); - if (step === 1) { + if (step === DATA_SOURCE_STEP) { + return ( + + {header} + + + + ); + } + + if (step === INDEX_PATTERN_STEP) { const { location } = this.props; const initialQuery = new URLSearchParams(location.search).get('id') || undefined; @@ -250,23 +290,25 @@ export class CreateIndexPatternWizard extends Component< allIndices={allIndices} initialQuery={indexPattern || initialQuery} indexPatternCreationType={this.state.indexPatternCreationType} - goToNextStep={this.goToTimeFieldStep} + goToPreviousStep={this.goToPreviousStep} + goToNextStep={this.goToNextFromIndexPattern} showSystemIndices={ - this.state.indexPatternCreationType.getShowSystemIndices() && this.state.step === 1 + this.state.indexPatternCreationType.getShowSystemIndices() && + this.state.step === INDEX_PATTERN_STEP } /> ); } - if (step === 2) { + if (step === TIME_FIELD_STEP) { return ( {header} { + if (supportsDataSource) { + return DATA_SOURCE_STEP; + } + + return INDEX_PATTERN_STEP; +}; + +export const getNextStep = ( + currentStep: StepType, + supportsDataSource: boolean +): StepType | null => { + if (supportsDataSource) { + return CREATION_FLOW_WITH_DATA_SOURCE_MAP.get(currentStep).next; + } + + return DEFAULT_CREATION_FLOW_MAP.get(currentStep).next; +}; + +export const getPrevStep = ( + currentStep: StepType, + supportsDataSource: boolean +): StepType | null => { + if (supportsDataSource) { + return CREATION_FLOW_WITH_DATA_SOURCE_MAP.get(currentStep).prev; + } + + return CREATION_FLOW_WITH_DATA_SOURCE_MAP.get(currentStep).prev; +}; + +export const getCurrentStepNumber = ( + currentStep: StepType, + supportsDataSource: boolean +): number => { + if (supportsDataSource) { + return CREATION_FLOW_WITH_DATA_SOURCE_MAP.get(currentStep).stepNumber; + } + + return CREATION_FLOW_WITH_DATA_SOURCE_MAP.get(currentStep).stepNumber; +}; diff --git a/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/lib/index.ts b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/lib/index.ts index b9e7771be27..09644bc4d8d 100644 --- a/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/lib/index.ts +++ b/src/plugins/index_pattern_management/public/components/create_index_pattern_wizard/lib/index.ts @@ -39,3 +39,5 @@ export { getMatchedIndices } from './get_matched_indices'; export { containsIllegalCharacters } from './contains_illegal_characters'; export { extractTimeFields } from './extract_time_fields'; + +export * from './creation_flow'; diff --git a/src/plugins/index_pattern_management/public/components/index_pattern_table/index_pattern_table.tsx b/src/plugins/index_pattern_management/public/components/index_pattern_table/index_pattern_table.tsx index 205c657421e..9a412ec89e1 100644 --- a/src/plugins/index_pattern_management/public/components/index_pattern_table/index_pattern_table.tsx +++ b/src/plugins/index_pattern_management/public/components/index_pattern_table/index_pattern_table.tsx @@ -103,6 +103,7 @@ export const IndexPatternTable = ({ canSave, history }: Props) => { http, getMlCardState, data, + dataSourceEnabled, } = useOpenSearchDashboards().services; const [indexPatterns, setIndexPatterns] = useState([]); const [creationOptions, setCreationOptions] = useState([]); @@ -210,16 +211,18 @@ export const IndexPatternTable = ({ canSave, history }: Props) => { const hasDataIndices = sources.some(({ name }: MatchedItem) => !name.startsWith('.')); if (!indexPatterns.length) { - if (!hasDataIndices && !remoteClustersExist) { - return ( - - ); + if (!dataSourceEnabled) { + if (!hasDataIndices && !remoteClustersExist) { + return ( + + ); + } } else { return ( MlCardState; + dataSourceEnabled: boolean; } export type IndexPatternManagmentContextValue = OpenSearchDashboardsReactContextValue< @@ -67,3 +69,5 @@ export enum MlCardState { DISABLED, ENABLED, } + +export type DataSourceRef = Pick;