From bd4c3adc4da0614021ecfb3ea29b46539778fcc9 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Wed, 11 Mar 2020 16:16:25 -0600 Subject: [PATCH] [Maps] Add UI to disable style meta and get top categories from current features (#59707) (#59933) * rough start * remove unused files * get everything working * add style options types * convert DynmaicStyleProperty to TS * limit scope of PR * CategoricalFieldMetaPopover * update label and move functions to IStyleProperty interface * fix ts lint errors * replace unknown with IJoin now that its available * remove duplicate import * review feedback Co-authored-by: Elastic Machine --- .../legacy/plugins/maps/common/constants.ts | 15 +- .../style_property_descriptor_types.d.ts | 123 +++++++++++++++++ .../public/layers/sources/vector_source.d.ts | 2 + .../categorical_field_meta_popover.tsx | 43 ++++++ .../field_meta/field_meta_popover.tsx | 64 +++++++++ .../field_meta/ordinal_field_meta_popover.tsx | 93 +++++++++++++ .../vector_style_label_border_size_editor.js | 3 +- .../ordinal_field_meta_options_popover.js | 130 ------------------ .../vector/components/vector_style_editor.js | 7 +- .../properties/dynamic_color_property.js | 2 +- .../dynamic_orientation_property.js | 2 +- .../properties/dynamic_size_property.js | 4 +- .../properties/dynamic_style_property.d.ts | 32 +++++ .../properties/dynamic_style_property.js | 33 +++-- .../properties/dynamic_text_property.js | 2 +- .../properties/label_border_size_property.js | 3 +- .../vector/properties/style_property.js | 55 -------- .../vector/properties/style_property.ts | 87 ++++++++++++ .../layers/styles/vector/vector_style.js | 4 +- .../styles/vector/vector_style_defaults.js | 12 +- .../maps/public/layers/vector_layer.d.ts | 10 +- 21 files changed, 506 insertions(+), 220 deletions(-) create mode 100644 x-pack/legacy/plugins/maps/common/style_property_descriptor_types.d.ts create mode 100644 x-pack/legacy/plugins/maps/public/layers/styles/vector/components/field_meta/categorical_field_meta_popover.tsx create mode 100644 x-pack/legacy/plugins/maps/public/layers/styles/vector/components/field_meta/field_meta_popover.tsx create mode 100644 x-pack/legacy/plugins/maps/public/layers/styles/vector/components/field_meta/ordinal_field_meta_popover.tsx delete mode 100644 x-pack/legacy/plugins/maps/public/layers/styles/vector/components/ordinal_field_meta_options_popover.js create mode 100644 x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.d.ts delete mode 100644 x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/style_property.js create mode 100644 x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/style_property.ts diff --git a/x-pack/legacy/plugins/maps/common/constants.ts b/x-pack/legacy/plugins/maps/common/constants.ts index a4afae0b9e077..a73e13cc948c8 100644 --- a/x-pack/legacy/plugins/maps/common/constants.ts +++ b/x-pack/legacy/plugins/maps/common/constants.ts @@ -167,9 +167,16 @@ export const COLOR_PALETTE_MAX_SIZE = 10; export const CATEGORICAL_DATA_TYPES = ['string', 'ip', 'boolean']; export const ORDINAL_DATA_TYPES = ['number', 'date']; -export const SYMBOLIZE_AS_TYPES = { - CIRCLE: 'circle', - ICON: 'icon', -}; +export enum SYMBOLIZE_AS_TYPES { + CIRCLE = 'circle', + ICON = 'icon', +} + +export enum LABEL_BORDER_SIZES { + NONE = 'NONE', + SMALL = 'SMALL', + MEDIUM = 'MEDIUM', + LARGE = 'LARGE', +} export const DEFAULT_ICON = 'airfield'; diff --git a/x-pack/legacy/plugins/maps/common/style_property_descriptor_types.d.ts b/x-pack/legacy/plugins/maps/common/style_property_descriptor_types.d.ts new file mode 100644 index 0000000000000..8254055cf40b9 --- /dev/null +++ b/x-pack/legacy/plugins/maps/common/style_property_descriptor_types.d.ts @@ -0,0 +1,123 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +/* eslint-disable @typescript-eslint/consistent-type-definitions */ + +import { FIELD_ORIGIN, LABEL_BORDER_SIZES, SYMBOLIZE_AS_TYPES } from './constants'; + +// Non-static/dynamic options +export type SymbolizeAsOptions = { + value: SYMBOLIZE_AS_TYPES; +}; + +export type LabelBorderSizeOptions = { + size: LABEL_BORDER_SIZES; +}; + +// Static/dynamic options + +export type FieldMetaOptions = { + isEnabled: boolean; + sigma?: number; +}; + +export type StylePropertyField = { + name: string; + origin: FIELD_ORIGIN; +}; + +export type OrdinalColorStop = { + stop: number; + color: string; +}; + +export type CategoryColorStop = { + stop: string | null; + color: string; +}; + +export type IconStop = { + stop: string | null; + icon: string; +}; + +export type ColorDynamicOptions = { + // ordinal color properties + color: string; // TODO move color category ramps to constants and make ENUM type + customColorRamp?: OrdinalColorStop[]; + useCustomColorRamp?: boolean; + + // category color properties + colorCategory?: string; // TODO move color category palettes to constants and make ENUM type + customColorPalette?: CategoryColorStop[]; + useCustomColorPalette?: boolean; + + field?: StylePropertyField; + fieldMetaOptions: FieldMetaOptions; +}; + +export type ColorStaticOptions = { + color: string; +}; + +export type IconDynamicOptions = { + iconPaletteId?: string; + customIconStops?: IconStop[]; + useCustomIconMap?: boolean; + field?: StylePropertyField; + fieldMetaOptions: FieldMetaOptions; +}; + +export type IconStaticOptions = { + value: string; // icon id +}; + +export type LabelDynamicOptions = { + field: StylePropertyField; // field containing label value +}; + +export type LabelStaticOptions = { + value: string; // static label text +}; + +export type OrientationDynamicOptions = { + field?: StylePropertyField; + fieldMetaOptions: FieldMetaOptions; +}; + +export type OrientationStaticOptions = { + orientation: number; +}; + +export type SizeDynamicOptions = { + minSize: number; + maxSize: number; + field?: StylePropertyField; + fieldMetaOptions: FieldMetaOptions; +}; + +export type SizeStaticOptions = { + size: number; +}; + +export type StylePropertyOptions = + | LabelBorderSizeOptions + | SymbolizeAsOptions + | DynamicStylePropertyOptions + | StaticStylePropertyOptions; + +export type StaticStylePropertyOptions = + | ColorStaticOptions + | IconStaticOptions + | LabelStaticOptions + | OrientationStaticOptions + | SizeStaticOptions; + +export type DynamicStylePropertyOptions = + | ColorDynamicOptions + | IconDynamicOptions + | LabelDynamicOptions + | OrientationDynamicOptions + | SizeDynamicOptions; diff --git a/x-pack/legacy/plugins/maps/public/layers/sources/vector_source.d.ts b/x-pack/legacy/plugins/maps/public/layers/sources/vector_source.d.ts index f6f4dff88bdda..5fa8b28aa837b 100644 --- a/x-pack/legacy/plugins/maps/public/layers/sources/vector_source.d.ts +++ b/x-pack/legacy/plugins/maps/public/layers/sources/vector_source.d.ts @@ -28,6 +28,7 @@ export interface IVectorSource extends ISource { ): Promise; getFields(): Promise; + getFieldByName(fieldName: string): IField; } export class AbstractVectorSource extends AbstractSource { @@ -38,4 +39,5 @@ export class AbstractVectorSource extends AbstractSource { ): Promise; getFields(): Promise; + getFieldByName(fieldName: string): IField; } diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/field_meta/categorical_field_meta_popover.tsx b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/field_meta/categorical_field_meta_popover.tsx new file mode 100644 index 0000000000000..9aec7ece45f36 --- /dev/null +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/field_meta/categorical_field_meta_popover.tsx @@ -0,0 +1,43 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +/* eslint-disable @typescript-eslint/consistent-type-definitions */ + +import _ from 'lodash'; +import React from 'react'; +import { EuiFormRow, EuiSwitch, EuiSwitchEvent } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FieldMetaPopover } from './field_meta_popover'; +import { IDynamicStyleProperty } from '../../properties/dynamic_style_property'; +import { FieldMetaOptions } from '../../../../../../common/style_property_descriptor_types'; + +type Props = { + styleProperty: IDynamicStyleProperty; + onChange: (fieldMetaOptions: FieldMetaOptions) => void; +}; + +export function CategoricalFieldMetaPopover(props: Props) { + const onIsEnabledChange = (event: EuiSwitchEvent) => { + props.onChange({ + ...props.styleProperty.getFieldMetaOptions(), + isEnabled: event.target.checked, + }); + }; + + return ( + + + + + + ); +} diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/field_meta/field_meta_popover.tsx b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/field_meta/field_meta_popover.tsx new file mode 100644 index 0000000000000..dfd98937135e1 --- /dev/null +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/field_meta/field_meta_popover.tsx @@ -0,0 +1,64 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +/* eslint-disable @typescript-eslint/consistent-type-definitions */ + +import React, { Component, ReactElement } from 'react'; +import { EuiButtonIcon, EuiPopover } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +type Props = { + children: ReactElement; +}; + +type State = { + isPopoverOpen: boolean; +}; + +export class FieldMetaPopover extends Component { + state = { + isPopoverOpen: false, + }; + + _togglePopover = () => { + this.setState({ + isPopoverOpen: !this.state.isPopoverOpen, + }); + }; + + _closePopover = () => { + this.setState({ + isPopoverOpen: false, + }); + }; + + _renderButton() { + return ( + + ); + } + + render() { + return ( + + {this.props.children} + + ); + } +} diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/field_meta/ordinal_field_meta_popover.tsx b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/field_meta/ordinal_field_meta_popover.tsx new file mode 100644 index 0000000000000..0980f7df74e3c --- /dev/null +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/field_meta/ordinal_field_meta_popover.tsx @@ -0,0 +1,93 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +/* eslint-disable @typescript-eslint/consistent-type-definitions */ + +import _ from 'lodash'; +import React, { ChangeEvent, Fragment, MouseEvent } from 'react'; +import { EuiFormRow, EuiRange, EuiSwitch, EuiSwitchEvent } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +// @ts-ignore +import { DEFAULT_SIGMA, VECTOR_STYLES } from '../../vector_style_defaults'; +import { FieldMetaPopover } from './field_meta_popover'; +import { IDynamicStyleProperty } from '../../properties/dynamic_style_property'; +import { FieldMetaOptions } from '../../../../../../common/style_property_descriptor_types'; + +function getIsEnableToggleLabel(styleName: string) { + switch (styleName) { + case VECTOR_STYLES.FILL_COLOR: + case VECTOR_STYLES.LINE_COLOR: + return i18n.translate('xpack.maps.styles.fieldMetaOptions.isEnabled.colorLabel', { + defaultMessage: 'Calculate color ramp range from indices', + }); + case VECTOR_STYLES.LINE_WIDTH: + return i18n.translate('xpack.maps.styles.fieldMetaOptions.isEnabled.widthLabel', { + defaultMessage: 'Calculate border width range from indices', + }); + case VECTOR_STYLES.ICON_SIZE: + return i18n.translate('xpack.maps.styles.fieldMetaOptions.isEnabled.sizeLabel', { + defaultMessage: 'Calculate symbol size range from indices', + }); + default: + return i18n.translate('xpack.maps.styles.fieldMetaOptions.isEnabled.defaultLabel', { + defaultMessage: 'Calculate symbolization range from indices', + }); + } +} + +type Props = { + styleProperty: IDynamicStyleProperty; + onChange: (fieldMetaOptions: FieldMetaOptions) => void; +}; + +export function OrdinalFieldMetaPopover(props: Props) { + const onIsEnabledChange = (event: EuiSwitchEvent) => { + props.onChange({ + ...props.styleProperty.getFieldMetaOptions(), + isEnabled: event.target.checked, + }); + }; + + const onSigmaChange = (event: ChangeEvent | MouseEvent) => { + props.onChange({ + ...props.styleProperty.getFieldMetaOptions(), + sigma: parseInt(event.currentTarget.value, 10), + }); + }; + + return ( + + + + + + + + + + + + ); +} diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/label/vector_style_label_border_size_editor.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/label/vector_style_label_border_size_editor.js index 04bb800eb1ecf..a65065bbb2032 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/label/vector_style_label_border_size_editor.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/label/vector_style_label_border_size_editor.js @@ -7,9 +7,10 @@ import React from 'react'; import { EuiFormRow, EuiSelect, EuiToolTip } from '@elastic/eui'; -import { LABEL_BORDER_SIZES, VECTOR_STYLES } from '../../vector_style_defaults'; +import { VECTOR_STYLES } from '../../vector_style_defaults'; import { getVectorStyleLabel, getDisabledByMessage } from '../get_vector_style_label'; import { i18n } from '@kbn/i18n'; +import { LABEL_BORDER_SIZES } from '../../../../../../common/constants'; const options = [ { diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/ordinal_field_meta_options_popover.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/ordinal_field_meta_options_popover.js deleted file mode 100644 index dee333f163960..0000000000000 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/ordinal_field_meta_options_popover.js +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { Component, Fragment } from 'react'; -import { EuiButtonIcon, EuiFormRow, EuiPopover, EuiRange, EuiSwitch } from '@elastic/eui'; -import { VECTOR_STYLES } from '../vector_style_defaults'; -import { i18n } from '@kbn/i18n'; - -function getIsEnableToggleLabel(styleName) { - switch (styleName) { - case VECTOR_STYLES.FILL_COLOR: - case VECTOR_STYLES.LINE_COLOR: - return i18n.translate('xpack.maps.styles.fieldMetaOptions.isEnabled.colorLabel', { - defaultMessage: 'Calculate color ramp range from indices', - }); - case VECTOR_STYLES.LINE_WIDTH: - return i18n.translate('xpack.maps.styles.fieldMetaOptions.isEnabled.widthLabel', { - defaultMessage: 'Calculate border width range from indices', - }); - case VECTOR_STYLES.ICON_SIZE: - return i18n.translate('xpack.maps.styles.fieldMetaOptions.isEnabled.sizeLabel', { - defaultMessage: 'Calculate symbol size range from indices', - }); - default: - return i18n.translate('xpack.maps.styles.fieldMetaOptions.isEnabled.defaultLabel', { - defaultMessage: 'Calculate symbolization range from indices', - }); - } -} - -export class OrdinalFieldMetaOptionsPopover extends Component { - state = { - isPopoverOpen: false, - }; - - _togglePopover = () => { - this.setState({ - isPopoverOpen: !this.state.isPopoverOpen, - }); - }; - - _closePopover = () => { - this.setState({ - isPopoverOpen: false, - }); - }; - - _onIsEnabledChange = event => { - this.props.onChange({ - ...this.props.styleProperty.getFieldMetaOptions(), - isEnabled: event.target.checked, - }); - }; - - _onSigmaChange = event => { - this.props.onChange({ - ...this.props.styleProperty.getFieldMetaOptions(), - sigma: event.target.value, - }); - }; - - _renderButton() { - return ( - - ); - } - - _renderContent() { - return ( - - - - - - - - - - ); - } - - render() { - if (!this.props.styleProperty.supportsFieldMeta()) { - return null; - } - - return ( - - {this._renderContent()} - - ); - } -} diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector_style_editor.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector_style_editor.js index 7ad36bd2ae33d..8e05cf287efa6 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector_style_editor.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/components/vector_style_editor.js @@ -18,7 +18,6 @@ import { OrientationEditor } from './orientation/orientation_editor'; import { getDefaultDynamicProperties, getDefaultStaticProperties, - LABEL_BORDER_SIZES, VECTOR_STYLES, } from '../vector_style_defaults'; import { DEFAULT_FILL_COLORS, DEFAULT_LINE_COLORS } from '../../color_utils'; @@ -26,7 +25,11 @@ import { VECTOR_SHAPE_TYPES } from '../../../sources/vector_feature_types'; import { i18n } from '@kbn/i18n'; import { EuiSpacer, EuiButtonGroup, EuiFormRow, EuiSwitch } from '@elastic/eui'; -import { CATEGORICAL_DATA_TYPES, ORDINAL_DATA_TYPES } from '../../../../../common/constants'; +import { + CATEGORICAL_DATA_TYPES, + ORDINAL_DATA_TYPES, + LABEL_BORDER_SIZES, +} from '../../../../../common/constants'; export class VectorStyleEditor extends Component { state = { diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_color_property.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_color_property.js index 9404c2da3d274..9163901b49213 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_color_property.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_color_property.js @@ -84,7 +84,7 @@ export class DynamicColorProperty extends DynamicStyleProperty { return this._options.useCustomColorRamp; } - supportsFeatureState() { + supportsMbFeatureState() { return true; } diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_orientation_property.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_orientation_property.js index 1d2457142c082..81b476b717c94 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_orientation_property.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_orientation_property.js @@ -22,7 +22,7 @@ export class DynamicOrientationProperty extends DynamicStyleProperty { } } - supportsFeatureState() { + supportsMbFeatureState() { return false; } diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_size_property.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_size_property.js index 77f2d09982291..97bb252b3da1d 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_size_property.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_size_property.js @@ -48,7 +48,7 @@ export class DynamicSizeProperty extends DynamicStyleProperty { this._isSymbolizedAsIcon = isSymbolizedAsIcon; } - supportsFeatureState() { + supportsMbFeatureState() { // mb style "icon-size" does not support feature state if (this.getStyleName() === VECTOR_STYLES.ICON_SIZE && this._isSymbolizedAsIcon) { return false; @@ -124,7 +124,7 @@ export class DynamicSizeProperty extends DynamicStyleProperty { } _getMbDataDrivenSize({ targetName, minSize, maxSize }) { - const lookup = this.supportsFeatureState() ? 'feature-state' : 'get'; + const lookup = this.supportsMbFeatureState() ? 'feature-state' : 'get'; return [ 'interpolate', ['linear'], diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.d.ts b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.d.ts new file mode 100644 index 0000000000000..f4c487b28757e --- /dev/null +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.d.ts @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +/* eslint-disable @typescript-eslint/consistent-type-definitions */ + +import { IStyleProperty } from './style_property'; +import { FIELD_ORIGIN } from '../../../../../common/constants'; +import { FieldMetaOptions } from '../../../../../common/style_property_descriptor_types'; +import { IField } from '../../../fields/field'; +import { IVectorLayer } from '../../../vector_layer'; +import { IVectorSource } from '../../../sources/vector_source'; +import { CategoryFieldMeta, RangeFieldMeta } from '../../../../../common/descriptor_types'; + +export interface IDynamicStyleProperty extends IStyleProperty { + getFieldMetaOptions(): FieldMetaOptions; + getField(): IField | undefined; + getFieldName(): string; + getFieldOrigin(): FIELD_ORIGIN | undefined; + getComputedFieldName(): string | undefined; + getRangeFieldMeta(): RangeFieldMeta; + getCategoryFieldMeta(): CategoryFieldMeta; + isFieldMetaEnabled(): boolean; + supportsFieldMeta(): boolean; + getFieldMetaRequest(): Promise; + supportsMbFeatureState(): boolean; + pluckOrdinalStyleMetaFromFeatures(features: unknown[]): RangeFieldMeta; + pluckCategoricalStyleMetaFromFeatures(features: unknown[]): CategoryFieldMeta; + pluckOrdinalStyleMetaFromFieldMetaData(fieldMetaData: unknown): RangeFieldMeta; + pluckCategoricalStyleMetaFromFieldMetaData(fieldMetaData: unknown): CategoryFieldMeta; +} diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.js index 7b94e58f0e7d4..030d3a2a1ef87 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.js @@ -17,7 +17,8 @@ import { scaleValue, getComputedFieldName } from '../style_util'; import React from 'react'; import { OrdinalLegend } from './components/ordinal_legend'; import { CategoricalLegend } from './components/categorical_legend'; -import { OrdinalFieldMetaOptionsPopover } from '../components/ordinal_field_meta_options_popover'; +import { OrdinalFieldMetaPopover } from '../components/field_meta/ordinal_field_meta_popover'; +import { CategoricalFieldMetaPopover } from '../components/field_meta/categorical_field_meta_popover'; export class DynamicStyleProperty extends AbstractStyleProperty { static type = STYLE_TYPE.DYNAMIC; @@ -31,7 +32,7 @@ export class DynamicStyleProperty extends AbstractStyleProperty { getValueSuggestions = query => { const field = this.getField(); - const fieldSource = this.getFieldSource(); + const fieldSource = this._getFieldSource(); return fieldSource && field ? fieldSource.getValueSuggestions(field, query) : []; }; @@ -52,6 +53,10 @@ export class DynamicStyleProperty extends AbstractStyleProperty { const fieldName = this.getFieldName(); const rangeFieldMetaFromLocalFeatures = styleMeta.getRangeFieldMetaDescriptor(fieldName); + if (!this.isFieldMetaEnabled()) { + return rangeFieldMetaFromLocalFeatures; + } + const dataRequestId = this._getStyleMetaDataRequestId(fieldName); if (!dataRequestId) { return rangeFieldMetaFromLocalFeatures; @@ -71,28 +76,32 @@ export class DynamicStyleProperty extends AbstractStyleProperty { const style = this._layer.getStyle(); const styleMeta = style.getStyleMeta(); const fieldName = this.getFieldName(); - const rangeFieldMetaFromLocalFeatures = styleMeta.getCategoryFieldMetaDescriptor(fieldName); + const categoryFieldMetaFromLocalFeatures = styleMeta.getCategoryFieldMetaDescriptor(fieldName); + + if (!this.isFieldMetaEnabled()) { + return categoryFieldMetaFromLocalFeatures; + } const dataRequestId = this._getStyleMetaDataRequestId(fieldName); if (!dataRequestId) { - return rangeFieldMetaFromLocalFeatures; + return categoryFieldMetaFromLocalFeatures; } const styleMetaDataRequest = this._layer.findDataRequestById(dataRequestId); if (!styleMetaDataRequest || !styleMetaDataRequest.hasData()) { - return rangeFieldMetaFromLocalFeatures; + return categoryFieldMetaFromLocalFeatures; } const data = styleMetaDataRequest.getData(); const rangeFieldMeta = this.pluckCategoricalStyleMetaFromFieldMetaData(data); - return rangeFieldMeta ? rangeFieldMeta : rangeFieldMetaFromLocalFeatures; + return rangeFieldMeta ? rangeFieldMeta : categoryFieldMetaFromLocalFeatures; } getField() { return this._field; } - getFieldSource() { + _getFieldSource() { return this._field ? this._field.getSource() : null; } @@ -160,7 +169,7 @@ export class DynamicStyleProperty extends AbstractStyleProperty { } } - supportsFeatureState() { + supportsMbFeatureState() { return true; } @@ -338,12 +347,14 @@ export class DynamicStyleProperty extends AbstractStyleProperty { } renderFieldMetaPopover(onFieldMetaOptionsChange) { - if (!this.isOrdinal() || !this.supportsFieldMeta()) { + if (!this.supportsFieldMeta()) { return null; } - return ( - + return this.isCategorical() ? ( + + ) : ( + ); } } diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_text_property.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_text_property.js index 6a40a80a1a7a6..c561ec128dec5 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_text_property.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/dynamic_text_property.js @@ -25,7 +25,7 @@ export class DynamicTextProperty extends DynamicStyleProperty { return false; } - supportsFeatureState() { + supportsMbFeatureState() { return false; } diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/label_border_size_property.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/label_border_size_property.js index e08c2875c310e..7119b659c1232 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/label_border_size_property.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/label_border_size_property.js @@ -6,7 +6,8 @@ import _ from 'lodash'; import { AbstractStyleProperty } from './style_property'; -import { DEFAULT_LABEL_SIZE, LABEL_BORDER_SIZES } from '../vector_style_defaults'; +import { DEFAULT_LABEL_SIZE } from '../vector_style_defaults'; +import { LABEL_BORDER_SIZES } from '../../../../../common/constants'; const SMALL_SIZE = 1 / 16; const MEDIUM_SIZE = 1 / 8; diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/style_property.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/style_property.js deleted file mode 100644 index c49fe46664025..0000000000000 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/style_property.js +++ /dev/null @@ -1,55 +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 { getVectorStyleLabel } from '../components/get_vector_style_label'; -export class AbstractStyleProperty { - constructor(options, styleName) { - this._options = options; - this._styleName = styleName; - } - - isDynamic() { - return false; - } - - /** - * Is the style fully defined and usable? (e.g. for rendering, in legend UX, ...) - * Why? during editing, partially-completed descriptors may be added to the layer-descriptor - * e.g. dynamic-fields can have an incomplete state when the field is not yet selected from the drop-down - * @returns {boolean} - */ - isComplete() { - return true; - } - - formatField(value) { - return value; - } - - getStyleName() { - return this._styleName; - } - - getOptions() { - return this._options || {}; - } - - renderRangeLegendHeader() { - return null; - } - - renderLegendDetailRow() { - return null; - } - - renderFieldMetaPopover() { - return null; - } - - getDisplayStyleName() { - return getVectorStyleLabel(this.getStyleName()); - } -} diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/style_property.ts b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/style_property.ts new file mode 100644 index 0000000000000..bba6cdb48e672 --- /dev/null +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/properties/style_property.ts @@ -0,0 +1,87 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +/* eslint-disable @typescript-eslint/consistent-type-definitions */ + +import { ReactElement } from 'react'; +// @ts-ignore +import { getVectorStyleLabel } from '../components/get_vector_style_label'; +import { + FieldMetaOptions, + StylePropertyOptions, +} from '../../../../../common/style_property_descriptor_types'; + +type LegendProps = { + isPointsOnly: boolean; + isLinesOnly: boolean; + symbolId?: string; +}; + +export interface IStyleProperty { + isDynamic(): boolean; + isComplete(): boolean; + formatField(value: string | undefined): string; + getStyleName(): string; + getOptions(): StylePropertyOptions; + renderRangeLegendHeader(): ReactElement | null; + renderLegendDetailRow(legendProps: LegendProps): ReactElement | null; + renderFieldMetaPopover( + onFieldMetaOptionsChange: (fieldMetaOptions: FieldMetaOptions) => void + ): ReactElement | null; + getDisplayStyleName(): string; +} + +export class AbstractStyleProperty implements IStyleProperty { + private _options: StylePropertyOptions; + private _styleName: string; + + constructor(options: StylePropertyOptions, styleName: string) { + this._options = options; + this._styleName = styleName; + } + + isDynamic(): boolean { + return false; + } + + /** + * Is the style fully defined and usable? (e.g. for rendering, in legend UX, ...) + * Why? during editing, partially-completed descriptors may be added to the layer-descriptor + * e.g. dynamic-fields can have an incomplete state when the field is not yet selected from the drop-down + * @returns {boolean} + */ + isComplete(): boolean { + return true; + } + + formatField(value: string | undefined): string { + // eslint-disable-next-line eqeqeq + return value == undefined ? '' : value; + } + + getStyleName(): string { + return this._styleName; + } + + getOptions(): StylePropertyOptions { + return this._options || {}; + } + + renderRangeLegendHeader() { + return null; + } + + renderLegendDetailRow() { + return null; + } + + renderFieldMetaPopover() { + return null; + } + + getDisplayStyleName() { + return getVectorStyleLabel(this.getStyleName()); + } +} diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.js index 528c5a9bfdc85..1c8ff3e205a38 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.js @@ -508,7 +508,7 @@ export class VectorStyle extends AbstractStyle { const name = dynamicStyleProp.getField().getName(); const computedName = getComputedFieldName(dynamicStyleProp.getStyleName(), name); const styleValue = dynamicStyleProp.getMbValue(feature.properties[name]); - if (dynamicStyleProp.supportsFeatureState()) { + if (dynamicStyleProp.supportsMbFeatureState()) { tmpFeatureState[computedName] = styleValue; } else { feature.properties[computedName] = styleValue; @@ -523,7 +523,7 @@ export class VectorStyle extends AbstractStyle { //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.supportsFeatureState()); + return dynamicStyleProps.some(dynamicStyleProp => !dynamicStyleProp.supportsMbFeatureState()); } arePointsSymbolizedAsCircles() { diff --git a/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style_defaults.js b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style_defaults.js index 952f8766a6156..8bc397dd98b56 100644 --- a/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style_defaults.js +++ b/x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style_defaults.js @@ -5,7 +5,7 @@ */ import { VectorStyle } from './vector_style'; -import { DEFAULT_ICON, SYMBOLIZE_AS_TYPES } from '../../../../common/constants'; +import { DEFAULT_ICON, LABEL_BORDER_SIZES, SYMBOLIZE_AS_TYPES } from '../../../../common/constants'; import { COLOR_GRADIENTS, COLOR_PALETTES, @@ -22,13 +22,6 @@ export const DEFAULT_SIGMA = 3; export const DEFAULT_LABEL_SIZE = 14; export const DEFAULT_ICON_SIZE = 6; -export const LABEL_BORDER_SIZES = { - NONE: 'NONE', - SMALL: 'SMALL', - MEDIUM: 'MEDIUM', - LARGE: 'LARGE', -}; - export const VECTOR_STYLES = { SYMBOLIZE_AS: 'symbolizeAs', FILL_COLOR: 'fillColor', @@ -147,6 +140,9 @@ export function getDefaultDynamicProperties() { options: { iconPaletteId: 'filledShapes', field: undefined, + fieldMetaOptions: { + isEnabled: true, + }, }, }, [VECTOR_STYLES.FILL_COLOR]: { diff --git a/x-pack/legacy/plugins/maps/public/layers/vector_layer.d.ts b/x-pack/legacy/plugins/maps/public/layers/vector_layer.d.ts index e3ef744525d63..748b2fd1d782c 100644 --- a/x-pack/legacy/plugins/maps/public/layers/vector_layer.d.ts +++ b/x-pack/legacy/plugins/maps/public/layers/vector_layer.d.ts @@ -8,12 +8,20 @@ import { AbstractLayer } from './layer'; import { IVectorSource } from './sources/vector_source'; import { VectorLayerDescriptor } from '../../common/descriptor_types'; +import { ILayer } from './layer'; +import { IJoin } from './joins/join'; type VectorLayerArguments = { source: IVectorSource; layerDescriptor: VectorLayerDescriptor; }; -export class VectorLayer extends AbstractLayer { +export interface IVectorLayer extends ILayer { + getValidJoins(): IJoin[]; +} + +export class VectorLayer extends AbstractLayer implements IVectorLayer { constructor(options: VectorLayerArguments); + + getValidJoins(): IJoin[]; }