diff --git a/x-pack/legacy/plugins/maps/public/layers/fields/ems_region_field.js b/x-pack/legacy/plugins/maps/public/layers/fields/ems_region_field.js
new file mode 100644
index 0000000000000..a078fc6cd3f35
--- /dev/null
+++ b/x-pack/legacy/plugins/maps/public/layers/fields/ems_region_field.js
@@ -0,0 +1,27 @@
+/*
+ * 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 { AbstractField } from './field';
+import { TooltipProperty } from '../tooltips/tooltip_property';
+
+//todo: rename to ESMFileField
+export class EMSRegionLayerField extends AbstractField {
+ static type = 'EMS_REGION_LAYER';
+
+ async getLabel() {
+ const emsFileLayer = await this._source.getEMSFileLayer();
+ const emsFields = emsFileLayer.getFieldsInLanguage();
+ // Map EMS field name to language specific label
+ const emsField = emsFields.find(field => field.name === this.getName());
+ return emsField ? emsField.description : this.getName();
+ }
+
+ async createTooltipProperty(value) {
+ const label = await this.getLabel();
+ return new TooltipProperty(this.getName(), label, value);
+ }
+}
diff --git a/x-pack/legacy/plugins/maps/public/layers/fields/es_agg_field.js b/x-pack/legacy/plugins/maps/public/layers/fields/es_agg_field.js
new file mode 100644
index 0000000000000..a92027ae7f2d1
--- /dev/null
+++ b/x-pack/legacy/plugins/maps/public/layers/fields/es_agg_field.js
@@ -0,0 +1,64 @@
+/*
+ * 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 { AbstractField } from './field';
+import { METRIC_TYPE } from '../../../common/constants';
+
+export class ESAggMetricField extends AbstractField {
+
+ static type = 'ES_AGG';
+
+ constructor({ label, source, aggType, esDocField }) {
+ super({ source });
+ this._label = label;
+ this._aggType = aggType;
+ this._esDocField = esDocField;
+ }
+
+ getName() {
+ return this._source.formatMetricKey(this.getAggType(), this.getESDocFieldName());
+ }
+
+ async getLabel() {
+ return this.getPropertyLabel();
+ }
+
+ getAggType() {
+ return this._aggType;
+ }
+
+ isValid() {
+ return (this.getAggType() === METRIC_TYPE.COUNT) ? true : !!this._esDocField;
+ }
+
+ getPropertyLabel() {
+ return this._label ? this._label : this._source.formatMetricLabel(this.getAggType(), this.getESDocFieldName());
+ }
+
+ getESDocFieldName() {
+ return this._esDocField ? this._esDocField.getName() : '';
+ }
+
+ getRequestDescription() {
+ return this.getAggType() !== METRIC_TYPE.COUNT ? `${this.getAggType()} ${this.getESDocFieldName()}` : METRIC_TYPE.COUNT;
+ }
+
+ makeMetricAggConfig() {
+ const metricAggConfig = {
+ id: this.getName(),
+ enabled: true,
+ type: this.getAggType(),
+ schema: 'metric',
+ params: {}
+ };
+ if (this.getAggType() !== METRIC_TYPE.COUNT) {
+ metricAggConfig.params = { field: this.getESDocFieldName() };
+ }
+ return metricAggConfig;
+ }
+
+}
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
new file mode 100644
index 0000000000000..187e046a2eb6c
--- /dev/null
+++ b/x-pack/legacy/plugins/maps/public/layers/fields/es_doc_field.js
@@ -0,0 +1,30 @@
+/*
+ * 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 { AbstractField } from './field';
+import { ESTooltipProperty } from '../tooltips/es_tooltip_property';
+
+export class ESDocField extends AbstractField {
+
+ static type = 'ES_DOC';
+
+ async _getField() {
+ const indexPattern = await this._source.getIndexPattern();
+ return indexPattern.fields.find((field) => field.name === this._fieldName);
+ }
+
+ async createTooltipProperty(value) {
+ const indexPattern = await this._source.getIndexPattern();
+ return new ESTooltipProperty(this.getName(), this.getName(), value, indexPattern);
+ }
+
+ async getType() {
+ const field = await this._getField();
+ return field.type;
+ }
+
+}
diff --git a/x-pack/legacy/plugins/maps/public/layers/fields/field.js b/x-pack/legacy/plugins/maps/public/layers/fields/field.js
new file mode 100644
index 0000000000000..49a24c398213f
--- /dev/null
+++ b/x-pack/legacy/plugins/maps/public/layers/fields/field.js
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+
+export class AbstractField {
+
+ //todo consider removing
+ //double check if we're actually using this consistently
+ static FIELD_TYPE = {
+ STRING: 'string',
+ NUMBER: 'number',
+ DATE: 'date'
+ };
+
+ constructor({ fieldName, source }) {
+ this._fieldName = fieldName;
+ this._source = source;
+ }
+
+ getName() {
+ return this._fieldName;
+ }
+
+ isValid() {
+ return !!this._fieldName;
+ }
+
+ async getType() {
+ return AbstractField.FIELD_TYPE.STRING;
+ }
+
+ async getLabel() {
+ return this._fieldName;
+ }
+
+ async createTooltipProperty() {
+ throw new Error('must implement Field#createTooltipProperty');
+ }
+
+}
+
+
+
+
+
+
+
+
+
diff --git a/x-pack/legacy/plugins/maps/public/layers/fields/kibana_region_field.js b/x-pack/legacy/plugins/maps/public/layers/fields/kibana_region_field.js
new file mode 100644
index 0000000000000..f341d05db9a3b
--- /dev/null
+++ b/x-pack/legacy/plugins/maps/public/layers/fields/kibana_region_field.js
@@ -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 { AbstractField } from './field';
+
+//todo: need to be implemented
+export class KibanaRegionField extends AbstractField {
+
+ static type = 'KIBANA_REGION';
+
+ async getType() {
+ return AbstractField.FIELD_TYPE.STRING;
+ }
+
+}
diff --git a/x-pack/legacy/plugins/maps/public/layers/heatmap_layer.js b/x-pack/legacy/plugins/maps/public/layers/heatmap_layer.js
index 629fb3284ff11..157d45fbbd275 100644
--- a/x-pack/legacy/plugins/maps/public/layers/heatmap_layer.js
+++ b/x-pack/legacy/plugins/maps/public/layers/heatmap_layer.js
@@ -4,10 +4,9 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import _ from 'lodash';
import { AbstractLayer } from './layer';
import { VectorLayer } from './vector_layer';
-import { HeatmapStyle } from './styles/heatmap_style';
+import { HeatmapStyle } from './styles/heatmap/heatmap_style';
import { EMPTY_FEATURE_COLLECTION, LAYER_TYPE } from '../../common/constants';
const SCALED_PROPERTY_NAME = '__kbn_heatmap_weight__';//unique name to store scaled value for weighting
@@ -28,12 +27,14 @@ export class HeatmapLayer extends VectorLayer {
if (!style) {
const defaultStyle = HeatmapStyle.createDescriptor();
this._style = new HeatmapStyle(defaultStyle);
+ } else {
+ this._style = style;
}
}
_getPropKeyOfSelectedMetric() {
const metricfields = this._source.getMetricFields();
- return metricfields[0].propertyKey;
+ return metricfields[0].getName();
}
_getHeatmapLayerId() {
@@ -102,7 +103,8 @@ export class HeatmapLayer extends VectorLayer {
}
getLegendDetails() {
- const label = _.get(this._source.getMetricFields(), '[0].propertyLabel', '');
+ const metricFields = this._source.getMetricFields();
+ const label = metricFields[0].getPropertyLabel();
return this._style.getLegendDetails(label);
}
}
diff --git a/x-pack/legacy/plugins/maps/public/layers/joins/inner_join.js b/x-pack/legacy/plugins/maps/public/layers/joins/inner_join.js
index 8d1d1439a967e..781c02c3cffc2 100644
--- a/x-pack/legacy/plugins/maps/public/layers/joins/inner_join.js
+++ b/x-pack/legacy/plugins/maps/public/layers/joins/inner_join.js
@@ -6,13 +6,15 @@
import { ESTermSource } from '../sources/es_term_source';
-import { VectorStyle } from '../styles/vector_style';
+import { getComputedFieldNamePrefix } from '../styles/vector/style_util';
export class InnerJoin {
- constructor(joinDescriptor, inspectorAdapters) {
+ constructor(joinDescriptor, leftSource) {
this._descriptor = joinDescriptor;
+ const inspectorAdapters = leftSource.getInspectorAdapters();
this._rightSource = new ESTermSource(joinDescriptor.right, inspectorAdapters);
+ this._leftField = this._descriptor.leftField ? leftSource.createField({ fieldName: joinDescriptor.leftField }) : null;
}
destroy() {
@@ -20,20 +22,16 @@ export class InnerJoin {
}
hasCompleteConfig() {
- if (this._descriptor.leftField && this._rightSource) {
+ if (this._leftField && this._rightSource) {
return this._rightSource.hasCompleteConfig();
}
return false;
}
- getRightMetricFields() {
- return this._rightSource.getMetricFields();
- }
-
getJoinFields() {
- return this.getRightMetricFields().map(({ propertyKey: name, propertyLabel: label }) => {
- return { label, name };
+ return this._rightSource.getMetricFields().map(esAggMetricField => {
+ return { label: esAggMetricField.getPropertyLabel(), name: esAggMetricField.getName() };
});
}
@@ -44,18 +42,19 @@ export class InnerJoin {
return `join_source_${this._rightSource.getId()}`;
}
- getLeftFieldName() {
- return this._descriptor.leftField;
+ getLeftField() {
+ return this._leftField;
}
- joinPropertiesToFeature(feature, propertiesMap, rightMetricFields) {
+ joinPropertiesToFeature(feature, propertiesMap) {
+ const rightMetricFields = this._rightSource.getMetricFields();
// delete feature properties added by previous join
for (let j = 0; j < rightMetricFields.length; j++) {
- const { propertyKey: metricPropertyKey } = rightMetricFields[j];
+ const metricPropertyKey = rightMetricFields[j].getName();
delete feature.properties[metricPropertyKey];
// delete all dynamic properties for metric field
- const stylePropertyPrefix = VectorStyle.getComputedFieldNamePrefix(metricPropertyKey);
+ const stylePropertyPrefix = getComputedFieldNamePrefix(metricPropertyKey);
Object.keys(feature.properties).forEach(featurePropertyKey => {
if (featurePropertyKey.length >= stylePropertyPrefix.length &&
featurePropertyKey.substring(0, stylePropertyPrefix.length) === stylePropertyPrefix) {
@@ -64,7 +63,7 @@ export class InnerJoin {
});
}
- const joinKey = feature.properties[this._descriptor.leftField];
+ const joinKey = feature.properties[this._leftField.getName()];
const coercedKey = typeof joinKey === 'undefined' || joinKey === null ? null : joinKey.toString();
if (propertiesMap && coercedKey !== null && propertiesMap.has(coercedKey)) {
Object.assign(feature.properties, propertiesMap.get(coercedKey));
diff --git a/x-pack/legacy/plugins/maps/public/layers/joins/inner_join.test.js b/x-pack/legacy/plugins/maps/public/layers/joins/inner_join.test.js
index c493062723470..12790cae42ba2 100644
--- a/x-pack/legacy/plugins/maps/public/layers/joins/inner_join.test.js
+++ b/x-pack/legacy/plugins/maps/public/layers/joins/inner_join.test.js
@@ -23,12 +23,25 @@ const rightSource = {
indexPatternId: '90943e30-9a47-11e8-b64d-95841ca0b247',
indexPatternTitle: 'kibana_sample_data_logs',
term: 'geo.dest',
+ metrics: [{ type: 'count' }]
+};
+
+const mockSource = {
+ getInspectorAdapters() {
+ },
+ createField(name) {
+ return {
+ getName() {
+ return name;
+ }
+ };
+ }
};
const leftJoin = new InnerJoin({
leftField: 'iso2',
right: rightSource
-});
+}, mockSource);
const COUNT_PROPERTY_NAME = '__kbnjoin__count_groupby_kibana_sample_data_logs.geo.dest';
describe('joinPropertiesToFeature', () => {
@@ -76,7 +89,7 @@ describe('joinPropertiesToFeature', () => {
const leftJoin = new InnerJoin({
leftField: 'zipcode',
right: rightSource
- });
+ }, mockSource);
const feature = {
properties: {
@@ -118,7 +131,7 @@ describe('joinPropertiesToFeature', () => {
const leftJoin = new InnerJoin({
leftField: 'code',
right: rightSource
- });
+ }, mockSource);
const feature = {
properties: {
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/ems_file_source/ems_file_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/ems_file_source/ems_file_source.js
index 3af1378e8e016..9c1bd57873a2e 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/ems_file_source/ems_file_source.js
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/ems_file_source/ems_file_source.js
@@ -13,7 +13,7 @@ import { EMSFileCreateSourceEditor } from './create_source_editor';
import { i18n } from '@kbn/i18n';
import { getDataSourceLabel } from '../../../../common/i18n_getters';
import { UpdateSourceEditor } from './update_source_editor';
-import { TooltipProperty } from '../../tooltips/tooltip_property';
+import { EMSRegionLayerField } from '../../fields/ems_region_field';
export class EMSFileSource extends AbstractVectorSource {
@@ -45,19 +45,28 @@ export class EMSFileSource extends AbstractVectorSource {
constructor(descriptor, inspectorAdapters) {
super(EMSFileSource.createDescriptor(descriptor), inspectorAdapters);
+ this._tooltipFields = this._descriptor.tooltipProperties.map(propertyKey => this.createField({ fieldName: propertyKey }));
+ }
+
+ createField({ fieldName }) {
+ return new EMSRegionLayerField({
+ fieldName,
+ source: this
+ });
}
renderSourceSettingsEditor({ onChange }) {
return (
);
}
- async _getEMSFileLayer() {
+ async getEMSFileLayer() {
const emsClient = getEMSClient();
const emsFileLayers = await emsClient.getFileLayers();
const emsFileLayer = emsFileLayers.find((fileLayer => fileLayer.getId() === this._descriptor.id));
@@ -73,7 +82,7 @@ export class EMSFileSource extends AbstractVectorSource {
}
async getGeoJsonWithMeta() {
- const emsFileLayer = await this._getEMSFileLayer();
+ const emsFileLayer = await this.getEMSFileLayer();
const featureCollection = await AbstractVectorSource.getGeoJson({
format: emsFileLayer.getDefaultFormatType(),
featureCollectionPath: 'data',
@@ -98,7 +107,7 @@ export class EMSFileSource extends AbstractVectorSource {
async getImmutableProperties() {
let emsLink;
try {
- const emsFileLayer = await this._getEMSFileLayer();
+ const emsFileLayer = await this.getEMSFileLayer();
emsLink = emsFileLayer.getEMSHotLink();
} catch(error) {
// ignore error if EMS layer id could not be found
@@ -121,7 +130,7 @@ export class EMSFileSource extends AbstractVectorSource {
async getDisplayName() {
try {
- const emsFileLayer = await this._getEMSFileLayer();
+ const emsFileLayer = await this.getEMSFileLayer();
return emsFileLayer.getDisplayName();
} catch (error) {
return this._descriptor.id;
@@ -129,13 +138,13 @@ export class EMSFileSource extends AbstractVectorSource {
}
async getAttributions() {
- const emsFileLayer = await this._getEMSFileLayer();
+ const emsFileLayer = await this.getEMSFileLayer();
return emsFileLayer.getAttributions();
}
async getLeftJoinFields() {
- const emsFileLayer = await this._getEMSFileLayer();
+ const emsFileLayer = await this.getEMSFileLayer();
const fields = emsFileLayer.getFieldsInLanguage();
return fields.map(f => {
return { name: f.name, label: f.description };
@@ -143,22 +152,16 @@ export class EMSFileSource extends AbstractVectorSource {
}
canFormatFeatureProperties() {
- return this._descriptor.tooltipProperties.length;
+ return this._tooltipFields.length > 0;
}
async filterAndFormatPropertiesToHtml(properties) {
- const emsFileLayer = await this._getEMSFileLayer();
- const emsFields = emsFileLayer.getFieldsInLanguage();
-
- return this._descriptor.tooltipProperties.map(propertyName => {
- // Map EMS field name to language specific label
- const emsField = emsFields.find(field => {
- return field.name === propertyName;
- });
- const label = emsField ? emsField.description : propertyName;
-
- return new TooltipProperty(propertyName, label, properties[propertyName]);
+ const tooltipProperties = this._tooltipFields.map(field => {
+ const value = properties[field.getName()];
+ return field.createTooltipProperty(value);
});
+
+ return Promise.all(tooltipProperties);
}
async getSupportedShapeTypes() {
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/ems_file_source/ems_file_source.test.js b/x-pack/legacy/plugins/maps/public/layers/sources/ems_file_source/ems_file_source.test.js
index d9f759bdcc2cd..15581f1cfbacb 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/ems_file_source/ems_file_source.test.js
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/ems_file_source/ems_file_source.test.js
@@ -13,7 +13,7 @@ function makeEMSFileSource(tooltipProperties) {
const emsFileSource = new EMSFileSource({
tooltipProperties: tooltipProperties
});
- emsFileSource._getEMSFileLayer = () => {
+ emsFileSource.getEMSFileLayer = () => {
return {
getFieldsInLanguage() {
return [{
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/ems_file_source/update_source_editor.js b/x-pack/legacy/plugins/maps/public/layers/sources/ems_file_source/update_source_editor.js
index ccd7592649e21..705f45a9d69b6 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/ems_file_source/update_source_editor.js
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/ems_file_source/update_source_editor.js
@@ -8,12 +8,14 @@ import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { TooltipSelector } from '../../../components/tooltip_selector';
import { getEMSClient } from '../../../meta';
+import { EMSRegionLayerField } from '../../fields/ems_region_field';
export class UpdateSourceEditor extends Component {
static propTypes = {
onChange: PropTypes.func.isRequired,
- tooltipProperties: PropTypes.arrayOf(PropTypes.string).isRequired
+ tooltipFields: PropTypes.arrayOf(PropTypes.object).isRequired,
+ source: PropTypes.object
};
state = {
@@ -36,16 +38,15 @@ export class UpdateSourceEditor extends Component {
const emsFiles = await emsClient.getFileLayers();
const emsFile = emsFiles.find((emsFile => emsFile.getId() === this.props.layerId));
const emsFields = emsFile.getFieldsInLanguage();
- fields = emsFields.map(field => {
- return {
- name: field.name,
- label: field.description
- };
- });
+ fields = emsFields.map(field => new EMSRegionLayerField({
+ fieldName: field.name,
+ source: this.props.source
+ }));
} catch(e) {
//swallow this error. when a matching EMS-config cannot be found, the source already will have thrown errors during the data request. This will propagate to the vector-layer and be displayed in the UX
fields = [];
}
+
if (this._isMounted) {
this.setState({ fields: fields });
}
@@ -56,9 +57,14 @@ export class UpdateSourceEditor extends Component {
};
render() {
+
+ if (!this.state.fields) {
+ return null;
+ }
+
return (
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
new file mode 100644
index 0000000000000..5b8e6e4574cd8
--- /dev/null
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_agg_source.js
@@ -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 { AbstractESSource } from './es_source';
+import { ESAggMetricTooltipProperty } from '../tooltips/es_aggmetric_tooltip_property';
+import { ESAggMetricField } from '../fields/es_agg_field';
+import { ESDocField } from '../fields/es_doc_field';
+import { METRIC_TYPE } from '../../../common/constants';
+
+const COUNT_PROP_LABEL = METRIC_TYPE.COUNT;
+const COUNT_PROP_NAME = 'doc_count';
+
+const AGG_DELIMITER = '_of_';
+
+//todo: extract in separate PR
+export class AbstractESAggSource extends AbstractESSource {
+
+ static COUNT_PROP_LABEL = COUNT_PROP_LABEL;
+ static COUNT_PROP_NANE = COUNT_PROP_NAME;
+
+ constructor(descriptor, inspectorAdapters) {
+ super(descriptor, inspectorAdapters);
+ this._metricFields = this._descriptor.metrics ? this._descriptor.metrics.map(metric => {
+ const esDocField = metric.field ? new ESDocField({ fieldName: metric.field, source: this }) : null;
+ return new ESAggMetricField({
+ label: metric.label,
+ esDocField: esDocField,
+ aggType: metric.type,
+ source: this
+ });
+ }) : [];
+ }
+
+ createField({ fieldName, label }) {
+ if (fieldName === COUNT_PROP_NAME) {
+ return new ESAggMetricField({
+ aggType: METRIC_TYPE.COUNT,
+ label: label,
+ source: this
+ });
+ } else {
+ //this only works because aggType is a fixed set and does not include the `_of_` string
+ const [aggType, docField] = fieldName.split(AGG_DELIMITER);
+ const esDocField = new ESDocField({ fieldName: docField, source: this });
+ return new ESAggMetricField({
+ label: label,
+ esDocField,
+ aggType,
+ source: this
+ });
+ }
+ }
+
+ getMetricFieldForName(fieldName) {
+ return this._metricFields.find(metricField => {
+ return metricField.getName() === fieldName;
+ });
+ }
+
+ getMetricFields() {
+ const metrics = this._metricFields.filter(esAggField => esAggField.isValid());
+ if (metrics.length === 0) {
+ metrics.push(new ESAggMetricField({
+ aggType: METRIC_TYPE.COUNT,
+ source: this
+ }));
+ }
+ return metrics;
+ }
+
+ formatMetricKey(aggType, fieldName) {
+ return aggType !== METRIC_TYPE.COUNT ? `${aggType}${AGG_DELIMITER}${fieldName}` : METRIC_TYPE.COUNT;
+ }
+
+ formatMetricLabel(aggType, fieldName) {
+ return aggType !== METRIC_TYPE.COUNT ? `${aggType} of ${fieldName}` : METRIC_TYPE.COUNT;
+ }
+
+ createMetricAggConfigs() {
+ return this.getMetricFields().map(esAggMetric => esAggMetric.makeMetricAggConfig());
+ }
+
+
+ async getNumberFields() {
+ return this.getMetricFields().map(esAggMetricField => {
+ return { label: esAggMetricField.getPropertyLabel(), name: esAggMetricField.getName() };
+ });
+ }
+
+ async filterAndFormatPropertiesToHtmlForMetricFields(properties) {
+ let indexPattern;
+ try {
+ indexPattern = await this.getIndexPattern();
+ } catch(error) {
+ console.warn(`Unable to find Index pattern ${this._descriptor.indexPatternId}, values are not formatted`);
+ return properties;
+ }
+
+
+ const metricFields = this.getMetricFields();
+ const tooltipProperties = [];
+ metricFields.forEach((metricField) => {
+ let value;
+ for (const key in properties) {
+ if (properties.hasOwnProperty(key) && metricField.getName() === key) {
+ value = properties[key];
+ break;
+ }
+ }
+
+ const tooltipProperty = new ESAggMetricTooltipProperty(
+ metricField.getName(),
+ metricField.getPropertyLabel(),
+ value,
+ indexPattern,
+ metricField
+ );
+ tooltipProperties.push(tooltipProperty);
+ });
+
+ return tooltipProperties;
+
+ }
+}
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 776980e17bb13..12028a17ad334 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
@@ -8,15 +8,14 @@ import React from 'react';
import uuid from 'uuid/v4';
import { VECTOR_SHAPE_TYPES } from '../vector_feature_types';
-import { AbstractESSource } from '../es_source';
import { HeatmapLayer } from '../../heatmap_layer';
import { VectorLayer } from '../../vector_layer';
import { Schemas } from 'ui/vis/editors/default/schemas';
import { AggConfigs } from 'ui/agg_types';
import { tabifyAggResponse } from 'ui/agg_response/tabify';
import { convertToGeoJson } from './convert_to_geojson';
-import { VectorStyle } from '../../styles/vector_style';
-import { vectorStyles } from '../../styles/vector_style_defaults';
+import { VectorStyle } from '../../styles/vector/vector_style';
+import { vectorStyles } from '../../styles/vector/vector_style_defaults';
import { RENDER_AS } from './render_as';
import { CreateSourceEditor } from './create_source_editor';
import { UpdateSourceEditor } from './update_source_editor';
@@ -24,9 +23,9 @@ import { GRID_RESOLUTION } from '../../grid_resolution';
import { SOURCE_DATA_ID_ORIGIN, ES_GEO_GRID, METRIC_TYPE } from '../../../../common/constants';
import { i18n } from '@kbn/i18n';
import { getDataSourceLabel } from '../../../../common/i18n_getters';
+import { AbstractESAggSource } from '../es_agg_source';
+import { DynamicStyleProperty } from '../../styles/vector/properties/dynamic_style_property';
-const COUNT_PROP_LABEL = 'count';
-const COUNT_PROP_NAME = 'doc_count';
const MAX_GEOTILE_LEVEL = 29;
const aggSchemas = new Schemas([
@@ -58,7 +57,7 @@ const aggSchemas = new Schemas([
}
]);
-export class ESGeoGridSource extends AbstractESSource {
+export class ESGeoGridSource extends AbstractESAggSource {
static type = ES_GEO_GRID;
static title = i18n.translate('xpack.maps.source.esGridTitle', {
@@ -109,7 +108,7 @@ export class ESGeoGridSource extends AbstractESSource {
async getImmutableProperties() {
let indexPatternTitle = this._descriptor.indexPatternId;
try {
- const indexPattern = await this._getIndexPattern();
+ const indexPattern = await this.getIndexPattern();
indexPatternTitle = indexPattern.title;
} catch (error) {
// ignore error, title will just default to id
@@ -141,9 +140,7 @@ export class ESGeoGridSource extends AbstractESSource {
}
getFieldNames() {
- return this.getMetricFields().map(({ propertyKey }) => {
- return propertyKey;
- });
+ return this.getMetricFields().map((esAggMetricField => esAggMetricField.getName()));
}
isGeoGridPrecisionAware() {
@@ -184,14 +181,8 @@ export class ESGeoGridSource extends AbstractESSource {
}));
}
- async getNumberFields() {
- return this.getMetricFields().map(({ propertyKey: name, propertyLabel: label }) => {
- return { label, name };
- });
- }
-
async getGeoJsonWithMeta(layerName, searchFilters, registerCancelCallback) {
- const indexPattern = await this._getIndexPattern();
+ const indexPattern = await this.getIndexPattern();
const searchSource = await this._makeSearchSource(searchFilters, 0);
const aggConfigs = new AggConfigs(indexPattern, this._makeAggConfigs(searchFilters.geogridPrecision), aggSchemas.all);
searchSource.setField('aggs', aggConfigs.toDsl());
@@ -221,29 +212,8 @@ export class ESGeoGridSource extends AbstractESSource {
return true;
}
- _formatMetricKey(metric) {
- return metric.type !== METRIC_TYPE.COUNT ? `${metric.type}_of_${metric.field}` : COUNT_PROP_NAME;
- }
-
- _formatMetricLabel(metric) {
- return metric.type !== METRIC_TYPE.COUNT ? `${metric.type} of ${metric.field}` : COUNT_PROP_LABEL;
- }
-
_makeAggConfigs(precision) {
- const metricAggConfigs = this.getMetricFields().map(metric => {
- const metricAggConfig = {
- id: metric.propertyKey,
- enabled: true,
- type: metric.type,
- schema: 'metric',
- params: {}
- };
- if (metric.type !== METRIC_TYPE.COUNT) {
- metricAggConfig.params = { field: metric.field };
- }
- return metricAggConfig;
- });
-
+ const metricAggConfigs = this.createMetricAggConfigs();
return [
...metricAggConfigs,
{
@@ -274,22 +244,22 @@ export class ESGeoGridSource extends AbstractESSource {
});
descriptor.style = VectorStyle.createDescriptor({
[vectorStyles.FILL_COLOR]: {
- type: VectorStyle.STYLE_TYPE.DYNAMIC,
+ type: DynamicStyleProperty.type,
options: {
field: {
- label: COUNT_PROP_LABEL,
- name: COUNT_PROP_NAME,
+ label: AbstractESAggSource.COUNT_PROP_LABEL,
+ name: AbstractESAggSource.COUNT_PROP_NANE,
origin: SOURCE_DATA_ID_ORIGIN
},
color: 'Blues'
}
},
[vectorStyles.ICON_SIZE]: {
- type: VectorStyle.STYLE_TYPE.DYNAMIC,
+ type: DynamicStyleProperty.type,
options: {
field: {
- label: COUNT_PROP_LABEL,
- name: COUNT_PROP_NAME,
+ label: AbstractESAggSource.COUNT_PROP_LABEL,
+ name: AbstractESAggSource.COUNT_PROP_NANE,
origin: SOURCE_DATA_ID_ORIGIN
},
minSize: 4,
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/es_pew_pew_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/es_pew_pew_source.js
index 3debfdf1541f7..29be8eb4ba0c2 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/es_pew_pew_source.js
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_pew_pew_source/es_pew_pew_source.js
@@ -8,21 +8,20 @@ import React from 'react';
import uuid from 'uuid/v4';
import { VECTOR_SHAPE_TYPES } from '../vector_feature_types';
-import { AbstractESSource } from '../es_source';
import { VectorLayer } from '../../vector_layer';
import { CreateSourceEditor } from './create_source_editor';
import { UpdateSourceEditor } from './update_source_editor';
-import { VectorStyle } from '../../styles/vector_style';
-import { vectorStyles } from '../../styles/vector_style_defaults';
+import { VectorStyle } from '../../styles/vector/vector_style';
+import { vectorStyles } from '../../styles/vector/vector_style_defaults';
import { i18n } from '@kbn/i18n';
import { SOURCE_DATA_ID_ORIGIN, ES_PEW_PEW, METRIC_TYPE } from '../../../../common/constants';
import { getDataSourceLabel } from '../../../../common/i18n_getters';
import { convertToLines } from './convert_to_lines';
import { Schemas } from 'ui/vis/editors/default/schemas';
import { AggConfigs } from 'ui/agg_types';
+import { AbstractESAggSource } from '../es_agg_source';
+import { DynamicStyleProperty } from '../../styles/vector/properties/dynamic_style_property';
-const COUNT_PROP_LABEL = 'count';
-const COUNT_PROP_NAME = 'doc_count';
const MAX_GEOTILE_LEVEL = 29;
const aggSchemas = new Schemas([
@@ -46,7 +45,7 @@ const aggSchemas = new Schemas([
}
]);
-export class ESPewPewSource extends AbstractESSource {
+export class ESPewPewSource extends AbstractESAggSource {
static type = ES_PEW_PEW;
static title = i18n.translate('xpack.maps.source.pewPewTitle', {
@@ -103,12 +102,6 @@ export class ESPewPewSource extends AbstractESSource {
return true;
}
- async getNumberFields() {
- return this.getMetricFields().map(({ propertyKey: name, propertyLabel: label }) => {
- return { label, name };
- });
- }
-
async getSupportedShapeTypes() {
return [VECTOR_SHAPE_TYPES.LINE];
}
@@ -116,7 +109,7 @@ export class ESPewPewSource extends AbstractESSource {
async getImmutableProperties() {
let indexPatternTitle = this._descriptor.indexPatternId;
try {
- const indexPattern = await this._getIndexPattern();
+ const indexPattern = await this.getIndexPattern();
indexPatternTitle = indexPattern.title;
} catch (error) {
// ignore error, title will just default to id
@@ -150,22 +143,22 @@ export class ESPewPewSource extends AbstractESSource {
createDefaultLayer(options) {
const styleDescriptor = VectorStyle.createDescriptor({
[vectorStyles.LINE_COLOR]: {
- type: VectorStyle.STYLE_TYPE.DYNAMIC,
+ type: DynamicStyleProperty.type,
options: {
field: {
- label: COUNT_PROP_LABEL,
- name: COUNT_PROP_NAME,
+ label: AbstractESAggSource.COUNT_PROP_LABEL,
+ name: AbstractESAggSource.COUNT_PROP_NANE,
origin: SOURCE_DATA_ID_ORIGIN
},
color: 'Blues'
}
},
[vectorStyles.LINE_WIDTH]: {
- type: VectorStyle.STYLE_TYPE.DYNAMIC,
+ type: DynamicStyleProperty.type,
options: {
field: {
- label: COUNT_PROP_LABEL,
- name: COUNT_PROP_NAME,
+ label: AbstractESAggSource.COUNT_PROP_LABEL,
+ name: AbstractESAggSource.COUNT_PROP_NANE,
origin: SOURCE_DATA_ID_ORIGIN
},
minSize: 4,
@@ -191,20 +184,9 @@ export class ESPewPewSource extends AbstractESSource {
}
async getGeoJsonWithMeta(layerName, searchFilters, registerCancelCallback) {
- const indexPattern = await this._getIndexPattern();
- const metricAggConfigs = this.getMetricFields().map(metric => {
- const metricAggConfig = {
- id: metric.propertyKey,
- enabled: true,
- type: metric.type,
- schema: 'metric',
- params: {}
- };
- if (metric.type !== METRIC_TYPE.COUNT) {
- metricAggConfig.params = { field: metric.field };
- }
- return metricAggConfig;
- });
+
+ const metricAggConfigs = this.createMetricAggConfigs();
+ const indexPattern = await this.getIndexPattern();
const aggConfigs = new AggConfigs(indexPattern, metricAggConfigs, aggSchemas.all);
const searchSource = await this._makeSearchSource(searchFilters, 0);
@@ -258,16 +240,8 @@ export class ESPewPewSource extends AbstractESSource {
};
}
- _formatMetricKey(metric) {
- return metric.type !== METRIC_TYPE.COUNT ? `${metric.type}_of_${metric.field}` : COUNT_PROP_NAME;
- }
-
- _formatMetricLabel(metric) {
- return metric.type !== METRIC_TYPE.COUNT ? `${metric.type} of ${metric.field}` : COUNT_PROP_LABEL;
- }
-
async _getGeoField() {
- const indexPattern = await this._getIndexPattern();
+ const indexPattern = await this.getIndexPattern();
const geoField = indexPattern.fields.getByName(this._descriptor.destGeoField);
if (!geoField) {
throw new Error(i18n.translate('xpack.maps.source.esSource.noGeoFieldErrorMessage', {
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/__snapshots__/update_source_editor.test.js.snap b/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/__snapshots__/update_source_editor.test.js.snap
index c0e443758ada6..4bfa1ef79cc99 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/__snapshots__/update_source_editor.test.js.snap
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/__snapshots__/update_source_editor.test.js.snap
@@ -13,7 +13,7 @@ exports[`should enable sort order select when sort field provided 1`] = `
this.createField(property));
+ }
+
+ createField({ fieldName }) {
+ return new ESDocField({
+ fieldName,
+ source: this
+ });
}
renderSourceSettingsEditor({ onChange }) {
return (
{
return { name: field.name, label: field.name };
});
@@ -98,7 +108,7 @@ export class ESSearchSource extends AbstractESSource {
async getDateFields() {
try {
- const indexPattern = await this._getIndexPattern();
+ const indexPattern = await this.getIndexPattern();
return indexPattern.fields.getByType('date').map(field => {
return { name: field.name, label: field.name };
});
@@ -107,10 +117,6 @@ export class ESSearchSource extends AbstractESSource {
}
}
- getMetricFields() {
- return [];
- }
-
getFieldNames() {
return [this._descriptor.geoField];
}
@@ -119,7 +125,7 @@ export class ESSearchSource extends AbstractESSource {
let indexPatternTitle = this._descriptor.indexPatternId;
let geoFieldType = '';
try {
- const indexPattern = await this._getIndexPattern();
+ const indexPattern = await this.getIndexPattern();
indexPatternTitle = indexPattern.title;
const geoField = await this._getGeoField();
geoFieldType = geoField.type;
@@ -196,7 +202,7 @@ export class ESSearchSource extends AbstractESSource {
topHitsSize,
} = this._descriptor;
- const indexPattern = await this._getIndexPattern();
+ const indexPattern = await this.getIndexPattern();
const geoField = await this._getGeoField();
const scriptFields = {};
@@ -327,7 +333,7 @@ export class ESSearchSource extends AbstractESSource {
? await this._getTopHits(layerName, searchFilters, registerCancelCallback)
: await this._getSearchHits(layerName, searchFilters, registerCancelCallback);
- const indexPattern = await this._getIndexPattern();
+ const indexPattern = await this.getIndexPattern();
const unusedMetaFields = indexPattern.metaFields.filter(metaField => {
return !['_id', '_index'].includes(metaField);
});
@@ -360,11 +366,11 @@ export class ESSearchSource extends AbstractESSource {
}
canFormatFeatureProperties() {
- return this._descriptor.tooltipProperties.length > 0;
+ return this._tooltipFields.length > 0;
}
async _loadTooltipProperties(docId, index, indexPattern) {
- if (this._descriptor.tooltipProperties.length === 0) {
+ if (this._tooltipFields.length === 0) {
return {};
}
@@ -376,7 +382,7 @@ export class ESSearchSource extends AbstractESSource {
query: `_id:"${docId}" and _index:${index}`
};
searchSource.setField('query', query);
- searchSource.setField('fields', this._descriptor.tooltipProperties);
+ searchSource.setField('fields', this._getTooltipPropertyNames());
const resp = await searchSource.fetch();
@@ -392,7 +398,7 @@ export class ESSearchSource extends AbstractESSource {
const properties = indexPattern.flattenHit(hit);
indexPattern.metaFields.forEach(metaField => {
- if (!this._descriptor.tooltipProperties.includes(metaField)) {
+ if (!this._getTooltipPropertyNames().includes(metaField)) {
delete properties[metaField];
}
});
@@ -400,12 +406,13 @@ export class ESSearchSource extends AbstractESSource {
}
async filterAndFormatPropertiesToHtml(properties) {
- const indexPattern = await this._getIndexPattern();
+ const indexPattern = await this.getIndexPattern();
const propertyValues = await this._loadTooltipProperties(properties._id, properties._index, indexPattern);
-
- return this._descriptor.tooltipProperties.map(propertyName => {
- return new ESTooltipProperty(propertyName, propertyName, propertyValues[propertyName], indexPattern);
+ const tooltipProperties = this._tooltipFields.map(field => {
+ const value = propertyValues[field.getName()];
+ return field.createTooltipProperty(value);
});
+ return Promise.all(tooltipProperties);
}
isFilterByMapBounds() {
@@ -413,7 +420,7 @@ export class ESSearchSource extends AbstractESSource {
}
async getLeftJoinFields() {
- const indexPattern = await this._getIndexPattern();
+ const indexPattern = await this.getIndexPattern();
// Left fields are retrieved from _source.
return getSourceFields(indexPattern.fields)
.map(field => {
@@ -505,7 +512,6 @@ export class ESSearchSource extends AbstractESSource {
async getPreIndexedShape(properties) {
const geoField = await this._getGeoField();
-
return {
index: properties._index, // Can not use index pattern title because it may reference many indices
id: properties._id,
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/update_source_editor.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/update_source_editor.js
index 3678af4d54940..05bdfe701e356 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/update_source_editor.js
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/update_source_editor.js
@@ -21,18 +21,20 @@ import { i18n } from '@kbn/i18n';
import { getTermsFields, getSourceFields } from '../../../index_pattern_util';
import { ValidatedRange } from '../../../components/validated_range';
import { SORT_ORDER } from '../../../../common/constants';
+import { ESDocField } from '../../fields/es_doc_field';
export class UpdateSourceEditor extends Component {
static propTypes = {
indexPatternId: PropTypes.string.isRequired,
onChange: PropTypes.func.isRequired,
filterByMapBounds: PropTypes.bool.isRequired,
- tooltipProperties: PropTypes.arrayOf(PropTypes.string).isRequired,
+ tooltipFields: PropTypes.arrayOf(PropTypes.object).isRequired,
sortField: PropTypes.string,
sortOrder: PropTypes.string.isRequired,
useTopHits: PropTypes.bool.isRequired,
topHitsSplitField: PropTypes.string,
topHitsSize: PropTypes.number.isRequired,
+ source: PropTypes.object
};
state = {
@@ -72,10 +74,19 @@ export class UpdateSourceEditor extends Component {
return;
}
+ //todo move this all to the source
+ const rawTooltipFields = getSourceFields(indexPattern.fields);
+ const tooltipFields = rawTooltipFields.map(field => {
+ return new ESDocField({
+ fieldName: field.name,
+ source: this.props.source
+ });
+ });
+
this.setState({
- tooltipFields: getSourceFields(indexPattern.fields),
- termFields: getTermsFields(indexPattern.fields),
- sortFields: indexPattern.fields.filter(field => field.sortable),
+ tooltipFields: tooltipFields,
+ termFields: getTermsFields(indexPattern.fields), //todo change term fields to use fields
+ sortFields: indexPattern.fields.filter(field => field.sortable), //todo change sort fields to use fields
});
}
_onTooltipPropertiesChange = propertyNames => {
@@ -168,7 +179,7 @@ export class UpdateSourceEditor extends Component {
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/update_source_editor.test.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/update_source_editor.test.js
index 9a3a74e0ed680..5a1b83589a1ee 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/update_source_editor.test.js
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/update_source_editor.test.js
@@ -15,7 +15,7 @@ const defaultProps = {
indexPatternId: 'indexPattern1',
onChange: () => {},
filterByMapBounds: true,
- tooltipProperties: [],
+ tooltipFields: [],
sortOrder: 'DESC',
useTopHits: false,
topHitsSplitField: 'trackId',
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_source.js
index 85c866479a6ba..5f72727f71897 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/es_source.js
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_source.js
@@ -15,11 +15,10 @@ import { timefilter } from 'ui/timefilter';
import _ from 'lodash';
import { AggConfigs } from 'ui/agg_types';
import { i18n } from '@kbn/i18n';
-import { ESAggMetricTooltipProperty } from '../tooltips/es_aggmetric_tooltip_property';
import uuid from 'uuid/v4';
import { copyPersistentState } from '../../reducers/util';
-import { ES_GEO_FIELD_TYPE, METRIC_TYPE } from '../../../common/constants';
+import { ES_GEO_FIELD_TYPE } from '../../../common/constants';
import { DataRequestAbortError } from '../util/data_request';
export class AbstractESSource extends AbstractVectorSource {
@@ -57,81 +56,6 @@ export class AbstractESSource extends AbstractVectorSource {
return clonedDescriptor;
}
- _getValidMetrics() {
- const metrics = _.get(this._descriptor, 'metrics', []).filter(({ type, field }) => {
- if (type === METRIC_TYPE.COUNT) {
- return true;
- }
-
- if (field) {
- return true;
- }
- return false;
- });
- if (metrics.length === 0) {
- metrics.push({ type: METRIC_TYPE.COUNT });
- }
- return metrics;
- }
-
- _formatMetricKey() {
- throw new Error('should implement');
- }
-
- _formatMetricLabel() {
- throw new Error('should implement');
- }
-
- getMetricFields() {
- return this._getValidMetrics().map(metric => {
- const metricKey = this._formatMetricKey(metric);
- const metricLabel = metric.label ? metric.label : this._formatMetricLabel(metric);
- const metricCopy = { ...metric };
- delete metricCopy.label;
- return {
- ...metricCopy,
- propertyKey: metricKey,
- propertyLabel: metricLabel
- };
- });
- }
-
- async filterAndFormatPropertiesToHtmlForMetricFields(properties) {
- let indexPattern;
- try {
- indexPattern = await this._getIndexPattern();
- } catch(error) {
- console.warn(`Unable to find Index pattern ${this._descriptor.indexPatternId}, values are not formatted`);
- return properties;
- }
-
-
- const metricFields = this.getMetricFields();
- const tooltipProperties = [];
- metricFields.forEach((metricField) => {
- let value;
- for (const key in properties) {
- if (properties.hasOwnProperty(key) && metricField.propertyKey === key) {
- value = properties[key];
- break;
- }
- }
-
- const tooltipProperty = new ESAggMetricTooltipProperty(
- metricField.propertyKey,
- metricField.propertyLabel,
- value,
- indexPattern,
- metricField
- );
- tooltipProperties.push(tooltipProperty);
- });
-
- return tooltipProperties;
-
- }
-
-
async _runEsQuery(requestName, searchSource, registerCancelCallback, requestDescription) {
const abortController = new AbortController();
registerCancelCallback(() => abortController.abort());
@@ -158,7 +82,7 @@ export class AbstractESSource extends AbstractVectorSource {
}
async _makeSearchSource(searchFilters, limit, initialSearchContext) {
- const indexPattern = await this._getIndexPattern();
+ const indexPattern = await this.getIndexPattern();
const isTimeAware = await this.isTimeAware();
const applyGlobalQuery = _.get(searchFilters, 'applyGlobalQuery', true);
const globalFilters = applyGlobalQuery ? searchFilters.filters : [];
@@ -193,7 +117,7 @@ export class AbstractESSource extends AbstractVectorSource {
const searchSource = await this._makeSearchSource({ sourceQuery, query, timeFilters, filters, applyGlobalQuery }, 0);
const geoField = await this._getGeoField();
- const indexPattern = await this._getIndexPattern();
+ const indexPattern = await this.getIndexPattern();
const geoBoundsAgg = [{
type: 'geo_bounds',
@@ -234,7 +158,7 @@ export class AbstractESSource extends AbstractVectorSource {
async isTimeAware() {
try {
- const indexPattern = await this._getIndexPattern();
+ const indexPattern = await this.getIndexPattern();
const timeField = indexPattern.timeFieldName;
return !!timeField;
} catch (error) {
@@ -242,7 +166,7 @@ export class AbstractESSource extends AbstractVectorSource {
}
}
- async _getIndexPattern() {
+ async getIndexPattern() {
if (this.indexPattern) {
return this.indexPattern;
}
@@ -271,7 +195,7 @@ export class AbstractESSource extends AbstractVectorSource {
async _getGeoField() {
- const indexPattern = await this._getIndexPattern();
+ const indexPattern = await this.getIndexPattern();
const geoField = indexPattern.fields.getByName(this._descriptor.geoField);
if (!geoField) {
throw new Error(i18n.translate('xpack.maps.source.esSource.noGeoFieldErrorMessage', {
@@ -284,7 +208,7 @@ export class AbstractESSource extends AbstractVectorSource {
async getDisplayName() {
try {
- const indexPattern = await this._getIndexPattern();
+ const indexPattern = await this.getIndexPattern();
return indexPattern.title;
} catch (error) {
// Unable to load index pattern, just return id as display name
@@ -300,31 +224,31 @@ export class AbstractESSource extends AbstractVectorSource {
return this._descriptor.id;
}
- async getFieldFormatter(fieldName) {
- const metricField = this.getMetricFields().find(({ propertyKey }) => {
- return propertyKey === fieldName;
- });
+ _getRawFieldName(fieldName) {
+ const metricField = this.getMetricFields().find((esAggMetricField) => esAggMetricField.getName() === fieldName);
+ return metricField ? metricField.getESDocFieldName() : null;
+ }
- // Do not use field formatters for counting metrics
- if (metricField && metricField.type === METRIC_TYPE.COUNT || metricField.type === METRIC_TYPE.UNIQUE_COUNT) {
+ async getFieldFormatter(fieldName) {
+ // fieldName could be an aggregation so it needs to be unpacked to expose raw field.
+ const rawFieldName = this._getRawFieldName(fieldName);
+ if (!rawFieldName) {
return null;
}
let indexPattern;
try {
- indexPattern = await this._getIndexPattern();
+ indexPattern = await this.getIndexPattern();
} catch(error) {
return null;
}
- const realFieldName = metricField
- ? metricField.field
- : fieldName;
- const fieldFromIndexPattern = indexPattern.fields.getByName(realFieldName);
+ const fieldFromIndexPattern = indexPattern.fields.getByName(rawFieldName);
if (!fieldFromIndexPattern) {
return null;
}
return fieldFromIndexPattern.format.getConverterFor('text');
}
+
}
diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/es_term_source.js b/x-pack/legacy/plugins/maps/public/layers/sources/es_term_source.js
index 1f5adc00cca6f..37af2ea4a97d2 100644
--- a/x-pack/legacy/plugins/maps/public/layers/sources/es_term_source.js
+++ b/x-pack/legacy/plugins/maps/public/layers/sources/es_term_source.js
@@ -6,15 +6,18 @@
import _ from 'lodash';
-import { AbstractESSource } from './es_source';
import { Schemas } from 'ui/vis/editors/default/schemas';
import { AggConfigs } from 'ui/agg_types';
import { i18n } from '@kbn/i18n';
-import { ESTooltipProperty } from '../tooltips/es_tooltip_property';
import { ES_SIZE_LIMIT, METRIC_TYPE } from '../../../common/constants';
+import { ESDocField } from '../fields/es_doc_field';
+import { AbstractESAggSource } from './es_agg_source';
const TERMS_AGG_NAME = 'join';
+const FIELD_NAME_PREFIX = '__kbnjoin__';
+const GROUP_BY_DELIMITER = '_groupby_';
+
const aggSchemas = new Schemas([
{
group: 'metrics',
@@ -61,16 +64,24 @@ export function extractPropertiesMap(rawEsData, propertyNames, countPropertyName
return propertiesMap;
}
-export class ESTermSource extends AbstractESSource {
+export class ESTermSource extends AbstractESAggSource {
static type = 'ES_TERM_SOURCE';
+ constructor(descriptor, inspectorAdapters) {
+ super(descriptor, inspectorAdapters);
+ this._termField = new ESDocField({ fieldName: descriptor.term, source: this });
+ }
static renderEditor({}) {
//no need to localize. this editor is never rendered.
return `editor details
`;
}
+ createField() {
+ throw new Error('Not implemented. Should retrieve corresponding field from the inner_join.metrics config.');
+ }
+
hasCompleteConfig() {
return (_.has(this._descriptor, 'indexPatternId') && _.has(this._descriptor, 'term'));
}
@@ -79,22 +90,22 @@ export class ESTermSource extends AbstractESSource {
return [this._descriptor.indexPatternId];
}
- getTerm() {
- return this._descriptor.term;
+ getTermField() {
+ return this._termField;
}
getWhereQuery() {
return this._descriptor.whereQuery;
}
- _formatMetricKey(metric) {
- const metricKey = metric.type !== METRIC_TYPE.COUNT ? `${metric.type}_of_${metric.field}` : metric.type;
- return `__kbnjoin__${metricKey}_groupby_${this._descriptor.indexPatternTitle}.${this._descriptor.term}`;
+ formatMetricKey(aggType, fieldName) {
+ const metricKey = aggType !== METRIC_TYPE.COUNT ? `${aggType}_of_${fieldName}` : aggType;
+ return `${FIELD_NAME_PREFIX}${metricKey}${GROUP_BY_DELIMITER}${this._descriptor.indexPatternTitle}.${this._termField.getName()}`;
}
- _formatMetricLabel(metric) {
- const metricLabel = metric.type !== METRIC_TYPE.COUNT ? `${metric.type} ${metric.field}` : 'count';
- return `${metricLabel} of ${this._descriptor.indexPatternTitle}:${this._descriptor.term}`;
+ formatMetricLabel(type, fieldName) {
+ const metricLabel = type !== METRIC_TYPE.COUNT ? `${type} ${fieldName}` : 'count';
+ return `${metricLabel} of ${this._descriptor.indexPatternTitle}:${this._termField.getName()}`;
}
async getPropertiesMap(searchFilters, leftSourceName, leftFieldName, registerCancelCallback) {
@@ -103,13 +114,13 @@ export class ESTermSource extends AbstractESSource {
return [];
}
- const indexPattern = await this._getIndexPattern();
+ const indexPattern = await this.getIndexPattern();
const searchSource = await this._makeSearchSource(searchFilters, 0);
const configStates = this._makeAggConfigs();
const aggConfigs = new AggConfigs(indexPattern, configStates, aggSchemas.all);
searchSource.setField('aggs', aggConfigs.toDsl());
- const requestName = `${this._descriptor.indexPatternTitle}.${this._descriptor.term}`;
+ const requestName = `${this._descriptor.indexPatternTitle}.${this._termField.getName()}`;
const requestDesc = this._getRequestDescription(leftSourceName, leftFieldName);
const rawEsData = await this._runEsQuery(requestName, searchSource, registerCancelCallback, requestDesc);
@@ -134,15 +145,13 @@ export class ESTermSource extends AbstractESSource {
}
_getRequestDescription(leftSourceName, leftFieldName) {
- const metrics = this._getValidMetrics().map(metric => {
- return metric.type !== METRIC_TYPE.COUNT ? `${metric.type} ${metric.field}` : 'count';
- });
+ const metrics = this.getMetricFields().map(esAggMetric => esAggMetric.getRequestDescription());
const joinStatement = [];
joinStatement.push(i18n.translate('xpack.maps.source.esJoin.joinLeftDescription', {
defaultMessage: `Join {leftSourceName}:{leftFieldName} with`,
values: { leftSourceName, leftFieldName }
}));
- joinStatement.push(`${this._descriptor.indexPatternTitle}:${this._descriptor.term}`);
+ joinStatement.push(`${this._descriptor.indexPatternTitle}:${this._termField.getName()}`);
joinStatement.push(i18n.translate('xpack.maps.source.esJoin.joinMetricsDescription', {
defaultMessage: `for metrics {metrics}`,
values: { metrics: metrics.join(',') }
@@ -156,20 +165,7 @@ export class ESTermSource extends AbstractESSource {
}
_makeAggConfigs() {
- const metricAggConfigs = this.getMetricFields().map(metric => {
- const metricAggConfig = {
- id: metric.propertyKey,
- enabled: true,
- type: metric.type,
- schema: 'metric',
- params: {}
- };
- if (metric.type !== METRIC_TYPE.COUNT) {
- metricAggConfig.params = { field: metric.field };
- }
- return metricAggConfig;
- });
-
+ const metricAggConfigs = this.createMetricAggConfigs();
return [
...metricAggConfigs,
{
@@ -178,7 +174,7 @@ export class ESTermSource extends AbstractESSource {
type: 'terms',
schema: 'segment',
params: {
- field: this._descriptor.term,
+ field: this._termField.getName(),
size: ES_SIZE_LIMIT
}
}
@@ -194,21 +190,7 @@ export class ESTermSource extends AbstractESSource {
return await this.filterAndFormatPropertiesToHtmlForMetricFields(properties);
}
- async createESTooltipProperty(propertyName, rawValue) {
- try {
- const indexPattern = await this._getIndexPattern();
- if (!indexPattern) {
- return null;
- }
- return new ESTooltipProperty(propertyName, propertyName, rawValue, indexPattern);
- } catch (e) {
- return null;
- }
- }
-
getFieldNames() {
- return this.getMetricFields().map(({ propertyKey }) => {
- return propertyKey;
- });
+ return this.getMetricFields().map(esAggMetricField => esAggMetricField.getName());
}
}
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 b3e8c1b019f28..e8f0829cfd8b8 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
@@ -7,7 +7,7 @@
import { VectorLayer } from '../vector_layer';
import { TooltipProperty } from '../tooltips/tooltip_property';
-import { VectorStyle } from '../styles/vector_style';
+import { VectorStyle } from '../styles/vector/vector_style';
import { AbstractSource } from './source';
import * as topojson from 'topojson-client';
import _ from 'lodash';
@@ -48,6 +48,10 @@ export class AbstractVectorSource extends AbstractSource {
}));
}
+ createField() {
+ throw new Error(`Should implemement ${this.constructor.type} ${this}`);
+ }
+
_createDefaultLayerDescriptor(options, mapColors) {
return VectorLayer.createDescriptor(
{
@@ -57,6 +61,10 @@ export class AbstractVectorSource extends AbstractSource {
mapColors);
}
+ _getTooltipPropertyNames() {
+ return this._tooltipFields.map(field => field.getName());
+ }
+
createDefaultLayer(options, mapColors) {
const layerDescriptor = this._createDefaultLayerDescriptor(options, mapColors);
const style = new VectorStyle(layerDescriptor.style, this);
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/_color_gradient.scss b/x-pack/legacy/plugins/maps/public/layers/styles/_color_gradient.scss
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/_color_gradient.scss
rename to x-pack/legacy/plugins/maps/public/layers/styles/_color_gradient.scss
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/_index.scss b/x-pack/legacy/plugins/maps/public/layers/styles/_index.scss
index 87c7bd1face64..971f92fe76152 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/_index.scss
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/_index.scss
@@ -1,3 +1,3 @@
-@import './components/color_gradient';
-@import './components/static_dynamic_style_row';
-@import './components/vector/color/color_stops';
+@import './color_gradient';
+@import 'vector/components/static_dynamic_style_row';
+@import 'vector/components/vector/color/color_stops';
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/color_gradient.js b/x-pack/legacy/plugins/maps/public/layers/styles/color_gradient.js
similarity index 96%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/color_gradient.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/color_gradient.js
index b416d869e592b..d5a75586eb80a 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/components/color_gradient.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/color_gradient.js
@@ -5,7 +5,7 @@
*/
import React from 'react';
-import { COLOR_RAMP_NAMES, getRGBColorRangeStrings, getLinearGradient } from '../color_utils';
+import { COLOR_RAMP_NAMES, getRGBColorRangeStrings, getLinearGradient } from './color_utils';
import classNames from 'classnames';
export const ColorGradient = ({ colorRamp, colorRampName, className }) => {
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/color_utils.js b/x-pack/legacy/plugins/maps/public/layers/styles/color_utils.js
index 78a7c9d51739a..9e96b25645ada 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/color_utils.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/color_utils.js
@@ -8,7 +8,7 @@ import React from 'react';
import { vislibColorMaps } from 'ui/vislib/components/color/colormaps';
import { getLegendColors, getColor } from 'ui/vis/map/color_util';
-import { ColorGradient } from './components/color_gradient';
+import { ColorGradient } from './color_gradient';
import { palettes } from '@elastic/eui/lib/services';
import tinycolor from 'tinycolor2';
import chroma from 'chroma-js';
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/heatmap/__snapshots__/heatmap_style_editor.test.js.snap b/x-pack/legacy/plugins/maps/public/layers/styles/heatmap/components/__snapshots__/heatmap_style_editor.test.js.snap
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/heatmap/__snapshots__/heatmap_style_editor.test.js.snap
rename to x-pack/legacy/plugins/maps/public/layers/styles/heatmap/components/__snapshots__/heatmap_style_editor.test.js.snap
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/heatmap/heatmap_constants.js b/x-pack/legacy/plugins/maps/public/layers/styles/heatmap/components/heatmap_constants.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/heatmap/heatmap_constants.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/heatmap/components/heatmap_constants.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/heatmap/heatmap_style_editor.js b/x-pack/legacy/plugins/maps/public/layers/styles/heatmap/components/heatmap_style_editor.js
similarity index 95%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/heatmap/heatmap_style_editor.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/heatmap/components/heatmap_style_editor.js
index 0aa20f29c341b..f461bb580b281 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/components/heatmap/heatmap_style_editor.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/heatmap/components/heatmap_style_editor.js
@@ -8,7 +8,7 @@ import React from 'react';
import { EuiFormRow, EuiSuperSelect } from '@elastic/eui';
import { COLOR_GRADIENTS } from '../../color_utils';
-import { ColorGradient } from '../color_gradient';
+import { ColorGradient } from '../../color_gradient';
import {
DEFAULT_RGB_HEATMAP_COLOR_RAMP,
DEFAULT_HEATMAP_COLOR_RAMP_NAME,
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/heatmap/heatmap_style_editor.test.js b/x-pack/legacy/plugins/maps/public/layers/styles/heatmap/components/heatmap_style_editor.test.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/heatmap/heatmap_style_editor.test.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/heatmap/components/heatmap_style_editor.test.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/heatmap/legend/heatmap_legend.js b/x-pack/legacy/plugins/maps/public/layers/styles/heatmap/components/legend/heatmap_legend.js
similarity index 88%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/heatmap/legend/heatmap_legend.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/heatmap/components/legend/heatmap_legend.js
index 74fce11abf0a6..dddc4f88e9bee 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/components/heatmap/legend/heatmap_legend.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/heatmap/components/legend/heatmap_legend.js
@@ -7,8 +7,8 @@
import React from 'react';
import { i18n } from '@kbn/i18n';
-import { ColorGradient } from '../../color_gradient';
-import { StyleLegendRow } from '../../style_legend_row';
+import { ColorGradient } from '../../../color_gradient';
+import { StyleLegendRow } from '../../../vector/components/style_legend_row';
import {
DEFAULT_RGB_HEATMAP_COLOR_RAMP,
DEFAULT_HEATMAP_COLOR_RAMP_NAME,
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/heatmap_style.js b/x-pack/legacy/plugins/maps/public/layers/styles/heatmap/heatmap_style.js
similarity index 90%
rename from x-pack/legacy/plugins/maps/public/layers/styles/heatmap_style.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/heatmap/heatmap_style.js
index 5ccabe610a120..e537da8a3e2e4 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/heatmap_style.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/heatmap/heatmap_style.js
@@ -5,12 +5,12 @@
*/
import React from 'react';
-import { GRID_RESOLUTION } from '../grid_resolution';
-import { AbstractStyle } from './abstract_style';
-import { HeatmapStyleEditor } from './components/heatmap/heatmap_style_editor';
-import { HeatmapLegend } from './components/heatmap/legend/heatmap_legend';
-import { DEFAULT_HEATMAP_COLOR_RAMP_NAME } from './components/heatmap/heatmap_constants';
-import { getColorRampStops } from './color_utils';
+import { GRID_RESOLUTION } from '../../grid_resolution';
+import { AbstractStyle } from '../abstract_style';
+import { HeatmapStyleEditor } from './components/heatmap_style_editor';
+import { HeatmapLegend } from './components/legend/heatmap_legend';
+import { DEFAULT_HEATMAP_COLOR_RAMP_NAME } from './components/heatmap_constants';
+import { getColorRampStops } from '../color_utils';
import { i18n } from '@kbn/i18n';
import { EuiIcon } from '@elastic/eui';
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/_static_dynamic_style_row.scss b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/_static_dynamic_style_row.scss
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/_static_dynamic_style_row.scss
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/_static_dynamic_style_row.scss
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/static_dynamic_style_row.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/static_dynamic_style_row.js
similarity index 92%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/static_dynamic_style_row.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/static_dynamic_style_row.js
index cfe7a0741a194..6eb6b0ab23a3c 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/components/static_dynamic_style_row.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/static_dynamic_style_row.js
@@ -5,7 +5,8 @@
*/
import React from 'react';
-import { VectorStyle } from '../vector_style';
+import { DynamicStyleProperty } from '../properties/dynamic_style_property';
+import { StaticStyleProperty } from '../properties/static_style_property';
import _ from 'lodash';
import { i18n } from '@kbn/i18n';
@@ -25,7 +26,7 @@ export class StaticDynamicStyleRow extends React.Component {
if (!this.props.styleDescriptor) {
return false;
}
- return this.props.styleDescriptor.type === VectorStyle.STYLE_TYPE.DYNAMIC;
+ return this.props.styleDescriptor.type === DynamicStyleProperty.type;
}
_getStyleOptions() {
@@ -34,7 +35,7 @@ export class StaticDynamicStyleRow extends React.Component {
_onStaticStyleChange = options => {
const styleDescriptor = {
- type: VectorStyle.STYLE_TYPE.STATIC,
+ type: StaticStyleProperty.type,
options,
};
this.props.handlePropertyChange(this.props.property, styleDescriptor);
@@ -42,7 +43,7 @@ export class StaticDynamicStyleRow extends React.Component {
_onDynamicStyleChange = options => {
const styleDescriptor = {
- type: VectorStyle.STYLE_TYPE.DYNAMIC,
+ type: DynamicStyleProperty.type,
options,
};
this.props.handlePropertyChange(this.props.property, styleDescriptor);
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/style_legend_row.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/style_legend_row.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/style_legend_row.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/style_legend_row.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/__snapshots__/vector_style_symbol_editor.test.js.snap b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/__snapshots__/vector_style_symbol_editor.test.js.snap
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/__snapshots__/vector_style_symbol_editor.test.js.snap
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/__snapshots__/vector_style_symbol_editor.test.js.snap
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/_color_stops.scss b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/color/_color_stops.scss
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/_color_stops.scss
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/color/_color_stops.scss
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/color_ramp_select.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/color/color_ramp_select.js
similarity index 97%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/color_ramp_select.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/color/color_ramp_select.js
index c2dd51a0182e3..5fc535b764d51 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/color_ramp_select.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/color/color_ramp_select.js
@@ -8,7 +8,7 @@ import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import { EuiSuperSelect, EuiSpacer } from '@elastic/eui';
-import { COLOR_GRADIENTS } from '../../../color_utils';
+import { COLOR_GRADIENTS } from '../../../../color_utils';
import { FormattedMessage } from '@kbn/i18n/react';
import { ColorStops } from './color_stops';
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/color_stops.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/color/color_stops.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/color_stops.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/color/color_stops.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/color_stops_utils.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/color/color_stops_utils.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/color_stops_utils.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/color/color_stops_utils.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/dynamic_color_selection.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/color/dynamic_color_selection.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/dynamic_color_selection.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/color/dynamic_color_selection.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/static_color_selection.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/color/static_color_selection.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/static_color_selection.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/color/static_color_selection.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/vector_style_color_editor.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/color/vector_style_color_editor.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/color/vector_style_color_editor.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/color/vector_style_color_editor.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/field_select.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/field_select.js
similarity index 96%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/field_select.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/field_select.js
index 1d8f4e13fdd1a..ce50978a9dc5c 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/field_select.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/field_select.js
@@ -8,7 +8,7 @@ import PropTypes from 'prop-types';
import React from 'react';
import { EuiComboBox } from '@elastic/eui';
-import { SOURCE_DATA_ID_ORIGIN } from '../../../../../common/constants';
+import { SOURCE_DATA_ID_ORIGIN } from '../../../../../../common/constants';
import { i18n } from '@kbn/i18n';
export function FieldSelect({ fields, selectedFieldName, onChange, ...rest }) {
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/get_vector_style_label.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/get_vector_style_label.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/get_vector_style_label.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/get_vector_style_label.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/__snapshots__/vector_icon.test.js.snap b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/legend/__snapshots__/vector_icon.test.js.snap
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/__snapshots__/vector_icon.test.js.snap
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/legend/__snapshots__/vector_icon.test.js.snap
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/circle_icon.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/legend/circle_icon.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/circle_icon.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/legend/circle_icon.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/line_icon.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/legend/line_icon.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/line_icon.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/legend/line_icon.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/polygon_icon.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/legend/polygon_icon.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/polygon_icon.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/legend/polygon_icon.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/style_property_legend_row.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/legend/style_property_legend_row.js
similarity index 95%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/style_property_legend_row.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/legend/style_property_legend_row.js
index 2f8a603c290ab..ad2156bd20edc 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/style_property_legend_row.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/legend/style_property_legend_row.js
@@ -9,8 +9,8 @@ import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import { styleOptionShapes, rangeShape } from '../style_option_shapes';
-import { VectorStyle } from '../../../vector_style';
-import { ColorGradient } from '../../color_gradient';
+import { StaticStyleProperty } from '../../../properties/static_style_property';
+import { ColorGradient } from '../../../../color_gradient';
import { CircleIcon } from './circle_icon';
import { getVectorStyleLabel } from '../get_vector_style_label';
import { EuiFlexGroup, EuiFlexItem, EuiHorizontalRule } from '@elastic/eui';
@@ -121,7 +121,7 @@ export class StylePropertyLegendRow extends Component {
}
_isStatic() {
- return this.props.type === VectorStyle.STYLE_TYPE.STATIC ||
+ return this.props.type === StaticStyleProperty.type ||
!this.props.options.field || !this.props.options.field.name;
}
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/symbol_icon.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/legend/symbol_icon.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/symbol_icon.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/legend/symbol_icon.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/vector_icon.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/legend/vector_icon.js
similarity index 93%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/vector_icon.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/legend/vector_icon.js
index 0f9e76c3e74d9..bd9f8356c0ef9 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/vector_icon.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/legend/vector_icon.js
@@ -12,8 +12,8 @@ import { CircleIcon } from './circle_icon';
import { LineIcon } from './line_icon';
import { PolygonIcon } from './polygon_icon';
import { SymbolIcon } from './symbol_icon';
-import { VectorStyle } from '../../../vector_style';
-import { getColorRampCenterColor } from '../../../color_utils';
+import { StaticStyleProperty } from '../../../properties/static_style_property';
+import { getColorRampCenterColor } from '../../../../color_utils';
export class VectorIcon extends Component {
@@ -87,7 +87,7 @@ function extractColorFromStyleProperty(colorStyleProperty, defaultColor) {
return defaultColor;
}
- if (colorStyleProperty.type === VectorStyle.STYLE_TYPE.STATIC) {
+ if (colorStyleProperty.type === StaticStyleProperty.type) {
return colorStyleProperty.options.color;
}
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/vector_icon.test.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/legend/vector_icon.test.js
similarity index 91%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/vector_icon.test.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/legend/vector_icon.test.js
index 221b6268c55df..4c773b35cced3 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/vector_icon.test.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/legend/vector_icon.test.js
@@ -8,7 +8,8 @@ import React from 'react';
import { shallow } from 'enzyme';
import { VectorIcon } from './vector_icon';
-import { VectorStyle } from '../../../vector_style';
+import { StaticStyleProperty } from '../../../properties/static_style_property';
+import { DynamicStyleProperty } from '../../../properties/dynamic_style_property';
let isPointsOnly = false;
let isLinesOnly = false;
@@ -16,13 +17,13 @@ const defaultProps = {
loadIsPointsOnly: () => { return isPointsOnly; },
loadIsLinesOnly: () => { return isLinesOnly; },
fillColor: {
- type: VectorStyle.STYLE_TYPE.STATIC,
+ type: StaticStyleProperty.type,
options: {
color: '#ff0000',
}
},
lineColor: {
- type: VectorStyle.STYLE_TYPE.DYNAMIC,
+ type: DynamicStyleProperty.type,
options: {
color: 'Blues',
field: {
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/vector_style_legend.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/legend/vector_style_legend.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/legend/vector_style_legend.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/legend/vector_style_legend.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/orientation/dynamic_orientation_selection.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/orientation/dynamic_orientation_selection.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/orientation/dynamic_orientation_selection.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/orientation/dynamic_orientation_selection.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/orientation/orientation_editor.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/orientation/orientation_editor.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/orientation/orientation_editor.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/orientation/orientation_editor.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/orientation/static_orientation_selection.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/orientation/static_orientation_selection.js
similarity index 91%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/orientation/static_orientation_selection.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/orientation/static_orientation_selection.js
index b5529c6987459..5e32ed966d360 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/orientation/static_orientation_selection.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/orientation/static_orientation_selection.js
@@ -7,7 +7,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { staticOrientationShape } from '../style_option_shapes';
-import { ValidatedRange } from '../../../../../components/validated_range';
+import { ValidatedRange } from '../../../../../../components/validated_range';
export function StaticOrientationSelection({ onChange, styleOptions }) {
const onOrientationChange = orientation => {
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/size/dynamic_size_selection.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/size/dynamic_size_selection.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/size/dynamic_size_selection.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/size/dynamic_size_selection.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/size/size_range_selector.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/size/size_range_selector.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/size/size_range_selector.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/size/size_range_selector.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/size/static_size_selection.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/size/static_size_selection.js
similarity index 92%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/size/static_size_selection.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/size/static_size_selection.js
index 38f8fe53d1748..0168a3ef68d9d 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/size/static_size_selection.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/size/static_size_selection.js
@@ -7,7 +7,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { staticSizeShape } from '../style_option_shapes';
-import { ValidatedRange } from '../../../../../components/validated_range';
+import { ValidatedRange } from '../../../../../../components/validated_range';
import { i18n } from '@kbn/i18n';
export function StaticSizeSelection({ onChange, styleOptions }) {
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/size/vector_style_size_editor.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/size/vector_style_size_editor.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/size/vector_style_size_editor.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/size/vector_style_size_editor.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/style_option_shapes.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/style_option_shapes.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/style_option_shapes.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/style_option_shapes.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/vector_style_editor.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/vector_style_editor.js
similarity index 98%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/vector_style_editor.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/vector_style_editor.js
index 83d4ff7c11d66..48404f6fbeafb 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/vector_style_editor.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/vector_style_editor.js
@@ -17,8 +17,8 @@ import {
getDefaultStaticProperties,
vectorStyles,
} from '../../vector_style_defaults';
-import { DEFAULT_FILL_COLORS, DEFAULT_LINE_COLORS } from '../../color_utils';
-import { VECTOR_SHAPE_TYPES } from '../../../sources/vector_feature_types';
+import { DEFAULT_FILL_COLORS, DEFAULT_LINE_COLORS } from '../../../color_utils';
+import { VECTOR_SHAPE_TYPES } from '../../../../sources/vector_feature_types';
import { SYMBOLIZE_AS_ICON } from '../../vector_constants';
import { i18n } from '@kbn/i18n';
import { SYMBOL_OPTIONS } from '../../symbol_utils';
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/vector_style_symbol_editor.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/vector_style_symbol_editor.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/vector_style_symbol_editor.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/vector_style_symbol_editor.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/components/vector/vector_style_symbol_editor.test.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/vector_style_symbol_editor.test.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/components/vector/vector_style_symbol_editor.test.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector/vector_style_symbol_editor.test.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_color_property.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_color_property.js
new file mode 100644
index 0000000000000..eda9242fe53dd
--- /dev/null
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_color_property.js
@@ -0,0 +1,117 @@
+/*
+ * 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 { DynamicStyleProperty } from './dynamic_style_property';
+import _ from 'lodash';
+import { getComputedFieldName } from '../style_util';
+import { getColorRampStops } from '../../color_utils';
+
+
+export class DynamicColorProperty extends DynamicStyleProperty {
+
+
+ syncCircleColorWithMb(mbLayerId, mbMap, alpha) {
+ const color = this._getMbColor();
+ mbMap.setPaintProperty(mbLayerId, 'circle-color', color);
+ mbMap.setPaintProperty(mbLayerId, 'circle-opacity', alpha);
+ }
+
+ syncIconColorWithMb(mbLayerId, mbMap) {
+ const color = this._getMbColor();
+ mbMap.setPaintProperty(mbLayerId, 'icon-color', color);
+ }
+
+ syncHaloBorderColorWithMb(mbLayerId, mbMap) {
+ const color = this._getMbColor();
+ mbMap.setPaintProperty(mbLayerId, 'icon-halo-color', color);
+ }
+
+ syncCircleStrokeWithMb(pointLayerId, mbMap, alpha) {
+ const color = this._getMbColor();
+ mbMap.setPaintProperty(pointLayerId, 'circle-stroke-color', color);
+ mbMap.setPaintProperty(pointLayerId, 'circle-stroke-opacity', alpha);
+ }
+
+ syncFillColorWithMb(mbLayerId, mbMap, alpha) {
+ const color = this._getMbColor();
+ mbMap.setPaintProperty(mbLayerId, 'fill-color', color);
+ mbMap.setPaintProperty(mbLayerId, 'fill-opacity', alpha);
+ }
+
+ syncLineColorWithMb(mbLayerId, mbMap, alpha) {
+ const color = this._getMbColor();
+ mbMap.setPaintProperty(mbLayerId, 'line-color', color);
+ mbMap.setPaintProperty(mbLayerId, 'line-opacity', alpha);
+ }
+
+ isCustomColorRamp() {
+ return !!this._options.customColorRamp;
+ }
+
+ supportsFeatureState() {
+ return true;
+ }
+
+ isScaled() {
+ return !this.isCustomColorRamp();
+ }
+
+ _getMbColor() {
+ const isDynamicConfigComplete = _.has(this._options, 'field.name') && _.has(this._options, 'color');
+ if (!isDynamicConfigComplete) {
+ return null;
+ }
+
+ if (this._options.useCustomColorRamp && (!this._options.customColorRamp || !this._options.customColorRamp.length)) {
+ return null;
+ }
+
+ return this._getMBDataDrivenColor({
+ targetName: getComputedFieldName(this._styleName, this._options.field.name),
+ colorStops: this._getMBColorStops(),
+ isSteps: this._options.useCustomColorRamp,
+ });
+ }
+
+ _getMBDataDrivenColor({ targetName, colorStops, isSteps }) {
+ if (isSteps) {
+ const firstStopValue = colorStops[0];
+ const lessThenFirstStopValue = firstStopValue - 1;
+ return [
+ 'step',
+ ['coalesce', ['feature-state', targetName], lessThenFirstStopValue],
+ 'rgba(0,0,0,0)', // MB will assign the base value to any features that is below the first stop value
+ ...colorStops
+ ];
+ }
+
+ return [
+ 'interpolate',
+ ['linear'],
+ ['coalesce', ['feature-state', targetName], -1],
+ -1, 'rgba(0,0,0,0)',
+ ...colorStops
+ ];
+ }
+
+
+ _getMBColorStops() {
+
+ if (this._options.useCustomColorRamp) {
+ return this._options.customColorRamp.reduce((accumulatedStops, nextStop) => {
+ return [...accumulatedStops, nextStop.stop, nextStop.color];
+ }, []);
+ }
+
+ return getColorRampStops(this._options.color);
+ }
+
+}
+
+
+
+
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_orientation_property.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_orientation_property.js
new file mode 100644
index 0000000000000..fb4ffd8cce4b4
--- /dev/null
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_orientation_property.js
@@ -0,0 +1,37 @@
+/*
+ * 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 { DynamicStyleProperty } from './dynamic_style_property';
+import { getComputedFieldName } from '../style_util';
+import { vectorStyles } from '../vector_style_defaults';
+
+
+export class DynamicOrientationProperty extends DynamicStyleProperty {
+
+ syncIconRotationWithMb(symbolLayerId, mbMap) {
+ if (this._options.field && this._options.field.name) {
+ const targetName = getComputedFieldName(vectorStyles.ICON_ORIENTATION, this._options.field.name);
+ // Using property state instead of feature-state because layout properties do not support feature-state
+ mbMap.setLayoutProperty(symbolLayerId, 'icon-rotate', ['coalesce', ['get', targetName], 0]);
+ } else {
+ mbMap.setLayoutProperty(symbolLayerId, 'icon-rotate', 0);
+ }
+ }
+
+ supportsFeatureState() {
+ return false;
+ }
+
+ isScaled() {
+ return false;
+ }
+
+}
+
+
+
+
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_size_property.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_size_property.js
new file mode 100644
index 0000000000000..cfd46ed20823a
--- /dev/null
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_size_property.js
@@ -0,0 +1,84 @@
+/*
+ * 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 { DynamicStyleProperty } from './dynamic_style_property';
+import { getComputedFieldName } from '../style_util';
+import { HALF_LARGE_MAKI_ICON_SIZE, LARGE_MAKI_ICON_SIZE, SMALL_MAKI_ICON_SIZE } from '../symbol_utils';
+import { vectorStyles } from '../vector_style_defaults';
+import _ from 'lodash';
+
+export class DynamicSizeProperty extends DynamicStyleProperty {
+
+ syncHaloWidthWithMb(mbLayerId, mbMap) {
+ const haloWidth = this._getMbSize();
+ mbMap.setPaintProperty(mbLayerId, 'icon-halo-width', haloWidth);
+ }
+
+
+ syncIconImageAndSizeWithMb(symbolLayerId, mbMap, symbolId) {
+ if (this._isSizeDynamicConfigComplete(this._options)) {
+ const iconPixels = this._options.maxSize >= HALF_LARGE_MAKI_ICON_SIZE
+ ? LARGE_MAKI_ICON_SIZE
+ : SMALL_MAKI_ICON_SIZE;
+ mbMap.setLayoutProperty(symbolLayerId, 'icon-image', `${symbolId}-${iconPixels}`);
+
+ const halfIconPixels = iconPixels / 2;
+ const targetName = getComputedFieldName(vectorStyles.ICON_SIZE, this._options.field.name);
+ // Using property state instead of feature-state because layout properties do not support feature-state
+ mbMap.setLayoutProperty(symbolLayerId, 'icon-size', [
+ 'interpolate',
+ ['linear'],
+ ['coalesce', ['get', targetName], 0],
+ 0, this._options.minSize / halfIconPixels,
+ 1, this._options.maxSize / halfIconPixels
+ ]);
+ } else {
+ mbMap.setLayoutProperty(symbolLayerId, 'icon-image', null);
+ mbMap.setLayoutProperty(symbolLayerId, 'icon-size', null);
+ }
+ }
+
+ syncCircleStrokeWidthWithMb(mbLayerId, mbMap) {
+ const lineWidth = this._getMbSize();
+ mbMap.setPaintProperty(mbLayerId, 'circle-stroke-width', lineWidth);
+ }
+
+ syncCircleRadiusWithMb(mbLayerId, mbMap) {
+ const circleRadius = this._getMbSize();
+ mbMap.setPaintProperty(mbLayerId, 'circle-radius', circleRadius);
+ }
+
+ syncLineWidthWithMb(mbLayerId, mbMap) {
+ const lineWidth = this._getMbSize();
+ mbMap.setPaintProperty(mbLayerId, 'line-width', lineWidth);
+ }
+
+ _getMbSize() {
+ if (this._isSizeDynamicConfigComplete(this._options)) {
+ return this._getMbDataDrivenSize({
+ targetName: getComputedFieldName(this._styleName, this._options.field.name),
+ minSize: this._options.minSize,
+ maxSize: this._options.maxSize,
+ });
+ }
+ return null;
+ }
+
+ _getMbDataDrivenSize({ targetName, minSize, maxSize }) {
+ return [
+ 'interpolate',
+ ['linear'],
+ ['coalesce', ['feature-state', targetName], 0],
+ 0, minSize,
+ 1, maxSize
+ ];
+ }
+
+ _isSizeDynamicConfigComplete() {
+ return this._field.isValid() && _.has(this._options, 'minSize') && _.has(this._options, 'maxSize');
+ }
+}
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.js
new file mode 100644
index 0000000000000..2110d9a1e1bb4
--- /dev/null
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.js
@@ -0,0 +1,37 @@
+/*
+ * 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 { AbstractStyleProperty } from './style_property';
+
+export class DynamicStyleProperty extends AbstractStyleProperty {
+ static type = 'DYNAMIC';
+
+ constructor(options, styleName, field) {
+ super(options, styleName);
+ this._field = field;
+ }
+
+ getField() {
+ return this._field;
+ }
+
+ isDynamic() {
+ return !!this._field;
+ }
+
+ getFieldOrigin() {
+ return this._options.field.origin;
+ }
+
+ supportsFeatureState() {
+ return true;
+ }
+
+ isScaled() {
+ return true;
+ }
+}
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/static_color_property.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/static_color_property.js
new file mode 100644
index 0000000000000..d4c44fca1bd08
--- /dev/null
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/static_color_property.js
@@ -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.
+ */
+
+
+import { StaticStyleProperty } from './static_style_property';
+
+
+export class StaticColorProperty extends StaticStyleProperty {
+
+ syncCircleColorWithMb(mbLayerId, mbMap, alpha) {
+ mbMap.setPaintProperty(mbLayerId, 'circle-color', this._options.color);
+ mbMap.setPaintProperty(mbLayerId, 'circle-opacity', alpha);
+ }
+
+ syncFillColorWithMb(mbLayerId, mbMap, alpha) {
+ mbMap.setPaintProperty(mbLayerId, 'fill-color', this._options.color);
+ mbMap.setPaintProperty(mbLayerId, 'fill-opacity', alpha);
+ }
+
+ syncIconColorWithMb(mbLayerId, mbMap) {
+ mbMap.setPaintProperty(mbLayerId, 'icon-color', this._options.color);
+ }
+
+ syncHaloBorderColorWithMb(mbLayerId, mbMap) {
+ mbMap.setPaintProperty(mbLayerId, 'icon-halo-color', this._options.color);
+ }
+
+ syncLineColorWithMb(mbLayerId, mbMap, alpha) {
+ mbMap.setPaintProperty(mbLayerId, 'line-color', this._options.color);
+ mbMap.setPaintProperty(mbLayerId, 'line-opacity', alpha);
+ }
+
+ syncCircleStrokeWithMb(pointLayerId, mbMap, alpha) {
+ mbMap.setPaintProperty(pointLayerId, 'circle-stroke-color', this._options.color);
+ mbMap.setPaintProperty(pointLayerId, 'circle-stroke-opacity', alpha);
+ }
+
+}
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/static_orientation_property.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/static_orientation_property.js
new file mode 100644
index 0000000000000..48a7bbd3f79df
--- /dev/null
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/static_orientation_property.js
@@ -0,0 +1,26 @@
+/*
+ * 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 { StaticStyleProperty } from './static_style_property';
+
+
+export class StaticOrientationProperty extends StaticStyleProperty {
+
+ constructor(options, styleName) {
+ if (typeof options.orientation !== 'number') {
+ super({ orientation: 0 }, styleName);
+ } else {
+ super(options, styleName);
+ }
+ }
+
+ syncIconRotationWithMb(symbolLayerId, mbMap) {
+ mbMap.setLayoutProperty(symbolLayerId, 'icon-rotate', this._options.orientation);
+ }
+
+
+}
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/static_size_property.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/static_size_property.js
new file mode 100644
index 0000000000000..37162d8cb0a3c
--- /dev/null
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/static_size_property.js
@@ -0,0 +1,46 @@
+/*
+ * 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 { StaticStyleProperty } from './static_style_property';
+import { HALF_LARGE_MAKI_ICON_SIZE, LARGE_MAKI_ICON_SIZE, SMALL_MAKI_ICON_SIZE } from '../symbol_utils';
+
+
+export class StaticSizeProperty extends StaticStyleProperty {
+
+ constructor(options, styleName) {
+ if (typeof options.size !== 'number') {
+ super({ size: 1 }, styleName);
+ } else {
+ super(options, styleName);
+ }
+ }
+
+ syncHaloWidthWithMb(mbLayerId, mbMap) {
+ mbMap.setPaintProperty(mbLayerId, 'icon-halo-width', this._options.size);
+ }
+
+ syncIconImageAndSizeWithMb(symbolLayerId, mbMap, symbolId) {
+ const iconPixels = this._size >= HALF_LARGE_MAKI_ICON_SIZE ? LARGE_MAKI_ICON_SIZE : SMALL_MAKI_ICON_SIZE;
+ mbMap.setLayoutProperty(symbolLayerId, 'icon-image', `${symbolId}-${iconPixels}`);
+ const halfIconPixels = iconPixels / 2;
+ mbMap.setLayoutProperty(symbolLayerId, 'icon-size', this._options.size / halfIconPixels);
+ }
+
+ syncCircleStrokeWidthWithMb(mbLayerId, mbMap) {
+ mbMap.setPaintProperty(mbLayerId, 'circle-stroke-width', this._options.size);
+ }
+
+ syncCircleRadiusWithMb(mbLayerId, mbMap) {
+ mbMap.setPaintProperty(mbLayerId, 'circle-radius', this._options.size);
+ }
+
+ syncLineWidthWithMb(mbLayerId, mbMap) {
+ mbMap.setPaintProperty(mbLayerId, 'line-width', this._options.size);
+ }
+
+
+}
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/static_style_property.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/static_style_property.js
new file mode 100644
index 0000000000000..448efc06899e5
--- /dev/null
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/static_style_property.js
@@ -0,0 +1,13 @@
+/*
+ * 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 { AbstractStyleProperty } from './style_property';
+
+export class StaticStyleProperty extends AbstractStyleProperty {
+ static type = 'STATIC';
+
+}
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/style_property.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/style_property.js
new file mode 100644
index 0000000000000..302fbb10d00b2
--- /dev/null
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/style_property.js
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+
+
+
+
+export class AbstractStyleProperty {
+
+ constructor(options, styleName) {
+ this._options = options;
+ this._styleName = styleName;
+ }
+
+ isDynamic() {
+ return false;
+ }
+
+ getStyleName() {
+ return this._styleName;
+ }
+ getOptions() {
+ return this._options || {};
+ }
+}
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/style_util.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/style_util.js
new file mode 100644
index 0000000000000..69caaca080138
--- /dev/null
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/style_util.js
@@ -0,0 +1,14 @@
+/*
+ * 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.
+ */
+
+
+export function getComputedFieldName(styleName, fieldName) {
+ return `${getComputedFieldNamePrefix(fieldName)}__${styleName}`;
+}
+
+export function getComputedFieldNamePrefix(fieldName) {
+ return `__kbn__dynamic__${fieldName}`;
+}
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/symbol_utils.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/symbol_utils.js
similarity index 97%
rename from x-pack/legacy/plugins/maps/public/layers/styles/symbol_utils.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/symbol_utils.js
index 22e1a6aea6a72..967d0e0bbd096 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/symbol_utils.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/symbol_utils.js
@@ -6,7 +6,7 @@
import maki from '@elastic/maki';
import xml2js from 'xml2js';
-import { parseXmlString } from '../../../common/parse_xml_string';
+import { parseXmlString } from '../../../../common/parse_xml_string';
export const LARGE_MAKI_ICON_SIZE = 15;
const LARGE_MAKI_ICON_SIZE_AS_STRING = LARGE_MAKI_ICON_SIZE.toString();
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/symbol_utils.test.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/symbol_utils.test.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/symbol_utils.test.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/symbol_utils.test.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector_constants.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_constants.js
similarity index 100%
rename from x-pack/legacy/plugins/maps/public/layers/styles/vector_constants.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_constants.js
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.js
new file mode 100644
index 0000000000000..55a52213aacbc
--- /dev/null
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.js
@@ -0,0 +1,534 @@
+/*
+ * 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 _ from 'lodash';
+import React from 'react';
+import { i18n } from '@kbn/i18n';
+import { VectorStyleEditor } from './components/vector/vector_style_editor';
+import { getDefaultProperties, vectorStyles } from './vector_style_defaults';
+import { AbstractStyle } from '../abstract_style';
+import { SOURCE_DATA_ID_ORIGIN, GEO_JSON_TYPE, FIELD_ORIGIN } from '../../../../common/constants';
+import { VectorIcon } from './components/vector/legend/vector_icon';
+import { VectorStyleLegend } from './components/vector/legend/vector_style_legend';
+import { VECTOR_SHAPE_TYPES } from '../../sources/vector_feature_types';
+import { SYMBOLIZE_AS_CIRCLE, SYMBOLIZE_AS_ICON } from './vector_constants';
+import { getMakiSymbolAnchor } from './symbol_utils';
+import { DynamicStyleProperty } from './properties/dynamic_style_property';
+import { StaticStyleProperty } from './properties/static_style_property';
+import { DynamicSizeProperty } from './properties/dynamic_size_property';
+import { StaticSizeProperty } from './properties/static_size_property';
+import { getComputedFieldName } from './style_util';
+import { StaticColorProperty } from './properties/static_color_property';
+import { DynamicColorProperty } from './properties/dynamic_color_property';
+import { StaticOrientationProperty } from './properties/static_orientation_property';
+import { DynamicOrientationProperty } from './properties/dynamic_orientation_property';
+
+const POINTS = [GEO_JSON_TYPE.POINT, GEO_JSON_TYPE.MULTI_POINT];
+const LINES = [GEO_JSON_TYPE.LINE_STRING, GEO_JSON_TYPE.MULTI_LINE_STRING];
+const POLYGONS = [GEO_JSON_TYPE.POLYGON, GEO_JSON_TYPE.MULTI_POLYGON];
+
+export class VectorStyle extends AbstractStyle {
+
+ static type = 'VECTOR';
+
+ static createDescriptor(properties = {}) {
+ return {
+ type: VectorStyle.type,
+ properties: { ...getDefaultProperties(), ...properties }
+ };
+ }
+
+ static createDefaultStyleProperties(mapColors) {
+ return getDefaultProperties(mapColors);
+ }
+
+ static getDisplayName() {
+ return i18n.translate('xpack.maps.style.vector.displayNameLabel', {
+ defaultMessage: 'Vector style'
+ });
+ }
+
+ static description = '';
+
+
+ constructor(descriptor = {}, source, layer) {
+ super();
+ this._source = source;
+ this._layer = layer;
+ this._descriptor = {
+ ...descriptor,
+ ...VectorStyle.createDescriptor(descriptor.properties),
+ };
+
+ this._lineColorStyleProperty = this._makeStyleProperty(vectorStyles.LINE_COLOR, this._descriptor.properties[vectorStyles.LINE_COLOR]);
+ this._fillColorStyleProperty = this._makeStyleProperty(vectorStyles.FILL_COLOR, this._descriptor.properties[vectorStyles.FILL_COLOR]);
+ this._lineWidthStyleProperty = this._makeStyleProperty(vectorStyles.LINE_WIDTH, this._descriptor.properties[vectorStyles.LINE_WIDTH]);
+ this._iconSizeStyleProperty = this._makeStyleProperty(vectorStyles.ICON_SIZE, this._descriptor.properties[vectorStyles.ICON_SIZE]);
+ // eslint-disable-next-line max-len
+ this._iconOrientationProperty = this._makeStyleProperty(vectorStyles.ICON_ORIENTATION, this._descriptor.properties[vectorStyles.ICON_ORIENTATION]);
+ }
+
+ _getAllStyleProperties() {
+ return [
+ this._lineColorStyleProperty,
+ this._fillColorStyleProperty,
+ this._lineWidthStyleProperty,
+ this._iconSizeStyleProperty,
+ this._iconOrientationProperty
+ ];
+ }
+
+ renderEditor({ layer, onStyleDescriptorChange }) {
+ const styleProperties = { ...this.getRawProperties() };
+ const handlePropertyChange = (propertyName, settings) => {
+ styleProperties[propertyName] = settings;//override single property, but preserve the rest
+ const vectorStyleDescriptor = VectorStyle.createDescriptor(styleProperties);
+ onStyleDescriptorChange(vectorStyleDescriptor);
+ };
+
+ return (
+
+ );
+ }
+
+ /*
+ * Changes to source descriptor and join descriptor will impact style properties.
+ * For instance, a style property may be dynamically tied to the value of an ordinal field defined
+ * by a join or a metric aggregation. The metric aggregation or join may be edited or removed.
+ * When this happens, the style will be linked to a no-longer-existing ordinal field.
+ * This method provides a way for a style to clean itself and return a descriptor that unsets any dynamic
+ * properties that are tied to missing oridinal fields
+ *
+ * This method does not update its descriptor. It just returns a new descriptor that the caller
+ * can then use to update store state via dispatch.
+ */
+ getDescriptorWithMissingStylePropsRemoved(nextOrdinalFields) {
+ const originalProperties = this.getRawProperties();
+ const updatedProperties = {};
+
+
+ this.getDynamicPropertiesArray().forEach(dynamicProperty =>{
+
+ const field = dynamicProperty.getField();
+ if (field || !field.isValid()) {
+ return;
+ }
+
+ const fieldName = field.getName();
+ const matchingOrdinalField = nextOrdinalFields.find(oridinalField => {
+ return fieldName === oridinalField.name;
+ });
+
+ if (matchingOrdinalField) {
+ return;
+ }
+
+ updatedProperties[dynamicProperty.getStyleName()] = {
+ type: DynamicStyleProperty.type,
+ options: {
+ ...originalProperties[dynamicProperty.getStyleName()].options
+ }
+ };
+ delete updatedProperties[dynamicProperty.getStyleName()].options.field;
+
+ });
+
+ if (Object.keys(updatedProperties).length === 0) {
+ return {
+ hasChanges: false,
+ nextStyleDescriptor: { ...this._descriptor },
+ };
+ }
+
+ return {
+ hasChanges: true,
+ nextStyleDescriptor: VectorStyle.createDescriptor({
+ ...originalProperties,
+ ...updatedProperties,
+ })
+ };
+
+ }
+
+ async pluckStyleMetaFromSourceDataRequest(sourceDataRequest) {
+ const features = _.get(sourceDataRequest.getData(), 'features', []);
+ if (features.length === 0) {
+ return {};
+ }
+
+ const scaledFields = this.getDynamicPropertiesArray()
+ .map(styleProperty => {
+ return {
+ name: styleProperty.getField().getName(),
+ min: Infinity,
+ max: -Infinity
+ };
+ });
+
+ const supportedFeatures = await this._source.getSupportedShapeTypes();
+ const isSingleFeatureType = supportedFeatures.length === 1;
+
+ if (scaledFields.length === 0 && isSingleFeatureType) {
+ // no meta data to pull from source data request.
+ return {};
+ }
+
+ let hasPoints = false;
+ let hasLines = false;
+ let hasPolygons = false;
+ for (let i = 0; i < features.length; i++) {
+ const feature = features[i];
+ if (!hasPoints && POINTS.includes(feature.geometry.type)) {
+ hasPoints = true;
+ }
+ if (!hasLines && LINES.includes(feature.geometry.type)) {
+ hasLines = true;
+ }
+ if (!hasPolygons && POLYGONS.includes(feature.geometry.type)) {
+ hasPolygons = true;
+ }
+
+ for (let j = 0; j < scaledFields.length; j++) {
+ const scaledField = scaledFields[j];
+ const newValue = parseFloat(feature.properties[scaledField.name]);
+ if (!isNaN(newValue)) {
+ scaledField.min = Math.min(scaledField.min, newValue);
+ scaledField.max = Math.max(scaledField.max, newValue);
+ }
+ }
+ }
+
+ const featuresMeta = {
+ hasFeatureType: {
+ [VECTOR_SHAPE_TYPES.POINT]: hasPoints,
+ [VECTOR_SHAPE_TYPES.LINE]: hasLines,
+ [VECTOR_SHAPE_TYPES.POLYGON]: hasPolygons
+ }
+ };
+
+ scaledFields.forEach(({ min, max, name }) => {
+ if (min !== Infinity && max !== -Infinity) {
+ featuresMeta[name] = {
+ min,
+ max,
+ delta: max - min,
+ };
+ }
+ });
+
+ return featuresMeta;
+ }
+
+ getSourceFieldNames() {
+ const fieldNames = [];
+ this.getDynamicPropertiesArray().forEach(styleProperty => {
+ if (styleProperty.getFieldOrigin() === SOURCE_DATA_ID_ORIGIN) {
+ fieldNames.push(styleProperty.getField().getName());
+ }
+ });
+ return fieldNames;
+ }
+
+ getRawProperties() {
+ return this._descriptor.properties || {};
+ }
+
+ getDynamicPropertiesArray() {
+ const styleProperties = this._getAllStyleProperties();
+ return styleProperties.filter(styleProperty => styleProperty.isDynamic());
+ }
+
+ _checkIfOnlyFeatureType = async (featureType) => {
+ const supportedFeatures = await this._source.getSupportedShapeTypes();
+
+ if (supportedFeatures.length === 1) {
+ return supportedFeatures[0] === featureType;
+ }
+
+ if (!this._descriptor.__styleMeta || !this._descriptor.__styleMeta.hasFeatureType) {
+ return false;
+ }
+
+ const featureTypes = Object.keys(this._descriptor.__styleMeta.hasFeatureType);
+ return featureTypes.reduce((isOnlySingleFeatureType, featureTypeKey) => {
+ const hasFeature = this._descriptor.__styleMeta.hasFeatureType[featureTypeKey];
+ return featureTypeKey === featureType
+ ? isOnlySingleFeatureType && hasFeature
+ : isOnlySingleFeatureType && !hasFeature;
+ }, true);
+ }
+
+ _getIsPointsOnly = async () => {
+ return this._checkIfOnlyFeatureType(VECTOR_SHAPE_TYPES.POINT);
+ }
+
+ _getIsLinesOnly = async () => {
+ return this._checkIfOnlyFeatureType(VECTOR_SHAPE_TYPES.LINE);
+ }
+
+ _getFieldRange = (fieldName) => {
+ return _.get(this._descriptor, ['__styleMeta', fieldName]);
+ }
+
+ getIcon = () => {
+ const styles = this.getRawProperties();
+ const symbolId = this.arePointsSymbolizedAsCircles()
+ ? undefined
+ : this._descriptor.properties.symbol.options.symbolId;
+ return (
+
+ );
+ }
+
+ renderLegendDetails(getFieldLabel, getFieldFormatter) {
+ const styles = this.getRawProperties();
+ const styleProperties = Object.keys(styles).map(styleName => {
+ const { type, options } = styles[styleName];
+ return {
+ name: styleName,
+ type,
+ options,
+ range: options && options.field && options.field.name ? this._getFieldRange(options.field.name) : null,
+ };
+ });
+
+ return (
+
+ );
+ }
+
+ _getStyleFields() {
+ return this.getDynamicPropertiesArray()
+ .map(styleProperty => {
+
+ // "feature-state" data expressions are not supported with layout properties.
+ // To work around this limitation, some styling values must fall back to geojson property values.
+ let supportsFeatureState;
+ let isScaled;
+ if (styleProperty.getStyleName() === vectorStyles.ICON_SIZE
+ && this._descriptor.properties.symbol.options.symbolizeAs === SYMBOLIZE_AS_ICON) {
+ supportsFeatureState = false;
+ isScaled = true;
+ } else {
+ supportsFeatureState = styleProperty.supportsFeatureState();
+ isScaled = styleProperty.isScaled();
+ }
+
+ const field = styleProperty.getField();
+ return {
+ supportsFeatureState,
+ isScaled,
+ name: field.getName(),
+ range: this._getFieldRange(field.getName()),
+ computedName: getComputedFieldName(styleProperty.getStyleName(), field.getName()),
+ };
+ });
+ }
+
+ clearFeatureState(featureCollection, mbMap, sourceId) {
+ const tmpFeatureIdentifier = {
+ source: null,
+ id: null
+ };
+ for (let i = 0; i < featureCollection.features.length; i++) {
+ const feature = featureCollection.features[i];
+ tmpFeatureIdentifier.source = sourceId;
+ tmpFeatureIdentifier.id = feature.id;
+ mbMap.removeFeatureState(tmpFeatureIdentifier);
+ }
+ }
+
+ setFeatureState(featureCollection, mbMap, sourceId) {
+
+ if (!featureCollection) {
+ return;
+ }
+
+ const styleFields = this._getStyleFields();
+ if (styleFields.length === 0) {
+ return;
+ }
+
+ const tmpFeatureIdentifier = {
+ source: null,
+ id: null
+ };
+ const tmpFeatureState = {};
+
+ //scale to [0,1] domain
+ for (let i = 0; i < featureCollection.features.length; i++) {
+ const feature = featureCollection.features[i];
+
+ for (let j = 0; j < styleFields.length; j++) {
+ const { supportsFeatureState, isScaled, name, range, computedName } = styleFields[j];
+ const value = parseFloat(feature.properties[name]);
+ let styleValue;
+ if (isScaled) {
+ if (isNaN(value) || !range) {//cannot scale
+ styleValue = -1;//put outside range
+ } else if (range.delta === 0) {//values are identical
+ styleValue = 1;//snap to end of color range
+ } else {
+ styleValue = (value - range.min) / range.delta;
+ }
+ } else {
+ if (isNaN(value)) {
+ styleValue = 0;
+ } else {
+ styleValue = value;
+ }
+ }
+
+ if (supportsFeatureState) {
+ tmpFeatureState[computedName] = styleValue;
+ } else {
+ feature.properties[computedName] = styleValue;
+ }
+ }
+ tmpFeatureIdentifier.source = sourceId;
+ tmpFeatureIdentifier.id = feature.id;
+ mbMap.setFeatureState(tmpFeatureIdentifier, tmpFeatureState);
+ }
+
+ const hasGeoJsonProperties = styleFields.some(({ supportsFeatureState }) => {
+ return !supportsFeatureState;
+ });
+ return hasGeoJsonProperties;
+ }
+
+ setMBPaintProperties({ alpha, mbMap, fillLayerId, lineLayerId }) {
+ this._fillColorStyleProperty.syncFillColorWithMb(fillLayerId, mbMap, alpha);
+ this._lineColorStyleProperty.syncLineColorWithMb(lineLayerId, mbMap, alpha);
+ this._lineWidthStyleProperty.syncLineWidthWithMb(lineLayerId, mbMap);
+ }
+
+ setMBPaintPropertiesForPoints({ alpha, mbMap, pointLayerId }) {
+ this._fillColorStyleProperty.syncCircleColorWithMb(pointLayerId, mbMap, alpha);
+ this._lineColorStyleProperty.syncCircleStrokeWithMb(pointLayerId, mbMap, alpha);
+ this._lineWidthStyleProperty.syncCircleStrokeWidthWithMb(pointLayerId, mbMap);
+ this._iconSizeStyleProperty.syncCircleRadiusWithMb(pointLayerId, mbMap);
+ }
+
+ setMBSymbolPropertiesForPoints({ mbMap, symbolLayerId, alpha }) {
+
+ const symbolId = this._descriptor.properties.symbol.options.symbolId;
+ mbMap.setLayoutProperty(symbolLayerId, 'icon-ignore-placement', true);
+ mbMap.setLayoutProperty(symbolLayerId, 'icon-anchor', getMakiSymbolAnchor(symbolId));
+ mbMap.setPaintProperty(symbolLayerId, 'icon-opacity', alpha);
+
+ // icon-color is only supported on SDF icons.
+ this._fillColorStyleProperty.syncIconColorWithMb(symbolLayerId, mbMap);
+ this._lineColorStyleProperty.syncHaloBorderColorWithMb(symbolLayerId, mbMap);
+ this._lineWidthStyleProperty.syncHaloWidthWithMb(symbolLayerId, mbMap);
+ this._iconSizeStyleProperty.syncIconImageAndSizeWithMb(symbolLayerId, mbMap, symbolId);
+ this._iconOrientationProperty.syncIconRotationWithMb(symbolLayerId, mbMap);
+
+ }
+
+ arePointsSymbolizedAsCircles() {
+ return this._descriptor.properties.symbol.options.symbolizeAs === SYMBOLIZE_AS_CIRCLE;
+ }
+
+ _makeField(fieldDescriptor) {
+
+ if (!fieldDescriptor || !fieldDescriptor.name) {
+ return null;
+ }
+
+ if (fieldDescriptor.origin === FIELD_ORIGIN.SOURCE) {
+ return this._source.createField({
+ fieldName: fieldDescriptor.name,
+ label: fieldDescriptor.label
+ });
+ } else if (fieldDescriptor.origin === FIELD_ORIGIN.JOIN) {
+ let matchingField = null;
+ const joins = this._layer.getValidJoins();
+ joins.find(join => {
+ const aggSource = join.getRightJoinSource();
+ matchingField = aggSource.getMetricFieldForName(fieldDescriptor.name);
+ return !!matchingField;
+ });
+ return matchingField;
+ } else {
+ throw new Error(`Unknown origin-type ${fieldDescriptor.origin}`);
+ }
+
+
+ }
+
+ _makeSizeProperty(descriptor, styleName) {
+ if (!descriptor || !descriptor.options) {
+ return new StaticSizeProperty({ size: 0 }, styleName);
+ } else if (descriptor.type === StaticStyleProperty.type) {
+ return new StaticSizeProperty(descriptor.options, styleName);
+ } else if (descriptor.type === DynamicStyleProperty.type) {
+ const field = this._makeField(descriptor.options.field);
+ return new DynamicSizeProperty(descriptor.options, styleName, field);
+ } else {
+ throw new Error(`${descriptor} not implemented`);
+ }
+ }
+
+ _makeColorProperty(descriptor, styleName) {
+ if (!descriptor || !descriptor.options) {
+ return new StaticColorProperty({ color: null }, styleName);
+ } else if (descriptor.type === StaticStyleProperty.type) {
+ return new StaticColorProperty(descriptor.options, styleName);
+ } else if (descriptor.type === DynamicStyleProperty.type) {
+ const field = this._makeField(descriptor.options.field);
+ return new DynamicColorProperty(descriptor.options, styleName, field);
+ } else {
+ throw new Error(`${descriptor} not implemented`);
+ }
+ }
+
+ _makeOrientationProperty(descriptor, styleName) {
+ if (!descriptor || !descriptor.options) {
+ return new StaticOrientationProperty({ orientation: 0 }, styleName);
+ } else if (descriptor.type === StaticStyleProperty.type) {
+ return new StaticOrientationProperty(descriptor.options, styleName);
+ } else if (descriptor.type === DynamicStyleProperty.type) {
+ const field = this._makeField(descriptor.options.field);
+ return new DynamicOrientationProperty(descriptor.options, styleName, field);
+ } else {
+ throw new Error(`${descriptor} not implemented`);
+ }
+ }
+
+ _makeStyleProperty(propertyName, descriptor) {
+
+ if (propertyName === vectorStyles.LINE_WIDTH) {
+ return this._makeSizeProperty(descriptor, vectorStyles.LINE_WIDTH);
+ } else if (propertyName === vectorStyles.ICON_SIZE) {
+ return this._makeSizeProperty(descriptor, vectorStyles.ICON_SIZE);
+ } else if (propertyName === vectorStyles.LINE_COLOR) {
+ return this._makeColorProperty(descriptor, vectorStyles.LINE_COLOR);
+ } else if (propertyName === vectorStyles.FILL_COLOR) {
+ return this._makeColorProperty(descriptor, vectorStyles.FILL_COLOR);
+ } else if (propertyName === vectorStyles.ICON_ORIENTATION) {
+ return this._makeOrientationProperty(descriptor, vectorStyles.ICON_ORIENTATION);
+ }
+
+ throw new Error(`${propertyName} not implemented`);
+ }
+
+}
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector_style.test.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.test.js
similarity index 94%
rename from x-pack/legacy/plugins/maps/public/layers/styles/vector_style.test.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.test.js
index 7c993564018aa..2b1f7ce4e5468 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/vector_style.test.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.test.js
@@ -5,22 +5,25 @@
*/
import { VectorStyle } from './vector_style';
-import { DataRequest } from '../util/data_request';
-import { VECTOR_SHAPE_TYPES } from '../sources/vector_feature_types';
+import { DataRequest } from '../../util/data_request';
+import { VECTOR_SHAPE_TYPES } from '../../sources/vector_feature_types';
+import { DynamicStyleProperty } from './properties/dynamic_style_property';
+import { StaticStyleProperty } from './properties/static_style_property';
+
describe('getDescriptorWithMissingStylePropsRemoved', () => {
const fieldName = 'doIStillExist';
const properties = {
fillColor: {
- type: VectorStyle.STYLE_TYPE.STATIC,
+ type: StaticStyleProperty.type,
options: {}
},
lineColor: {
- type: VectorStyle.STYLE_TYPE.DYNAMIC,
+ type: DynamicStyleProperty.type,
options: {}
},
iconSize: {
- type: VectorStyle.STYLE_TYPE.DYNAMIC,
+ type: DynamicStyleProperty.type,
options: {
color: 'a color',
field: { name: fieldName }
@@ -180,7 +183,7 @@ describe('pluckStyleMetaFromSourceDataRequest', () => {
const vectorStyle = new VectorStyle({
properties: {
fillColor: {
- type: VectorStyle.STYLE_TYPE.DYNAMIC,
+ type: DynamicStyleProperty.type,
options: {
field: {
name: 'myDynamicFieldWithNoValues'
@@ -202,7 +205,7 @@ describe('pluckStyleMetaFromSourceDataRequest', () => {
const vectorStyle = new VectorStyle({
properties: {
fillColor: {
- type: VectorStyle.STYLE_TYPE.DYNAMIC,
+ type: DynamicStyleProperty.type,
options: {
field: {
name: 'myDynamicField'
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector_style_defaults.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style_defaults.js
similarity index 82%
rename from x-pack/legacy/plugins/maps/public/layers/styles/vector_style_defaults.js
rename to x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style_defaults.js
index dfd0c1ca1b86b..1e215b27fa145 100644
--- a/x-pack/legacy/plugins/maps/public/layers/styles/vector_style_defaults.js
+++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style_defaults.js
@@ -4,13 +4,14 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { VectorStyle } from './vector_style';
+import { DynamicStyleProperty } from './properties/dynamic_style_property';
+import { StaticStyleProperty } from './properties/static_style_property';
import { SYMBOLIZE_AS_CIRCLE, DEFAULT_ICON_SIZE } from './vector_constants';
import {
COLOR_GRADIENTS,
DEFAULT_FILL_COLORS,
DEFAULT_LINE_COLORS
-} from './color_utils';
+} from '../color_utils';
const DEFAULT_ICON = 'airfield';
@@ -49,31 +50,31 @@ export function getDefaultStaticProperties(mapColors = []) {
return {
[vectorStyles.FILL_COLOR]: {
- type: VectorStyle.STYLE_TYPE.STATIC,
+ type: StaticStyleProperty.type,
options: {
color: nextFillColor,
}
},
[vectorStyles.LINE_COLOR]: {
- type: VectorStyle.STYLE_TYPE.STATIC,
+ type: StaticStyleProperty.type,
options: {
color: nextLineColor
}
},
[vectorStyles.LINE_WIDTH]: {
- type: VectorStyle.STYLE_TYPE.STATIC,
+ type: StaticStyleProperty.type,
options: {
size: 1
}
},
[vectorStyles.ICON_SIZE]: {
- type: VectorStyle.STYLE_TYPE.STATIC,
+ type: StaticStyleProperty.type,
options: {
size: DEFAULT_ICON_SIZE
}
},
[vectorStyles.ICON_ORIENTATION]: {
- type: VectorStyle.STYLE_TYPE.STATIC,
+ type: StaticStyleProperty.type,
options: {
orientation: 0
}
@@ -84,21 +85,21 @@ export function getDefaultStaticProperties(mapColors = []) {
export function getDefaultDynamicProperties() {
return {
[vectorStyles.FILL_COLOR]: {
- type: VectorStyle.STYLE_TYPE.DYNAMIC,
+ type: DynamicStyleProperty.type,
options: {
color: COLOR_GRADIENTS[0].value,
field: undefined,
}
},
[vectorStyles.LINE_COLOR]: {
- type: VectorStyle.STYLE_TYPE.DYNAMIC,
+ type: DynamicStyleProperty.type,
options: {
color: COLOR_GRADIENTS[0].value,
field: undefined,
}
},
[vectorStyles.LINE_WIDTH]: {
- type: VectorStyle.STYLE_TYPE.DYNAMIC,
+ type: DynamicStyleProperty.type,
options: {
minSize: DEFAULT_MIN_SIZE,
maxSize: DEFAULT_MAX_SIZE,
@@ -106,7 +107,7 @@ export function getDefaultDynamicProperties() {
}
},
[vectorStyles.ICON_SIZE]: {
- type: VectorStyle.STYLE_TYPE.DYNAMIC,
+ type: DynamicStyleProperty.type,
options: {
minSize: DEFAULT_MIN_SIZE,
maxSize: DEFAULT_MAX_SIZE,
@@ -114,7 +115,7 @@ export function getDefaultDynamicProperties() {
}
},
[vectorStyles.ICON_ORIENTATION]: {
- type: VectorStyle.STYLE_TYPE.STATIC,
+ type: StaticStyleProperty.type,
options: {
field: undefined,
}
diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector_style.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector_style.js
deleted file mode 100644
index f26f4df0b1753..0000000000000
--- a/x-pack/legacy/plugins/maps/public/layers/styles/vector_style.js
+++ /dev/null
@@ -1,639 +0,0 @@
-/*
- * 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 _ from 'lodash';
-import React from 'react';
-import { i18n } from '@kbn/i18n';
-import { getColorRampStops } from './color_utils';
-import { VectorStyleEditor } from './components/vector/vector_style_editor';
-import { getDefaultProperties, vectorStyles } from './vector_style_defaults';
-import { AbstractStyle } from './abstract_style';
-import { SOURCE_DATA_ID_ORIGIN, GEO_JSON_TYPE } from '../../../common/constants';
-import { VectorIcon } from './components/vector/legend/vector_icon';
-import { VectorStyleLegend } from './components/vector/legend/vector_style_legend';
-import { VECTOR_SHAPE_TYPES } from '../sources/vector_feature_types';
-import { SYMBOLIZE_AS_CIRCLE, SYMBOLIZE_AS_ICON } from './vector_constants';
-import {
- getMakiSymbolAnchor,
- LARGE_MAKI_ICON_SIZE,
- SMALL_MAKI_ICON_SIZE,
- HALF_LARGE_MAKI_ICON_SIZE
-} from './symbol_utils';
-
-export class VectorStyle extends AbstractStyle {
-
- static type = 'VECTOR';
- static STYLE_TYPE = { 'DYNAMIC': 'DYNAMIC', 'STATIC': 'STATIC' };
-
- static getComputedFieldName(styleName, fieldName) {
- return `${VectorStyle.getComputedFieldNamePrefix(fieldName)}__${styleName}`;
- }
-
- static getComputedFieldNamePrefix(fieldName) {
- return `__kbn__dynamic__${fieldName}`;
- }
-
- constructor(descriptor = {}, source) {
- super();
- this._source = source;
- this._descriptor = {
- ...descriptor,
- ...VectorStyle.createDescriptor(descriptor.properties),
- };
- }
-
- static createDescriptor(properties = {}) {
- return {
- type: VectorStyle.type,
- properties: { ...getDefaultProperties(), ...properties }
- };
- }
-
- static createDefaultStyleProperties(mapColors) {
- return getDefaultProperties(mapColors);
- }
-
- static getDisplayName() {
- return i18n.translate('xpack.maps.style.vector.displayNameLabel', {
- defaultMessage: 'Vector style'
- });
- }
-
- static description = '';
-
- renderEditor({ layer, onStyleDescriptorChange }) {
- const styleProperties = { ...this.getProperties() };
- const handlePropertyChange = (propertyName, settings) => {
- styleProperties[propertyName] = settings;//override single property, but preserve the rest
- const vectorStyleDescriptor = VectorStyle.createDescriptor(styleProperties);
- onStyleDescriptorChange(vectorStyleDescriptor);
- };
-
- return (
-
- );
- }
-
- /*
- * Changes to source descriptor and join descriptor will impact style properties.
- * For instance, a style property may be dynamically tied to the value of an ordinal field defined
- * by a join or a metric aggregation. The metric aggregation or join may be edited or removed.
- * When this happens, the style will be linked to a no-longer-existing ordinal field.
- * This method provides a way for a style to clean itself and return a descriptor that unsets any dynamic
- * properties that are tied to missing oridinal fields
- *
- * This method does not update its descriptor. It just returns a new descriptor that the caller
- * can then use to update store state via dispatch.
- */
- getDescriptorWithMissingStylePropsRemoved(nextOrdinalFields) {
- const originalProperties = this.getProperties();
- const updatedProperties = {};
- Object.keys(originalProperties).forEach(propertyName => {
- if (!this._isPropertyDynamic(propertyName)) {
- return;
- }
-
- const fieldName = _.get(originalProperties[propertyName], 'options.field.name');
- if (!fieldName) {
- return;
- }
-
- const matchingOrdinalField = nextOrdinalFields.find(oridinalField => {
- return fieldName === oridinalField.name;
- });
-
- if (matchingOrdinalField) {
- return;
- }
-
- updatedProperties[propertyName] = {
- type: VectorStyle.STYLE_TYPE.DYNAMIC,
- options: {
- ...originalProperties[propertyName].options
- }
- };
- delete updatedProperties[propertyName].options.field;
- });
-
- if (Object.keys(updatedProperties).length === 0) {
- return {
- hasChanges: false,
- nextStyleDescriptor: { ...this._descriptor },
- };
- }
-
- return {
- hasChanges: true,
- nextStyleDescriptor: VectorStyle.createDescriptor({
- ...originalProperties,
- ...updatedProperties,
- })
- };
- }
-
- async pluckStyleMetaFromSourceDataRequest(sourceDataRequest) {
- const features = _.get(sourceDataRequest.getData(), 'features', []);
- if (features.length === 0) {
- return {};
- }
-
- const scaledFields = this.getDynamicPropertiesArray()
- .map(({ options }) => {
- return {
- name: options.field.name,
- min: Infinity,
- max: -Infinity
- };
- });
-
- const supportedFeatures = await this._source.getSupportedShapeTypes();
- const isSingleFeatureType = supportedFeatures.length === 1;
-
- if (scaledFields.length === 0 && isSingleFeatureType) {
- // no meta data to pull from source data request.
- return {};
- }
-
- let hasPoints = false;
- let hasLines = false;
- let hasPolygons = false;
- for (let i = 0; i < features.length; i++) {
- const feature = features[i];
- if (!hasPoints && [GEO_JSON_TYPE.POINT, GEO_JSON_TYPE.MULTI_POINT].includes(feature.geometry.type)) {
- hasPoints = true;
- }
- if (!hasLines && [GEO_JSON_TYPE.LINE_STRING, GEO_JSON_TYPE.MULTI_LINE_STRING].includes(feature.geometry.type)) {
- hasLines = true;
- }
- if (!hasPolygons && [GEO_JSON_TYPE.POLYGON, GEO_JSON_TYPE.MULTI_POLYGON].includes(feature.geometry.type)) {
- hasPolygons = true;
- }
-
- for (let j = 0; j < scaledFields.length; j++) {
- const scaledField = scaledFields[j];
- const newValue = parseFloat(feature.properties[scaledField.name]);
- if (!isNaN(newValue)) {
- scaledField.min = Math.min(scaledField.min, newValue);
- scaledField.max = Math.max(scaledField.max, newValue);
- }
- }
- }
-
- const featuresMeta = {
- hasFeatureType: {
- [VECTOR_SHAPE_TYPES.POINT]: hasPoints,
- [VECTOR_SHAPE_TYPES.LINE]: hasLines,
- [VECTOR_SHAPE_TYPES.POLYGON]: hasPolygons
- }
- };
-
- scaledFields.forEach(({ min, max, name }) => {
- if (min !== Infinity && max !== -Infinity) {
- featuresMeta[name] = {
- min,
- max,
- delta: max - min,
- };
- }
- });
-
- return featuresMeta;
- }
-
- getSourceFieldNames() {
- const properties = this.getProperties();
- const fieldNames = [];
- Object.keys(properties).forEach(propertyName => {
- if (!this._isPropertyDynamic(propertyName)) {
- return;
- }
-
- const field = _.get(properties[propertyName], 'options.field', {});
- if (field.origin === SOURCE_DATA_ID_ORIGIN && field.name) {
- fieldNames.push(field.name);
- }
- });
-
- return fieldNames;
- }
-
- getProperties() {
- return this._descriptor.properties || {};
- }
-
- getDynamicPropertiesArray() {
- const styles = this.getProperties();
- return Object.keys(styles)
- .map(styleName => {
- const { type, options } = styles[styleName];
- return {
- styleName,
- type,
- options
- };
- })
- .filter(({ styleName }) => {
- return this._isPropertyDynamic(styleName);
- });
- }
-
- _isPropertyDynamic(propertyName) {
- const { type, options } = _.get(this._descriptor, ['properties', propertyName], {});
- return type === VectorStyle.STYLE_TYPE.DYNAMIC && options.field && options.field.name;
- }
-
- _checkIfOnlyFeatureType = async (featureType) => {
- const supportedFeatures = await this._source.getSupportedShapeTypes();
-
- if (supportedFeatures.length === 1) {
- return supportedFeatures[0] === featureType;
- }
-
- if (!this._descriptor.__styleMeta || !this._descriptor.__styleMeta.hasFeatureType) {
- return false;
- }
-
- const featureTypes = Object.keys(this._descriptor.__styleMeta.hasFeatureType);
- return featureTypes.reduce((isOnlySingleFeatureType, featureTypeKey) => {
- const hasFeature = this._descriptor.__styleMeta.hasFeatureType[featureTypeKey];
- return featureTypeKey === featureType
- ? isOnlySingleFeatureType && hasFeature
- : isOnlySingleFeatureType && !hasFeature;
- }, true);
- }
-
- _getIsPointsOnly = async () => {
- return this._checkIfOnlyFeatureType(VECTOR_SHAPE_TYPES.POINT);
- }
-
- _getIsLinesOnly = async () => {
- return this._checkIfOnlyFeatureType(VECTOR_SHAPE_TYPES.LINE);
- }
-
- _getIsPolygonsOnly = async () => {
- return this._checkIfOnlyFeatureType(VECTOR_SHAPE_TYPES.POLYGON);
- }
-
- _getFieldRange = (fieldName) => {
- return _.get(this._descriptor, ['__styleMeta', fieldName]);
- }
-
- getIcon = () => {
- const styles = this.getProperties();
- const symbolId = this.arePointsSymbolizedAsCircles()
- ? undefined
- : this._descriptor.properties.symbol.options.symbolId;
- return (
-
- );
- }
-
- getLegendDetails(getFieldLabel, getFieldFormatter) {
- const styles = this.getProperties();
- const styleProperties = Object.keys(styles).map(styleName => {
- const { type, options } = styles[styleName];
- return {
- name: styleName,
- type,
- options,
- range: options && options.field && options.field.name ? this._getFieldRange(options.field.name) : null,
- };
- });
-
- return (
-
- );
- }
-
- _getStyleFields() {
- return this.getDynamicPropertiesArray()
- .map(({ styleName, options }) => {
- const name = options.field.name;
-
- // "feature-state" data expressions are not supported with layout properties.
- // To work around this limitation, some styling values must fall back to geojson property values.
- let supportsFeatureState;
- let isScaled;
- if (styleName === 'iconSize'
- && this._descriptor.properties.symbol.options.symbolizeAs === SYMBOLIZE_AS_ICON) {
- supportsFeatureState = false;
- isScaled = true;
- } else if (styleName === 'iconOrientation') {
- supportsFeatureState = false;
- isScaled = false;
- } else if ((styleName === vectorStyles.FILL_COLOR || styleName === vectorStyles.LINE_COLOR)
- && options.useCustomColorRamp) {
- supportsFeatureState = true;
- isScaled = false;
- } else {
- supportsFeatureState = true;
- isScaled = true;
- }
-
- return {
- supportsFeatureState,
- isScaled,
- name,
- range: this._getFieldRange(name),
- computedName: VectorStyle.getComputedFieldName(styleName, name),
- };
- });
- }
-
- clearFeatureState(featureCollection, mbMap, sourceId) {
- const tmpFeatureIdentifier = {
- source: null,
- id: null
- };
- for (let i = 0; i < featureCollection.features.length; i++) {
- const feature = featureCollection.features[i];
- tmpFeatureIdentifier.source = sourceId;
- tmpFeatureIdentifier.id = feature.id;
- mbMap.removeFeatureState(tmpFeatureIdentifier);
- }
- }
-
- setFeatureState(featureCollection, mbMap, sourceId) {
-
- if (!featureCollection) {
- return;
- }
-
- const styleFields = this._getStyleFields();
- if (styleFields.length === 0) {
- return;
- }
-
- const tmpFeatureIdentifier = {
- source: null,
- id: null
- };
- const tmpFeatureState = {};
-
- //scale to [0,1] domain
- for (let i = 0; i < featureCollection.features.length; i++) {
- const feature = featureCollection.features[i];
-
- for (let j = 0; j < styleFields.length; j++) {
- const { supportsFeatureState, isScaled, name, range, computedName } = styleFields[j];
- const value = parseFloat(feature.properties[name]);
- let styleValue;
- if (isScaled) {
- if (isNaN(value) || !range) {//cannot scale
- styleValue = -1;//put outside range
- } else if (range.delta === 0) {//values are identical
- styleValue = 1;//snap to end of color range
- } else {
- styleValue = (value - range.min) / range.delta;
- }
- } else {
- if (isNaN(value)) {
- styleValue = 0;
- } else {
- styleValue = value;
- }
- }
-
- if (supportsFeatureState) {
- tmpFeatureState[computedName] = styleValue;
- } else {
- feature.properties[computedName] = styleValue;
- }
- }
- tmpFeatureIdentifier.source = sourceId;
- tmpFeatureIdentifier.id = feature.id;
- mbMap.setFeatureState(tmpFeatureIdentifier, tmpFeatureState);
- }
-
- const hasGeoJsonProperties = styleFields.some(({ supportsFeatureState }) => {
- return !supportsFeatureState;
- });
- return hasGeoJsonProperties;
- }
-
- _getMBDataDrivenColor({ targetName, colorStops, isSteps }) {
- if (isSteps) {
- const firstStopValue = colorStops[0];
- const lessThenFirstStopValue = firstStopValue - 1;
- return [
- 'step',
- ['coalesce', ['feature-state', targetName], lessThenFirstStopValue],
- 'rgba(0,0,0,0)', // MB will assign the base value to any features that is below the first stop value
- ...colorStops
- ];
- }
-
- return [
- 'interpolate',
- ['linear'],
- ['coalesce', ['feature-state', targetName], -1],
- -1, 'rgba(0,0,0,0)',
- ...colorStops
- ];
- }
-
- _getMbDataDrivenSize({ targetName, minSize, maxSize }) {
- return [
- 'interpolate',
- ['linear'],
- ['coalesce', ['feature-state', targetName], 0],
- 0, minSize,
- 1, maxSize
- ];
- }
-
- _getMBColor(styleName, styleDescriptor) {
- const isStatic = styleDescriptor.type === VectorStyle.STYLE_TYPE.STATIC;
- if (isStatic) {
- return _.get(styleDescriptor, 'options.color', null);
- }
-
- const isDynamicConfigComplete = _.has(styleDescriptor, 'options.field.name')
- && _.has(styleDescriptor, 'options.color');
- if (!isDynamicConfigComplete) {
- return null;
- }
-
- if (styleDescriptor.options.useCustomColorRamp &&
- (!styleDescriptor.options.customColorRamp ||
- !styleDescriptor.options.customColorRamp.length)) {
- return null;
- }
-
- return this._getMBDataDrivenColor({
- targetName: VectorStyle.getComputedFieldName(styleName, styleDescriptor.options.field.name),
- colorStops: this._getMBColorStops(styleDescriptor),
- isSteps: styleDescriptor.options.useCustomColorRamp,
- });
- }
-
- _getMBColorStops(styleDescriptor) {
- if (styleDescriptor.options.useCustomColorRamp) {
- return styleDescriptor.options.customColorRamp.reduce((accumulatedStops, nextStop) => {
- return [...accumulatedStops, nextStop.stop, nextStop.color];
- }, []);
- }
-
- return getColorRampStops(styleDescriptor.options.color);
- }
-
- _isSizeDynamicConfigComplete(styleDescriptor) {
- return _.has(styleDescriptor, 'options.field.name')
- && _.has(styleDescriptor, 'options.minSize')
- && _.has(styleDescriptor, 'options.maxSize');
- }
-
- _getMbSize(styleName, styleDescriptor) {
- if (styleDescriptor.type === VectorStyle.STYLE_TYPE.STATIC) {
- return styleDescriptor.options.size;
- }
-
- if (this._isSizeDynamicConfigComplete(styleDescriptor)) {
- return this._getMbDataDrivenSize({
- targetName: VectorStyle.getComputedFieldName(styleName, styleDescriptor.options.field.name),
- minSize: styleDescriptor.options.minSize,
- maxSize: styleDescriptor.options.maxSize,
- });
- }
-
- return null;
- }
-
- setMBPaintProperties({ alpha, mbMap, fillLayerId, lineLayerId }) {
- if (this._descriptor.properties.fillColor) {
- const color = this._getMBColor(vectorStyles.FILL_COLOR, this._descriptor.properties.fillColor);
- mbMap.setPaintProperty(fillLayerId, 'fill-color', color);
- mbMap.setPaintProperty(fillLayerId, 'fill-opacity', alpha);
- } else {
- mbMap.setPaintProperty(fillLayerId, 'fill-color', null);
- mbMap.setPaintProperty(fillLayerId, 'fill-opacity', 0);
- }
-
- if (this._descriptor.properties.lineColor) {
- const color = this._getMBColor(vectorStyles.LINE_COLOR, this._descriptor.properties.lineColor);
- mbMap.setPaintProperty(lineLayerId, 'line-color', color);
- mbMap.setPaintProperty(lineLayerId, 'line-opacity', alpha);
-
- } else {
- mbMap.setPaintProperty(lineLayerId, 'line-color', null);
- mbMap.setPaintProperty(lineLayerId, 'line-opacity', 0);
- }
-
- if (this._descriptor.properties.lineWidth) {
- const lineWidth = this._getMbSize(vectorStyles.LINE_WIDTH, this._descriptor.properties.lineWidth);
- mbMap.setPaintProperty(lineLayerId, 'line-width', lineWidth);
- } else {
- mbMap.setPaintProperty(lineLayerId, 'line-width', 0);
- }
- }
-
- setMBPaintPropertiesForPoints({ alpha, mbMap, pointLayerId }) {
- if (this._descriptor.properties.fillColor) {
- const color = this._getMBColor(vectorStyles.FILL_COLOR, this._descriptor.properties.fillColor);
- mbMap.setPaintProperty(pointLayerId, 'circle-color', color);
- mbMap.setPaintProperty(pointLayerId, 'circle-opacity', alpha);
- } else {
- mbMap.setPaintProperty(pointLayerId, 'circle-color', null);
- mbMap.setPaintProperty(pointLayerId, 'circle-opacity', 0);
- }
- if (this._descriptor.properties.lineColor) {
- const color = this._getMBColor(vectorStyles.LINE_COLOR, this._descriptor.properties.lineColor);
- mbMap.setPaintProperty(pointLayerId, 'circle-stroke-color', color);
- mbMap.setPaintProperty(pointLayerId, 'circle-stroke-opacity', alpha);
-
- } else {
- mbMap.setPaintProperty(pointLayerId, 'circle-stroke-color', null);
- mbMap.setPaintProperty(pointLayerId, 'circle-stroke-opacity', 0);
- }
- if (this._descriptor.properties.lineWidth) {
- const lineWidth = this._getMbSize(vectorStyles.LINE_WIDTH, this._descriptor.properties.lineWidth);
- mbMap.setPaintProperty(pointLayerId, 'circle-stroke-width', lineWidth);
- } else {
- mbMap.setPaintProperty(pointLayerId, 'circle-stroke-width', 0);
- }
- if (this._descriptor.properties.iconSize) {
- const iconSize = this._getMbSize(vectorStyles.ICON_SIZE, this._descriptor.properties.iconSize);
- mbMap.setPaintProperty(pointLayerId, 'circle-radius', iconSize);
- } else {
- mbMap.setPaintProperty(pointLayerId, 'circle-radius', 0);
- }
- }
-
- async setMBSymbolPropertiesForPoints({ mbMap, symbolLayerId, alpha }) {
- mbMap.setLayoutProperty(symbolLayerId, 'icon-ignore-placement', true);
-
- const symbolId = this._descriptor.properties.symbol.options.symbolId;
- mbMap.setLayoutProperty(symbolLayerId, 'icon-anchor', getMakiSymbolAnchor(symbolId));
- const color = this._getMBColor(vectorStyles.FILL_COLOR, this._descriptor.properties.fillColor);
- const haloColor = this._getMBColor(vectorStyles.LINE_COLOR, this._descriptor.properties.lineColor);
- const haloWidth = this._getMbSize(vectorStyles.LINE_WIDTH, this._descriptor.properties.lineWidth);
- // icon-color is only supported on SDF icons.
- mbMap.setPaintProperty(symbolLayerId, 'icon-color', color);
- mbMap.setPaintProperty(symbolLayerId, 'icon-halo-color', haloColor);
- mbMap.setPaintProperty(symbolLayerId, 'icon-halo-width', haloWidth);
- mbMap.setPaintProperty(symbolLayerId, 'icon-opacity', alpha);
-
- // circle sizing is by radius
- // to make icons be similiar in size to circles then have to deal with icon in half width measurements
- const iconSize = this._descriptor.properties.iconSize;
- if (iconSize.type === VectorStyle.STYLE_TYPE.STATIC) {
- const iconPixels = iconSize.options.size >= HALF_LARGE_MAKI_ICON_SIZE
- ? LARGE_MAKI_ICON_SIZE
- : SMALL_MAKI_ICON_SIZE;
- mbMap.setLayoutProperty(symbolLayerId, 'icon-image', `${symbolId}-${iconPixels}`);
-
- const halfIconPixels = iconPixels / 2;
- mbMap.setLayoutProperty(symbolLayerId, 'icon-size', iconSize.options.size / halfIconPixels);
- } else if (this._isSizeDynamicConfigComplete(iconSize)) {
- const iconPixels = iconSize.options.maxSize >= HALF_LARGE_MAKI_ICON_SIZE
- ? LARGE_MAKI_ICON_SIZE
- : SMALL_MAKI_ICON_SIZE;
- mbMap.setLayoutProperty(symbolLayerId, 'icon-image', `${symbolId}-${iconPixels}`);
-
- const halfIconPixels = iconPixels / 2;
- const targetName = VectorStyle.getComputedFieldName(vectorStyles.ICON_SIZE, iconSize.options.field.name);
- // Using property state instead of feature-state because layout properties do not support feature-state
- mbMap.setLayoutProperty(symbolLayerId, 'icon-size', [
- 'interpolate',
- ['linear'],
- ['coalesce', ['get', targetName], 0],
- 0, iconSize.options.minSize / halfIconPixels,
- 1, iconSize.options.maxSize / halfIconPixels
- ]);
- }
-
- const iconOrientation = this._descriptor.properties.iconOrientation;
- if (iconOrientation.type === VectorStyle.STYLE_TYPE.STATIC) {
- mbMap.setLayoutProperty(symbolLayerId, 'icon-rotate', iconOrientation.options.orientation);
- } else if (_.has(iconOrientation, 'options.field.name')) {
- const targetName = VectorStyle.getComputedFieldName(vectorStyles.ICON_ORIENTATION, iconOrientation.options.field.name);
- // Using property state instead of feature-state because layout properties do not support feature-state
- mbMap.setLayoutProperty(symbolLayerId, 'icon-rotate', [
- 'coalesce', ['get', targetName], 0
- ]);
- }
- }
-
- arePointsSymbolizedAsCircles() {
- return this._descriptor.properties.symbol.options.symbolizeAs === SYMBOLIZE_AS_CIRCLE;
- }
-}
diff --git a/x-pack/legacy/plugins/maps/public/layers/tooltips/es_aggmetric_tooltip_property.js b/x-pack/legacy/plugins/maps/public/layers/tooltips/es_aggmetric_tooltip_property.js
index 42629e192c27d..48fa4327a5217 100644
--- a/x-pack/legacy/plugins/maps/public/layers/tooltips/es_aggmetric_tooltip_property.js
+++ b/x-pack/legacy/plugins/maps/public/layers/tooltips/es_aggmetric_tooltip_property.js
@@ -14,6 +14,7 @@ export class ESAggMetricTooltipProperty extends ESTooltipProperty {
super(propertyKey, propertyName, rawValue, indexPattern);
this._metricField = metricField;
}
+
isFilterable() {
return false;
}
diff --git a/x-pack/legacy/plugins/maps/public/layers/tooltips/join_tooltip_property.js b/x-pack/legacy/plugins/maps/public/layers/tooltips/join_tooltip_property.js
index cc19521063f36..ed9b284c12826 100644
--- a/x-pack/legacy/plugins/maps/public/layers/tooltips/join_tooltip_property.js
+++ b/x-pack/legacy/plugins/maps/public/layers/tooltips/join_tooltip_property.js
@@ -38,12 +38,14 @@ export class JoinTooltipProperty extends TooltipProperty {
for (let i = 0; i < this._leftInnerJoins.length; i++) {
const rightSource = this._leftInnerJoins[i].getRightJoinSource();
- const esTooltipProperty = await rightSource.createESTooltipProperty(
- rightSource.getTerm(),
- this._tooltipProperty.getRawValue()
- );
- if (esTooltipProperty) {
- esFilters.push(...(await esTooltipProperty.getESFilters()));
+ const termField = rightSource.getTermField();
+ try {
+ const esTooltipProperty = await termField.createTooltipProperty(this._tooltipProperty.getRawValue());
+ if (esTooltipProperty) {
+ esFilters.push(...(await esTooltipProperty.getESFilters()));
+ }
+ } catch(e) {
+ console.error('Cannot create joined filter', e);
}
}
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 7372b549f6423..caa01a052b1c4 100644
--- a/x-pack/legacy/plugins/maps/public/layers/vector_layer.js
+++ b/x-pack/legacy/plugins/maps/public/layers/vector_layer.js
@@ -7,7 +7,7 @@
import turf from 'turf';
import React from 'react';
import { AbstractLayer } from './layer';
-import { VectorStyle } from './styles/vector_style';
+import { VectorStyle } from './styles/vector/vector_style';
import { InnerJoin } from './joins/inner_join';
import {
GEO_JSON_TYPE,
@@ -91,9 +91,11 @@ export class VectorLayer extends AbstractLayer {
this._joins = [];
if (options.layerDescriptor.joins) {
options.layerDescriptor.joins.forEach((joinDescriptor) => {
- this._joins.push(new InnerJoin(joinDescriptor, this._source.getInspectorAdapters()));
+ const join = new InnerJoin(joinDescriptor, this._source);
+ this._joins.push(join);
});
}
+ this._style = new VectorStyle(this._descriptor.style, this._source, this);
}
destroy() {
@@ -200,7 +202,7 @@ export class VectorLayer extends AbstractLayer {
return await source.getFieldFormatter(field.name);
};
- return this._style.getLegendDetails(getFieldLabel, getFieldFormatter);
+ return this._style.renderLegendDetails(getFieldLabel, getFieldFormatter);
}
_getBoundsBasedOnData() {
@@ -241,7 +243,6 @@ export class VectorLayer extends AbstractLayer {
return this._source.getDisplayName();
}
-
async getDateFields() {
const timeFields = await this._source.getDateFields();
return timeFields.map(({ label, name }) => {
@@ -253,7 +254,6 @@ export class VectorLayer extends AbstractLayer {
});
}
-
async getNumberFields() {
const numberFields = await this._source.getNumberFields();
const numberFieldOptions = numberFields.map(({ label, name }) => {
@@ -410,7 +410,7 @@ export class VectorLayer extends AbstractLayer {
} = await joinSource.getPropertiesMap(
searchFilters,
leftSourceName,
- join.getLeftFieldName(),
+ join.getLeftField().getName(),
registerCancelCallback.bind(null, requestToken));
stopLoading(sourceDataId, requestToken, propertiesMap);
return {
@@ -442,9 +442,7 @@ export class VectorLayer extends AbstractLayer {
const fieldNames = [
...this._source.getFieldNames(),
...this._style.getSourceFieldNames(),
- ...this.getValidJoins().map(join => {
- return join.getLeftFieldName();
- })
+ ...this.getValidJoins().map(join => join.getLeftField().getName())
];
return {
@@ -476,9 +474,8 @@ export class VectorLayer extends AbstractLayer {
let isFeatureVisible = true;
for (let j = 0; j < joinStates.length; j++) {
const joinState = joinStates[j];
- const InnerJoin = joinState.join;
- const rightMetricFields = InnerJoin.getRightMetricFields();
- const canJoinOnCurrent = InnerJoin.joinPropertiesToFeature(feature, joinState.propertiesMap, rightMetricFields);
+ const innerJoin = joinState.join;
+ const canJoinOnCurrent = innerJoin.joinPropertiesToFeature(feature, joinState.propertiesMap);
isFeatureVisible = isFeatureVisible && canJoinOnCurrent;
}
@@ -762,7 +759,7 @@ export class VectorLayer extends AbstractLayer {
const tooltipProperty = tooltipsFromSource[i];
const matchingJoins = [];
for (let j = 0; j < this._joins.length; j++) {
- if (this._joins[j].getLeftFieldName() === tooltipProperty.getPropertyKey()) {
+ if (this._joins[j].getLeftField().getName() === tooltipProperty.getPropertyKey()) {
matchingJoins.push(this._joins[j]);
}
}