diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/constant_keyword_type.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/constant_keyword_type.tsx new file mode 100644 index 0000000000000..4c02171d49eec --- /dev/null +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/constant_keyword_type.tsx @@ -0,0 +1,82 @@ +/* + * 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, { FunctionComponent } from 'react'; +import { i18n } from '@kbn/i18n'; + +import { documentationService } from '../../../../../../services/documentation'; +import { UseField, Field, JsonEditorField } from '../../../../shared_imports'; +import { getFieldConfig } from '../../../../lib'; +import { NormalizedField } from '../../../../types'; +import { AdvancedParametersSection, EditFieldFormRow, BasicParametersSection } from '../edit_field'; + +interface Props { + field: NormalizedField; +} + +export const ConstantKeywordType: FunctionComponent = ({ field }) => { + return ( + <> + + {/* Value field */} + + + + + + + {/* Meta field */} + + + + + + ); +}; 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 d84d9c6ea40cf..0cf921f66451b 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 @@ -28,6 +28,7 @@ import { ObjectType } from './object_type'; import { OtherType } from './other_type'; import { NestedType } from './nested_type'; import { JoinType } from './join_type'; +import { ConstantKeywordType } from './constant_keyword_type'; import { RankFeatureType } from './rank_feature_type'; import { WildcardType } from './wildcard_type'; @@ -54,6 +55,7 @@ const typeToParametersFormMap: { [key in DataType]?: ComponentType } = { other: OtherType, nested: NestedType, join: JoinType, + constant_keyword: ConstantKeywordType, rank_feature: RankFeatureType, wildcard: WildcardType, }; 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 a8844c7a9b270..18d9c637bd45b 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 @@ -71,6 +71,26 @@ export const TYPE_DEFINITION: { [key in DataType]: DataTypeDefinition } = {

), }, + constant_keyword: { + value: 'constant_keyword', + label: i18n.translate('xpack.idxMgmt.mappingsEditor.dataType.constantKeywordDescription', { + defaultMessage: 'Constant keyword', + }), + documentation: { + main: '/keyword.html#constant-keyword-field-type', + }, + description: () => ( +

+ {'keyword'}, + }} + /> +

+ ), + }, numeric: { value: 'numeric', label: i18n.translate('xpack.idxMgmt.mappingsEditor.dataType.numericDescription', { @@ -822,6 +842,7 @@ export const MAIN_TYPES: MainType[] = [ 'binary', 'boolean', 'completion', + 'constant_keyword', 'date', 'date_nanos', 'dense_vector', 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 f2148f1f657a6..fd17dc1b8fd1e 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 @@ -29,7 +29,7 @@ import { INDEX_DEFAULT } from './default_values'; import { TYPE_DEFINITION } from './data_types_definition'; const { toInt } = fieldFormatters; -const { emptyField, containsCharsField, numberGreaterThanField } = fieldValidators; +const { emptyField, containsCharsField, numberGreaterThanField, isJsonField } = fieldValidators; const commonErrorMessages = { smallerThanZero: i18n.translate( @@ -404,6 +404,88 @@ export const PARAMETERS_DEFINITION: { [key in ParameterName]: ParameterDefinitio }, schema: t.string, }, + value: { + fieldConfig: { + defaultValue: '', + type: FIELD_TYPES.TEXT, + label: i18n.translate('xpack.idxMgmt.mappingsEditor.parameters.valueLabel', { + defaultMessage: 'Value', + }), + }, + schema: t.string, + }, + meta: { + fieldConfig: { + defaultValue: '', + label: i18n.translate('xpack.idxMgmt.mappingsEditor.parameters.metaLabel', { + defaultMessage: 'Metadata', + }), + helpText: ( + {JSON.stringify({ arbitrary_key: 'anything_goes' })}, + }} + /> + ), + validations: [ + { + validator: isJsonField( + i18n.translate('xpack.idxMgmt.mappingsEditor.parameters.metaFieldEditorJsonError', { + defaultMessage: 'Invalid JSON.', + }), + { allowEmptyString: true } + ), + }, + { + validator: ({ value }: ValidationFuncArg) => { + if (typeof value !== 'string' || value.trim() === '') { + return; + } + + const json = JSON.parse(value); + const valuesAreNotString = Object.values(json).some((v) => typeof v !== 'string'); + + if (Array.isArray(json)) { + return { + message: i18n.translate( + 'xpack.idxMgmt.mappingsEditor.parameters.metaFieldEditorArraysNotAllowedError', + { + defaultMessage: 'Arrays are not allowed.', + } + ), + }; + } else if (valuesAreNotString) { + return { + message: i18n.translate( + 'xpack.idxMgmt.mappingsEditor.parameters.metaFieldEditorOnlyStringValuesAllowedError', + { + defaultMessage: 'Values must be a string.', + } + ), + }; + } + }, + }, + ], + deserializer: (value: any) => { + if (value === '') { + return value; + } + return JSON.stringify(value, null, 2); + }, + serializer: (value: string) => { + const parsed = JSON.parse(value); + // If an empty object was passed, strip out this value entirely. + if (!Object.keys(parsed).length) { + return undefined; + } + return parsed; + }, + }, + schema: t.any, + }, max_input_length: { fieldConfig: { defaultValue: 50, 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 fd0e4ed32bfe8..c2a44152ae1ee 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 @@ -59,6 +59,7 @@ export type MainType = | 'geo_point' | 'geo_shape' | 'token_count' + | 'constant_keyword' | 'wildcard' /** * 'other' is a special type that only exists inside of MappingsEditor as a placeholder @@ -146,7 +147,9 @@ export type ParameterName = | 'dims' | 'depth_limit' | 'relations' - | 'max_shingle_size'; + | 'max_shingle_size' + | 'value' + | 'meta'; export interface Parameter { fieldConfig: FieldConfig; diff --git a/x-pack/plugins/index_management/public/application/services/documentation.ts b/x-pack/plugins/index_management/public/application/services/documentation.ts index afc9c76f1afbe..c52b958d94ae1 100644 --- a/x-pack/plugins/index_management/public/application/services/documentation.ts +++ b/x-pack/plugins/index_management/public/application/services/documentation.ts @@ -123,6 +123,10 @@ class DocumentationService { return `${this.esDocsBase}/ignore-malformed.html`; } + public getMetaLink() { + return `${this.esDocsBase}/mapping-field-meta.html`; + } + public getFormatLink() { return `${this.esDocsBase}/mapping-date-format.html`; }