diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/__jest__/client_integration/helpers/index.ts b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/__jest__/client_integration/helpers/index.ts
new file mode 100644
index 0000000000000..e3313bfba56fd
--- /dev/null
+++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/__jest__/client_integration/helpers/index.ts
@@ -0,0 +1,17 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+import { setup as mappingsEditorSetup } from './mappings_editor.helpers';
+
+export {
+ nextTick,
+ getRandomString,
+ findTestSubject,
+ TestBed,
+} from '../../../../../../../../../../test_utils';
+
+export const componentHelpers = {
+ mappingsEditor: { setup: mappingsEditorSetup },
+};
diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/__jest__/client_integration/helpers/mappings_editor.helpers.ts b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/__jest__/client_integration/helpers/mappings_editor.helpers.ts
new file mode 100644
index 0000000000000..b8b67a0f36bd2
--- /dev/null
+++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/__jest__/client_integration/helpers/mappings_editor.helpers.ts
@@ -0,0 +1,16 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { registerTestBed } from '../../../../../../../../../../test_utils';
+import { MappingsEditor } from '../../../mappings_editor';
+
+export const setup = (props: any) =>
+ registerTestBed(MappingsEditor, {
+ memoryRouter: {
+ wrapComponent: false,
+ },
+ defaultProps: props,
+ });
diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/__jest__/client_integration/mappings_editor.test.tsx b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/__jest__/client_integration/mappings_editor.test.tsx
new file mode 100644
index 0000000000000..9e390e785c7d5
--- /dev/null
+++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/__jest__/client_integration/mappings_editor.test.tsx
@@ -0,0 +1,55 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { componentHelpers } from './helpers';
+
+const { setup } = componentHelpers.mappingsEditor;
+const mockOnUpdate = () => undefined;
+
+describe('', () => {
+ describe('multiple mappings detection', () => {
+ test('should show a warning when multiple mappings are detected', async () => {
+ const defaultValue = {
+ type1: {
+ properties: {
+ name1: {
+ type: 'keyword',
+ },
+ },
+ },
+ type2: {
+ properties: {
+ name2: {
+ type: 'keyword',
+ },
+ },
+ },
+ };
+ const testBed = await setup({ onUpdate: mockOnUpdate, defaultValue })();
+ const { exists } = testBed;
+
+ expect(exists('mappingsEditor')).toBe(true);
+ expect(exists('mappingTypesDetectedCallout')).toBe(true);
+ expect(exists('documentFields')).toBe(false);
+ });
+
+ test('should not show a warning when mappings a single-type', async () => {
+ const defaultValue = {
+ properties: {
+ name1: {
+ type: 'keyword',
+ },
+ },
+ };
+ const testBed = await setup({ onUpdate: mockOnUpdate, defaultValue })();
+ const { exists } = testBed;
+
+ expect(exists('mappingsEditor')).toBe(true);
+ expect(exists('mappingTypesDetectedCallout')).toBe(false);
+ expect(exists('documentFields')).toBe(true);
+ });
+ });
+});
diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/document_fields.tsx b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/document_fields.tsx
index 71b5966c3295d..378d669dee69c 100644
--- a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/document_fields.tsx
+++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/document_fields/document_fields.tsx
@@ -48,7 +48,7 @@ export const DocumentFields = React.memo(() => {
const searchTerm = search.term.trim();
return (
- <>
+
{searchTerm !== '' ? (
@@ -57,6 +57,6 @@ export const DocumentFields = React.memo(() => {
editor
)}
{renderEditField()}
- >
+
);
});
diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/index.ts b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/index.ts
index d5ad51ba35839..2958ecd75910f 100644
--- a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/index.ts
+++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/index.ts
@@ -9,3 +9,5 @@ export * from './configuration_form';
export * from './document_fields';
export * from './templates_form';
+
+export * from './multiple_mappings_warning';
diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/multiple_mappings_warning.tsx b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/multiple_mappings_warning.tsx
new file mode 100644
index 0000000000000..507e4dac262ff
--- /dev/null
+++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/multiple_mappings_warning.tsx
@@ -0,0 +1,42 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { i18n } from '@kbn/i18n';
+import { FormattedMessage } from '@kbn/i18n/react';
+import { EuiCallOut, EuiLink } from '@elastic/eui';
+
+import { documentationService } from '../../../services/documentation';
+
+export const MultipleMappingsWarning = () => (
+
+
+
+ {i18n.translate(
+ 'xpack.idxMgmt.mappingsEditor.mappingTypesDetectedCallOutDocumentationLink',
+ {
+ defaultMessage: 'Consider these alternatives to mapping types.',
+ }
+ )}
+
+ ),
+ }}
+ />
+
+
+);
diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/extract_mappings_definition.test.ts b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/extract_mappings_definition.test.ts
new file mode 100644
index 0000000000000..3e38ff5991a8c
--- /dev/null
+++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/extract_mappings_definition.test.ts
@@ -0,0 +1,128 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { extractMappingsDefinition } from './extract_mappings_definition';
+
+describe('extractMappingsDefinition', () => {
+ test('should detect that the mappings has multiple types and return null', () => {
+ const mappings = {
+ type1: {
+ properties: {
+ name1: {
+ type: 'keyword',
+ },
+ },
+ },
+ type2: {
+ properties: {
+ name2: {
+ type: 'keyword',
+ },
+ },
+ },
+ };
+
+ expect(extractMappingsDefinition(mappings)).toBe(null);
+ });
+
+ test('should detect that the mappings has multiple types even when one of the type has not defined any "properties"', () => {
+ const mappings = {
+ type1: {
+ _source: {
+ excludes: [],
+ includes: [],
+ enabled: true,
+ },
+ _routing: {
+ required: false,
+ },
+ },
+ type2: {
+ properties: {
+ name2: {
+ type: 'keyword',
+ },
+ },
+ },
+ };
+
+ expect(extractMappingsDefinition(mappings)).toBe(null);
+ });
+
+ test('should detect that one of the mapping type is invalid and filter it out', () => {
+ const mappings = {
+ type1: {
+ invalidSetting: {
+ excludes: [],
+ includes: [],
+ enabled: true,
+ },
+ _routing: {
+ required: false,
+ },
+ },
+ type2: {
+ properties: {
+ name2: {
+ type: 'keyword',
+ },
+ },
+ },
+ };
+
+ expect(extractMappingsDefinition(mappings)).toBe(mappings.type2);
+ });
+
+ test('should detect that the mappings has one type and return its mapping definition', () => {
+ const mappings = {
+ myType: {
+ _source: {
+ excludes: [],
+ includes: [],
+ enabled: true,
+ },
+ _meta: {},
+ _routing: {
+ required: false,
+ },
+ dynamic: true,
+ properties: {
+ title: {
+ type: 'keyword',
+ },
+ },
+ },
+ };
+
+ expect(extractMappingsDefinition(mappings)).toBe(mappings.myType);
+ });
+
+ test('should detect that the mappings has one type at root level', () => {
+ const mappings = {
+ _source: {
+ excludes: [],
+ includes: [],
+ enabled: true,
+ },
+ _meta: {},
+ _routing: {
+ required: false,
+ },
+ dynamic: true,
+ numeric_detection: false,
+ date_detection: true,
+ dynamic_date_formats: ['strict_date_optional_time'],
+ dynamic_templates: [],
+ properties: {
+ title: {
+ type: 'keyword',
+ },
+ },
+ };
+
+ expect(extractMappingsDefinition(mappings)).toBe(mappings);
+ });
+});
diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/extract_mappings_definition.ts b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/extract_mappings_definition.ts
new file mode 100644
index 0000000000000..eae3c5b15759c
--- /dev/null
+++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/extract_mappings_definition.ts
@@ -0,0 +1,103 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+import { isPlainObject } from 'lodash';
+
+import { GenericObject } from '../types';
+import {
+ validateMappingsConfiguration,
+ mappingsConfigurationSchemaKeys,
+} from './mappings_validator';
+
+const ALLOWED_PARAMETERS = [...mappingsConfigurationSchemaKeys, 'dynamic_templates', 'properties'];
+
+const isMappingDefinition = (obj: GenericObject): boolean => {
+ const areAllKeysValid = Object.keys(obj).every(key => ALLOWED_PARAMETERS.includes(key));
+
+ if (!areAllKeysValid) {
+ return false;
+ }
+
+ const { properties, dynamic_templates: dynamicTemplates, ...mappingsConfiguration } = obj;
+
+ const { errors } = validateMappingsConfiguration(mappingsConfiguration);
+ const isConfigurationValid = errors.length === 0;
+ const isPropertiesValid = properties === undefined || isPlainObject(properties);
+ const isDynamicTemplatesValid = dynamicTemplates === undefined || Array.isArray(dynamicTemplates);
+
+ // If the configuration, the properties and the dynamic templates are valid
+ // we can assume that the mapping is declared at root level (no types)
+ return isConfigurationValid && isPropertiesValid && isDynamicTemplatesValid;
+};
+
+/**
+ * 5.x index templates can be created with multiple types.
+ * e.g.
+ ```
+ const mappings = {
+ type1: {
+ properties: {
+ name1: {
+ type: 'keyword',
+ },
+ },
+ },
+ type2: {
+ properties: {
+ name2: {
+ type: 'keyword',
+ },
+ },
+ },
+ };
+ ```
+ * A mappings can also be declared under an explicit "_doc" property.
+ ```
+ const mappings = {
+ _doc: {
+ _source: {
+ "enabled": false
+ },
+ properties: {
+ name1: {
+ type: 'keyword',
+ },
+ },
+ },
+ };
+ ```
+ * This helpers parse the mappings provided an removes any possible mapping "type" declared
+ *
+ * @param mappings The mappings object to validate
+ */
+export const extractMappingsDefinition = (mappings: GenericObject = {}): GenericObject | null => {
+ if (isMappingDefinition(mappings)) {
+ // No need to go any further
+ return mappings;
+ }
+
+ // At this point there must be one or more type mappings
+ const typedMappings = Object.values(mappings).reduce((acc: GenericObject[], value) => {
+ if (isMappingDefinition(value)) {
+ acc.push(value as GenericObject);
+ }
+ return acc;
+ }, []);
+
+ // If there are no typed mappings found this means that one of the type must did not pass
+ // the "isMappingDefinition()" validation.
+ // In theory this should never happen but let's make sure the UI does not try to load an invalid mapping
+ if (typedMappings.length === 0) {
+ return null;
+ }
+
+ // If there's only one mapping type then we can consume it as if the type doesn't exist.
+ if (typedMappings.length === 1) {
+ return typedMappings[0];
+ }
+
+ // If there's more than one mapping type, then the mappings object isn't usable.
+ return null;
+};
diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/index.ts b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/index.ts
index 1b1c5cc8dc8d4..8cd1bbf0764ab 100644
--- a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/index.ts
+++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/index.ts
@@ -13,3 +13,5 @@ export * from './validators';
export * from './mappings_validator';
export * from './search_fields';
+
+export * from './extract_mappings_definition';
diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/mappings_validator.test.ts b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/mappings_validator.test.ts
index c70462a656e2f..f1e6efb06c649 100644
--- a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/mappings_validator.test.ts
+++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/mappings_validator.test.ts
@@ -3,8 +3,9 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
+import { isPlainObject } from 'lodash';
-import { validateMappings, validateProperties, isObject } from './mappings_validator';
+import { validateMappings, validateProperties } from './mappings_validator';
describe('Mappings configuration validator', () => {
it('should convert non object to empty object', () => {
@@ -12,7 +13,7 @@ describe('Mappings configuration validator', () => {
tests.forEach(testValue => {
const { value, errors } = validateMappings(testValue as any);
- expect(isObject(value)).toBe(true);
+ expect(isPlainObject(value)).toBe(true);
expect(errors).toBe(undefined);
});
});
@@ -76,7 +77,7 @@ describe('Properties validator', () => {
tests.forEach(testValue => {
const { value, errors } = validateProperties(testValue as any);
- expect(isObject(value)).toBe(true);
+ expect(isPlainObject(value)).toBe(true);
expect(errors).toEqual([]);
});
});
diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/mappings_validator.ts b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/mappings_validator.ts
index fff735da2e758..6ccbfeb50dcf4 100644
--- a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/mappings_validator.ts
+++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/mappings_validator.ts
@@ -3,15 +3,16 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
-import { pick } from 'lodash';
+import { pick, isPlainObject } from 'lodash';
import * as t from 'io-ts';
import { ordString } from 'fp-ts/lib/Ord';
import { toArray } from 'fp-ts/lib/Set';
import { isLeft, isRight } from 'fp-ts/lib/Either';
+
import { errorReporter } from './error_reporter';
import { ALL_DATA_TYPES, PARAMETERS_DEFINITION } from '../constants';
import { FieldMeta } from '../types';
-import { getFieldMeta } from '../lib';
+import { getFieldMeta } from './utils';
const ALLOWED_FIELD_PROPERTIES = [
...Object.keys(PARAMETERS_DEFINITION),
@@ -49,8 +50,6 @@ interface GenericObject {
[key: string]: any;
}
-export const isObject = (obj: any) => obj != null && obj.constructor.name === 'Object';
-
const validateFieldType = (type: any): boolean => {
if (typeof type !== 'string') {
return false;
@@ -72,7 +71,7 @@ const validateParameter = (parameter: string, value: any): boolean => {
}
if (parameter === 'properties' || parameter === 'fields') {
- return isObject(value);
+ return isPlainObject(value);
}
const parameterSchema = (PARAMETERS_DEFINITION as any)[parameter]!.schema;
@@ -100,7 +99,7 @@ const stripUnknownOrInvalidParameter = (field: GenericObject): FieldValidatorRes
const parseField = (field: any): FieldValidatorResponse & { meta?: FieldMeta } => {
// Sanitize the input to make sure we are working with an object
- if (!isObject(field)) {
+ if (!isPlainObject(field)) {
return { parametersRemoved: [] };
}
// Make sure the field "type" is valid
@@ -186,7 +185,7 @@ const parseFields = (
*/
export const validateProperties = (properties = {}): PropertiesValidatorResponse => {
// Sanitize the input to make sure we are working with an object
- if (!isObject(properties)) {
+ if (!isPlainObject(properties)) {
return { value: {}, errors: [] };
}
@@ -213,9 +212,9 @@ export const mappingsConfigurationSchema = t.partial({
}),
});
-const mappingsConfigurationSchemaKeys = Object.keys(mappingsConfigurationSchema.props);
+export const mappingsConfigurationSchemaKeys = Object.keys(mappingsConfigurationSchema.props);
-const validateMappingsConfiguration = (
+export const validateMappingsConfiguration = (
mappingsConfiguration: any
): { value: any; errors: MappingsValidationError[] } => {
// Set to keep track of invalid configuration parameters.
@@ -249,7 +248,7 @@ const validateMappingsConfiguration = (
};
export const validateMappings = (mappings: any = {}): MappingsValidatorResponse => {
- if (!isObject(mappings)) {
+ if (!isPlainObject(mappings)) {
return { value: {} };
}
diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/mappings_editor.tsx b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/mappings_editor.tsx
index e3fdf42d889e9..d79a023386e8d 100644
--- a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/mappings_editor.tsx
+++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/mappings_editor.tsx
@@ -4,14 +4,20 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import React, { useMemo, useState } from 'react';
+import React, { useMemo, useState, useEffect } from 'react';
import { i18n } from '@kbn/i18n';
import { EuiSpacer, EuiTabs, EuiTab } from '@elastic/eui';
-import { ConfigurationForm, DocumentFields, TemplatesForm } from './components';
+import {
+ ConfigurationForm,
+ DocumentFields,
+ TemplatesForm,
+ MultipleMappingsWarning,
+} from './components';
import { IndexSettings } from './types';
+import { extractMappingsDefinition } from './lib';
import { State } from './reducer';
-import { MappingsState, Props as MappingsStateProps } from './mappings_state';
+import { MappingsState, Props as MappingsStateProps, Types } from './mappings_state';
import { IndexSettingsProvider } from './index_settings_context';
interface Props {
@@ -25,7 +31,13 @@ type TabName = 'fields' | 'advanced' | 'templates';
export const MappingsEditor = React.memo(({ onUpdate, defaultValue, indexSettings }: Props) => {
const [selectedTab, selectTab] = useState('fields');
- const parsedDefaultValue = useMemo(() => {
+ const { parsedDefaultValue, multipleMappingsDeclared } = useMemo(() => {
+ const mappingsDefinition = extractMappingsDefinition(defaultValue);
+
+ if (mappingsDefinition === null) {
+ return { multipleMappingsDeclared: true };
+ }
+
const {
_source = {},
_meta = {},
@@ -36,9 +48,9 @@ export const MappingsEditor = React.memo(({ onUpdate, defaultValue, indexSetting
dynamic_date_formats,
properties = {},
dynamic_templates,
- } = defaultValue ?? {};
+ } = mappingsDefinition;
- return {
+ const parsed = {
configuration: {
_source,
_meta,
@@ -53,8 +65,21 @@ export const MappingsEditor = React.memo(({ onUpdate, defaultValue, indexSetting
dynamic_templates,
},
};
+
+ return { parsedDefaultValue: parsed, multipleMappingsDeclared: false };
}, [defaultValue]);
+ useEffect(() => {
+ if (multipleMappingsDeclared) {
+ // We set the data getter here as the user won't be able to make any changes
+ onUpdate({
+ getData: () => defaultValue! as Types['Mappings'],
+ validate: () => Promise.resolve(true),
+ isValid: true,
+ });
+ }
+ }, [multipleMappingsDeclared]);
+
const changeTab = async (tab: TabName, state: State) => {
if (selectedTab === 'advanced') {
// When we navigate away we need to submit the form to validate if there are any errors.
@@ -63,7 +88,6 @@ export const MappingsEditor = React.memo(({ onUpdate, defaultValue, indexSetting
if (!isConfigurationFormValid) {
/**
* Don't navigate away from the tab if there are errors in the form.
- * For now there is no need to display a CallOut as the form can never be invalid.
*/
return;
}
@@ -79,51 +103,57 @@ export const MappingsEditor = React.memo(({ onUpdate, defaultValue, indexSetting
};
return (
-
-
- {({ state }) => {
- const tabToContentMap = {
- fields: ,
- templates: ,
- advanced: ,
- };
-
- return (
-
-
- changeTab('fields', state)}
- isSelected={selectedTab === 'fields'}
- >
- {i18n.translate('xpack.idxMgmt.mappingsEditor.fieldsTabLabel', {
- defaultMessage: 'Mapped fields',
- })}
-
- changeTab('templates', state)}
- isSelected={selectedTab === 'templates'}
- >
- {i18n.translate('xpack.idxMgmt.mappingsEditor.templatesTabLabel', {
- defaultMessage: 'Dynamic templates',
- })}
-
- changeTab('advanced', state)}
- isSelected={selectedTab === 'advanced'}
- >
- {i18n.translate('xpack.idxMgmt.mappingsEditor.advancedTabLabel', {
- defaultMessage: 'Advanced options',
- })}
-
-
-
-
-
- {tabToContentMap[selectedTab]}
-
- );
- }}
-
-
+
+ {multipleMappingsDeclared ? (
+
+ ) : (
+
+
+ {({ state }) => {
+ const tabToContentMap = {
+ fields: ,
+ templates: ,
+ advanced: ,
+ };
+
+ return (
+
+
+ changeTab('fields', state)}
+ isSelected={selectedTab === 'fields'}
+ >
+ {i18n.translate('xpack.idxMgmt.mappingsEditor.fieldsTabLabel', {
+ defaultMessage: 'Mapped fields',
+ })}
+
+ changeTab('templates', state)}
+ isSelected={selectedTab === 'templates'}
+ >
+ {i18n.translate('xpack.idxMgmt.mappingsEditor.templatesTabLabel', {
+ defaultMessage: 'Dynamic templates',
+ })}
+
+ changeTab('advanced', state)}
+ isSelected={selectedTab === 'advanced'}
+ >
+ {i18n.translate('xpack.idxMgmt.mappingsEditor.advancedTabLabel', {
+ defaultMessage: 'Advanced options',
+ })}
+
+
+
+
+
+ {tabToContentMap[selectedTab]}
+
+ );
+ }}
+
+
+ )}
+
);
});
diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/types.ts b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/types.ts
index 5d9c15caf9cd9..dbbffe5a0bd31 100644
--- a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/types.ts
+++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/types.ts
@@ -287,3 +287,7 @@ export interface SearchMetadata {
*/
stringMatch: string | null;
}
+
+export interface GenericObject {
+ [key: string]: any;
+}
diff --git a/x-pack/legacy/plugins/index_management/public/app/services/documentation.ts b/x-pack/legacy/plugins/index_management/public/app/services/documentation.ts
index f63dc622453fe..9bf0d983df161 100644
--- a/x-pack/legacy/plugins/index_management/public/app/services/documentation.ts
+++ b/x-pack/legacy/plugins/index_management/public/app/services/documentation.ts
@@ -181,6 +181,10 @@ class DocumentationService {
return `${this.esDocsBase}/index-options.html`;
}
+ public getAlternativeToMappingTypesLink() {
+ return `${this.esDocsBase}/removal-of-types.html#_alternatives_to_mapping_types`;
+ }
+
public getJoinMultiLevelsPerformanceLink() {
return `${this.esDocsBase}/parent-join.html#_parent_join_and_performance`;
}