[Maps] fix custom icon palettes UI not being displayed (#71482)

* [Maps] fix custom icon palettes UI not being displayed

* cleanup test

* remove uneeded change to vector style defaults

* fix jest tests

* review feedback

* fix jest tests
This commit is contained in:
Nathan Reese 2020-07-14 15:19:51 -06:00 committed by GitHub
parent 0c87aa506d
commit 34c54ed31b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 428 additions and 278 deletions

View file

@ -95,7 +95,7 @@ export type ColorStylePropertyDescriptor =
| ColorDynamicStylePropertyDescriptor;
export type IconDynamicOptions = {
iconPaletteId?: string;
iconPaletteId: string | null;
customIconStops?: IconStop[];
useCustomIconMap?: boolean;
field?: StylePropertyField;

View file

@ -5,14 +5,9 @@
*/
jest.mock('../../../../kibana_services', () => {
const mockUiSettings = {
get: () => {
return undefined;
},
};
return {
getUiSettings: () => {
return mockUiSettings;
getIsDarkMode() {
return false;
},
};
});

View file

@ -5,14 +5,9 @@
*/
jest.mock('../../../../kibana_services', () => {
const mockUiSettings = {
get: () => {
return undefined;
},
};
return {
getUiSettings: () => {
return mockUiSettings;
getIsDarkMode() {
return false;
},
};
});

View file

@ -8,12 +8,8 @@ import sinon from 'sinon';
jest.mock('../../../kibana_services', () => {
return {
getUiSettings() {
return {
get() {
return false;
},
};
getIsDarkMode() {
return false;
},
};
});

View file

@ -12,7 +12,7 @@ import { UpdateSourceEditor } from './update_source_editor';
import { i18n } from '@kbn/i18n';
import { getDataSourceLabel } from '../../../../common/i18n_getters';
import { SOURCE_TYPES } from '../../../../common/constants';
import { getEmsTileLayerId, getUiSettings } from '../../../kibana_services';
import { getEmsTileLayerId, getIsDarkMode } from '../../../kibana_services';
import { registerSource } from '../source_registry';
export const sourceTitle = i18n.translate('xpack.maps.source.emsTileTitle', {
@ -122,9 +122,8 @@ export class EMSTMSSource extends AbstractTMSSource {
return this._descriptor.id;
}
const isDarkMode = getUiSettings().get('theme:darkMode', false);
const emsTileLayerId = getEmsTileLayerId();
return isDarkMode ? emsTileLayerId.dark : emsTileLayerId.bright;
return getIsDarkMode() ? emsTileLayerId.dark : emsTileLayerId.bright;
}
}

View file

@ -1,100 +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 { EuiSuperSelect, EuiSpacer } from '@elastic/eui';
const CUSTOM_MAP = 'CUSTOM_MAP';
export class StyleMapSelect extends Component {
state = {};
static getDerivedStateFromProps(nextProps, prevState) {
if (nextProps.customMapStops === prevState.prevPropsCustomMapStops) {
return null;
}
return {
prevPropsCustomMapStops: nextProps.customMapStops, // reset tracker to latest value
customMapStops: nextProps.customMapStops, // reset customMapStops to latest value
};
}
_onMapSelect = (selectedValue) => {
const useCustomMap = selectedValue === CUSTOM_MAP;
this.props.onChange({
selectedMapId: useCustomMap ? null : selectedValue,
useCustomMap,
});
};
_onCustomMapChange = ({ customMapStops, isInvalid }) => {
// Manage invalid custom map in local state
if (isInvalid) {
this.setState({ customMapStops });
return;
}
this.props.onChange({
useCustomMap: true,
customMapStops,
});
};
_renderCustomStopsInput() {
return !this.props.isCustomOnly && !this.props.useCustomMap
? null
: this.props.renderCustomStopsInput(this._onCustomMapChange);
}
_renderMapSelect() {
if (this.props.isCustomOnly) {
return null;
}
const mapOptionsWithCustom = [
{
value: CUSTOM_MAP,
inputDisplay: this.props.customOptionLabel,
},
...this.props.options,
];
let valueOfSelected;
if (this.props.useCustomMap) {
valueOfSelected = CUSTOM_MAP;
} else {
valueOfSelected = this.props.options.find(
(option) => option.value === this.props.selectedMapId
)
? this.props.selectedMapId
: '';
}
return (
<Fragment>
<EuiSuperSelect
options={mapOptionsWithCustom}
onChange={this._onMapSelect}
valueOfSelected={valueOfSelected}
hasDividers={true}
compressed
/>
<EuiSpacer size="s" />
</Fragment>
);
}
render() {
return (
<Fragment>
{this._renderMapSelect()}
{this._renderCustomStopsInput()}
</Fragment>
);
}
}

View file

@ -0,0 +1,124 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Should not render icon map select when isCustomOnly 1`] = `
<Fragment>
<IconStops
field={
MockField {
"_fieldName": "myField",
"_origin": "source",
}
}
getValueSuggestions={[Function]}
iconStops={
Array [
Object {
"icon": "circle",
"stop": null,
},
Object {
"icon": undefined,
"stop": "",
},
]
}
onChange={[Function]}
/>
</Fragment>
`;
exports[`Should render custom stops input when useCustomIconMap 1`] = `
<Fragment>
<EuiSuperSelect
compressed={true}
fullWidth={false}
hasDividers={true}
isInvalid={false}
isLoading={false}
onChange={[Function]}
options={
Array [
Object {
"inputDisplay": "Custom icon palette",
"value": "CUSTOM_MAP_ID",
},
Object {
"inputDisplay": <div>
mock filledShapes option
</div>,
"value": "filledShapes",
},
Object {
"inputDisplay": <div>
mock hollowShapes option
</div>,
"value": "hollowShapes",
},
]
}
valueOfSelected="CUSTOM_MAP_ID"
/>
<EuiSpacer
size="s"
/>
<IconStops
field={
MockField {
"_fieldName": "myField",
"_origin": "source",
}
}
getValueSuggestions={[Function]}
iconStops={
Array [
Object {
"icon": "circle",
"stop": null,
},
Object {
"icon": "marker",
"stop": "value1",
},
]
}
onChange={[Function]}
/>
</Fragment>
`;
exports[`Should render default props 1`] = `
<Fragment>
<EuiSuperSelect
compressed={true}
fullWidth={false}
hasDividers={true}
isInvalid={false}
isLoading={false}
onChange={[Function]}
options={
Array [
Object {
"inputDisplay": "Custom icon palette",
"value": "CUSTOM_MAP_ID",
},
Object {
"inputDisplay": <div>
mock filledShapes option
</div>,
"value": "filledShapes",
},
Object {
"inputDisplay": <div>
mock hollowShapes option
</div>,
"value": "hollowShapes",
},
]
}
valueOfSelected="filledShapes"
/>
<EuiSpacer
size="s"
/>
</Fragment>
`;

View file

@ -12,11 +12,9 @@ import { IconMapSelect } from './icon_map_select';
export function DynamicIconForm({
fields,
isDarkMode,
onDynamicStyleChange,
staticDynamicSelect,
styleProperty,
symbolOptions,
}) {
const styleOptions = styleProperty.getOptions();
@ -44,11 +42,8 @@ export function DynamicIconForm({
return (
<IconMapSelect
{...styleOptions}
useCustomIconMap={_.get(styleOptions, 'useCustomColorRamp', false)}
styleProperty={styleProperty}
onChange={onIconMapChange}
isDarkMode={isDarkMode}
symbolOptions={symbolOptions}
isCustomOnly={!field.supportsAutoDomain()}
/>
);

View file

@ -1,59 +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 from 'react';
import { StyleMapSelect } from '../style_map_select';
import { i18n } from '@kbn/i18n';
import { IconStops } from './icon_stops';
import { getIconPaletteOptions } from '../../symbol_utils';
export function IconMapSelect({
customIconStops,
iconPaletteId,
isDarkMode,
onChange,
styleProperty,
symbolOptions,
useCustomIconMap,
isCustomOnly,
}) {
function onMapSelectChange({ customMapStops, selectedMapId, useCustomMap }) {
onChange({
customIconStops: customMapStops,
iconPaletteId: selectedMapId,
useCustomIconMap: useCustomMap,
});
}
function renderCustomIconStopsInput(onCustomMapChange) {
return (
<IconStops
field={styleProperty.getField()}
getValueSuggestions={styleProperty.getValueSuggestions}
iconStops={customIconStops}
isDarkMode={isDarkMode}
onChange={onCustomMapChange}
symbolOptions={symbolOptions}
/>
);
}
return (
<StyleMapSelect
onChange={onMapSelectChange}
customOptionLabel={i18n.translate('xpack.maps.styles.icon.customMapLabel', {
defaultMessage: 'Custom icon palette',
})}
options={getIconPaletteOptions(isDarkMode)}
customMapStops={customIconStops}
useCustomMap={useCustomIconMap}
selectedMapId={iconPaletteId}
renderCustomStopsInput={renderCustomIconStopsInput}
isCustomOnly={isCustomOnly}
/>
);
}

View file

@ -0,0 +1,78 @@
/*
* 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 max-classes-per-file */
jest.mock('./icon_stops', () => ({
IconStops: () => {
return <div>mockIconStops</div>;
},
}));
jest.mock('../../symbol_utils', () => {
return {
getIconPaletteOptions: () => {
return [
{ value: 'filledShapes', inputDisplay: <div>mock filledShapes option</div> },
{ value: 'hollowShapes', inputDisplay: <div>mock hollowShapes option</div> },
];
},
PREFERRED_ICONS: ['circle'],
};
});
import React from 'react';
import { shallow } from 'enzyme';
import { FIELD_ORIGIN } from '../../../../../../common/constants';
import { AbstractField } from '../../../../fields/field';
import { IDynamicStyleProperty } from '../../properties/dynamic_style_property';
import { IconMapSelect } from './icon_map_select';
class MockField extends AbstractField {}
class MockDynamicStyleProperty {
getField() {
return new MockField({ fieldName: 'myField', origin: FIELD_ORIGIN.SOURCE });
}
getValueSuggestions() {
return [];
}
}
const defaultProps = {
iconPaletteId: 'filledShapes',
onChange: () => {},
styleProperty: (new MockDynamicStyleProperty() as unknown) as IDynamicStyleProperty,
isCustomOnly: false,
};
test('Should render default props', () => {
const component = shallow(<IconMapSelect {...defaultProps} />);
expect(component).toMatchSnapshot();
});
test('Should render custom stops input when useCustomIconMap', () => {
const component = shallow(
<IconMapSelect
{...defaultProps}
useCustomIconMap={true}
customIconStops={[
{ stop: null, icon: 'circle' },
{ stop: 'value1', icon: 'marker' },
]}
/>
);
expect(component).toMatchSnapshot();
});
test('Should not render icon map select when isCustomOnly', () => {
const component = shallow(<IconMapSelect {...defaultProps} isCustomOnly={true} />);
expect(component).toMatchSnapshot();
});

View file

@ -0,0 +1,136 @@
/*
* 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 { EuiSuperSelect, EuiSpacer } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
// @ts-expect-error
import { IconStops } from './icon_stops';
// @ts-expect-error
import { getIconPaletteOptions, PREFERRED_ICONS } from '../../symbol_utils';
import { IconStop } from '../../../../../../common/descriptor_types';
import { IDynamicStyleProperty } from '../../properties/dynamic_style_property';
const CUSTOM_MAP_ID = 'CUSTOM_MAP_ID';
const DEFAULT_ICON_STOPS = [
{ stop: null, icon: PREFERRED_ICONS[0] }, // first stop is the "other" category
{ stop: '', icon: PREFERRED_ICONS[1] },
];
interface StyleOptionChanges {
customIconStops?: IconStop[];
iconPaletteId?: string | null;
useCustomIconMap: boolean;
}
interface Props {
customIconStops?: IconStop[];
iconPaletteId: string | null;
onChange: ({ customIconStops, iconPaletteId, useCustomIconMap }: StyleOptionChanges) => void;
styleProperty: IDynamicStyleProperty;
useCustomIconMap?: boolean;
isCustomOnly: boolean;
}
interface State {
customIconStops: IconStop[];
}
export class IconMapSelect extends Component<Props, State> {
state = {
customIconStops: this.props.customIconStops ? this.props.customIconStops : DEFAULT_ICON_STOPS,
};
_onMapSelect = (selectedValue: string) => {
const useCustomIconMap = selectedValue === CUSTOM_MAP_ID;
const changes: StyleOptionChanges = {
iconPaletteId: useCustomIconMap ? null : selectedValue,
useCustomIconMap,
};
// edge case when custom palette is first enabled
// customIconStops is undefined so need to update custom stops with default so icons are rendered.
if (!this.props.customIconStops) {
changes.customIconStops = DEFAULT_ICON_STOPS;
}
this.props.onChange(changes);
};
_onCustomMapChange = ({
customStops,
isInvalid,
}: {
customStops: IconStop[];
isInvalid: boolean;
}) => {
// Manage invalid custom map in local state
this.setState({ customIconStops: customStops });
if (!isInvalid) {
this.props.onChange({
useCustomIconMap: true,
customIconStops: customStops,
});
}
};
_renderCustomStopsInput() {
return !this.props.isCustomOnly && !this.props.useCustomIconMap ? null : (
<IconStops
field={this.props.styleProperty.getField()}
getValueSuggestions={this.props.styleProperty.getValueSuggestions}
iconStops={this.state.customIconStops}
onChange={this._onCustomMapChange}
/>
);
}
_renderMapSelect() {
if (this.props.isCustomOnly) {
return null;
}
const mapOptionsWithCustom = [
{
value: CUSTOM_MAP_ID,
inputDisplay: i18n.translate('xpack.maps.styles.icon.customMapLabel', {
defaultMessage: 'Custom icon palette',
}),
},
...getIconPaletteOptions(),
];
let valueOfSelected = '';
if (this.props.useCustomIconMap) {
valueOfSelected = CUSTOM_MAP_ID;
} else if (this.props.iconPaletteId) {
valueOfSelected = this.props.iconPaletteId;
}
return (
<Fragment>
<EuiSuperSelect
options={mapOptionsWithCustom}
onChange={this._onMapSelect}
valueOfSelected={valueOfSelected}
hasDividers={true}
compressed
/>
<EuiSpacer size="s" />
</Fragment>
);
}
render() {
return (
<Fragment>
{this._renderMapSelect()}
{this._renderCustomStopsInput()}
</Fragment>
);
}
}

View file

@ -15,6 +15,8 @@ import {
EuiSelectable,
} from '@elastic/eui';
import { SymbolIcon } from '../legend/symbol_icon';
import { SYMBOL_OPTIONS } from '../../symbol_utils';
import { getIsDarkMode } from '../../../../../kibana_services';
function isKeyboardEvent(event) {
return typeof event === 'object' && 'keyCode' in event;
@ -62,7 +64,6 @@ export class IconSelect extends Component {
};
_renderPopoverButton() {
const { isDarkMode, value } = this.props;
return (
<EuiFormControlLayout
icon={{ type: 'arrowDown', side: 'right' }}
@ -75,16 +76,16 @@ export class IconSelect extends Component {
<EuiFieldText
onClick={this._togglePopover}
onKeyDown={this._handleKeyboardActivity}
value={value}
value={this.props.value}
compressed
readOnly
fullWidth
prepend={
<SymbolIcon
key={value}
key={this.props.value}
className="mapIconSelectSymbol__inputButton"
symbolId={value}
fill={isDarkMode ? 'rgb(223, 229, 239)' : 'rgb(52, 55, 65)'}
symbolId={this.props.value}
fill={getIsDarkMode() ? 'rgb(223, 229, 239)' : 'rgb(52, 55, 65)'}
/>
}
/>
@ -93,8 +94,7 @@ export class IconSelect extends Component {
}
_renderIconSelectable() {
const { isDarkMode } = this.props;
const options = this.props.symbolOptions.map(({ value, label }) => {
const options = SYMBOL_OPTIONS.map(({ value, label }) => {
return {
value,
label,
@ -102,7 +102,7 @@ export class IconSelect extends Component {
<SymbolIcon
key={value}
symbolId={value}
fill={isDarkMode ? 'rgb(223, 229, 239)' : 'rgb(52, 55, 65)'}
fill={getIsDarkMode() ? 'rgb(223, 229, 239)' : 'rgb(52, 55, 65)'}
/>
),
};

View file

@ -4,25 +4,30 @@
* you may not use this file except in compliance with the Elastic License.
*/
jest.mock('../../../../../kibana_services', () => {
return {
getIsDarkMode() {
return false;
},
};
});
jest.mock('../../symbol_utils', () => {
return {
SYMBOL_OPTIONS: [
{ value: 'symbol1', label: 'symbol1' },
{ value: 'symbol2', label: 'symbol2' },
],
};
});
import React from 'react';
import { shallow } from 'enzyme';
import { IconSelect } from './icon_select';
const symbolOptions = [
{ value: 'symbol1', label: 'symbol1' },
{ value: 'symbol2', label: 'symbol2' },
];
test('Should render icon select', () => {
const component = shallow(
<IconSelect
value={symbolOptions[0].value}
onChange={() => {}}
symbolOptions={symbolOptions}
isDarkMode={false}
/>
);
const component = shallow(<IconSelect value={'symbol1'} onChange={() => {}} />);
expect(component).toMatchSnapshot();
});

View file

@ -11,7 +11,7 @@ import { getOtherCategoryLabel } from '../../style_util';
import { EuiButtonIcon, EuiFlexGroup, EuiFlexItem, EuiFormRow, EuiFieldText } from '@elastic/eui';
import { IconSelect } from './icon_select';
import { StopInput } from '../stop_input';
import { PREFERRED_ICONS } from '../../symbol_utils';
import { PREFERRED_ICONS, SYMBOL_OPTIONS } from '../../symbol_utils';
function isDuplicateStop(targetStop, iconStops) {
const stops = iconStops.filter(({ stop }) => {
@ -20,7 +20,7 @@ function isDuplicateStop(targetStop, iconStops) {
return stops.length > 1;
}
export function getFirstUnusedSymbol(symbolOptions, iconStops) {
export function getFirstUnusedSymbol(iconStops) {
const firstUnusedPreferredIconId = PREFERRED_ICONS.find((iconId) => {
const isSymbolBeingUsed = iconStops.some(({ icon }) => {
return icon === iconId;
@ -32,7 +32,7 @@ export function getFirstUnusedSymbol(symbolOptions, iconStops) {
return firstUnusedPreferredIconId;
}
const firstUnusedSymbol = symbolOptions.find(({ value }) => {
const firstUnusedSymbol = SYMBOL_OPTIONS.find(({ value }) => {
const isSymbolBeingUsed = iconStops.some(({ icon }) => {
return icon === value;
});
@ -42,19 +42,7 @@ export function getFirstUnusedSymbol(symbolOptions, iconStops) {
return firstUnusedSymbol ? firstUnusedSymbol.value : DEFAULT_ICON;
}
const DEFAULT_ICON_STOPS = [
{ stop: null, icon: PREFERRED_ICONS[0] }, //first stop is the "other" color
{ stop: '', icon: PREFERRED_ICONS[1] },
];
export function IconStops({
field,
getValueSuggestions,
iconStops = DEFAULT_ICON_STOPS,
isDarkMode,
onChange,
symbolOptions,
}) {
export function IconStops({ field, getValueSuggestions, iconStops, onChange }) {
return iconStops.map(({ stop, icon }, index) => {
const onIconSelect = (selectedIconId) => {
const newIconStops = [...iconStops];
@ -62,7 +50,7 @@ export function IconStops({
...iconStops[index],
icon: selectedIconId,
};
onChange({ customMapStops: newIconStops });
onChange({ customStops: newIconStops });
};
const onStopChange = (newStopValue) => {
const newIconStops = [...iconStops];
@ -71,17 +59,17 @@ export function IconStops({
stop: newStopValue,
};
onChange({
customMapStops: newIconStops,
customStops: newIconStops,
isInvalid: isDuplicateStop(newStopValue, iconStops),
});
};
const onAdd = () => {
onChange({
customMapStops: [
customStops: [
...iconStops.slice(0, index + 1),
{
stop: '',
icon: getFirstUnusedSymbol(symbolOptions, iconStops),
icon: getFirstUnusedSymbol(iconStops),
},
...iconStops.slice(index + 1),
],
@ -89,7 +77,7 @@ export function IconStops({
};
const onRemove = () => {
onChange({
customMapStops: [...iconStops.slice(0, index), ...iconStops.slice(index + 1)],
customStops: [...iconStops.slice(0, index), ...iconStops.slice(index + 1)],
});
};
@ -157,13 +145,7 @@ export function IconStops({
{stopInput}
</EuiFlexItem>
<EuiFlexItem>
<IconSelect
isDarkMode={isDarkMode}
onChange={onIconSelect}
symbolOptions={symbolOptions}
value={icon}
append={iconStopButtons}
/>
<IconSelect onChange={onIconSelect} value={icon} append={iconStopButtons} />
</EuiFlexItem>
</EuiFlexGroup>
</EuiFormRow>

View file

@ -4,17 +4,41 @@
* you may not use this file except in compliance with the Elastic License.
*/
import React from 'react';
import { getFirstUnusedSymbol } from './icon_stops';
describe('getFirstUnusedSymbol', () => {
const symbolOptions = [{ value: 'icon1' }, { value: 'icon2' }];
jest.mock('./icon_select', () => ({
IconSelect: () => {
return <div>mockIconSelect</div>;
},
}));
jest.mock('../../symbol_utils', () => {
return {
SYMBOL_OPTIONS: [{ value: 'icon1' }, { value: 'icon2' }],
PREFERRED_ICONS: [
'circle',
'marker',
'square',
'star',
'triangle',
'hospital',
'circle-stroked',
'marker-stroked',
'square-stroked',
'star-stroked',
'triangle-stroked',
],
};
});
describe('getFirstUnusedSymbol', () => {
test('Should return first unused icon from PREFERRED_ICONS', () => {
const iconStops = [
{ stop: 'category1', icon: 'circle' },
{ stop: 'category2', icon: 'marker' },
];
const nextIcon = getFirstUnusedSymbol(symbolOptions, iconStops);
const nextIcon = getFirstUnusedSymbol(iconStops);
expect(nextIcon).toBe('square');
});
@ -33,7 +57,7 @@ describe('getFirstUnusedSymbol', () => {
{ stop: 'category11', icon: 'triangle-stroked' },
{ stop: 'category12', icon: 'icon1' },
];
const nextIcon = getFirstUnusedSymbol(symbolOptions, iconStops);
const nextIcon = getFirstUnusedSymbol(iconStops);
expect(nextIcon).toBe('icon2');
});
@ -53,7 +77,7 @@ describe('getFirstUnusedSymbol', () => {
{ stop: 'category12', icon: 'icon1' },
{ stop: 'category13', icon: 'icon2' },
];
const nextIcon = getFirstUnusedSymbol(symbolOptions, iconStops);
const nextIcon = getFirstUnusedSymbol(iconStops);
expect(nextIcon).toBe('marker');
});
});

View file

@ -8,13 +8,7 @@ import React from 'react';
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { IconSelect } from './icon_select';
export function StaticIconForm({
isDarkMode,
onStaticStyleChange,
staticDynamicSelect,
styleProperty,
symbolOptions,
}) {
export function StaticIconForm({ onStaticStyleChange, staticDynamicSelect, styleProperty }) {
const onChange = (selectedIconId) => {
onStaticStyleChange(styleProperty.getStyleName(), { value: selectedIconId });
};
@ -25,12 +19,7 @@ export function StaticIconForm({
{staticDynamicSelect}
</EuiFlexItem>
<EuiFlexItem>
<IconSelect
isDarkMode={isDarkMode}
onChange={onChange}
symbolOptions={symbolOptions}
value={styleProperty.getOptions().value}
/>
<IconSelect onChange={onChange} value={styleProperty.getOptions().value} />
</EuiFlexItem>
</EuiFlexGroup>
);

View file

@ -6,25 +6,15 @@
import React from 'react';
import { getUiSettings } from '../../../../../kibana_services';
import { StylePropEditor } from '../style_prop_editor';
import { DynamicIconForm } from './dynamic_icon_form';
import { StaticIconForm } from './static_icon_form';
import { SYMBOL_OPTIONS } from '../../symbol_utils';
export function VectorStyleIconEditor(props) {
const iconForm = props.styleProperty.isDynamic() ? (
<DynamicIconForm
{...props}
isDarkMode={getUiSettings().get('theme:darkMode', false)}
symbolOptions={SYMBOL_OPTIONS}
/>
<DynamicIconForm {...props} />
) : (
<StaticIconForm
{...props}
isDarkMode={getUiSettings().get('theme:darkMode', false)}
symbolOptions={SYMBOL_OPTIONS}
/>
<StaticIconForm {...props} />
);
return <StylePropEditor {...props}>{iconForm}</StylePropEditor>;

View file

@ -33,4 +33,5 @@ export interface IDynamicStyleProperty extends IStyleProperty {
pluckCategoricalStyleMetaFromFeatures(features: unknown[]): CategoryFieldMeta;
pluckOrdinalStyleMetaFromFieldMetaData(fieldMetaData: unknown): RangeFieldMeta;
pluckCategoricalStyleMetaFromFieldMetaData(fieldMetaData: unknown): CategoryFieldMeta;
getValueSuggestions(query: string): string[];
}

View file

@ -9,6 +9,7 @@ import maki from '@elastic/maki';
import xml2js from 'xml2js';
import { parseXmlString } from '../../../../common/parse_xml_string';
import { SymbolIcon } from './components/legend/symbol_icon';
import { getIsDarkMode } from '../../../kibana_services';
export const LARGE_MAKI_ICON_SIZE = 15;
const LARGE_MAKI_ICON_SIZE_AS_STRING = LARGE_MAKI_ICON_SIZE.toString();
@ -111,7 +112,8 @@ ICON_PALETTES.forEach((iconPalette) => {
});
});
export function getIconPaletteOptions(isDarkMode) {
export function getIconPaletteOptions() {
const isDarkMode = getIsDarkMode();
return ICON_PALETTES.map(({ id, icons }) => {
const iconsDisplay = icons.map((iconId) => {
const style = {

View file

@ -5,14 +5,9 @@
*/
jest.mock('../../../kibana_services', () => {
const mockUiSettings = {
get: () => {
return undefined;
},
};
return {
getUiSettings: () => {
return mockUiSettings;
getIsDarkMode() {
return false;
},
};
});

View file

@ -18,8 +18,7 @@ import {
CATEGORICAL_COLOR_PALETTES,
} from '../color_palettes';
import { VectorStylePropertiesDescriptor } from '../../../../common/descriptor_types';
// @ts-ignore
import { getUiSettings } from '../../../kibana_services';
import { getIsDarkMode } from '../../../kibana_services';
export const MIN_SIZE = 1;
export const MAX_SIZE = 64;
@ -67,7 +66,7 @@ export function getDefaultStaticProperties(
const nextFillColor = DEFAULT_FILL_COLORS[nextColorIndex];
const nextLineColor = DEFAULT_LINE_COLORS[nextColorIndex];
const isDarkMode = getUiSettings().get('theme:darkMode', false);
const isDarkMode = getIsDarkMode();
return {
[VECTOR_STYLES.ICON]: {

View file

@ -24,6 +24,7 @@ export function getVisualizations(): any;
export function getDocLinks(): any;
export function getCoreChrome(): any;
export function getUiSettings(): any;
export function getIsDarkMode(): boolean;
export function getCoreOverlays(): any;
export function getData(): any;
export function getUiActions(): any;

View file

@ -40,6 +40,9 @@ export const getFileUploadComponent = () => {
let uiSettings;
export const setUiSettings = (coreUiSettings) => (uiSettings = coreUiSettings);
export const getUiSettings = () => uiSettings;
export const getIsDarkMode = () => {
return getUiSettings().get('theme:darkMode', false);
};
let indexPatternSelectComponent;
export const setIndexPatternSelect = (indexPatternSelect) =>