[Maps] Fix legend icon color for custom categorial palettes (#67141)

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
Nathan Reese 2020-05-26 08:21:32 -06:00 committed by GitHub
parent c8b1fc585b
commit c9c37f77e6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 281 additions and 70 deletions

View file

@ -170,10 +170,10 @@ export enum LAYER_STYLE_TYPE {
TILE = 'TILE',
}
export const COLOR_MAP_TYPE = {
CATEGORICAL: 'CATEGORICAL',
ORDINAL: 'ORDINAL',
};
export enum COLOR_MAP_TYPE {
CATEGORICAL = 'CATEGORICAL',
ORDINAL = 'ORDINAL',
}
export const CATEGORICAL_DATA_TYPES = ['string', 'ip', 'boolean'];
export const ORDINAL_DATA_TYPES = ['number', 'date'];

View file

@ -6,6 +6,7 @@
/* eslint-disable @typescript-eslint/consistent-type-definitions */
import {
COLOR_MAP_TYPE,
FIELD_ORIGIN,
LABEL_BORDER_SIZES,
SYMBOLIZE_AS_TYPES,
@ -60,7 +61,7 @@ export type IconStop = {
export type ColorDynamicOptions = {
// ordinal color properties
color: string; // TODO move color category ramps to constants and make ENUM type
color?: string; // TODO move color category ramps to constants and make ENUM type
customColorRamp?: OrdinalColorStop[];
useCustomColorRamp?: boolean;
@ -71,21 +72,27 @@ export type ColorDynamicOptions = {
field?: StylePropertyField;
fieldMetaOptions: FieldMetaOptions;
type?: COLOR_MAP_TYPE;
};
export type ColorStaticOptions = {
color: string;
};
export type ColorStaticStylePropertyDescriptor = {
type: STYLE_TYPE.STATIC;
options: ColorStaticOptions;
};
export type ColorDynamicStylePropertyDescriptor = {
type: STYLE_TYPE.DYNAMIC;
options: ColorDynamicOptions;
};
export type ColorStylePropertyDescriptor =
| {
type: STYLE_TYPE.STATIC;
options: ColorStaticOptions;
}
| {
type: STYLE_TYPE.DYNAMIC;
options: ColorDynamicOptions;
};
| ColorStaticStylePropertyDescriptor
| ColorDynamicStylePropertyDescriptor;
export type IconDynamicOptions = {
iconPaletteId?: string;

View file

@ -1,57 +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 { getColorRampCenterColor, getColorPalette } from '../../../color_utils';
import { COLOR_MAP_TYPE, STYLE_TYPE } from '../../../../../../common/constants';
export function extractColorFromStyleProperty(colorStyleProperty, defaultColor) {
if (!colorStyleProperty) {
return defaultColor;
}
if (colorStyleProperty.type === STYLE_TYPE.STATIC) {
return colorStyleProperty.options.color;
}
// Do not use dynamic color unless configuration is complete
if (!colorStyleProperty.options.field || !colorStyleProperty.options.field.name) {
return defaultColor;
}
if (colorStyleProperty.options.type === COLOR_MAP_TYPE.CATEGORICAL) {
if (colorStyleProperty.options.useCustomColorPalette) {
return colorStyleProperty.options.customColorPalette &&
colorStyleProperty.options.customColorPalette.length
? colorStyleProperty.options.customColorPalette[0].colorCategory
: defaultColor;
}
if (!colorStyleProperty.options.colorCategory) {
return null;
}
const palette = getColorPalette(colorStyleProperty.options.colorCategory);
return palette[0];
} else {
// return middle of gradient for dynamic style property
if (colorStyleProperty.options.useCustomColorRamp) {
if (
!colorStyleProperty.options.customColorRamp ||
!colorStyleProperty.options.customColorRamp.length
) {
return defaultColor;
}
// favor the lowest color in even arrays
const middleIndex = Math.floor((colorStyleProperty.options.customColorRamp.length - 1) / 2);
return colorStyleProperty.options.customColorRamp[middleIndex].color;
}
if (!colorStyleProperty.options.color) {
return null;
}
return getColorRampCenterColor(colorStyleProperty.options.color);
}
}

View file

@ -0,0 +1,198 @@
/*
* 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 { extractColorFromStyleProperty } from './extract_color_from_style_property';
import {
ColorDynamicOptions,
ColorDynamicStylePropertyDescriptor,
ColorStaticOptions,
ColorStaticStylePropertyDescriptor,
} from '../../../../../../common/descriptor_types';
import { COLOR_MAP_TYPE, FIELD_ORIGIN, STYLE_TYPE } from '../../../../../../common/constants';
// @ts-ignore
import { euiPaletteColorBlind } from '@elastic/eui/lib/services';
const blue = '#0000ff';
const yellow = '#ffff00';
const green = '#00FF00';
const purple = '#800080';
const defaultColor = '#FFFFFF';
const fieldMetaOptions = {
isEnabled: true,
};
const field = {
name: 'myField',
origin: FIELD_ORIGIN.SOURCE,
};
describe('static', () => {
test('Should return color', () => {
const colorStyleProperty = {
type: STYLE_TYPE.STATIC,
options: {
color: blue,
} as ColorStaticOptions,
} as ColorStaticStylePropertyDescriptor;
expect(extractColorFromStyleProperty(colorStyleProperty, defaultColor)).toBe(blue);
});
});
describe('dynamic', () => {
test('Should return default color when field is not provided', () => {
const colorStyleProperty = {
type: STYLE_TYPE.DYNAMIC,
options: {
fieldMetaOptions,
} as ColorDynamicOptions,
} as ColorDynamicStylePropertyDescriptor;
expect(extractColorFromStyleProperty(colorStyleProperty, defaultColor)).toBe(defaultColor);
});
describe('categorical', () => {
describe('predefined color palette', () => {
test('Should return default color when color palette is not specified', () => {
const colorStyleProperty = {
type: STYLE_TYPE.DYNAMIC,
options: {
type: COLOR_MAP_TYPE.CATEGORICAL,
field,
fieldMetaOptions,
} as ColorDynamicOptions,
} as ColorDynamicStylePropertyDescriptor;
expect(extractColorFromStyleProperty(colorStyleProperty, defaultColor)).toBe(defaultColor);
});
test('Should return first color from color palette', () => {
const colorStyleProperty = {
type: STYLE_TYPE.DYNAMIC,
options: {
type: COLOR_MAP_TYPE.CATEGORICAL,
colorCategory: 'palette_0',
field,
fieldMetaOptions,
} as ColorDynamicOptions,
} as ColorDynamicStylePropertyDescriptor;
expect(extractColorFromStyleProperty(colorStyleProperty, defaultColor)).toBe(
euiPaletteColorBlind()[0]
);
});
});
describe('custom color palette', () => {
test('Should return default color when custom color palette is not provided', () => {
const colorStyleProperty = {
type: STYLE_TYPE.DYNAMIC,
options: {
type: COLOR_MAP_TYPE.CATEGORICAL,
colorCategory: 'palette_0',
field,
fieldMetaOptions,
useCustomColorPalette: true,
} as ColorDynamicOptions,
} as ColorDynamicStylePropertyDescriptor;
expect(extractColorFromStyleProperty(colorStyleProperty, defaultColor)).toBe(defaultColor);
});
test('Should return first color from custom color palette', () => {
const colorStyleProperty = {
type: STYLE_TYPE.DYNAMIC,
options: {
type: COLOR_MAP_TYPE.CATEGORICAL,
colorCategory: 'palette_0',
field,
fieldMetaOptions,
useCustomColorPalette: true,
customColorPalette: [{ stop: 'myCategory1', color: blue }],
} as ColorDynamicOptions,
} as ColorDynamicStylePropertyDescriptor;
expect(extractColorFromStyleProperty(colorStyleProperty, defaultColor)).toBe(blue);
});
});
});
describe('ordinal', () => {
describe('predefined color ramp', () => {
test('Should return default color when color ramp is not specified', () => {
const colorStyleProperty = {
type: STYLE_TYPE.DYNAMIC,
options: {
type: COLOR_MAP_TYPE.ORDINAL,
field,
fieldMetaOptions,
} as ColorDynamicOptions,
} as ColorDynamicStylePropertyDescriptor;
expect(extractColorFromStyleProperty(colorStyleProperty, defaultColor)).toBe(defaultColor);
});
test('Should return center color from color ramp', () => {
const colorStyleProperty = {
type: STYLE_TYPE.DYNAMIC,
options: {
type: COLOR_MAP_TYPE.ORDINAL,
color: 'Blues',
field,
fieldMetaOptions,
} as ColorDynamicOptions,
} as ColorDynamicStylePropertyDescriptor;
expect(extractColorFromStyleProperty(colorStyleProperty, defaultColor)).toBe(
'rgb(106,173,213)'
);
});
});
describe('custom color ramp', () => {
test('Should return default color when custom color ramp is not provided', () => {
const colorStyleProperty = {
type: STYLE_TYPE.DYNAMIC,
options: {
type: COLOR_MAP_TYPE.ORDINAL,
field,
fieldMetaOptions,
useCustomColorRamp: true,
} as ColorDynamicOptions,
} as ColorDynamicStylePropertyDescriptor;
expect(extractColorFromStyleProperty(colorStyleProperty, defaultColor)).toBe(defaultColor);
});
test('Should return middle color from custom color ramp (odd # of stops)', () => {
const colorStyleProperty = {
type: STYLE_TYPE.DYNAMIC,
options: {
type: COLOR_MAP_TYPE.ORDINAL,
field,
fieldMetaOptions,
useCustomColorRamp: true,
customColorRamp: [
{ stop: 0, color: blue },
{ stop: 5, color: green },
{ stop: 10, color: yellow },
],
} as ColorDynamicOptions,
} as ColorDynamicStylePropertyDescriptor;
expect(extractColorFromStyleProperty(colorStyleProperty, defaultColor)).toBe(green);
});
test('Should return middle color from custom color ramp (even # of stops)', () => {
const colorStyleProperty = {
type: STYLE_TYPE.DYNAMIC,
options: {
type: COLOR_MAP_TYPE.ORDINAL,
field,
fieldMetaOptions,
useCustomColorRamp: true,
customColorRamp: [
{ stop: 0, color: blue },
{ stop: 3, color: purple },
{ stop: 6, color: green },
{ stop: 10, color: yellow },
],
} as ColorDynamicOptions,
} as ColorDynamicStylePropertyDescriptor;
expect(extractColorFromStyleProperty(colorStyleProperty, defaultColor)).toBe(purple);
});
});
});
});

View file

@ -0,0 +1,63 @@
/*
* 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.
*/
// @ts-ignore
import { getColorRampCenterColor, getColorPalette } from '../../../color_utils';
import { COLOR_MAP_TYPE, STYLE_TYPE } from '../../../../../../common/constants';
import {
ColorDynamicOptions,
ColorStylePropertyDescriptor,
} from '../../../../../../common/descriptor_types';
export function extractColorFromStyleProperty(
colorStyleProperty: ColorStylePropertyDescriptor | undefined,
defaultColor: string
): string {
if (!colorStyleProperty) {
return defaultColor;
}
if (colorStyleProperty.type === STYLE_TYPE.STATIC) {
return colorStyleProperty.options.color;
}
const dynamicOptions: ColorDynamicOptions = colorStyleProperty.options;
// Do not use dynamic color unless configuration is complete
if (!dynamicOptions.field || !dynamicOptions.field.name) {
return defaultColor;
}
if (dynamicOptions.type === COLOR_MAP_TYPE.CATEGORICAL) {
if (dynamicOptions.useCustomColorPalette) {
return dynamicOptions.customColorPalette && dynamicOptions.customColorPalette.length
? dynamicOptions.customColorPalette[0].color
: defaultColor;
}
if (!dynamicOptions.colorCategory) {
return defaultColor;
}
const palette = getColorPalette(dynamicOptions.colorCategory);
return palette[0];
} else {
// return middle of gradient for dynamic style property
if (dynamicOptions.useCustomColorRamp) {
if (!dynamicOptions.customColorRamp || !dynamicOptions.customColorRamp.length) {
return defaultColor;
}
// favor the lowest color in even arrays
const middleIndex = Math.floor((dynamicOptions.customColorRamp.length - 1) / 2);
return dynamicOptions.customColorRamp[middleIndex].color;
}
if (!dynamicOptions.color) {
return defaultColor;
}
return getColorRampCenterColor(dynamicOptions.color);
}
}