diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/text_expansion_callout.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/text_expansion_callout.tsx index 993b15d404cf8..a72a328188c6f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/text_expansion_callout.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/text_expansion_callout.tsx @@ -29,7 +29,7 @@ import { docLinks } from '../../../../../shared/doc_links'; import { KibanaLogic } from '../../../../../shared/kibana'; import { useTextExpansionCallOutData } from './text_expansion_callout_data'; -import { TextExpansionCalloutLogic } from './text_expansion_callout_logic'; +import { getTextExpansionError, TextExpansionCalloutLogic } from './text_expansion_callout_logic'; import { TextExpansionErrors } from './text_expansion_errors'; export interface TextExpansionCallOutState { @@ -339,19 +339,12 @@ export const TextExpansionCallOut: React.FC = (props) } = useValues(TextExpansionCalloutLogic); // In case of an error, show the error callout only - if ( - createTextExpansionModelError !== undefined || - fetchTextExpansionModelError !== undefined || - startTextExpansionModelError !== undefined - ) { - return ( - - ); - } + const error = getTextExpansionError( + createTextExpansionModelError, + fetchTextExpansionModelError, + startTextExpansionModelError + ); + if (error) return ; if (!show) return null; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/text_expansion_callout_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/text_expansion_callout_logic.test.ts index c47dcf985564f..15e1d929ebdf9 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/text_expansion_callout_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/text_expansion_callout_logic.test.ts @@ -9,12 +9,13 @@ import { LogicMounter } from '../../../../../__mocks__/kea_logic'; import { HttpResponse } from '@kbn/core/public'; -import { ErrorResponse, Status } from '../../../../../../../common/types/api'; +import { ErrorResponse, HttpError, Status } from '../../../../../../../common/types/api'; import { MlModelDeploymentState } from '../../../../../../../common/types/ml'; import { CreateTextExpansionModelApiLogic } from '../../../../api/ml_models/text_expansion/create_text_expansion_model_api_logic'; import { FetchTextExpansionModelApiLogic } from '../../../../api/ml_models/text_expansion/fetch_text_expansion_model_api_logic'; import { + getTextExpansionError, TextExpansionCalloutLogic, TextExpansionCalloutValues, } from './text_expansion_callout_logic'; @@ -58,6 +59,37 @@ describe('TextExpansionCalloutLogic', () => { expect(TextExpansionCalloutLogic.values).toEqual(DEFAULT_VALUES); }); + describe('getTextExpansionError', () => { + const error = { + body: { + error: 'some-error', + message: 'some-error-message', + statusCode: 500, + }, + } as HttpError; + it('returns null if there is no error', () => { + expect(getTextExpansionError(undefined, undefined, undefined)).toBe(null); + }); + it('uses the correct title and message from a create error', () => { + expect(getTextExpansionError(error, undefined, undefined)).toEqual({ + title: 'Error with ELSER deployment', + message: error.body?.message, + }); + }); + it('uses the correct title and message from a create error', () => { + expect(getTextExpansionError(undefined, error, undefined)).toEqual({ + title: 'Error fetching ELSER model', + message: error.body?.message, + }); + }); + it('uses the correct title and message from a create error', () => { + expect(getTextExpansionError(undefined, undefined, error)).toEqual({ + title: 'Error starting ELSER deployment', + message: error.body?.message, + }); + }); + }); + describe('listeners', () => { describe('createTextExpansionModelPollingTimeout', () => { const duration = 5000; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/text_expansion_callout_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/text_expansion_callout_logic.ts index 0ebe1577b29f1..488d0b9aae9e3 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/text_expansion_callout_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/text_expansion_callout_logic.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { i18n } from '@kbn/i18n'; import { kea, MakeLogicType } from 'kea'; import { HttpError, Status } from '../../../../../../../common/types/api'; @@ -23,6 +24,7 @@ import { StartTextExpansionModelApiLogic, StartTextExpansionModelApiLogicActions, } from '../../../../api/ml_models/text_expansion/start_text_expansion_model_api_logic'; +import { getErrorsFromHttpResponse } from '../../../../../shared/flash_messages/handle_api_errors'; const FETCH_TEXT_EXPANSION_MODEL_POLLING_DURATION = 5000; // 5 seconds const FETCH_TEXT_EXPANSION_MODEL_POLLING_DURATION_ON_FAILURE = 30000; // 30 seconds @@ -62,6 +64,51 @@ export interface TextExpansionCalloutValues { textExpansionModelPollTimeoutId: null | ReturnType; } +/** + * Extracts the topmost error in precedence order (create > start > fetch). + * @param createError + * @param fetchError + * @param startError + * @returns the extracted error or null if there is no error + */ +export const getTextExpansionError = ( + createError: HttpError | undefined, + fetchError: HttpError | undefined, + startError: HttpError | undefined +) => { + return createError !== undefined + ? { + title: i18n.translate( + 'xpack.enterpriseSearch.content.indices.pipelines.textExpansionCreateError.title', + { + defaultMessage: 'Error with ELSER deployment', + } + ), + message: getErrorsFromHttpResponse(createError)[0], + } + : startError !== undefined + ? { + title: i18n.translate( + 'xpack.enterpriseSearch.content.indices.pipelines.textExpansionStartError.title', + { + defaultMessage: 'Error starting ELSER deployment', + } + ), + message: getErrorsFromHttpResponse(startError)[0], + } + : fetchError !== undefined + ? { + title: i18n.translate( + 'xpack.enterpriseSearch.content.indices.pipelines.textExpansionFetchError.title', + { + defaultMessage: 'Error fetching ELSER model', + } + ), + message: getErrorsFromHttpResponse(fetchError)[0], + } + : null; +}; + export const TextExpansionCalloutLogic = kea< MakeLogicType >({ diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/text_expansion_errors.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/text_expansion_errors.test.tsx index 7f4410f90b169..cb15c2c5c5411 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/text_expansion_errors.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/text_expansion_errors.test.tsx @@ -13,8 +13,6 @@ import { shallow } from 'enzyme'; import { EuiCallOut } from '@elastic/eui'; -import { HttpError } from '../../../../../../../common/types/api'; - import { TextExpansionErrors } from './text_expansion_errors'; describe('TextExpansionErrors', () => { @@ -23,38 +21,14 @@ describe('TextExpansionErrors', () => { setMockValues({}); }); const error = { - body: { - error: 'some-error', - message: 'some-error-message', - statusCode: 500, - }, - } as HttpError; - it('renders error panel if ELSER deployment fails', () => { - const wrapper = shallow( - - ); - expect(wrapper.find(EuiCallOut).length).toBe(1); - expect(wrapper.find(EuiCallOut).prop('title')).toEqual('Error with ELSER deployment'); - }); - it('renders error panel if ELSER fetching fails', () => { - const wrapper = shallow( - - ); + title: 'some-error-title', + message: 'some-error-message', + }; + it('extracts error panel with the given title and message', () => { + const wrapper = shallow(); expect(wrapper.find(EuiCallOut).length).toBe(1); - expect(wrapper.find(EuiCallOut).prop('title')).toEqual('Error fetching ELSER model'); - }); - it('renders error panel if ELSER starting fails', () => { - const wrapper = shallow( - - ); - expect(wrapper.find(EuiCallOut).length).toBe(1); - expect(wrapper.find(EuiCallOut).prop('title')).toEqual('Error starting ELSER deployment'); - }); - it('extracts and renders the error message', () => { - const wrapper = shallow( - - ); + expect(wrapper.find(EuiCallOut).prop('title')).toEqual(error.title); expect(wrapper.find(EuiCallOut).find('p').length).toBe(1); - expect(wrapper.find(EuiCallOut).find('p').text()).toEqual(error?.body?.message); + expect(wrapper.find(EuiCallOut).find('p').text()).toEqual(error.message); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/text_expansion_errors.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/text_expansion_errors.tsx index 05a8dc15abd5a..d9b1d1f1f2bc2 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/text_expansion_errors.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/text_expansion_errors.tsx @@ -13,59 +13,17 @@ import { EuiCallOut, EuiLink } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { HttpError } from '../../../../../../../common/types/api'; -import { getErrorsFromHttpResponse } from '../../../../../shared/flash_messages/handle_api_errors'; import { HttpLogic } from '../../../../../shared/http'; import { ML_NOTIFICATIONS_PATH } from '../../../../routes'; -export const TextExpansionErrors = ({ - createError, - fetchError, - startError, -}: { - createError: HttpError | undefined; - fetchError: HttpError | undefined; - startError: HttpError | undefined; -}) => { +export const TextExpansionErrors = ({ error }: { error: { title: string; message: string } }) => { const { http } = useValues(HttpLogic); - // Extract the topmost error in precedence order - const error: HttpError | undefined = createError ?? startError ?? fetchError; - if (error === undefined) { - return null; - } - const topError = getErrorsFromHttpResponse(error)[0]; - return ( <> - -

{topError}

+ +

{error.message}

{i18n.translate( 'xpack.enterpriseSearch.content.indices.pipelines.textExpansionCreateError.mlNotificationsLink',