Skip to content

Commit

Permalink
add categories
Browse files Browse the repository at this point in the history
remove cruft

remove cruft

more palettes

move options to size as well

default

rename

auto-select

tmp

stops

for consistency

fix legend

toggle behavior

add default stop

subdued text color
  • Loading branch information
thomasneirynck committed Jan 12, 2020
1 parent 80b6dd8 commit b8f0aa3
Show file tree
Hide file tree
Showing 24 changed files with 865 additions and 169 deletions.
7 changes: 7 additions & 0 deletions x-pack/legacy/plugins/maps/common/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,3 +140,10 @@ export const LAYER_STYLE_TYPE = {
VECTOR: 'VECTOR',
HEATMAP: 'HEATMAP',
};

export const COLOR_MAP_TYPE = {
CATEGORICAL: 'CATEGORICAL',
ORDINAL: 'ORDINAL',
};

export const COLOR_PALETTE_MAX_SIZE = 10;
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export class ESAggMetricField extends AbstractField {
return !isMetricCountable(this.getAggType());
}

async getFieldMetaRequest(config) {
return this._esDocField.getFieldMetaRequest(config);
async getOrdinalFieldMetaRequest(config) {
return this._esDocField.getOrdinalFieldMetaRequest(config);
}
}
28 changes: 27 additions & 1 deletion x-pack/legacy/plugins/maps/public/layers/fields/es_doc_field.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import { AbstractField } from './field';
import { ESTooltipProperty } from '../tooltips/es_tooltip_property';
import { COLOR_PALETTE_MAX_SIZE } from '../../../common/constants';

export class ESDocField extends AbstractField {
static type = 'ES_DOC';
Expand All @@ -29,7 +30,7 @@ export class ESDocField extends AbstractField {
return true;
}

async getFieldMetaRequest(/* config */) {
async getOrdinalFieldMetaRequest() {
const field = await this._getField();

if (field.type !== 'number' && field.type !== 'date') {
Expand All @@ -51,4 +52,29 @@ export class ESDocField extends AbstractField {
},
};
}

async getCategoricalFieldMetaRequest() {
const field = await this._getField();
if (field.type !== 'string') {
//UX does not support categorical styling for number/date fields
return null;
}

const topTerms = {
size: COLOR_PALETTE_MAX_SIZE - 1, //need additional color for the "other"-value
};
if (field.scripted) {
topTerms.script = {
source: field.script,
lang: field.lang,
};
} else {
topTerms.field = this._fieldName;
}
return {
[this._fieldName]: {
terms: topTerms,
},
};
}
}
6 changes: 5 additions & 1 deletion x-pack/legacy/plugins/maps/public/layers/fields/field.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,11 @@ export class AbstractField {
return false;
}

async getFieldMetaRequest(/* config */) {
async getOrdinalFieldMetaRequest(/* config */) {
return null;
}

async getCategoricalFieldMetaRequest() {
return null;
}
}
4 changes: 4 additions & 0 deletions x-pack/legacy/plugins/maps/public/layers/layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,10 @@ export class AbstractLayer {
return [];
}

async getStringFields() {
return [];
}

async getFields() {
return [];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,21 @@ export class ESSearchSource extends AbstractESSource {
}
}

async getStringFields() {
try {
const indexPattern = await this.getIndexPattern();
const aggFields = indexPattern.fields.getByType('string').filter(field => {
return field.aggregatable;
});
return aggFields.map(field => {
return this.createField({ fieldName: field.name });
});
} catch (error) {
//error surfaces in the LayerTOC UI
return [];
}
}

async getFields() {
try {
const indexPattern = await this.getIndexPattern();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ export class AbstractVectorSource extends AbstractSource {
return [...(await this.getDateFields()), ...(await this.getNumberFields())];
}

async getStringFields() {
return [];
}

async getLeftJoinFields() {
return [];
}
Expand Down
43 changes: 43 additions & 0 deletions x-pack/legacy/plugins/maps/public/layers/styles/color_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { ColorGradient } from './components/color_gradient';
import { palettes } from '@elastic/eui/lib/services';
import tinycolor from 'tinycolor2';
import chroma from 'chroma-js';
import { COLOR_PALETTE_MAX_SIZE } from '../../../common/constants';

const GRADIENT_INTERVALS = 8;

Expand Down Expand Up @@ -84,3 +85,45 @@ export function getLinearGradient(colorStrings) {
}
return `${linearGradient} ${colorStrings[colorStrings.length - 1]} 100%)`;
}

export const COLOR_PALETTES = [
{
id: 'palette_0',
colors: DEFAULT_FILL_COLORS.slice(0, COLOR_PALETTE_MAX_SIZE),
},
{
id: 'palette_1',
colors: [
'#a6cee3',
'#1f78b4',
'#b2df8a',
'#33a02c',
'#fb9a99',
'#e31a1c',
'#fdbf6f',
'#ff7f00',
'#cab2d6',
'#6a3d9a',
],
},
{
id: 'palette_2',
colors: [
'#8dd3c7',
'#ffffb3',
'#bebada',
'#fb8072',
'#80b1d3',
'#fdb462',
'#b3de69',
'#fccde5',
'#d9d9d9',
'#bc80bd',
],
},
];

export function getColorPalette(paletteId) {
const palette = COLOR_PALETTES.find(palette => palette.id === paletteId);
return palette ? palette.colors : null;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/*
* 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 PropTypes from 'prop-types';

import { EuiSuperSelect, EuiSpacer } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { ColorStopsCategorical } from './color_stops_categorical';
import { COLOR_PALETTES } from '../../../color_utils';
import { COLOR_MAP_TYPE } from '../../../../../../common/constants';

const CUSTOM_COLOR_PALETTE = 'CUSTOM_COLOR_PALETTE';
const CUSTOM_OPTION = {
value: CUSTOM_COLOR_PALETTE,
inputDisplay: (
<FormattedMessage
id="xpack.maps.style.customColorPaletteLabel"
defaultMessage="Custom color palette"
/>
),
};

const colorPaletteInputs = COLOR_PALETTES.map(palette => {
const paletteDisplay = palette.colors.map(color => {
const style = {
backgroundColor: color,
width: '10%',
position: 'relative',
height: '100%',
display: 'inline-block',
};
// eslint-disable-next-line react/no-danger
return <div style={style} dangerouslySetInnerHTML={{ __html: '&nbsp;' }} />;
});
return {
value: palette.id,
inputDisplay: <div className={'mapColorGradient'}>{paletteDisplay}</div>,
};
});

export class ColorPaletteSelect extends Component {
state = {};

static getDerivedStateFromProps(nextProps, prevState) {
if (nextProps.customColorPalette !== prevState.prevPropsCustomColorPalette) {
return {
prevPropsCustomColorPalette: nextProps.customColorPalette, // reset tracker to latest value
customColorPalette: nextProps.customColorPalette, // reset customColorPalette to latest value
};
}

return null;
}

_onColorPaletteSelect = selectedValue => {
const useCustomColorPalette = selectedValue === CUSTOM_COLOR_PALETTE;
this.props.onChange({
type: COLOR_MAP_TYPE.CATEGORICAL,
color: useCustomColorPalette ? null : selectedValue,
useCustomColorPalette,
});
};

_onCustomColorPaletteChange = ({ colorStops }) => {
this.props.onChange({
type: COLOR_MAP_TYPE.CATEGORICAL,
customColorPalette: colorStops,
});
};

render() {
const {
color,
onChange, // eslint-disable-line no-unused-vars
useCustomColorPalette,
customColorPalette, // eslint-disable-line no-unused-vars
...rest
} = this.props;

let colorStopsInput;
if (useCustomColorPalette) {
colorStopsInput = (
<Fragment>
<EuiSpacer size="s" />
<ColorStopsCategorical
colorStops={this.state.customColorPalette}
onChange={this._onCustomColorPaletteChange}
/>
</Fragment>
);
}

const colorPaletteOptions = [CUSTOM_OPTION, ...colorPaletteInputs];
let valueOfSelected;
if (useCustomColorPalette) {
valueOfSelected = CUSTOM_COLOR_PALETTE;
} else {
if (colorPaletteOptions.find(option => option.value === color)) {
valueOfSelected = color;
} else {
valueOfSelected = colorPaletteInputs[0].value;
this._onColorPaletteSelect(valueOfSelected);
}
}

return (
<Fragment>
<EuiSuperSelect
options={colorPaletteOptions}
onChange={this._onColorPaletteSelect}
valueOfSelected={valueOfSelected}
hasDividers={true}
{...rest}
/>
{colorStopsInput}
</Fragment>
);
}
}

ColorPaletteSelect.propTypes = {
color: PropTypes.string,
onChange: PropTypes.func.isRequired,
useCustomColorPalette: PropTypes.bool,
customColorPalette: PropTypes.array,
};
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import PropTypes from 'prop-types';
import { EuiSuperSelect, EuiSpacer } from '@elastic/eui';
import { COLOR_GRADIENTS } from '../../../color_utils';
import { FormattedMessage } from '@kbn/i18n/react';
import { ColorStops } from './color_stops';
import { ColorStopsOrdinal } from './color_stops_ordinal';
import { COLOR_MAP_TYPE } from '../../../../../../common/constants';

const CUSTOM_COLOR_RAMP = 'CUSTOM_COLOR_RAMP';

Expand All @@ -33,6 +34,7 @@ export class ColorRampSelect extends Component {
this.props.onChange({
color: useCustomColorRamp ? null : selectedValue,
useCustomColorRamp,
type: COLOR_MAP_TYPE.ORDINAL,
});
};

Expand All @@ -45,6 +47,7 @@ export class ColorRampSelect extends Component {

this.props.onChange({
customColorRamp: colorStops,
type: COLOR_MAP_TYPE.ORDINAL,
});
};

Expand All @@ -62,7 +65,7 @@ export class ColorRampSelect extends Component {
colorStopsInput = (
<Fragment>
<EuiSpacer size="s" />
<ColorStops
<ColorStopsOrdinal
colorStops={this.state.customColorRamp}
onChange={this._onCustomColorRampChange}
/>
Expand All @@ -82,13 +85,24 @@ export class ColorRampSelect extends Component {
},
...COLOR_GRADIENTS,
];
let valueOfSelected;
if (useCustomColorRamp) {
valueOfSelected = CUSTOM_COLOR_RAMP;
} else {
if (colorRampOptions.find(option => option.value === color)) {
valueOfSelected = color;
} else {
valueOfSelected = COLOR_GRADIENTS[0].value;
this._onColorRampSelect(valueOfSelected);
}
}

return (
<Fragment>
<EuiSuperSelect
options={colorRampOptions}
onChange={this._onColorRampSelect}
valueOfSelected={useCustomColorRamp ? CUSTOM_COLOR_RAMP : color}
valueOfSelected={valueOfSelected}
hasDividers={true}
{...rest}
/>
Expand Down
Loading

0 comments on commit b8f0aa3

Please sign in to comment.