[Maps] convert style classes to TS (#75374)

* [Maps] convert style classes to TS

* convert VectorStyle to TS

* clean up

* revert change to fix unit test

* review feedback

* review feedback

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
Nathan Reese 2020-08-21 15:40:07 -06:00 committed by GitHub
parent a4fa73054a
commit 3df47dc66b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 433 additions and 279 deletions

View file

@ -38,36 +38,3 @@ export type LayerDescriptor = {
export type VectorLayerDescriptor = LayerDescriptor & {
style: VectorStyleDescriptor;
};
export type RangeFieldMeta = {
min: number;
max: number;
delta: number;
isMinOutsideStdRange?: boolean;
isMaxOutsideStdRange?: boolean;
};
export type Category = {
key: string;
count: number;
};
export type CategoryFieldMeta = {
categories: Category[];
};
export type GeometryTypes = {
isPointsOnly: boolean;
isLinesOnly: boolean;
isPolygonsOnly: boolean;
};
export type StyleMetaDescriptor = {
geometryTypes?: GeometryTypes;
fieldMeta: {
[key: string]: {
range: RangeFieldMeta;
categories: CategoryFieldMeta;
};
};
};

View file

@ -12,7 +12,6 @@ import {
SYMBOLIZE_AS_TYPES,
VECTOR_STYLES,
STYLE_TYPE,
LAYER_STYLE_TYPE,
} from '../constants';
// Non-static/dynamic options
@ -193,9 +192,47 @@ export type StyleDescriptor = {
type: string;
};
export type RangeFieldMeta = {
min: number;
max: number;
delta: number;
isMinOutsideStdRange?: boolean;
isMaxOutsideStdRange?: boolean;
};
export type Category = {
key: string;
count: number;
};
export type CategoryFieldMeta = {
categories: Category[];
};
export type GeometryTypes = {
isPointsOnly: boolean;
isLinesOnly: boolean;
isPolygonsOnly: boolean;
};
export type StyleMetaDescriptor = {
geometryTypes?: GeometryTypes;
fieldMeta: {
[key: string]: {
range?: RangeFieldMeta;
categories?: CategoryFieldMeta;
};
};
};
export type VectorStyleDescriptor = StyleDescriptor & {
type: LAYER_STYLE_TYPE.VECTOR;
properties: VectorStylePropertiesDescriptor;
isTimeAware: boolean;
__styleMeta?: StyleMetaDescriptor;
};
export type HeatmapStyleDescriptor = StyleDescriptor & {
colorRampName: string;
};
export type StylePropertyOptions =

View file

@ -11,7 +11,7 @@ import uuid from 'uuid/v4';
import { multiPoint } from '@turf/helpers';
import { FeatureCollection } from 'geojson';
import { MapStoreState } from '../reducers/store';
import { LAYER_TYPE, SOURCE_DATA_REQUEST_ID } from '../../common/constants';
import { LAYER_STYLE_TYPE, LAYER_TYPE, SOURCE_DATA_REQUEST_ID } from '../../common/constants';
import {
getDataFilters,
getDataRequestDescriptor,
@ -42,6 +42,7 @@ import { IVectorLayer } from '../classes/layers/vector_layer/vector_layer';
import { DataMeta, MapExtent, MapFilters } from '../../common/descriptor_types';
import { DataRequestAbortError } from '../classes/util/data_request';
import { scaleBounds, turfBboxToBounds } from '../../common/elasticsearch_geo_utils';
import { IVectorStyle } from '../classes/styles/vector/vector_style';
const FIT_TO_BOUNDS_SCALE_FACTOR = 0.1;
@ -85,10 +86,12 @@ export function updateStyleMeta(layerId: string | null) {
}
const sourceDataRequest = layer.getSourceDataRequest();
const style = layer.getCurrentStyle();
if (!style || !sourceDataRequest) {
if (!style || !sourceDataRequest || style.getType() !== LAYER_STYLE_TYPE.VECTOR) {
return;
}
const styleMeta = await style.pluckStyleMetaFromSourceDataRequest(sourceDataRequest);
const styleMeta = await (style as IVectorStyle).pluckStyleMetaFromSourceDataRequest(
sourceDataRequest
);
dispatch({
type: SET_LAYER_STYLE_META,
layerId,

View file

@ -40,7 +40,8 @@ import { cleanTooltipStateForLayer } from './tooltip_actions';
import { JoinDescriptor, LayerDescriptor, StyleDescriptor } from '../../common/descriptor_types';
import { ILayer } from '../classes/layers/layer';
import { IVectorLayer } from '../classes/layers/vector_layer/vector_layer';
import { LAYER_TYPE } from '../../common/constants';
import { LAYER_STYLE_TYPE, LAYER_TYPE } from '../../common/constants';
import { IVectorStyle } from '../classes/styles/vector/vector_style';
export function trackCurrentLayerState(layerId: string) {
return {
@ -381,12 +382,15 @@ export function clearMissingStyleProperties(layerId: string) {
}
const style = targetLayer!.getCurrentStyle();
if (!style) {
if (!style || style.getType() !== LAYER_STYLE_TYPE.VECTOR) {
return;
}
const nextFields = await (targetLayer as IVectorLayer).getFields(); // take into account all fields, since labels can be driven by any field (source or join)
const { hasChanges, nextStyleDescriptor } = style.getDescriptorWithMissingStylePropsRemoved(
const {
hasChanges,
nextStyleDescriptor,
} = (style as IVectorStyle).getDescriptorWithMissingStylePropsRemoved(
nextFields,
getMapColors(getState())
);

View file

@ -17,4 +17,6 @@ export class InnerJoin implements IJoin {
toDescriptor(): JoinDescriptor;
getSourceMetaDataRequestId(): string;
getSourceFormattersDataRequestId(): string;
}

View file

@ -13,4 +13,6 @@ export interface IJoin {
toDescriptor(): JoinDescriptor;
getSourceMetaDataRequestId(): string;
getSourceFormattersDataRequestId(): string;
}

View file

@ -102,6 +102,7 @@ function getClusterStyleDescriptor(
},
},
},
isTimeAware: true,
};
documentStyle
.getAllStyleProperties()

View file

@ -309,7 +309,7 @@ export class VectorLayer extends AbstractLayer {
_getSearchFilters(dataFilters, source, style) {
const fieldNames = [
...source.getFieldNames(),
...style.getSourceFieldNames(),
...(style.getType() === LAYER_STYLE_TYPE.VECTOR ? style.getSourceFieldNames() : []),
...this.getValidJoins().map((join) => join.getLeftField().getName()),
];
@ -415,7 +415,7 @@ export class VectorLayer extends AbstractLayer {
}
async _syncSourceStyleMeta(syncContext, source, style) {
if (this.getCurrentStyle().constructor.type !== LAYER_STYLE_TYPE.VECTOR) {
if (this.getCurrentStyle().getType() !== LAYER_STYLE_TYPE.VECTOR) {
return;
}
@ -511,7 +511,7 @@ export class VectorLayer extends AbstractLayer {
}
async _syncSourceFormatters(syncContext, source, style) {
if (style.constructor.type !== LAYER_STYLE_TYPE.VECTOR) {
if (style.getType() !== LAYER_STYLE_TYPE.VECTOR) {
return;
}

View file

@ -15,6 +15,7 @@ export interface IESAggSource extends IESSource {
getAggLabel(aggType: AGG_TYPE, fieldName: string): string;
getMetricFields(): IESAggField[];
hasMatchingMetricField(fieldName: string): boolean;
getMetricFieldForName(fieldName: string): IESAggField | null;
}
export class AbstractESAggSource extends AbstractESSource implements IESAggSource {
@ -24,4 +25,5 @@ export class AbstractESAggSource extends AbstractESSource implements IESAggSourc
getAggLabel(aggType: AGG_TYPE, fieldName: string): string;
getMetricFields(): IESAggField[];
hasMatchingMetricField(fieldName: string): boolean;
getMetricFieldForName(fieldName: string): IESAggField | null;
}

View file

@ -53,6 +53,7 @@ export interface IVectorSource extends ISource {
getApplyGlobalQuery(): boolean;
createField({ fieldName }: { fieldName: string }): IField;
canFormatFeatureProperties(): boolean;
getSupportedShapeTypes(): Promise<VECTOR_SHAPE_TYPE[]>;
}
export class AbstractVectorSource extends AbstractSource implements IVectorSource {

View file

@ -4,12 +4,25 @@
* you may not use this file except in compliance with the Elastic License.
*/
import React from 'react';
import PropTypes from 'prop-types';
import React, { ReactElement } from 'react';
import { EuiFlexGroup, EuiFlexItem, EuiText, EuiToolTip } from '@elastic/eui';
export function RangedStyleLegendRow({ header, minLabel, maxLabel, propertyLabel, fieldLabel }) {
interface Props {
header: ReactElement<any>;
minLabel: string | number;
maxLabel: string | number;
propertyLabel: string;
fieldLabel: string;
}
export function RangedStyleLegendRow({
header,
minLabel,
maxLabel,
propertyLabel,
fieldLabel,
}: Props) {
return (
<div>
<EuiFlexGroup gutterSize="xs" justifyContent="spaceBetween">
@ -39,11 +52,3 @@ export function RangedStyleLegendRow({ header, minLabel, maxLabel, propertyLabel
</div>
);
}
RangedStyleLegendRow.propTypes = {
header: PropTypes.node.isRequired,
minLabel: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
maxLabel: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
propertyLabel: PropTypes.string.isRequired,
fieldLabel: PropTypes.string.isRequired,
};

View file

@ -4,18 +4,27 @@
* you may not use this file except in compliance with the Elastic License.
*/
import React from 'react';
import React, { Component } from 'react';
import { i18n } from '@kbn/i18n';
import { ColorGradient } from './color_gradient';
import { RangedStyleLegendRow } from '../../../components/ranged_style_legend_row';
import { HEATMAP_COLOR_RAMP_LABEL } from '../heatmap_constants';
import { IField } from '../../../../fields/field';
export class HeatmapLegend extends React.Component {
constructor() {
super();
this.state = { label: '' };
}
interface Props {
colorRampName: string;
field: IField;
}
interface State {
label: string;
}
export class HeatmapLegend extends Component<Props, State> {
private _isMounted: boolean = false;
state: State = { label: '' };
componentDidUpdate() {
this._loadLabel();

View file

@ -5,43 +5,48 @@
*/
import React from 'react';
import { AbstractStyle } from '../style';
import { Map as MbMap } from 'mapbox-gl';
import { i18n } from '@kbn/i18n';
import { EuiIcon } from '@elastic/eui';
import { IStyle } from '../style';
import { HeatmapStyleEditor } from './components/heatmap_style_editor';
import { HeatmapLegend } from './components/legend/heatmap_legend';
import { DEFAULT_HEATMAP_COLOR_RAMP_NAME, getOrdinalMbColorRampStops } from '../color_palettes';
import { LAYER_STYLE_TYPE, GRID_RESOLUTION } from '../../../../common/constants';
import { HeatmapStyleDescriptor, StyleDescriptor } from '../../../../common/descriptor_types';
import { IField } from '../../fields/field';
import { i18n } from '@kbn/i18n';
import { EuiIcon } from '@elastic/eui';
//The heatmap range chosen hear runs from 0 to 1. It is arbitrary.
//Weighting is on the raw count/sum values.
// The heatmap range chosen hear runs from 0 to 1. It is arbitrary.
// Weighting is on the raw count/sum values.
const MIN_RANGE = 0.1; // 0 to 0.1 is displayed as transparent color stop
const MAX_RANGE = 1;
export class HeatmapStyle extends AbstractStyle {
static type = LAYER_STYLE_TYPE.HEATMAP;
export class HeatmapStyle implements IStyle {
readonly _descriptor: HeatmapStyleDescriptor;
constructor(descriptor = {}) {
super();
constructor(
descriptor: { colorRampName: string } = { colorRampName: DEFAULT_HEATMAP_COLOR_RAMP_NAME }
) {
this._descriptor = HeatmapStyle.createDescriptor(descriptor.colorRampName);
}
static createDescriptor(colorRampName) {
static createDescriptor(colorRampName: string) {
return {
type: HeatmapStyle.type,
type: LAYER_STYLE_TYPE.HEATMAP,
colorRampName: colorRampName ? colorRampName : DEFAULT_HEATMAP_COLOR_RAMP_NAME,
};
}
static getDisplayName() {
return i18n.translate('xpack.maps.style.heatmap.displayNameLabel', {
defaultMessage: 'Heatmap style',
});
getType() {
return LAYER_STYLE_TYPE.HEATMAP;
}
renderEditor({ onStyleDescriptorChange }) {
const onHeatmapColorChange = ({ colorRampName }) => {
renderEditor({
onStyleDescriptorChange,
}: {
onStyleDescriptorChange: (styleDescriptor: StyleDescriptor) => void;
}) {
const onHeatmapColorChange = ({ colorRampName }: { colorRampName: string }) => {
const styleDescriptor = HeatmapStyle.createDescriptor(colorRampName);
onStyleDescriptorChange(styleDescriptor);
};
@ -54,7 +59,7 @@ export class HeatmapStyle extends AbstractStyle {
);
}
renderLegendDetails(field) {
renderLegendDetails(field: IField) {
return <HeatmapLegend colorRampName={this._descriptor.colorRampName} field={field} />;
}
@ -62,7 +67,17 @@ export class HeatmapStyle extends AbstractStyle {
return <EuiIcon size="m" type="heatmap" />;
}
setMBPaintProperties({ mbMap, layerId, propertyName, resolution }) {
setMBPaintProperties({
mbMap,
layerId,
propertyName,
resolution,
}: {
mbMap: MbMap;
layerId: string;
propertyName: string;
resolution: GRID_RESOLUTION;
}) {
let radius;
if (resolution === GRID_RESOLUTION.COARSE) {
radius = 128;

View file

@ -5,18 +5,11 @@
*/
import { ReactElement } from 'react';
import { StyleDescriptor, StyleMetaDescriptor } from '../../../common/descriptor_types';
import { StyleDescriptor } from '../../../common/descriptor_types';
import { ILayer } from '../layers/layer';
import { IField } from '../fields/field';
import { DataRequest } from '../util/data_request';
export interface IStyle {
getDescriptor(): StyleDescriptor | null;
getDescriptorWithMissingStylePropsRemoved(
nextFields: IField[],
mapColors: string[]
): { hasChanges: boolean; nextStyleDescriptor?: StyleDescriptor };
pluckStyleMetaFromSourceDataRequest(sourceDataRequest: DataRequest): StyleMetaDescriptor;
getType(): string;
renderEditor({
layer,
onStyleDescriptorChange,
@ -24,38 +17,4 @@ export interface IStyle {
layer: ILayer;
onStyleDescriptorChange: (styleDescriptor: StyleDescriptor) => void;
}): ReactElement<any> | null;
getSourceFieldNames(): string[];
}
export class AbstractStyle implements IStyle {
readonly _descriptor: StyleDescriptor | null;
constructor(descriptor: StyleDescriptor | null) {
this._descriptor = descriptor;
}
getDescriptorWithMissingStylePropsRemoved(
nextFields: IField[],
mapColors: string[]
): { hasChanges: boolean; nextStyleDescriptor?: StyleDescriptor } {
return {
hasChanges: false,
};
}
pluckStyleMetaFromSourceDataRequest(sourceDataRequest: DataRequest): StyleMetaDescriptor {
return { fieldMeta: {} };
}
getDescriptor(): StyleDescriptor | null {
return this._descriptor;
}
renderEditor(/* { layer, onStyleDescriptorChange } */) {
return null;
}
getSourceFieldNames(): string[] {
return [];
}
}

View file

@ -4,13 +4,24 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { AbstractStyle } from '../style';
import { IStyle } from '../style';
import { StyleDescriptor } from '../../../../common/descriptor_types';
import { LAYER_STYLE_TYPE } from '../../../../common/constants';
export class TileStyle extends AbstractStyle {
export class TileStyle implements IStyle {
readonly _descriptor: StyleDescriptor;
constructor() {
super({
this._descriptor = {
type: LAYER_STYLE_TYPE.TILE,
});
};
}
getType() {
return LAYER_STYLE_TYPE.TILE;
}
renderEditor(/* { layer, onStyleDescriptorChange } */) {
return null;
}
}

View file

@ -7,7 +7,6 @@
import React, { Component, Fragment } from 'react';
import _ from 'lodash';
import { EuiFlexGroup, EuiFlexItem, EuiHorizontalRule } from '@elastic/eui';
// @ts-expect-error
import { RangedStyleLegendRow } from '../../../components/ranged_style_legend_row';
import { VECTOR_STYLES } from '../../../../../../common/constants';
import { CircleIcon } from './circle_icon';

View file

@ -11,7 +11,7 @@ interface Props {
isLinesOnly: boolean;
isPointsOnly: boolean;
styles: Array<IStyleProperty<any>>;
symbolId: string;
symbolId?: string;
}
export function VectorStyleLegend({ isLinesOnly, isPointsOnly, styles, symbolId }: Props) {
@ -31,5 +31,5 @@ export function VectorStyleLegend({ isLinesOnly, isPointsOnly, styles, symbolId
);
}
return legendRows;
return <>{legendRows}</>;
}

View file

@ -14,7 +14,7 @@ import {
StyleMetaDescriptor,
} from '../../../../../../common/descriptor_types';
import { AbstractField, IField } from '../../../../fields/field';
import { IStyle, AbstractStyle } from '../../../style';
import { IStyle } from '../../../style';
class MockField extends AbstractField {
async getLabel(): Promise<string> {
@ -30,16 +30,23 @@ export const mockField: IField = new MockField({
origin: FIELD_ORIGIN.SOURCE,
});
export class MockStyle extends AbstractStyle implements IStyle {
export class MockStyle implements IStyle {
private readonly _min: number;
private readonly _max: number;
constructor({ min = 0, max = 100 } = {}) {
super(null);
this._min = min;
this._max = max;
}
renderEditor() {
return null;
}
getType() {
return 'mockStyle';
}
getStyleMeta(): StyleMeta {
const geomTypes: GeometryTypes = {
isPointsOnly: false,

View file

@ -4,12 +4,14 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { Map as MbMap } from 'mapbox-gl';
import { DynamicStyleProperty } from './dynamic_style_property';
import { getComputedFieldName } from '../style_util';
import { VECTOR_STYLES } from '../../../../../common/constants';
import { OrientationDynamicOptions } from '../../../../../common/descriptor_types';
export class DynamicOrientationProperty extends DynamicStyleProperty {
syncIconRotationWithMb(symbolLayerId, mbMap) {
export class DynamicOrientationProperty extends DynamicStyleProperty<OrientationDynamicOptions> {
syncIconRotationWithMb(symbolLayerId: string, mbMap: MbMap) {
if (this._field && this._field.isValid()) {
const targetName = this._field.supportsAutoDomain()
? getComputedFieldName(VECTOR_STYLES.ICON_ORIENTATION, this.getFieldName())

View file

@ -17,14 +17,14 @@ export class StyleMeta {
}
getRangeFieldMetaDescriptor(fieldName: string): RangeFieldMeta | null {
return this._descriptor && this._descriptor.fieldMeta[fieldName]
? this._descriptor.fieldMeta[fieldName].range
return this._descriptor.fieldMeta[fieldName] && this._descriptor.fieldMeta[fieldName].range
? this._descriptor.fieldMeta[fieldName].range!
: null;
}
getCategoryFieldMetaDescriptor(fieldName: string): CategoryFieldMeta | null {
return this._descriptor && this._descriptor.fieldMeta[fieldName]
? this._descriptor.fieldMeta[fieldName].categories
return this._descriptor.fieldMeta[fieldName] && this._descriptor.fieldMeta[fieldName].categories
? this._descriptor.fieldMeta[fieldName].categories!
: null;
}

View file

@ -1,34 +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 { IStyleProperty } from './properties/style_property';
import { IDynamicStyleProperty } from './properties/dynamic_style_property';
import { IVectorLayer } from '../../layers/vector_layer/vector_layer';
import { IVectorSource } from '../../sources/vector_source';
import { AbstractStyle, IStyle } from '../style';
import {
DynamicStylePropertyOptions,
StylePropertyOptions,
VectorStyleDescriptor,
VectorStylePropertiesDescriptor,
} from '../../../../common/descriptor_types';
import { StyleMeta } from './style_meta';
export interface IVectorStyle extends IStyle {
getAllStyleProperties(): Array<IStyleProperty<StylePropertyOptions>>;
getDynamicPropertiesArray(): Array<IDynamicStyleProperty<DynamicStylePropertyOptions>>;
getSourceFieldNames(): string[];
getStyleMeta(): StyleMeta;
}
export class VectorStyle extends AbstractStyle implements IVectorStyle {
static createDescriptor(properties: VectorStylePropertiesDescriptor): VectorStyleDescriptor;
static createDefaultStyleProperties(mapColors: string[]): VectorStylePropertiesDescriptor;
constructor(descriptor: VectorStyleDescriptor, source: IVectorSource, layer: IVectorLayer);
getSourceFieldNames(): string[];
getAllStyleProperties(): Array<IStyleProperty<StylePropertyOptions>>;
getDynamicPropertiesArray(): Array<IDynamicStyleProperty<DynamicStylePropertyOptions>>;
getStyleMeta(): StyleMeta;
}

View file

@ -6,6 +6,9 @@
import _ from 'lodash';
import React from 'react';
import { Map as MbMap, FeatureIdentifier } from 'mapbox-gl';
import { FeatureCollection } from 'geojson';
// @ts-expect-error
import { VectorStyleEditor } from './components/vector_style_editor';
import {
getDefaultProperties,
@ -13,7 +16,6 @@ import {
LINE_STYLES,
POLYGON_STYLES,
} from './vector_style_defaults';
import { AbstractStyle } from '../style';
import {
GEO_JSON_TYPE,
FIELD_ORIGIN,
@ -43,45 +45,109 @@ import { extractColorFromStyleProperty } from './components/legend/extract_color
import { SymbolizeAsProperty } from './properties/symbolize_as_property';
import { StaticIconProperty } from './properties/static_icon_property';
import { DynamicIconProperty } from './properties/dynamic_icon_property';
import {
ColorDynamicOptions,
ColorStaticOptions,
ColorStylePropertyDescriptor,
DynamicStylePropertyOptions,
IconDynamicOptions,
IconStaticOptions,
IconStylePropertyDescriptor,
LabelDynamicOptions,
LabelStaticOptions,
LabelStylePropertyDescriptor,
OrientationDynamicOptions,
OrientationStaticOptions,
OrientationStylePropertyDescriptor,
SizeDynamicOptions,
SizeStaticOptions,
SizeStylePropertyDescriptor,
StyleDescriptor,
StyleMetaDescriptor,
StylePropertyField,
StylePropertyOptions,
VectorStyleDescriptor,
VectorStylePropertiesDescriptor,
} from '../../../../common/descriptor_types';
import { DataRequest } from '../../util/data_request';
import { IStyle } from '../style';
import { IStyleProperty } from './properties/style_property';
import { IDynamicStyleProperty } from './properties/dynamic_style_property';
import { IField } from '../../fields/field';
import { IVectorLayer } from '../../layers/vector_layer/vector_layer';
import { IVectorSource } from '../../sources/vector_source';
import { ILayer } from '../../layers/layer';
const POINTS = [GEO_JSON_TYPE.POINT, GEO_JSON_TYPE.MULTI_POINT];
const LINES = [GEO_JSON_TYPE.LINE_STRING, GEO_JSON_TYPE.MULTI_LINE_STRING];
const POLYGONS = [GEO_JSON_TYPE.POLYGON, GEO_JSON_TYPE.MULTI_POLYGON];
function getNumericalMbFeatureStateValue(value) {
function getNumericalMbFeatureStateValue(value: string) {
const valueAsFloat = parseFloat(value);
return isNaN(valueAsFloat) ? null : valueAsFloat;
}
export class VectorStyle extends AbstractStyle {
static type = LAYER_STYLE_TYPE.VECTOR;
export interface IVectorStyle extends IStyle {
getAllStyleProperties(): Array<IStyleProperty<StylePropertyOptions>>;
getDynamicPropertiesArray(): Array<IDynamicStyleProperty<DynamicStylePropertyOptions>>;
getSourceFieldNames(): string[];
getStyleMeta(): StyleMeta;
getDescriptorWithMissingStylePropsRemoved(
nextFields: IField[],
mapColors: string[]
): { hasChanges: boolean; nextStyleDescriptor?: VectorStyleDescriptor };
pluckStyleMetaFromSourceDataRequest(sourceDataRequest: DataRequest): Promise<StyleMetaDescriptor>;
}
export class VectorStyle implements IVectorStyle {
private readonly _descriptor: VectorStyleDescriptor;
private readonly _layer: IVectorLayer;
private readonly _source: IVectorSource;
private readonly _styleMeta: StyleMeta;
private readonly _symbolizeAsStyleProperty: SymbolizeAsProperty;
private readonly _lineColorStyleProperty: StaticColorProperty | DynamicColorProperty;
private readonly _fillColorStyleProperty: StaticColorProperty | DynamicColorProperty;
private readonly _lineWidthStyleProperty: StaticSizeProperty | DynamicSizeProperty;
private readonly _iconStyleProperty: StaticIconProperty | DynamicIconProperty;
private readonly _iconSizeStyleProperty: StaticSizeProperty | DynamicSizeProperty;
private readonly _iconOrientationProperty: StaticOrientationProperty | DynamicOrientationProperty;
private readonly _labelStyleProperty: StaticTextProperty | DynamicTextProperty;
private readonly _labelSizeStyleProperty: StaticSizeProperty | DynamicSizeProperty;
private readonly _labelColorStyleProperty: StaticColorProperty | DynamicColorProperty;
private readonly _labelBorderColorStyleProperty: StaticColorProperty | DynamicColorProperty;
private readonly _labelBorderSizeStyleProperty: LabelBorderSizeProperty;
static createDescriptor(properties = {}, isTimeAware = true) {
return {
type: VectorStyle.type,
type: LAYER_STYLE_TYPE.VECTOR,
properties: { ...getDefaultProperties(), ...properties },
isTimeAware,
};
}
static createDefaultStyleProperties(mapColors) {
static createDefaultStyleProperties(mapColors: string[]) {
return getDefaultProperties(mapColors);
}
constructor(descriptor = {}, source, layer) {
super();
descriptor = descriptor === null ? {} : descriptor;
constructor(
descriptor: VectorStyleDescriptor | null,
source: IVectorSource,
layer: IVectorLayer
) {
this._source = source;
this._layer = layer;
this._descriptor = {
...descriptor,
...VectorStyle.createDescriptor(descriptor.properties, descriptor.isTimeAware),
};
this._descriptor = descriptor
? {
...descriptor,
...VectorStyle.createDescriptor(descriptor.properties, descriptor.isTimeAware),
}
: VectorStyle.createDescriptor();
this._styleMeta = new StyleMeta(this._descriptor.__styleMeta);
this._symbolizeAsStyleProperty = new SymbolizeAsProperty(
this._descriptor.properties[VECTOR_STYLES.SYMBOLIZE_AS].options,
this._descriptor.properties[VECTOR_STYLES.SYMBOLIZE_AS]!.options,
VECTOR_STYLES.SYMBOLIZE_AS
);
this._lineColorStyleProperty = this._makeColorProperty(
@ -94,7 +160,8 @@ export class VectorStyle extends AbstractStyle {
);
this._lineWidthStyleProperty = this._makeSizeProperty(
this._descriptor.properties[VECTOR_STYLES.LINE_WIDTH],
VECTOR_STYLES.LINE_WIDTH
VECTOR_STYLES.LINE_WIDTH,
this._symbolizeAsStyleProperty.isSymbolizedAsIcon()
);
this._iconStyleProperty = this._makeIconProperty(
this._descriptor.properties[VECTOR_STYLES.ICON]
@ -113,7 +180,8 @@ export class VectorStyle extends AbstractStyle {
);
this._labelSizeStyleProperty = this._makeSizeProperty(
this._descriptor.properties[VECTOR_STYLES.LABEL_SIZE],
VECTOR_STYLES.LABEL_SIZE
VECTOR_STYLES.LABEL_SIZE,
this._symbolizeAsStyleProperty.isSymbolizedAsIcon()
);
this._labelColorStyleProperty = this._makeColorProperty(
this._descriptor.properties[VECTOR_STYLES.LABEL_COLOR],
@ -124,12 +192,16 @@ export class VectorStyle extends AbstractStyle {
VECTOR_STYLES.LABEL_BORDER_COLOR
);
this._labelBorderSizeStyleProperty = new LabelBorderSizeProperty(
this._descriptor.properties[VECTOR_STYLES.LABEL_BORDER_SIZE].options,
this._descriptor.properties[VECTOR_STYLES.LABEL_BORDER_SIZE]!.options,
VECTOR_STYLES.LABEL_BORDER_SIZE,
this._labelSizeStyleProperty
);
}
getType() {
return LAYER_STYLE_TYPE.VECTOR;
}
getAllStyleProperties() {
return [
this._symbolizeAsStyleProperty,
@ -150,18 +222,24 @@ export class VectorStyle extends AbstractStyle {
_hasBorder() {
return this._lineWidthStyleProperty.isDynamic()
? this._lineWidthStyleProperty.isComplete()
: this._lineWidthStyleProperty.getOptions().size !== 0;
: (this._lineWidthStyleProperty as StaticSizeProperty).getOptions().size !== 0;
}
renderEditor({ layer, onStyleDescriptorChange }) {
renderEditor({
layer,
onStyleDescriptorChange,
}: {
layer: ILayer;
onStyleDescriptorChange: (styleDescriptor: StyleDescriptor) => void;
}) {
const rawProperties = this.getRawProperties();
const handlePropertyChange = (propertyName, settings) => {
rawProperties[propertyName] = settings; //override single property, but preserve the rest
const handlePropertyChange = (propertyName: VECTOR_STYLES, settings: any) => {
rawProperties[propertyName] = settings; // override single property, but preserve the rest
const vectorStyleDescriptor = VectorStyle.createDescriptor(rawProperties, this.isTimeAware());
onStyleDescriptorChange(vectorStyleDescriptor);
};
const onIsTimeAwareChange = (isTimeAware) => {
const onIsTimeAwareChange = (isTimeAware: boolean) => {
const vectorStyleDescriptor = VectorStyle.createDescriptor(rawProperties, isTimeAware);
onStyleDescriptorChange(vectorStyleDescriptor);
};
@ -170,8 +248,9 @@ export class VectorStyle extends AbstractStyle {
return dynamicStyleProp.isFieldMetaEnabled();
});
const styleProperties = {};
const styleProperties: VectorStylePropertiesDescriptor = {};
this.getAllStyleProperties().forEach((styleProperty) => {
// @ts-expect-error
styleProperties[styleProperty.getStyleName()] = styleProperty;
});
@ -201,26 +280,40 @@ export class VectorStyle extends AbstractStyle {
* This method does not update its descriptor. It just returns a new descriptor that the caller
* can then use to update store state via dispatch.
*/
getDescriptorWithMissingStylePropsRemoved(nextFields, mapColors) {
getDescriptorWithMissingStylePropsRemoved(nextFields: IField[], mapColors: string[]) {
const originalProperties = this.getRawProperties();
const updatedProperties = {};
const updatedProperties = {} as VectorStylePropertiesDescriptor;
const dynamicProperties = Object.keys(originalProperties).filter((key) => {
const { type, options } = originalProperties[key] || {};
return type === STYLE_TYPE.DYNAMIC && options.field && options.field.name;
const dynamicProperties = (Object.keys(originalProperties) as VECTOR_STYLES[]).filter((key) => {
if (!originalProperties[key]) {
return false;
}
const propertyDescriptor = originalProperties[key];
if (
!propertyDescriptor ||
!('type' in propertyDescriptor) ||
propertyDescriptor.type !== STYLE_TYPE.DYNAMIC ||
!propertyDescriptor.options
) {
return false;
}
const dynamicOptions = propertyDescriptor.options as DynamicStylePropertyOptions;
return dynamicOptions.field && dynamicOptions.field.name;
});
dynamicProperties.forEach((key) => {
dynamicProperties.forEach((key: VECTOR_STYLES) => {
// Convert dynamic styling to static stying when there are no nextFields
if (nextFields.length === 0) {
const staticProperties = getDefaultStaticProperties(mapColors);
updatedProperties[key] = staticProperties[key];
updatedProperties[key] = staticProperties[key] as any;
return;
}
const dynamicProperty = originalProperties[key];
const fieldName =
dynamicProperty && dynamicProperty.options.field && dynamicProperty.options.field.name;
if (!dynamicProperty || !dynamicProperty.options) {
return;
}
const fieldName = (dynamicProperty.options as DynamicStylePropertyOptions).field!.name;
if (!fieldName) {
return;
}
@ -236,9 +329,10 @@ export class VectorStyle extends AbstractStyle {
updatedProperties[key] = {
type: DynamicStyleProperty.type,
options: {
...originalProperties[key].options,
...originalProperties[key]!.options,
},
};
} as any;
// @ts-expect-error
delete updatedProperties[key].options.field;
});
@ -261,7 +355,7 @@ export class VectorStyle extends AbstractStyle {
};
}
async pluckStyleMetaFromSourceDataRequest(sourceDataRequest) {
async pluckStyleMetaFromSourceDataRequest(sourceDataRequest: DataRequest) {
const features = _.get(sourceDataRequest.getData(), 'features', []);
const supportedFeatures = await this._source.getSupportedShapeTypes();
@ -307,7 +401,7 @@ export class VectorStyle extends AbstractStyle {
),
},
fieldMeta: {},
};
} as StyleMetaDescriptor;
const dynamicProperties = this.getDynamicPropertiesArray();
if (dynamicProperties.length === 0 || features.length === 0) {
@ -318,7 +412,7 @@ export class VectorStyle extends AbstractStyle {
dynamicProperties.forEach((dynamicProperty) => {
const categoricalStyleMeta = dynamicProperty.pluckCategoricalStyleMetaFromFeatures(features);
const ordinalStyleMeta = dynamicProperty.pluckOrdinalStyleMetaFromFeatures(features);
const name = dynamicProperty.getField().getName();
const name = dynamicProperty.getFieldName();
if (!styleMeta.fieldMeta[name]) {
styleMeta.fieldMeta[name] = {};
}
@ -335,10 +429,10 @@ export class VectorStyle extends AbstractStyle {
}
getSourceFieldNames() {
const fieldNames = [];
const fieldNames: string[] = [];
this.getDynamicPropertiesArray().forEach((styleProperty) => {
if (styleProperty.getFieldOrigin() === FIELD_ORIGIN.SOURCE) {
fieldNames.push(styleProperty.getField().getName());
fieldNames.push(styleProperty.getFieldName());
}
});
return fieldNames;
@ -356,7 +450,7 @@ export class VectorStyle extends AbstractStyle {
const styleProperties = this.getAllStyleProperties();
return styleProperties.filter(
(styleProperty) => styleProperty.isDynamic() && styleProperty.isComplete()
);
) as Array<IDynamicStyleProperty<DynamicStylePropertyOptions>>;
}
_getIsPointsOnly = () => {
@ -371,10 +465,10 @@ export class VectorStyle extends AbstractStyle {
return this._styleMeta.isPolygonsOnly();
};
_getDynamicPropertyByFieldName(fieldName) {
_getDynamicPropertyByFieldName(fieldName: string) {
const dynamicProps = this.getDynamicPropertiesArray();
return dynamicProps.find((dynamicProp) => {
return fieldName === dynamicProp.getField().getName();
return fieldName === dynamicProp.getFieldName();
});
}
@ -382,7 +476,7 @@ export class VectorStyle extends AbstractStyle {
return this._styleMeta;
}
_getFieldFormatter = (fieldName) => {
_getFieldFormatter = (fieldName: string) => {
const dynamicProp = this._getDynamicPropertyByFieldName(fieldName);
if (!dynamicProp) {
return null;
@ -392,11 +486,11 @@ export class VectorStyle extends AbstractStyle {
if (dynamicProp.getFieldOrigin() === FIELD_ORIGIN.SOURCE) {
dataRequestId = SOURCE_FORMATTERS_DATA_REQUEST_ID;
} else {
const join = this._layer.getValidJoins().find((join) => {
const targetJoin = this._layer.getValidJoins().find((join) => {
return join.getRightJoinSource().hasMatchingMetricField(fieldName);
});
if (join) {
dataRequestId = join.getSourceFormattersDataRequestId();
if (targetJoin) {
dataRequestId = targetJoin.getSourceFormattersDataRequestId();
}
}
@ -410,13 +504,14 @@ export class VectorStyle extends AbstractStyle {
}
const formatters = formattersDataRequest.getData();
return formatters[fieldName];
// @ts-expect-error
return formatters ? formatters[fieldName] : null;
};
_getSymbolId() {
return this.arePointsSymbolizedAsCircles()
return this.arePointsSymbolizedAsCircles() || this._iconStyleProperty.isDynamic()
? undefined
: this._iconStyleProperty.getOptions().value;
: (this._iconStyleProperty as StaticIconProperty).getOptions().value;
}
getIcon = () => {
@ -434,7 +529,7 @@ export class VectorStyle extends AbstractStyle {
);
}
const fillColor = isLinesOnly
? null
? undefined
: extractColorFromStyleProperty(
this._descriptor.properties[VECTOR_STYLES.FILL_COLOR],
'grey'
@ -485,10 +580,10 @@ export class VectorStyle extends AbstractStyle {
);
}
clearFeatureState(featureCollection, mbMap, sourceId) {
const tmpFeatureIdentifier = {
source: null,
id: null,
clearFeatureState(featureCollection: FeatureCollection, mbMap: MbMap, sourceId: string) {
const tmpFeatureIdentifier: FeatureIdentifier = {
source: '',
id: undefined,
};
for (let i = 0; i < featureCollection.features.length; i++) {
const feature = featureCollection.features[i];
@ -498,7 +593,11 @@ export class VectorStyle extends AbstractStyle {
}
}
setFeatureStateAndStyleProps(featureCollection, mbMap, mbSourceId) {
setFeatureStateAndStyleProps(
featureCollection: FeatureCollection,
mbMap: MbMap,
mbSourceId: string
) {
if (!featureCollection) {
return;
}
@ -508,24 +607,24 @@ export class VectorStyle extends AbstractStyle {
return;
}
const tmpFeatureIdentifier = {
source: null,
id: null,
const tmpFeatureIdentifier: FeatureIdentifier = {
source: '',
id: undefined,
};
const tmpFeatureState = {};
const tmpFeatureState: any = {};
for (let i = 0; i < featureCollection.features.length; i++) {
const feature = featureCollection.features[i];
for (let j = 0; j < dynamicStyleProps.length; j++) {
const dynamicStyleProp = dynamicStyleProps[j];
const name = dynamicStyleProp.getField().getName();
const name = dynamicStyleProp.getFieldName();
const computedName = getComputedFieldName(dynamicStyleProp.getStyleName(), name);
const rawValue = feature.properties[name];
const rawValue = feature.properties ? feature.properties[name] : undefined;
if (dynamicStyleProp.supportsMbFeatureState()) {
tmpFeatureState[name] = getNumericalMbFeatureStateValue(rawValue); //the same value will be potentially overridden multiple times, if the name remains identical
tmpFeatureState[name] = getNumericalMbFeatureStateValue(rawValue); // the same value will be potentially overridden multiple times, if the name remains identical
} else {
//in practice, a new system property will only be created for:
// in practice, a new system property will only be created for:
// - label text: this requires the value to be formatted first.
// - icon orientation: this is a lay-out property which do not support feature-state (but we're still coercing to a number)
@ -533,7 +632,7 @@ export class VectorStyle extends AbstractStyle {
? getNumericalMbFeatureStateValue(rawValue)
: dynamicStyleProp.formatField(rawValue);
feature.properties[computedName] = formattedValue;
if (feature.properties) feature.properties[computedName] = formattedValue;
}
}
tmpFeatureIdentifier.source = mbSourceId;
@ -541,10 +640,10 @@ export class VectorStyle extends AbstractStyle {
mbMap.setFeatureState(tmpFeatureIdentifier, tmpFeatureState);
}
//returns boolean indicating if styles do not support feature-state and some values are stored in geojson properties
//this return-value is used in an optimization for style-updates with mapbox-gl.
//`true` indicates the entire data needs to reset on the source (otherwise the style-rules will not be reapplied)
//`false` indicates the data does not need to be reset on the store, because styles are re-evaluated if they use featureState
// returns boolean indicating if styles do not support feature-state and some values are stored in geojson properties
// this return-value is used in an optimization for style-updates with mapbox-gl.
// `true` indicates the entire data needs to reset on the source (otherwise the style-rules will not be reapplied)
// `false` indicates the data does not need to be reset on the store, because styles are re-evaluated if they use featureState
return dynamicStyleProps.some((dynamicStyleProp) => !dynamicStyleProp.supportsMbFeatureState());
}
@ -552,23 +651,49 @@ export class VectorStyle extends AbstractStyle {
return !this._symbolizeAsStyleProperty.isSymbolizedAsIcon();
}
setMBPaintProperties({ alpha, mbMap, fillLayerId, lineLayerId }) {
setMBPaintProperties({
alpha,
mbMap,
fillLayerId,
lineLayerId,
}: {
alpha: number;
mbMap: MbMap;
fillLayerId: string;
lineLayerId: string;
}) {
this._fillColorStyleProperty.syncFillColorWithMb(fillLayerId, mbMap, alpha);
this._lineColorStyleProperty.syncLineColorWithMb(lineLayerId, mbMap, alpha);
this._lineWidthStyleProperty.syncLineWidthWithMb(lineLayerId, mbMap);
}
setMBPaintPropertiesForPoints({ alpha, mbMap, pointLayerId }) {
setMBPaintPropertiesForPoints({
alpha,
mbMap,
pointLayerId,
}: {
alpha: number;
mbMap: MbMap;
pointLayerId: string;
}) {
this._fillColorStyleProperty.syncCircleColorWithMb(pointLayerId, mbMap, alpha);
this._lineColorStyleProperty.syncCircleStrokeWithMb(pointLayerId, mbMap, alpha);
const hasNoRadius =
!this._iconSizeStyleProperty.isDynamic() &&
this._iconSizeStyleProperty.getOptions().size === 0;
(this._iconSizeStyleProperty as StaticSizeProperty).getOptions().size === 0;
this._lineWidthStyleProperty.syncCircleStrokeWidthWithMb(pointLayerId, mbMap, hasNoRadius);
this._iconSizeStyleProperty.syncCircleRadiusWithMb(pointLayerId, mbMap, hasNoRadius);
this._iconSizeStyleProperty.syncCircleRadiusWithMb(pointLayerId, mbMap);
}
setMBPropertiesForLabelText({ alpha, mbMap, textLayerId }) {
setMBPropertiesForLabelText({
alpha,
mbMap,
textLayerId,
}: {
alpha: number;
mbMap: MbMap;
textLayerId: string;
}) {
mbMap.setLayoutProperty(textLayerId, 'icon-allow-overlap', true);
mbMap.setLayoutProperty(textLayerId, 'text-allow-overlap', true);
this._labelStyleProperty.syncTextFieldWithMb(textLayerId, mbMap);
@ -578,7 +703,15 @@ export class VectorStyle extends AbstractStyle {
this._labelBorderColorStyleProperty.syncLabelBorderColorWithMb(textLayerId, mbMap);
}
setMBSymbolPropertiesForPoints({ mbMap, symbolLayerId, alpha }) {
setMBSymbolPropertiesForPoints({
mbMap,
symbolLayerId,
alpha,
}: {
alpha: number;
mbMap: MbMap;
symbolLayerId: string;
}) {
mbMap.setLayoutProperty(symbolLayerId, 'icon-ignore-placement', true);
mbMap.setPaintProperty(symbolLayerId, 'icon-opacity', alpha);
@ -595,34 +728,41 @@ export class VectorStyle extends AbstractStyle {
this._iconOrientationProperty.syncIconRotationWithMb(symbolLayerId, mbMap);
}
_makeField(fieldDescriptor) {
_makeField(fieldDescriptor?: StylePropertyField) {
if (!fieldDescriptor || !fieldDescriptor.name) {
return null;
}
//fieldDescriptor.label is ignored. This is essentially cruft duplicating label-info from the metric-selection
//Ignore this custom label
// fieldDescriptor.label is ignored. This is essentially cruft duplicating label-info from the metric-selection
// Ignore this custom label
if (fieldDescriptor.origin === FIELD_ORIGIN.SOURCE) {
return this._source.getFieldByName(fieldDescriptor.name);
} else if (fieldDescriptor.origin === FIELD_ORIGIN.JOIN) {
const join = this._layer.getValidJoins().find((join) => {
const targetJoin = this._layer.getValidJoins().find((join) => {
return join.getRightJoinSource().hasMatchingMetricField(fieldDescriptor.name);
});
return join ? join.getRightJoinSource().getMetricFieldForName(fieldDescriptor.name) : null;
return targetJoin
? targetJoin.getRightJoinSource().getMetricFieldForName(fieldDescriptor.name)
: null;
} else {
throw new Error(`Unknown origin-type ${fieldDescriptor.origin}`);
}
}
_makeSizeProperty(descriptor, styleName, isSymbolizedAsIcon) {
_makeSizeProperty(
descriptor: SizeStylePropertyDescriptor | undefined,
styleName: VECTOR_STYLES,
isSymbolizedAsIcon: boolean
) {
if (!descriptor || !descriptor.options) {
return new StaticSizeProperty({ size: 0 }, styleName);
} else if (descriptor.type === StaticStyleProperty.type) {
return new StaticSizeProperty(descriptor.options, styleName);
return new StaticSizeProperty(descriptor.options as SizeStaticOptions, styleName);
} else if (descriptor.type === DynamicStyleProperty.type) {
const field = this._makeField(descriptor.options.field);
const options = descriptor.options as SizeDynamicOptions;
const field = this._makeField(options.field);
return new DynamicSizeProperty(
descriptor.options,
options,
styleName,
field,
this._layer,
@ -634,15 +774,19 @@ export class VectorStyle extends AbstractStyle {
}
}
_makeColorProperty(descriptor, styleName) {
_makeColorProperty(
descriptor: ColorStylePropertyDescriptor | undefined,
styleName: VECTOR_STYLES
) {
if (!descriptor || !descriptor.options) {
return new StaticColorProperty({ color: null }, styleName);
return new StaticColorProperty({ color: '' }, styleName);
} else if (descriptor.type === StaticStyleProperty.type) {
return new StaticColorProperty(descriptor.options, styleName);
return new StaticColorProperty(descriptor.options as ColorStaticOptions, styleName);
} else if (descriptor.type === DynamicStyleProperty.type) {
const field = this._makeField(descriptor.options.field);
const options = descriptor.options as ColorDynamicOptions;
const field = this._makeField(options.field);
return new DynamicColorProperty(
descriptor.options,
options,
styleName,
field,
this._layer,
@ -653,15 +797,22 @@ export class VectorStyle extends AbstractStyle {
}
}
_makeOrientationProperty(descriptor, styleName) {
_makeOrientationProperty(
descriptor: OrientationStylePropertyDescriptor | undefined,
styleName: VECTOR_STYLES
) {
if (!descriptor || !descriptor.options) {
return new StaticOrientationProperty({ orientation: 0 }, styleName);
} else if (descriptor.type === StaticStyleProperty.type) {
return new StaticOrientationProperty(descriptor.options, styleName);
return new StaticOrientationProperty(
descriptor.options as OrientationStaticOptions,
styleName
);
} else if (descriptor.type === DynamicStyleProperty.type) {
const field = this._makeField(descriptor.options.field);
const options = descriptor.options as OrientationDynamicOptions;
const field = this._makeField(options.field);
return new DynamicOrientationProperty(
descriptor.options,
options,
styleName,
field,
this._layer,
@ -672,15 +823,19 @@ export class VectorStyle extends AbstractStyle {
}
}
_makeLabelProperty(descriptor) {
_makeLabelProperty(descriptor?: LabelStylePropertyDescriptor) {
if (!descriptor || !descriptor.options) {
return new StaticTextProperty({ value: '' }, VECTOR_STYLES.LABEL_TEXT);
} else if (descriptor.type === StaticStyleProperty.type) {
return new StaticTextProperty(descriptor.options, VECTOR_STYLES.LABEL_TEXT);
return new StaticTextProperty(
descriptor.options as LabelStaticOptions,
VECTOR_STYLES.LABEL_TEXT
);
} else if (descriptor.type === DynamicStyleProperty.type) {
const field = this._makeField(descriptor.options.field);
const options = descriptor.options as LabelDynamicOptions;
const field = this._makeField(options.field);
return new DynamicTextProperty(
descriptor.options,
options,
VECTOR_STYLES.LABEL_TEXT,
field,
this._layer,
@ -691,15 +846,16 @@ export class VectorStyle extends AbstractStyle {
}
}
_makeIconProperty(descriptor) {
_makeIconProperty(descriptor?: IconStylePropertyDescriptor) {
if (!descriptor || !descriptor.options) {
return new StaticIconProperty({ value: DEFAULT_ICON }, VECTOR_STYLES.ICON);
} else if (descriptor.type === StaticStyleProperty.type) {
return new StaticIconProperty(descriptor.options, VECTOR_STYLES.ICON);
return new StaticIconProperty(descriptor.options as IconStaticOptions, VECTOR_STYLES.ICON);
} else if (descriptor.type === DynamicStyleProperty.type) {
const field = this._makeField(descriptor.options.field);
const options = descriptor.options as IconDynamicOptions;
const field = this._makeField(options.field);
return new DynamicIconProperty(
descriptor.options,
options,
VECTOR_STYLES.ICON,
field,
this._layer,

View file

@ -9,7 +9,7 @@ import React from 'react';
import { shallow } from 'enzyme';
import { AbstractLayer, ILayer } from '../../../../../../classes/layers/layer';
import { AbstractSource, ISource } from '../../../../../../classes/sources/source';
import { AbstractStyle, IStyle } from '../../../../../../classes/styles/style';
import { IStyle } from '../../../../../../classes/styles/style';
import { TOCEntryActionsPopover } from './toc_entry_actions_popover';
@ -17,7 +17,15 @@ let supportsFitToBounds: boolean;
class MockSource extends AbstractSource implements ISource {}
class MockStyle extends AbstractStyle implements IStyle {}
class MockStyle implements IStyle {
renderEditor() {
return null;
}
getType() {
return 'mockStyle';
}
}
class LayerMock extends AbstractLayer implements ILayer {
constructor() {
@ -25,7 +33,7 @@ class LayerMock extends AbstractLayer implements ILayer {
type: 'mySourceType',
};
const source = new MockSource(sourceDescriptor);
const style = new MockStyle({ type: 'myStyleType' });
const style = new MockStyle();
const layerDescriptor = {
id: 'testLayer',
sourceDescriptor,

View file

@ -10609,7 +10609,6 @@
"xpack.maps.style.customColorPaletteLabel": "カスタムカラーパレット",
"xpack.maps.style.customColorRampLabel": "カスタマカラーランプ",
"xpack.maps.style.fieldSelect.OriginLabel": "{fieldOrigin} からのフィールド",
"xpack.maps.style.heatmap.displayNameLabel": "ヒートマップスタイル",
"xpack.maps.style.heatmap.resolutionStyleErrorMessage": "解像度パラメーターが認識されません: {resolution}",
"xpack.maps.styles.categorical.otherCategoryLabel": "その他",
"xpack.maps.styles.color.staticDynamicSelect.staticLabel": "塗りつぶし",

View file

@ -10612,7 +10612,6 @@
"xpack.maps.style.customColorPaletteLabel": "定制调色板",
"xpack.maps.style.customColorRampLabel": "定制颜色渐变",
"xpack.maps.style.fieldSelect.OriginLabel": "来自 {fieldOrigin} 的字段",
"xpack.maps.style.heatmap.displayNameLabel": "热图样式",
"xpack.maps.style.heatmap.resolutionStyleErrorMessage": "无法识别分辨率参数:{resolution}",
"xpack.maps.styles.categorical.otherCategoryLabel": "其他",
"xpack.maps.styles.color.staticDynamicSelect.staticLabel": "纯色",