[Maps] refactor isPointsOnly, isLinesOnly, and isPolygonsOnly to make synchronous (#54067)
* [Maps] refactor isPointsOnly, isLinesOnly, and isPolygonsOnly to make synchronous * fix jest test * review feedback Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
parent
e7472e2f00
commit
14df4c096c
|
@ -1,6 +1,6 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Renders CircleIcon with correct styles when isPointOnly 1`] = `
|
||||
exports[`Renders CircleIcon 1`] = `
|
||||
<CircleIcon
|
||||
style={
|
||||
Object {
|
||||
|
@ -12,7 +12,7 @@ exports[`Renders CircleIcon with correct styles when isPointOnly 1`] = `
|
|||
/>
|
||||
`;
|
||||
|
||||
exports[`Renders LineIcon with correct styles when isLineOnly 1`] = `
|
||||
exports[`Renders LineIcon 1`] = `
|
||||
<LineIcon
|
||||
style={
|
||||
Object {
|
||||
|
@ -23,7 +23,7 @@ exports[`Renders LineIcon with correct styles when isLineOnly 1`] = `
|
|||
/>
|
||||
`;
|
||||
|
||||
exports[`Renders PolygonIcon with correct styles when not line only or not point only 1`] = `
|
||||
exports[`Renders PolygonIcon 1`] = `
|
||||
<PolygonIcon
|
||||
style={
|
||||
Object {
|
||||
|
@ -35,7 +35,7 @@ exports[`Renders PolygonIcon with correct styles when not line only or not point
|
|||
/>
|
||||
`;
|
||||
|
||||
exports[`Renders SymbolIcon with correct styles when isPointOnly and symbolId provided 1`] = `
|
||||
exports[`Renders SymbolIcon 1`] = `
|
||||
<SymbolIcon
|
||||
fill="#ff0000"
|
||||
stroke="rgb(106,173,213)"
|
||||
|
|
|
@ -4,82 +4,51 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { CircleIcon } from './circle_icon';
|
||||
import { LineIcon } from './line_icon';
|
||||
import { PolygonIcon } from './polygon_icon';
|
||||
import { SymbolIcon } from './symbol_icon';
|
||||
import { VECTOR_STYLES } from '../../vector_style_defaults';
|
||||
|
||||
export class VectorIcon extends Component {
|
||||
state = {
|
||||
isInitialized: false,
|
||||
export function VectorIcon({ fillColor, isPointsOnly, isLinesOnly, strokeColor, symbolId }) {
|
||||
if (isLinesOnly) {
|
||||
const style = {
|
||||
stroke: strokeColor,
|
||||
strokeWidth: '4px',
|
||||
};
|
||||
return <LineIcon style={style} />;
|
||||
}
|
||||
|
||||
const style = {
|
||||
stroke: strokeColor,
|
||||
strokeWidth: '1px',
|
||||
fill: fillColor,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this._isMounted = true;
|
||||
this._init();
|
||||
if (!isPointsOnly) {
|
||||
return <PolygonIcon style={style} />;
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this._isMounted = false;
|
||||
if (!symbolId) {
|
||||
return <CircleIcon style={style} />;
|
||||
}
|
||||
|
||||
async _init() {
|
||||
const isPointsOnly = await this.props.loadIsPointsOnly();
|
||||
const isLinesOnly = await this.props.loadIsLinesOnly();
|
||||
if (this._isMounted) {
|
||||
this.setState({
|
||||
isInitialized: true,
|
||||
isPointsOnly,
|
||||
isLinesOnly,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
if (!this.state.isInitialized) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (this.state.isLinesOnly) {
|
||||
const style = {
|
||||
stroke: this.props.getColorForProperty(VECTOR_STYLES.LINE_COLOR, true),
|
||||
strokeWidth: '4px',
|
||||
};
|
||||
return <LineIcon style={style} />;
|
||||
}
|
||||
|
||||
const style = {
|
||||
stroke: this.props.getColorForProperty(VECTOR_STYLES.LINE_COLOR, false),
|
||||
strokeWidth: '1px',
|
||||
fill: this.props.getColorForProperty(VECTOR_STYLES.FILL_COLOR, false),
|
||||
};
|
||||
|
||||
if (!this.state.isPointsOnly) {
|
||||
return <PolygonIcon style={style} />;
|
||||
}
|
||||
|
||||
if (!this.props.symbolId) {
|
||||
return <CircleIcon style={style} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<SymbolIcon
|
||||
symbolId={this.props.symbolId}
|
||||
fill={style.fill}
|
||||
stroke={style.stroke}
|
||||
strokeWidth={style.strokeWidth}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<SymbolIcon
|
||||
symbolId={symbolId}
|
||||
fill={style.fill}
|
||||
stroke={style.stroke}
|
||||
strokeWidth={style.strokeWidth}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
VectorIcon.propTypes = {
|
||||
getColorForProperty: PropTypes.func.isRequired,
|
||||
fillColor: PropTypes.string,
|
||||
isPointsOnly: PropTypes.bool.isRequired,
|
||||
isLinesOnly: PropTypes.bool.isRequired,
|
||||
strokeColor: PropTypes.string.isRequired,
|
||||
symbolId: PropTypes.string,
|
||||
loadIsPointsOnly: PropTypes.func.isRequired,
|
||||
loadIsLinesOnly: PropTypes.func.isRequired,
|
||||
};
|
||||
|
|
|
@ -8,113 +8,51 @@ import React from 'react';
|
|||
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 styles = {
|
||||
fillColor: {
|
||||
type: VectorStyle.STYLE_TYPE.STATIC,
|
||||
options: {
|
||||
color: '#ff0000',
|
||||
},
|
||||
},
|
||||
lineColor: {
|
||||
type: VectorStyle.STYLE_TYPE.DYNAMIC,
|
||||
options: {
|
||||
color: 'Blues',
|
||||
field: {
|
||||
name: 'prop1',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
function configureIsPointsOnly() {
|
||||
isLinesOnly = false;
|
||||
isPointsOnly = true;
|
||||
}
|
||||
|
||||
function configureNotLineOrPointOnly() {
|
||||
isLinesOnly = false;
|
||||
isPointsOnly = false;
|
||||
}
|
||||
|
||||
test('Renders PolygonIcon with correct styles when not line only or not point only', async () => {
|
||||
configureNotLineOrPointOnly();
|
||||
const component = shallow(<VectorIcon {...defaultProps} />);
|
||||
|
||||
// Ensure all promises resolve
|
||||
await new Promise(resolve => process.nextTick(resolve));
|
||||
// Ensure the state changes are reflected
|
||||
component.update();
|
||||
test('Renders PolygonIcon', () => {
|
||||
const component = shallow(
|
||||
<VectorIcon
|
||||
fillColor="#ff0000"
|
||||
isPointsOnly={false}
|
||||
isLinesOnly={false}
|
||||
strokeColor="rgb(106,173,213)"
|
||||
/>
|
||||
);
|
||||
|
||||
expect(component).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('Renders LineIcon with correct styles when isLineOnly', async () => {
|
||||
configureIsLinesOnly();
|
||||
const component = shallow(<VectorIcon {...defaultProps} />);
|
||||
|
||||
// Ensure all promises resolve
|
||||
await new Promise(resolve => process.nextTick(resolve));
|
||||
// Ensure the state changes are reflected
|
||||
component.update();
|
||||
test('Renders LineIcon', () => {
|
||||
const component = shallow(
|
||||
<VectorIcon isPointsOnly={false} isLinesOnly={true} strokeColor="rgb(106,173,213)" />
|
||||
);
|
||||
|
||||
expect(component).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('Renders CircleIcon with correct styles when isPointOnly', async () => {
|
||||
configureIsPointsOnly();
|
||||
const component = shallow(<VectorIcon {...defaultProps} />);
|
||||
|
||||
// Ensure all promises resolve
|
||||
await new Promise(resolve => process.nextTick(resolve));
|
||||
// Ensure the state changes are reflected
|
||||
component.update();
|
||||
test('Renders CircleIcon', () => {
|
||||
const component = shallow(
|
||||
<VectorIcon
|
||||
fillColor="#ff0000"
|
||||
isPointsOnly={true}
|
||||
isLinesOnly={false}
|
||||
strokeColor="rgb(106,173,213)"
|
||||
/>
|
||||
);
|
||||
|
||||
expect(component).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('Renders SymbolIcon with correct styles when isPointOnly and symbolId provided', async () => {
|
||||
configureIsPointsOnly();
|
||||
const component = shallow(<VectorIcon {...defaultProps} symbolId="airfield-15" />);
|
||||
|
||||
// Ensure all promises resolve
|
||||
await new Promise(resolve => process.nextTick(resolve));
|
||||
// Ensure the state changes are reflected
|
||||
component.update();
|
||||
test('Renders SymbolIcon', () => {
|
||||
const component = shallow(
|
||||
<VectorIcon
|
||||
fillColor="#ff0000"
|
||||
isPointsOnly={true}
|
||||
isLinesOnly={false}
|
||||
strokeColor="rgb(106,173,213)"
|
||||
symbolId="airfield-15"
|
||||
/>
|
||||
);
|
||||
|
||||
expect(component).toMatchSnapshot();
|
||||
});
|
||||
|
|
|
@ -4,57 +4,18 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import _ from 'lodash';
|
||||
import React, { Component, Fragment } from 'react';
|
||||
import React, { Fragment } from 'react';
|
||||
|
||||
export class VectorStyleLegend extends Component {
|
||||
state = {
|
||||
styles: [],
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this._isMounted = true;
|
||||
this._prevStyleDescriptors = undefined;
|
||||
this._loadRows();
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this._loadRows();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this._isMounted = false;
|
||||
}
|
||||
|
||||
_loadRows = _.debounce(async () => {
|
||||
const styles = await this.props.getLegendDetailStyleProperties();
|
||||
const styleDescriptorPromises = styles.map(async style => {
|
||||
return {
|
||||
type: style.getStyleName(),
|
||||
options: style.getOptions(),
|
||||
fieldMeta: style.getFieldMeta(),
|
||||
label: await style.getField().getLabel(),
|
||||
};
|
||||
});
|
||||
|
||||
const styleDescriptors = await Promise.all(styleDescriptorPromises);
|
||||
if (this._isMounted && !_.isEqual(styleDescriptors, this._prevStyleDescriptors)) {
|
||||
this._prevStyleDescriptors = styleDescriptors;
|
||||
this.setState({ styles: styles });
|
||||
}
|
||||
}, 100);
|
||||
|
||||
render() {
|
||||
return this.state.styles.map(style => {
|
||||
return (
|
||||
<Fragment key={style.getStyleName()}>
|
||||
{style.renderLegendDetailRow({
|
||||
loadIsLinesOnly: this.props.loadIsLinesOnly,
|
||||
loadIsPointsOnly: this.props.loadIsPointsOnly,
|
||||
symbolId: this.props.symbolId,
|
||||
})}
|
||||
</Fragment>
|
||||
);
|
||||
});
|
||||
}
|
||||
export function VectorStyleLegend({ isLinesOnly, isPointsOnly, styles, symbolId }) {
|
||||
return styles.map(style => {
|
||||
return (
|
||||
<Fragment key={style.getStyleName()}>
|
||||
{style.renderLegendDetailRow({
|
||||
isLinesOnly,
|
||||
isPointsOnly,
|
||||
symbolId,
|
||||
})}
|
||||
</Fragment>
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -86,25 +86,14 @@ export class VectorStyleEditor extends Component {
|
|||
|
||||
async _loadSupportedFeatures() {
|
||||
const supportedFeatures = await this.props.layer.getSource().getSupportedShapeTypes();
|
||||
const isPointsOnly = await this.props.loadIsPointsOnly();
|
||||
const isLinesOnly = await this.props.loadIsLinesOnly();
|
||||
|
||||
if (!this._isMounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
_.isEqual(supportedFeatures, this.state.supportedFeatures) &&
|
||||
isPointsOnly === this.state.isPointsOnly &&
|
||||
isLinesOnly === this.state.isLinesOnly
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
let selectedFeature = VECTOR_SHAPE_TYPES.POLYGON;
|
||||
if (isPointsOnly) {
|
||||
if (this.props.isPointsOnly) {
|
||||
selectedFeature = VECTOR_SHAPE_TYPES.POINT;
|
||||
} else if (isLinesOnly) {
|
||||
} else if (this.props.isLinesOnly) {
|
||||
selectedFeature = VECTOR_SHAPE_TYPES.LINE;
|
||||
}
|
||||
|
||||
|
@ -112,12 +101,7 @@ export class VectorStyleEditor extends Component {
|
|||
!_.isEqual(supportedFeatures, this.state.supportedFeatures) ||
|
||||
selectedFeature !== this.state.selectedFeature
|
||||
) {
|
||||
this.setState({
|
||||
supportedFeatures,
|
||||
selectedFeature,
|
||||
isPointsOnly,
|
||||
isLinesOnly,
|
||||
});
|
||||
this.setState({ supportedFeatures, selectedFeature });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,98 +1,10 @@
|
|||
// 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 categorical legend 1`] = `""`;
|
||||
|
||||
exports[`Should render ranged legend 1`] = `
|
||||
<RangedStyleLegendRow
|
||||
fieldLabel="foobar_label"
|
||||
fieldLabel=""
|
||||
header={
|
||||
<ColorGradient
|
||||
colorRampName="Blues"
|
||||
|
|
|
@ -9,24 +9,13 @@ 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,
|
||||
};
|
||||
}
|
||||
state = {
|
||||
label: EMPTY_VALUE,
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
componentDidMount() {
|
||||
this._isMounted = true;
|
||||
this._loadParams();
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
|
@ -37,9 +26,12 @@ export class CategoricalLegend extends React.Component {
|
|||
this._isMounted = false;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this._isMounted = true;
|
||||
this._loadParams();
|
||||
async _loadParams() {
|
||||
const label = await this.props.style.getField().getLabel();
|
||||
const newState = { label };
|
||||
if (this._isMounted && !_.isEqual(this.state, newState)) {
|
||||
this.setState(newState);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -48,8 +40,8 @@ export class CategoricalLegend extends React.Component {
|
|||
}
|
||||
return this.props.style.renderBreakedLegend({
|
||||
fieldLabel: this.state.label,
|
||||
isLinesOnly: this.state.isLinesOnly,
|
||||
isPointsOnly: this.state.isPointsOnly,
|
||||
isLinesOnly: this.props.isLinesOnly,
|
||||
isPointsOnly: this.props.isPointsOnly,
|
||||
symbolId: this.props.symbolId,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -146,28 +146,14 @@ export class DynamicColorProperty extends DynamicStyleProperty {
|
|||
);
|
||||
}
|
||||
|
||||
const loadIsLinesOnly = () => {
|
||||
return isLinesOnly;
|
||||
};
|
||||
|
||||
const loadIsPointsOnly = () => {
|
||||
return isPointsOnly;
|
||||
};
|
||||
|
||||
const getColorForProperty = (styleProperty, isLinesOnly) => {
|
||||
if (isLinesOnly) {
|
||||
return color;
|
||||
}
|
||||
|
||||
return this.getStyleName() === styleProperty ? color : 'none';
|
||||
};
|
||||
|
||||
const fillColor = this.getStyleName() === VECTOR_STYLES.FILL_COLOR ? color : 'none';
|
||||
return (
|
||||
<VectorIcon
|
||||
fillColor={fillColor}
|
||||
isPointsOnly={isPointsOnly}
|
||||
isLinesOnly={isLinesOnly}
|
||||
strokeColor={color}
|
||||
symbolId={symbolId}
|
||||
loadIsPointsOnly={loadIsPointsOnly}
|
||||
loadIsLinesOnly={loadIsLinesOnly}
|
||||
getColorForProperty={getColorForProperty}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ const mockField = {
|
|||
},
|
||||
};
|
||||
|
||||
test('Should render ranged legend', async () => {
|
||||
test('Should render ranged legend', () => {
|
||||
const colorStyle = new DynamicColorProperty(
|
||||
{
|
||||
color: 'Blues',
|
||||
|
@ -40,25 +40,15 @@ test('Should render ranged legend', async () => {
|
|||
);
|
||||
|
||||
const legendRow = colorStyle.renderLegendDetailRow({
|
||||
loadIsPointsOnly: () => {
|
||||
return true;
|
||||
},
|
||||
loadIsLinesOnly: () => {
|
||||
return false;
|
||||
},
|
||||
isPointsOnly: true,
|
||||
isLinesOnly: 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 () => {
|
||||
test('Should render categorical legend', () => {
|
||||
const colorStyle = new DynamicColorProperty(
|
||||
{
|
||||
useCustomColorRamp: true,
|
||||
|
@ -84,20 +74,10 @@ test('Should render categorical legend', async () => {
|
|||
);
|
||||
|
||||
const legendRow = colorStyle.renderLegendDetailRow({
|
||||
loadIsPointsOnly: () => {
|
||||
return true;
|
||||
},
|
||||
loadIsLinesOnly: () => {
|
||||
return false;
|
||||
},
|
||||
isPointsOnly: true,
|
||||
isLinesOnly: 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();
|
||||
});
|
||||
|
|
|
@ -165,12 +165,12 @@ export class DynamicStyleProperty extends AbstractStyleProperty {
|
|||
return null;
|
||||
}
|
||||
|
||||
_renderCategoricalLegend({ loadIsPointsOnly, loadIsLinesOnly, symbolId }) {
|
||||
_renderCategoricalLegend({ isPointsOnly, isLinesOnly, symbolId }) {
|
||||
return (
|
||||
<CategoricalLegend
|
||||
style={this}
|
||||
loadIsLinesOnly={loadIsLinesOnly}
|
||||
loadIsPointsOnly={loadIsPointsOnly}
|
||||
isPointsOnly={isPointsOnly}
|
||||
isLinesOnly={isLinesOnly}
|
||||
symbolId={symbolId}
|
||||
/>
|
||||
);
|
||||
|
@ -180,11 +180,11 @@ export class DynamicStyleProperty extends AbstractStyleProperty {
|
|||
return <OrdinalLegend style={this} />;
|
||||
}
|
||||
|
||||
renderLegendDetailRow({ loadIsPointsOnly, loadIsLinesOnly, symbolId }) {
|
||||
renderLegendDetailRow({ isPointsOnly, isLinesOnly, symbolId }) {
|
||||
if (this.isRanged()) {
|
||||
return this._renderRangeLegend();
|
||||
} else if (this.hasBreaks()) {
|
||||
return this._renderCategoricalLegend({ loadIsPointsOnly, loadIsLinesOnly, symbolId });
|
||||
return this._renderCategoricalLegend({ isPointsOnly, isLinesOnly, symbolId });
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -17,10 +17,6 @@ export function isOnlySingleFeatureType(featureType, supportedFeatures, hasFeatu
|
|||
return supportedFeatures[0] === featureType;
|
||||
}
|
||||
|
||||
if (!hasFeatureType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const featureTypes = Object.keys(hasFeatureType);
|
||||
return featureTypes.reduce((isOnlyTargetFeatureType, featureTypeKey) => {
|
||||
const hasFeature = hasFeatureType[featureTypeKey];
|
||||
|
|
|
@ -143,8 +143,8 @@ export class VectorStyle extends AbstractStyle {
|
|||
styleProperties={styleProperties}
|
||||
symbolDescriptor={this._descriptor.properties[VECTOR_STYLES.SYMBOL]}
|
||||
layer={layer}
|
||||
loadIsPointsOnly={this._getIsPointsOnly}
|
||||
loadIsLinesOnly={this._getIsLinesOnly}
|
||||
isPointsOnly={this._getIsPointsOnly()}
|
||||
isLinesOnly={this._getIsLinesOnly()}
|
||||
onIsTimeAwareChange={onIsTimeAwareChange}
|
||||
isTimeAware={this.isTimeAware()}
|
||||
showIsTimeAware={propertiesWithFieldMeta.length > 0}
|
||||
|
@ -218,43 +218,57 @@ export class VectorStyle extends AbstractStyle {
|
|||
|
||||
async pluckStyleMetaFromSourceDataRequest(sourceDataRequest) {
|
||||
const features = _.get(sourceDataRequest.getData(), 'features', []);
|
||||
if (features.length === 0) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const dynamicProperties = this.getDynamicPropertiesArray();
|
||||
|
||||
const supportedFeatures = await this._source.getSupportedShapeTypes();
|
||||
const isSingleFeatureType = supportedFeatures.length === 1;
|
||||
if (dynamicProperties.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;
|
||||
const hasFeatureType = {
|
||||
[VECTOR_SHAPE_TYPES.POINT]: false,
|
||||
[VECTOR_SHAPE_TYPES.LINE]: false,
|
||||
[VECTOR_SHAPE_TYPES.POLYGON]: false,
|
||||
};
|
||||
if (supportedFeatures.length > 1) {
|
||||
for (let i = 0; i < features.length; i++) {
|
||||
const feature = features[i];
|
||||
if (!hasFeatureType[VECTOR_SHAPE_TYPES.POINT] && POINTS.includes(feature.geometry.type)) {
|
||||
hasFeatureType[VECTOR_SHAPE_TYPES.POINT] = true;
|
||||
}
|
||||
if (!hasFeatureType[VECTOR_SHAPE_TYPES.LINE] && LINES.includes(feature.geometry.type)) {
|
||||
hasFeatureType[VECTOR_SHAPE_TYPES.LINE] = true;
|
||||
}
|
||||
if (
|
||||
!hasFeatureType[VECTOR_SHAPE_TYPES.POLYGON] &&
|
||||
POLYGONS.includes(feature.geometry.type)
|
||||
) {
|
||||
hasFeatureType[VECTOR_SHAPE_TYPES.POLYGON] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const featuresMeta = {
|
||||
hasFeatureType: {
|
||||
[VECTOR_SHAPE_TYPES.POINT]: hasPoints,
|
||||
[VECTOR_SHAPE_TYPES.LINE]: hasLines,
|
||||
[VECTOR_SHAPE_TYPES.POLYGON]: hasPolygons,
|
||||
geometryTypes: {
|
||||
isPointsOnly: isOnlySingleFeatureType(
|
||||
VECTOR_SHAPE_TYPES.POINT,
|
||||
supportedFeatures,
|
||||
hasFeatureType
|
||||
),
|
||||
isLinesOnly: isOnlySingleFeatureType(
|
||||
VECTOR_SHAPE_TYPES.LINE,
|
||||
supportedFeatures,
|
||||
hasFeatureType
|
||||
),
|
||||
isPolygonsOnly: isOnlySingleFeatureType(
|
||||
VECTOR_SHAPE_TYPES.POLYGON,
|
||||
supportedFeatures,
|
||||
hasFeatureType
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
const dynamicProperties = this.getDynamicPropertiesArray();
|
||||
if (dynamicProperties.length === 0 || features.length === 0) {
|
||||
// no additional meta data to pull from source data request.
|
||||
return featuresMeta;
|
||||
}
|
||||
|
||||
dynamicProperties.forEach(dynamicProperty => {
|
||||
const styleMeta = dynamicProperty.pluckStyleMetaFromFeatures(features);
|
||||
if (styleMeta) {
|
||||
|
@ -291,24 +305,16 @@ export class VectorStyle extends AbstractStyle {
|
|||
);
|
||||
}
|
||||
|
||||
_isOnlySingleFeatureType = async featureType => {
|
||||
return isOnlySingleFeatureType(
|
||||
featureType,
|
||||
await this._source.getSupportedShapeTypes(),
|
||||
this._getStyleMeta().hasFeatureType
|
||||
);
|
||||
_getIsPointsOnly = () => {
|
||||
return _.get(this._getStyleMeta(), 'geometryTypes.isPointsOnly', false);
|
||||
};
|
||||
|
||||
_getIsPointsOnly = async () => {
|
||||
return this._isOnlySingleFeatureType(VECTOR_SHAPE_TYPES.POINT);
|
||||
_getIsLinesOnly = () => {
|
||||
return _.get(this._getStyleMeta(), 'geometryTypes.isLinesOnly', false);
|
||||
};
|
||||
|
||||
_getIsLinesOnly = async () => {
|
||||
return this._isOnlySingleFeatureType(VECTOR_SHAPE_TYPES.LINE);
|
||||
};
|
||||
|
||||
_getIsPolygonsOnly = async () => {
|
||||
return this._isOnlySingleFeatureType(VECTOR_SHAPE_TYPES.POLYGON);
|
||||
_getIsPolygonsOnly = () => {
|
||||
return _.get(this._getStyleMeta(), 'geometryTypes.isPolygonsOnly', false);
|
||||
};
|
||||
|
||||
_getDynamicPropertyByFieldName(fieldName) {
|
||||
|
@ -393,50 +399,44 @@ export class VectorStyle extends AbstractStyle {
|
|||
: 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();
|
||||
const isLinesOnly = this._getIsLinesOnly();
|
||||
const strokeColor = isLinesOnly
|
||||
? extractColorFromStyleProperty(this._descriptor.properties[VECTOR_STYLES.LINE_COLOR], 'grey')
|
||||
: extractColorFromStyleProperty(
|
||||
this._descriptor.properties[VECTOR_STYLES.LINE_COLOR],
|
||||
'none'
|
||||
);
|
||||
const fillColor = isLinesOnly
|
||||
? null
|
||||
: extractColorFromStyleProperty(
|
||||
this._descriptor.properties[VECTOR_STYLES.FILL_COLOR],
|
||||
'grey'
|
||||
);
|
||||
|
||||
return (
|
||||
<VectorIcon
|
||||
loadIsPointsOnly={this._getIsPointsOnly}
|
||||
loadIsLinesOnly={this._getIsLinesOnly}
|
||||
symbolId={symbolId}
|
||||
getColorForProperty={this._getColorForProperty}
|
||||
isPointsOnly={this._getIsPointsOnly()}
|
||||
isLinesOnly={isLinesOnly}
|
||||
symbolId={this._getSymbolId()}
|
||||
strokeColor={strokeColor}
|
||||
fillColor={fillColor}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
_getLegendDetailStyleProperties = async () => {
|
||||
const isLinesOnly = await this._getIsLinesOnly();
|
||||
const isPolygonsOnly = await this._getIsPolygonsOnly();
|
||||
|
||||
_getLegendDetailStyleProperties = () => {
|
||||
return this.getDynamicPropertiesArray().filter(styleProperty => {
|
||||
const styleName = styleProperty.getStyleName();
|
||||
if ([VECTOR_STYLES.ICON_ORIENTATION, VECTOR_STYLES.LABEL_TEXT].includes(styleName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isLinesOnly) {
|
||||
if (this._getIsLinesOnly()) {
|
||||
return LINE_STYLES.includes(styleName);
|
||||
}
|
||||
|
||||
if (isPolygonsOnly) {
|
||||
if (this._getIsPolygonsOnly()) {
|
||||
return POLYGON_STYLES.includes(styleName);
|
||||
}
|
||||
|
||||
|
@ -445,16 +445,15 @@ export class VectorStyle extends AbstractStyle {
|
|||
};
|
||||
|
||||
async hasLegendDetails() {
|
||||
const styles = await this._getLegendDetailStyleProperties();
|
||||
return styles.length > 0;
|
||||
return this._getLegendDetailStyleProperties().length > 0;
|
||||
}
|
||||
|
||||
renderLegendDetails() {
|
||||
return (
|
||||
<VectorStyleLegend
|
||||
getLegendDetailStyleProperties={this._getLegendDetailStyleProperties}
|
||||
loadIsPointsOnly={this._getIsPointsOnly}
|
||||
loadIsLinesOnly={this._getIsLinesOnly}
|
||||
styles={this._getLegendDetailStyleProperties()}
|
||||
isPointsOnly={this._getIsPointsOnly()}
|
||||
isLinesOnly={this._getIsLinesOnly()}
|
||||
symbolId={this._getSymbolId()}
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -159,11 +159,9 @@ describe('pluckStyleMetaFromSourceDataRequest', () => {
|
|||
const vectorStyle = new VectorStyle({}, new MockSource());
|
||||
|
||||
const featuresMeta = await vectorStyle.pluckStyleMetaFromSourceDataRequest(sourceDataRequest);
|
||||
expect(featuresMeta.hasFeatureType).toEqual({
|
||||
LINE: false,
|
||||
POINT: true,
|
||||
POLYGON: false,
|
||||
});
|
||||
expect(featuresMeta.geometryTypes.isPointsOnly).toBe(true);
|
||||
expect(featuresMeta.geometryTypes.isLinesOnly).toBe(false);
|
||||
expect(featuresMeta.geometryTypes.isPolygonsOnly).toBe(false);
|
||||
});
|
||||
|
||||
it('Should identify when feature collection only contains lines', async () => {
|
||||
|
@ -189,11 +187,9 @@ describe('pluckStyleMetaFromSourceDataRequest', () => {
|
|||
const vectorStyle = new VectorStyle({}, new MockSource());
|
||||
|
||||
const featuresMeta = await vectorStyle.pluckStyleMetaFromSourceDataRequest(sourceDataRequest);
|
||||
expect(featuresMeta.hasFeatureType).toEqual({
|
||||
LINE: true,
|
||||
POINT: false,
|
||||
POLYGON: false,
|
||||
});
|
||||
expect(featuresMeta.geometryTypes.isPointsOnly).toBe(false);
|
||||
expect(featuresMeta.geometryTypes.isLinesOnly).toBe(true);
|
||||
expect(featuresMeta.geometryTypes.isPolygonsOnly).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -241,11 +237,9 @@ describe('pluckStyleMetaFromSourceDataRequest', () => {
|
|||
);
|
||||
|
||||
const featuresMeta = await vectorStyle.pluckStyleMetaFromSourceDataRequest(sourceDataRequest);
|
||||
expect(featuresMeta.hasFeatureType).toEqual({
|
||||
LINE: false,
|
||||
POINT: true,
|
||||
POLYGON: false,
|
||||
});
|
||||
expect(featuresMeta.geometryTypes.isPointsOnly).toBe(true);
|
||||
expect(featuresMeta.geometryTypes.isLinesOnly).toBe(false);
|
||||
expect(featuresMeta.geometryTypes.isPolygonsOnly).toBe(false);
|
||||
});
|
||||
|
||||
it('Should extract scaled field range', async () => {
|
||||
|
@ -275,88 +269,3 @@ describe('pluckStyleMetaFromSourceDataRequest', () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('checkIfOnlyFeatureType', () => {
|
||||
describe('source supports single feature type', () => {
|
||||
it('isPointsOnly should be true when source feature type only supports points', async () => {
|
||||
const vectorStyle = new VectorStyle(
|
||||
{},
|
||||
new MockSource({
|
||||
supportedShapeTypes: [VECTOR_SHAPE_TYPES.POINT],
|
||||
})
|
||||
);
|
||||
const isPointsOnly = await vectorStyle._getIsPointsOnly();
|
||||
expect(isPointsOnly).toBe(true);
|
||||
});
|
||||
|
||||
it('isLineOnly should be false when source feature type only supports points', async () => {
|
||||
const vectorStyle = new VectorStyle(
|
||||
{},
|
||||
new MockSource({
|
||||
supportedShapeTypes: [VECTOR_SHAPE_TYPES.POINT],
|
||||
})
|
||||
);
|
||||
const isLineOnly = await vectorStyle._getIsLinesOnly();
|
||||
expect(isLineOnly).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('source supports multiple feature types', () => {
|
||||
it('isPointsOnly should be true when data contains just points', async () => {
|
||||
const vectorStyle = new VectorStyle(
|
||||
{
|
||||
__styleMeta: {
|
||||
hasFeatureType: {
|
||||
POINT: true,
|
||||
LINE: false,
|
||||
POLYGON: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
new MockSource({
|
||||
supportedShapeTypes: Object.values(VECTOR_SHAPE_TYPES),
|
||||
})
|
||||
);
|
||||
const isPointsOnly = await vectorStyle._getIsPointsOnly();
|
||||
expect(isPointsOnly).toBe(true);
|
||||
});
|
||||
|
||||
it('isPointsOnly should be false when data contains just lines', async () => {
|
||||
const vectorStyle = new VectorStyle(
|
||||
{
|
||||
__styleMeta: {
|
||||
hasFeatureType: {
|
||||
POINT: false,
|
||||
LINE: true,
|
||||
POLYGON: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
new MockSource({
|
||||
supportedShapeTypes: Object.values(VECTOR_SHAPE_TYPES),
|
||||
})
|
||||
);
|
||||
const isPointsOnly = await vectorStyle._getIsPointsOnly();
|
||||
expect(isPointsOnly).toBe(false);
|
||||
});
|
||||
|
||||
it('isPointsOnly should be false when data contains points, lines, and polygons', async () => {
|
||||
const vectorStyle = new VectorStyle(
|
||||
{
|
||||
__styleMeta: {
|
||||
hasFeatureType: {
|
||||
POINT: true,
|
||||
LINE: true,
|
||||
POLYGON: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
new MockSource({
|
||||
supportedShapeTypes: Object.values(VECTOR_SHAPE_TYPES),
|
||||
})
|
||||
);
|
||||
const isPointsOnly = await vectorStyle._getIsPointsOnly();
|
||||
expect(isPointsOnly).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue