diff --git a/src/plugins/data/common/index_patterns/index_patterns/ensure_default_index_pattern.ts b/src/plugins/data/common/index_patterns/index_patterns/ensure_default_index_pattern.ts index e64b0bf33f63..9fed0e1d0519 100644 --- a/src/plugins/data/common/index_patterns/index_patterns/ensure_default_index_pattern.ts +++ b/src/plugins/data/common/index_patterns/index_patterns/ensure_default_index_pattern.ts @@ -32,7 +32,9 @@ import { includes } from 'lodash'; import { IndexPatternsContract } from './index_patterns'; import { UiSettingsCommon } from '../types'; -export type EnsureDefaultIndexPattern = () => Promise | undefined; +export type EnsureDefaultIndexPattern = ( + shouldRedirect?: boolean +) => Promise | undefined; export const createEnsureDefaultIndexPattern = ( uiSettings: UiSettingsCommon, @@ -42,7 +44,10 @@ export const createEnsureDefaultIndexPattern = ( * Checks whether a default index pattern is set and exists and defines * one otherwise. */ - return async function ensureDefaultIndexPattern(this: IndexPatternsContract) { + return async function ensureDefaultIndexPattern( + this: IndexPatternsContract, + shouldRedirect: boolean = true + ) { const patterns = await this.getIds(); let defaultId = await uiSettings.get('defaultIndex'); let defined = !!defaultId; @@ -62,7 +67,8 @@ export const createEnsureDefaultIndexPattern = ( defaultId = patterns[0]; await uiSettings.set('defaultIndex', defaultId); } else { - return onRedirectNoIndexPattern(); + if (shouldRedirect) return onRedirectNoIndexPattern(); + else return; } }; }; diff --git a/src/plugins/data/public/index.ts b/src/plugins/data/public/index.ts index f986cd59e0eb..773f24118907 100644 --- a/src/plugins/data/public/index.ts +++ b/src/plugins/data/public/index.ts @@ -62,13 +62,14 @@ import { } from '../common'; import { FilterLabel } from './ui'; - export { createEditor, DefaultInput, DQLBody, SingleLineInput, DatasetSelector, + AdvancedSelector, + NoIndexPatternsPanel, DatasetSelectorAppearance, } from './ui'; 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 41d1547e8eeb..d8414a33779e 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 @@ -207,6 +207,11 @@ export class DatasetService { return Number(this.sessionStorage.get('lastCacheTime')) || undefined; } + public removeFromRecentDatasets(datasetId: string): void { + this.recentDatasets.del(datasetId); + this.serializeRecentDatasets(); + } + private setLastCacheTime(time: number): void { this.sessionStorage.set('lastCacheTime', time); } diff --git a/src/plugins/data/public/ui/_common.scss b/src/plugins/data/public/ui/_common.scss new file mode 100644 index 000000000000..e74a1ccca6d9 --- /dev/null +++ b/src/plugins/data/public/ui/_common.scss @@ -0,0 +1,11 @@ +.dataUI-centerPanel { + height: 100%; + width: 100%; + + // Push the centralized child up, just like ouiOverlayMask + padding-bottom: 10vh; + + & > * { + @include euiLegibilityMaxWidth(100%); + } +} diff --git a/src/plugins/data/public/ui/_index.scss b/src/plugins/data/public/ui/_index.scss index 9ab4ca672b38..cdbe539a2e19 100644 --- a/src/plugins/data/public/ui/_index.scss +++ b/src/plugins/data/public/ui/_index.scss @@ -1,3 +1,4 @@ +@import "./common"; @import "./filter_bar/index"; @import "./typeahead/index"; @import "./saved_query_management/index"; diff --git a/src/plugins/data/public/ui/dataset_selector/advanced_selector.tsx b/src/plugins/data/public/ui/dataset_selector/advanced_selector.tsx index 734153452eea..25434062de8e 100644 --- a/src/plugins/data/public/ui/dataset_selector/advanced_selector.tsx +++ b/src/plugins/data/public/ui/dataset_selector/advanced_selector.tsx @@ -13,19 +13,27 @@ import { } from '../../../common'; import { DatasetExplorer } from './dataset_explorer'; import { Configurator } from './configurator'; -import { getQueryService } from '../../services'; import { IDataPluginServices } from '../../types'; export const AdvancedSelector = ({ services, onSelect, onCancel, + selectedDataset, + setSelectedDataset, + setIndexPattern, + direct = false, }: { services: IDataPluginServices; onSelect: (dataset: Dataset) => void; onCancel: () => void; + selectedDataset?: Dataset; + setSelectedDataset: (data: Dataset | undefined) => void; + setIndexPattern: (id: string | undefined) => void; + direct?: boolean; }) => { - const queryString = getQueryService().queryString; + const queryService = services.data.query; + const queryString = queryService.queryString; const [path, setPath] = useState([ { @@ -48,14 +56,21 @@ export const AdvancedSelector = ({ }), }, ]); - const [selectedDataset, setSelectedDataset] = useState(); - return selectedDataset ? ( + const [currentSelectedDataset, setCurrentSelectedDataset] = useState( + selectedDataset + ); + + return currentSelectedDataset ? ( setSelectedDataset(undefined)} + onPrevious={() => { + setSelectedDataset(undefined); + setCurrentSelectedDataset(undefined); + }} + queryService={queryService} /> ) : ( setSelectedDataset(dataset)} + onNext={(dataset) => { + setSelectedDataset(dataset); + setIndexPattern(dataset.id); + setCurrentSelectedDataset(dataset); + if (direct) { + const query = queryString.getInitialQueryByDataset(dataset); + queryString.setQuery(query); + queryString.getDatasetService().addRecentDataset(dataset); + } + }} onCancel={onCancel} /> ); diff --git a/src/plugins/data/public/ui/dataset_selector/configurator.tsx b/src/plugins/data/public/ui/dataset_selector/configurator.tsx index db1cb80dd6e3..b8a74a9353e0 100644 --- a/src/plugins/data/public/ui/dataset_selector/configurator.tsx +++ b/src/plugins/data/public/ui/dataset_selector/configurator.tsx @@ -20,20 +20,21 @@ import { i18n } from '@osd/i18n'; import { FormattedMessage } from '@osd/i18n/react'; import React, { useEffect, useMemo, useState } from 'react'; import { BaseDataset, DEFAULT_DATA, Dataset, DatasetField } from '../../../common'; -import { getIndexPatterns, getQueryService } from '../../services'; +import { getIndexPatterns } from '../../services'; export const Configurator = ({ baseDataset, onConfirm, onCancel, onPrevious, + queryService, }: { baseDataset: BaseDataset; onConfirm: (dataset: Dataset) => void; onCancel: () => void; onPrevious: () => void; + queryService: any; }) => { - const queryService = getQueryService(); const queryString = queryService.queryString; const languageService = queryService.queryString.getLanguageService(); const indexPatternsService = getIndexPatterns(); 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 691f477a5818..6755645020d1 100644 --- a/src/plugins/data/public/ui/dataset_selector/dataset_selector.tsx +++ b/src/plugins/data/public/ui/dataset_selector/dataset_selector.tsx @@ -33,7 +33,9 @@ type EuiSmallButtonEmptyProps = React.ComponentProps interface DatasetSelectorProps { selectedDataset?: Dataset; - setSelectedDataset: (dataset: Dataset) => void; + setSelectedDataset: (data: Dataset | undefined) => void; + setIndexPattern: (id: string | undefined) => void; + handleDatasetChange: (dataset: Dataset) => void; services: IDataPluginServices; } @@ -71,6 +73,8 @@ const RootComponent: React.FC< export const DatasetSelector = ({ selectedDataset, setSelectedDataset, + setIndexPattern, + handleDatasetChange, services, appearance, buttonProps, @@ -102,7 +106,7 @@ export const DatasetSelector = ({ // If no dataset is selected, select the first one if (!selectedDataset && fetchedDatasets.length > 0) { - setSelectedDataset(fetchedDatasets[0]); + handleDatasetChange(fetchedDatasets[0]); } }; @@ -179,11 +183,11 @@ export const DatasetSelector = ({ indexPatterns.find((dataset) => dataset.id === selectedOption.key); if (foundDataset) { closePopover(); - setSelectedDataset(foundDataset); + handleDatasetChange(foundDataset); } } }, - [recentDatasets, indexPatterns, setSelectedDataset, closePopover] + [recentDatasets, indexPatterns, handleDatasetChange, closePopover] ); const datasetTitle = useMemo(() => { @@ -266,10 +270,14 @@ export const DatasetSelector = ({ onSelect={(dataset?: Dataset) => { overlay?.close(); if (dataset) { - setSelectedDataset(dataset); + handleDatasetChange(dataset); } }} onCancel={() => overlay?.close()} + selectedDataset={undefined} + setSelectedDataset={setSelectedDataset} + setIndexPattern={setIndexPattern} + direct={true} /> ), { diff --git a/src/plugins/data/public/ui/dataset_selector/index.test.tsx b/src/plugins/data/public/ui/dataset_selector/index.test.tsx index db78461b96c1..9e486beb5310 100644 --- a/src/plugins/data/public/ui/dataset_selector/index.test.tsx +++ b/src/plugins/data/public/ui/dataset_selector/index.test.tsx @@ -49,40 +49,77 @@ describe('ConnectedDatasetSelector', () => { }); it('should render DatasetSelector with correct props', () => { - const wrapper = mount(); + const wrapper = mount( + + ); expect(wrapper.find(DatasetSelector).props()).toEqual({ selectedDataset: undefined, setSelectedDataset: expect.any(Function), + setIndexPattern: expect.any(Function), + handleDatasetChange: expect.any(Function), services: mockServices, }); }); it('should initialize selectedDataset correctly', () => { const mockDataset: Dataset = { id: 'initial', title: 'Initial Dataset', type: 'test' }; - mockQueryString.getQuery.mockReturnValueOnce({ dataset: mockDataset }); - const wrapper = mount(); + const wrapper = mount( + + ); expect(wrapper.find(DatasetSelector).prop('selectedDataset')).toEqual(mockDataset); }); it('should call handleDatasetChange only once when dataset changes', () => { - const wrapper = mount(); - const setSelectedDataset = wrapper.find(DatasetSelector).prop('setSelectedDataset') as ( + const setSelectedDataset = jest.fn(); + const setIndexPattern = jest.fn(); + const wrapper = mount( + + ); + const handleDatasetChange = wrapper.find(DatasetSelector).prop('handleDatasetChange') as ( dataset?: Dataset ) => void; const newDataset: Dataset = { id: 'test', title: 'Test Dataset', type: 'test' }; act(() => { - setSelectedDataset(newDataset); + handleDatasetChange(newDataset); }); expect(mockQueryString.getInitialQueryByDataset).toHaveBeenCalledTimes(1); expect(mockQueryString.setQuery).toHaveBeenCalledTimes(1); expect(mockOnSubmit).toHaveBeenCalledTimes(1); + expect(setSelectedDataset).toHaveBeenCalledWith(newDataset); + expect(setIndexPattern).toHaveBeenCalledWith(newDataset.id); }); it('should subscribe to queryString.getUpdates$ and unsubscribe on unmount', () => { - const wrapper = mount(); + const wrapper = mount( + + ); expect(mockQueryString.getUpdates$).toHaveBeenCalledTimes(1); expect(mockSubscribe).toHaveBeenCalledTimes(1); diff --git a/src/plugins/data/public/ui/dataset_selector/index.tsx b/src/plugins/data/public/ui/dataset_selector/index.tsx index 405e4a672a4d..48cd2926de22 100644 --- a/src/plugins/data/public/ui/dataset_selector/index.tsx +++ b/src/plugins/data/public/ui/dataset_selector/index.tsx @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { useCallback, useState, useEffect } from 'react'; +import { useCallback, useEffect } from 'react'; import React from 'react'; import { Dataset, Query, TimeRange } from '../../../common'; import { @@ -12,37 +12,42 @@ import { DatasetSelectorUsingButtonProps, DatasetSelectorAppearance, } from './dataset_selector'; -import { useOpenSearchDashboards } from '../../../../opensearch_dashboards_react/public'; -import { IDataPluginServices } from '../../types'; +import { AdvancedSelector } from './advanced_selector'; interface ConnectedDatasetSelectorProps { onSubmit: ((query: Query, dateRange?: TimeRange | undefined) => void) | undefined; + selectedDataset?: Dataset; + setSelectedDataset: (data: Dataset | undefined) => void; + setIndexPattern: (id: string | undefined) => void; + services?: any; } const ConnectedDatasetSelector = ({ onSubmit, + selectedDataset, + setSelectedDataset, + setIndexPattern, + services, ...datasetSelectorProps }: ConnectedDatasetSelectorProps & (DatasetSelectorUsingButtonProps | DatasetSelectorUsingButtonEmptyProps)) => { - const { services } = useOpenSearchDashboards(); const queryString = services.data.query.queryString; - const [selectedDataset, setSelectedDataset] = useState( - () => queryString.getQuery().dataset || queryString.getDefaultQuery().dataset - ); useEffect(() => { const subscription = queryString.getUpdates$().subscribe((query) => { setSelectedDataset(query.dataset); + setIndexPattern(query.dataset?.id); }); return () => { subscription.unsubscribe(); }; - }, [queryString]); + }, [queryString, setSelectedDataset, setIndexPattern]); const handleDatasetChange = useCallback( (dataset?: Dataset) => { setSelectedDataset(dataset); + setIndexPattern(dataset?.id); if (dataset) { const query = queryString.getInitialQueryByDataset(dataset); queryString.setQuery(query); @@ -50,17 +55,19 @@ const ConnectedDatasetSelector = ({ queryString.getDatasetService().addRecentDataset(dataset); } }, - [onSubmit, queryString] + [onSubmit, queryString, setSelectedDataset, setIndexPattern] ); return ( ); }; -export { ConnectedDatasetSelector as DatasetSelector, DatasetSelectorAppearance }; +export { ConnectedDatasetSelector as DatasetSelector, AdvancedSelector, DatasetSelectorAppearance }; diff --git a/src/plugins/data/public/ui/index.ts b/src/plugins/data/public/ui/index.ts index 89bd87ae39f8..00ac361bb26e 100644 --- a/src/plugins/data/public/ui/index.ts +++ b/src/plugins/data/public/ui/index.ts @@ -51,4 +51,5 @@ export { useQueryStringManager, } from './search_bar'; export { SuggestionsComponent } from './typeahead'; -export { DatasetSelector, DatasetSelectorAppearance } from './dataset_selector'; +export { DatasetSelector, AdvancedSelector, DatasetSelectorAppearance } from './dataset_selector'; +export { NoIndexPatternsPanel } from './no_index_patterns'; diff --git a/src/plugins/data/public/ui/no_index_patterns/index.ts b/src/plugins/data/public/ui/no_index_patterns/index.ts new file mode 100644 index 000000000000..4f7a76b5baa2 --- /dev/null +++ b/src/plugins/data/public/ui/no_index_patterns/index.ts @@ -0,0 +1,6 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +export * from './no_index_patterns_panel'; diff --git a/src/plugins/data/public/ui/no_index_patterns/no_index_patterns_panel.tsx b/src/plugins/data/public/ui/no_index_patterns/no_index_patterns_panel.tsx new file mode 100644 index 000000000000..6dd7d2a8614c --- /dev/null +++ b/src/plugins/data/public/ui/no_index_patterns/no_index_patterns_panel.tsx @@ -0,0 +1,145 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import React from 'react'; +import { i18n } from '@osd/i18n'; +import { + EuiPanel, + EuiFlexGroup, + EuiFlexItem, + EuiIcon, + EuiText, + EuiSmallButton, + EuiSpacer, + EuiTitle, + EuiButtonEmpty, +} from '@elastic/eui'; + +interface NoIndexPatternsPanelProps { + onOpenDataSelector: () => void; +} + +export const NoIndexPatternsPanel: React.FC = ({ + onOpenDataSelector, +}) => ( + + + + + + + + + +

+ {i18n.translate('data.noIndexPatterns.selectDataTitle', { + defaultMessage: 'Select data', + })} +

+
+
+ + + {i18n.translate('data.noIndexPatterns.selectDataDescription', { + defaultMessage: + 'Select an available data source and choose a query language to use for running queries. You can use the data dropdown or use the enhanced data selector to select data.', + })} + + + + + {i18n.translate('data.noIndexPatterns.openDataSelectorButton', { + defaultMessage: 'Open data selector', + })} + + + + + +

+ {i18n.translate('data.noIndexPatterns.learnMoreAboutQueryLanguages', { + defaultMessage: 'Learn more about query languages', + })} +

+
+
+ + + + + + {i18n.translate('data.noIndexPatterns.pplDocumentation', { + defaultMessage: 'PPL documentation', + })} + + + + + + + {i18n.translate('data.noIndexPatterns.sqlDocumentation', { + defaultMessage: 'SQL documentation', + })} + + + + + + + {i18n.translate('data.noIndexPatterns.luceneDocumentation', { + defaultMessage: 'Lucene documentation', + })} + + + + + + + {i18n.translate('data.noIndexPatterns.dqlDocumentation', { + defaultMessage: 'DQL documentation', + })} + + + + + +
+
+
+
+); diff --git a/src/plugins/data_explorer/public/components/sidebar/index.tsx b/src/plugins/data_explorer/public/components/sidebar/index.tsx index 56250228e559..3c5975d9452e 100644 --- a/src/plugins/data_explorer/public/components/sidebar/index.tsx +++ b/src/plugins/data_explorer/public/components/sidebar/index.tsx @@ -17,26 +17,35 @@ import { DatasetSelector, DatasetSelectorAppearance, } from '../../../../data/public/'; +import { Dataset } from '../../../../data/common'; import { useOpenSearchDashboards } from '../../../../opensearch_dashboards_react/public'; import { DataExplorerServices } from '../../types'; -import { setIndexPattern, useTypedDispatch, useTypedSelector } from '../../utils/state_management'; +import { + setIndexPattern, + useTypedDispatch, + useTypedSelector, + setSelectedDataset, +} from '../../utils/state_management'; import './index.scss'; +type HandleSetIndexPattern = (id: string | undefined) => void; +type HandleSelectedDataset = (data: Dataset | undefined) => void; + export const Sidebar: FC = ({ children }) => { - const { indexPattern: indexPatternId } = useTypedSelector((state) => state.metadata); + const { indexPattern: indexPatternId, selectedDataset } = useTypedSelector( + (state) => state.metadata + ); const dispatch = useTypedDispatch(); const [selectedSources, setSelectedSources] = useState([]); const [dataSourceOptionList, setDataSourceOptionList] = useState([]); const [activeDataSources, setActiveDataSources] = useState([]); - + const { services } = useOpenSearchDashboards(); const { - services: { - data: { indexPatterns, dataSources }, - notifications: { toasts }, - application, - uiSettings, - }, - } = useOpenSearchDashboards(); + data: { indexPatterns, dataSources }, + notifications: { toasts }, + application, + uiSettings, + } = services; const handleDatasetSubmit = useCallback( (query: any) => { @@ -128,6 +137,14 @@ export const Sidebar: FC = ({ children }) => { dataSources.dataSourceService.reload(); }, [dataSources.dataSourceService]); + const handleSetIndexPattern: HandleSetIndexPattern = (id: string | undefined) => { + dispatch(setIndexPattern(id)); + }; + + const handleSelectedDataset: HandleSelectedDataset = (data: Dataset | undefined) => { + dispatch(setSelectedDataset(data)); + }; + return ( { {isEnhancementEnabled ? ( ) => { state.view = action.payload; }, + setSelectedDataset: (state, action: PayloadAction) => { + state.selectedDataset = action.payload; + }, setState: (_state, action: PayloadAction) => { return action.payload; }, @@ -58,4 +66,10 @@ export const slice = createSlice({ }); export const { reducer } = slice; -export const { setIndexPattern, setOriginatingApp, setView, setState } = slice.actions; +export const { + setIndexPattern, + setOriginatingApp, + setView, + setState, + setSelectedDataset, +} = slice.actions; diff --git a/src/plugins/data_explorer/public/utils/state_management/redux_persistence.test.tsx b/src/plugins/data_explorer/public/utils/state_management/redux_persistence.test.tsx index 62159558a0c4..9af3bcf3d491 100644 --- a/src/plugins/data_explorer/public/utils/state_management/redux_persistence.test.tsx +++ b/src/plugins/data_explorer/public/utils/state_management/redux_persistence.test.tsx @@ -26,6 +26,7 @@ describe('test redux state persistence', () => { "metadata": Object { "indexPattern": "id", "originatingApp": undefined, + "selectedDataset": undefined, }, } `); diff --git a/src/plugins/data_explorer/public/utils/state_management/store.ts b/src/plugins/data_explorer/public/utils/state_management/store.ts index daf0b3d7e369..1ac3564e34ce 100644 --- a/src/plugins/data_explorer/public/utils/state_management/store.ts +++ b/src/plugins/data_explorer/public/utils/state_management/store.ts @@ -116,4 +116,9 @@ export type RenderState = Omit; // Remaining state after export type Store = ReturnType; export type AppDispatch = Store['dispatch']; -export { MetadataState, setIndexPattern, setOriginatingApp } from './metadata_slice'; +export { + MetadataState, + setIndexPattern, + setOriginatingApp, + setSelectedDataset, +} from './metadata_slice'; diff --git a/src/plugins/discover/public/application/components/top_nav/get_top_nav_links.tsx b/src/plugins/discover/public/application/components/top_nav/get_top_nav_links.tsx index 647b989f42e4..d87e1e47f702 100644 --- a/src/plugins/discover/public/application/components/top_nav/get_top_nav_links.tsx +++ b/src/plugins/discover/public/application/components/top_nav/get_top_nav_links.tsx @@ -277,7 +277,8 @@ export const getTopNavLinks = ( services: DiscoverViewServices, inspectorAdapters: Adapters, savedSearch: SavedSearch, - isEnhancementEnabled: boolean = false + isEnhancementEnabled: boolean = false, + useNoIndexPatternsTopNav: boolean = false ) => { const { history, @@ -503,8 +504,18 @@ export const getTopNavLinks = ( // Order their appearance return ['save', 'open', 'new', 'inspect', 'share'].reduce((acc, item) => { const itemDef = topNavLinksMap.get(item); - if (itemDef) acc.push(itemDef); - + if (itemDef) { + if (useNoIndexPatternsTopNav && item !== 'open') { + // Disable all buttons except 'open' when in no index patterns mode + acc.push({ + ...itemDef, + disabled: true, + run: () => {}, // Empty function for disabled buttons + }); + } else { + acc.push(itemDef); + } + } return acc; }, [] as TopNavMenuData[]); }; diff --git a/src/plugins/discover/public/application/view_components/canvas/index.tsx b/src/plugins/discover/public/application/view_components/canvas/index.tsx index fcad13342e07..4cf6a15dc7d5 100644 --- a/src/plugins/discover/public/application/view_components/canvas/index.tsx +++ b/src/plugins/discover/public/application/view_components/canvas/index.tsx @@ -27,18 +27,27 @@ import { OpenSearchSearchHit } from '../../../application/doc_views/doc_views_ty import { buildColumns } from '../../utils/columns'; import './discover_canvas.scss'; import { HeaderVariant } from '../../../../../../core/public'; +import { setIndexPattern, setSelectedDataset } from '../../../../../data_explorer/public'; +import { NoIndexPatternsPanel, AdvancedSelector } from '../../../../../data/public'; +import { Dataset } from '../../../../../data/common'; +import { toMountPoint } from '../../../../../opensearch_dashboards_react/public'; // eslint-disable-next-line import/no-default-export export default function DiscoverCanvas({ setHeaderActionMenu, history, optionalRef }: ViewProps) { + const { indexPattern: currentIndexPattern, selectedDataset } = useSelector( + (state) => state.metadata + ); + const [loadedIndexPattern, setLoadedIndexPattern] = useState(selectedDataset?.id); const panelRef = useRef(null); const { data$, refetch$, indexPattern } = useDiscoverContext(); + const { services } = useOpenSearchDashboards(); const { - services: { - uiSettings, - capabilities, - chrome: { setHeaderVariant }, - }, - } = useOpenSearchDashboards(); + uiSettings, + capabilities, + chrome: { setHeaderVariant }, + data, + overlays, + } = services; const { columns } = useSelector((state) => { const stateColumns = state.discover.columns; @@ -122,10 +131,48 @@ export default function DiscoverCanvas({ setHeaderActionMenu, history, optionalR }; const showSaveQuery = !!capabilities.discover?.saveQuery; + const handleDatasetChange = (dataset: Dataset) => { + dispatch(setSelectedDataset(dataset)); + + // Update query and other necessary state + const queryString = data.query.queryString; + const query = queryString.getInitialQueryByDataset(dataset); + queryString.setQuery(query); + queryString.getDatasetService().addRecentDataset(dataset); + }; + + const handleOpenDataSelector = () => { + const overlay = overlays?.openModal( + toMountPoint( + { + overlay?.close(); + if (dataset) { + handleDatasetChange(dataset); + } + }} + onCancel={() => overlay?.close()} + selectedDataset={undefined} + setSelectedDataset={setSelectedDataset} + setIndexPattern={setIndexPattern} + dispatch={dispatch} + /> + ), + { + maxWidth: false, + className: 'datasetSelector__advancedModal', + } + ); + }; + + const hasNoDataset = !currentIndexPattern && !loadedIndexPattern && isEnhancementsEnabled; + return ( - - {fetchState.status === ResultStatus.NO_RESULTS && ( - - )} - {fetchState.status === ResultStatus.ERROR && ( - - )} - {fetchState.status === ResultStatus.UNINITIALIZED && ( - refetch$.next()} /> - )} - {fetchState.status === ResultStatus.LOADING && } - {fetchState.status === ResultStatus.READY && isEnhancementsEnabled && ( + {hasNoDataset ? ( + + ) : ( <> - - + {fetchState.status === ResultStatus.NO_RESULTS && ( + + )} + {fetchState.status === ResultStatus.ERROR && ( + + )} + {fetchState.status === ResultStatus.UNINITIALIZED && ( + refetch$.next()} /> + )} + {fetchState.status === ResultStatus.LOADING && } + {fetchState.status === ResultStatus.READY && isEnhancementsEnabled && ( + <> + + + + )} + {fetchState.status === ResultStatus.READY && !isEnhancementsEnabled && ( + + + + + )} )} - {fetchState.status === ResultStatus.READY && !isEnhancementsEnabled && ( - - - - - )} ); } diff --git a/src/plugins/discover/public/application/view_components/canvas/top_nav.tsx b/src/plugins/discover/public/application/view_components/canvas/top_nav.tsx index 2aa288b9bdf1..0b3f1275d7ff 100644 --- a/src/plugins/discover/public/application/view_components/canvas/top_nav.tsx +++ b/src/plugins/discover/public/application/view_components/canvas/top_nav.tsx @@ -35,9 +35,15 @@ export interface TopNavProps { }; showSaveQuery: boolean; isEnhancementsEnabled?: boolean; + useNoIndexPatternsTopNav?: boolean; } -export const TopNav = ({ opts, showSaveQuery, isEnhancementsEnabled }: TopNavProps) => { +export const TopNav = ({ + opts, + showSaveQuery, + isEnhancementsEnabled, + useNoIndexPatternsTopNav = false, +}: TopNavProps) => { const { services } = useOpenSearchDashboards(); const { data$, inspectorAdapters, savedSearch, indexPattern } = useDiscoverContext(); const [indexPatterns, setIndexPatterns] = useState(undefined); @@ -62,7 +68,13 @@ export const TopNav = ({ opts, showSaveQuery, isEnhancementsEnabled }: TopNavPro const showActionsInGroup = uiSettings.get('home:useNewHomePage'); const topNavLinks = savedSearch - ? getTopNavLinks(services, inspectorAdapters, savedSearch, isEnhancementsEnabled) + ? getTopNavLinks( + services, + inspectorAdapters, + savedSearch, + isEnhancementsEnabled, + useNoIndexPatternsTopNav + ) : []; connectStorageToQueryState( @@ -88,7 +100,7 @@ export const TopNav = ({ opts, showSaveQuery, isEnhancementsEnabled }: TopNavPro useEffect(() => { let isMounted = true; const initializeDataset = async () => { - await data.indexPatterns.ensureDefaultIndexPattern(); + await data.indexPatterns.ensureDefaultIndexPattern(isEnhancementsEnabled ? false : true); const defaultIndexPattern = await data.indexPatterns.getDefault(); // TODO: ROCKY do we need this? // const queryString = data.query.queryString; @@ -107,7 +119,7 @@ export const TopNav = ({ opts, showSaveQuery, isEnhancementsEnabled }: TopNavPro return () => { isMounted = false; }; - }, [data.indexPatterns, data.query]); + }, [data.indexPatterns, data.query, isEnhancementsEnabled]); useEffect(() => { const pageTitleSuffix = savedSearch?.id && savedSearch.title ? `: ${savedSearch.title}` : ''; @@ -164,18 +176,30 @@ export const TopNav = ({ opts, showSaveQuery, isEnhancementsEnabled }: TopNavPro {} : opts.onQuerySubmit} + savedQueryId={useNoIndexPatternsTopNav ? undefined : state.savedQuery} + onSavedQueryIdChange={useNoIndexPatternsTopNav ? () => {} : updateSavedQueryId} + datePickerRef={useNoIndexPatternsTopNav ? undefined : opts?.optionalRef?.datePickerRef} groupActions={showActionsInGroup} - screenTitle={screenTitle} + screenTitle={ + useNoIndexPatternsTopNav + ? i18n.translate('discover.noIndexPatterns.screenTitle', { + defaultMessage: 'Select data', + }) + : screenTitle + } queryStatus={queryStatus} /> diff --git a/src/plugins/index_pattern_management/public/components/edit_index_pattern/edit_index_pattern.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/edit_index_pattern.tsx index e5f87af2e974..4beafd982013 100644 --- a/src/plugins/index_pattern_management/public/components/edit_index_pattern/edit_index_pattern.tsx +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/edit_index_pattern.tsx @@ -162,6 +162,8 @@ export const EditIndexPattern = withRouter( } if (indexPattern.id) { Promise.resolve(data.indexPatterns.delete(indexPattern.id)).then(function () { + const datasetService = data.query.queryString.getDatasetService(); + datasetService.removeFromRecentDatasets(indexPattern.id); history.push(''); }); }