[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:
parent
a4fa73054a
commit
3df47dc66b
|
@ -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;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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())
|
||||
);
|
||||
|
|
|
@ -17,4 +17,6 @@ export class InnerJoin implements IJoin {
|
|||
toDescriptor(): JoinDescriptor;
|
||||
|
||||
getSourceMetaDataRequestId(): string;
|
||||
|
||||
getSourceFormattersDataRequestId(): string;
|
||||
}
|
||||
|
|
|
@ -13,4 +13,6 @@ export interface IJoin {
|
|||
toDescriptor(): JoinDescriptor;
|
||||
|
||||
getSourceMetaDataRequestId(): string;
|
||||
|
||||
getSourceFormattersDataRequestId(): string;
|
||||
}
|
||||
|
|
|
@ -102,6 +102,7 @@ function getClusterStyleDescriptor(
|
|||
},
|
||||
},
|
||||
},
|
||||
isTimeAware: true,
|
||||
};
|
||||
documentStyle
|
||||
.getAllStyleProperties()
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
};
|
|
@ -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();
|
|
@ -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;
|
|
@ -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 [];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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}</>;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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())
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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,
|
|
@ -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,
|
||||
|
|
|
@ -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": "塗りつぶし",
|
||||
|
|
|
@ -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": "纯色",
|
||||
|
|
Loading…
Reference in a new issue