diff --git a/x-pack/legacy/plugins/maps/common/constants.ts b/x-pack/legacy/plugins/maps/common/constants.ts index 53289fbbc9005a..a4afae0b9e077d 100644 --- a/x-pack/legacy/plugins/maps/common/constants.ts +++ b/x-pack/legacy/plugins/maps/common/constants.ts @@ -165,6 +165,7 @@ export const COLOR_MAP_TYPE = { export const COLOR_PALETTE_MAX_SIZE = 10; export const CATEGORICAL_DATA_TYPES = ['string', 'ip', 'boolean']; +export const ORDINAL_DATA_TYPES = ['number', 'date']; export const SYMBOLIZE_AS_TYPES = { CIRCLE: 'circle', diff --git a/x-pack/legacy/plugins/maps/common/descriptor_types.d.ts b/x-pack/legacy/plugins/maps/common/descriptor_types.d.ts index f03f828200bbd9..ce0743ba2baedf 100644 --- a/x-pack/legacy/plugins/maps/common/descriptor_types.d.ts +++ b/x-pack/legacy/plugins/maps/common/descriptor_types.d.ts @@ -35,11 +35,11 @@ export type AggDescriptor = { type: AGG_TYPE; }; -export type AbstractESAggDescriptor = AbstractESSourceDescriptor & { +export type AbstractESAggSourceDescriptor = AbstractESSourceDescriptor & { metrics: AggDescriptor[]; }; -export type ESGeoGridSourceDescriptor = AbstractESAggDescriptor & { +export type ESGeoGridSourceDescriptor = AbstractESAggSourceDescriptor & { requestType?: RENDER_AS; resolution?: GRID_RESOLUTION; }; @@ -54,12 +54,12 @@ export type ESSearchSourceDescriptor = AbstractESSourceDescriptor & { topHitsSize?: number; }; -export type ESPewPewSourceDescriptor = AbstractESAggDescriptor & { +export type ESPewPewSourceDescriptor = AbstractESAggSourceDescriptor & { sourceGeoField: string; destGeoField: string; }; -export type ESTermSourceDescriptor = AbstractESAggDescriptor & { +export type ESTermSourceDescriptor = AbstractESAggSourceDescriptor & { indexPatternTitle: string; term: string; // term field name }; diff --git a/x-pack/legacy/plugins/maps/public/layers/fields/es_doc_field.js b/x-pack/legacy/plugins/maps/public/layers/fields/es_doc_field.js index 0b90dbe47c6e9f..ea7641ed5e8dd6 100644 --- a/x-pack/legacy/plugins/maps/public/layers/fields/es_doc_field.js +++ b/x-pack/legacy/plugins/maps/public/layers/fields/es_doc_field.js @@ -57,11 +57,6 @@ export class ESDocField extends AbstractField { async getCategoricalFieldMetaRequest() { const field = await this._getField(); - if (field.type !== 'string') { - //UX does not support categorical styling for number/date fields - return null; - } - const topTerms = { size: COLOR_PALETTE_MAX_SIZE - 1, //need additional color for the "other"-value }; diff --git a/x-pack/legacy/plugins/maps/public/layers/layer.js b/x-pack/legacy/plugins/maps/public/layers/layer.js index b76f1ebce15d21..71e5d7b95e44fd 100644 --- a/x-pack/legacy/plugins/maps/public/layers/layer.js +++ b/x-pack/legacy/plugins/maps/public/layers/layer.js @@ -332,18 +332,6 @@ export class AbstractLayer { return []; } - async getDateFields() { - return []; - } - - async getNumberFields() { - return []; - } - - async getCategoricalFields() { - return []; - } - async getFields() { return []; } diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_agg_source.d.ts b/x-pack/legacy/plugins/maps/public/layers/sources/es_agg_source.d.ts index a91bb4a8bb1a7b..99ee1ec652b542 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_agg_source.d.ts +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_agg_source.d.ts @@ -7,13 +7,19 @@ import { IESSource } from './es_source'; import { AbstractESSource } from './es_source'; import { AGG_TYPE } from '../../../common/constants'; +import { IESAggField } from '../fields/es_agg_field'; +import { AbstractESAggSourceDescriptor } from '../../../common/descriptor_types'; export interface IESAggSource extends IESSource { getAggKey(aggType: AGG_TYPE, fieldName: string): string; getAggLabel(aggType: AGG_TYPE, fieldName: string): string; + getMetricFields(): IESAggField[]; } export class AbstractESAggSource extends AbstractESSource implements IESAggSource { + constructor(sourceDescriptor: AbstractESAggSourceDescriptor, inspectorAdapters: object); + getAggKey(aggType: AGG_TYPE, fieldName: string): string; getAggLabel(aggType: AGG_TYPE, fieldName: string): string; + getMetricFields(): IESAggField[]; } diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_agg_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_agg_source.js index 62f3369ceb3a36..9f4b89cadc7773 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_agg_source.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_agg_source.js @@ -78,6 +78,10 @@ export class AbstractESAggSource extends AbstractESSource { } } + async getFields() { + return this.getMetricFields(); + } + getValueAggsDsl(indexPattern) { const valueAggsDsl = {}; this.getMetricFields().forEach(esAggMetric => { @@ -89,10 +93,6 @@ export class AbstractESAggSource extends AbstractESSource { return valueAggsDsl; } - async getNumberFields() { - return this.getMetricFields(); - } - async filterAndFormatPropertiesToHtmlForMetricFields(properties) { const metricFields = this.getMetricFields(); const tooltipPropertiesPromises = []; diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_agg_source.test.ts b/x-pack/legacy/plugins/maps/public/layers/sources/es_agg_source.test.ts new file mode 100644 index 00000000000000..848091586eb9cb --- /dev/null +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_agg_source.test.ts @@ -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 { AbstractESAggSource } from './es_agg_source'; +import { IField } from '../fields/field'; +import { IESAggField } from '../fields/es_agg_field'; +import _ from 'lodash'; +import { AGG_TYPE } from '../../../common/constants'; +import { AggDescriptor } from '../../../common/descriptor_types'; + +jest.mock('ui/new_platform'); + +const sumFieldName = 'myFieldGettingSummed'; +const metricExamples = [ + { + type: AGG_TYPE.SUM, + field: sumFieldName, + label: 'my custom label', + }, + { + // metric config is invalid beause field is missing + type: AGG_TYPE.MAX, + }, + { + // metric config is valid because "count" metric does not need to provide field + type: AGG_TYPE.COUNT, + label: '', // should ignore empty label fields + }, +]; + +class TestESAggSource extends AbstractESAggSource { + constructor(metrics: AggDescriptor[]) { + super({ type: 'test', id: 'foobar', indexPatternId: 'foobarid', metrics }, []); + } +} + +describe('getMetricFields', () => { + it('should add default "count" metric when no metrics are provided', async () => { + const source = new TestESAggSource([]); + const metrics = source.getMetricFields(); + expect(metrics.length).toBe(1); + + expect(metrics[0].getName()).toEqual('doc_count'); + expect(await metrics[0].getLabel()).toEqual('count'); + }); + + it('should remove incomplete metric configurations', async () => { + const source = new TestESAggSource(metricExamples); + const metrics = source.getMetricFields(); + expect(metrics.length).toBe(2); + + expect(metrics[0].getRootName()).toEqual(sumFieldName); + expect(metrics[0].getName()).toEqual('sum_of_myFieldGettingSummed'); + expect(await metrics[0].getLabel()).toEqual('my custom label'); + + expect(metrics[1].getName()).toEqual('doc_count'); + expect(await metrics[1].getLabel()).toEqual('count'); + }); + + it('getMetrics should be identical to getFields', async () => { + const source = new TestESAggSource(metricExamples); + const metrics = source.getMetricFields(); + const fields = await source.getFields(); + + const getFieldMeta = async (field: IField) => { + const esAggField = field as IESAggField; // this ensures we can downcast correctly. + return { + name: esAggField.getName(), + label: await esAggField.getLabel(), + esDoc: esAggField.getRootName(), + }; + }; + + const metricsFieldMeta = await Promise.all(metrics.map(getFieldMeta)); + const fieldsFieldMeta = await Promise.all(fields.map(getFieldMeta)); + + expect(_.isEqual(metricsFieldMeta, fieldsFieldMeta)).toEqual(true); + }); +}); diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.d.ts b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.d.ts index 652409b61fd722..48e90b6c41d51a 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.d.ts +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.d.ts @@ -6,7 +6,10 @@ import { AbstractESAggSource } from '../es_agg_source'; import { ESGeoGridSourceDescriptor } from '../../../../common/descriptor_types'; +import { GRID_RESOLUTION } from '../../../../common/constants'; export class ESGeoGridSource extends AbstractESAggSource { constructor(sourceDescriptor: ESGeoGridSourceDescriptor, inspectorAdapters: unknown); + getGridResolution(): GRID_RESOLUTION; + getGeoGridPrecision(zoom: number): number; } diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js index 4987d052b8ab70..3b3e8004ded053 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js @@ -35,7 +35,7 @@ import { DynamicStyleProperty } from '../../styles/vector/properties/dynamic_sty import { StaticStyleProperty } from '../../styles/vector/properties/static_style_property'; import { DataRequestAbortError } from '../../util/data_request'; -const MAX_GEOTILE_LEVEL = 29; +export const MAX_GEOTILE_LEVEL = 29; export class ESGeoGridSource extends AbstractESAggSource { static type = ES_GEO_GRID; diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.test.ts b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.test.ts new file mode 100644 index 00000000000000..727435c3cbfef1 --- /dev/null +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.test.ts @@ -0,0 +1,41 @@ +/* + * 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. + */ +jest.mock('../../../kibana_services', () => {}); +jest.mock('ui/new_platform'); + +import { ESGeoGridSource } from './es_geo_grid_source'; +import { ES_GEO_GRID, GRID_RESOLUTION, RENDER_AS } from '../../../../common/constants'; + +describe('ESGeoGridSource', () => { + const geogridSource = new ESGeoGridSource( + { + id: 'foobar', + indexPatternId: 'fooIp', + geoField: 'bar', + metrics: [], + resolution: GRID_RESOLUTION.COARSE, + type: ES_GEO_GRID, + requestType: RENDER_AS.HEATMAP, + }, + {} + ); + + describe('getGridResolution', () => { + it('should echo gridResoltuion', () => { + expect(geogridSource.getGridResolution()).toBe(GRID_RESOLUTION.COARSE); + }); + }); + + describe('getGeoGridPrecision', () => { + it('should clamp geo-grid derived zoom to max geotile level supported by ES', () => { + expect(geogridSource.getGeoGridPrecision(29)).toBe(29); + }); + + it('should use heuristic to derive precision', () => { + expect(geogridSource.getGeoGridPrecision(10)).toBe(12); + }); + }); +}); diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.js index 35332824361393..7f0e8707605120 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.js @@ -19,7 +19,6 @@ import { ES_GEO_FIELD_TYPE, DEFAULT_MAX_BUCKETS_LIMIT, SORT_ORDER, - CATEGORICAL_DATA_TYPES, } from '../../../../common/constants'; import { i18n } from '@kbn/i18n'; import { getDataSourceLabel } from '../../../../common/i18n_getters'; @@ -135,49 +134,6 @@ export class ESSearchSource extends AbstractESSource { ); } - async getNumberFields() { - try { - const indexPattern = await this.getIndexPattern(); - return indexPattern.fields.getByType('number').map(field => { - return this.createField({ fieldName: field.name }); - }); - } catch (error) { - return []; - } - } - - async getDateFields() { - try { - const indexPattern = await this.getIndexPattern(); - return indexPattern.fields.getByType('date').map(field => { - return this.createField({ fieldName: field.name }); - }); - } catch (error) { - return []; - } - } - - async getCategoricalFields() { - try { - const indexPattern = await this.getIndexPattern(); - - const aggFields = []; - CATEGORICAL_DATA_TYPES.forEach(dataType => { - indexPattern.fields.getByType(dataType).forEach(field => { - if (field.aggregatable) { - aggFields.push(field); - } - }); - }); - return aggFields.map(field => { - return this.createField({ fieldName: field.name }); - }); - } catch (error) { - //error surfaces in the LayerTOC UI - return []; - } - } - async getFields() { try { const indexPattern = await this.getIndexPattern(); diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_term_source.test.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_term_source.test.js index d6f9f6d2911e91..890b1e3aaac1f0 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/es_term_source.test.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_term_source.test.js @@ -31,36 +31,27 @@ const metricExamples = [ ]; describe('getMetricFields', () => { - it('should add default "count" metric when no metrics are provided', async () => { + it('should override name and label of count metric', async () => { const source = new ESTermSource({ indexPatternTitle: indexPatternTitle, term: termFieldName, }); const metrics = source.getMetricFields(); - expect(metrics.length).toBe(1); - - expect(metrics[0].getAggType()).toEqual('count'); expect(metrics[0].getName()).toEqual('__kbnjoin__count_groupby_myIndex.myTermField'); expect(await metrics[0].getLabel()).toEqual('Count of myIndex'); }); - it('should remove incomplete metric configurations', async () => { + it('should override name and label of sum metric', async () => { const source = new ESTermSource({ indexPatternTitle: indexPatternTitle, term: termFieldName, metrics: metricExamples, }); const metrics = source.getMetricFields(); - expect(metrics.length).toBe(2); - - expect(metrics[0].getAggType()).toEqual('sum'); - expect(metrics[0].getRootName()).toEqual(sumFieldName); expect(metrics[0].getName()).toEqual( '__kbnjoin__sum_of_myFieldGettingSummed_groupby_myIndex.myTermField' ); expect(await metrics[0].getLabel()).toEqual('my custom label'); - - expect(metrics[1].getAggType()).toEqual('count'); expect(metrics[1].getName()).toEqual('__kbnjoin__count_groupby_myIndex.myTermField'); expect(await metrics[1].getLabel()).toEqual('Count of myIndex'); }); diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/vector_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/vector_source.js index 8369ca562e14b3..0f74dd605c8f1b 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/vector_source.js +++ b/x-pack/legacy/plugins/maps/public/layers/sources/vector_source.js @@ -111,19 +111,7 @@ export class AbstractVectorSource extends AbstractSource { return null; } - async getDateFields() { - return []; - } - - async getNumberFields() { - return []; - } - async getFields() { - return [...(await this.getDateFields()), ...(await this.getNumberFields())]; - } - - async getCategoricalFields() { return []; } diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/color_map_select.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/color_map_select.js index 436a92b6199090..0d4cf322d2a406 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/color_map_select.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/color_map_select.js @@ -6,10 +6,11 @@ import React, { Component, Fragment } from 'react'; -import { EuiSuperSelect, EuiSpacer } from '@elastic/eui'; +import { EuiSpacer, EuiSelect, EuiSuperSelect, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { ColorStopsOrdinal } from './color_stops_ordinal'; import { COLOR_MAP_TYPE } from '../../../../../../common/constants'; import { ColorStopsCategorical } from './color_stops_categorical'; +import { i18n } from '@kbn/i18n'; const CUSTOM_COLOR_MAP = 'CUSTOM_COLOR_MAP'; @@ -27,6 +28,43 @@ export class ColorMapSelect extends Component { }; } + _renderColorMapToggle() { + const options = [ + { + value: COLOR_MAP_TYPE.ORDINAL, + text: i18n.translate('xpack.maps.styles.dynamicColorSelect.quantitativeLabel', { + defaultMessage: 'As number', + }), + }, + { + value: COLOR_MAP_TYPE.CATEGORICAL, + text: i18n.translate('xpack.maps.styles.dynamicColorSelect.qualitativeLabel', { + defaultMessage: 'As category', + }), + }, + ]; + + const selectedValue = this.props.styleProperty.isOrdinal() + ? COLOR_MAP_TYPE.ORDINAL + : COLOR_MAP_TYPE.CATEGORICAL; + + return ( + + ); + } + _onColorMapSelect = selectedValue => { const useCustomColorMap = selectedValue === CUSTOM_COLOR_MAP; this.props.onChange({ @@ -55,32 +93,32 @@ export class ColorMapSelect extends Component { return null; } + let colorStopEditor; if (this.props.colorMapType === COLOR_MAP_TYPE.ORDINAL) { - return ( - - - - + colorStopEditor = ( + ); - } - - return ( - - + } else + colorStopEditor = ( - + ); + + return ( + + {colorStopEditor} + ); } - render() { + _renderColorMapSelections() { const colorMapOptionsWithCustom = [ { value: CUSTOM_COLOR_MAP, @@ -98,15 +136,31 @@ export class ColorMapSelect extends Component { : ''; } + const toggle = this.props.showColorMapTypeToggle ? ( + {this._renderColorMapToggle()} + ) : null; + + return ( + + {toggle} + + + + + ); + } + + render() { return ( - + {this._renderColorMapSelections()} + {this._renderColorStopsInput()} ); diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/dynamic_color_form.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/dynamic_color_form.js index 3dc356c31cf30b..c6b68b7e944099 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/dynamic_color_form.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/color/dynamic_color_form.js @@ -40,21 +40,44 @@ export function DynamicColorForm({ }; const onFieldChange = async ({ field }) => { - const { name, origin, type } = field; + const { name, origin, type: fieldType } = field; + const defaultColorMapType = CATEGORICAL_DATA_TYPES.includes(fieldType) + ? COLOR_MAP_TYPE.CATEGORICAL + : COLOR_MAP_TYPE.ORDINAL; onDynamicStyleChange(styleProperty.getStyleName(), { ...styleOptions, field: { name, origin }, - type: CATEGORICAL_DATA_TYPES.includes(type) - ? COLOR_MAP_TYPE.CATEGORICAL - : COLOR_MAP_TYPE.ORDINAL, + type: defaultColorMapType, + }); + }; + + const onColorMapTypeChange = async e => { + const colorMapType = e.target.value; + onDynamicStyleChange(styleProperty.getStyleName(), { + ...styleOptions, + type: colorMapType, + }); + }; + + const getField = () => { + const fieldName = styleProperty.getFieldName(); + if (!fieldName) { + return null; + } + + return fields.find(field => { + return field.name === fieldName; }); }; const renderColorMapSelect = () => { - if (!styleOptions.field || !styleOptions.field.name) { + const field = getField(); + if (!field) { return null; } + const showColorMapTypeToggle = !CATEGORICAL_DATA_TYPES.includes(field.type); + if (styleProperty.isOrdinal()) { return ( + ); + } else if (styleProperty.isCategorical()) { + return ( + ); } - - return ( - - ); }; return ( diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector_style_editor.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector_style_editor.js index 7daf85b68dd8e1..7ad36bd2ae33d1 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector_style_editor.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector_style_editor.js @@ -26,13 +26,14 @@ import { VECTOR_SHAPE_TYPES } from '../../../sources/vector_feature_types'; import { i18n } from '@kbn/i18n'; import { EuiSpacer, EuiButtonGroup, EuiFormRow, EuiSwitch } from '@elastic/eui'; +import { CATEGORICAL_DATA_TYPES, ORDINAL_DATA_TYPES } from '../../../../../common/constants'; export class VectorStyleEditor extends Component { state = { dateFields: [], numberFields: [], - categoricalFields: [], fields: [], + ordinalAndCategoricalFields: [], defaultDynamicProperties: getDefaultDynamicProperties(), defaultStaticProperties: getDefaultStaticProperties(), supportedFeatures: undefined, @@ -64,33 +65,24 @@ export class VectorStyleEditor extends Component { }; }; - const dateFields = await this.props.layer.getDateFields(); - const dateFieldPromises = dateFields.map(getFieldMeta); - const dateFieldsArray = await Promise.all(dateFieldPromises); - if (this._isMounted && !_.isEqual(dateFieldsArray, this.state.dateFields)) { - this.setState({ dateFields: dateFieldsArray }); - } - - const numberFields = await this.props.layer.getNumberFields(); - const numberFieldPromises = numberFields.map(getFieldMeta); - const numberFieldsArray = await Promise.all(numberFieldPromises); - if (this._isMounted && !_.isEqual(numberFieldsArray, this.state.numberFields)) { - this.setState({ numberFields: numberFieldsArray }); - } - - const categoricalFields = await this.props.layer.getCategoricalFields(); - const categoricalFieldMeta = categoricalFields.map(getFieldMeta); - const categoricalFieldsArray = await Promise.all(categoricalFieldMeta); - if (this._isMounted && !_.isEqual(categoricalFieldsArray, this.state.categoricalFields)) { - this.setState({ categoricalFields: categoricalFieldsArray }); - } - + //These are all fields (only used for text labeling) const fields = await this.props.layer.getFields(); const fieldPromises = fields.map(getFieldMeta); - const fieldsArray = await Promise.all(fieldPromises); - if (this._isMounted && !_.isEqual(fieldsArray, this.state.fields)) { - this.setState({ fields: fieldsArray }); + const fieldsArrayAll = await Promise.all(fieldPromises); + if (!this._isMounted || _.isEqual(fieldsArrayAll, this.state.fields)) { + return; } + + this.setState({ + fields: fieldsArrayAll, + ordinalAndCategoricalFields: fieldsArrayAll.filter(field => { + return ( + CATEGORICAL_DATA_TYPES.includes(field.type) || ORDINAL_DATA_TYPES.includes(field.type) + ); + }), + dateFields: fieldsArrayAll.filter(field => field.type === 'date'), + numberFields: fieldsArrayAll.filter(field => field.type === 'number'), + }); } async _loadSupportedFeatures() { @@ -118,10 +110,6 @@ export class VectorStyleEditor extends Component { return [...this.state.dateFields, ...this.state.numberFields]; } - _getOrdinalAndCategoricalFields() { - return [...this.state.dateFields, ...this.state.numberFields, ...this.state.categoricalFields]; - } - _handleSelectedFeatureChange = selectedFeature => { this.setState({ selectedFeature }); }; @@ -172,7 +160,7 @@ export class VectorStyleEditor extends Component { onStaticStyleChange={this._onStaticStyleChange} onDynamicStyleChange={this._onDynamicStyleChange} styleProperty={this.props.styleProperties[VECTOR_STYLES.FILL_COLOR]} - fields={this._getOrdinalAndCategoricalFields()} + fields={this.state.ordinalAndCategoricalFields} defaultStaticStyleOptions={ this.state.defaultStaticProperties[VECTOR_STYLES.FILL_COLOR].options } @@ -193,7 +181,7 @@ export class VectorStyleEditor extends Component { onStaticStyleChange={this._onStaticStyleChange} onDynamicStyleChange={this._onDynamicStyleChange} styleProperty={this.props.styleProperties[VECTOR_STYLES.LINE_COLOR]} - fields={this._getOrdinalAndCategoricalFields()} + fields={this.state.ordinalAndCategoricalFields} defaultStaticStyleOptions={ this.state.defaultStaticProperties[VECTOR_STYLES.LINE_COLOR].options } @@ -249,7 +237,7 @@ export class VectorStyleEditor extends Component { onStaticStyleChange={this._onStaticStyleChange} onDynamicStyleChange={this._onDynamicStyleChange} styleProperty={this.props.styleProperties[VECTOR_STYLES.LABEL_COLOR]} - fields={this._getOrdinalAndCategoricalFields()} + fields={this.state.ordinalAndCategoricalFields} defaultStaticStyleOptions={ this.state.defaultStaticProperties[VECTOR_STYLES.LABEL_COLOR].options } @@ -282,7 +270,7 @@ export class VectorStyleEditor extends Component { onStaticStyleChange={this._onStaticStyleChange} onDynamicStyleChange={this._onDynamicStyleChange} styleProperty={this.props.styleProperties[VECTOR_STYLES.LABEL_BORDER_COLOR]} - fields={this._getOrdinalAndCategoricalFields()} + fields={this.state.ordinalAndCategoricalFields} defaultStaticStyleOptions={ this.state.defaultStaticProperties[VECTOR_STYLES.LABEL_BORDER_COLOR].options } @@ -335,7 +323,7 @@ export class VectorStyleEditor extends Component { onStaticStyleChange={this._onStaticStyleChange} onDynamicStyleChange={this._onDynamicStyleChange} styleProperty={this.props.styleProperties[VECTOR_STYLES.ICON]} - fields={this.state.categoricalFields} + fields={this.state.ordinalAndCategoricalFields} defaultStaticStyleOptions={ this.state.defaultStaticProperties[VECTOR_STYLES.ICON].options } diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_color_property.test.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_color_property.test.js index c2f7a1313d02ae..5b286e4ba120ec 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_color_property.test.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_color_property.test.js @@ -236,3 +236,33 @@ test('Should pluck the categorical style-meta from fieldmeta', async () => { ], }); }); + +test('isCategorical should return true when type is categorical', async () => { + const categoricalColorStyle = makeProperty({ + type: COLOR_MAP_TYPE.CATEGORICAL, + colorCategory: 'palette_0', + }); + + expect(categoricalColorStyle.isOrdinal()).toEqual(false); + expect(categoricalColorStyle.isCategorical()).toEqual(true); +}); + +test('isOrdinal should return true when type is ordinal', async () => { + const ordinalColorStyle = makeProperty({ + type: undefined, + color: 'Blues', + }); + + expect(ordinalColorStyle.isOrdinal()).toEqual(true); + expect(ordinalColorStyle.isCategorical()).toEqual(false); +}); + +test('Should read out ordinal type correctly', async () => { + const ordinalColorStyle2 = makeProperty({ + type: COLOR_MAP_TYPE.ORDINAL, + colorCategory: 'palette_0', + }); + + expect(ordinalColorStyle2.isOrdinal()).toEqual(true); + expect(ordinalColorStyle2.isCategorical()).toEqual(false); +}); diff --git a/x-pack/legacy/plugins/maps/public/layers/vector_layer.js b/x-pack/legacy/plugins/maps/public/layers/vector_layer.js index 32fdbcf9654147..70bba3d91c7237 100644 --- a/x-pack/legacy/plugins/maps/public/layers/vector_layer.js +++ b/x-pack/legacy/plugins/maps/public/layers/vector_layer.js @@ -197,19 +197,6 @@ export class VectorLayer extends AbstractLayer { return joinFields; } - async getDateFields() { - return await this._source.getDateFields(); - } - - async getNumberFields() { - const numberFieldOptions = await this._source.getNumberFields(); - return [...numberFieldOptions, ...this._getJoinFields()]; - } - - async getCategoricalFields() { - return await this._source.getCategoricalFields(); - } - async getFields() { const sourceFields = await this._source.getFields(); return [...sourceFields, ...this._getJoinFields()];