Skip to content

Commit 78e8a1e

Browse files
[Mappings editor] Add support for point field type (#77543)
1 parent be7ae56 commit 78e8a1e

File tree

9 files changed

+335
-10
lines changed

9 files changed

+335
-10
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
import { act } from 'react-dom/test-utils';
7+
8+
import { componentHelpers, MappingsEditorTestBed } from '../helpers';
9+
10+
const { setup, getMappingsEditorDataFactory } = componentHelpers.mappingsEditor;
11+
12+
// Parameters automatically added to the point datatype when saved (with the default values)
13+
export const defaultPointParameters = {
14+
type: 'point',
15+
ignore_malformed: false,
16+
ignore_z_value: true,
17+
};
18+
19+
describe('Mappings editor: point datatype', () => {
20+
/**
21+
* Variable to store the mappings data forwarded to the consumer component
22+
*/
23+
let data: any;
24+
let onChangeHandler: jest.Mock = jest.fn();
25+
let getMappingsEditorData = getMappingsEditorDataFactory(onChangeHandler);
26+
let testBed: MappingsEditorTestBed;
27+
28+
beforeAll(() => {
29+
jest.useFakeTimers();
30+
});
31+
32+
afterAll(() => {
33+
jest.useRealTimers();
34+
});
35+
36+
beforeEach(() => {
37+
onChangeHandler = jest.fn();
38+
getMappingsEditorData = getMappingsEditorDataFactory(onChangeHandler);
39+
});
40+
41+
test('initial view and default parameters values', async () => {
42+
const defaultMappings = {
43+
properties: {
44+
myField: {
45+
type: 'point',
46+
},
47+
},
48+
};
49+
50+
const updatedMappings = { ...defaultMappings };
51+
52+
await act(async () => {
53+
testBed = setup({ value: defaultMappings, onChange: onChangeHandler });
54+
});
55+
testBed.component.update();
56+
57+
const {
58+
component,
59+
actions: { startEditField, updateFieldAndCloseFlyout },
60+
} = testBed;
61+
62+
// Open the flyout to edit the field
63+
await startEditField('myField');
64+
65+
// Save the field and close the flyout
66+
await updateFieldAndCloseFlyout();
67+
68+
// It should have the default parameters values added
69+
updatedMappings.properties.myField = defaultPointParameters;
70+
71+
({ data } = await getMappingsEditorData(component));
72+
expect(data).toEqual(updatedMappings);
73+
});
74+
75+
describe('meta parameter', () => {
76+
const defaultMappings = {
77+
properties: {
78+
myField: {
79+
type: 'point',
80+
},
81+
},
82+
};
83+
84+
const updatedMappings = { ...defaultMappings };
85+
86+
const metaParameter = {
87+
meta: {
88+
my_metadata: 'foobar',
89+
},
90+
};
91+
92+
beforeEach(async () => {
93+
await act(async () => {
94+
testBed = setup({ value: defaultMappings, onChange: onChangeHandler });
95+
});
96+
testBed.component.update();
97+
});
98+
99+
test('valid meta object', async () => {
100+
const {
101+
component,
102+
actions: {
103+
startEditField,
104+
updateFieldAndCloseFlyout,
105+
showAdvancedSettings,
106+
toggleFormRow,
107+
updateJsonEditor,
108+
},
109+
} = testBed;
110+
111+
// Open the flyout to edit the field
112+
await startEditField('myField');
113+
await showAdvancedSettings();
114+
115+
// Enable the meta parameter and add value
116+
toggleFormRow('metaParameter');
117+
await act(async () => {
118+
updateJsonEditor('metaParameterEditor', metaParameter.meta);
119+
});
120+
component.update();
121+
122+
// Save the field and close the flyout
123+
await updateFieldAndCloseFlyout();
124+
125+
// It should have the default parameters values added, plus metadata
126+
updatedMappings.properties.myField = {
127+
...defaultPointParameters,
128+
...metaParameter,
129+
};
130+
131+
({ data } = await getMappingsEditorData(component));
132+
expect(data).toEqual(updatedMappings);
133+
});
134+
135+
test('strip empty string', async () => {
136+
const {
137+
component,
138+
actions: { startEditField, updateFieldAndCloseFlyout, showAdvancedSettings, toggleFormRow },
139+
} = testBed;
140+
141+
// Open the flyout to edit the field
142+
await startEditField('myField');
143+
await showAdvancedSettings();
144+
145+
// Enable the meta parameter
146+
toggleFormRow('metaParameter');
147+
148+
// Save the field and close the flyout without adding any values to meta parameter
149+
await updateFieldAndCloseFlyout();
150+
151+
// It should have the default parameters values added
152+
updatedMappings.properties.myField = defaultPointParameters;
153+
154+
({ data } = await getMappingsEditorData(component));
155+
expect(data).toEqual(updatedMappings);
156+
});
157+
});
158+
});

x-pack/plugins/index_management/public/application/components/mappings_editor/__jest__/client_integration/helpers/mappings_editor.helpers.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,10 @@ const createActions = (testBed: TestBed<TestSubjects>) => {
239239
const getCheckboxValue = (testSubject: TestSubjects): boolean =>
240240
find(testSubject).props().checked;
241241

242+
const toggleFormRow = (formRowName: string) => {
243+
form.toggleEuiSwitch(`${formRowName}.formRowToggle`);
244+
};
245+
242246
return {
243247
selectTab,
244248
getFieldAt,
@@ -252,6 +256,7 @@ const createActions = (testBed: TestBed<TestSubjects>) => {
252256
getComboBoxValue,
253257
getToggleValue,
254258
getCheckboxValue,
259+
toggleFormRow,
255260
};
256261
};
257262

@@ -365,4 +370,6 @@ export type TestSubjects =
365370
| 'searchQuoteAnalyzer-custom'
366371
| 'searchQuoteAnalyzer-toggleCustomButton'
367372
| 'searchQuoteAnalyzer-custom.input'
368-
| 'useSameAnalyzerForSearchCheckBox.input';
373+
| 'useSameAnalyzerForSearchCheckBox.input'
374+
| 'metaParameterEditor'
375+
| string;

x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/ignore_z_value_parameter.tsx

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,18 @@ import { i18n } from '@kbn/i18n';
1010

1111
import { EditFieldFormRow } from '../fields/edit_field';
1212

13-
export const IgnoreZValueParameter = () => (
13+
export const IgnoreZValueParameter = ({ description }: { description?: string }) => (
1414
<EditFieldFormRow
1515
title={i18n.translate('xpack.idxMgmt.mappingsEditor.ignoreZValueFieldTitle', {
1616
defaultMessage: 'Ignore Z value',
1717
})}
18-
description={i18n.translate('xpack.idxMgmt.mappingsEditor.ignoredZValueFieldDescription', {
19-
defaultMessage:
20-
'Three dimension points will be accepted, but only latitude and longitude values will be indexed; the third dimension is ignored.',
21-
})}
18+
description={
19+
description ||
20+
i18n.translate('xpack.idxMgmt.mappingsEditor.ignoredZValueFieldDescription', {
21+
defaultMessage:
22+
'Three dimension points will be accepted, but only latitude and longitude values will be indexed; the third dimension is ignored.',
23+
})
24+
}
2225
formFieldPath="ignore_z_value"
2326
/>
2427
);

x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/field_parameters/meta_parameter.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,15 @@ export const MetaParameter: FunctionComponent<Props> = ({ defaultToggleValue })
3232
}),
3333
href: documentationService.getMetaLink(),
3434
}}
35+
data-test-subj="metaParameter"
3536
>
3637
<UseField
3738
path="meta"
3839
config={getFieldConfig('meta')}
3940
component={JsonEditorField}
4041
componentProps={{
4142
euiCodeEditorProps: {
43+
['data-test-subj']: 'metaParameterEditor',
4244
height: '300px',
4345
'aria-label': i18n.translate('xpack.idxMgmt.mappingsEditor.metaParameterAriaLabel', {
4446
defaultMessage: 'metadata field data editor',

x-pack/plugins/index_management/public/application/components/mappings_editor/components/document_fields/fields/field_types/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import { HistogramType } from './histogram_type';
3232
import { ConstantKeywordType } from './constant_keyword_type';
3333
import { RankFeatureType } from './rank_feature_type';
3434
import { WildcardType } from './wildcard_type';
35+
import { PointType } from './point_type';
3536

3637
const typeToParametersFormMap: { [key in DataType]?: ComponentType<any> } = {
3738
alias: AliasType,
@@ -60,6 +61,7 @@ const typeToParametersFormMap: { [key in DataType]?: ComponentType<any> } = {
6061
constant_keyword: ConstantKeywordType,
6162
rank_feature: RankFeatureType,
6263
wildcard: WildcardType,
64+
point: PointType,
6365
};
6466

6567
export const getParametersFormForType = (
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
import React, { FunctionComponent } from 'react';
7+
8+
import { i18n } from '@kbn/i18n';
9+
10+
import { NormalizedField, Field as FieldType, ParameterName } from '../../../../types';
11+
import { UseField, TextAreaField } from '../../../../shared_imports';
12+
import { getFieldConfig } from '../../../../lib';
13+
import {
14+
IgnoreMalformedParameter,
15+
IgnoreZValueParameter,
16+
NullValueParameter,
17+
MetaParameter,
18+
} from '../../field_parameters';
19+
import { AdvancedParametersSection, BasicParametersSection } from '../edit_field';
20+
21+
interface Props {
22+
field: NormalizedField;
23+
}
24+
25+
const getDefaultToggleValue = (param: ParameterName, field: FieldType) => {
26+
return field[param] !== undefined && field[param] !== getFieldConfig(param).defaultValue;
27+
};
28+
29+
export const PointType: FunctionComponent<Props> = ({ field }) => {
30+
return (
31+
<>
32+
<BasicParametersSection>
33+
<IgnoreMalformedParameter
34+
description={i18n.translate(
35+
'xpack.idxMgmt.mappingsEditor.point.ignoreMalformedFieldDescription',
36+
{
37+
defaultMessage:
38+
'By default, documents that contain malformed points are not indexed. If enabled, these documents are indexed, but fields with malformed points are filtered out. Be careful: if too many documents are indexed this way, queries on the field become meaningless.',
39+
}
40+
)}
41+
/>
42+
</BasicParametersSection>
43+
44+
<AdvancedParametersSection>
45+
<IgnoreZValueParameter
46+
description={i18n.translate(
47+
'xpack.idxMgmt.mappingsEditor.point.ignoreZValueFieldDescription',
48+
{
49+
defaultMessage:
50+
'Three dimension points will be accepted, but only x and y values will be indexed; the third dimension is ignored.',
51+
}
52+
)}
53+
/>
54+
55+
<NullValueParameter
56+
defaultToggleValue={getDefaultToggleValue('null_value', field.source)}
57+
description={i18n.translate(
58+
'xpack.idxMgmt.mappingsEditor.point.nullValueFieldDescription',
59+
{
60+
defaultMessage:
61+
'Replace explicit null values with a point value so that it can be indexed and searched.',
62+
}
63+
)}
64+
>
65+
<UseField
66+
path="null_value"
67+
component={TextAreaField}
68+
config={getFieldConfig('null_value_point')}
69+
/>
70+
</NullValueParameter>
71+
72+
<MetaParameter defaultToggleValue={getDefaultToggleValue('meta', field.source)} />
73+
</AdvancedParametersSection>
74+
</>
75+
);
76+
};

x-pack/plugins/index_management/public/application/components/mappings_editor/constants/data_types_definition.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -821,6 +821,26 @@ export const TYPE_DEFINITION: { [key in DataType]: DataTypeDefinition } = {
821821
</p>
822822
),
823823
},
824+
point: {
825+
label: i18n.translate('xpack.idxMgmt.mappingsEditor.dataType.pointDescription', {
826+
defaultMessage: 'Point',
827+
}),
828+
value: 'point',
829+
documentation: {
830+
main: '/point.html',
831+
},
832+
description: () => (
833+
<p>
834+
<FormattedMessage
835+
id="xpack.idxMgmt.mappingsEditor.dataType.pointLongDescription"
836+
defaultMessage="Point fields enable searching of {code} pairs that fall in a 2-dimensional planar coordinate system."
837+
values={{
838+
code: <EuiCode inline>{'x,y'}</EuiCode>,
839+
}}
840+
/>
841+
</p>
842+
),
843+
},
824844
wildcard: {
825845
label: i18n.translate('xpack.idxMgmt.mappingsEditor.dataType.wildcardDescription', {
826846
defaultMessage: 'Wildcard',
@@ -882,6 +902,7 @@ export const MAIN_TYPES: MainType[] = [
882902
'token_count',
883903
'histogram',
884904
'wildcard',
905+
'point',
885906
'other',
886907
];
887908

0 commit comments

Comments
 (0)