diff --git a/changelogs/fragments/8650.yml b/changelogs/fragments/8650.yml new file mode 100644 index 000000000000..3f53ba7a41fa --- /dev/null +++ b/changelogs/fragments/8650.yml @@ -0,0 +1,2 @@ +fix: +- Fix random big number when loading in query result ([#8650](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/8650)) \ No newline at end of file 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 9fed0e1d0519..94df6995186a 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,9 +32,7 @@ import { includes } from 'lodash'; import { IndexPatternsContract } from './index_patterns'; import { UiSettingsCommon } from '../types'; -export type EnsureDefaultIndexPattern = ( - shouldRedirect?: boolean -) => Promise | undefined; +export type EnsureDefaultIndexPattern = () => Promise | undefined; export const createEnsureDefaultIndexPattern = ( uiSettings: UiSettingsCommon, @@ -44,10 +42,7 @@ export const createEnsureDefaultIndexPattern = ( * Checks whether a default index pattern is set and exists and defines * one otherwise. */ - return async function ensureDefaultIndexPattern( - this: IndexPatternsContract, - shouldRedirect: boolean = true - ) { + return async function ensureDefaultIndexPattern(this: IndexPatternsContract) { const patterns = await this.getIds(); let defaultId = await uiSettings.get('defaultIndex'); let defined = !!defaultId; @@ -67,6 +62,8 @@ export const createEnsureDefaultIndexPattern = ( defaultId = patterns[0]; await uiSettings.set('defaultIndex', defaultId); } else { + const isEnhancementsEnabled = await uiSettings.get('query:enhancements:enabled'); + const shouldRedirect = !isEnhancementsEnabled; if (shouldRedirect) return onRedirectNoIndexPattern(); else return; } diff --git a/src/plugins/data/public/query/query_string/language_service/lib/dql_language.ts b/src/plugins/data/public/query/query_string/language_service/lib/dql_language.ts index 6816bf0d7121..402af7482d08 100644 --- a/src/plugins/data/public/query/query_string/language_service/lib/dql_language.ts +++ b/src/plugins/data/public/query/query_string/language_service/lib/dql_language.ts @@ -24,6 +24,12 @@ export const getDQLLanguageConfig = ( visualizable: true, }, showDocLinks: true, + docLink: { + title: i18n.translate('data.dqlLanguage.docLink', { + defaultMessage: 'DQL documentation', + }), + url: 'https://opensearch.org/docs/latest/query-dsl/full-text/query-string/', + }, editorSupportedAppNames: ['discover'], supportedAppNames: ['discover', 'dashboards', 'visualize', 'data-explorer', 'vis-builder', '*'], sampleQueries: [ diff --git a/src/plugins/data/public/query/query_string/language_service/lib/lucene_language.ts b/src/plugins/data/public/query/query_string/language_service/lib/lucene_language.ts index c42b14543633..4da92f868654 100644 --- a/src/plugins/data/public/query/query_string/language_service/lib/lucene_language.ts +++ b/src/plugins/data/public/query/query_string/language_service/lib/lucene_language.ts @@ -24,6 +24,12 @@ export const getLuceneLanguageConfig = ( visualizable: true, }, showDocLinks: true, + docLink: { + title: i18n.translate('data.luceneLanguage.docLink', { + defaultMessage: 'Lucene documentation', + }), + url: 'https://opensearch.org/docs/latest/query-dsl/full-text/query-string/', + }, editorSupportedAppNames: ['discover'], supportedAppNames: ['discover', 'dashboards', 'visualize', 'data-explorer', 'vis-builder', '*'], sampleQueries: [ diff --git a/src/plugins/data/public/query/query_string/language_service/lib/query_result.tsx b/src/plugins/data/public/query/query_string/language_service/lib/query_result.tsx index 042d2e11a664..074ba4b5d0d5 100644 --- a/src/plugins/data/public/query/query_string/language_service/lib/query_result.tsx +++ b/src/plugins/data/public/query/query_string/language_service/lib/query_result.tsx @@ -41,40 +41,42 @@ export function QueryResult(props: { queryStatus: QueryStatus }) { setPopover(!isPopoverOpen); }; - const updateElapsedTime = () => { - const time = Date.now() - (props.queryStatus.startTime || 0); - if (time > BUFFER_TIME) { - setElapsedTime(time); - } else { - setElapsedTime(0); - } - }; - useEffect(() => { + const updateElapsedTime = () => { + const currentTime = Date.now(); + if (!props.queryStatus.startTime) { + return; + } + const elapsed = currentTime - props.queryStatus.startTime; + setElapsedTime(elapsed); + }; + const interval = setInterval(updateElapsedTime, 1000); - return () => clearInterval(interval); - }); + return () => { + clearInterval(interval); + setElapsedTime(0); + }; + }, [props.queryStatus.startTime]); - if (props.queryStatus.status === ResultStatus.LOADING) { - if (elapsedTime < BUFFER_TIME) { - return null; + if (elapsedTime > BUFFER_TIME) { + if (props.queryStatus.status === ResultStatus.LOADING) { + const time = Math.floor(elapsedTime / 1000); + return ( + {}} + isLoading + data-test-subj="queryResultLoading" + > + {i18n.translate('data.query.languageService.queryResults.loadTime', { + defaultMessage: 'Loading {time} s', + values: { time }, + })} + + ); } - const time = Math.floor(elapsedTime / 1000); - return ( - {}} - isLoading - data-test-subj="queryResultLoading" - > - {i18n.translate('data.query.languageService.queryResults.loadTime', { - defaultMessage: 'Loading {time} s', - values: { time }, - })} - - ); } if (props.queryStatus.status === ResultStatus.READY) { @@ -85,7 +87,7 @@ export function QueryResult(props: { queryStatus: QueryStatus }) { }); } else if (props.queryStatus.elapsedMs < 1000) { message = i18n.translate( - 'data.query.languageService.queryResults.completeTimeInMiliseconds', + 'data.query.languageService.queryResults.completeTimeInMilliseconds', { defaultMessage: 'Completed in {timeMS} ms', values: { timeMS: props.queryStatus.elapsedMs }, diff --git a/src/plugins/data/public/query/query_string/language_service/types.ts b/src/plugins/data/public/query/query_string/language_service/types.ts index 0889f7e63950..c80858d67102 100644 --- a/src/plugins/data/public/query/query_string/language_service/types.ts +++ b/src/plugins/data/public/query/query_string/language_service/types.ts @@ -55,6 +55,10 @@ export interface LanguageConfig { visualizable?: boolean; }; showDocLinks?: boolean; + docLink?: { + title: string; + url: string; + }; editorSupportedAppNames?: string[]; supportedAppNames?: string[]; hideDatePicker?: boolean; diff --git a/src/plugins/data/public/ui/dataset_selector/index.tsx b/src/plugins/data/public/ui/dataset_selector/index.tsx index 48cd2926de22..53966ed6375f 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, useEffect } from 'react'; +import { useCallback, useState, useEffect } from 'react'; import React from 'react'; import { Dataset, Query, TimeRange } from '../../../common'; import { @@ -12,42 +12,37 @@ import { DatasetSelectorUsingButtonProps, DatasetSelectorAppearance, } from './dataset_selector'; -import { AdvancedSelector } from './advanced_selector'; +import { useOpenSearchDashboards } from '../../../../opensearch_dashboards_react/public'; +import { IDataPluginServices } from '../../types'; 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, setSelectedDataset, setIndexPattern]); + }, [queryString]); const handleDatasetChange = useCallback( (dataset?: Dataset) => { setSelectedDataset(dataset); - setIndexPattern(dataset?.id); if (dataset) { const query = queryString.getInitialQueryByDataset(dataset); queryString.setQuery(query); @@ -55,19 +50,21 @@ const ConnectedDatasetSelector = ({ queryString.getDatasetService().addRecentDataset(dataset); } }, - [onSubmit, queryString, setSelectedDataset, setIndexPattern] + [onSubmit, queryString] ); return ( ); }; -export { ConnectedDatasetSelector as DatasetSelector, AdvancedSelector, DatasetSelectorAppearance }; +export { + ConnectedDatasetSelector as DatasetSelector, + ConnectedDatasetSelectorProps as DatasetSelectorProps, + DatasetSelectorAppearance, +}; diff --git a/src/plugins/data/public/ui/filter_bar/filter_options.tsx b/src/plugins/data/public/ui/filter_bar/filter_options.tsx index 26fcc9714212..6de37d562ce1 100644 --- a/src/plugins/data/public/ui/filter_bar/filter_options.tsx +++ b/src/plugins/data/public/ui/filter_bar/filter_options.tsx @@ -88,8 +88,7 @@ const FilterOptionsUI = (props: Props) => { const uiSettings = opensearchDashboards.services.uiSettings; const isPinned = uiSettings!.get(UI_SETTINGS.FILTERS_PINNED_BY_DEFAULT); const useNewHeader = Boolean(uiSettings!.get(UI_SETTINGS.NEW_HOME_PAGE)); - const [indexPattern] = props.indexPatterns; - const index = indexPattern && indexPattern.id; + const index = Array.isArray(props.indexPatterns) ? props.indexPatterns[0]?.id : undefined; const newFilter = buildEmptyFilter(isPinned, index); const togglePopover = () => { diff --git a/src/plugins/data/public/ui/index.ts b/src/plugins/data/public/ui/index.ts index 00ac361bb26e..bdde4cc42a39 100644 --- a/src/plugins/data/public/ui/index.ts +++ b/src/plugins/data/public/ui/index.ts @@ -28,7 +28,7 @@ * under the License. */ -export { UiEnhancements, IUiStart, IUiSetup } from './types'; +export { IUiStart, IUiSetup } from './types'; export { IndexPatternSelectProps } from './index_pattern_select'; export { FilterLabel } from './filter_bar'; export { QueryStringInput, QueryStringInputProps } from './query_string_input'; @@ -51,5 +51,4 @@ export { useQueryStringManager, } from './search_bar'; export { SuggestionsComponent } from './typeahead'; -export { DatasetSelector, AdvancedSelector, DatasetSelectorAppearance } from './dataset_selector'; -export { NoIndexPatternsPanel } from './no_index_patterns'; +export { DatasetSelector, DatasetSelectorAppearance } from './dataset_selector'; diff --git a/src/plugins/data/public/ui/query_editor/__snapshots__/language_selector.test.tsx.snap b/src/plugins/data/public/ui/query_editor/__snapshots__/language_selector.test.tsx.snap index 740611ae6d36..68e06485f77c 100644 --- a/src/plugins/data/public/ui/query_editor/__snapshots__/language_selector.test.tsx.snap +++ b/src/plugins/data/public/ui/query_editor/__snapshots__/language_selector.test.tsx.snap @@ -508,7 +508,6 @@ exports[`LanguageSelector should select DQL if language is kuery 1`] = ` @@ -532,14 +531,12 @@ exports[`LanguageSelector should select DQL if language is kuery 1`] = ` @@ -1104,7 +1100,6 @@ exports[`LanguageSelector should select lucene if language is lucene 1`] = ` @@ -1128,14 +1123,12 @@ exports[`LanguageSelector should select lucene if language is lucene 1`] = ` diff --git a/src/plugins/data/public/ui/query_editor/_query_editor.scss b/src/plugins/data/public/ui/query_editor/_query_editor.scss index 719cc65785c2..cf2321cf3d4e 100644 --- a/src/plugins/data/public/ui/query_editor/_query_editor.scss +++ b/src/plugins/data/public/ui/query_editor/_query_editor.scss @@ -150,9 +150,6 @@ } .osdQueryEditor__querycontrols { - float: right; - margin: $euiSizeS $euiSizeS; - .osdQueryEditor__extensionQueryControls { display: flex; padding: 0 $euiSizeS 0 $euiSizeXS; diff --git a/src/plugins/data/public/ui/query_editor/editors/default_editor/index.tsx b/src/plugins/data/public/ui/query_editor/editors/default_editor/index.tsx index 1134d104befd..0d76ff0e78f3 100644 --- a/src/plugins/data/public/ui/query_editor/editors/default_editor/index.tsx +++ b/src/plugins/data/public/ui/query_editor/editors/default_editor/index.tsx @@ -77,14 +77,22 @@ export const DefaultInput: React.FC = ({ gutterSize="none" className="defaultEditor__footerRow" > - {footerItems.start?.map((item) => ( - + {footerItems.start?.map((item, idx) => ( + {item} ))} - {footerItems.end?.map((item) => ( - + {footerItems.end?.map((item, idx) => ( + {item} ))} diff --git a/src/plugins/data/public/ui/query_editor/language_selector.tsx b/src/plugins/data/public/ui/query_editor/language_selector.tsx index ed7598fea563..6fc0606c1997 100644 --- a/src/plugins/data/public/ui/query_editor/language_selector.tsx +++ b/src/plugins/data/public/ui/query_editor/language_selector.tsx @@ -111,7 +111,6 @@ export const QueryLanguageSelector = (props: QueryLanguageSelectorProps) => { button={ { className={classNames('osdQueryEditor__banner', this.props.bannerClassName)} />
-
{this.state.isCollapsed ? languageEditor.TopBar.Collapsed() diff --git a/src/plugins/data/public/ui/query_editor/query_editor_top_row.tsx b/src/plugins/data/public/ui/query_editor/query_editor_top_row.tsx index 62ba24527cd5..ab9b8c50e038 100644 --- a/src/plugins/data/public/ui/query_editor/query_editor_top_row.tsx +++ b/src/plugins/data/public/ui/query_editor/query_editor_top_row.tsx @@ -15,7 +15,15 @@ import { import classNames from 'classnames'; import React, { useState } from 'react'; import { createPortal } from 'react-dom'; -import { IDataPluginServices, IIndexPattern, Query, TimeHistoryContract, TimeRange } from '../..'; +import { + DatasetSelector, + DatasetSelectorAppearance, + IDataPluginServices, + IIndexPattern, + Query, + TimeHistoryContract, + TimeRange, +} from '../..'; import { useOpenSearchDashboards, withOpenSearchDashboards, @@ -52,6 +60,7 @@ export interface QueryEditorTopRowProps { isDirty: boolean; timeHistory?: TimeHistoryContract; indicateNoData?: boolean; + datasetSelectorRef?: React.RefObject; datePickerRef?: React.RefObject; savedQueryManagement?: any; queryStatus?: QueryStatus; @@ -63,14 +72,7 @@ export default function QueryEditorTopRow(props: QueryEditorTopRowProps) { const [isDateRangeInvalid, setIsDateRangeInvalid] = useState(false); const [isQueryEditorFocused, setIsQueryEditorFocused] = useState(false); const opensearchDashboards = useOpenSearchDashboards(); - const { - uiSettings, - storage, - appName, - data: { - query: { queryString }, - }, - } = opensearchDashboards.services; + const { uiSettings, storage, appName } = opensearchDashboards.services; const queryLanguage = props.query && props.query.language; const persistedLog: PersistedLog | undefined = React.useMemo( @@ -170,6 +172,19 @@ export default function QueryEditorTopRow(props: QueryEditorTopRowProps) { return valueAsMoment.toISOString(); } + function renderDatasetSelector() { + return ( + + ); + } + function renderQueryEditor() { if (!shouldRenderQueryEditor()) return; return ( @@ -315,6 +330,8 @@ export default function QueryEditorTopRow(props: QueryEditorTopRowProps) { ); + const datasetSelector = <>{renderDatasetSelector()}; + return ( + {props?.datasetSelectorRef?.current && + createPortal(datasetSelector, props.datasetSelectorRef.current)} {props?.datePickerRef?.current && uiSettings.get(UI_SETTINGS.QUERY_ENHANCEMENTS_ENABLED) ? createPortal(datePicker, props.datePickerRef.current) : datePicker} diff --git a/src/plugins/data/public/ui/search_bar/create_search_bar.tsx b/src/plugins/data/public/ui/search_bar/create_search_bar.tsx index 03bb2abfa508..f8b9694caabc 100644 --- a/src/plugins/data/public/ui/search_bar/create_search_bar.tsx +++ b/src/plugins/data/public/ui/search_bar/create_search_bar.tsx @@ -209,6 +209,7 @@ export function createSearchBar({ core, storage, data }: StatefulSearchBarDeps) onClearSavedQuery={defaultOnClearSavedQuery(props, clearSavedQuery)} onSavedQueryUpdated={defaultOnSavedQueryUpdated(props, setSavedQuery)} onSaved={defaultOnSavedQueryUpdated(props, setSavedQuery)} + datasetSelectorRef={props.datasetSelectorRef} datePickerRef={props.datePickerRef} isFilterBarPortable={props.isFilterBarPortable} {...overrideDefaultBehaviors(props)} diff --git a/src/plugins/data/public/ui/search_bar/search_bar.tsx b/src/plugins/data/public/ui/search_bar/search_bar.tsx index 975b0535c9d8..35c2065b14c8 100644 --- a/src/plugins/data/public/ui/search_bar/search_bar.tsx +++ b/src/plugins/data/public/ui/search_bar/search_bar.tsx @@ -75,6 +75,7 @@ export interface SearchBarOwnProps { refreshInterval?: number; dateRangeFrom?: string; dateRangeTo?: string; + datasetSelectorRef?: React.RefObject; datePickerRef?: React.RefObject; // Query bar - should be in SearchBarInjectedDeps query?: Query; @@ -223,7 +224,8 @@ class SearchBarUI extends Component { const showDatePicker = this.props.showDatePicker || this.props.showAutoRefreshOnly; // TODO: MQL showQueryEditor should be a prop of it's own but using showQueryInput for now const showQueryEditor = - this.props.showQueryInput && this.props.indexPatterns && this.state.query; + (this.props.showQueryInput && this.props.indexPatterns && this.state.query) || + this.props.datasetSelectorRef?.current; return this.props.showQueryBar && (showDatePicker || showQueryEditor); } @@ -549,6 +551,7 @@ class SearchBarUI extends Component { filterBar={filterBar} dataTestSubj={this.props.dataTestSubj} indicateNoData={this.props.indicateNoData} + datasetSelectorRef={this.props.datasetSelectorRef} datePickerRef={this.props.datePickerRef} savedQueryManagement={searchBarMenu(false, true)} queryStatus={this.props.queryStatus} diff --git a/src/plugins/data/public/ui/ui_service.ts b/src/plugins/data/public/ui/ui_service.ts index 4eb45b1a67f2..87cfcf630965 100644 --- a/src/plugins/data/public/ui/ui_service.ts +++ b/src/plugins/data/public/ui/ui_service.ts @@ -4,7 +4,6 @@ */ import { CoreSetup, CoreStart, Plugin, PluginInitializerContext } from 'src/core/public'; -import { BehaviorSubject } from 'rxjs'; import { ConfigSchema } from '../../config'; import { DataPublicPluginStart } from '../types'; import { createIndexPatternSelect } from './index_pattern_select'; @@ -12,8 +11,6 @@ import { createSearchBar } from './search_bar/create_search_bar'; import { SuggestionsComponent } from './typeahead'; import { IUiSetup, IUiStart } from './types'; import { DataStorage } from '../../common'; -import { QueryStatus } from '../query'; -import { ResultStatus } from '../query/query_string/language_service/lib'; /** @internal */ // eslint-disable-next-line @typescript-eslint/no-empty-interface diff --git a/src/plugins/data_explorer/public/components/app_container.tsx b/src/plugins/data_explorer/public/components/app_container.tsx index abd1328bafeb..63f759f65408 100644 --- a/src/plugins/data_explorer/public/components/app_container.tsx +++ b/src/plugins/data_explorer/public/components/app_container.tsx @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import React, { memo, useEffect, useRef } from 'react'; +import React, { memo, useRef } from 'react'; import { EuiFlexGroup, EuiFlexItem, @@ -23,13 +23,7 @@ import './app_container.scss'; import { useOpenSearchDashboards } from '../../../opensearch_dashboards_react/public'; import { IDataPluginServices } from '../../../data/public'; import { QUERY_ENHANCEMENT_ENABLED_SETTING } from './constants'; -import { - DISCOVER_LOAD_EVENT, - NEW_DISCOVER_LOAD_EVENT, - NEW_DISCOVER_OPT_IN, - NEW_DISCOVER_OPT_OUT, - trackUiMetric, -} from '../ui_metric'; +import { DISCOVER_LOAD_EVENT, NEW_DISCOVER_LOAD_EVENT, trackUiMetric } from '../ui_metric'; export const AppContainer = React.memo( ({ view, params }: { view?: View; params: AppMountParameters }) => { @@ -41,6 +35,7 @@ export const AppContainer = React.memo( const showActionsInGroup = uiSettings?.get('home:useNewHomePage'); const topLinkRef = useRef(null); + const datasetSelectorRef = useRef(null); const datePickerRef = useRef(null); if (!view) { @@ -59,6 +54,7 @@ export const AppContainer = React.memo( params.optionalRef = { topLinkRef, + datasetSelectorRef, datePickerRef, }; // Render the application DOM. @@ -103,7 +99,7 @@ export const AppContainer = React.memo( mode={['collapsible', { position: 'top' }]} paddingSize="none" > - + diff --git a/src/plugins/data_explorer/public/components/sidebar/index.tsx b/src/plugins/data_explorer/public/components/sidebar/index.tsx index 3c5975d9452e..6a4ef0585e33 100644 --- a/src/plugins/data_explorer/public/components/sidebar/index.tsx +++ b/src/plugins/data_explorer/public/components/sidebar/index.tsx @@ -12,50 +12,32 @@ import { DataSourceSelectable, UI_SETTINGS, } from '../../../../data/public'; -import { - DataSourceOption, - DatasetSelector, - DatasetSelectorAppearance, -} from '../../../../data/public/'; -import { Dataset } from '../../../../data/common'; +import { DataSourceOption } from '../../../../data/public/'; import { useOpenSearchDashboards } from '../../../../opensearch_dashboards_react/public'; import { DataExplorerServices } from '../../types'; -import { - setIndexPattern, - useTypedDispatch, - useTypedSelector, - setSelectedDataset, -} from '../../utils/state_management'; +import { setIndexPattern, useTypedDispatch, useTypedSelector } from '../../utils/state_management'; import './index.scss'; -type HandleSetIndexPattern = (id: string | undefined) => void; -type HandleSelectedDataset = (data: Dataset | undefined) => void; +interface SidebarProps { + children: React.ReactNode; + datasetSelectorRef: React.RefObject; +} -export const Sidebar: FC = ({ children }) => { - const { indexPattern: indexPatternId, selectedDataset } = useTypedSelector( - (state) => state.metadata - ); +export const Sidebar: FC = ({ children, datasetSelectorRef }) => { + const { indexPattern: indexPatternId } = useTypedSelector((state) => state.metadata); const dispatch = useTypedDispatch(); const [selectedSources, setSelectedSources] = useState([]); const [dataSourceOptionList, setDataSourceOptionList] = useState([]); const [activeDataSources, setActiveDataSources] = useState([]); - const { services } = useOpenSearchDashboards(); + const { - data: { indexPatterns, dataSources }, - notifications: { toasts }, - application, - uiSettings, - } = services; - - const handleDatasetSubmit = useCallback( - (query: any) => { - // Update the index pattern - if (query.dataset) { - dispatch(setIndexPattern(query.dataset.id)); - } + services: { + data: { indexPatterns, dataSources }, + notifications: { toasts }, + application, + uiSettings, }, - [dispatch] - ); + } = useOpenSearchDashboards(); const [isEnhancementEnabled, setIsEnhancementEnabled] = useState(false); @@ -137,14 +119,6 @@ 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 ( { hasBorder={true} borderRadius="l" > - - {isEnhancementEnabled ? ( - - ) : ( + + {isEnhancementEnabled &&
} + {!isEnhancementEnabled && ( { /> )} + {children} diff --git a/src/plugins/data_explorer/public/index.ts b/src/plugins/data_explorer/public/index.ts index 9d9ae2f46d2b..f8adda434ced 100644 --- a/src/plugins/data_explorer/public/index.ts +++ b/src/plugins/data_explorer/public/index.ts @@ -18,6 +18,4 @@ export { useTypedSelector, useTypedDispatch, setIndexPattern, - setSelectedDataset, - setDataSet, } from './utils/state_management'; diff --git a/src/plugins/discover/public/application/components/no_index_patterns/no_index_patterns.scss b/src/plugins/discover/public/application/components/no_index_patterns/no_index_patterns.scss new file mode 100644 index 000000000000..b435d3b36a6d --- /dev/null +++ b/src/plugins/discover/public/application/components/no_index_patterns/no_index_patterns.scss @@ -0,0 +1,12 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +.discoverNoIndexPatterns-centerPanel { + width: 100%; + + & > * { + @include euiLegibilityMaxWidth(100%); + } +} diff --git a/src/plugins/discover/public/application/components/no_index_patterns/no_index_patterns.tsx b/src/plugins/discover/public/application/components/no_index_patterns/no_index_patterns.tsx new file mode 100644 index 000000000000..7906a2f06041 --- /dev/null +++ b/src/plugins/discover/public/application/components/no_index_patterns/no_index_patterns.tsx @@ -0,0 +1,89 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import './no_index_patterns.scss'; +import React from 'react'; +import { i18n } from '@osd/i18n'; +import { + EuiPanel, + EuiFlexGroup, + EuiFlexItem, + EuiIcon, + EuiText, + EuiTitle, + EuiButtonEmpty, +} from '@elastic/eui'; +import { getServices } from '../../../opensearch_dashboards_services'; + +export const DiscoverNoIndexPatterns: React.FC = () => { + const languageService = getServices().data.query.queryString.getLanguageService(); + const registeredLanguages = languageService.getLanguages(); + + return ( + + + + + + + + + +

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

+
+
+ + + {i18n.translate('discover.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('discover.noIndexPatterns.learnMoreAboutQueryLanguages', { + defaultMessage: 'Learn more about query languages', + })} +

+
+
+ + + {registeredLanguages.map( + (language) => + language.docLink && ( + + + {language.docLink.title} + + + ) + )} + + +
+
+
+
+ ); +}; diff --git a/src/plugins/discover/public/application/components/no_results/no_results.tsx b/src/plugins/discover/public/application/components/no_results/no_results.tsx index 6c8421535fde..57d34b64ef64 100644 --- a/src/plugins/discover/public/application/components/no_results/no_results.tsx +++ b/src/plugins/discover/public/application/components/no_results/no_results.tsx @@ -41,31 +41,21 @@ import { EuiPanel, } from '@elastic/eui'; import { i18n } from '@osd/i18n'; -import { Query } from '../../../../../data/common'; import { - DatasetServiceContract, - LanguageServiceContract, + Query, + QueryStringContract, SavedQuery, SavedQueryService, } from '../../../../../data/public/'; interface Props { - datasetService: DatasetServiceContract; + queryString: QueryStringContract; savedQuery: SavedQueryService; - languageService: LanguageServiceContract; query: Query | undefined; timeFieldName?: string; - queryLanguage?: string; } -export const DiscoverNoResults = ({ - datasetService, - savedQuery, - languageService, - query, - timeFieldName, - queryLanguage, -}: Props) => { +export const DiscoverNoResults = ({ queryString, query, savedQuery, timeFieldName }: Props) => { // Commented out due to no usage in code // See: https://github.com/opensearch-project/OpenSearch-Dashboards/issues/8149 // @@ -212,15 +202,17 @@ export const DiscoverNoResults = ({ // Samples for the dataset type if (query?.dataset?.type) { - const datasetSampleQueries = datasetService - .getType(query.dataset.type) + const datasetSampleQueries = queryString + .getDatasetService() + ?.getType(query.dataset.type) ?.getSampleQueries?.(query.dataset, query.language); if (Array.isArray(datasetSampleQueries)) sampleQueries.push(...datasetSampleQueries); } // Samples for the language if (query?.language) { - const languageSampleQueries = languageService.getLanguage(query.language)?.sampleQueries; + const languageSampleQueries = queryString.getLanguageService()?.getLanguage(query.language) + ?.sampleQueries; if (Array.isArray(languageSampleQueries)) sampleQueries.push(...languageSampleQueries); } @@ -264,7 +256,7 @@ export const DiscoverNoResults = ({ ] : []), ]; - }, [datasetService, languageService, query, savedQueries]); + }, [queryString, query, savedQueries]); return ( diff --git a/src/plugins/discover/public/application/components/sidebar/lib/get_index_pattern_field_list.ts b/src/plugins/discover/public/application/components/sidebar/lib/get_index_pattern_field_list.ts index 93b80ae99653..5d9a030e2e13 100644 --- a/src/plugins/discover/public/application/components/sidebar/lib/get_index_pattern_field_list.ts +++ b/src/plugins/discover/public/application/components/sidebar/lib/get_index_pattern_field_list.ts @@ -28,8 +28,7 @@ * under the License. */ -import { difference } from 'lodash'; -import { IndexPattern, IndexPatternField } from 'src/plugins/data/public'; +import { IndexPattern } from 'src/plugins/data/public'; export function getIndexPatternFieldList( indexPattern?: IndexPattern, 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 af94e0e6f542..cf834888b4f0 100644 --- a/src/plugins/discover/public/application/view_components/canvas/index.tsx +++ b/src/plugins/discover/public/application/view_components/canvas/index.tsx @@ -4,7 +4,7 @@ */ import React, { useEffect, useState, useRef, useCallback } from 'react'; -import { EuiPanel } from '@elastic/eui'; +import { EuiPanel, EuiSpacer } from '@elastic/eui'; import { TopNav } from './top_nav'; import { ViewProps } from '../../../../../data_explorer/public'; import { DiscoverTable } from './discover_table'; @@ -12,6 +12,7 @@ import { DiscoverChartContainer } from './discover_chart_container'; import { useDiscoverContext } from '../context'; import { ResultStatus, SearchData } from '../utils/use_search'; import { DiscoverNoResults } from '../../components/no_results/no_results'; +import { DiscoverNoIndexPatterns } from '../../components/no_index_patterns/no_index_patterns'; import { DiscoverUninitialized } from '../../components/uninitialized/uninitialized'; import { LoadingSpinner } from '../../components/loading_spinner/loading_spinner'; import { setColumns, useDispatch, useSelector } from '../../utils/state_management'; @@ -27,31 +28,19 @@ import { OpenSearchSearchHit } from '../../../application/doc_views/doc_views_ty import { buildColumns } from '../../utils/columns'; import './discover_canvas.scss'; import { HeaderVariant } from '../../../../../../core/public'; -import { Query } from '../../../../../../../src/plugins/data/common/types'; -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 { - uiSettings, - capabilities, - chrome: { setHeaderVariant }, - data, - overlays, - } = services; - const datasetService = data.query.queryString.getDatasetService(); - const savedQuery = data.query.savedQueries; - const languageService = data.query.queryString.getLanguageService(); + services: { + uiSettings, + capabilities, + chrome: { setHeaderVariant }, + data, + }, + } = useOpenSearchDashboards(); const { columns } = useSelector((state) => { const stateColumns = state.discover.columns; @@ -69,7 +58,6 @@ export default function DiscoverCanvas({ setHeaderActionMenu, history, optionalR ); const dispatch = useDispatch(); const prevIndexPattern = useRef(indexPattern); - const [query, setQuery] = useState(); const [fetchState, setFetchState] = useState({ status: data$.getValue().status, @@ -79,9 +67,6 @@ export default function DiscoverCanvas({ setHeaderActionMenu, history, optionalR const onQuerySubmit = useCallback( (payload, isUpdate) => { - if (payload?.query) { - setQuery(payload?.query); - } if (isUpdate === false) { refetch$.next(); } @@ -139,48 +124,10 @@ 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 initialQuery = queryString.getInitialQueryByDataset(dataset); - queryString.setQuery(initialQuery); - 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 ( - {hasNoDataset ? ( - - ) : ( + + {indexPattern ? ( <> {fetchState.status === ResultStatus.NO_RESULTS && ( )} {fetchState.status === ResultStatus.ERROR && ( )} {fetchState.status === ResultStatus.UNINITIALIZED && ( @@ -237,6 +178,11 @@ export default function DiscoverCanvas({ setHeaderActionMenu, history, optionalR )} + ) : ( + <> + + + )} ); 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 0b3f1275d7ff..6f827e563ec6 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,15 +35,9 @@ export interface TopNavProps { }; showSaveQuery: boolean; isEnhancementsEnabled?: boolean; - useNoIndexPatternsTopNav?: boolean; } -export const TopNav = ({ - opts, - showSaveQuery, - isEnhancementsEnabled, - useNoIndexPatternsTopNav = false, -}: TopNavProps) => { +export const TopNav = ({ opts, showSaveQuery, isEnhancementsEnabled }: TopNavProps) => { const { services } = useOpenSearchDashboards(); const { data$, inspectorAdapters, savedSearch, indexPattern } = useDiscoverContext(); const [indexPatterns, setIndexPatterns] = useState(undefined); @@ -68,13 +62,7 @@ export const TopNav = ({ const showActionsInGroup = uiSettings.get('home:useNewHomePage'); const topNavLinks = savedSearch - ? getTopNavLinks( - services, - inspectorAdapters, - savedSearch, - isEnhancementsEnabled, - useNoIndexPatternsTopNav - ) + ? getTopNavLinks(services, inspectorAdapters, savedSearch, isEnhancementsEnabled) : []; connectStorageToQueryState( @@ -100,18 +88,11 @@ export const TopNav = ({ useEffect(() => { let isMounted = true; const initializeDataset = async () => { - await data.indexPatterns.ensureDefaultIndexPattern(isEnhancementsEnabled ? false : true); + await data.indexPatterns.ensureDefaultIndexPattern(); const defaultIndexPattern = await data.indexPatterns.getDefault(); - // TODO: ROCKY do we need this? - // const queryString = data.query.queryString; - // const defaultDataset = queryString.getDatasetService().getDefault(); - if (!isMounted) return; setIndexPatterns(defaultIndexPattern ? [defaultIndexPattern] : undefined); - // if (defaultDataset) { - // datasetManager.setDataset(defaultDataset); - // } }; initializeDataset(); @@ -119,7 +100,7 @@ export const TopNav = ({ return () => { isMounted = false; }; - }, [data.indexPatterns, data.query, isEnhancementsEnabled]); + }, [data.indexPatterns, data.query]); useEffect(() => { const pageTitleSuffix = savedSearch?.id && savedSearch.title ? `: ${savedSearch.title}` : ''; @@ -176,31 +157,21 @@ export const TopNav = ({ {} : opts.onQuerySubmit} - savedQueryId={useNoIndexPatternsTopNav ? undefined : state.savedQuery} - onSavedQueryIdChange={useNoIndexPatternsTopNav ? () => {} : updateSavedQueryId} - datePickerRef={useNoIndexPatternsTopNav ? undefined : opts?.optionalRef?.datePickerRef} + indexPatterns={indexPattern ? [indexPattern] : indexPatterns} + onQuerySubmit={opts.onQuerySubmit} + savedQueryId={state.savedQuery} + onSavedQueryIdChange={updateSavedQueryId} + datasetSelectorRef={opts?.optionalRef?.datasetSelectorRef} + datePickerRef={opts?.optionalRef?.datePickerRef} groupActions={showActionsInGroup} - screenTitle={ - useNoIndexPatternsTopNav - ? i18n.translate('discover.noIndexPatterns.screenTitle', { - defaultMessage: 'Select data', - }) - : screenTitle - } + screenTitle={screenTitle} queryStatus={queryStatus} + showQueryBar={!!opts?.optionalRef?.datasetSelectorRef} /> ); diff --git a/src/plugins/query_enhancements/public/plugin.tsx b/src/plugins/query_enhancements/public/plugin.tsx index ff3df7e9ce1c..cbd40cb60b60 100644 --- a/src/plugins/query_enhancements/public/plugin.tsx +++ b/src/plugins/query_enhancements/public/plugin.tsx @@ -77,6 +77,12 @@ export class QueryEnhancementsPlugin filterable: false, visualizable: false, }, + docLink: { + title: i18n.translate('queryEnhancements.pplLanguage.docLink', { + defaultMessage: 'PPL documentation', + }), + url: 'https://opensearch.org/docs/latest/search-plugins/sql/ppl/syntax/', + }, showDocLinks: false, editor: enhancedPPLQueryEditor, editorSupportedAppNames: ['discover'], @@ -96,6 +102,12 @@ export class QueryEnhancementsPlugin filterable: false, visualizable: false, }, + docLink: { + title: i18n.translate('queryEnhancements.sqlLanguage.docLink', { + defaultMessage: 'SQL documentation', + }), + url: 'https://opensearch.org/docs/latest/search-plugins/sql/sql/basic/', + }, showDocLinks: false, editor: enhancedSQLQueryEditor, editorSupportedAppNames: ['discover'],