[Enterprise Search] add ml pipeline empty schema error (#142618)

Added an error for when there are no source fields available.
Loaded a small set of default fields if we know its a connector index.
This commit is contained in:
Rodney Norris 2022-10-05 08:47:17 -05:00 committed by GitHub
parent 37e4eb2d04
commit c19ccdb96c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 43 additions and 3 deletions

View file

@ -22,11 +22,29 @@ import {
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import { docLinks } from '../../../../../shared/doc_links';
import { MLInferenceLogic } from './ml_inference_logic';
const NoSourceFieldsError: React.FC = () => (
<FormattedMessage
id="xpack.enterpriseSearch.content.indices.pipelines.addInferencePipelineModal.steps.configure.sourceField.error"
defaultMessage="Selecting a source field is required for pipeline configuration, but this index does not have a field mapping. {learnMore}"
values={{
learnMore: (
<EuiLink href={docLinks.elasticsearchMapping} target="_blank" color="danger">
{i18n.translate(
'xpack.enterpriseSearch.content.indices.pipelines.addInferencePipelineModal.steps.configure.sourceField.error.docLink',
{ defaultMessage: 'Learn more about field mapping' }
)}
</EuiLink>
),
}}
/>
);
export const ConfigurePipeline: React.FC = () => {
const {
addInferencePipelineModal: { configuration },
@ -39,6 +57,7 @@ export const ConfigurePipeline: React.FC = () => {
const { destinationField, modelID, pipelineName, sourceField } = configuration;
const models = supportedMLModels ?? [];
const nameError = formErrors.pipelineName !== undefined && pipelineName.length > 0;
const emptySourceFields = (sourceFields?.length ?? 0) === 0;
return (
<>
@ -143,6 +162,8 @@ export const ConfigurePipeline: React.FC = () => {
defaultMessage: 'Source field',
}
)}
error={emptySourceFields && <NoSourceFieldsError />}
isInvalid={emptySourceFields}
>
<EuiSelect
value={sourceField}

View file

@ -19,10 +19,16 @@ import { HttpError, Status } from '../../../../../../../common/types/api';
import { MlInferencePipeline } from '../../../../../../../common/types/pipelines';
import { getErrorsFromHttpResponse } from '../../../../../shared/flash_messages/handle_api_errors';
import {
FetchIndexApiLogic,
FetchIndexApiResponse,
} from '../../../../api/index/fetch_index_api_logic';
import { MappingsApiLogic } from '../../../../api/mappings/mappings_logic';
import { CreateMlInferencePipelineApiLogic } from '../../../../api/ml_models/create_ml_inference_pipeline';
import { MLModelsApiLogic } from '../../../../api/ml_models/ml_models_logic';
import { isConnectorIndex } from '../../../../utils/indices';
import { AddInferencePipelineFormErrors, InferencePipelineConfiguration } from './types';
import {
isSupportedMLModel,
@ -44,6 +50,7 @@ export enum AddInferencePipelineSteps {
}
const API_REQUEST_COMPLETE_STATUSES = [Status.SUCCESS, Status.ERROR];
const DEFAULT_CONNECTOR_FIELDS = ['body', 'title', 'id', 'type', 'url'];
interface MLInferenceProcessorsActions {
createApiError: (error: HttpError) => HttpError;
@ -76,6 +83,7 @@ interface MLInferenceProcessorsValues {
formErrors: AddInferencePipelineFormErrors;
isLoading: boolean;
isPipelineDataValid: boolean;
index: FetchIndexApiResponse;
mappingData: typeof MappingsApiLogic.values.data;
mappingStatus: Status;
mlInferencePipeline?: MlInferencePipeline;
@ -113,6 +121,8 @@ export const MLInferenceLogic = kea<
],
],
values: [
FetchIndexApiLogic,
['data as index'],
MappingsApiLogic,
['data as mappingData', 'status as mappingStatus'],
MLModelsApiLogic,
@ -210,10 +220,19 @@ export const MLInferenceLogic = kea<
},
],
sourceFields: [
() => [selectors.mappingStatus, selectors.mappingData],
(status: Status, mapping: IndicesGetMappingIndexMappingRecord) => {
() => [selectors.mappingStatus, selectors.mappingData, selectors.index],
(
status: Status,
mapping: IndicesGetMappingIndexMappingRecord,
index: FetchIndexApiResponse
) => {
if (status !== Status.SUCCESS) return;
if (mapping?.mappings?.properties === undefined) return [];
if (mapping?.mappings?.properties === undefined) {
if (isConnectorIndex(index)) {
return DEFAULT_CONNECTOR_FIELDS;
}
return [];
}
return Object.entries(mapping.mappings.properties)
.reduce((fields, [key, value]) => {
if (value.type === 'text' || value.type === 'keyword') {