diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/reference_field_selects.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/reference_field_selects.tsx index 9d923f529931b..c9c2127454e54 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/reference_field_selects.tsx +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/reference_field_selects.tsx @@ -26,7 +26,7 @@ export const ReferenceFieldSelects = () => { }; const referenceFieldOptions: SuperSelectOption[] = Object.values(allFields.byId) - .filter((field) => field.source.type === 'text') + .filter((field) => field.source.type === 'text' && !field.isMultiField) .map((field) => ({ value: field.path.join('.'), inputDisplay: field.path.join('.'), diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/semantic_text/use_semantic_text.ts b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/semantic_text/use_semantic_text.ts index 2eb4343d0c7a4..b763c5c7ddc00 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/semantic_text/use_semantic_text.ts +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/semantic_text/use_semantic_text.ts @@ -54,7 +54,7 @@ export function useSemanticText(props: UseSemanticTextProps) { const defaultName = getFieldByPathName(allFields, 'semantic_text') ? '' : 'semantic_text'; const referenceField = Object.values(allFields.byId) - .find((field) => field.source.type === 'text') + .find((field) => field.source.type === 'text' && !field.isMultiField) ?.path.join('.') || ''; if (!form.getFormData().name) { form.setFieldValue('name', defaultName); diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/lib/utils.test.ts b/x-pack/plugins/index_management/public/application/components/mappings_editor/lib/utils.test.ts index 3a4f71a8d533b..58b40293f64f2 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/lib/utils.test.ts +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/lib/utils.test.ts @@ -641,6 +641,173 @@ describe('utils', () => { } as any; expect(getStateWithCopyToFields(state)).toEqual(expectedState); }); + test('adds nested text field with copy to to state for multi-fields correctly', () => { + const state = { + fields: { + byId: { + '88ebcfdb-19b7-4458-9ea2-9488df54453d': { + id: '88ebcfdb-19b7-4458-9ea2-9488df54453d', + isMultiField: false, + path: ['title'], + source: { + name: 'title', + type: 'semantic_text', + inference_id: 'id', + reference_field: 'existing.new', + }, + }, + }, + rootLevelFields: ['88ebcfdb-19b7-4458-9ea2-9488df54453d'], + }, + mappingViewFields: { + byId: { + existing: { + id: 'existing', + isMultiField: false, + path: ['existing'], + source: { + name: 'existing', + type: 'object', + }, + }, + 'new-field': { + childFields: ['child-1', 'child-2'], + id: 'new-field', + parentId: 'existing', + isMultiField: true, + path: ['existing', 'new'], + source: { + name: 'new', + type: 'text', + }, + }, + 'child-1': { + id: 'child-1', + parentId: 'new-field', + isMultiField: false, + path: ['existing', 'new', 'child-1'], + source: { + name: 'child-1', + type: 'text', + }, + }, + 'child-2': { + id: 'child-2', + parentId: 'new-field', + isMultiField: true, + path: ['existing', 'new', 'child-2'], + source: { + name: 'child-2', + type: 'text', + }, + }, + }, + }, + } as any; + const expectedState = { + fields: { + byId: { + '88ebcfdb-19b7-4458-9ea2-9488df54453d': { + id: '88ebcfdb-19b7-4458-9ea2-9488df54453d', + isMultiField: false, + path: ['title'], + source: { + name: 'title', + type: 'semantic_text', + inference_id: 'id', + }, + }, + existing: { + id: 'existing', + isMultiField: false, + path: ['existing'], + source: { + name: 'existing', + type: 'object', + }, + }, + 'new-field': { + childFields: ['child-1', 'child-2'], + id: 'new-field', + isMultiField: true, + parentId: 'existing', + path: ['existing', 'new'], + source: { + name: 'new', + type: 'text', + copy_to: ['title'], + }, + }, + 'child-1': { + id: 'child-1', + parentId: 'new-field', + isMultiField: false, + path: ['existing', 'new', 'child-1'], + source: { + name: 'child-1', + type: 'text', + }, + }, + 'child-2': { + id: 'child-2', + parentId: 'new-field', + isMultiField: true, + path: ['existing', 'new', 'child-2'], + source: { + name: 'child-2', + type: 'text', + }, + }, + }, + rootLevelFields: ['88ebcfdb-19b7-4458-9ea2-9488df54453d', 'existing'], + }, + mappingViewFields: { + byId: { + existing: { + id: 'existing', + isMultiField: false, + path: ['existing'], + source: { + name: 'existing', + type: 'object', + }, + }, + 'new-field': { + childFields: ['child-1', 'child-2'], + id: 'new-field', + parentId: 'existing', + isMultiField: true, + path: ['existing', 'new'], + source: { + name: 'new', + type: 'text', + }, + }, + 'child-1': { + id: 'child-1', + parentId: 'new-field', + isMultiField: false, + path: ['existing', 'new', 'child-1'], + source: { + name: 'child-1', + type: 'text', + }, + }, + 'child-2': { + id: 'child-2', + parentId: 'new-field', + isMultiField: true, + path: ['existing', 'new', 'child-2'], + source: { + name: 'child-2', + type: 'text', + }, + }, + }, + }, + } as any; + expect(getStateWithCopyToFields(state)).toEqual(expectedState); + }); }); }); }); diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/lib/utils.ts b/x-pack/plugins/index_management/public/application/components/mappings_editor/lib/utils.ts index 4b882e5bc4951..728ba79eedd81 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/lib/utils.ts +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/lib/utils.ts @@ -732,16 +732,7 @@ export function getStateWithCopyToFields(state: State): State { : [field.path.join('.')], }, }; - // add existing text field and children to byId list - const children = existingTextField.childFields - ? existingTextField.childFields.reduce>( - (acc, childFieldId) => { - acc[childFieldId] = state.mappingViewFields.byId[childFieldId]; - return acc; - }, - {} - ) - : {}; + updatedState = { ...updatedState, fields: { @@ -749,10 +740,10 @@ export function getStateWithCopyToFields(state: State): State { byId: { ...updatedState.fields.byId, [existingTextField.id]: updatedTextField, - ...children, }, }, }; + addChildFieldsToState(updatedTextField, updatedState); if (existingTextField.parentId) { let currentField = existingTextField; let hasParent = true; @@ -768,6 +759,10 @@ export function getStateWithCopyToFields(state: State): State { // parent is not in state yet updatedState.fields.byId[currentField.parentId] = updatedState.mappingViewFields.byId[currentField.parentId]; + addChildFieldsToState( + updatedState.mappingViewFields.byId[currentField.parentId], + updatedState + ); currentField = updatedState.fields.byId[currentField.parentId]; } } @@ -782,6 +777,19 @@ export function getStateWithCopyToFields(state: State): State { return updatedState; } +function addChildFieldsToState(field: NormalizedField, state: State): State { + if (!field.childFields || field.childFields.length === 0) { + return state; + } + for (const childFieldId of field.childFields) { + if (!state.fields.byId[childFieldId]) { + state.fields.byId[childFieldId] = state.mappingViewFields.byId[childFieldId]; + state = addChildFieldsToState(state.fields.byId[childFieldId], state); + } + } + return state; +} + export const getFieldByPathName = (fields: NormalizedFields, name: string) => { return Object.values(fields.byId).find((field) => field.path.join('.') === name); };