mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[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:
parent
c8b1fc585b
commit
c9c37f77e6
5 changed files with 281 additions and 70 deletions
|
@ -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'];
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -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);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue