diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.d.ts b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.d.ts
index 5e1ea68533f1..e420087628bc 100644
--- a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.d.ts
+++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.d.ts
@@ -30,6 +30,7 @@ export interface IVectorLayer extends ILayer {
getJoins(): IJoin[];
getValidJoins(): IJoin[];
getSource(): IVectorSource;
+ getStyle(): IVectorStyle;
}
export class VectorLayer extends AbstractLayer implements IVectorLayer {
@@ -73,4 +74,5 @@ export class VectorLayer extends AbstractLayer implements IVectorLayer {
_setMbPointsProperties(mbMap: unknown, mvtSourceLayer?: string): void;
_setMbLinePolygonProperties(mbMap: unknown, mvtSourceLayer?: string): void;
getSource(): IVectorSource;
+ getStyle(): IVectorStyle;
}
diff --git a/x-pack/plugins/maps/public/classes/styles/_index.scss b/x-pack/plugins/maps/public/classes/styles/_index.scss
index a1c4c297a3ac..3ee713ffc1a0 100644
--- a/x-pack/plugins/maps/public/classes/styles/_index.scss
+++ b/x-pack/plugins/maps/public/classes/styles/_index.scss
@@ -2,3 +2,5 @@
@import 'vector/components/style_prop_editor';
@import 'vector/components/color/color_stops';
@import 'vector/components/symbol/icon_select';
+@import 'vector/components/legend/category';
+@import 'vector/components/legend/vector_legend';
diff --git a/x-pack/plugins/maps/public/classes/styles/color_utils.js b/x-pack/plugins/maps/public/classes/styles/color_utils.js
index 2df743375a53..9dc79c006dff 100644
--- a/x-pack/plugins/maps/public/classes/styles/color_utils.js
+++ b/x-pack/plugins/maps/public/classes/styles/color_utils.js
@@ -11,7 +11,7 @@ import { euiPaletteColorBlind } from '@elastic/eui/lib/services';
import { ColorGradient } from './components/color_gradient';
import { vislibColorMaps } from '../../../../../../src/plugins/charts/public';
-const GRADIENT_INTERVALS = 8;
+export const GRADIENT_INTERVALS = 8;
export const DEFAULT_FILL_COLORS = euiPaletteColorBlind();
export const DEFAULT_LINE_COLORS = [
@@ -73,7 +73,7 @@ export function getColorRampCenterColor(colorRampName) {
// Returns an array of color stops
// [ stop_input_1: number, stop_output_1: color, stop_input_n: number, stop_output_n: color ]
-export function getOrdinalColorRampStops(colorRampName, min, max) {
+export function getOrdinalMbColorRampStops(colorRampName, min, max, numberColors) {
if (!colorRampName) {
return null;
}
@@ -82,7 +82,7 @@ export function getOrdinalColorRampStops(colorRampName, min, max) {
return null;
}
- const hexColors = getHexColorRangeStrings(colorRampName, GRADIENT_INTERVALS);
+ const hexColors = getHexColorRangeStrings(colorRampName, numberColors);
if (max === min) {
//just return single stop value
return [max, hexColors[hexColors.length - 1]];
diff --git a/x-pack/plugins/maps/public/classes/styles/color_utils.test.js b/x-pack/plugins/maps/public/classes/styles/color_utils.test.js
index 9a5ece01d520..ed7cafd53a6f 100644
--- a/x-pack/plugins/maps/public/classes/styles/color_utils.test.js
+++ b/x-pack/plugins/maps/public/classes/styles/color_utils.test.js
@@ -3,11 +3,10 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
-
import {
COLOR_GRADIENTS,
getColorRampCenterColor,
- getOrdinalColorRampStops,
+ getOrdinalMbColorRampStops,
getHexColorRangeStrings,
getLinearGradient,
getRGBColorRangeStrings,
@@ -25,7 +24,7 @@ describe('COLOR_GRADIENTS', () => {
describe('getRGBColorRangeStrings', () => {
it('Should create RGB color ramp', () => {
- expect(getRGBColorRangeStrings('Blues')).toEqual([
+ expect(getRGBColorRangeStrings('Blues', 8)).toEqual([
'rgb(247,250,255)',
'rgb(221,234,247)',
'rgb(197,218,238)',
@@ -61,7 +60,7 @@ describe('getColorRampCenterColor', () => {
describe('getColorRampStops', () => {
it('Should create color stops for custom range', () => {
- expect(getOrdinalColorRampStops('Blues', 0, 1000)).toEqual([
+ expect(getOrdinalMbColorRampStops('Blues', 0, 1000, 8)).toEqual([
0,
'#f7faff',
125,
@@ -82,7 +81,7 @@ describe('getColorRampStops', () => {
});
it('Should snap to end of color stops for identical range', () => {
- expect(getOrdinalColorRampStops('Blues', 23, 23)).toEqual([23, '#072f6b']);
+ expect(getOrdinalMbColorRampStops('Blues', 23, 23, 8)).toEqual([23, '#072f6b']);
});
});
diff --git a/x-pack/plugins/maps/public/classes/styles/components/color_gradient.js b/x-pack/plugins/maps/public/classes/styles/components/color_gradient.js
index 8772f33b76fd..bf7e88df3a69 100644
--- a/x-pack/plugins/maps/public/classes/styles/components/color_gradient.js
+++ b/x-pack/plugins/maps/public/classes/styles/components/color_gradient.js
@@ -5,7 +5,12 @@
*/
import React from 'react';
-import { COLOR_RAMP_NAMES, getRGBColorRangeStrings, getLinearGradient } from '../color_utils';
+import {
+ COLOR_RAMP_NAMES,
+ GRADIENT_INTERVALS,
+ getRGBColorRangeStrings,
+ getLinearGradient,
+} from '../color_utils';
import classNames from 'classnames';
export const ColorGradient = ({ colorRamp, colorRampName, className }) => {
@@ -14,7 +19,9 @@ export const ColorGradient = ({ colorRamp, colorRampName, className }) => {
}
const classes = classNames('mapColorGradient', className);
- const rgbColorStrings = colorRampName ? getRGBColorRangeStrings(colorRampName) : colorRamp;
+ const rgbColorStrings = colorRampName
+ ? getRGBColorRangeStrings(colorRampName, GRADIENT_INTERVALS)
+ : colorRamp;
const background = getLinearGradient(rgbColorStrings);
return
;
};
diff --git a/x-pack/plugins/maps/public/classes/styles/components/ranged_style_legend_row.js b/x-pack/plugins/maps/public/classes/styles/components/ranged_style_legend_row.js
index 3eb34ec1406d..4a43cc24e2c0 100644
--- a/x-pack/plugins/maps/public/classes/styles/components/ranged_style_legend_row.js
+++ b/x-pack/plugins/maps/public/classes/styles/components/ranged_style_legend_row.js
@@ -7,19 +7,12 @@
import React from 'react';
import PropTypes from 'prop-types';
-import { EuiFlexGroup, EuiFlexItem, EuiText, EuiSpacer, EuiToolTip } from '@elastic/eui';
+import { EuiFlexGroup, EuiFlexItem, EuiText, EuiToolTip } from '@elastic/eui';
export function RangedStyleLegendRow({ header, minLabel, maxLabel, propertyLabel, fieldLabel }) {
return (
-
- {header}
-
-
- {minLabel}
-
-
@@ -29,6 +22,14 @@ export function RangedStyleLegendRow({ header, minLabel, maxLabel, propertyLabel
+
+ {header}
+
+
+
+ {minLabel}
+
+
{maxLabel}
diff --git a/x-pack/plugins/maps/public/classes/styles/heatmap/heatmap_style.js b/x-pack/plugins/maps/public/classes/styles/heatmap/heatmap_style.js
index 1fa24943c5e5..3b5bcf591c2a 100644
--- a/x-pack/plugins/maps/public/classes/styles/heatmap/heatmap_style.js
+++ b/x-pack/plugins/maps/public/classes/styles/heatmap/heatmap_style.js
@@ -10,7 +10,7 @@ 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 { LAYER_STYLE_TYPE, GRID_RESOLUTION } from '../../../../common/constants';
-import { getOrdinalColorRampStops } from '../color_utils';
+import { getOrdinalMbColorRampStops, GRADIENT_INTERVALS } from '../color_utils';
import { i18n } from '@kbn/i18n';
import { EuiIcon } from '@elastic/eui';
@@ -85,7 +85,12 @@ export class HeatmapStyle extends AbstractStyle {
const { colorRampName } = this._descriptor;
if (colorRampName && colorRampName !== DEFAULT_HEATMAP_COLOR_RAMP_NAME) {
- const colorStops = getOrdinalColorRampStops(colorRampName, MIN_RANGE, MAX_RANGE);
+ const colorStops = getOrdinalMbColorRampStops(
+ colorRampName,
+ MIN_RANGE,
+ MAX_RANGE,
+ GRADIENT_INTERVALS
+ );
mbMap.setPaintProperty(layerId, 'heatmap-color', [
'interpolate',
['linear'],
diff --git a/x-pack/plugins/maps/public/classes/styles/vector/components/legend/_category.scss b/x-pack/plugins/maps/public/classes/styles/vector/components/legend/_category.scss
new file mode 100644
index 000000000000..aff843c3ed12
--- /dev/null
+++ b/x-pack/plugins/maps/public/classes/styles/vector/components/legend/_category.scss
@@ -0,0 +1,3 @@
+.mapLegendIconPreview {
+ width: $euiSizeL;
+}
diff --git a/x-pack/plugins/maps/public/classes/styles/vector/components/legend/_vector_legend.scss b/x-pack/plugins/maps/public/classes/styles/vector/components/legend/_vector_legend.scss
new file mode 100644
index 000000000000..d260f6effb2c
--- /dev/null
+++ b/x-pack/plugins/maps/public/classes/styles/vector/components/legend/_vector_legend.scss
@@ -0,0 +1,5 @@
+.vectorStyleLegendSpacer {
+ &:not(:last-child) {
+ margin-bottom: $euiSizeS;
+ }
+}
diff --git a/x-pack/plugins/maps/public/classes/styles/vector/components/legend/breaked_legend.js b/x-pack/plugins/maps/public/classes/styles/vector/components/legend/breaked_legend.js
new file mode 100644
index 000000000000..7e8e6896ef9c
--- /dev/null
+++ b/x-pack/plugins/maps/public/classes/styles/vector/components/legend/breaked_legend.js
@@ -0,0 +1,82 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import _ from 'lodash';
+import { EuiFlexGroup, EuiFlexItem, EuiText, EuiToolTip } from '@elastic/eui';
+import { Category } from './category';
+const EMPTY_VALUE = '';
+
+export class BreakedLegend extends React.Component {
+ state = {
+ label: EMPTY_VALUE,
+ };
+
+ componentDidMount() {
+ this._isMounted = true;
+ this._loadParams();
+ }
+
+ componentDidUpdate() {
+ this._loadParams();
+ }
+
+ componentWillUnmount() {
+ this._isMounted = false;
+ }
+
+ async _loadParams() {
+ const label = await this.props.style.getField().getLabel();
+ const newState = { label };
+ if (this._isMounted && !_.isEqual(this.state, newState)) {
+ this.setState(newState);
+ }
+ }
+
+ render() {
+ if (this.state.label === EMPTY_VALUE) {
+ return null;
+ }
+
+ const categories = this.props.breaks.map((brk, index) => {
+ return (
+
+
+
+ );
+ });
+
+ return (
+
+
+
+
+
+
+ {this.state.label}
+
+
+
+
+
+
+ {categories}
+
+
+ );
+ }
+}
diff --git a/x-pack/plugins/maps/public/classes/styles/vector/components/legend/category.js b/x-pack/plugins/maps/public/classes/styles/vector/components/legend/category.js
index b0f397b6375a..cfdbd728c221 100644
--- a/x-pack/plugins/maps/public/classes/styles/vector/components/legend/category.js
+++ b/x-pack/plugins/maps/public/classes/styles/vector/components/legend/category.js
@@ -31,13 +31,13 @@ export function Category({ styleName, label, color, isLinesOnly, isPointsOnly, s
}
return (
-
-
-
- {label}
-
- {renderIcon()}
-
-
+
+
+ {renderIcon()}
+
+
+ {label}
+
+
);
}
diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/components/ordinal_legend.js b/x-pack/plugins/maps/public/classes/styles/vector/components/legend/ordinal_legend.js
similarity index 50%
rename from x-pack/plugins/maps/public/classes/styles/vector/properties/components/ordinal_legend.js
rename to x-pack/plugins/maps/public/classes/styles/vector/components/legend/ordinal_legend.js
index 1ebd04211848..478d96962e47 100644
--- a/x-pack/plugins/maps/public/classes/styles/vector/properties/components/ordinal_legend.js
+++ b/x-pack/plugins/maps/public/classes/styles/vector/components/legend/ordinal_legend.js
@@ -4,9 +4,37 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import React from 'react';
+import React, { Fragment } from 'react';
import _ from 'lodash';
import { RangedStyleLegendRow } from '../../../components/ranged_style_legend_row';
+import { VECTOR_STYLES } from '../../../../../../common/constants';
+import { EuiFlexGroup, EuiFlexItem, EuiHorizontalRule } from '@elastic/eui';
+import { CircleIcon } from './circle_icon';
+
+function getLineWidthIcons() {
+ const defaultStyle = {
+ stroke: 'grey',
+ fill: 'none',
+ width: '12px',
+ };
+ return [
+ ,
+ ,
+ ,
+ ];
+}
+
+function getSymbolSizeIcons() {
+ const defaultStyle = {
+ stroke: 'grey',
+ fill: 'grey',
+ };
+ return [
+ ,
+ ,
+ ,
+ ];
+}
const EMPTY_VALUE = '';
export class OrdinalLegend extends React.Component {
@@ -45,7 +73,46 @@ export class OrdinalLegend extends React.Component {
this._isMounted = true;
this._loadParams();
}
+
+ _renderRangeLegendHeader() {
+ let icons;
+ if (this.props.style.getStyleName() === VECTOR_STYLES.LINE_WIDTH) {
+ icons = getLineWidthIcons();
+ } else if (this.props.style.getStyleName() === VECTOR_STYLES.ICON_SIZE) {
+ icons = getSymbolSizeIcons();
+ } else {
+ return null;
+ }
+
+ return (
+
+ {icons.map((icon, index) => {
+ const isLast = index === icons.length - 1;
+ let spacer;
+ if (!isLast) {
+ spacer = (
+
+
+
+ );
+ }
+ return (
+
+ {icon}
+ {spacer}
+
+ );
+ })}
+
+ );
+ }
+
render() {
+ const header = this._renderRangeLegendHeader();
+ if (!header) {
+ return null;
+ }
+
const fieldMeta = this.props.style.getRangeFieldMeta();
let minLabel = EMPTY_VALUE;
@@ -67,7 +134,7 @@ export class OrdinalLegend extends React.Component {
return (
{
- return (
-
- {style.renderLegendDetailRow({
- isLinesOnly,
- isPointsOnly,
- symbolId,
- })}
-
+ const legendRows = [];
+
+ for (let i = 0; i < styles.length; i++) {
+ const row = styles[i].renderLegendDetailRow({
+ isLinesOnly,
+ isPointsOnly,
+ symbolId,
+ });
+
+ legendRows.push(
+
+ {row}
+
);
- });
+ }
+
+ return legendRows;
}
diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_color_property.test.js.snap b/x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_color_property.test.js.snap
index ab47e88bb314..29eb52897a50 100644
--- a/x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_color_property.test.js.snap
+++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_color_property.test.js.snap
@@ -1,50 +1,12 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`Should render categorical legend with breaks from custom 1`] = `""`;
+exports[`categorical Should render categorical legend with breaks from custom 1`] = `""`;
-exports[`Should render categorical legend with breaks from default 1`] = `
+exports[`categorical Should render categorical legend with breaks from default 1`] = `
-
-
-
-
-
- Other
-
- }
- styleName="lineColor"
- />
-
-
-`;
-
-exports[`Should render ordinal legend 1`] = `
-
- }
- maxLabel="100_format"
- minLabel="0_format"
- propertyLabel="Border color"
-/>
-`;
-
-exports[`Should render ordinal legend with breaks 1`] = `
-
-
-
-
+ >
+
+
+
+
+
+
+
+ Other
+
+ }
+ styleName="lineColor"
+ />
+
+
+`;
+
+exports[`ordinal Should render custom ordinal legend with breaks 1`] = `
+
+
+
+
+
+
+
+`;
+
+exports[`ordinal Should render only single band of last color when delta is 0 1`] = `
+
+
+
+
+
+
+
+ foobar_label
+
+
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`ordinal Should render ordinal legend as bands 1`] = `
+
+
+
+
+
+
+
+ foobar_label
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
`;
diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_icon_property.test.tsx.snap b/x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_icon_property.test.tsx.snap
index 057907353d68..b4843324a0de 100644
--- a/x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_icon_property.test.tsx.snap
+++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_icon_property.test.tsx.snap
@@ -2,50 +2,9 @@
exports[`Should render categorical legend with breaks 1`] = `
-
-
-
-
-
- Other
-
- }
- styleName="icon"
- symbolId="square"
- />
-
+
+
+
+
+
+
+
+
`;
diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_size_property.test.tsx.snap b/x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_size_property.test.tsx.snap
new file mode 100644
index 000000000000..11138bf33704
--- /dev/null
+++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_size_property.test.tsx.snap
@@ -0,0 +1,73 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`renderLegendDetailRow Should render as range 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ }
+ maxLabel="100_format"
+ minLabel="0_format"
+ propertyLabel="Symbol size"
+/>
+`;
diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/__tests__/test_util.ts b/x-pack/plugins/maps/public/classes/styles/vector/properties/__tests__/test_util.ts
index 1c478bb85ccc..a8fba834d65a 100644
--- a/x-pack/plugins/maps/public/classes/styles/vector/properties/__tests__/test_util.ts
+++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/__tests__/test_util.ts
@@ -14,6 +14,7 @@ import {
StyleMetaDescriptor,
} from '../../../../../../common/descriptor_types';
import { AbstractField, IField } from '../../../../fields/field';
+import { IStyle, AbstractStyle } from '../../../style';
class MockField extends AbstractField {
async getLabel(): Promise {
@@ -29,14 +30,27 @@ export const mockField: IField = new MockField({
origin: FIELD_ORIGIN.SOURCE,
});
-class MockStyle {
+export class MockStyle extends AbstractStyle implements IStyle {
+ private readonly _min: number;
+ private readonly _max: number;
+
+ constructor({ min = 0, max = 100 } = {}) {
+ super(null);
+ this._min = min;
+ this._max = max;
+ }
+
getStyleMeta(): StyleMeta {
const geomTypes: GeometryTypes = {
isPointsOnly: false,
isLinesOnly: false,
isPolygonsOnly: false,
};
- const rangeFieldMeta: RangeFieldMeta = { min: 0, max: 100, delta: 100 };
+ const rangeFieldMeta: RangeFieldMeta = {
+ min: this._min,
+ max: this._max,
+ delta: this._max - this._min,
+ };
const catFieldMeta: CategoryFieldMeta = {
categories: [
{
@@ -65,8 +79,12 @@ class MockStyle {
}
export class MockLayer {
+ private readonly _style: IStyle;
+ constructor(style = new MockStyle()) {
+ this._style = style;
+ }
getStyle() {
- return new MockStyle();
+ return this._style;
}
getDataRequest() {
diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/components/categorical_legend.js b/x-pack/plugins/maps/public/classes/styles/vector/properties/components/categorical_legend.js
deleted file mode 100644
index a46492b6034a..000000000000
--- a/x-pack/plugins/maps/public/classes/styles/vector/properties/components/categorical_legend.js
+++ /dev/null
@@ -1,48 +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 React from 'react';
-import _ from 'lodash';
-const EMPTY_VALUE = '';
-
-export class CategoricalLegend extends React.Component {
- state = {
- label: EMPTY_VALUE,
- };
-
- componentDidMount() {
- this._isMounted = true;
- this._loadParams();
- }
-
- componentDidUpdate() {
- this._loadParams();
- }
-
- componentWillUnmount() {
- this._isMounted = false;
- }
-
- async _loadParams() {
- const label = await this.props.style.getField().getLabel();
- const newState = { label };
- if (this._isMounted && !_.isEqual(this.state, newState)) {
- this.setState(newState);
- }
- }
-
- render() {
- if (this.state.label === EMPTY_VALUE) {
- return null;
- }
- return this.props.style.renderBreakedLegend({
- fieldLabel: this.state.label,
- isLinesOnly: this.props.isLinesOnly,
- isPointsOnly: this.props.isPointsOnly,
- symbolId: this.props.symbolId,
- });
- }
-}
diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_color_property.js b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_color_property.js
index 0afc784c482c..4c02dee762e9 100644
--- a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_color_property.js
+++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_color_property.js
@@ -5,23 +5,24 @@
*/
import { DynamicStyleProperty } from './dynamic_style_property';
-import { getOtherCategoryLabel, makeMbClampedNumberExpression } from '../style_util';
-import { getOrdinalColorRampStops, getColorPalette } from '../../color_utils';
-import { ColorGradient } from '../../components/color_gradient';
-import React from 'react';
+import { makeMbClampedNumberExpression, dynamicRound } from '../style_util';
import {
- EuiFlexGroup,
- EuiFlexItem,
- EuiSpacer,
- EuiText,
- EuiToolTip,
- EuiTextColor,
-} from '@elastic/eui';
-import { Category } from '../components/legend/category';
-import { COLOR_MAP_TYPE, RGBA_0000 } from '../../../../../common/constants';
-import { isCategoricalStopsInvalid } from '../components/color/color_stops_utils';
+ getOrdinalMbColorRampStops,
+ getColorPalette,
+ getHexColorRangeStrings,
+ GRADIENT_INTERVALS,
+} from '../../color_utils';
+import React from 'react';
+import { COLOR_MAP_TYPE } from '../../../../../common/constants';
+import {
+ isCategoricalStopsInvalid,
+ getOtherCategoryLabel,
+} from '../components/color/color_stops_utils';
+import { BreakedLegend } from '../components/legend/breaked_legend';
+import { EuiTextColor } from '@elastic/eui';
const EMPTY_STOPS = { stops: [], defaultColor: null };
+const RGBA_0000 = 'rgba(0,0,0,0)';
export class DynamicColorProperty extends DynamicStyleProperty {
syncCircleColorWithMb(mbLayerId, mbMap, alpha) {
@@ -99,14 +100,6 @@ export class DynamicColorProperty extends DynamicStyleProperty {
return true;
}
- isOrdinalRanged() {
- return this.isOrdinal() && !this._options.useCustomColorRamp;
- }
-
- hasOrdinalBreaks() {
- return (this.isOrdinal() && this._options.useCustomColorRamp) || this.isCategorical();
- }
-
_getMbColor() {
if (!this._field || !this._field.getName()) {
return null;
@@ -142,10 +135,11 @@ export class DynamicColorProperty extends DynamicStyleProperty {
return null;
}
- const colorStops = getOrdinalColorRampStops(
+ const colorStops = getOrdinalMbColorRampStops(
this._options.color,
rangeFieldMeta.min,
- rangeFieldMeta.max
+ rangeFieldMeta.max,
+ GRADIENT_INTERVALS
);
if (!colorStops) {
return null;
@@ -237,28 +231,47 @@ export class DynamicColorProperty extends DynamicStyleProperty {
for (let i = 0; i < stops.length; i++) {
const stop = stops[i];
const branch = `${stop.stop}`;
- if (typeof branch === 'string') {
- mbStops.push(branch);
- mbStops.push(stop.color);
- }
+ mbStops.push(branch);
+ mbStops.push(stop.color);
}
mbStops.push(defaultColor); //last color is default color
return ['match', ['to-string', ['get', this._field.getName()]], ...mbStops];
}
- renderRangeLegendHeader() {
- if (this._options.color) {
- return ;
- } else {
- return null;
- }
- }
-
_getColorRampStops() {
- return this._options.useCustomColorRamp && this._options.customColorRamp
- ? this._options.customColorRamp
- : [];
+ if (this._options.useCustomColorRamp && this._options.customColorRamp) {
+ return this._options.customColorRamp;
+ }
+
+ if (!this._options.color) {
+ return [];
+ }
+
+ const rangeFieldMeta = this.getRangeFieldMeta();
+ if (!rangeFieldMeta) {
+ return [];
+ }
+
+ const colors = getHexColorRangeStrings(this._options.color, GRADIENT_INTERVALS);
+
+ if (rangeFieldMeta.delta === 0) {
+ //map to last color.
+ return [
+ {
+ color: colors[colors.length - 1],
+ stop: dynamicRound(rangeFieldMeta.max),
+ },
+ ];
+ }
+
+ return colors.map((color, index) => {
+ const rawStopValue = rangeFieldMeta.min + rangeFieldMeta.delta * (index / GRADIENT_INTERVALS);
+ return {
+ color,
+ stop: dynamicRound(rawStopValue),
+ };
+ });
}
_getColorStops() {
@@ -274,55 +287,33 @@ export class DynamicColorProperty extends DynamicStyleProperty {
}
}
- renderBreakedLegend({ fieldLabel, isPointsOnly, isLinesOnly, symbolId }) {
- const categories = [];
+ renderLegendDetailRow({ isPointsOnly, isLinesOnly, symbolId }) {
const { stops, defaultColor } = this._getColorStops();
- stops.map(({ stop, color }) => {
- categories.push(
-
- );
+ const breaks = [];
+ stops.forEach(({ stop, color }) => {
+ if (stop) {
+ breaks.push({
+ color,
+ symbolId,
+ label: this.formatField(stop),
+ });
+ }
});
-
if (defaultColor) {
- categories.push(
- {getOtherCategoryLabel()}}
- color={defaultColor}
- isLinesOnly={isLinesOnly}
- isPointsOnly={isPointsOnly}
- symbolId={symbolId}
- />
- );
+ breaks.push({
+ color: defaultColor,
+ label: {getOtherCategoryLabel()},
+ symbolId,
+ });
}
return (
-
-
-
- {categories}
-
-
-
-
-
-
- {fieldLabel}
-
-
-
-
-
-
+
);
}
}
diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_color_property.test.js b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_color_property.test.js
index afcdf1e3cfc5..1879b260da2e 100644
--- a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_color_property.test.js
+++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_color_property.test.js
@@ -16,12 +16,18 @@ import { shallow } from 'enzyme';
import { DynamicColorProperty } from './dynamic_color_property';
import { COLOR_MAP_TYPE, VECTOR_STYLES } from '../../../../../common/constants';
-import { mockField, MockLayer } from './__tests__/test_util';
+import { mockField, MockLayer, MockStyle } from './__tests__/test_util';
-const makeProperty = (options, field = mockField) => {
- return new DynamicColorProperty(options, VECTOR_STYLES.LINE_COLOR, field, new MockLayer(), () => {
- return (x) => x + '_format';
- });
+const makeProperty = (options, mockStyle, field = mockField) => {
+ return new DynamicColorProperty(
+ options,
+ VECTOR_STYLES.LINE_COLOR,
+ field,
+ new MockLayer(mockStyle),
+ () => {
+ return (x) => x + '_format';
+ }
+ );
};
const defaultLegendParams = {
@@ -29,91 +35,121 @@ const defaultLegendParams = {
isLinesOnly: false,
};
-test('Should render ordinal legend', async () => {
- const colorStyle = makeProperty({
- color: 'Blues',
- type: undefined,
+describe('ordinal', () => {
+ test('Should render ordinal legend as bands', async () => {
+ const colorStyle = makeProperty({
+ color: 'Blues',
+ type: undefined,
+ });
+
+ const legendRow = colorStyle.renderLegendDetailRow(defaultLegendParams);
+
+ const component = shallow(legendRow);
+
+ // Ensure all promises resolve
+ await new Promise((resolve) => process.nextTick(resolve));
+ // Ensure the state changes are reflected
+ component.update();
+
+ expect(component).toMatchSnapshot();
});
- const legendRow = colorStyle.renderLegendDetailRow(defaultLegendParams);
+ test('Should render only single band of last color when delta is 0', async () => {
+ const colorStyle = makeProperty(
+ {
+ color: 'Blues',
+ type: undefined,
+ },
+ new MockStyle({ min: 100, max: 100 })
+ );
- const component = shallow(legendRow);
+ const legendRow = colorStyle.renderLegendDetailRow(defaultLegendParams);
- expect(component).toMatchSnapshot();
+ const component = shallow(legendRow);
+
+ // Ensure all promises resolve
+ await new Promise((resolve) => process.nextTick(resolve));
+ // Ensure the state changes are reflected
+ component.update();
+
+ expect(component).toMatchSnapshot();
+ });
+
+ test('Should render custom ordinal legend with breaks', async () => {
+ const colorStyle = makeProperty({
+ type: COLOR_MAP_TYPE.ORDINAL,
+ useCustomColorRamp: true,
+ customColorRamp: [
+ {
+ stop: 0,
+ color: '#FF0000',
+ },
+ {
+ stop: 10,
+ color: '#00FF00',
+ },
+ ],
+ });
+
+ const legendRow = colorStyle.renderLegendDetailRow(defaultLegendParams);
+
+ const component = shallow(legendRow);
+
+ // Ensure all promises resolve
+ await new Promise((resolve) => process.nextTick(resolve));
+ // Ensure the state changes are reflected
+ component.update();
+
+ expect(component).toMatchSnapshot();
+ });
});
-test('Should render ordinal legend with breaks', async () => {
- const colorStyle = makeProperty({
- type: COLOR_MAP_TYPE.ORDINAL,
- useCustomColorRamp: true,
- customColorRamp: [
- {
- stop: 0,
- color: '#FF0000',
- },
- {
- stop: 10,
- color: '#00FF00',
- },
- ],
+describe('categorical', () => {
+ test('Should render categorical legend with breaks from default', async () => {
+ const colorStyle = makeProperty({
+ type: COLOR_MAP_TYPE.CATEGORICAL,
+ useCustomColorPalette: false,
+ colorCategory: 'palette_0',
+ });
+
+ const legendRow = colorStyle.renderLegendDetailRow(defaultLegendParams);
+
+ const component = shallow(legendRow);
+
+ // Ensure all promises resolve
+ await new Promise((resolve) => process.nextTick(resolve));
+ // Ensure the state changes are reflected
+ component.update();
+
+ expect(component).toMatchSnapshot();
});
- const legendRow = colorStyle.renderLegendDetailRow(defaultLegendParams);
+ test('Should render categorical legend with breaks from custom', async () => {
+ const colorStyle = makeProperty({
+ type: COLOR_MAP_TYPE.CATEGORICAL,
+ useCustomColorPalette: true,
+ customColorPalette: [
+ {
+ stop: null, //should include the default stop
+ color: '#FFFF00',
+ },
+ {
+ stop: 'US_STOP',
+ color: '#FF0000',
+ },
+ {
+ stop: 'CN_STOP',
+ color: '#00FF00',
+ },
+ ],
+ });
- const component = shallow(legendRow);
+ const legendRow = colorStyle.renderLegendDetailRow(defaultLegendParams);
- // Ensure all promises resolve
- await new Promise((resolve) => process.nextTick(resolve));
- // Ensure the state changes are reflected
- component.update();
+ const component = shallow(legendRow);
- expect(component).toMatchSnapshot();
-});
-
-test('Should render categorical legend with breaks from default', async () => {
- const colorStyle = makeProperty({
- type: COLOR_MAP_TYPE.CATEGORICAL,
- useCustomColorPalette: false,
- colorCategory: 'palette_0',
+ expect(component).toMatchSnapshot();
});
-
- const legendRow = colorStyle.renderLegendDetailRow(defaultLegendParams);
-
- const component = shallow(legendRow);
-
- // Ensure all promises resolve
- await new Promise((resolve) => process.nextTick(resolve));
- // Ensure the state changes are reflected
- component.update();
-
- expect(component).toMatchSnapshot();
-});
-
-test('Should render categorical legend with breaks from custom', async () => {
- const colorStyle = makeProperty({
- type: COLOR_MAP_TYPE.CATEGORICAL,
- useCustomColorPalette: true,
- customColorPalette: [
- {
- stop: null, //should include the default stop
- color: '#FFFF00',
- },
- {
- stop: 'US_STOP',
- color: '#FF0000',
- },
- {
- stop: 'CN_STOP',
- color: '#00FF00',
- },
- ],
- });
-
- const legendRow = colorStyle.renderLegendDetailRow(defaultLegendParams);
-
- const component = shallow(legendRow);
-
- expect(component).toMatchSnapshot();
});
function makeFeatures(foobarPropValues) {
@@ -201,7 +237,7 @@ describe('supportsFieldMeta', () => {
const dynamicStyleOptions = {
type: COLOR_MAP_TYPE.ORDINAL,
};
- const styleProp = makeProperty(dynamicStyleOptions, field);
+ const styleProp = makeProperty(dynamicStyleOptions, undefined, field);
expect(styleProp.supportsFieldMeta()).toEqual(false);
});
@@ -210,7 +246,7 @@ describe('supportsFieldMeta', () => {
const dynamicStyleOptions = {
type: COLOR_MAP_TYPE.ORDINAL,
};
- const styleProp = makeProperty(dynamicStyleOptions, null);
+ const styleProp = makeProperty(dynamicStyleOptions, undefined, null);
expect(styleProp.supportsFieldMeta()).toEqual(false);
});
diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_icon_property.js b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_icon_property.js
index 27c4fca7d701..c7620512710d 100644
--- a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_icon_property.js
+++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_icon_property.js
@@ -6,19 +6,11 @@
import _ from 'lodash';
import React from 'react';
-import { getOtherCategoryLabel, assignCategoriesToPalette } from '../style_util';
import { DynamicStyleProperty } from './dynamic_style_property';
import { getIconPalette, getMakiIconId, getMakiSymbolAnchor } from '../symbol_utils';
-
-import {
- EuiFlexGroup,
- EuiFlexItem,
- EuiSpacer,
- EuiText,
- EuiToolTip,
- EuiTextColor,
-} from '@elastic/eui';
-import { Category } from '../components/legend/category';
+import { BreakedLegend } from '../components/legend/breaked_legend';
+import { getOtherCategoryLabel, assignCategoriesToPalette } from '../style_util';
+import { EuiTextColor } from '@elastic/eui';
export class DynamicIconProperty extends DynamicStyleProperty {
isOrdinal() {
@@ -60,7 +52,7 @@ export class DynamicIconProperty extends DynamicStyleProperty {
}
return {
- fallback:
+ fallbackSymbolId:
this._options.customIconStops.length > 0 ? this._options.customIconStops[0].icon : null,
stops,
};
@@ -73,9 +65,9 @@ export class DynamicIconProperty extends DynamicStyleProperty {
}
_getMbIconImageExpression(iconPixelSize) {
- const { stops, fallback } = this._getPaletteStops();
+ const { stops, fallbackSymbolId } = this._getPaletteStops();
- if (stops.length < 1 || !fallback) {
+ if (stops.length < 1 || !fallbackSymbolId) {
//occurs when no data
return null;
}
@@ -85,14 +77,17 @@ export class DynamicIconProperty extends DynamicStyleProperty {
mbStops.push(`${stop}`);
mbStops.push(getMakiIconId(style, iconPixelSize));
});
- mbStops.push(getMakiIconId(fallback, iconPixelSize)); //last item is fallback style for anything that does not match provided stops
+
+ if (fallbackSymbolId) {
+ mbStops.push(getMakiIconId(fallbackSymbolId, iconPixelSize)); //last item is fallback style for anything that does not match provided stops
+ }
return ['match', ['to-string', ['get', this._field.getName()]], ...mbStops];
}
_getMbIconAnchorExpression() {
- const { stops, fallback } = this._getPaletteStops();
+ const { stops, fallbackSymbolId } = this._getPaletteStops();
- if (stops.length < 1 || !fallback) {
+ if (stops.length < 1 || !fallbackSymbolId) {
//occurs when no data
return null;
}
@@ -102,7 +97,10 @@ export class DynamicIconProperty extends DynamicStyleProperty {
mbStops.push(`${stop}`);
mbStops.push(getMakiSymbolAnchor(style));
});
- mbStops.push(getMakiSymbolAnchor(fallback)); //last item is fallback style for anything that does not match provided stops
+
+ if (fallbackSymbolId) {
+ mbStops.push(getMakiSymbolAnchor(fallbackSymbolId)); //last item is fallback style for anything that does not match provided stops
+ }
return ['match', ['to-string', ['get', this._field.getName()]], ...mbStops];
}
@@ -110,55 +108,34 @@ export class DynamicIconProperty extends DynamicStyleProperty {
return this._field && this._field.isValid();
}
- renderBreakedLegend({ fieldLabel, isPointsOnly, isLinesOnly }) {
- const categories = [];
- const { stops, fallback } = this._getPaletteStops();
- stops.map(({ stop, style }) => {
- categories.push(
-
- );
+ renderLegendDetailRow({ isPointsOnly, isLinesOnly }) {
+ const { stops, fallbackSymbolId } = this._getPaletteStops();
+ const breaks = [];
+ stops.forEach(({ stop, style }) => {
+ if (stop) {
+ breaks.push({
+ color: 'grey',
+ label: this.formatField(stop),
+ symbolId: style,
+ });
+ }
});
- if (fallback) {
- categories.push(
- {getOtherCategoryLabel()}}
- color="grey"
- isLinesOnly={isLinesOnly}
- isPointsOnly={isPointsOnly}
- symbolId={fallback}
- />
- );
+ if (fallbackSymbolId) {
+ breaks.push({
+ color: 'grey',
+ label: {getOtherCategoryLabel()},
+ symbolId: fallbackSymbolId,
+ });
}
return (
-
-
-
- {categories}
-
-
-
-
-
-
- {fieldLabel}
-
-
-
-
-
-
+
);
}
}
diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_size_property.js b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_size_property.js
index 71ac25f0c6e6..898da439c44a 100644
--- a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_size_property.js
+++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_size_property.js
@@ -5,6 +5,7 @@
*/
import { DynamicStyleProperty } from './dynamic_style_property';
+import { OrdinalLegend } from '../components/legend/ordinal_legend';
import { makeMbClampedNumberExpression } from '../style_util';
import {
HALF_LARGE_MAKI_ICON_SIZE,
@@ -13,34 +14,7 @@ import {
} from '../symbol_utils';
import { VECTOR_STYLES } from '../../../../../common/constants';
import _ from 'lodash';
-import { CircleIcon } from '../components/legend/circle_icon';
-import React, { Fragment } from 'react';
-import { EuiFlexGroup, EuiFlexItem, EuiHorizontalRule } from '@elastic/eui';
-
-function getLineWidthIcons() {
- const defaultStyle = {
- stroke: 'grey',
- fill: 'none',
- width: '12px',
- };
- return [
- ,
- ,
- ,
- ];
-}
-
-function getSymbolSizeIcons() {
- const defaultStyle = {
- stroke: 'grey',
- fill: 'grey',
- };
- return [
- ,
- ,
- ,
- ];
-}
+import React from 'react';
export class DynamicSizeProperty extends DynamicStyleProperty {
constructor(options, styleName, field, vectorLayer, getFieldFormatter, isSymbolizedAsIcon) {
@@ -99,13 +73,9 @@ export class DynamicSizeProperty extends DynamicStyleProperty {
}
}
- syncCircleStrokeWidthWithMb(mbLayerId, mbMap, hasNoRadius) {
- if (hasNoRadius) {
- mbMap.setPaintProperty(mbLayerId, 'circle-stroke-width', 0);
- } else {
- const lineWidth = this.getMbSizeExpression();
- mbMap.setPaintProperty(mbLayerId, 'circle-stroke-width', lineWidth);
- }
+ syncCircleStrokeWidthWithMb(mbLayerId, mbMap) {
+ const lineWidth = this.getMbSizeExpression();
+ mbMap.setPaintProperty(mbLayerId, 'circle-stroke-width', lineWidth);
}
syncCircleRadiusWithMb(mbLayerId, mbMap) {
@@ -166,36 +136,7 @@ export class DynamicSizeProperty extends DynamicStyleProperty {
);
}
- renderRangeLegendHeader() {
- let icons;
- if (this.getStyleName() === VECTOR_STYLES.LINE_WIDTH) {
- icons = getLineWidthIcons();
- } else if (this.getStyleName() === VECTOR_STYLES.ICON_SIZE) {
- icons = getSymbolSizeIcons();
- } else {
- return null;
- }
-
- return (
-
- {icons.map((icon, index) => {
- const isLast = index === icons.length - 1;
- let spacer;
- if (!isLast) {
- spacer = (
-
-
-
- );
- }
- return (
-
- {icon}
- {spacer}
-
- );
- })}
-
- );
+ renderLegendDetailRow() {
+ return ;
}
}
diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_size_property.test.tsx b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_size_property.test.tsx
new file mode 100644
index 000000000000..34f3e796f409
--- /dev/null
+++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_size_property.test.tsx
@@ -0,0 +1,102 @@
+/*
+ * 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 { IVectorStyle } from '../vector_style';
+
+jest.mock('ui/new_platform');
+jest.mock('../components/vector_style_editor', () => ({
+ VectorStyleEditor: () => {
+ return mockVectorStyleEditor
;
+ },
+}));
+
+import React from 'react';
+import { shallow } from 'enzyme';
+
+// @ts-ignore
+import { DynamicSizeProperty } from './dynamic_size_property';
+import { StyleMeta } from '../style_meta';
+import { FIELD_ORIGIN, VECTOR_STYLES } from '../../../../../common/constants';
+import { DataRequest } from '../../../util/data_request';
+import { IVectorLayer } from '../../../layers/vector_layer/vector_layer';
+import { IField } from '../../../fields/field';
+
+// @ts-ignore
+const mockField: IField = {
+ async getLabel() {
+ return 'foobar_label';
+ },
+ getName() {
+ return 'foobar';
+ },
+ getRootName() {
+ return 'foobar';
+ },
+ getOrigin() {
+ return FIELD_ORIGIN.SOURCE;
+ },
+ supportsFieldMeta() {
+ return true;
+ },
+ canValueBeFormatted() {
+ return true;
+ },
+ async getDataType() {
+ return 'number';
+ },
+};
+
+// @ts-ignore
+const mockLayer: IVectorLayer = {
+ getDataRequest(): DataRequest | undefined {
+ return undefined;
+ },
+ getStyle(): IVectorStyle {
+ // @ts-ignore
+ return {
+ getStyleMeta(): StyleMeta {
+ return new StyleMeta({
+ geometryTypes: {
+ isPointsOnly: true,
+ isLinesOnly: false,
+ isPolygonsOnly: false,
+ },
+ fieldMeta: {
+ foobar: {
+ range: { min: 0, max: 100, delta: 100 },
+ categories: { categories: [] },
+ },
+ },
+ });
+ },
+ };
+ },
+};
+
+const makeProperty: DynamicSizeProperty = (options: object) => {
+ return new DynamicSizeProperty(options, VECTOR_STYLES.ICON_SIZE, mockField, mockLayer, () => {
+ return (x: string) => x + '_format';
+ });
+};
+
+const defaultLegendParams = {
+ isPointsOnly: true,
+ isLinesOnly: false,
+};
+
+describe('renderLegendDetailRow', () => {
+ test('Should render as range', async () => {
+ const sizeProp = makeProperty();
+ const legendRow = sizeProp.renderLegendDetailRow(defaultLegendParams);
+ const component = shallow(legendRow);
+
+ // Ensure all promises resolve
+ await new Promise((resolve) => process.nextTick(resolve));
+ // Ensure the state changes are reflected
+ component.update();
+ expect(component).toMatchSnapshot();
+ });
+});
diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.js b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.js
index 82645b3a2931..98d5d3feb60e 100644
--- a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.js
+++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.js
@@ -9,8 +9,6 @@ import { AbstractStyleProperty } from './style_property';
import { DEFAULT_SIGMA } from '../vector_style_defaults';
import { STYLE_TYPE, SOURCE_META_ID_ORIGIN, FIELD_ORIGIN } from '../../../../../common/constants';
import React from 'react';
-import { OrdinalLegend } from './components/ordinal_legend';
-import { CategoricalLegend } from './components/categorical_legend';
import { OrdinalFieldMetaPopover } from '../components/field_meta/ordinal_field_meta_popover';
import { CategoricalFieldMetaPopover } from '../components/field_meta/categorical_field_meta_popover';
@@ -119,14 +117,6 @@ export class DynamicStyleProperty extends AbstractStyleProperty {
return 0;
}
- hasOrdinalBreaks() {
- return false;
- }
-
- isOrdinalRanged() {
- return true;
- }
-
isComplete() {
return !!this._field;
}
@@ -280,49 +270,14 @@ export class DynamicStyleProperty extends AbstractStyleProperty {
}
getNumericalMbFeatureStateValue(value) {
- if (typeof value === 'number') {
- return value;
- }
-
const valueAsFloat = parseFloat(value);
return isNaN(valueAsFloat) ? null : valueAsFloat;
}
- renderBreakedLegend() {
+ renderLegendDetailRow() {
return null;
}
- _renderCategoricalLegend({ isPointsOnly, isLinesOnly, symbolId }) {
- return (
-
- );
- }
-
- _renderRangeLegend() {
- return ;
- }
-
- renderLegendDetailRow({ isPointsOnly, isLinesOnly, symbolId }) {
- if (this.isOrdinal()) {
- if (this.isOrdinalRanged()) {
- return this._renderRangeLegend();
- } else if (this.hasOrdinalBreaks()) {
- return this._renderCategoricalLegend({ isPointsOnly, isLinesOnly, symbolId });
- } else {
- return null;
- }
- } else if (this.isCategorical()) {
- return this._renderCategoricalLegend({ isPointsOnly, isLinesOnly, symbolId });
- } else {
- return null;
- }
- }
-
renderFieldMetaPopover(onFieldMetaOptionsChange) {
if (!this.supportsFieldMeta()) {
return null;
diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/style_property.ts b/x-pack/plugins/maps/public/classes/styles/vector/properties/style_property.ts
index af04a95e3c3b..b704e4bd5697 100644
--- a/x-pack/plugins/maps/public/classes/styles/vector/properties/style_property.ts
+++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/style_property.ts
@@ -23,7 +23,6 @@ export interface IStyleProperty {
formatField(value: string | undefined): string;
getStyleName(): VECTOR_STYLES;
getOptions(): StylePropertyOptions;
- renderRangeLegendHeader(): ReactElement | null;
renderLegendDetailRow(legendProps: LegendProps): ReactElement | null;
renderFieldMetaPopover(
onFieldMetaOptionsChange: (fieldMetaOptions: FieldMetaOptions) => void
@@ -67,10 +66,6 @@ export class AbstractStyleProperty implements IStyleProperty {
return this._options || {};
}
- renderRangeLegendHeader() {
- return null;
- }
-
renderLegendDetailRow() {
return null;
}
diff --git a/x-pack/plugins/maps/public/classes/styles/vector/style_util.js b/x-pack/plugins/maps/public/classes/styles/vector/style_util.js
index 082056846843..3b62dcb27dce 100644
--- a/x-pack/plugins/maps/public/classes/styles/vector/style_util.js
+++ b/x-pack/plugins/maps/public/classes/styles/vector/style_util.js
@@ -34,6 +34,21 @@ export function isOnlySingleFeatureType(featureType, supportedFeatures, hasFeatu
}, true);
}
+export function dynamicRound(value) {
+ if (typeof value !== 'number') {
+ return value;
+ }
+
+ let precision = 0;
+ let threshold = 10;
+ while (value < threshold && precision < 8) {
+ precision++;
+ threshold = threshold / 10;
+ }
+
+ return precision === 0 ? Math.round(value) : parseFloat(value.toFixed(precision + 1));
+}
+
export function assignCategoriesToPalette({ categories, paletteValues }) {
const stops = [];
let fallback = null;
diff --git a/x-pack/plugins/maps/public/classes/styles/vector/style_util.test.js b/x-pack/plugins/maps/public/classes/styles/vector/style_util.test.js
index 76bbfc84e389..eb4c6708fb2d 100644
--- a/x-pack/plugins/maps/public/classes/styles/vector/style_util.test.js
+++ b/x-pack/plugins/maps/public/classes/styles/vector/style_util.test.js
@@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { isOnlySingleFeatureType, assignCategoriesToPalette } from './style_util';
+import { isOnlySingleFeatureType, assignCategoriesToPalette, dynamicRound } from './style_util';
import { VECTOR_SHAPE_TYPES } from '../../sources/vector_feature_types';
describe('isOnlySingleFeatureType', () => {
@@ -100,3 +100,15 @@ describe('assignCategoriesToPalette', () => {
});
});
});
+
+describe('dynamicRound', () => {
+ test('Should truncate based on magnitude of number', () => {
+ expect(dynamicRound(1000.1234)).toBe(1000);
+ expect(dynamicRound(1.1234)).toBe(1.12);
+ expect(dynamicRound(0.0012345678)).toBe(0.00123);
+ });
+
+ test('Should return argument when not a number', () => {
+ expect(dynamicRound('foobar')).toBe('foobar');
+ });
+});
diff --git a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.d.ts b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.d.ts
index beea94394399..ea0736c4837d 100644
--- a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.d.ts
+++ b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.d.ts
@@ -12,11 +12,13 @@ import {
VectorStyleDescriptor,
VectorStylePropertiesDescriptor,
} from '../../../../common/descriptor_types';
+import { StyleMeta } from './style_meta';
export interface IVectorStyle extends IStyle {
getAllStyleProperties(): IStyleProperty[];
getDynamicPropertiesArray(): IDynamicStyleProperty[];
getSourceFieldNames(): string[];
+ getStyleMeta(): StyleMeta;
}
export class VectorStyle extends AbstractStyle implements IVectorStyle {
@@ -26,4 +28,5 @@ export class VectorStyle extends AbstractStyle implements IVectorStyle {
getSourceFieldNames(): string[];
getAllStyleProperties(): IStyleProperty[];
getDynamicPropertiesArray(): IDynamicStyleProperty[];
+ getStyleMeta(): StyleMeta;
}
diff --git a/x-pack/test/functional/apps/maps/joins.js b/x-pack/test/functional/apps/maps/joins.js
index 2bf52153b7a3..7534a1b09cc2 100644
--- a/x-pack/test/functional/apps/maps/joins.js
+++ b/x-pack/test/functional/apps/maps/joins.js
@@ -58,11 +58,18 @@ export default function ({ getPageObjects, getService }) {
const layerTOCDetails = await PageObjects.maps.getLayerTOCDetails('geo_shapes*');
const split = layerTOCDetails.trim().split('\n');
- const min = split[0];
- expect(min).to.equal('3');
+ //field display name
+ expect(split[0]).to.equal('max prop1');
- const max = split[2];
- expect(max).to.equal('12');
+ //bands 1-8
+ expect(split[1]).to.equal('3');
+ expect(split[2]).to.equal('4.13');
+ expect(split[3]).to.equal('5.25');
+ expect(split[4]).to.equal('6.38');
+ expect(split[5]).to.equal('7.5');
+ expect(split[6]).to.equal('8.63');
+ expect(split[7]).to.equal('9.75');
+ expect(split[8]).to.equal('11');
});
it('should decorate feature properties with join property', async () => {
@@ -164,10 +171,10 @@ export default function ({ getPageObjects, getService }) {
const split = layerTOCDetails.trim().split('\n');
const min = split[0];
- expect(min).to.equal('12');
+ expect(min).to.equal('max prop1');
- const max = split[2];
- expect(max).to.equal('12');
+ const max = split[1];
+ expect(max).to.equal('12'); // just single band because single value
});
it('should flag only the joined features as visible', async () => {