Skip to content

Commit

Permalink
[Maps] convert HeatmapLayer dependencies to TS (#66823)
Browse files Browse the repository at this point in the history
* [Maps] convert HeatmapLayer and dependencies to TS

* heatmap_style_editor snapshots

* eslint

* fix merge problems

* eslint cleanup

* revert rename of getOrdinalMbColorRampStops

* eslint

* tslint

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
  • Loading branch information
nreese and elasticmachine committed May 28, 2020
1 parent 17573f1 commit 57345e0
Show file tree
Hide file tree
Showing 13 changed files with 117 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import {
VECTOR_STYLES,
STYLE_TYPE,
} from '../../../../common/constants';
// @ts-ignore
import { COLOR_GRADIENTS } from '../../styles/color_utils';

export const clustersLayerWizardConfig: LayerWizard = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import {
VECTOR_STYLES,
STYLE_TYPE,
} from '../../../../common/constants';
// @ts-ignore
import { COLOR_GRADIENTS } from '../../styles/color_utils';
// @ts-ignore
import { CreateSourceEditor } from './create_source_editor';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,73 +7,85 @@
import React from 'react';
import tinycolor from 'tinycolor2';
import chroma from 'chroma-js';
// @ts-ignore
import { euiPaletteColorBlind } from '@elastic/eui/lib/services';
import { ColorGradient } from './components/color_gradient';
import { vislibColorMaps } from '../../../../../../src/plugins/charts/public';
import { RawColorSchema, vislibColorMaps } from '../../../../../../src/plugins/charts/public';

export const GRADIENT_INTERVALS = 8;

export const DEFAULT_FILL_COLORS = euiPaletteColorBlind();
export const DEFAULT_LINE_COLORS = [
...DEFAULT_FILL_COLORS.map((color) => tinycolor(color).darken().toHexString()),
export const DEFAULT_FILL_COLORS: string[] = euiPaletteColorBlind();
export const DEFAULT_LINE_COLORS: string[] = [
...DEFAULT_FILL_COLORS.map((color: string) => tinycolor(color).darken().toHexString()),
// Explicitly add black & white as border color options
'#000',
'#FFF',
];

function getLegendColors(colorRamp, numLegendColors = 4) {
function getRGBColors(colorRamp: Array<[number, number[]]>, numLegendColors: number = 4): string[] {
const colors = [];
colors[0] = getColor(colorRamp, 0);
colors[0] = getRGBColor(colorRamp, 0);
for (let i = 1; i < numLegendColors - 1; i++) {
colors[i] = getColor(colorRamp, Math.floor((colorRamp.length * i) / numLegendColors));
colors[i] = getRGBColor(colorRamp, Math.floor((colorRamp.length * i) / numLegendColors));
}
colors[numLegendColors - 1] = getColor(colorRamp, colorRamp.length - 1);
colors[numLegendColors - 1] = getRGBColor(colorRamp, colorRamp.length - 1);
return colors;
}

function getColor(colorRamp, i) {
const color = colorRamp[i][1];
const red = Math.floor(color[0] * 255);
const green = Math.floor(color[1] * 255);
const blue = Math.floor(color[2] * 255);
function getRGBColor(colorRamp: Array<[number, number[]]>, i: number): string {
const rgbArray = colorRamp[i][1];
const red = Math.floor(rgbArray[0] * 255);
const green = Math.floor(rgbArray[1] * 255);
const blue = Math.floor(rgbArray[2] * 255);
return `rgb(${red},${green},${blue})`;
}

function getColorRamp(colorRampName) {
const colorRamp = vislibColorMaps[colorRampName];
if (!colorRamp) {
function getColorSchema(colorRampName: string): RawColorSchema {
const colorSchema = vislibColorMaps[colorRampName];
if (!colorSchema) {
throw new Error(
`${colorRampName} not found. Expected one of following values: ${Object.keys(
vislibColorMaps
)}`
);
}
return colorRamp;
return colorSchema;
}

export function getRGBColorRangeStrings(colorRampName, numberColors = GRADIENT_INTERVALS) {
const colorRamp = getColorRamp(colorRampName);
return getLegendColors(colorRamp.value, numberColors);
export function getRGBColorRangeStrings(
colorRampName: string,
numberColors: number = GRADIENT_INTERVALS
): string[] {
const colorSchema = getColorSchema(colorRampName);
return getRGBColors(colorSchema.value, numberColors);
}

export function getHexColorRangeStrings(colorRampName, numberColors = GRADIENT_INTERVALS) {
export function getHexColorRangeStrings(
colorRampName: string,
numberColors: number = GRADIENT_INTERVALS
): string[] {
return getRGBColorRangeStrings(colorRampName, numberColors).map((rgbColor) =>
chroma(rgbColor).hex()
);
}

export function getColorRampCenterColor(colorRampName) {
export function getColorRampCenterColor(colorRampName: string): string | null {
if (!colorRampName) {
return null;
}
const colorRamp = getColorRamp(colorRampName);
const centerIndex = Math.floor(colorRamp.value.length / 2);
return getColor(colorRamp.value, centerIndex);
const colorSchema = getColorSchema(colorRampName);
const centerIndex = Math.floor(colorSchema.value.length / 2);
return getRGBColor(colorSchema.value, centerIndex);
}

// Returns an array of color stops
// [ stop_input_1: number, stop_output_1: color, stop_input_n: number, stop_output_n: color ]
export function getOrdinalMbColorRampStops(colorRampName, min, max, numberColors) {
export function getOrdinalMbColorRampStops(
colorRampName: string,
min: number,
max: number,
numberColors: number
): Array<number | string> | null {
if (!colorRampName) {
return null;
}
Expand All @@ -84,15 +96,18 @@ export function getOrdinalMbColorRampStops(colorRampName, min, max, numberColors

const hexColors = getHexColorRangeStrings(colorRampName, numberColors);
if (max === min) {
//just return single stop value
// just return single stop value
return [max, hexColors[hexColors.length - 1]];
}

const delta = max - min;
return hexColors.reduce((accu, stopColor, idx, srcArr) => {
const stopNumber = min + (delta * idx) / srcArr.length;
return [...accu, stopNumber, stopColor];
}, []);
return hexColors.reduce(
(accu: Array<number | string>, stopColor: string, idx: number, srcArr: string[]) => {
const stopNumber = min + (delta * idx) / srcArr.length;
return [...accu, stopNumber, stopColor];
},
[]
);
}

export const COLOR_GRADIENTS = Object.keys(vislibColorMaps).map((colorRampName) => ({
Expand All @@ -102,7 +117,7 @@ export const COLOR_GRADIENTS = Object.keys(vislibColorMaps).map((colorRampName)

export const COLOR_RAMP_NAMES = Object.keys(vislibColorMaps);

export function getLinearGradient(colorStrings) {
export function getLinearGradient(colorStrings: string[]): string {
const intervals = colorStrings.length;
let linearGradient = `linear-gradient(to right, ${colorStrings[0]} 0%,`;
for (let i = 1; i < intervals - 1; i++) {
Expand All @@ -112,7 +127,12 @@ export function getLinearGradient(colorStrings) {
return `${linearGradient} ${colorStrings[colorStrings.length - 1]} 100%)`;
}

const COLOR_PALETTES_CONFIGS = [
export interface ColorPalette {
id: string;
colors: string[];
}

const COLOR_PALETTES_CONFIGS: ColorPalette[] = [
{
id: 'palette_0',
colors: euiPaletteColorBlind(),
Expand All @@ -127,14 +147,14 @@ const COLOR_PALETTES_CONFIGS = [
},
];

export function getColorPalette(paletteId) {
const palette = COLOR_PALETTES_CONFIGS.find((palette) => palette.id === paletteId);
export function getColorPalette(paletteId: string): string[] | null {
const palette = COLOR_PALETTES_CONFIGS.find(({ id }: ColorPalette) => id === paletteId);
return palette ? palette.colors : null;
}

export const COLOR_PALETTES = COLOR_PALETTES_CONFIGS.map((palette) => {
const paletteDisplay = palette.colors.map((color) => {
const style = {
const style: React.CSSProperties = {
backgroundColor: color,
width: `${100 / palette.colors.length}%`,
position: 'relative',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,20 @@ import {
getRGBColorRangeStrings,
getLinearGradient,
} from '../color_utils';
import classNames from 'classnames';

export const ColorGradient = ({ colorRamp, colorRampName, className }) => {
interface Props {
colorRamp?: string[];
colorRampName?: string;
}

export const ColorGradient = ({ colorRamp, colorRampName }: Props) => {
if (!colorRamp && (!colorRampName || !COLOR_RAMP_NAMES.includes(colorRampName))) {
return null;
}

const classes = classNames('mapColorGradient', className);
const rgbColorStrings = colorRampName
? getRGBColorRangeStrings(colorRampName, GRADIENT_INTERVALS)
: colorRamp;
: colorRamp!;
const background = getLinearGradient(rgbColorStrings);
return <div className={classes} style={{ background }} />;
return <div className="mapColorGradient" style={{ background }} />;
};
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,13 @@ import {
HEATMAP_COLOR_RAMP_LABEL,
} from './heatmap_constants';

export function HeatmapStyleEditor({ colorRampName, onHeatmapColorChange }) {
const onColorRampChange = (selectedColorRampName) => {
interface Props {
colorRampName: string;
onHeatmapColorChange: ({ colorRampName }: { colorRampName: string }) => void;
}

export function HeatmapStyleEditor({ colorRampName, onHeatmapColorChange }: Props) {
const onColorRampChange = (selectedColorRampName: string) => {
onHeatmapColorChange({
colorRampName: selectedColorRampName,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ export class HeatmapStyle extends AbstractStyle {
MAX_RANGE,
GRADIENT_INTERVALS
);
// TODO handle null
mbMap.setPaintProperty(layerId, 'heatmap-color', [
'interpolate',
['linear'],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export function extractColorFromStyleProperty(
}

const palette = getColorPalette(dynamicOptions.colorCategory);
return palette[0];
return palette ? palette[0] : defaultColor;
} else {
// return middle of gradient for dynamic style property
if (dynamicOptions.useCustomColorRamp) {
Expand All @@ -58,6 +58,7 @@ export function extractColorFromStyleProperty(
if (!dynamicOptions.color) {
return defaultColor;
}
return getColorRampCenterColor(dynamicOptions.color);
const centerColor = getColorRampCenterColor(dynamicOptions.color);
return centerColor ? centerColor : defaultColor;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* 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.
*/

jest.mock('../../../kibana_services', () => {
const mockUiSettings = {
get: () => {
return undefined;
},
};
return {
getUiSettings: () => {
return mockUiSettings;
},
};
});

import { VECTOR_STYLES } from '../../../../common/constants';
import { getDefaultStaticProperties } from './vector_style_defaults';

describe('getDefaultStaticProperties', () => {
test('Should use first color in DEFAULT_*_COLORS when no colors are used on the map', () => {
const styleProperties = getDefaultStaticProperties([]);
expect(styleProperties[VECTOR_STYLES.FILL_COLOR]!.options.color).toBe('#54B399');
expect(styleProperties[VECTOR_STYLES.LINE_COLOR]!.options.color).toBe('#41937c');
});

test('Should next color in DEFAULT_*_COLORS when colors are used on the map', () => {
const styleProperties = getDefaultStaticProperties(['#54B399']);
expect(styleProperties[VECTOR_STYLES.FILL_COLOR]!.options.color).toBe('#6092C0');
expect(styleProperties[VECTOR_STYLES.LINE_COLOR]!.options.color).toBe('#4379aa');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import {
COLOR_PALETTES,
DEFAULT_FILL_COLORS,
DEFAULT_LINE_COLORS,
// @ts-ignore
} from '../color_utils';
import { VectorStylePropertiesDescriptor } from '../../../../common/descriptor_types';
// @ts-ignore
Expand Down Expand Up @@ -58,9 +57,13 @@ export function getDefaultProperties(mapColors: string[] = []): VectorStylePrope
export function getDefaultStaticProperties(
mapColors: string[] = []
): VectorStylePropertiesDescriptor {
// Colors must be state-aware to reduce unnecessary incrementation
const lastColor = mapColors.pop();
const nextColorIndex = (DEFAULT_FILL_COLORS.indexOf(lastColor) + 1) % DEFAULT_FILL_COLORS.length;
let nextColorIndex = 0;
if (mapColors.length) {
const lastColor = mapColors[mapColors.length - 1];
if (DEFAULT_FILL_COLORS.includes(lastColor)) {
nextColorIndex = (DEFAULT_FILL_COLORS.indexOf(lastColor) + 1) % DEFAULT_FILL_COLORS.length;
}
}
const nextFillColor = DEFAULT_FILL_COLORS[nextColorIndex];
const nextLineColor = DEFAULT_LINE_COLORS[nextColorIndex];

Expand Down

0 comments on commit 57345e0

Please sign in to comment.