-
- {i18n.translate('xpack.idxMgmt.mappingsEditor.termVectorFieldWarningMessage', {
+
-
+ }
+ )}
+ />
>
)}
>
diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/create_field.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/create_field.tsx
index a8170b1d59fbb..cff2b9af4fd10 100644
--- a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/create_field.tsx
+++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/create_field.tsx
@@ -14,15 +14,17 @@ import {
EuiFlexGroup,
EuiFlexItem,
EuiOutsideClickDetector,
+ EuiSpacer,
} from '@elastic/eui';
import { useForm, Form, FormDataProvider } from '../../../../shared_imports';
-import { EUI_SIZE } from '../../../../constants';
+import { EUI_SIZE, TYPE_DEFINITION } from '../../../../constants';
import { useDispatch } from '../../../../mappings_state_context';
import { fieldSerializer } from '../../../../lib';
-import { Field, NormalizedFields } from '../../../../types';
+import { Field, NormalizedFields, MainType } from '../../../../types';
import { NameParameter, TypeParameter, SubTypeParameter } from '../../field_parameters';
-import { getParametersFormForType } from './required_parameters_forms';
+import { FieldBetaBadge } from '../field_beta_badge';
+import { getRequiredParametersFormForType } from './required_parameters_forms';
const formWrapper = (props: any) =>
;
@@ -195,18 +197,27 @@ export const CreateField = React.memo(function CreateFieldComponent({
{({ type, subType }) => {
- const ParametersForm = getParametersFormForType(
+ const RequiredParametersForm = getRequiredParametersFormForType(
type?.[0].value,
subType?.[0].value
);
- if (!ParametersForm) {
+ if (!RequiredParametersForm) {
return null;
}
+ const typeDefinition = TYPE_DEFINITION[type?.[0].value as MainType];
+
return (
-
+ {typeDefinition.isBeta ? (
+ <>
+
+
+ >
+ ) : null}
+
+
);
}}
diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/index.ts b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/index.ts
index 1112bf99713ed..5c04b2fbb336c 100644
--- a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/index.ts
+++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/index.ts
@@ -11,6 +11,7 @@ import { AliasTypeRequiredParameters } from './alias_type';
import { TokenCountTypeRequiredParameters } from './token_count_type';
import { ScaledFloatTypeRequiredParameters } from './scaled_float_type';
import { DenseVectorRequiredParameters } from './dense_vector_type';
+import { RuntimeTypeRequiredParameters } from './runtime_type';
export interface ComponentProps {
allFields: NormalizedFields['byId'];
@@ -21,9 +22,10 @@ const typeToParametersFormMap: { [key in DataType]?: ComponentType } = {
token_count: TokenCountTypeRequiredParameters,
scaled_float: ScaledFloatTypeRequiredParameters,
dense_vector: DenseVectorRequiredParameters,
+ runtime: RuntimeTypeRequiredParameters,
};
-export const getParametersFormForType = (
+export const getRequiredParametersFormForType = (
type: MainType,
subType?: SubType
): ComponentType | undefined =>
diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/runtime_type.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/runtime_type.tsx
new file mode 100644
index 0000000000000..54907295f8a15
--- /dev/null
+++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/create_field/required_parameters_forms/runtime_type.tsx
@@ -0,0 +1,18 @@
+/*
+ * 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 { RuntimeTypeParameter, PainlessScriptParameter } from '../../../field_parameters';
+
+export const RuntimeTypeRequiredParameters = () => {
+ return (
+ <>
+
+
+ >
+ );
+};
diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/edit_field_header_form.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/edit_field_header_form.tsx
index 3b55c5ac076c2..e91a666cc4221 100644
--- a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/edit_field_header_form.tsx
+++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/edit_field_header_form.tsx
@@ -5,12 +5,13 @@
*/
import React from 'react';
-import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
+import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui';
import { FormDataProvider } from '../../../../shared_imports';
-import { MainType, SubType, Field } from '../../../../types';
+import { MainType, SubType, Field, DataTypeDefinition } from '../../../../types';
import { TYPE_DEFINITION } from '../../../../constants';
import { NameParameter, TypeParameter, SubTypeParameter } from '../../field_parameters';
+import { FieldBetaBadge } from '../field_beta_badge';
import { FieldDescriptionSection } from './field_description_section';
interface Props {
@@ -19,6 +20,25 @@ interface Props {
isMultiField: boolean;
}
+const getTypeDefinition = (type: MainType, subType: SubType): DataTypeDefinition | undefined => {
+ if (!type) {
+ return;
+ }
+
+ const typeDefinition = TYPE_DEFINITION[type];
+ const hasSubType = typeDefinition.subTypes !== undefined;
+
+ if (hasSubType) {
+ if (subType) {
+ return TYPE_DEFINITION[subType];
+ }
+
+ return;
+ }
+
+ return typeDefinition;
+};
+
export const EditFieldHeaderForm = React.memo(
({ defaultValue, isRootLevelField, isMultiField }: Props) => {
return (
@@ -56,27 +76,29 @@ export const EditFieldHeaderForm = React.memo(
{/* Field description */}
-
-
- {({ type, subType }) => {
- if (!type) {
- return null;
- }
- const typeDefinition = TYPE_DEFINITION[type[0].value as MainType];
- const hasSubType = typeDefinition.subTypes !== undefined;
-
- if (hasSubType) {
- if (subType) {
- const subTypeDefinition = TYPE_DEFINITION[subType as SubType];
- return (subTypeDefinition?.description?.() as JSX.Element) ?? null;
- }
- return null;
- }
+
+ {({ type, subType }) => {
+ const typeDefinition = getTypeDefinition(
+ type[0].value as MainType,
+ subType && (subType[0].value as SubType)
+ );
+ const description = (typeDefinition?.description?.() as JSX.Element) ?? null;
- return typeDefinition.description?.() as JSX.Element;
- }}
-
-
+ return (
+ <>
+
+
+ {typeDefinition?.isBeta && }
+
+
+
+
+ {description}
+
+ >
+ );
+ }}
+
>
);
}
diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/field_description_section.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/field_description_section.tsx
index 2040d7f40d5cb..2301f7a47bf2f 100644
--- a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/field_description_section.tsx
+++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/edit_field/field_description_section.tsx
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
import React from 'react';
-import { EuiSpacer, EuiText } from '@elastic/eui';
+import { EuiText } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
interface Props {
@@ -19,7 +19,6 @@ export const FieldDescriptionSection = ({ children, isMultiField }: Props) => {
return (
-
{children}
diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_beta_badge.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_beta_badge.tsx
new file mode 100644
index 0000000000000..99c725e8a00b3
--- /dev/null
+++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_beta_badge.tsx
@@ -0,0 +1,21 @@
+/*
+ * 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 { EuiBetaBadge } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+
+export const FieldBetaBadge = () => {
+ const betaText = i18n.translate('xpack.idxMgmt.mappingsEditor.fieldBetaBadgeLabel', {
+ defaultMessage: 'Beta',
+ });
+
+ const tooltipText = i18n.translate('xpack.idxMgmt.mappingsEditor.fieldBetaBadgeTooltip', {
+ defaultMessage: 'This field type is not GA. Please help us by reporting any bugs.',
+ });
+
+ return ;
+};
diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/index.ts b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/index.ts
index 6b092c5561b3b..4d36b4dd2578d 100644
--- a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/index.ts
+++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/index.ts
@@ -31,6 +31,7 @@ import { JoinType } from './join_type';
import { HistogramType } from './histogram_type';
import { ConstantKeywordType } from './constant_keyword_type';
import { RankFeatureType } from './rank_feature_type';
+import { RuntimeType } from './runtime_type';
import { WildcardType } from './wildcard_type';
import { PointType } from './point_type';
@@ -60,6 +61,7 @@ const typeToParametersFormMap: { [key in DataType]?: ComponentType } = {
histogram: HistogramType,
constant_keyword: ConstantKeywordType,
rank_feature: RankFeatureType,
+ runtime: RuntimeType,
wildcard: WildcardType,
point: PointType,
};
diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/runtime_type.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/runtime_type.tsx
new file mode 100644
index 0000000000000..dcf5a74e0e304
--- /dev/null
+++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/runtime_type.tsx
@@ -0,0 +1,19 @@
+/*
+ * 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 { RuntimeTypeParameter, PainlessScriptParameter } from '../../field_parameters';
+import { BasicParametersSection } from '../edit_field';
+
+export const RuntimeType = () => {
+ return (
+
+
+
+
+ );
+};
diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/fields_list_item.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/fields_list_item.tsx
index 4ab0ea0fb355b..1939f09fa6762 100644
--- a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/fields_list_item.tsx
+++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/fields_list_item.tsx
@@ -16,7 +16,7 @@ import {
import { i18n } from '@kbn/i18n';
import { NormalizedField, NormalizedFields } from '../../../types';
-import { getTypeLabelFromType } from '../../../lib';
+import { getTypeLabelFromField } from '../../../lib';
import { CHILD_FIELD_INDENT_SIZE, LEFT_PADDING_SIZE_FIELD_ITEM_WRAPPER } from '../../../constants';
import { FieldsList } from './fields_list';
@@ -67,6 +67,7 @@ function FieldListItemComponent(
isExpanded,
path,
} = field;
+
// When there aren't any "child" fields (the maxNestedDepth === 0), there is no toggle icon on the left of any field.
// For that reason, we need to compensate and substract some indent to left align on the page.
const substractIndentAmount = maxNestedDepth === 0 ? CHILD_FIELD_INDENT_SIZE * 0.5 : 0;
@@ -280,10 +281,10 @@ function FieldListItemComponent(
? i18n.translate('xpack.idxMgmt.mappingsEditor.multiFieldBadgeLabel', {
defaultMessage: '{dataType} multi-field',
values: {
- dataType: getTypeLabelFromType(source.type),
+ dataType: getTypeLabelFromField(source),
},
})
- : getTypeLabelFromType(source.type)}
+ : getTypeLabelFromField(source)}
diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/search_fields/search_result_item.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/search_fields/search_result_item.tsx
index a2d9a50f28394..a4cc4b4776e2b 100644
--- a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/search_fields/search_result_item.tsx
+++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/search_fields/search_result_item.tsx
@@ -11,7 +11,7 @@ import { i18n } from '@kbn/i18n';
import { SearchResult } from '../../../types';
import { TYPE_DEFINITION } from '../../../constants';
import { useDispatch } from '../../../mappings_state_context';
-import { getTypeLabelFromType } from '../../../lib';
+import { getTypeLabelFromField } from '../../../lib';
import { DeleteFieldProvider } from '../fields/delete_field_provider';
interface Props {
@@ -121,7 +121,7 @@ export const SearchResultItem = React.memo(function FieldListItemFlatComponent({
dataType: TYPE_DEFINITION[source.type].label,
},
})
- : getTypeLabelFromType(source.type)}
+ : getTypeLabelFromField(source)}
diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/constants/data_types_definition.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/constants/data_types_definition.tsx
index 293ae56d57ace..7bcd8f32f1a7d 100644
--- a/x-pack/plugins/index_management/public/application/components/mappings_editor/constants/data_types_definition.tsx
+++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/constants/data_types_definition.tsx
@@ -13,6 +13,25 @@ import { documentationService } from '../../../services/documentation';
import { MainType, SubType, DataType, DataTypeDefinition } from '../types';
export const TYPE_DEFINITION: { [key in DataType]: DataTypeDefinition } = {
+ runtime: {
+ value: 'runtime',
+ isBeta: true,
+ label: i18n.translate('xpack.idxMgmt.mappingsEditor.dataType.runtimeFieldDescription', {
+ defaultMessage: 'Runtime',
+ }),
+ // TODO: Add this once the page exists.
+ // documentation: {
+ // main: '/runtime_field.html',
+ // },
+ description: () => (
+
+
+
+ ),
+ },
text: {
value: 'text',
label: i18n.translate('xpack.idxMgmt.mappingsEditor.dataType.textDescription', {
@@ -896,6 +915,7 @@ export const MAIN_TYPES: MainType[] = [
'range',
'rank_feature',
'rank_features',
+ 'runtime',
'search_as_you_type',
'shape',
'text',
diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/constants/field_options.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/constants/field_options.tsx
index d16bf68b80e5d..25fdac5089b86 100644
--- a/x-pack/plugins/index_management/public/application/components/mappings_editor/constants/field_options.tsx
+++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/constants/field_options.tsx
@@ -18,6 +18,7 @@ export const TYPE_NOT_ALLOWED_MULTIFIELD: DataType[] = [
'object',
'nested',
'alias',
+ 'runtime',
];
export const FIELD_TYPES_OPTIONS = Object.entries(MAIN_DATA_TYPE_DEFINITION).map(
@@ -27,6 +28,35 @@ export const FIELD_TYPES_OPTIONS = Object.entries(MAIN_DATA_TYPE_DEFINITION).map
})
) as ComboBoxOption[];
+export const RUNTIME_FIELD_OPTIONS = [
+ {
+ label: 'Keyword',
+ value: 'keyword',
+ },
+ {
+ label: 'Long',
+ value: 'long',
+ },
+ {
+ label: 'Double',
+ value: 'double',
+ },
+ {
+ label: 'Date',
+ value: 'date',
+ },
+ {
+ label: 'IP',
+ value: 'ip',
+ },
+ {
+ label: 'Boolean',
+ value: 'boolean',
+ },
+] as ComboBoxOption[];
+
+export const RUNTIME_FIELD_TYPES = ['keyword', 'long', 'double', 'date', 'ip', 'boolean'] as const;
+
interface SuperSelectOptionConfig {
inputDisplay: string;
dropdownDisplay: JSX.Element;
diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/constants/parameters_definition.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/constants/parameters_definition.tsx
index 4ffedc8ca114d..4c9786d88bfa2 100644
--- a/x-pack/plugins/index_management/public/application/components/mappings_editor/constants/parameters_definition.tsx
+++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/constants/parameters_definition.tsx
@@ -20,6 +20,7 @@ import {
import {
AliasOption,
DataType,
+ RuntimeType,
ComboBoxOption,
ParameterName,
ParameterDefinition,
@@ -27,6 +28,7 @@ import {
import { documentationService } from '../../../services/documentation';
import { INDEX_DEFAULT } from './default_values';
import { TYPE_DEFINITION } from './data_types_definition';
+import { RUNTIME_FIELD_OPTIONS } from './field_options';
const { toInt } = fieldFormatters;
const { emptyField, containsCharsField, numberGreaterThanField, isJsonField } = fieldValidators;
@@ -185,6 +187,52 @@ export const PARAMETERS_DEFINITION: { [key in ParameterName]: ParameterDefinitio
},
schema: t.string,
},
+ runtime_type: {
+ fieldConfig: {
+ type: FIELD_TYPES.COMBO_BOX,
+ label: i18n.translate('xpack.idxMgmt.mappingsEditor.parameters.runtimeTypeLabel', {
+ defaultMessage: 'Type',
+ }),
+ defaultValue: 'keyword',
+ deserializer: (fieldType: RuntimeType | undefined) => {
+ if (typeof fieldType === 'string' && Boolean(fieldType)) {
+ const label =
+ RUNTIME_FIELD_OPTIONS.find(({ value }) => value === fieldType)?.label ?? fieldType;
+ return [
+ {
+ label,
+ value: fieldType,
+ },
+ ];
+ }
+ return [];
+ },
+ serializer: (value: ComboBoxOption[]) => (value.length === 0 ? '' : value[0].value),
+ },
+ schema: t.string,
+ },
+ script: {
+ fieldConfig: {
+ defaultValue: '',
+ type: FIELD_TYPES.TEXT,
+ label: i18n.translate('xpack.idxMgmt.mappingsEditor.parameters.painlessScriptLabel', {
+ defaultMessage: 'Script',
+ }),
+ validations: [
+ {
+ validator: emptyField(
+ i18n.translate(
+ 'xpack.idxMgmt.mappingsEditor.parameters.validations.scriptIsRequiredErrorMessage',
+ {
+ defaultMessage: 'Script must emit() a value.',
+ }
+ )
+ ),
+ },
+ ],
+ },
+ schema: t.string,
+ },
store: {
fieldConfig: {
type: FIELD_TYPES.CHECKBOX,
diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/lib/index.ts b/x-pack/plugins/index_management/public/application/components/mappings_editor/lib/index.ts
index 8cd1bbf0764ab..0a59cafdcef47 100644
--- a/x-pack/plugins/index_management/public/application/components/mappings_editor/lib/index.ts
+++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/lib/index.ts
@@ -4,7 +4,27 @@
* you may not use this file except in compliance with the Elastic License.
*/
-export * from './utils';
+export {
+ getUniqueId,
+ getChildFieldsName,
+ getFieldMeta,
+ getTypeLabelFromField,
+ getFieldConfig,
+ getTypeMetaFromSource,
+ normalize,
+ deNormalize,
+ updateFieldsPathAfterFieldNameChange,
+ getAllChildFields,
+ getAllDescendantAliases,
+ getFieldAncestors,
+ filterTypesForMultiField,
+ filterTypesForNonRootFields,
+ getMaxNestedDepth,
+ buildFieldTreeFromIds,
+ shouldDeleteChildFieldsAfterTypeChange,
+ canUseMappingsEditor,
+ stripUndefinedValues,
+} from './utils';
export * from './serializers';
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 bc495b05e07b7..e1988c071314e 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
@@ -4,9 +4,12 @@
* you may not use this file except in compliance with the Elastic License.
*/
-jest.mock('../constants', () => ({ MAIN_DATA_TYPE_DEFINITION: {} }));
+jest.mock('../constants', () => {
+ const { TYPE_DEFINITION } = jest.requireActual('../constants');
+ return { MAIN_DATA_TYPE_DEFINITION: {}, TYPE_DEFINITION };
+});
-import { stripUndefinedValues } from './utils';
+import { stripUndefinedValues, getTypeLabelFromField } from './utils';
describe('utils', () => {
describe('stripUndefinedValues()', () => {
@@ -53,4 +56,46 @@ describe('utils', () => {
expect(stripUndefinedValues(dataIN)).toEqual(dataOUT);
});
});
+
+ describe('getTypeLabelFromField()', () => {
+ test('returns an unprocessed label for non-runtime fields', () => {
+ expect(
+ getTypeLabelFromField({
+ name: 'testField',
+ type: 'keyword',
+ })
+ ).toBe('Keyword');
+ });
+
+ test(`returns a label prepended with 'Other' for unrecognized fields`, () => {
+ expect(
+ getTypeLabelFromField({
+ name: 'testField',
+ // @ts-ignore
+ type: 'hyperdrive',
+ })
+ ).toBe('Other: hyperdrive');
+ });
+
+ test("returns a label prepended with 'Runtime' for runtime fields", () => {
+ expect(
+ getTypeLabelFromField({
+ name: 'testField',
+ type: 'runtime',
+ runtime_type: 'keyword',
+ })
+ ).toBe('Runtime Keyword');
+ });
+
+ test("returns a label prepended with 'Runtime Other' for unrecognized runtime fields", () => {
+ expect(
+ getTypeLabelFromField({
+ name: 'testField',
+ type: 'runtime',
+ // @ts-ignore
+ runtime_type: 'hyperdrive',
+ })
+ ).toBe('Runtime Other: hyperdrive');
+ });
+ });
});
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 8b3ff60005305..d96f20683216a 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
@@ -71,8 +71,23 @@ export const getFieldMeta = (field: Field, isMultiField?: boolean): FieldMeta =>
};
};
-export const getTypeLabelFromType = (type: DataType) =>
- TYPE_DEFINITION[type] ? TYPE_DEFINITION[type].label : `${TYPE_DEFINITION.other.label}: ${type}`;
+const getTypeLabel = (type?: DataType): string => {
+ return type && TYPE_DEFINITION[type]
+ ? TYPE_DEFINITION[type].label
+ : `${TYPE_DEFINITION.other.label}: ${type}`;
+};
+
+export const getTypeLabelFromField = (field: Field) => {
+ const { type, runtime_type: runtimeType } = field;
+ const typeLabel = getTypeLabel(type);
+
+ if (type === 'runtime') {
+ const runtimeTypeLabel = getTypeLabel(runtimeType);
+ return `${typeLabel} ${runtimeTypeLabel}`;
+ }
+
+ return typeLabel;
+};
export const getFieldConfig = (
param: ParameterName,
diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/shared_imports.ts b/x-pack/plugins/index_management/public/application/components/mappings_editor/shared_imports.ts
index 097d039527950..54b2486108183 100644
--- a/x-pack/plugins/index_management/public/application/components/mappings_editor/shared_imports.ts
+++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/shared_imports.ts
@@ -51,3 +51,5 @@ export {
OnJsonEditorUpdateHandler,
GlobalFlyout,
} from '../../../../../../../src/plugins/es_ui_shared/public';
+
+export { CodeEditor } from '../../../../../../../src/plugins/kibana_react/public';
diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/types/document_fields.ts b/x-pack/plugins/index_management/public/application/components/mappings_editor/types/document_fields.ts
index ca38a8d1e6c33..48282abd1d799 100644
--- a/x-pack/plugins/index_management/public/application/components/mappings_editor/types/document_fields.ts
+++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/types/document_fields.ts
@@ -8,7 +8,7 @@ import { ReactNode } from 'react';
import { GenericObject } from './mappings_editor';
import { FieldConfig } from '../shared_imports';
-import { PARAMETERS_DEFINITION } from '../constants';
+import { PARAMETERS_DEFINITION, RUNTIME_FIELD_TYPES } from '../constants';
export interface DataTypeDefinition {
label: string;
@@ -19,6 +19,7 @@ export interface DataTypeDefinition {
};
subTypes?: { label: string; types: SubType[] };
description?: () => ReactNode;
+ isBeta?: boolean;
}
export interface ParameterDefinition {
@@ -35,6 +36,7 @@ export interface ParameterDefinition {
}
export type MainType =
+ | 'runtime'
| 'text'
| 'keyword'
| 'numeric'
@@ -73,6 +75,8 @@ export type SubType = NumericType | RangeType;
export type DataType = MainType | SubType;
+export type RuntimeType = typeof RUNTIME_FIELD_TYPES[number];
+
export type NumericType =
| 'long'
| 'integer'
@@ -151,6 +155,8 @@ export type ParameterName =
| 'depth_limit'
| 'relations'
| 'max_shingle_size'
+ | 'runtime_type'
+ | 'script'
| 'value'
| 'meta';
@@ -168,6 +174,7 @@ export interface Fields {
interface FieldBasic {
name: string;
type: DataType;
+ runtime_type?: DataType;
subType?: SubType;
properties?: { [key: string]: Omit };
fields?: { [key: string]: Omit };
diff --git a/x-pack/plugins/index_management/public/application/index.tsx b/x-pack/plugins/index_management/public/application/index.tsx
index f881c2e01cefc..d8b5da8361c43 100644
--- a/x-pack/plugins/index_management/public/application/index.tsx
+++ b/x-pack/plugins/index_management/public/application/index.tsx
@@ -11,7 +11,7 @@ import { render, unmountComponentAtNode } from 'react-dom';
import { CoreStart } from '../../../../../src/core/public';
import { API_BASE_PATH } from '../../common';
-import { GlobalFlyout } from '../shared_imports';
+import { createKibanaReactContext, GlobalFlyout } from '../shared_imports';
import { AppContextProvider, AppDependencies } from './app_context';
import { App } from './app';
@@ -30,7 +30,12 @@ export const renderApp = (
const { i18n, docLinks, notifications, application } = core;
const { Context: I18nContext } = i18n;
- const { services, history, setBreadcrumbs } = dependencies;
+ const { services, history, setBreadcrumbs, uiSettings } = dependencies;
+
+ // uiSettings is required by the CodeEditor component used to edit runtime field Painless scripts.
+ const { Provider: KibanaReactContextProvider } = createKibanaReactContext({
+ uiSettings,
+ });
const componentTemplateProviderValues = {
httpClient: services.httpService.httpClient,
@@ -44,17 +49,19 @@ export const renderApp = (
render(
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
,
elem
);
diff --git a/x-pack/plugins/index_management/public/application/mount_management_section.ts b/x-pack/plugins/index_management/public/application/mount_management_section.ts
index 6257b68430cf0..f7b728c875762 100644
--- a/x-pack/plugins/index_management/public/application/mount_management_section.ts
+++ b/x-pack/plugins/index_management/public/application/mount_management_section.ts
@@ -41,6 +41,7 @@ export async function mountManagementSection(
fatalErrors,
application,
chrome: { docTitle },
+ uiSettings,
} = core;
docTitle.change(PLUGIN.getI18nName(i18n));
@@ -60,6 +61,7 @@ export async function mountManagementSection(
services,
history,
setBreadcrumbs,
+ uiSettings,
};
const unmountAppCallback = renderApp(element, { core, dependencies: appDependencies });
diff --git a/x-pack/plugins/index_management/public/shared_imports.ts b/x-pack/plugins/index_management/public/shared_imports.ts
index d58545768732e..acb3eb512e2c1 100644
--- a/x-pack/plugins/index_management/public/shared_imports.ts
+++ b/x-pack/plugins/index_management/public/shared_imports.ts
@@ -44,4 +44,7 @@ export {
export { isJSON } from '../../../../src/plugins/es_ui_shared/static/validators/string';
-export { reactRouterNavigate } from '../../../../src/plugins/kibana_react/public';
+export {
+ createKibanaReactContext,
+ reactRouterNavigate,
+} from '../../../../src/plugins/kibana_react/public';