Skip to content

Commit

Permalink
[Maps] Add UI to disable style meta and get top categories from curre…
Browse files Browse the repository at this point in the history
…nt features (#59707)

* 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
  • Loading branch information
nreese authored Mar 11, 2020
1 parent 4e83062 commit e4c4b7f
Show file tree
Hide file tree
Showing 21 changed files with 506 additions and 220 deletions.
15 changes: 11 additions & 4 deletions x-pack/legacy/plugins/maps/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
123 changes: 123 additions & 0 deletions x-pack/legacy/plugins/maps/common/style_property_descriptor_types.d.ts
Original file line number Diff line number Diff line change
@@ -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;
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export interface IVectorSource extends ISource {
): Promise<GeoJsonWithMeta>;

getFields(): Promise<IField[]>;
getFieldByName(fieldName: string): IField;
}

export class AbstractVectorSource extends AbstractSource {
Expand All @@ -38,4 +39,5 @@ export class AbstractVectorSource extends AbstractSource {
): Promise<GeoJsonWithMeta>;

getFields(): Promise<IField[]>;
getFieldByName(fieldName: string): IField;
}
Original file line number Diff line number Diff line change
@@ -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 (
<FieldMetaPopover>
<EuiFormRow display="columnCompressedSwitch">
<EuiSwitch
label={i18n.translate('xpack.maps.styles.fieldMetaOptions.isEnabled.categoricalLabel', {
defaultMessage: 'Get categories from indices',
})}
checked={props.styleProperty.getFieldMetaOptions().isEnabled}
onChange={onIsEnabledChange}
compressed
/>
</EuiFormRow>
</FieldMetaPopover>
);
}
Original file line number Diff line number Diff line change
@@ -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<any>;
};

type State = {
isPopoverOpen: boolean;
};

export class FieldMetaPopover extends Component<Props, State> {
state = {
isPopoverOpen: false,
};

_togglePopover = () => {
this.setState({
isPopoverOpen: !this.state.isPopoverOpen,
});
};

_closePopover = () => {
this.setState({
isPopoverOpen: false,
});
};

_renderButton() {
return (
<EuiButtonIcon
onClick={this._togglePopover}
size="s"
iconType="gear"
aria-label={i18n.translate('xpack.maps.styles.fieldMetaOptions.popoverToggle', {
defaultMessage: 'Field meta options popover toggle',
})}
/>
);
}

render() {
return (
<EuiPopover
id="fieldMetaOptionsPopover"
anchorPosition="leftCenter"
button={this._renderButton()}
isOpen={this.state.isPopoverOpen}
closePopover={this._closePopover}
ownFocus
>
{this.props.children}
</EuiPopover>
);
}
}
Original file line number Diff line number Diff line change
@@ -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<HTMLInputElement> | MouseEvent<HTMLButtonElement>) => {
props.onChange({
...props.styleProperty.getFieldMetaOptions(),
sigma: parseInt(event.currentTarget.value, 10),
});
};

return (
<FieldMetaPopover>
<Fragment>
<EuiFormRow display="columnCompressedSwitch">
<EuiSwitch
label={getIsEnableToggleLabel(props.styleProperty.getStyleName())}
checked={props.styleProperty.getFieldMetaOptions().isEnabled}
onChange={onIsEnabledChange}
compressed
/>
</EuiFormRow>

<EuiFormRow
label={i18n.translate('xpack.maps.styles.fieldMetaOptions.sigmaLabel', {
defaultMessage: 'Sigma',
})}
display="columnCompressed"
>
<EuiRange
min={1}
max={5}
step={0.25}
value={_.get(props.styleProperty.getFieldMetaOptions(), 'sigma', DEFAULT_SIGMA)}
onChange={onSigmaChange}
disabled={!props.styleProperty.getFieldMetaOptions().isEnabled}
showTicks
tickInterval={1}
compressed
/>
</EuiFormRow>
</Fragment>
</FieldMetaPopover>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 = [
{
Expand Down
Loading

0 comments on commit e4c4b7f

Please sign in to comment.