diff --git a/src/core/public/saved_objects/saved_objects_client.ts b/src/core/public/saved_objects/saved_objects_client.ts index ad934e0a73ae..9dc6a84b484a 100644 --- a/src/core/public/saved_objects/saved_objects_client.ts +++ b/src/core/public/saved_objects/saved_objects_client.ts @@ -457,14 +457,14 @@ export class SavedObjectsClient { * { id: 'foo', type: 'index-pattern' } * ]) */ - public bulkGet = (objects: Array<{ id: string; type: string }> = []) => { + public bulkGet = (objects: Array<{ id: string; type: string }> = []) => { const filteredObjects = objects.map((obj) => pick(obj, ['id', 'type'])); return this.performBulkGet(filteredObjects).then((resp) => { resp.saved_objects = resp.saved_objects.map((d) => this.createSavedObject(d)); return renameKeys< PromiseType>, - SavedObjectsBatchResponse - >({ saved_objects: 'savedObjects' }, resp) as SavedObjectsBatchResponse; + SavedObjectsBatchResponse + >({ saved_objects: 'savedObjects' }, resp) as SavedObjectsBatchResponse; }); }; diff --git a/src/plugins/data/common/datasets/types.ts b/src/plugins/data/common/datasets/types.ts index ae50326ead61..69549a631ab9 100644 --- a/src/plugins/data/common/datasets/types.ts +++ b/src/plugins/data/common/datasets/types.ts @@ -119,8 +119,6 @@ export interface DataStructure { parent?: DataStructure; /** Optional array of child data structures */ children?: DataStructure[]; - /** Optional array of data structures of ancestors */ - path?: DataStructure[]; hasNext?: boolean; columnHeader?: string; /** Optional metadata for the data structure */ @@ -212,12 +210,16 @@ export interface BaseDataset { * * @example * Example of a Dataset for an OpenSearch index pattern - * Index patterns have a reference to the data source and their title is pre appended with the data source they belong to so we dont need to append the data source to the dataset object * const logsIndexDataset: Dataset = { * id: "2e1b1b80-9c4d-11ee-8c90-0242ac120001", - * title: "Cluster1::logs-*", + * title: "logs-*", * type: "INDEX_PATTERN", * timeFieldName: "@timestamp", + * dataSource: { + * id: "2e1b1b80-9c4d-11ee-8c90-0242ac120001", + * title: "Cluster1", + * type: "OpenSearch" + * } * }; * * @example diff --git a/src/plugins/data/public/query/query_string/dataset_service/dataset_service.ts b/src/plugins/data/public/query/query_string/dataset_service/dataset_service.ts index 52cafc5798ec..7dd10c2e5245 100644 --- a/src/plugins/data/public/query/query_string/dataset_service/dataset_service.ts +++ b/src/plugins/data/public/query/query_string/dataset_service/dataset_service.ts @@ -98,9 +98,9 @@ export class DatasetService { return undefined; } - const handler = this.typesRegistry.get(DEFAULT_DATA.SET_TYPES.INDEX_PATTERN); - if (handler) { - const dataset = handler.toDataset([ + const dataType = this.typesRegistry.get(DEFAULT_DATA.SET_TYPES.INDEX_PATTERN); + if (dataType) { + const dataset = dataType.toDataset([ { id: indexPattern.id, title: indexPattern.title, diff --git a/src/plugins/data/public/query/query_string/dataset_service/lib/index_pattern_type.ts b/src/plugins/data/public/query/query_string/dataset_service/lib/index_pattern_type.ts index 098f954214f4..eeb17cb7a146 100644 --- a/src/plugins/data/public/query/query_string/dataset_service/lib/index_pattern_type.ts +++ b/src/plugins/data/public/query/query_string/dataset_service/lib/index_pattern_type.ts @@ -4,12 +4,14 @@ */ import { SavedObjectsClientContract } from 'opensearch-dashboards/public'; +import { DataSourceAttributes } from '../../../../../../data_source/common/data_sources'; import { DEFAULT_DATA, DataStructure, DatasetField, Dataset, IIndexPattern, + DATA_STRUCTURE_META_TYPES, } from '../../../../../common'; import { DatasetTypeConfig } from '../types'; import { getIndexPatterns } from '../../../../services'; @@ -22,7 +24,7 @@ export const indexPatternTypeConfig: DatasetTypeConfig = { tooltip: 'OpenSearch Index Patterns', }, - toDataset: (path: DataStructure[]): Dataset => { + toDataset: (path) => { const pattern = path[path.length - 1]; return { id: pattern.id, @@ -35,13 +37,10 @@ export const indexPatternTypeConfig: DatasetTypeConfig = { type: pattern.parent.type, } : undefined, - }; + } as Dataset; }, - fetch: async ( - savedObjects: SavedObjectsClientContract, - path: DataStructure[] - ): Promise => { + fetch: async (savedObjects, path) => { const dataStructure = path[path.length - 1]; const indexPatterns = await fetchIndexPatterns(savedObjects); return { @@ -60,8 +59,11 @@ export const indexPatternTypeConfig: DatasetTypeConfig = { })); }, - supportedLanguages: (): string[] => { - return ['SQL', 'PPL', 'DQL', 'Lucene']; + supportedLanguages: (dataset): string[] => { + if (dataset.dataSource?.type === 'OpenSearch Serverless') { + return ['DQL', 'Lucene']; + } + return ['DQL', 'Lucene', 'PPL', 'SQL']; }, }; @@ -73,19 +75,51 @@ const fetchIndexPatterns = async (client: SavedObjectsClientContract): Promise ({ - id: savedObject.id, - title: savedObject.attributes.title, - timeFieldName: savedObject.attributes.timeFieldName, - type: DEFAULT_DATA.SET_TYPES.INDEX_PATTERN, - ...(savedObject.references[0] - ? { - dataSource: { - id: savedObject.references[0]?.id, - name: savedObject.references[0]?.name, - type: 'data-source', - }, - } - : {}), - })); + + // Get all unique data source ids + const datasourceIds = Array.from( + new Set( + resp.savedObjects + .filter((savedObject) => savedObject.references.length > 0) + .map((savedObject) => savedObject.references.find((ref) => ref.type === 'data-source')?.id) + .filter(Boolean) + ) + ) as string[]; + + const dataSourceMap: Record = {}; + if (datasourceIds.length > 0) { + const dataSourceResp = await client.bulkGet( + datasourceIds.map((id) => ({ id, type: 'data-source' })) + ); + + dataSourceResp.savedObjects.forEach((savedObject) => { + dataSourceMap[savedObject.id] = savedObject.attributes; + }); + } + + return resp.savedObjects.map( + (savedObject): DataStructure => { + const dataSourceId = savedObject.references.find((ref) => ref.type === 'data-source')?.id; + const dataSource = dataSourceId ? dataSourceMap[dataSourceId] : undefined; + + const indexPatternDataStructure: DataStructure = { + id: savedObject.id, + title: savedObject.attributes.title, + type: DEFAULT_DATA.SET_TYPES.INDEX_PATTERN, + meta: { + type: DATA_STRUCTURE_META_TYPES.CUSTOM, + timeFieldName: savedObject.attributes.timeFieldName, + }, + }; + + if (dataSource) { + indexPatternDataStructure.parent = { + id: dataSourceId!, // Since we know it exists + title: dataSource.title, + type: dataSource.dataSourceEngineType ?? 'OpenSearch', + }; + } + return indexPatternDataStructure; + } + ); }; diff --git a/src/plugins/data/public/query/query_string/dataset_service/lib/index_type.ts b/src/plugins/data/public/query/query_string/dataset_service/lib/index_type.ts index 1200d207e822..fcc531c56f80 100644 --- a/src/plugins/data/public/query/query_string/dataset_service/lib/index_type.ts +++ b/src/plugins/data/public/query/query_string/dataset_service/lib/index_type.ts @@ -5,7 +5,7 @@ import { SavedObjectsClientContract } from 'opensearch-dashboards/public'; import { map } from 'rxjs/operators'; -import { DEFAULT_DATA, DataStructure, DatasetField, Dataset } from '../../../../../common'; +import { DEFAULT_DATA, DataStructure, Dataset } from '../../../../../common'; import { DatasetTypeConfig } from '../types'; import { getSearchService, getIndexPatterns } from '../../../../services'; @@ -25,7 +25,7 @@ export const indexTypeConfig: DatasetTypeConfig = { tooltip: 'OpenSearch Indexes', }, - toDataset: (path: DataStructure[]): Dataset => { + toDataset: (path) => { const index = path[path.length - 1]; const dataSource = path.find((ds) => ds.type === 'DATA_SOURCE'); @@ -43,10 +43,7 @@ export const indexTypeConfig: DatasetTypeConfig = { }; }, - fetch: async ( - savedObjects: SavedObjectsClientContract, - path: DataStructure[] - ): Promise => { + fetch: async (savedObjects, path) => { const dataStructure = path[path.length - 1]; switch (dataStructure.type) { case 'DATA_SOURCE': { @@ -75,7 +72,7 @@ export const indexTypeConfig: DatasetTypeConfig = { } }, - fetchFields: async (dataset: Dataset): Promise => { + fetchFields: async (dataset) => { const fields = await getIndexPatterns().getFieldsForWildcard({ pattern: dataset.title, dataSourceId: dataset.dataSource?.id, @@ -86,7 +83,7 @@ export const indexTypeConfig: DatasetTypeConfig = { })); }, - supportedLanguages: (): string[] => { + supportedLanguages: (dataset: Dataset): string[] => { return ['SQL', 'PPL', 'DQL', 'Lucene']; }, }; diff --git a/src/plugins/data/public/query/query_string/dataset_service/types.ts b/src/plugins/data/public/query/query_string/dataset_service/types.ts index a8ef97eda6f5..8d597694ac49 100644 --- a/src/plugins/data/public/query/query_string/dataset_service/types.ts +++ b/src/plugins/data/public/query/query_string/dataset_service/types.ts @@ -43,5 +43,5 @@ export interface DatasetTypeConfig { * Retrieves the supported query languages for this dataset type. * @returns {Promise} A promise that resolves to an array of supported language names. */ - supportedLanguages: () => string[]; + supportedLanguages: (dataset: Dataset) => string[]; } diff --git a/src/plugins/data/public/query/query_string/query_string_manager.mock.ts b/src/plugins/data/public/query/query_string/query_string_manager.mock.ts index 3d7556c1e954..4d2f389a7f71 100644 --- a/src/plugins/data/public/query/query_string/query_string_manager.mock.ts +++ b/src/plugins/data/public/query/query_string/query_string_manager.mock.ts @@ -46,6 +46,7 @@ const createSetupContractMock = () => { getInitialQueryByLanguage: jest.fn(), getDatasetService: jest.fn(), getLanguageService: jest.fn(), + getInitialQueryByDataset: jest.fn(), }; return queryStringManagerMock; }; diff --git a/src/plugins/data/public/ui/dataset_selector/__mocks__/utils.ts b/src/plugins/data/public/ui/dataset_selector/__mocks__/utils.ts deleted file mode 100644 index 68fc16ed4b12..000000000000 --- a/src/plugins/data/public/ui/dataset_selector/__mocks__/utils.ts +++ /dev/null @@ -1,343 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -// import { Dataset, DataSource, DataStructure } from '../../../../common/datasets'; - -// interface DatasetVariations { -// dataSourceTypes: string[]; -// dataSetTypes: string[]; -// timeFields: string[]; -// } - -// export function generateRandomDatasets(count: number, variations: DatasetVariations): Dataset[] { -// const datasets: Dataset[] = []; - -// for (let i = 0; i < count; i++) { -// const dataSource: DataSource = { -// id: `ds-${Math.random().toString(36).substr(2, 9)}`, -// title: `Data Source ${i + 1}`, -// type: -// variations.dataSourceTypes[Math.floor(Math.random() * variations.dataSourceTypes.length)], -// }; - -// const dataset: Dataset = { -// id: `dataset-${Math.random().toString(36).substr(2, 9)}`, -// title: `Dataset ${i + 1}`, -// type: variations.dataSetTypes[Math.floor(Math.random() * variations.dataSetTypes.length)], -// timeFieldName: -// variations.timeFields[Math.floor(Math.random() * variations.timeFields.length)], -// dataSource, -// }; - -// datasets.push(dataset); -// } - -// return datasets; -// } - -// class MockDatasetManager implements DatasetManager { -// private types: { -// [key: string]: DatasetTypeConfig; -// } = {}; - -// private dataset?: Dataset; -// private recentDatasets: Dataset[] = []; - -// constructor() { -// this.registerType({ -// id: 'index-pattern', -// title: 'Index Pattern', -// getOptions: this.mockGetIndexPatternOptions, -// getDataset: this.mockGetIndexPatternDataset, -// getFields: this.mockGetIndexPatternFields, -// config: { -// supportedLanguages: ['DQL', 'lucene'], -// icon: { -// type: 'indexPatternApp', -// }, -// }, -// }); - -// this.registerType({ -// id: 'indices', -// title: 'Indices', -// getOptions: this.mockGetIndicesOptions, -// getDataset: this.mockGetIndicesDataset, -// getFields: this.mockGetIndicesFields, -// config: { -// supportedLanguages: ['DQL', 'lucene'], -// icon: { -// type: 'logoOpenSearch', -// }, -// hasTimeField: true, -// }, -// }); - -// this.registerType({ -// id: 's3', -// title: 'S3', -// getOptions: this.mockGetS3Options, -// getDataset: this.mockGetS3Dataset, -// getFields: this.mockGetS3Fields, -// config: { -// supportedLanguages: ['SQL'], -// icon: { -// type: 'logoAWS', -// }, -// hasTimeField: false, -// }, -// }); -// } - -// registerType = (props: DatasetTypeConfig) => { -// this.types[props.id] = props; -// }; - -// getTypes = () => { -// return Object.values(this.types); -// }; - -// getType = (type: string) => { -// return this.types[type]; -// }; - -// getDataSet = () => { -// return this.dataset; -// }; - -// setDataSet = (dataset: Dataset) => { -// this.dataset = dataset; -// // Store the top 10 recently used -// this.recentDatasets = [dataset, ...this.recentDatasets].slice(0, 10); -// }; - -// getRecentlyUsed = () => { -// return this.recentDatasets; -// }; - -// private mockGetIndexPatternOptions = async (path?: DataStructure[]) => { -// const lastOption = path?.[path.length - 1]; - -// if (lastOption?.id !== 'index-pattern') { -// return { -// options: [], -// columnHeader: 'Index patterns', -// }; -// } -// const mockData: DataStructure[] = [ -// { id: 'pattern1', title: 'logs-*', type: 'index-pattern' }, -// { id: 'pattern2', title: 'metrics-*', type: 'index-pattern' }, -// { id: 'pattern3', title: 'events-*', type: 'index-pattern' }, -// ]; - -// return { -// options: mockData, -// columnHeader: 'Index patterns', -// }; -// }; - -// private mockGetIndexPatternDataset = (path: DataStructure[]) => { -// const lastOption = path?.[path.length - 1]; - -// return { -// id: lastOption?.id, -// title: lastOption?.title, -// type: 'index-pattern', -// timeFieldName: 'timestamp', -// dataSource: { -// id: 'main-cluster', -// title: 'Main OpenSearch Cluster', -// type: 'OPENSEARCH', -// }, -// }; -// }; - -// private mockGetIndexPatternFields = async (dataset: Dataset) => { -// return [ -// { -// name: 'timestamp', -// type: 'date', -// }, -// { -// name: 'bytes', -// type: 'number', -// }, -// { -// name: 'cpu', -// type: 'number', -// }, -// { -// name: 'memory', -// type: 'number', -// }, -// { -// name: 'log', -// type: 'string', -// }, -// ]; -// }; - -// private mockGetIndicesOptions = async (path?: DataStructure[]) => { -// const option = path?.[path.length - 1]; -// if (option?.type === 'indices') { -// // First level: List of clusters -// const mockClusters: DataStructure[] = [ -// { id: 'cluster1', title: 'Production Cluster', type: 'cluster' }, -// { id: 'cluster2', title: 'Development Cluster', type: 'cluster' }, -// { id: 'cluster3', title: 'Testing Cluster', type: 'cluster' }, -// ]; - -// return { -// options: mockClusters, -// isLoadable: true, -// columnHeader: 'Clusters', -// }; -// } else if (option?.type === 'cluster') { -// // Second level: List of indices within the selected cluster -// const mockIndices: DataStructure[] = [ -// { id: `${option.id}-index1`, title: `${option.title}-logs-2023.05`, type: 'index' }, -// { id: `${option.id}-index2`, title: `${option.title}-metrics-2023.05`, type: 'index' }, -// { id: `${option.id}-index3`, title: `${option.title}-events-2023.05`, type: 'index' }, -// ]; - -// return { -// options: mockIndices, -// columnHeader: 'Indices', -// }; -// } - -// // If we reach here, it's an unexpected state -// return { -// options: [], -// columnHeader: 'Indices', -// }; -// }; - -// private mockGetIndicesDataset = (path: DataStructure[]) => { -// const option = path?.[path.length - 1]; - -// return { -// id: option?.id, -// title: option?.title, -// type: 'indices', -// timeFieldName: 'timestamp', -// dataSource: { -// id: 'main-cluster', -// title: 'Main OpenSearch Cluster', -// type: 'OPENSEARCH', -// }, -// }; -// }; - -// private mockGetIndicesFields = async (dataset: Dataset) => { -// return [ -// { -// name: 'timestamp', -// type: 'date', -// }, -// { -// name: 'bytes', -// type: 'number', -// }, -// { -// name: 'cpu', -// type: 'number', -// }, -// { -// name: 'memory', -// type: 'number', -// }, -// { -// name: 'log', -// type: 'string', -// }, -// ]; -// }; - -// private mockGetS3Options = async (path?: DataStructure[]) => { -// const lastOption = path?.[path.length - 1]; - -// if (!lastOption || lastOption.type === 's3') { -// // First level: Connections (instantaneous) -// const mockConnections: DataStructure[] = [ -// { id: 'conn1', title: 'Production S3', type: 'connection' }, -// { id: 'conn2', title: 'Development S3', type: 'connection' }, -// { id: 'conn3', title: 'Testing S3', type: 'connection' }, -// ]; - -// return { -// options: mockConnections, -// columnHeader: 'S3 Connections', -// isLoadable: true, -// }; -// } else if (lastOption.type === 'connection') { -// // Second level: Databases (10s delay) -// await new Promise((resolve) => setTimeout(resolve, 3000)); - -// const mockDatabases: DataStructure[] = [ -// { id: `${lastOption.id}-db1`, title: 'Customer Data', type: 'database' }, -// { id: `${lastOption.id}-db2`, title: 'Product Catalog', type: 'database' }, -// { id: `${lastOption.id}-db3`, title: 'Sales Records', type: 'database' }, -// ]; - -// return { -// options: mockDatabases, -// columnHeader: 'S3 Databases', -// isLoadable: true, -// }; -// } else if (lastOption.type === 'database') { -// // Third level: Tables (10s delay) -// await new Promise((resolve) => setTimeout(resolve, 3000)); - -// const mockTables: DataStructure[] = [ -// { id: `${lastOption.id}-table1`, title: 'Users', type: 'table' }, -// { id: `${lastOption.id}-table2`, title: 'Orders', type: 'table' }, -// { id: `${lastOption.id}-table3`, title: 'Products', type: 'table' }, -// ]; - -// return { -// options: mockTables, -// columnHeader: 'S3 Tables', -// isLoadable: false, -// }; -// } - -// return { -// options: [], -// columnHeader: 'S3', -// }; -// }; - -// private mockGetS3Dataset = (path: DataStructure[]) => { -// const lastOption = path[path.length - 1]; - -// return { -// id: lastOption.id, -// title: lastOption.title, -// type: 's3', -// dataSource: { -// id: path[1].id, // Connection ID -// title: path[1].title, // Connection Title -// type: 'S3', -// }, -// }; -// }; - -// private mockGetS3Fields = async (dataset: Dataset) => { -// // Simulate a delay for field fetching -// await new Promise((resolve) => setTimeout(resolve, 5000)); - -// return [ -// { name: 'id', type: 'string' }, -// { name: 'name', type: 'string' }, -// { name: 'created_at', type: 'date' }, -// { name: 'updated_at', type: 'date' }, -// { name: 'value', type: 'number' }, -// ]; -// }; -// } - -// // Export an instance of the mock manager -// export const mockDatasetManager = new MockDatasetManager(); diff --git a/src/plugins/data/public/ui/dataset_selector/configurator.tsx b/src/plugins/data/public/ui/dataset_selector/configurator.tsx index ce55fe331d3a..32e48691aa87 100644 --- a/src/plugins/data/public/ui/dataset_selector/configurator.tsx +++ b/src/plugins/data/public/ui/dataset_selector/configurator.tsx @@ -36,11 +36,10 @@ export const Configurator = ({ const queryService = getQueryService(); const queryString = queryService.queryString; const indexPatternsService = getIndexPatterns(); - const languages = - queryString.getDatasetService().getType(baseDataset.type)?.supportedLanguages() || []; + const type = queryString.getDatasetService().getType(baseDataset.type); + const languages = type?.supportedLanguages(baseDataset) || []; const [dataset, setDataset] = useState(baseDataset); - const [fields, setFields] = useState(); const [timeFields, setTimeFields] = useState(); const [timeField, setTimeField] = useState(dataset.timeFieldName); const [language, setLanguage] = useState(languages[0]); @@ -52,7 +51,6 @@ export const Configurator = ({ .getType(baseDataset.type) ?.fetchFields(baseDataset); - setFields(datasetFields); const dateFields = datasetFields?.filter((field) => field.type === 'date'); setTimeFields(dateFields || []); }; diff --git a/src/plugins/data/public/ui/dataset_selector/dataset_explorer.tsx b/src/plugins/data/public/ui/dataset_selector/dataset_explorer.tsx index c8c6adcb4866..dd35ce8065b2 100644 --- a/src/plugins/data/public/ui/dataset_selector/dataset_explorer.tsx +++ b/src/plugins/data/public/ui/dataset_selector/dataset_explorer.tsx @@ -110,7 +110,7 @@ export const DatasetExplorer = ({ ({ - label: child.title, + label: child.parent ? `${child.parent.title}::${child.title}` : child.title, value: child.id, prepend: child.meta?.type === DATA_STRUCTURE_META_TYPES.TYPE && child.meta?.icon && , diff --git a/src/plugins/data/public/ui/dataset_selector/dataset_selector.tsx b/src/plugins/data/public/ui/dataset_selector/dataset_selector.tsx index 5614a8ec48b3..01441f736c79 100644 --- a/src/plugins/data/public/ui/dataset_selector/dataset_selector.tsx +++ b/src/plugins/data/public/ui/dataset_selector/dataset_selector.tsx @@ -41,15 +41,22 @@ export const DatasetSelector = ({ datasetService.getType(selectedDataset?.type || '')?.meta.icon.type || 'database'; const fetchDatasets = useCallback(async () => { - const fetchedDatasets = await datasetService - .getType(DEFAULT_DATA.SET_TYPES.INDEX_PATTERN) - ?.fetch(savedObjects.client, []); - const newDatasets = fetchedDatasets?.children || []; - setDatasets(newDatasets); + const typeConfig = datasetService.getType(selectedDataset?.type || ''); + if (!typeConfig || typeConfig.id !== DEFAULT_DATA.SET_TYPES.INDEX_PATTERN) { + return; + } + + const fetchedIndexPatternDataStructures = await typeConfig.fetch(savedObjects.client, []); + + const fetchedDatasets = + fetchedIndexPatternDataStructures.children?.map((pattern) => + typeConfig.toDataset([pattern]) + ) ?? []; + setDatasets(fetchedDatasets); // If no dataset is selected, select the first one - if (!selectedDataset && newDatasets.length > 0) { - setSelectedDataset(newDatasets[0]); + if (!selectedDataset && fetchedDatasets.length > 0) { + setSelectedDataset(fetchedDatasets[0]); } }, [datasetService, savedObjects.client, selectedDataset, setSelectedDataset]); @@ -74,9 +81,10 @@ export const DatasetSelector = ({ }, ]; - datasets.forEach(({ id, title, type }) => { + datasets.forEach(({ id, title, type, dataSource }) => { + const label = dataSource ? `${dataSource.title}::${title}` : title; newOptions.push({ - label: title, + label, checked: id === selectedDataset?.id ? 'on' : undefined, key: id, prepend: , @@ -100,6 +108,18 @@ export const DatasetSelector = ({ [datasets, setSelectedDataset, closePopover] ); + const datasetTitle = useMemo(() => { + if (!selectedDataset) { + return 'Select data'; + } + + if (selectedDataset.dataSource) { + return `${selectedDataset.dataSource.title}::${selectedDataset.title}`; + } + + return selectedDataset.title; + }, [selectedDataset]); + return ( - {selectedDataset?.title ?? 'Select data'} + {datasetTitle} } diff --git a/src/plugins/data_explorer/public/utils/state_management/metadata_slice.ts b/src/plugins/data_explorer/public/utils/state_management/metadata_slice.ts index b0965869c336..1fca4a659244 100644 --- a/src/plugins/data_explorer/public/utils/state_management/metadata_slice.ts +++ b/src/plugins/data_explorer/public/utils/state_management/metadata_slice.ts @@ -5,6 +5,7 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import { DataExplorerServices } from '../../types'; +import { QUERY_ENHANCEMENT_ENABLED_SETTING } from '../../components/constants'; export interface MetadataState { indexPattern?: string; @@ -18,12 +19,16 @@ export const getPreloadedState = async ({ embeddable, scopedHistory, data, + uiSettings, }: DataExplorerServices): Promise => { const { originatingApp } = embeddable .getStateTransfer(scopedHistory) .getIncomingEditorState({ keysToRemoveAfterFetch: ['id', 'input'] }) || {}; - const defaultIndexPattern = await data.indexPatterns.getDefault(); + const isQueryEnhancementEnabled = uiSettings.get(QUERY_ENHANCEMENT_ENABLED_SETTING); + const defaultIndexPattern = isQueryEnhancementEnabled + ? undefined + : await data.indexPatterns.getDefault(); const preloadedState: MetadataState = { ...initialState, originatingApp, diff --git a/src/plugins/data_explorer/public/utils/state_management/redux_persistence.ts b/src/plugins/data_explorer/public/utils/state_management/redux_persistence.ts index a6a7d29156d3..7eb715433f01 100644 --- a/src/plugins/data_explorer/public/utils/state_management/redux_persistence.ts +++ b/src/plugins/data_explorer/public/utils/state_management/redux_persistence.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { DEFAULT_DATA } from '../../../../data/common'; +import { Dataset, DEFAULT_DATA } from '../../../../data/common'; import { QUERY_ENHANCEMENT_ENABLED_SETTING } from '../../components/constants'; import { DataExplorerServices } from '../../types'; import { getPreloadedState } from './preload'; @@ -21,20 +21,23 @@ export const loadReduxState = async (services: DataExplorerServices) => { serializedState.metadata.indexPattern ); - const dataset = { + const dataset: Dataset = { id: serializedState.metadata.indexPattern, title: indexPattern.title, type: DEFAULT_DATA.SET_TYPES.INDEX_PATTERN, }; - // TODO: This is a temporary fix since indexpattern.get does not modify the title like the other list based methods. This should be handeled in a better way: https://github.com/opensearch-project/OpenSearch-Dashboards/issues/7837 if (indexPattern.dataSourceRef) { const dataSource = await services.data.indexPatterns.getDataSource( indexPattern.dataSourceRef.id ); if (dataSource) { - dataset.title = `${dataSource.attributes.title}::${dataset.title}`; + dataset.dataSource = { + id: dataSource.id, + title: dataSource.attributes.title, + type: dataSource.attributes.dataSourceEngineType || '', + }; } } services.data.query.queryString.setQuery({ @@ -51,6 +54,7 @@ export const loadReduxState = async (services: DataExplorerServices) => { console.error(err); } + // If state is not found, load the default state return await getPreloadedState(services); };