[Maps] show custom color ramps in legend (#53780)
This commit is contained in:
parent
58da936968
commit
c19151d474
|
@ -113,7 +113,7 @@ export const ColorStops = ({ colorStops = [{ stop: 0, color: DEFAULT_COLOR }], o
|
|||
display="rowCompressed"
|
||||
>
|
||||
<div>
|
||||
<EuiFlexGroup responsive={false} alignItems="center" gutterSize="s">
|
||||
<EuiFlexGroup responsive={false} alignItems="center" gutterSize="xs">
|
||||
<EuiFlexItem>{stopInput}</EuiFlexItem>
|
||||
<EuiFlexItem>{colorInput}</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* 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 { VectorStyle } from '../../vector_style';
|
||||
import { getColorRampCenterColor } from '../../../color_utils';
|
||||
|
||||
export function extractColorFromStyleProperty(colorStyleProperty, defaultColor) {
|
||||
if (!colorStyleProperty) {
|
||||
return defaultColor;
|
||||
}
|
||||
|
||||
if (colorStyleProperty.type === VectorStyle.STYLE_TYPE.STATIC) {
|
||||
return colorStyleProperty.options.color;
|
||||
}
|
||||
|
||||
// Do not use dynamic color unless configuration is complete
|
||||
if (!colorStyleProperty.options.field || !colorStyleProperty.options.field.name) {
|
||||
return defaultColor;
|
||||
}
|
||||
|
||||
// return middle of gradient for dynamic style property
|
||||
|
||||
if (colorStyleProperty.options.useCustomColorRamp) {
|
||||
if (
|
||||
!colorStyleProperty.options.customColorRamp ||
|
||||
!colorStyleProperty.options.customColorRamp.length
|
||||
) {
|
||||
return defaultColor;
|
||||
}
|
||||
// favor the lowest color in even arrays
|
||||
const middleIndex = Math.floor((colorStyleProperty.options.customColorRamp.length - 1) / 2);
|
||||
return colorStyleProperty.options.customColorRamp[middleIndex].color;
|
||||
}
|
||||
|
||||
return getColorRampCenterColor(colorStyleProperty.options.color);
|
||||
}
|
|
@ -7,13 +7,11 @@
|
|||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { dynamicColorShape, staticColorShape } from '../style_option_shapes';
|
||||
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 { VECTOR_STYLES } from '../../vector_style_defaults';
|
||||
|
||||
export class VectorIcon extends Component {
|
||||
state = {
|
||||
|
@ -48,16 +46,16 @@ export class VectorIcon extends Component {
|
|||
|
||||
if (this.state.isLinesOnly) {
|
||||
const style = {
|
||||
stroke: extractColorFromStyleProperty(this.props.lineColor, 'grey'),
|
||||
stroke: this.props.getColorForProperty(VECTOR_STYLES.LINE_COLOR, true),
|
||||
strokeWidth: '4px',
|
||||
};
|
||||
return <LineIcon style={style} />;
|
||||
}
|
||||
|
||||
const style = {
|
||||
stroke: extractColorFromStyleProperty(this.props.lineColor, 'none'),
|
||||
stroke: this.props.getColorForProperty(VECTOR_STYLES.LINE_COLOR, false),
|
||||
strokeWidth: '1px',
|
||||
fill: extractColorFromStyleProperty(this.props.fillColor, 'grey'),
|
||||
fill: this.props.getColorForProperty(VECTOR_STYLES.FILL_COLOR, false),
|
||||
};
|
||||
|
||||
if (!this.state.isPointsOnly) {
|
||||
|
@ -79,45 +77,8 @@ export class VectorIcon extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
function extractColorFromStyleProperty(colorStyleProperty, defaultColor) {
|
||||
if (!colorStyleProperty) {
|
||||
return defaultColor;
|
||||
}
|
||||
|
||||
if (colorStyleProperty.type === VectorStyle.STYLE_TYPE.STATIC) {
|
||||
return colorStyleProperty.options.color;
|
||||
}
|
||||
|
||||
// Do not use dynamic color unless configuration is complete
|
||||
if (!colorStyleProperty.options.field || !colorStyleProperty.options.field.name) {
|
||||
return defaultColor;
|
||||
}
|
||||
|
||||
// return middle of gradient for dynamic style property
|
||||
|
||||
if (colorStyleProperty.options.useCustomColorRamp) {
|
||||
if (
|
||||
!colorStyleProperty.options.customColorRamp ||
|
||||
!colorStyleProperty.options.customColorRamp.length
|
||||
) {
|
||||
return defaultColor;
|
||||
}
|
||||
// favor the lowest color in even arrays
|
||||
const middleIndex = Math.floor((colorStyleProperty.options.customColorRamp.length - 1) / 2);
|
||||
return colorStyleProperty.options.customColorRamp[middleIndex].color;
|
||||
}
|
||||
|
||||
return getColorRampCenterColor(colorStyleProperty.options.color);
|
||||
}
|
||||
|
||||
const colorStylePropertyShape = PropTypes.shape({
|
||||
type: PropTypes.string.isRequired,
|
||||
options: PropTypes.oneOfType([dynamicColorShape, staticColorShape]).isRequired,
|
||||
});
|
||||
|
||||
VectorIcon.propTypes = {
|
||||
fillColor: colorStylePropertyShape,
|
||||
lineColor: colorStylePropertyShape,
|
||||
getColorForProperty: PropTypes.func.isRequired,
|
||||
symbolId: PropTypes.string,
|
||||
loadIsPointsOnly: PropTypes.func.isRequired,
|
||||
loadIsLinesOnly: PropTypes.func.isRequired,
|
||||
|
|
|
@ -9,16 +9,12 @@ import { shallow } from 'enzyme';
|
|||
|
||||
import { VectorIcon } from './vector_icon';
|
||||
import { VectorStyle } from '../../vector_style';
|
||||
import { extractColorFromStyleProperty } from './extract_color_from_style_property';
|
||||
import { VECTOR_STYLES } from '../../vector_style_defaults';
|
||||
|
||||
let isPointsOnly = false;
|
||||
let isLinesOnly = false;
|
||||
const defaultProps = {
|
||||
loadIsPointsOnly: () => {
|
||||
return isPointsOnly;
|
||||
},
|
||||
loadIsLinesOnly: () => {
|
||||
return isLinesOnly;
|
||||
},
|
||||
const styles = {
|
||||
fillColor: {
|
||||
type: VectorStyle.STYLE_TYPE.STATIC,
|
||||
options: {
|
||||
|
@ -36,6 +32,30 @@ const defaultProps = {
|
|||
},
|
||||
};
|
||||
|
||||
const defaultProps = {
|
||||
getColorForProperty: (styleProperty, isLinesOnly) => {
|
||||
if (isLinesOnly) {
|
||||
return extractColorFromStyleProperty(styles[VECTOR_STYLES.LINE_COLOR], 'grey');
|
||||
}
|
||||
|
||||
if (styleProperty === VECTOR_STYLES.LINE_COLOR) {
|
||||
return extractColorFromStyleProperty(styles[VECTOR_STYLES.LINE_COLOR], 'none');
|
||||
} else if (styleProperty === VECTOR_STYLES.FILL_COLOR) {
|
||||
return extractColorFromStyleProperty(styles[VECTOR_STYLES.FILL_COLOR], 'grey');
|
||||
} else {
|
||||
//unexpected
|
||||
console.error('Cannot return color for properties other then line or fill color');
|
||||
}
|
||||
},
|
||||
|
||||
loadIsPointsOnly: () => {
|
||||
return isPointsOnly;
|
||||
},
|
||||
loadIsLinesOnly: () => {
|
||||
return isLinesOnly;
|
||||
},
|
||||
};
|
||||
|
||||
function configureIsLinesOnly() {
|
||||
isLinesOnly = true;
|
||||
isPointsOnly = false;
|
||||
|
|
|
@ -46,7 +46,15 @@ export class VectorStyleLegend extends Component {
|
|||
|
||||
render() {
|
||||
return this.state.styles.map(style => {
|
||||
return <Fragment key={style.getStyleName()}>{style.renderLegendDetailRow()}</Fragment>;
|
||||
return (
|
||||
<Fragment key={style.getStyleName()}>
|
||||
{style.renderLegendDetailRow({
|
||||
loadIsLinesOnly: this.props.loadIsLinesOnly,
|
||||
loadIsPointsOnly: this.props.loadIsPointsOnly,
|
||||
symbolId: this.props.symbolId,
|
||||
})}
|
||||
</Fragment>
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -111,7 +111,7 @@ export class StaticDynamicStyleRow extends Component {
|
|||
});
|
||||
|
||||
return (
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexGroup gutterSize="xs">
|
||||
<EuiFlexItem
|
||||
className={isDynamic ? 'mapStaticDynamicSylingOption__dynamicSizeHack' : undefined}
|
||||
>
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Should render categorical legend 1`] = `
|
||||
<div>
|
||||
<EuiSpacer
|
||||
size="s"
|
||||
/>
|
||||
<EuiFlexGroup
|
||||
direction="column"
|
||||
gutterSize="none"
|
||||
>
|
||||
<EuiFlexItem
|
||||
key="0"
|
||||
>
|
||||
<EuiFlexGroup
|
||||
direction="row"
|
||||
gutterSize="none"
|
||||
>
|
||||
<EuiFlexItem>
|
||||
<EuiText
|
||||
size="xs"
|
||||
>
|
||||
0_format
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<VectorIcon
|
||||
getColorForProperty={[Function]}
|
||||
loadIsLinesOnly={[Function]}
|
||||
loadIsPointsOnly={[Function]}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem
|
||||
key="1"
|
||||
>
|
||||
<EuiFlexGroup
|
||||
direction="row"
|
||||
gutterSize="none"
|
||||
>
|
||||
<EuiFlexItem>
|
||||
<EuiText
|
||||
size="xs"
|
||||
>
|
||||
10_format
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<VectorIcon
|
||||
getColorForProperty={[Function]}
|
||||
loadIsLinesOnly={[Function]}
|
||||
loadIsPointsOnly={[Function]}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<EuiFlexGroup
|
||||
gutterSize="xs"
|
||||
justifyContent="spaceAround"
|
||||
>
|
||||
<EuiFlexItem
|
||||
grow={false}
|
||||
>
|
||||
<EuiToolTip
|
||||
content="foobar_label"
|
||||
delay="regular"
|
||||
position="top"
|
||||
title="Border color"
|
||||
>
|
||||
<EuiText
|
||||
className="eui-textTruncate"
|
||||
size="xs"
|
||||
style={
|
||||
Object {
|
||||
"maxWidth": "180px",
|
||||
}
|
||||
}
|
||||
>
|
||||
<small>
|
||||
<strong>
|
||||
foobar_label
|
||||
</strong>
|
||||
</small>
|
||||
</EuiText>
|
||||
</EuiToolTip>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Should render ranged legend 1`] = `
|
||||
<RangedStyleLegendRow
|
||||
fieldLabel="foobar_label"
|
||||
header={
|
||||
<ColorGradient
|
||||
colorRampName="Blues"
|
||||
/>
|
||||
}
|
||||
maxLabel="100_format"
|
||||
minLabel="0_format"
|
||||
propertyLabel="Border color"
|
||||
/>
|
||||
`;
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* 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 {
|
||||
constructor() {
|
||||
super();
|
||||
this._isMounted = false;
|
||||
this.state = {
|
||||
label: EMPTY_VALUE,
|
||||
isPointsOnly: null,
|
||||
isLinesOnly: null,
|
||||
};
|
||||
}
|
||||
|
||||
async _loadParams() {
|
||||
const label = await this.props.style.getField().getLabel();
|
||||
const isLinesOnly = await this.props.loadIsLinesOnly();
|
||||
const isPointsOnly = await this.props.loadIsPointsOnly();
|
||||
const newState = { label, isLinesOnly, isPointsOnly };
|
||||
if (this._isMounted && !_.isEqual(this.state, newState)) {
|
||||
this.setState(newState);
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this._loadParams();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this._isMounted = false;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this._isMounted = true;
|
||||
this._loadParams();
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.label === EMPTY_VALUE) {
|
||||
return null;
|
||||
}
|
||||
return this.props.style.renderBreakedLegend({
|
||||
fieldLabel: this.state.label,
|
||||
isLinesOnly: this.state.isLinesOnly,
|
||||
isPointsOnly: this.state.isPointsOnly,
|
||||
symbolId: this.props.symbolId,
|
||||
});
|
||||
}
|
||||
}
|
|
@ -7,11 +7,9 @@
|
|||
import React from 'react';
|
||||
import _ from 'lodash';
|
||||
import { RangedStyleLegendRow } from '../../../components/ranged_style_legend_row';
|
||||
import { getVectorStyleLabel } from '../../components/get_vector_style_label';
|
||||
|
||||
const EMPTY_VALUE = '';
|
||||
|
||||
export class DynamicLegendRow extends React.Component {
|
||||
export class OrdinalLegend extends React.Component {
|
||||
constructor() {
|
||||
super();
|
||||
this._isMounted = false;
|
||||
|
@ -28,6 +26,13 @@ export class DynamicLegendRow extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
_formatValue(value) {
|
||||
if (value === EMPTY_VALUE) {
|
||||
return value;
|
||||
}
|
||||
return this.props.style.formatField(value);
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this._loadParams();
|
||||
}
|
||||
|
@ -40,14 +45,6 @@ export class DynamicLegendRow extends React.Component {
|
|||
this._isMounted = true;
|
||||
this._loadParams();
|
||||
}
|
||||
|
||||
_formatValue(value) {
|
||||
if (value === EMPTY_VALUE) {
|
||||
return value;
|
||||
}
|
||||
return this.props.style.formatField(value);
|
||||
}
|
||||
|
||||
render() {
|
||||
const fieldMeta = this.props.style.getFieldMeta();
|
||||
|
||||
|
@ -70,10 +67,10 @@ export class DynamicLegendRow extends React.Component {
|
|||
|
||||
return (
|
||||
<RangedStyleLegendRow
|
||||
header={this.props.style.renderLegendHeader()}
|
||||
header={this.props.style.renderRangeLegendHeader()}
|
||||
minLabel={minLabel}
|
||||
maxLabel={maxLabel}
|
||||
propertyLabel={getVectorStyleLabel(this.props.style.getStyleName())}
|
||||
propertyLabel={this.props.style.getDisplayStyleName()}
|
||||
fieldLabel={this.state.label}
|
||||
/>
|
||||
);
|
|
@ -10,6 +10,9 @@ import { getComputedFieldName } from '../style_util';
|
|||
import { getColorRampStops } from '../../color_utils';
|
||||
import { ColorGradient } from '../../components/color_gradient';
|
||||
import React from 'react';
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText, EuiToolTip } from '@elastic/eui';
|
||||
import { VectorIcon } from '../components/legend/vector_icon';
|
||||
import { VECTOR_STYLES } from '../vector_style_defaults';
|
||||
|
||||
export class DynamicColorProperty extends DynamicStyleProperty {
|
||||
syncCircleColorWithMb(mbLayerId, mbMap, alpha) {
|
||||
|
@ -64,6 +67,14 @@ export class DynamicColorProperty extends DynamicStyleProperty {
|
|||
return !this.isCustomColorRamp();
|
||||
}
|
||||
|
||||
isRanged() {
|
||||
return !this.isCustomColorRamp();
|
||||
}
|
||||
|
||||
hasBreaks() {
|
||||
return this.isCustomColorRamp();
|
||||
}
|
||||
|
||||
_getMbColor() {
|
||||
const isDynamicConfigComplete =
|
||||
_.has(this._options, 'field.name') && _.has(this._options, 'color');
|
||||
|
@ -117,11 +128,95 @@ export class DynamicColorProperty extends DynamicStyleProperty {
|
|||
return getColorRampStops(this._options.color);
|
||||
}
|
||||
|
||||
renderLegendHeader() {
|
||||
renderRangeLegendHeader() {
|
||||
if (this._options.color) {
|
||||
return <ColorGradient colorRampName={this._options.color} />;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
_renderStopIcon(color, isLinesOnly, isPointsOnly, symbolId) {
|
||||
if (this.getStyleName() === VECTOR_STYLES.LABEL_COLOR) {
|
||||
const style = { color: color };
|
||||
return (
|
||||
<EuiText size={'xs'} style={style}>
|
||||
Tx
|
||||
</EuiText>
|
||||
);
|
||||
}
|
||||
|
||||
const loadIsLinesOnly = () => {
|
||||
return isLinesOnly;
|
||||
};
|
||||
|
||||
const loadIsPointsOnly = () => {
|
||||
return isPointsOnly;
|
||||
};
|
||||
|
||||
const getColorForProperty = (styleProperty, isLinesOnly) => {
|
||||
if (isLinesOnly) {
|
||||
return color;
|
||||
}
|
||||
|
||||
return this.getStyleName() === styleProperty ? color : 'none';
|
||||
};
|
||||
|
||||
return (
|
||||
<VectorIcon
|
||||
symbolId={symbolId}
|
||||
loadIsPointsOnly={loadIsPointsOnly}
|
||||
loadIsLinesOnly={loadIsLinesOnly}
|
||||
getColorForProperty={getColorForProperty}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
_renderColorbreaks({ isLinesOnly, isPointsOnly, symbolId }) {
|
||||
if (!this._options.customColorRamp) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this._options.customColorRamp.map((config, index) => {
|
||||
const value = this.formatField(config.stop);
|
||||
return (
|
||||
<EuiFlexItem key={index}>
|
||||
<EuiFlexGroup direction={'row'} gutterSize={'none'}>
|
||||
<EuiFlexItem>
|
||||
<EuiText size={'xs'}>{value}</EuiText>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
{this._renderStopIcon(config.color, isLinesOnly, isPointsOnly, symbolId)}
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiFlexItem>
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
renderBreakedLegend({ fieldLabel, isPointsOnly, isLinesOnly, symbolId }) {
|
||||
return (
|
||||
<div>
|
||||
<EuiSpacer size="s" />
|
||||
<EuiFlexGroup direction={'column'} gutterSize={'none'}>
|
||||
{this._renderColorbreaks({
|
||||
isPointsOnly,
|
||||
isLinesOnly,
|
||||
symbolId,
|
||||
})}
|
||||
</EuiFlexGroup>
|
||||
<EuiFlexGroup gutterSize="xs" justifyContent="spaceAround">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiToolTip position="top" title={this.getDisplayStyleName()} content={fieldLabel}>
|
||||
<EuiText className="eui-textTruncate" size="xs" style={{ maxWidth: '180px' }}>
|
||||
<small>
|
||||
<strong>{fieldLabel}</strong>
|
||||
</small>
|
||||
</EuiText>
|
||||
</EuiToolTip>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import { VECTOR_STYLES } from '../vector_style_defaults';
|
||||
import { DynamicColorProperty } from './dynamic_color_property';
|
||||
|
||||
const mockField = {
|
||||
async getLabel() {
|
||||
return 'foobar_label';
|
||||
},
|
||||
|
||||
getName() {
|
||||
return 'foobar';
|
||||
},
|
||||
supportsFieldMeta() {
|
||||
return true;
|
||||
},
|
||||
};
|
||||
|
||||
test('Should render ranged legend', async () => {
|
||||
const colorStyle = new DynamicColorProperty(
|
||||
{
|
||||
color: 'Blues',
|
||||
},
|
||||
VECTOR_STYLES.LINE_COLOR,
|
||||
mockField,
|
||||
() => {
|
||||
return { min: 0, max: 100 };
|
||||
},
|
||||
() => {
|
||||
return x => x + '_format';
|
||||
}
|
||||
);
|
||||
|
||||
const legendRow = colorStyle.renderLegendDetailRow({
|
||||
loadIsPointsOnly: () => {
|
||||
return true;
|
||||
},
|
||||
loadIsLinesOnly: () => {
|
||||
return false;
|
||||
},
|
||||
});
|
||||
|
||||
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', async () => {
|
||||
const colorStyle = new DynamicColorProperty(
|
||||
{
|
||||
useCustomColorRamp: true,
|
||||
customColorRamp: [
|
||||
{
|
||||
stop: 0,
|
||||
color: '#FF0000',
|
||||
},
|
||||
{
|
||||
stop: 10,
|
||||
color: '#00FF00',
|
||||
},
|
||||
],
|
||||
},
|
||||
VECTOR_STYLES.LINE_COLOR,
|
||||
mockField,
|
||||
() => {
|
||||
return { min: 0, max: 100 };
|
||||
},
|
||||
() => {
|
||||
return x => x + '_format';
|
||||
}
|
||||
);
|
||||
|
||||
const legendRow = colorStyle.renderLegendDetailRow({
|
||||
loadIsPointsOnly: () => {
|
||||
return true;
|
||||
},
|
||||
loadIsLinesOnly: () => {
|
||||
return false;
|
||||
},
|
||||
});
|
||||
|
||||
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();
|
||||
});
|
|
@ -146,7 +146,7 @@ export class DynamicSizeProperty extends DynamicStyleProperty {
|
|||
);
|
||||
}
|
||||
|
||||
renderLegendHeader() {
|
||||
renderRangeLegendHeader() {
|
||||
let icons;
|
||||
if (this.getStyleName() === VECTOR_STYLES.LINE_WIDTH) {
|
||||
icons = getLineWidthIcons();
|
||||
|
@ -157,7 +157,7 @@ export class DynamicSizeProperty extends DynamicStyleProperty {
|
|||
}
|
||||
|
||||
return (
|
||||
<EuiFlexGroup gutterSize="s" justifyContent="spaceBetween" alignItems="center">
|
||||
<EuiFlexGroup gutterSize="xs" justifyContent="spaceBetween" alignItems="center">
|
||||
{icons.map((icon, index) => {
|
||||
const isLast = index === icons.length - 1;
|
||||
let spacer;
|
||||
|
|
|
@ -8,9 +8,10 @@ import _ from 'lodash';
|
|||
import { AbstractStyleProperty } from './style_property';
|
||||
import { DEFAULT_SIGMA } from '../vector_style_defaults';
|
||||
import { STYLE_TYPE } from '../../../../../common/constants';
|
||||
import { DynamicLegendRow } from './components/dynamic_legend_row';
|
||||
import { scaleValue } from '../style_util';
|
||||
import React from 'react';
|
||||
import { OrdinalLegend } from './components/ordinal_legend';
|
||||
import { CategoricalLegend } from './components/categorical_legend';
|
||||
|
||||
export class DynamicStyleProperty extends AbstractStyleProperty {
|
||||
static type = STYLE_TYPE.DYNAMIC;
|
||||
|
@ -38,6 +39,14 @@ export class DynamicStyleProperty extends AbstractStyleProperty {
|
|||
return true;
|
||||
}
|
||||
|
||||
hasBreaks() {
|
||||
return false;
|
||||
}
|
||||
|
||||
isRanged() {
|
||||
return true;
|
||||
}
|
||||
|
||||
isComplete() {
|
||||
return !!this._field;
|
||||
}
|
||||
|
@ -75,6 +84,10 @@ export class DynamicStyleProperty extends AbstractStyleProperty {
|
|||
}
|
||||
|
||||
pluckStyleMetaFromFeatures(features) {
|
||||
if (!this.isOrdinal()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const name = this.getField().getName();
|
||||
let min = Infinity;
|
||||
let max = -Infinity;
|
||||
|
@ -97,6 +110,10 @@ export class DynamicStyleProperty extends AbstractStyleProperty {
|
|||
}
|
||||
|
||||
pluckStyleMetaFromFieldMetaData(fieldMetaData) {
|
||||
if (!this.isOrdinal()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const realFieldName = this._field.getESDocFieldName
|
||||
? this._field.getESDocFieldName()
|
||||
: this._field.getName();
|
||||
|
@ -120,13 +137,13 @@ export class DynamicStyleProperty extends AbstractStyleProperty {
|
|||
}
|
||||
|
||||
formatField(value) {
|
||||
if (!this.getField()) {
|
||||
if (this.getField()) {
|
||||
const fieldName = this.getField().getName();
|
||||
const fieldFormatter = this._getFieldFormatter(fieldName);
|
||||
return fieldFormatter ? fieldFormatter(value) : value;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
|
||||
const fieldName = this.getField().getName();
|
||||
const fieldFormatter = this._getFieldFormatter(fieldName);
|
||||
return fieldFormatter ? fieldFormatter(value) : value;
|
||||
}
|
||||
|
||||
getMbValue(value) {
|
||||
|
@ -144,7 +161,32 @@ export class DynamicStyleProperty extends AbstractStyleProperty {
|
|||
return valueAsFloat;
|
||||
}
|
||||
|
||||
renderLegendDetailRow() {
|
||||
return <DynamicLegendRow style={this} />;
|
||||
renderBreakedLegend() {
|
||||
return null;
|
||||
}
|
||||
|
||||
_renderCategoricalLegend({ loadIsPointsOnly, loadIsLinesOnly, symbolId }) {
|
||||
return (
|
||||
<CategoricalLegend
|
||||
style={this}
|
||||
loadIsLinesOnly={loadIsLinesOnly}
|
||||
loadIsPointsOnly={loadIsPointsOnly}
|
||||
symbolId={symbolId}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
_renderRangeLegend() {
|
||||
return <OrdinalLegend style={this} />;
|
||||
}
|
||||
|
||||
renderLegendDetailRow({ loadIsPointsOnly, loadIsLinesOnly, symbolId }) {
|
||||
if (this.isRanged()) {
|
||||
return this._renderRangeLegend();
|
||||
} else if (this.hasBreaks()) {
|
||||
return this._renderCategoricalLegend({ loadIsPointsOnly, loadIsLinesOnly, symbolId });
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,8 +32,4 @@ export class DynamicTextProperty extends DynamicStyleProperty {
|
|||
isScaled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
renderHeader() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { getVectorStyleLabel } from '../components/get_vector_style_label';
|
||||
export class AbstractStyleProperty {
|
||||
constructor(options, styleName) {
|
||||
this._options = options;
|
||||
|
@ -36,11 +37,15 @@ export class AbstractStyleProperty {
|
|||
return this._options || {};
|
||||
}
|
||||
|
||||
renderLegendHeader() {
|
||||
renderRangeLegendHeader() {
|
||||
return null;
|
||||
}
|
||||
|
||||
renderLegendDetailRow() {
|
||||
return null;
|
||||
}
|
||||
|
||||
getDisplayStyleName() {
|
||||
return getVectorStyleLabel(this.getStyleName());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ import { StaticOrientationProperty } from './properties/static_orientation_prope
|
|||
import { DynamicOrientationProperty } from './properties/dynamic_orientation_property';
|
||||
import { StaticTextProperty } from './properties/static_text_property';
|
||||
import { DynamicTextProperty } from './properties/dynamic_text_property';
|
||||
import { extractColorFromStyleProperty } from './components/legend/extract_color_from_style_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];
|
||||
|
@ -386,18 +387,37 @@ export class VectorStyle extends AbstractStyle {
|
|||
return _.get(this._descriptor, '__styleMeta', {});
|
||||
};
|
||||
|
||||
getIcon = () => {
|
||||
const styles = this.getRawProperties();
|
||||
const symbolId = this.arePointsSymbolizedAsCircles()
|
||||
_getSymbolId() {
|
||||
return this.arePointsSymbolizedAsCircles()
|
||||
? undefined
|
||||
: this._descriptor.properties.symbol.options.symbolId;
|
||||
}
|
||||
|
||||
_getColorForProperty = (styleProperty, isLinesOnly) => {
|
||||
const styles = this.getRawProperties();
|
||||
if (isLinesOnly) {
|
||||
return extractColorFromStyleProperty(styles[VECTOR_STYLES.LINE_COLOR], 'grey');
|
||||
}
|
||||
|
||||
if (styleProperty === VECTOR_STYLES.LINE_COLOR) {
|
||||
return extractColorFromStyleProperty(styles[VECTOR_STYLES.LINE_COLOR], 'none');
|
||||
} else if (styleProperty === VECTOR_STYLES.FILL_COLOR) {
|
||||
return extractColorFromStyleProperty(styles[VECTOR_STYLES.FILL_COLOR], 'grey');
|
||||
} else {
|
||||
//unexpected
|
||||
console.error('Cannot return color for properties other then line or fill color');
|
||||
}
|
||||
};
|
||||
|
||||
getIcon = () => {
|
||||
const symbolId = this._getSymbolId();
|
||||
|
||||
return (
|
||||
<VectorIcon
|
||||
loadIsPointsOnly={this._getIsPointsOnly}
|
||||
loadIsLinesOnly={this._getIsLinesOnly}
|
||||
fillColor={styles[VECTOR_STYLES.FILL_COLOR]}
|
||||
lineColor={styles[VECTOR_STYLES.LINE_COLOR]}
|
||||
symbolId={symbolId}
|
||||
getColorForProperty={this._getColorForProperty}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
@ -431,7 +451,12 @@ export class VectorStyle extends AbstractStyle {
|
|||
|
||||
renderLegendDetails() {
|
||||
return (
|
||||
<VectorStyleLegend getLegendDetailStyleProperties={this._getLegendDetailStyleProperties} />
|
||||
<VectorStyleLegend
|
||||
getLegendDetailStyleProperties={this._getLegendDetailStyleProperties}
|
||||
loadIsPointsOnly={this._getIsPointsOnly}
|
||||
loadIsLinesOnly={this._getIsLinesOnly}
|
||||
symbolId={this._getSymbolId()}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue