Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(series): set custom series colors through spec prop #95

Merged
merged 5 commits into from
Mar 11, 2019
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/lib/series/series.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,15 +265,15 @@ describe('Series', () => {

const emptyCustomColors = new Map();

const defaultColorMap = getSeriesColorMap(seriesColors, chartColors, emptyCustomColors, specs);
const defaultColorMap = getSeriesColorMap(seriesColors, chartColors, emptyCustomColors);
const expectedDefaultColorMap = new Map();
expectedDefaultColorMap.set('spec1', 'elastic_charts_c1');
expect(defaultColorMap).toEqual(expectedDefaultColorMap);

const customColors: Map<string, string> = new Map();
customColors.set('spec1', 'custom_color');

const customizedColorMap = getSeriesColorMap(seriesColors, chartColors, customColors, specs);
const customizedColorMap = getSeriesColorMap(seriesColors, chartColors, customColors);
const expectedCustomizedColorMap = new Map();
expectedCustomizedColorMap.set('spec1', 'custom_color');
expect(customizedColorMap).toEqual(expectedCustomizedColorMap);
Expand Down
13 changes: 4 additions & 9 deletions src/lib/series/series.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { ColorConfig } from '../themes/theme';
import { Accessor } from '../utils/accessor';
import { GroupId, SpecId } from '../utils/ids';
import { splitSpecsByGroupId, YBasicSeriesSpec } from './domains/y_domain';
import { getSeriesColorLabel } from './legend';
import { BasicSeriesSpec, Datum, SeriesAccessors } from './specs';

export interface RawDataSeriesDatum {
Expand Down Expand Up @@ -148,7 +147,7 @@ function getColorValues(
/**
* Get the array of values that forms a series key
*/
function getColorValuesAsString(colorValues: any[], specId: SpecId): string {
export function getColorValuesAsString(colorValues: any[], specId: SpecId): string {
return `specId:{${specId}},colors:{${colorValues}}`;
}

Expand Down Expand Up @@ -392,17 +391,13 @@ export function getSeriesColorMap(
seriesColors: Map<string, DataSeriesColorsValues>,
chartColors: ColorConfig,
customColors: Map<string, string>,
specs: Map<SpecId, BasicSeriesSpec>,
): Map<string, string> {
const seriesColorMap = new Map<string, string>();
let counter = 0;

seriesColors.forEach((value, seriesColorKey) => {
const spec = specs.get(value.specId);
const hasSingleSeries = seriesColors.size === 1;
const seriesLabel = getSeriesColorLabel(value, hasSingleSeries, spec);

const color = (seriesLabel && customColors.get(seriesLabel)) ||
seriesColors.forEach((value: DataSeriesColorsValues, seriesColorKey: string) => {
const customSeriesColor: string | undefined = customColors.get(seriesColorKey);
const color = customSeriesColor ||
chartColors.vizColors[counter % chartColors.vizColors.length];

seriesColorMap.set(
Expand Down
5 changes: 5 additions & 0 deletions src/lib/series/specs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Domain } from '../utils/domain';
import { AxisId, GroupId, SpecId } from '../utils/ids';
import { ScaleContinuousType, ScaleType } from '../utils/scales/scales';
import { CurveType } from './curves';
import { DataSeriesColorsValues } from './series';
import { TooltipPosition } from './tooltip';

export type Datum = any;
Expand Down Expand Up @@ -37,8 +38,12 @@ export interface SeriesSpec {
yDomain?: Domain;
/** The type of series you are looking to render */
seriesType: 'bar' | 'line' | 'area' | 'basic';
/** Custom colors for series */
customSeriesColors?: CustomSeriesColorsMap;
}

export type CustomSeriesColorsMap = Map<DataSeriesColorsValues, string>;

export interface SeriesAccessors {
/** The field name of the x value on Datum object */
xAccessor: Accessor;
Expand Down
15 changes: 11 additions & 4 deletions src/state/chart_state.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -483,16 +483,23 @@ describe('Chart Store', () => {
store.computeChart = computeChart;
store.legendItems = [firstLegendItem, secondLegendItem];

const expectedCustomColors = new Map();
expectedCustomColors.set(firstLegendItem.label, 'foo');

store.setSeriesColor(-1, 'foo');
expect(computeChart).not.toBeCalled();
expect(store.customSeriesColors).toEqual(new Map());

store.setSeriesColor(0, 'foo');
expect(computeChart).toBeCalled();
expect(store.customSeriesColors).toEqual(expectedCustomColors);
expect(store.seriesSpecs.get(firstLegendItem.value.specId)).toBeUndefined();

store.addSeriesSpec(spec);
store.setSeriesColor(0, 'foo');
const expectedSpecCustomColorSeries = new Map();
expectedSpecCustomColorSeries.set(firstLegendItem.value, 'foo');
expect(spec.customSeriesColors).toEqual(expectedSpecCustomColorSeries);

store.setSeriesColor(1, 'bar');
expectedSpecCustomColorSeries.set(secondLegendItem.value, 'bar');
expect(spec.customSeriesColors).toEqual(expectedSpecCustomColorSeries);
});

test('can reset selectedDataSeries', () => {
Expand Down
21 changes: 18 additions & 3 deletions src/state/chart_state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import {
getAllDataSeriesColorValues,
getAxesSpecForSpecId,
getLegendItemByIndex,
getUpdatedCustomSeriesColors,
Transform,
updateSelectedDataSeries,
} from './utils';
Expand Down Expand Up @@ -293,8 +294,19 @@ export class ChartStore {
const legendItem = getLegendItemByIndex(this.legendItems, legendItemIndex);

if (legendItem) {
const key = legendItem.label;
this.customSeriesColors.set(key, color);
const { specId } = legendItem.value;

const spec = this.seriesSpecs.get(specId);
if (spec) {
if (spec.customSeriesColors) {
spec.customSeriesColors.set(legendItem.value, color);
} else {
const specCustomSeriesColors = new Map();
spec.customSeriesColors = specCustomSeriesColors;
spec.customSeriesColors.set(legendItem.value, color);
}
}

this.computeChart();
}
});
Expand Down Expand Up @@ -438,6 +450,10 @@ export class ChartStore {
this.selectedDataSeries = getAllDataSeriesColorValues(seriesDomains.seriesColors);
}

// Merge all series spec custom colors with state custom colors map
const updatedCustomSeriesColors = getUpdatedCustomSeriesColors(this.seriesSpecs);
this.customSeriesColors = new Map([...this.customSeriesColors, ...updatedCustomSeriesColors]);

// tslint:disable-next-line:no-console
// console.log({colors: seriesDomains.seriesColors});

Expand All @@ -447,7 +463,6 @@ export class ChartStore {
seriesDomains.seriesColors,
this.chartTheme.colors,
this.customSeriesColors,
this.seriesSpecs,
);

this.legendItems = computeLegend(
Expand Down
33 changes: 33 additions & 0 deletions src/state/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
findSelectedDataSeries,
getAllDataSeriesColorValues,
getLegendItemByIndex,
getUpdatedCustomSeriesColors,
updateSelectedDataSeries,
} from './utils';

Expand Down Expand Up @@ -214,4 +215,36 @@ describe('Chart State utils', () => {

expect(getAllDataSeriesColorValues(colorMap)).toEqual(expected);
});
it('should get an updated customSeriesColor based on specs', () => {
const spec1: BasicSeriesSpec = {
id: getSpecId('spec1'),
groupId: getGroupId('group1'),
seriesType: 'line',
yScaleType: ScaleType.Log,
xScaleType: ScaleType.Linear,
xAccessor: 'x',
yAccessors: ['y'],
yScaleToDataExtent: false,
data: BARCHART_1Y0G,
};

const specs = new Map<SpecId, BasicSeriesSpec>();
specs.set(spec1.id, spec1);

const emptyCustomSeriesColors = getUpdatedCustomSeriesColors(specs);
expect(emptyCustomSeriesColors).toEqual(new Map());

const dataSeriesColorValues = {
specId: spec1.id,
colorValues: ['bar'],
};
spec1.customSeriesColors = new Map();
spec1.customSeriesColors.set(dataSeriesColorValues, 'custom_color');

const updatedCustomSeriesColors = getUpdatedCustomSeriesColors(specs);
const expectedCustomSeriesColors = new Map();
expectedCustomSeriesColors.set('specId:{spec1},colors:{bar}', 'custom_color');

expect(updatedCustomSeriesColors).toEqual(expectedCustomSeriesColors);
});
});
15 changes: 15 additions & 0 deletions src/state/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
DataSeries,
DataSeriesColorsValues,
FormattedDataSeries,
getColorValuesAsString,
getFormattedDataseries,
getSplittedSeries,
RawDataSeries,
Expand Down Expand Up @@ -89,6 +90,20 @@ export function updateSelectedDataSeries(
return updatedSeries;
}

export function getUpdatedCustomSeriesColors(seriesSpecs: Map<SpecId, BasicSeriesSpec>): Map<string, string> {
const updatedCustomSeriesColors = new Map();
seriesSpecs.forEach((spec: BasicSeriesSpec, id: SpecId) => {
if (spec.customSeriesColors) {
spec.customSeriesColors.forEach((color: string, seriesColorValues: DataSeriesColorsValues) => {
const { colorValues, specId } = seriesColorValues;
const seriesLabel = getColorValuesAsString(colorValues, specId);
updatedCustomSeriesColors.set(seriesLabel, color);
});
}
});
return updatedCustomSeriesColors;
}

export function computeSeriesDomains(
seriesSpecs: Map<SpecId, BasicSeriesSpec>,
selectedDataSeries?: DataSeriesColorsValues[] | null,
Expand Down
42 changes: 42 additions & 0 deletions stories/styling.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ import {
ScaleType,
Settings,
} from '../src/';
import { DataSeriesColorsValues } from '../src/lib/series/series';
import { CustomSeriesColorsMap } from '../src/lib/series/specs';
import * as TestDatasets from '../src/lib/series/utils/test_dataset';
import { DEFAULT_MISSING_COLOR } from '../src/lib/themes/theme_commons';

function range(
Expand Down Expand Up @@ -348,4 +351,43 @@ storiesOf('Stylings', module)
/>
</Chart>
);
})
.add('series colors', () => {
// const customSeriesColors: SpecsCustomSeriesColorsMap = new Map();
const customSeriesColors: CustomSeriesColorsMap = new Map();
const dataSeriesColorValues: DataSeriesColorsValues = {
colorValues: ['cloudflare.com', 'direct-cdn', 'y2'],
specId: getSpecId('bars'),
};
customSeriesColors.set(dataSeriesColorValues, '#000');

return (
<Chart renderer="canvas" className={'story-chart'}>
<Settings showLegend={true} legendPosition={Position.Right} />
<Axis
id={getAxisId('bottom')}
position={Position.Bottom}
title={'Bottom axis'}
showOverlappingTicks={true}
/>
<Axis
id={getAxisId('left2')}
title={'Left axis'}
position={Position.Left}
tickFormat={(d) => Number(d).toFixed(2)}
/>

<BarSeries
id={getSpecId('bars')}
xScaleType={ScaleType.Linear}
yScaleType={ScaleType.Linear}
xAccessor="x"
yAccessors={['y1', 'y2']}
splitSeriesAccessors={['g1', 'g2']}
customSeriesColors={customSeriesColors}
data={TestDatasets.BARCHART_2Y2G}
yScaleToDataExtent={false}
/>
</Chart>
);
});