Skip to content

Commit

Permalink
[Lens] Categorical color palettes (#75309)
Browse files Browse the repository at this point in the history
  • Loading branch information
flash1293 authored Nov 4, 2020
1 parent 7abb1e3 commit fe3b053
Show file tree
Hide file tree
Showing 123 changed files with 2,942 additions and 776 deletions.
33 changes: 33 additions & 0 deletions src/plugins/charts/common/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

// Currently supported palettes. This list might be extended dynamically in a later release
export const paletteIds = [
'default',
'kibana_palette',
'custom',
'status',
'temperature',
'complimentary',
'negative',
'positive',
'cool',
'warm',
'gray',
];
2 changes: 2 additions & 0 deletions src/plugins/charts/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,5 @@
*/

export const COLOR_MAPPING_SETTING = 'visualization:colorMapping';
export * from './palette';
export * from './constants';
102 changes: 102 additions & 0 deletions src/plugins/charts/common/palette.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import {
palette,
defaultCustomColors,
systemPalette,
PaletteOutput,
CustomPaletteState,
} from './palette';
import { functionWrapper } from 'src/plugins/expressions/common/expression_functions/specs/tests/utils';

describe('palette', () => {
const fn = functionWrapper(palette()) as (
context: null,
args?: { color?: string[]; gradient?: boolean; reverse?: boolean }
) => PaletteOutput<CustomPaletteState>;

it('results a palette', () => {
const result = fn(null);
expect(result).toHaveProperty('type', 'palette');
});

describe('args', () => {
describe('color', () => {
it('sets colors', () => {
const result = fn(null, { color: ['red', 'green', 'blue'] });
expect(result.params!.colors).toEqual(['red', 'green', 'blue']);
});

it('defaults to pault_tor_14 colors', () => {
const result = fn(null);
expect(result.params!.colors).toEqual(defaultCustomColors);
});
});

describe('gradient', () => {
it('sets gradient', () => {
let result = fn(null, { gradient: true });
expect(result.params).toHaveProperty('gradient', true);

result = fn(null, { gradient: false });
expect(result.params).toHaveProperty('gradient', false);
});

it('defaults to false', () => {
const result = fn(null);
expect(result.params).toHaveProperty('gradient', false);
});
});

describe('reverse', () => {
it('reverses order of the colors', () => {
const result = fn(null, { reverse: true });
expect(result.params!.colors).toEqual(defaultCustomColors.reverse());
});

it('keeps the original order of the colors', () => {
const result = fn(null, { reverse: false });
expect(result.params!.colors).toEqual(defaultCustomColors);
});

it(`defaults to 'false`, () => {
const result = fn(null);
expect(result.params!.colors).toEqual(defaultCustomColors);
});
});
});
});

describe('system_palette', () => {
const fn = functionWrapper(systemPalette()) as (
context: null,
args: { name: string; params?: unknown }
) => PaletteOutput<unknown>;

it('results a palette', () => {
const result = fn(null, { name: 'test' });
expect(result).toHaveProperty('type', 'palette');
});

it('returns the name', () => {
const result = fn(null, { name: 'test' });
expect(result).toHaveProperty('name', 'test');
});
});
160 changes: 160 additions & 0 deletions src/plugins/charts/common/palette.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common';
import { i18n } from '@kbn/i18n';
import { paletteIds } from './constants';

export interface CustomPaletteArguments {
color?: string[];
gradient: boolean;
reverse?: boolean;
}

export interface CustomPaletteState {
colors: string[];
gradient: boolean;
}

export interface SystemPaletteArguments {
name: string;
}

export interface PaletteOutput<T = unknown> {
type: 'palette';
name: string;
params?: T;
}
export const defaultCustomColors = [
// This set of defaults originated in Canvas, which, at present, is the primary
// consumer of this function. Changing this default requires a change in Canvas
// logic, which would likely be a breaking change in 7.x.
'#882E72',
'#B178A6',
'#D6C1DE',
'#1965B0',
'#5289C7',
'#7BAFDE',
'#4EB265',
'#90C987',
'#CAE0AB',
'#F7EE55',
'#F6C141',
'#F1932D',
'#E8601C',
'#DC050C',
];

export function palette(): ExpressionFunctionDefinition<
'palette',
null,
CustomPaletteArguments,
PaletteOutput<CustomPaletteState>
> {
return {
name: 'palette',
aliases: [],
type: 'palette',
inputTypes: ['null'],
help: i18n.translate('charts.functions.paletteHelpText', {
defaultMessage: 'Creates a color palette.',
}),
args: {
color: {
aliases: ['_'],
multi: true,
types: ['string'],
help: i18n.translate('charts.functions.palette.args.colorHelpText', {
defaultMessage:
'The palette colors. Accepts an {html} color name, {hex}, {hsl}, {hsla}, {rgb}, or {rgba}.',
values: {
html: 'HTML',
rgb: 'RGB',
rgba: 'RGBA',
hex: 'HEX',
hsl: 'HSL',
hsla: 'HSLA',
},
}),
required: false,
},
gradient: {
types: ['boolean'],
default: false,
help: i18n.translate('charts.functions.palette.args.gradientHelpText', {
defaultMessage: 'Make a gradient palette where supported?',
}),
options: [true, false],
},
reverse: {
types: ['boolean'],
default: false,
help: i18n.translate('charts.functions.palette.args.reverseHelpText', {
defaultMessage: 'Reverse the palette?',
}),
options: [true, false],
},
},
fn: (input, args) => {
const { color, reverse, gradient } = args;
const colors = ([] as string[]).concat(color || defaultCustomColors);

return {
type: 'palette',
name: 'custom',
params: {
colors: reverse ? colors.reverse() : colors,
gradient,
},
};
},
};
}

export function systemPalette(): ExpressionFunctionDefinition<
'system_palette',
null,
SystemPaletteArguments,
PaletteOutput
> {
return {
name: 'system_palette',
aliases: [],
type: 'palette',
inputTypes: ['null'],
help: i18n.translate('charts.functions.systemPaletteHelpText', {
defaultMessage: 'Creates a dynamic color palette.',
}),
args: {
name: {
types: ['string'],
help: i18n.translate('charts.functions.systemPalette.args.nameHelpText', {
defaultMessage: 'Name of the palette in the palette list',
}),
options: paletteIds,
},
},
fn: (input, args) => {
return {
type: 'palette',
name: args.name,
};
},
};
}
1 change: 1 addition & 0 deletions src/plugins/charts/kibana.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
"version": "kibana",
"server": true,
"ui": true,
"requiredPlugins": ["expressions"],
"requiredBundles": ["visDefaultEditor"]
}
11 changes: 9 additions & 2 deletions src/plugins/charts/public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,14 @@ import { ChartsPlugin } from './plugin';

export const plugin = () => new ChartsPlugin();

export type ChartsPluginSetup = ReturnType<ChartsPlugin['setup']>;
export type ChartsPluginStart = ReturnType<ChartsPlugin['start']>;
export { ChartsPluginSetup, ChartsPluginStart } from './plugin';

export * from './static';
export * from './services/palettes/types';
export {
PaletteOutput,
CustomPaletteArguments,
CustomPaletteState,
SystemPaletteArguments,
paletteIds,
} from '../common';
10 changes: 7 additions & 3 deletions src/plugins/charts/public/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,28 @@

import { ChartsPlugin } from './plugin';
import { themeServiceMock } from './services/theme/mock';
import { colorsServiceMock } from './services/colors/mock';
import { colorsServiceMock } from './services/legacy_colors/mock';
import { getPaletteRegistry, paletteServiceMock } from './services/palettes/mock';

export type Setup = jest.Mocked<ReturnType<ChartsPlugin['setup']>>;
export type Start = jest.Mocked<ReturnType<ChartsPlugin['start']>>;

const createSetupContract = (): Setup => ({
colors: colorsServiceMock,
legacyColors: colorsServiceMock,
theme: themeServiceMock,
palettes: paletteServiceMock.setup({} as any, {} as any),
});

const createStartContract = (): Start => ({
colors: colorsServiceMock,
legacyColors: colorsServiceMock,
theme: themeServiceMock,
palettes: paletteServiceMock.setup({} as any, {} as any),
});

export { colorMapsMock } from './static/color_maps/mock';

export const chartPluginMock = {
createSetupContract,
createStartContract,
createPaletteRegistry: getPaletteRegistry,
};
Loading

0 comments on commit fe3b053

Please sign in to comment.