diff --git a/src/plugins/data/public/index.ts b/src/plugins/data/public/index.ts index 0ca84c184bf4..cdf4d29697ca 100644 --- a/src/plugins/data/public/index.ts +++ b/src/plugins/data/public/index.ts @@ -473,6 +473,8 @@ export { LanguageServiceContract, RecentQueriesTable, QueryControls, + QueryResult, + QueryStatus, SavedQuery, SavedQueryService, SavedQueryTimeFilter, diff --git a/src/plugins/data/public/query/query_string/index.ts b/src/plugins/data/public/query/query_string/index.ts index c8f6df921ad3..a004103e971b 100644 --- a/src/plugins/data/public/query/query_string/index.ts +++ b/src/plugins/data/public/query/query_string/index.ts @@ -37,4 +37,6 @@ export { EditorEnhancements, RecentQueriesTable, QueryControls, + QueryResult, + QueryStatus, } from './language_service'; diff --git a/src/plugins/data/public/query/query_string/language_service/index.ts b/src/plugins/data/public/query/query_string/language_service/index.ts index cd04fcb50724..70df0971f50c 100644 --- a/src/plugins/data/public/query/query_string/language_service/index.ts +++ b/src/plugins/data/public/query/query_string/language_service/index.ts @@ -5,4 +5,4 @@ export * from './types'; export { LanguageServiceContract, LanguageService } from './language_service'; -export { RecentQueriesTable, QueryControls } from './lib'; +export { RecentQueriesTable, QueryControls, QueryResult, QueryStatus } from './lib'; diff --git a/src/plugins/data/public/query/query_string/language_service/lib/index.ts b/src/plugins/data/public/query/query_string/language_service/lib/index.ts index ca93870dfd4d..dbaaec3e1905 100644 --- a/src/plugins/data/public/query/query_string/language_service/lib/index.ts +++ b/src/plugins/data/public/query/query_string/language_service/lib/index.ts @@ -9,3 +9,4 @@ export * from './lucene_language'; export * from './default_language_reference'; export * from './get_query_control_links'; export * from './recent_query'; +export * from './query_result'; diff --git a/src/plugins/data/public/query/query_string/language_service/query_result.tsx b/src/plugins/data/public/query/query_string/language_service/lib/query_result.tsx similarity index 72% rename from src/plugins/data/public/query/query_string/language_service/query_result.tsx rename to src/plugins/data/public/query/query_string/language_service/lib/query_result.tsx index 1c33bb907eb9..206bf3a80251 100644 --- a/src/plugins/data/public/query/query_string/language_service/query_result.tsx +++ b/src/plugins/data/public/query/query_string/language_service/lib/query_result.tsx @@ -10,11 +10,21 @@ import { EuiButtonEmpty, EuiPopover, EuiText, EuiPopoverTitle } from '@elastic/e import React, { useState, useEffect } from 'react'; +export enum ResultStatus { + UNINITIALIZED = 'uninitialized', + LOADING = 'loading', // initial data load + READY = 'ready', // results came back + NO_RESULTS = 'none', // no results came back + ERROR = 'error', // error occurred +} + export interface QueryStatus { - status: string; - message?: { - error?: string; - message?: string; + status: ResultStatus; + body?: { + error?: { + reason?: string; + details: string; + }; statusCode?: number; }; time?: number; @@ -22,7 +32,7 @@ export interface QueryStatus { export function QueryResult(props: { queryStatus$: BehaviorSubject }) { const [isPopoverOpen, setPopover] = useState(false); - const [queryStatus, setQueryStatus] = useState({ status: 'ready' }); + const [queryStatus, setQueryStatus] = useState({ status: ResultStatus.READY }); const onButtonClick = () => { setPopover(!isPopoverOpen); }; @@ -34,22 +44,20 @@ export function QueryResult(props: { queryStatus$: BehaviorSubject return () => subscription.unsubscribe(); }, [props.queryStatus$]); - if (queryStatus.status === 'ready') { + if (queryStatus.status === ResultStatus.READY) { return ( {}}> - {'Complete in ' + queryStatus.time + ' ms'} + {queryStatus.time ? `Complete in ${queryStatus.time} ms` : 'Complete'} ); } - if (!queryStatus.message || !queryStatus.message.message) { + if (!queryStatus.body || !queryStatus.body.error) { return null; } - const errorMsg = JSON.parse(queryStatus.message.message); - return (
Reasons: - {errorMsg.error.reason} + {queryStatus.body.error.reason}

- Details: {errorMsg.error.details}{' '} + Details: {queryStatus.body.error.details}

diff --git a/src/plugins/data/public/ui/query_editor/query_editor.tsx b/src/plugins/data/public/ui/query_editor/query_editor.tsx index b281374946c0..200de53e4966 100644 --- a/src/plugins/data/public/ui/query_editor/query_editor.tsx +++ b/src/plugins/data/public/ui/query_editor/query_editor.tsx @@ -28,6 +28,8 @@ import { TimeRange, QueryControls, RecentQueriesTable, + QueryResult, + QueryStatus, } from '../..'; import { OpenSearchDashboardsReactContextValue } from '../../../../opensearch_dashboards_react/public'; import { fromUser, getQueryLog, PersistedLog, toUser } from '../../query'; @@ -38,7 +40,6 @@ import { getQueryService, getIndexPatterns } from '../../services'; import { DatasetSelector } from '../dataset_selector'; import { DefaultInputProps } from './editors'; import { MonacoCompatibleQuerySuggestion } from '../../autocomplete/providers/query_suggestion_provider'; -import { QueryResult, QueryStatus } from '../../query/query_string/language_service/query_result'; export interface QueryEditorProps { query: Query; 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 db9942c3a1d3..fe47d364121f 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 @@ -22,10 +22,9 @@ import { withOpenSearchDashboards, } from '../../../../opensearch_dashboards_react/public'; import { UI_SETTINGS } from '../../../common'; -import { getQueryLog, PersistedLog } from '../../query'; +import { getQueryLog, PersistedLog, QueryStatus } from '../../query'; import { NoDataPopover } from './no_data_popover'; import QueryEditorUI from './query_editor'; -import { QueryStatus } from '../../query/query_string/language_service/query_result'; const QueryEditor = withOpenSearchDashboards(QueryEditorUI); 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 4b4f983660fa..1ee4a2fdc975 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 @@ -33,7 +33,7 @@ import React, { useEffect, useRef } from 'react'; import { BehaviorSubject } from 'rxjs'; import { CoreStart } from 'src/core/public'; import { OpenSearchDashboardsContextProvider } from '../../../../opensearch_dashboards_react/public'; -import { QueryStart, SavedQuery } from '../../query'; +import { QueryStart, SavedQuery, QueryStatus } from '../../query'; import { SearchBar, SearchBarOwnProps } from './'; import { useFilterManager } from './lib/use_filter_manager'; import { useTimefilter } from './lib/use_timefilter'; @@ -41,7 +41,6 @@ import { useSavedQuery } from './lib/use_saved_query'; import { DataPublicPluginStart } from '../../types'; import { DataStorage, Filter, Query, TimeRange } from '../../../common'; import { useQueryStringManager } from './lib/use_query_string_manager'; -import { QueryStatus } from '../../query/query_string/language_service/query_result'; interface StatefulSearchBarDeps { core: CoreStart; 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 d179f5e4a237..bccd442cb3cd 100644 --- a/src/plugins/data/public/ui/search_bar/search_bar.tsx +++ b/src/plugins/data/public/ui/search_bar/search_bar.tsx @@ -39,15 +39,13 @@ import { withOpenSearchDashboards, } from '../../../../opensearch_dashboards_react/public'; import { Filter, IIndexPattern, Query, TimeRange, UI_SETTINGS } from '../../../common'; -import { SavedQuery, SavedQueryAttributes, TimeHistoryContract } from '../../query'; +import { SavedQuery, SavedQueryAttributes, TimeHistoryContract, QueryStatus } from '../../query'; import { IDataPluginServices } from '../../types'; import { FilterBar } from '../filter_bar/filter_bar'; import { QueryEditorTopRow } from '../query_editor'; import QueryBarTopRow from '../query_string_input/query_bar_top_row'; import { SavedQueryMeta, SaveQueryForm } from '../saved_query_form'; import { FilterOptions } from '../filter_bar/filter_options'; -import { SearchData } from '../../../../discover/public'; -import { QueryStatus } from '../../query/query_string/language_service/query_result'; interface SearchBarInjectedDeps { opensearchDashboards: OpenSearchDashboardsReactContextValue; diff --git a/src/plugins/data/public/ui/types.ts b/src/plugins/data/public/ui/types.ts index b94c781ece5a..639addaa69d0 100644 --- a/src/plugins/data/public/ui/types.ts +++ b/src/plugins/data/public/ui/types.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { QueryStatus } from '../query/query_string/language_service/query_result'; +import { QueryStatus } from '../query'; import { IndexPatternSelectProps } from './index_pattern_select'; import { StatefulSearchBarProps } from './search_bar'; import { SuggestionsComponentProps } from './typeahead/suggestions_component'; diff --git a/src/plugins/data/public/ui/ui_service.ts b/src/plugins/data/public/ui/ui_service.ts index 43fbc978449b..cab1302afa16 100644 --- a/src/plugins/data/public/ui/ui_service.ts +++ b/src/plugins/data/public/ui/ui_service.ts @@ -12,7 +12,8 @@ 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/query_string/language_service/query_result'; +import { QueryStatus } from '../query'; +import { ResultStatus } from '../query/query_string/language_service/lib'; /** @internal */ // eslint-disable-next-line @typescript-eslint/no-empty-interface @@ -26,7 +27,7 @@ export interface UiServiceStartDependencies { export class UiService implements Plugin { enhancementsConfig: ConfigSchema['enhancements']; - private queryStatus$ = new BehaviorSubject({ status: 'ready' }); + private queryStatus$ = new BehaviorSubject({ status: ResultStatus.READY }); constructor(initializerContext: PluginInitializerContext) { const { enhancements } = initializerContext.config.get(); 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 4b3f17dfed6a..0512969be419 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 @@ -71,12 +71,10 @@ export const TopNav = ({ opts, showSaveQuery, isEnhancementsEnabled }: TopNavPro useEffect(() => { const subscription = data$.subscribe((queryData) => { - data.ui.setQueryStatus({ - status: queryData.status, - message: queryData.statusBody?.errorMsg, - time: queryData.statusBody?.time, - }); + if (!queryData.queryStatus) return; + data.ui.setQueryStatus(queryData.queryStatus); }); + return () => subscription.unsubscribe(); }, [data$, data.ui]); useEffect(() => { diff --git a/src/plugins/discover/public/application/view_components/utils/use_search.ts b/src/plugins/discover/public/application/view_components/utils/use_search.ts index 779607295fd5..6850b49b6315 100644 --- a/src/plugins/discover/public/application/view_components/utils/use_search.ts +++ b/src/plugins/discover/public/application/view_components/utils/use_search.ts @@ -12,7 +12,7 @@ import { cloneDeep } from 'lodash'; import { useLocation } from 'react-router-dom'; import { RequestAdapter } from '../../../../../inspector/public'; import { DiscoverViewServices } from '../../../build_services'; -import { search } from '../../../../../data/public'; +import { QueryStatus, search } from '../../../../../data/public'; import { validateTimeRange } from '../../helpers/validate_time_range'; import { updateSearchSource } from './update_search_source'; import { useIndexPattern } from './use_index_pattern'; @@ -51,10 +51,7 @@ export interface SearchData { bucketInterval?: TimechartHeaderBucketInterval | {}; chartData?: Chart; title?: string; - statusBody?: { - errorMsg?: any; - time?: number; - }; + queryStatus?: QueryStatus; } export type SearchRefetch = 'refetch' | undefined; @@ -224,7 +221,8 @@ export const useSearch = (services: DiscoverViewServices) => { indexPattern?.title !== searchSource.getDataFrame()?.name ? searchSource.getDataFrame()?.name : indexPattern?.title, - statusBody: { + queryStatus: { + status: rows.length > 0 ? ResultStatus.READY : ResultStatus.NO_RESULTS, time: queryTime, }, }); @@ -232,10 +230,18 @@ export const useSearch = (services: DiscoverViewServices) => { // If the request was aborted then no need to surface this error in the UI if (error instanceof Error && error.name === 'AbortError') return; + let errorBody; + try { + errorBody = JSON.parse(error.body.message); + } catch (e) { + errorBody = error.body.message; + } + data$.next({ status: ResultStatus.ERROR, - statusBody: { - errorMsg: error.body, + queryStatus: { + status: ResultStatus.ERROR, + body: errorBody, time: queryTime, }, }); diff --git a/src/plugins/query_enhancements/common/utils.ts b/src/plugins/query_enhancements/common/utils.ts index 44949207e056..7388d6beea40 100644 --- a/src/plugins/query_enhancements/common/utils.ts +++ b/src/plugins/query_enhancements/common/utils.ts @@ -44,7 +44,7 @@ export const removeKeyword = (queryString: string | undefined) => { export const handleFacetError = (response: any) => { const error = new Error(response.data.body ?? response.data); error.name = response.data.status ?? response.status; - return throwError(error); + throw error; }; export const fetch = (context: EnhancedFetchContext, query: Query, aggConfig?: QueryAggConfig) => {