NamedColors: Named colors refactors (#28235)

* NamedColors: Refactoring, performance improvements, and simplifications

* More simplifification

* Updated to use new function

* Updates

* Updates

* Updated BarGauge to use fallback color intead of magic string

* Updates

* Fixed unused import
This commit is contained in:
Torkel Ödegaard 2020-10-14 10:21:45 +02:00 committed by GitHub
parent 66def25c6d
commit 451836a86a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 186 additions and 268 deletions

View File

@ -3,7 +3,7 @@ import { fieldColorModeRegistry, FieldValueColorCalculator } from './fieldColor'
describe('fieldColorModeRegistry', () => { describe('fieldColorModeRegistry', () => {
interface GetCalcOptions { interface GetCalcOptions {
mode: FieldColorModeId; mode: string;
seriesIndex?: number; seriesIndex?: number;
} }
@ -16,7 +16,7 @@ describe('fieldColorModeRegistry', () => {
} }
it('Schemes should interpolate', () => { it('Schemes should interpolate', () => {
const calcFn = getCalculator({ mode: FieldColorModeId.ContinousGrYlRd }); const calcFn = getCalculator({ mode: 'continuous-GrYlRd' });
expect(calcFn(70, 0.5, undefined)).toEqual('rgb(226, 192, 61)'); expect(calcFn(70, 0.5, undefined)).toEqual('rgb(226, 192, 61)');
}); });

View File

@ -1,5 +1,5 @@
import { FALLBACK_COLOR, Field, FieldColorModeId, GrafanaTheme, Threshold } from '../types'; import { FALLBACK_COLOR, Field, FieldColorModeId, GrafanaTheme, Threshold } from '../types';
import { classicColors, getColorFromHexRgbOrName, RegistryItem } from '../utils'; import { classicColors, getColorForTheme, RegistryItem } from '../utils';
import { Registry } from '../utils/Registry'; import { Registry } from '../utils/Registry';
import { interpolateRgbBasis } from 'd3-interpolate'; import { interpolateRgbBasis } from 'd3-interpolate';
import { fallBackTreshold } from './thresholds'; import { fallBackTreshold } from './thresholds';
@ -23,64 +23,56 @@ export const fieldColorModeRegistry = new Registry<FieldColorMode>(() => {
}, },
{ {
id: FieldColorModeId.Thresholds, id: FieldColorModeId.Thresholds,
name: 'Color by thresholds', name: 'From thresholds',
description: 'Derive colors from thresholds', description: 'Derive colors from thresholds',
getCalculator: (_field, theme) => { getCalculator: (_field, theme) => {
return (_value, _percent, threshold) => { return (_value, _percent, threshold) => {
const thresholdSafe = threshold ?? fallBackTreshold; const thresholdSafe = threshold ?? fallBackTreshold;
return getColorFromHexRgbOrName(thresholdSafe.color, theme.type); return getColorForTheme(thresholdSafe.color, theme);
}; };
}, },
}, },
new FieldColorSchemeMode({ // new FieldColorSchemeMode({
id: FieldColorModeId.PaletteSaturated, // id: FieldColorModeId.PaletteSaturated,
name: 'Color by series / Saturated palette', // name: 'By series / Saturated palette',
//description: 'Assigns color based on series or field index', // //description: 'Assigns color based on series or field index',
isContinuous: false, // isContinuous: false,
isByValue: false, // isByValue: false,
colors: [ // colors: [
'blue', // 'blue',
'red', // 'red',
'green', // 'green',
'yellow', // 'yellow',
'purple', // 'purple',
'orange', // 'orange',
'dark-blue', // 'dark-blue',
'dark-red', // 'dark-red',
'dark-yellow', // 'dark-yellow',
'dark-purple', // 'dark-purple',
'dark-orange', // 'dark-orange',
], // ],
}), // }),
new FieldColorSchemeMode({ new FieldColorSchemeMode({
id: FieldColorModeId.PaletteClassic, id: FieldColorModeId.PaletteClassic,
name: 'Color by series / Classic palette', name: 'By series / Classic palette',
//description: 'Assigns color based on series or field index', //description: 'Assigns color based on series or field index',
isContinuous: false, isContinuous: false,
isByValue: false, isByValue: false,
colors: classicColors, colors: classicColors,
}), }),
new FieldColorSchemeMode({ new FieldColorSchemeMode({
id: FieldColorModeId.ContinousGrYlRd, id: 'continuous-GrYlRd',
name: 'Color by value / Green-Yellow-Red / Continouous', name: 'By value / Green Yellow Red (gradient)',
//description: 'Interpolated colors based value, min and max', //description: 'Interpolated colors based value, min and max',
isContinuous: true, isContinuous: true,
isByValue: true, isByValue: true,
colors: ['green', 'yellow', 'red'], colors: ['green', 'yellow', 'red'],
}), }),
new FieldColorSchemeMode({
id: FieldColorModeId.ContinousBlGrOr,
name: 'Color by value / Blue-Green-Orange / Continouous',
//description: 'Interpolated colors based value, min and max',
isContinuous: true,
isByValue: true,
colors: ['blue', 'green', 'orange'],
}),
]; ];
}); });
interface FieldColorSchemeModeOptions { interface FieldColorSchemeModeOptions {
id: FieldColorModeId; id: string;
name: string; name: string;
description?: string; description?: string;
colors: string[]; colors: string[];
@ -112,7 +104,7 @@ export class FieldColorSchemeMode implements FieldColorMode {
return this.colorCache; return this.colorCache;
} }
this.colorCache = this.colors.map(c => getColorFromHexRgbOrName(c, theme.type)); this.colorCache = this.colors.map(c => getColorForTheme(c, theme));
return this.colorCache; return this.colorCache;
} }
@ -157,6 +149,6 @@ export function getFieldColorMode(mode?: FieldColorModeId): FieldColorMode {
function getFixedColor(field: Field, theme: GrafanaTheme) { function getFixedColor(field: Field, theme: GrafanaTheme) {
return () => { return () => {
return getColorFromHexRgbOrName(field.config.color?.fixedColor ?? FALLBACK_COLOR, theme.type); return getColorForTheme(field.config.color?.fixedColor ?? FALLBACK_COLOR, theme);
}; };
} }

View File

@ -1,7 +1,5 @@
export enum FieldColorModeId { export enum FieldColorModeId {
Thresholds = 'thresholds', Thresholds = 'thresholds',
ContinousGrYlRd = 'continuous-GrYlRd',
ContinousBlGrOr = 'continuous-BlGrOr',
PaletteClassic = 'palette-classic', PaletteClassic = 'palette-classic',
PaletteSaturated = 'palette-saturated', PaletteSaturated = 'palette-saturated',
Fixed = 'fixed', Fixed = 'fixed',

View File

@ -1,48 +1,9 @@
import { import { getColorFromHexRgbOrName, getColorDefinitionByName } from './namedColorsPalette';
getColorName,
getColorDefinition,
getColorByName,
getColorFromHexRgbOrName,
getColorDefinitionByName,
} from './namedColorsPalette';
import { GrafanaThemeType } from '../types/theme'; import { GrafanaThemeType } from '../types/theme';
describe('colors', () => { describe('colors', () => {
const SemiDarkBlue = getColorDefinitionByName('semi-dark-blue'); const SemiDarkBlue = getColorDefinitionByName('semi-dark-blue');
describe('getColorDefinition', () => {
it('returns undefined for unknown hex', () => {
expect(getColorDefinition('#ff0000', GrafanaThemeType.Light)).toBeUndefined();
expect(getColorDefinition('#ff0000', GrafanaThemeType.Dark)).toBeUndefined();
});
it('returns definition for known hex', () => {
expect(getColorDefinition(SemiDarkBlue.variants.light, GrafanaThemeType.Light)).toEqual(SemiDarkBlue);
expect(getColorDefinition(SemiDarkBlue.variants.dark, GrafanaThemeType.Dark)).toEqual(SemiDarkBlue);
});
});
describe('getColorName', () => {
it('returns undefined for unknown hex', () => {
expect(getColorName('#ff0000')).toBeUndefined();
});
it('returns name for known hex', () => {
expect(getColorName(SemiDarkBlue.variants.light, GrafanaThemeType.Light)).toEqual(SemiDarkBlue.name);
expect(getColorName(SemiDarkBlue.variants.dark, GrafanaThemeType.Dark)).toEqual(SemiDarkBlue.name);
});
});
describe('getColorByName', () => {
it('returns undefined for unknown color', () => {
expect(getColorByName('aruba-sunshine')).toBeUndefined();
});
it('returns color definition for known color', () => {
expect(getColorByName(SemiDarkBlue.name)).toBe(SemiDarkBlue);
});
});
describe('getColorFromHexRgbOrName', () => { describe('getColorFromHexRgbOrName', () => {
it('returns black for unknown color', () => { it('returns black for unknown color', () => {
expect(getColorFromHexRgbOrName('aruba-sunshine')).toBe('#000000'); expect(getColorFromHexRgbOrName('aruba-sunshine')).toBe('#000000');
@ -57,7 +18,7 @@ describe('colors', () => {
}); });
it('returns color if specified as hex or rgb/a', () => { it('returns color if specified as hex or rgb/a', () => {
expect(getColorFromHexRgbOrName('ff0000')).toBe('ff0000'); expect(getColorFromHexRgbOrName('ff0000')).toBe('#ff0000');
expect(getColorFromHexRgbOrName('#ff0000')).toBe('#ff0000'); expect(getColorFromHexRgbOrName('#ff0000')).toBe('#ff0000');
expect(getColorFromHexRgbOrName('#FF0000')).toBe('#FF0000'); expect(getColorFromHexRgbOrName('#FF0000')).toBe('#FF0000');
expect(getColorFromHexRgbOrName('#CCC')).toBe('#CCC'); expect(getColorFromHexRgbOrName('#CCC')).toBe('#CCC');

View File

@ -1,6 +1,6 @@
import flatten from 'lodash/flatten'; import flatten from 'lodash/flatten';
import tinycolor from 'tinycolor2'; import tinycolor from 'tinycolor2';
import { GrafanaThemeType } from '../types/theme'; import { GrafanaTheme, GrafanaThemeType } from '../types/theme';
type Hue = 'green' | 'yellow' | 'red' | 'blue' | 'orange' | 'purple'; type Hue = 'green' | 'yellow' | 'red' | 'blue' | 'orange' | 'purple';
@ -49,6 +49,8 @@ export type ColorDefinition = {
}; };
let colorsPaletteInstance: Map<Hue, ColorDefinition[]>; let colorsPaletteInstance: Map<Hue, ColorDefinition[]>;
let colorsMap: Record<Color, string> | undefined;
let colorsMapTheme: GrafanaTheme | undefined;
const buildColorDefinition = ( const buildColorDefinition = (
hue: Hue, hue: Hue,
@ -65,61 +67,59 @@ const buildColorDefinition = (
isPrimary: !!isPrimary, isPrimary: !!isPrimary,
}); });
export const getColorDefinitionByName = (name: Color): ColorDefinition => { export function getColorDefinitionByName(name: Color): ColorDefinition {
return flatten(Array.from(getNamedColorPalette().values())).filter(definition => definition.name === name)[0]; return flatten(Array.from(getNamedColorPalette().values())).filter(definition => definition.name === name)[0];
}; }
export const getColorDefinition = (hex: string, theme: GrafanaThemeType): ColorDefinition | undefined => { export function buildColorsMapForTheme(theme: GrafanaTheme): Record<Color, string> {
return flatten(Array.from(getNamedColorPalette().values())).filter( theme = theme ?? GrafanaThemeType.Dark;
definition => definition.variants[theme] === hex
)[0];
};
const isHex = (color: string) => { colorsMap = {} as Record<Color, string>;
const hexRegex = /^((0x){0,1}|#{0,1})([0-9A-F]{8}|[0-9A-F]{6}|[0-9A-F]{3})$/gi;
return hexRegex.test(color);
};
export const getColorName = (color?: string, theme?: GrafanaThemeType): Color | undefined => { for (const def of getNamedColorPalette().values()) {
for (const c of def) {
colorsMap[c.name] = c.variants[theme.type];
}
}
return colorsMap;
}
export function getColorForTheme(color: string, theme: GrafanaTheme): string {
if (!color) { if (!color) {
return undefined; return 'gray';
}
// check if we need to rebuild cache
if (!colorsMap || colorsMapTheme !== theme) {
colorsMap = buildColorsMapForTheme(theme);
colorsMapTheme = theme;
}
let realColor = colorsMap[color as Color];
if (realColor) {
return realColor;
}
if (color[0] === '#') {
return (colorsMap[color as Color] = color);
} }
if (color.indexOf('rgb') > -1) { if (color.indexOf('rgb') > -1) {
return undefined; return (colorsMap[color as Color] = color);
}
if (isHex(color)) {
const definition = getColorDefinition(color, theme || GrafanaThemeType.Dark);
return definition ? definition.name : undefined;
} }
return color as Color; return (colorsMap[color as Color] = tinycolor(color).toHexString());
}; }
export const getColorByName = (colorName: string) => { /**
const definition = flatten(Array.from(getNamedColorPalette().values())).filter( * @deprecated use getColorForTheme
definition => definition.name === colorName */
); export function getColorFromHexRgbOrName(color: string, type?: GrafanaThemeType): string {
return definition.length > 0 ? definition[0] : undefined; const themeType = type ?? GrafanaThemeType.Dark;
};
export const getColorFromHexRgbOrName = (color: string, theme?: GrafanaThemeType): string => { return getColorForTheme(color, ({ type: themeType } as unknown) as GrafanaTheme);
if (color.indexOf('rgb') > -1 || isHex(color)) { }
return color;
}
const colorDefinition = getColorByName(color);
if (!colorDefinition) {
return new tinycolor(color).toHexString();
}
return theme ? colorDefinition.variants[theme] : colorDefinition.variants.dark;
};
export const getColorForTheme = (color: ColorDefinition, theme?: GrafanaThemeType) => {
return theme ? color.variants[theme] : color.variants.dark;
};
const buildNamedColorsPalette = () => { const buildNamedColorsPalette = () => {
const palette = new Map<Hue, ColorDefinition[]>(); const palette = new Map<Hue, ColorDefinition[]>();

View File

@ -4,7 +4,7 @@ import { useTheme } from '../../themes/ThemeContext';
import { stylesFactory } from '../../themes/stylesFactory'; import { stylesFactory } from '../../themes/stylesFactory';
import { IconName } from '../../types'; import { IconName } from '../../types';
import { Tooltip } from '../Tooltip/Tooltip'; import { Tooltip } from '../Tooltip/Tooltip';
import { getColorFromHexRgbOrName, GrafanaTheme } from '@grafana/data'; import { getColorForTheme, GrafanaTheme } from '@grafana/data';
import tinycolor from 'tinycolor2'; import tinycolor from 'tinycolor2';
import { css } from 'emotion'; import { css } from 'emotion';
import { HorizontalGroup } from '..'; import { HorizontalGroup } from '..';
@ -42,7 +42,7 @@ export const Badge = React.memo<BadgeProps>(({ icon, color, text, tooltip }) =>
Badge.displayName = 'Badge'; Badge.displayName = 'Badge';
const getStyles = stylesFactory((theme: GrafanaTheme, color: BadgeColor) => { const getStyles = stylesFactory((theme: GrafanaTheme, color: BadgeColor) => {
let sourceColor = getColorFromHexRgbOrName(color); let sourceColor = getColorForTheme(color, theme);
let borderColor = ''; let borderColor = '';
let bgColor = ''; let bgColor = '';
let textColor = ''; let textColor = '';

View File

@ -12,6 +12,8 @@ import {
FieldConfig, FieldConfig,
FieldColorModeId, FieldColorModeId,
getFieldColorMode, getFieldColorMode,
getColorForTheme,
FALLBACK_COLOR,
} from '@grafana/data'; } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors'; import { selectors } from '@grafana/e2e-selectors';
@ -19,7 +21,6 @@ import { selectors } from '@grafana/e2e-selectors';
import { FormattedValueDisplay } from '../FormattedValueDisplay/FormattedValueDisplay'; import { FormattedValueDisplay } from '../FormattedValueDisplay/FormattedValueDisplay';
// Utils // Utils
import { getColorFromHexRgbOrName } from '@grafana/data';
import { measureText, calculateFontSize } from '../../utils/measureText'; import { measureText, calculateFontSize } from '../../utils/measureText';
// Types // Types
@ -131,8 +132,8 @@ export class BarGauge extends PureComponent<Props> {
const { value, display } = this.props; const { value, display } = this.props;
if (positionValue === null) { if (positionValue === null) {
return { return {
background: 'gray', background: FALLBACK_COLOR,
border: 'gray', border: FALLBACK_COLOR,
}; };
} }
@ -165,8 +166,8 @@ export class BarGauge extends PureComponent<Props> {
} }
return { return {
background: 'gray', background: FALLBACK_COLOR,
border: 'gray', border: FALLBACK_COLOR,
}; };
} }
@ -526,7 +527,7 @@ export function getBarGradient(props: Props, maxSize: number): string {
for (let i = 0; i < thresholds.steps.length; i++) { for (let i = 0; i < thresholds.steps.length; i++) {
const threshold = thresholds.steps[i]; const threshold = thresholds.steps[i];
const color = getColorFromHexRgbOrName(threshold.color); const color = getColorForTheme(threshold.color, props.theme);
const valuePercent = getValuePercent(threshold.value, minValue, maxValue); const valuePercent = getValuePercent(threshold.value, minValue, maxValue);
const pos = valuePercent * maxSize; const pos = valuePercent * maxSize;
const offset = Math.round(pos - (pos - lastpos) / 2); const offset = Math.round(pos - (pos - lastpos) / 2);
@ -545,7 +546,7 @@ export function getBarGradient(props: Props, maxSize: number): string {
} }
if (mode.colors) { if (mode.colors) {
const scheme = mode.colors.map(item => getColorFromHexRgbOrName(item, theme.type)); const scheme = mode.colors.map(item => getColorForTheme(item, theme));
for (let i = 0; i < scheme.length; i++) { for (let i = 0; i < scheme.length; i++) {
const color = scheme[i]; const color = scheme[i];
@ -560,18 +561,19 @@ export function getBarGradient(props: Props, maxSize: number): string {
return gradient + ')'; return gradient + ')';
} }
return 'gray'; return value.color ?? FALLBACK_COLOR;
} }
/** /**
* Only exported to for unit test * Only exported to for unit test
*/ */
export function getValueColor(props: Props): string { export function getValueColor(props: Props): string {
const { theme, value } = props; const { value } = props;
if (value.color) { if (value.color) {
return value.color; return value.color;
} }
return getColorFromHexRgbOrName('gray', theme.type);
return FALLBACK_COLOR;
} }
function getValueStyles( function getValueStyles(
@ -582,7 +584,7 @@ function getValueStyles(
orientation: VizOrientation orientation: VizOrientation
): CSSProperties { ): CSSProperties {
const styles: CSSProperties = { const styles: CSSProperties = {
color: color, color,
height: `${height}px`, height: `${height}px`,
width: `${width}px`, width: `${width}px`,
display: 'flex', display: 'flex',

View File

@ -4,7 +4,7 @@ import tinycolor from 'tinycolor2';
import { Chart, Geom } from 'bizcharts'; import { Chart, Geom } from 'bizcharts';
// Utils // Utils
import { getColorFromHexRgbOrName, formattedValueToString, DisplayValue } from '@grafana/data'; import { formattedValueToString, DisplayValue, getColorForTheme } from '@grafana/data';
import { calculateFontSize } from '../../utils/measureText'; import { calculateFontSize } from '../../utils/measureText';
// Types // Types
@ -30,7 +30,7 @@ export abstract class BigValueLayout {
constructor(private props: Props) { constructor(private props: Props) {
const { width, height, value, theme } = props; const { width, height, value, theme } = props;
this.valueColor = getColorFromHexRgbOrName(value.color || 'green', theme.type); this.valueColor = getColorForTheme(value.color || 'green', theme);
this.panelPadding = height > 100 ? 12 : 8; this.panelPadding = height > 100 ? 12 : 8;
this.textValues = getTextValues(props); this.textValues = getTextValues(props);
this.justifyCenter = shouldJustifyCenter(props.justifyMode, this.textValues.title); this.justifyCenter = shouldJustifyCenter(props.justifyMode, this.textValues.title);

View File

@ -3,7 +3,7 @@ import omit from 'lodash/omit';
import { PopoverController } from '../Tooltip/PopoverController'; import { PopoverController } from '../Tooltip/PopoverController';
import { Popover } from '../Tooltip/Popover'; import { Popover } from '../Tooltip/Popover';
import { ColorPickerPopover, ColorPickerProps, ColorPickerChangeHandler } from './ColorPickerPopover'; import { ColorPickerPopover, ColorPickerProps, ColorPickerChangeHandler } from './ColorPickerPopover';
import { getColorFromHexRgbOrName } from '@grafana/data'; import { getColorForTheme } from '@grafana/data';
import { SeriesColorPickerPopover } from './SeriesColorPickerPopover'; import { SeriesColorPickerPopover } from './SeriesColorPickerPopover';
import { withTheme } from '../../themes/ThemeContext'; import { withTheme } from '../../themes/ThemeContext';
@ -74,7 +74,7 @@ export const colorPickerFactory = <T extends ColorPickerProps>(
ref={this.pickerTriggerRef} ref={this.pickerTriggerRef}
onClick={showPopper} onClick={showPopper}
onMouseLeave={hidePopper} onMouseLeave={hidePopper}
color={getColorFromHexRgbOrName(this.props.color || '#000000', theme.type)} color={getColorForTheme(this.props.color || '#000000', theme)}
/> />
)} )}
</> </>

View File

@ -4,18 +4,16 @@ import { ColorPickerPopover } from './ColorPickerPopover';
import { ColorSwatch } from './NamedColorsGroup'; import { ColorSwatch } from './NamedColorsGroup';
import flatten from 'lodash/flatten'; import flatten from 'lodash/flatten';
import { getTheme } from '../../themes'; import { getTheme } from '../../themes';
import { GrafanaThemeType, getColorDefinitionByName, getNamedColorPalette } from '@grafana/data'; import { GrafanaThemeType, getNamedColorPalette, getColorFromHexRgbOrName } from '@grafana/data';
const allColors = flatten(Array.from(getNamedColorPalette().values())); const allColors = flatten(Array.from(getNamedColorPalette().values()));
describe('ColorPickerPopover', () => { describe('ColorPickerPopover', () => {
const BasicGreen = getColorDefinitionByName('green');
const BasicBlue = getColorDefinitionByName('blue');
describe('rendering', () => { describe('rendering', () => {
it('should render provided color as selected if color provided by name', () => { it('should render provided color as selected if color provided by name', () => {
const wrapper = mount(<ColorPickerPopover color={BasicGreen.name} onChange={() => {}} theme={getTheme()} />); const theme = getTheme();
const selectedSwatch = wrapper.find(ColorSwatch).findWhere(node => node.key() === BasicGreen.name); const wrapper = mount(<ColorPickerPopover color={'green'} onChange={() => {}} theme={theme} />);
const selectedSwatch = wrapper.find(ColorSwatch).findWhere(node => node.key() === 'green');
const notSelectedSwatches = wrapper.find(ColorSwatch).filterWhere(node => node.prop('isSelected') === false); const notSelectedSwatches = wrapper.find(ColorSwatch).filterWhere(node => node.prop('isSelected') === false);
expect(selectedSwatch.length).toBe(1); expect(selectedSwatch.length).toBe(1);
@ -24,10 +22,10 @@ describe('ColorPickerPopover', () => {
}); });
it('should render provided color as selected if color provided by hex', () => { it('should render provided color as selected if color provided by hex', () => {
const wrapper = mount( const theme = getTheme();
<ColorPickerPopover color={BasicGreen.variants.dark} onChange={() => {}} theme={getTheme()} /> const wrapper = mount(<ColorPickerPopover color={'green'} onChange={() => {}} theme={theme} />);
);
const selectedSwatch = wrapper.find(ColorSwatch).findWhere(node => node.key() === BasicGreen.name); const selectedSwatch = wrapper.find(ColorSwatch).findWhere(node => node.key() === 'green');
const notSelectedSwatches = wrapper.find(ColorSwatch).filterWhere(node => node.prop('isSelected') === false); const notSelectedSwatches = wrapper.find(ColorSwatch).filterWhere(node => node.prop('isSelected') === false);
expect(selectedSwatch.length).toBe(1); expect(selectedSwatch.length).toBe(1);
@ -47,35 +45,31 @@ describe('ColorPickerPopover', () => {
it('should pass hex color value to onChange prop by default', () => { it('should pass hex color value to onChange prop by default', () => {
wrapper = mount( wrapper = mount(
<ColorPickerPopover <ColorPickerPopover color={'green'} onChange={onChangeSpy} theme={getTheme(GrafanaThemeType.Light)} />
color={BasicGreen.variants.dark}
onChange={onChangeSpy}
theme={getTheme(GrafanaThemeType.Light)}
/>
); );
const basicBlueSwatch = wrapper.find(ColorSwatch).findWhere(node => node.key() === BasicBlue.name);
const basicBlueSwatch = wrapper.find(ColorSwatch).findWhere(node => node.key() === 'green');
basicBlueSwatch.simulate('click'); basicBlueSwatch.simulate('click');
expect(onChangeSpy).toBeCalledTimes(1); expect(onChangeSpy).toBeCalledTimes(1);
expect(onChangeSpy).toBeCalledWith(BasicBlue.variants.light); expect(onChangeSpy).toBeCalledWith(getColorFromHexRgbOrName('green', GrafanaThemeType.Light));
}); });
it('should pass color name to onChange prop when named colors enabled', () => { it('should pass color name to onChange prop when named colors enabled', () => {
wrapper = mount( wrapper = mount(
<ColorPickerPopover <ColorPickerPopover
enableNamedColors enableNamedColors
color={BasicGreen.variants.dark} color={'green'}
onChange={onChangeSpy} onChange={onChangeSpy}
theme={getTheme(GrafanaThemeType.Light)} theme={getTheme(GrafanaThemeType.Light)}
/> />
); );
const basicBlueSwatch = wrapper.find(ColorSwatch).findWhere(node => node.key() === BasicBlue.name);
const basicBlueSwatch = wrapper.find(ColorSwatch).findWhere(node => node.key() === 'green');
basicBlueSwatch.simulate('click'); basicBlueSwatch.simulate('click');
expect(onChangeSpy).toBeCalledTimes(1); expect(onChangeSpy).toBeCalledTimes(1);
expect(onChangeSpy).toBeCalledWith(BasicBlue.name); expect(onChangeSpy).toBeCalledWith('green');
}); });
}); });
}); });

View File

@ -4,7 +4,7 @@ import { PopoverContentProps } from '../Tooltip/Tooltip';
import SpectrumPalette from './SpectrumPalette'; import SpectrumPalette from './SpectrumPalette';
import { Themeable } from '../../types/theme'; import { Themeable } from '../../types/theme';
import { warnAboutColorPickerPropsDeprecation } from './warnAboutColorPickerPropsDeprecation'; import { warnAboutColorPickerPropsDeprecation } from './warnAboutColorPickerPropsDeprecation';
import { GrafanaThemeType, getColorName, getColorFromHexRgbOrName } from '@grafana/data'; import { GrafanaThemeType, getColorForTheme } from '@grafana/data';
export type ColorPickerChangeHandler = (color: string) => void; export type ColorPickerChangeHandler = (color: string) => void;
@ -57,7 +57,7 @@ export class ColorPickerPopover<T extends CustomPickersDescriptor> extends React
if (enableNamedColors) { if (enableNamedColors) {
return changeHandler(color); return changeHandler(color);
} }
changeHandler(getColorFromHexRgbOrName(color, theme.type)); changeHandler(getColorForTheme(color, theme));
}; };
onTabChange = (tab: PickerType | keyof T) => { onTabChange = (tab: PickerType | keyof T) => {
@ -72,9 +72,7 @@ export class ColorPickerPopover<T extends CustomPickersDescriptor> extends React
case 'spectrum': case 'spectrum':
return <SpectrumPalette color={color} onChange={this.handleChange} theme={theme} />; return <SpectrumPalette color={color} onChange={this.handleChange} theme={theme} />;
case 'palette': case 'palette':
return ( return <NamedColorsPalette color={color} onChange={this.handleChange} theme={theme} />;
<NamedColorsPalette color={getColorName(color, theme.type)} onChange={this.handleChange} theme={theme} />
);
default: default:
return this.renderCustomPicker(activePicker); return this.renderCustomPicker(activePicker);
} }

View File

@ -1,6 +1,6 @@
import React, { FunctionComponent } from 'react'; import React, { FunctionComponent } from 'react';
import { Themeable } from '../../types'; import { Themeable } from '../../types';
import { ColorDefinition, getColorForTheme } from '@grafana/data'; import { ColorDefinition } from '@grafana/data';
import { Color } from 'csstype'; import { Color } from 'csstype';
import upperFirst from 'lodash/upperFirst'; import upperFirst from 'lodash/upperFirst';
import find from 'lodash/find'; import find from 'lodash/find';
@ -86,7 +86,7 @@ const NamedColorsGroup: FunctionComponent<NamedColorsGroupProps> = ({
key={primaryColor.name} key={primaryColor.name}
isSelected={primaryColor.name === selectedColor} isSelected={primaryColor.name === selectedColor}
variant={ColorSwatchVariant.Large} variant={ColorSwatchVariant.Large}
color={getColorForTheme(primaryColor, theme.type)} color={primaryColor.variants[theme.type]}
label={upperFirst(primaryColor.hue)} label={upperFirst(primaryColor.hue)}
onClick={() => onColorSelect(primaryColor)} onClick={() => onColorSelect(primaryColor)}
theme={theme} theme={theme}
@ -105,7 +105,7 @@ const NamedColorsGroup: FunctionComponent<NamedColorsGroupProps> = ({
<ColorSwatch <ColorSwatch
key={color.name} key={color.name}
isSelected={color.name === selectedColor} isSelected={color.name === selectedColor}
color={getColorForTheme(color, theme.type)} color={color.variants[theme.type]}
onClick={() => onColorSelect(color)} onClick={() => onColorSelect(color)}
theme={theme} theme={theme}
/> />

View File

@ -1,16 +1,11 @@
import React from 'react'; import React from 'react';
import { NamedColorsPalette } from './NamedColorsPalette'; import { NamedColorsPalette } from './NamedColorsPalette';
import { getColorName, getColorDefinitionByName } from '@grafana/data';
import { select } from '@storybook/addon-knobs'; import { select } from '@storybook/addon-knobs';
import { withCenteredStory } from '../../utils/storybook/withCenteredStory'; import { withCenteredStory } from '../../utils/storybook/withCenteredStory';
import { renderComponentWithTheme } from '../../utils/storybook/withTheme'; import { renderComponentWithTheme } from '../../utils/storybook/withTheme';
import { UseState } from '../../utils/storybook/UseState'; import { UseState } from '../../utils/storybook/UseState';
import mdx from './ColorPicker.mdx'; import mdx from './ColorPicker.mdx';
const BasicGreen = getColorDefinitionByName('green');
const BasicRed = getColorDefinitionByName('red');
const LightBlue = getColorDefinitionByName('light-blue');
export default { export default {
title: 'Pickers and Editors/ColorPicker/Palettes/NamedColorsPalette', title: 'Pickers and Editors/ColorPicker/Palettes/NamedColorsPalette',
component: NamedColorsPalette, component: NamedColorsPalette,
@ -44,22 +39,3 @@ export const namedColors = () => {
</UseState> </UseState>
); );
}; };
export const hexValues = () => {
let hexVals: any = {};
hexVals[BasicGreen.variants.dark] = BasicGreen.variants.dark;
hexVals[BasicRed.variants.dark] = BasicRed.variants.dark;
hexVals[LightBlue.variants.dark] = LightBlue.variants.dark;
const selectedColor = select('Selected color', hexVals, 'red');
return (
<UseState initialState={selectedColor}>
{(selectedColor, updateSelectedColor) => {
return renderComponentWithTheme(NamedColorsPalette, {
color: getColorName(selectedColor),
onChange: updateSelectedColor,
});
}}
</UseState>
);
};

View File

@ -1,10 +1,10 @@
import React from 'react'; import React from 'react';
import { Color, getNamedColorPalette } from '@grafana/data'; import { getNamedColorPalette } from '@grafana/data';
import { Themeable } from '../../types/index'; import { Themeable } from '../../types/index';
import NamedColorsGroup from './NamedColorsGroup'; import NamedColorsGroup from './NamedColorsGroup';
export interface NamedColorsPaletteProps extends Themeable { export interface NamedColorsPaletteProps extends Themeable {
color?: Color; color?: string;
onChange: (colorName: string) => void; onChange: (colorName: string) => void;
} }

View File

@ -6,7 +6,7 @@ import tinycolor from 'tinycolor2';
import ColorInput from './ColorInput'; import ColorInput from './ColorInput';
import { Themeable } from '../../types'; import { Themeable } from '../../types';
import SpectrumPalettePointer, { SpectrumPalettePointerProps } from './SpectrumPalettePointer'; import SpectrumPalettePointer, { SpectrumPalettePointerProps } from './SpectrumPalettePointer';
import { GrafanaTheme, getColorFromHexRgbOrName } from '@grafana/data'; import { GrafanaTheme, getColorForTheme } from '@grafana/data';
export interface SpectrumPaletteProps extends Themeable { export interface SpectrumPaletteProps extends Themeable {
color: string; color: string;
@ -86,7 +86,7 @@ const SpectrumPalette: React.FunctionComponent<SpectrumPaletteProps> = ({ color,
return ( return (
<div> <div>
<SpectrumPicker <SpectrumPicker
color={tinycolor(getColorFromHexRgbOrName(color)).toRgb()} color={tinycolor(getColorForTheme(color, theme)).toRgb()}
onChange={(a: ColorResult) => { onChange={(a: ColorResult) => {
onChange(tinycolor(a.rgb).toString()); onChange(tinycolor(a.rgb).toString());
}} }}

View File

@ -2,12 +2,12 @@ import React, { PureComponent } from 'react';
import $ from 'jquery'; import $ from 'jquery';
import { import {
DisplayValue, DisplayValue,
getColorFromHexRgbOrName,
formattedValueToString, formattedValueToString,
FieldConfig, FieldConfig,
ThresholdsMode, ThresholdsMode,
getActiveThreshold, getActiveThreshold,
Threshold, Threshold,
getColorForTheme,
} from '@grafana/data'; } from '@grafana/data';
import { Themeable } from '../../types'; import { Themeable } from '../../types';
import { selectThemeVariant } from '../../themes'; import { selectThemeVariant } from '../../themes';
@ -67,7 +67,7 @@ export class Gauge extends PureComponent<Props> {
const first = getActiveThreshold(min, steps); const first = getActiveThreshold(min, steps);
const last = getActiveThreshold(max, steps); const last = getActiveThreshold(max, steps);
const formatted: Threshold[] = []; const formatted: Threshold[] = [];
formatted.push({ value: +min.toFixed(decimals), color: getColorFromHexRgbOrName(first.color, theme.type) }); formatted.push({ value: +min.toFixed(decimals), color: getColorForTheme(first.color, theme) });
let skip = true; let skip = true;
for (let i = 0; i < steps.length; i++) { for (let i = 0; i < steps.length; i++) {
const step = steps[i]; const step = steps[i];
@ -78,12 +78,12 @@ export class Gauge extends PureComponent<Props> {
continue; continue;
} }
const prev = steps[i - 1]; const prev = steps[i - 1];
formatted.push({ value: step.value, color: getColorFromHexRgbOrName(prev!.color, theme.type) }); formatted.push({ value: step.value, color: getColorForTheme(prev!.color, theme) });
if (step === last) { if (step === last) {
break; break;
} }
} }
formatted.push({ value: +max.toFixed(decimals), color: getColorFromHexRgbOrName(last.color, theme.type) }); formatted.push({ value: +max.toFixed(decimals), color: getColorForTheme(last.color, theme) });
return formatted; return formatted;
} }

View File

@ -4,10 +4,10 @@ import {
FieldType, FieldType,
FieldCache, FieldCache,
FieldColorModeId, FieldColorModeId,
getColorFromHexRgbOrName,
GrafanaThemeType,
Field, Field,
getColorForTheme,
} from '@grafana/data'; } from '@grafana/data';
import { getTheme } from '../../themes';
import { getMultiSeriesGraphHoverInfo, findHoverIndexFromData, graphTimeFormat } from './utils'; import { getMultiSeriesGraphHoverInfo, findHoverIndexFromData, graphTimeFormat } from './utils';
const mockResult = ( const mockResult = (
@ -63,7 +63,7 @@ const cSeries = toDataFrame({
}); });
function getFixedThemedColor(field: Field): string { function getFixedThemedColor(field: Field): string {
return getColorFromHexRgbOrName(field.config.color!.fixedColor!, GrafanaThemeType.Dark); return getColorForTheme(field.config.color!.fixedColor!, getTheme());
} }
describe('Graph utils', () => { describe('Graph utils', () => {

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import { GrafanaTheme, getColorFromHexRgbOrName } from '@grafana/data'; import { getColorForTheme, GrafanaTheme } from '@grafana/data';
import { ColorPicker } from '../ColorPicker/ColorPicker'; import { ColorPicker } from '../ColorPicker/ColorPicker';
import { stylesFactory, useTheme } from '../../themes'; import { stylesFactory, useTheme } from '../../themes';
import { css } from 'emotion'; import { css } from 'emotion';
@ -25,7 +25,7 @@ export const ColorValueEditor: React.FC<Props> = ({ value, onChange }) => {
ref={ref} ref={ref}
onClick={showColorPicker} onClick={showColorPicker}
onMouseLeave={hideColorPicker} onMouseLeave={hideColorPicker}
color={value ? getColorFromHexRgbOrName(value, theme.type) : theme.colors.formInputBorder} color={value ? getColorForTheme(value, theme) : theme.colors.formInputBorder}
/> />
</div> </div>
{/* <div className={styles.colorText} onClick={showColorPicker}> {/* <div className={styles.colorText} onClick={showColorPicker}>

View File

@ -7,7 +7,7 @@ import {
fieldColorModeRegistry, fieldColorModeRegistry,
FieldColorMode, FieldColorMode,
GrafanaTheme, GrafanaTheme,
getColorFromHexRgbOrName, getColorForTheme,
} from '@grafana/data'; } from '@grafana/data';
import { Select } from '../Select/Select'; import { Select } from '../Select/Select';
import { ColorValueEditor } from './color'; import { ColorValueEditor } from './color';
@ -70,7 +70,7 @@ const FieldColorModeViz: FC<ModeProps> = ({ mode, theme }) => {
return null; return null;
} }
const colors = mode.colors.map(item => getColorFromHexRgbOrName(item, theme.type)); const colors = mode.colors.map(item => getColorForTheme(item, theme));
const style: CSSProperties = { const style: CSSProperties = {
height: '8px', height: '8px',
width: '100%', width: '100%',

View File

@ -1,10 +1,10 @@
import { AreaProps, LineProps, PointProps } from './types'; import { AreaProps, LineProps, PointProps } from './types';
import tinycolor from 'tinycolor2'; import tinycolor from 'tinycolor2';
import { getColorFromHexRgbOrName } from '@grafana/data';
export const getAreaConfig = (props: AreaProps) => { export const getAreaConfig = (props: AreaProps) => {
// TODO can we pass therem here? or make sure color is already correct?
const fill = props.fill const fill = props.fill
? tinycolor(getColorFromHexRgbOrName(props.color)) ? tinycolor(props.color)
.setAlpha(props.fill) .setAlpha(props.fill)
.toRgbString() .toRgbString()
: undefined; : undefined;

View File

@ -1,8 +1,9 @@
import React from 'react'; import React from 'react';
import { GraphCustomFieldConfig, GraphLegend, LegendDisplayMode, LegendItem } from '../..'; import { GraphCustomFieldConfig, GraphLegend, LegendDisplayMode, LegendItem } from '../..';
import { usePlotData } from '../context'; import { usePlotData } from '../context';
import { FieldType, getColorFromHexRgbOrName, getFieldDisplayName } from '@grafana/data'; import { FieldType, getColorForTheme, getFieldDisplayName } from '@grafana/data';
import { colors } from '../../../utils'; import { colors } from '../../../utils';
import { useTheme } from '../../../themes';
export type LegendPlacement = 'top' | 'bottom' | 'left' | 'right'; export type LegendPlacement = 'top' | 'bottom' | 'left' | 'right';
@ -13,6 +14,7 @@ interface LegendPluginProps {
export const LegendPlugin: React.FC<LegendPluginProps> = ({ placement, displayMode = LegendDisplayMode.List }) => { export const LegendPlugin: React.FC<LegendPluginProps> = ({ placement, displayMode = LegendDisplayMode.List }) => {
const { data } = usePlotData(); const { data } = usePlotData();
const theme = useTheme();
const legendItems: LegendItem[] = []; const legendItems: LegendItem[] = [];
@ -27,7 +29,7 @@ export const LegendPlugin: React.FC<LegendPluginProps> = ({ placement, displayMo
legendItems.push({ legendItems.push({
color: color:
field.config.color && field.config.color.fixedColor field.config.color && field.config.color.fixedColor
? getColorFromHexRgbOrName(field.config.color.fixedColor) ? getColorForTheme(field.config.color.fixedColor, theme)
: colors[seriesIdx], : colors[seriesIdx],
label: getFieldDisplayName(field, data), label: getFieldDisplayName(field, data),
isVisible: true, isVisible: true,

View File

@ -1,7 +1,6 @@
import _ from 'lodash'; import _ from 'lodash';
import { colors } from '@grafana/ui'; import { colors } from '@grafana/ui';
import { import {
getColorFromHexRgbOrName,
TimeRange, TimeRange,
FieldType, FieldType,
Field, Field,
@ -9,6 +8,7 @@ import {
getTimeField, getTimeField,
dateTime, dateTime,
getFieldDisplayName, getFieldDisplayName,
getColorForTheme,
} from '@grafana/data'; } from '@grafana/data';
import TimeSeries from 'app/core/time_series2'; import TimeSeries from 'app/core/time_series2';
import config from 'app/core/config'; import config from 'app/core/config';
@ -84,7 +84,7 @@ export class DataProcessor {
const series = new TimeSeries({ const series = new TimeSeries({
datapoints: datapoints || [], datapoints: datapoints || [],
alias: alias, alias: alias,
color: getColorFromHexRgbOrName(color, config.theme.type), color: getColorForTheme(color, config.theme),
unit: field.config ? field.config.unit : undefined, unit: field.config ? field.config.unit : undefined,
dataFrameIndex, dataFrameIndex,
fieldIndex, fieldIndex,

View File

@ -75,7 +75,7 @@ class GraphElement {
this.panelWidth = 0; this.panelWidth = 0;
this.eventManager = new EventManager(this.ctrl); this.eventManager = new EventManager(this.ctrl);
this.thresholdManager = new ThresholdManager(this.ctrl); this.thresholdManager = new ThresholdManager(this.ctrl);
this.timeRegionManager = new TimeRegionManager(this.ctrl, config.theme.type); this.timeRegionManager = new TimeRegionManager(this.ctrl);
// @ts-ignore // @ts-ignore
this.tooltip = new GraphTooltip(this.elem, this.ctrl.dashboard, this.scope, () => { this.tooltip = new GraphTooltip(this.elem, this.ctrl.dashboard, this.scope, () => {
return this.sortedSeries; return this.sortedSeries;

View File

@ -12,7 +12,7 @@ import { axesEditorComponent } from './axes_editor';
import config from 'app/core/config'; import config from 'app/core/config';
import TimeSeries from 'app/core/time_series2'; import TimeSeries from 'app/core/time_series2';
import { getProcessedDataFrames } from 'app/features/dashboard/state/runRequest'; import { getProcessedDataFrames } from 'app/features/dashboard/state/runRequest';
import { getColorFromHexRgbOrName, PanelEvents, PanelPlugin, DataFrame, FieldConfigProperty } from '@grafana/data'; import { PanelEvents, PanelPlugin, DataFrame, FieldConfigProperty, getColorForTheme } from '@grafana/data';
import { GraphContextMenuCtrl } from './GraphContextMenuCtrl'; import { GraphContextMenuCtrl } from './GraphContextMenuCtrl';
import { graphPanelMigrationHandler } from './GraphMigrations'; import { graphPanelMigrationHandler } from './GraphMigrations';
@ -327,7 +327,7 @@ export class GraphCtrl extends MetricsPanelCtrl {
} }
onColorChange = (series: any, color: string) => { onColorChange = (series: any, color: string) => {
series.setColor(getColorFromHexRgbOrName(color, config.theme.type)); series.setColor(getColorForTheme(color, config.theme));
this.panel.aliasColors[series.alias] = color; this.panel.aliasColors[series.alias] = color;
this.render(); this.render();
}; };

View File

@ -1,4 +1,5 @@
import angular from 'angular'; import angular from 'angular';
import { config } from 'app/core/config';
import TimeSeries from 'app/core/time_series2'; import TimeSeries from 'app/core/time_series2';
import { ThresholdManager } from '../threshold_manager'; import { ThresholdManager } from '../threshold_manager';
@ -31,6 +32,7 @@ describe('ThresholdManager', () => {
describe('When creating plot markings', () => { describe('When creating plot markings', () => {
plotOptionsScenario('for simple gt threshold', (ctx: any) => { plotOptionsScenario('for simple gt threshold', (ctx: any) => {
console.log('config', config.theme);
ctx.setup([{ op: 'gt', value: 300, fill: true, line: true, colorMode: 'critical' }]); ctx.setup([{ op: 'gt', value: 300, fill: true, line: true, colorMode: 'critical' }]);
it('should add fill for threshold with fill: true', () => { it('should add fill for threshold with fill: true', () => {

View File

@ -1,9 +1,10 @@
import 'vendor/flot/jquery.flot'; import 'vendor/flot/jquery.flot';
import $ from 'jquery'; import $ from 'jquery';
import _ from 'lodash'; import _ from 'lodash';
import { getColorFromHexRgbOrName } from '@grafana/data'; import { getColorForTheme } from '@grafana/data';
import { CoreEvents } from 'app/types'; import { CoreEvents } from 'app/types';
import { PanelCtrl } from 'app/features/panel/panel_ctrl'; import { PanelCtrl } from 'app/features/panel/panel_ctrl';
import { config } from 'app/core/config';
export class ThresholdManager { export class ThresholdManager {
plot: any; plot: any;
@ -228,12 +229,12 @@ export class ThresholdManager {
if (threshold.yaxis === 'right' && this.hasSecondYAxis) { if (threshold.yaxis === 'right' && this.hasSecondYAxis) {
options.grid.markings.push({ options.grid.markings.push({
y2axis: { from: threshold.value, to: limit }, y2axis: { from: threshold.value, to: limit },
color: getColorFromHexRgbOrName(fillColor), color: getColorForTheme(fillColor, config.theme),
}); });
} else { } else {
options.grid.markings.push({ options.grid.markings.push({
yaxis: { from: threshold.value, to: limit }, yaxis: { from: threshold.value, to: limit },
color: getColorFromHexRgbOrName(fillColor), color: getColorForTheme(fillColor, config.theme),
}); });
} }
} }
@ -241,12 +242,12 @@ export class ThresholdManager {
if (threshold.yaxis === 'right' && this.hasSecondYAxis) { if (threshold.yaxis === 'right' && this.hasSecondYAxis) {
options.grid.markings.push({ options.grid.markings.push({
y2axis: { from: threshold.value, to: threshold.value }, y2axis: { from: threshold.value, to: threshold.value },
color: getColorFromHexRgbOrName(lineColor), color: getColorForTheme(lineColor, config.theme),
}); });
} else { } else {
options.grid.markings.push({ options.grid.markings.push({
yaxis: { from: threshold.value, to: threshold.value }, yaxis: { from: threshold.value, to: threshold.value },
color: getColorFromHexRgbOrName(lineColor), color: getColorForTheme(lineColor, config.theme),
}); });
} }
} }

View File

@ -1,6 +1,7 @@
import 'vendor/flot/jquery.flot'; import 'vendor/flot/jquery.flot';
import _ from 'lodash'; import _ from 'lodash';
import { GrafanaThemeType, getColorFromHexRgbOrName, dateTime, DateTime, AbsoluteTimeRange } from '@grafana/data'; import { getColorForTheme, dateTime, DateTime, AbsoluteTimeRange, GrafanaTheme } from '@grafana/data';
import { config } from 'app/core/config';
type TimeRegionColorDefinition = { type TimeRegionColorDefinition = {
fill: string | null; fill: string | null;
@ -42,27 +43,27 @@ export function getColorModes() {
}); });
} }
function getColor(timeRegion: any, theme: GrafanaThemeType): TimeRegionColorDefinition { function getColor(timeRegion: any, theme: GrafanaTheme): TimeRegionColorDefinition {
if (Object.keys(colorModes).indexOf(timeRegion.colorMode) === -1) { if (Object.keys(colorModes).indexOf(timeRegion.colorMode) === -1) {
timeRegion.colorMode = 'red'; timeRegion.colorMode = 'red';
} }
if (timeRegion.colorMode === 'custom') { if (timeRegion.colorMode === 'custom') {
return { return {
fill: timeRegion.fill && timeRegion.fillColor ? getColorFromHexRgbOrName(timeRegion.fillColor, theme) : null, fill: timeRegion.fill && timeRegion.fillColor ? getColorForTheme(timeRegion.fillColor, theme) : null,
line: timeRegion.line && timeRegion.lineColor ? getColorFromHexRgbOrName(timeRegion.lineColor, theme) : null, line: timeRegion.line && timeRegion.lineColor ? getColorForTheme(timeRegion.lineColor, theme) : null,
}; };
} }
const colorMode = colorModes[timeRegion.colorMode]; const colorMode = colorModes[timeRegion.colorMode];
if (colorMode.themeDependent === true) { if (colorMode.themeDependent === true) {
return theme === GrafanaThemeType.Light ? colorMode.lightColor : colorMode.darkColor; return theme.isLight ? colorMode.lightColor : colorMode.darkColor;
} }
return { return {
fill: timeRegion.fill ? getColorFromHexRgbOrName(colorMode.color.fill, theme) : null, fill: timeRegion.fill ? getColorForTheme(colorMode.color.fill, theme) : null,
line: timeRegion.fill ? getColorFromHexRgbOrName(colorMode.color.line, theme) : null, line: timeRegion.fill ? getColorForTheme(colorMode.color.line, theme) : null,
}; };
} }
@ -70,7 +71,7 @@ export class TimeRegionManager {
plot: any; plot: any;
timeRegions: any; timeRegions: any;
constructor(private panelCtrl: any, private theme: GrafanaThemeType = GrafanaThemeType.Dark) {} constructor(private panelCtrl: any) {}
draw(plot: any) { draw(plot: any) {
this.timeRegions = this.panelCtrl.panel.timeRegions; this.timeRegions = this.panelCtrl.panel.timeRegions;
@ -204,7 +205,7 @@ export class TimeRegionManager {
fromStart.add(24, 'hours'); fromStart.add(24, 'hours');
} }
timeRegionColor = getColor(timeRegion, this.theme); timeRegionColor = getColor(timeRegion, config.theme);
for (let j = 0; j < regions.length; j++) { for (let j = 0; j < regions.length; j++) {
const r = regions[j]; const r = regions[j];

View File

@ -5,7 +5,8 @@ import { contextSrv } from 'app/core/core';
import { tickStep } from 'app/core/utils/ticks'; import { tickStep } from 'app/core/utils/ticks';
import { getColorScale, getOpacityScale } from './color_scale'; import { getColorScale, getOpacityScale } from './color_scale';
import coreModule from 'app/core/core_module'; import coreModule from 'app/core/core_module';
import { PanelEvents, GrafanaThemeType, getColorFromHexRgbOrName } from '@grafana/data'; import { PanelEvents, getColorForTheme } from '@grafana/data';
import { config } from 'app/core/config';
const LEGEND_HEIGHT_PX = 6; const LEGEND_HEIGHT_PX = 6;
const LEGEND_WIDTH_PX = 100; const LEGEND_WIDTH_PX = 100;
@ -272,13 +273,7 @@ function drawSimpleOpacityLegend(elem: JQuery, options: { colorScale: string; ex
.attr('width', rangeStep) .attr('width', rangeStep)
.attr('height', legendHeight) .attr('height', legendHeight)
.attr('stroke-width', 0) .attr('stroke-width', 0)
.attr( .attr('fill', getColorForTheme(options.cardColor, config.theme))
'fill',
getColorFromHexRgbOrName(
options.cardColor,
contextSrv.user.lightTheme ? GrafanaThemeType.Light : GrafanaThemeType.Dark
)
)
.style('opacity', d => legendOpacityScale(d)); .style('opacity', d => legendOpacityScale(d));
} }
} }

View File

@ -9,14 +9,14 @@ import { getColorScale, getOpacityScale } from './color_scale';
import { import {
toUtc, toUtc,
PanelEvents, PanelEvents,
GrafanaThemeType,
getColorFromHexRgbOrName,
getValueFormat, getValueFormat,
formattedValueToString, formattedValueToString,
dateTimeFormat, dateTimeFormat,
getColorForTheme,
} from '@grafana/data'; } from '@grafana/data';
import { graphTimeFormat } from '@grafana/ui'; import { graphTimeFormat } from '@grafana/ui';
import { CoreEvents } from 'app/types'; import { CoreEvents } from 'app/types';
import { config } from 'app/core/config';
const MIN_CARD_SIZE = 1, const MIN_CARD_SIZE = 1,
CARD_PADDING = 1, CARD_PADDING = 1,
@ -682,10 +682,7 @@ export class HeatmapRenderer {
getCardColor(d: { count: any }) { getCardColor(d: { count: any }) {
if (this.panel.color.mode === 'opacity') { if (this.panel.color.mode === 'opacity') {
return getColorFromHexRgbOrName( return getColorForTheme(this.panel.color.cardColor, config.theme);
this.panel.color.cardColor,
contextSrv.user.lightTheme ? GrafanaThemeType.Light : GrafanaThemeType.Dark
);
} else { } else {
return this.colorScale(d.count); return this.colorScale(d.count);
} }

View File

@ -19,11 +19,11 @@ import {
LegacyResponseData, LegacyResponseData,
getFlotPairs, getFlotPairs,
getDisplayProcessor, getDisplayProcessor,
getColorFromHexRgbOrName,
PanelEvents, PanelEvents,
formattedValueToString, formattedValueToString,
locationUtil, locationUtil,
getFieldDisplayName, getFieldDisplayName,
getColorForTheme,
} from '@grafana/data'; } from '@grafana/data';
import { convertOldAngularValueMapping } from '@grafana/ui'; import { convertOldAngularValueMapping } from '@grafana/ui';
@ -542,7 +542,7 @@ class SingleStatCtrl extends MetricsPanelCtrl {
show: true, show: true,
fill: 1, fill: 1,
lineWidth: 1, lineWidth: 1,
fillColor: getColorFromHexRgbOrName(panel.sparkline.fillColor, config.theme.type), fillColor: getColorForTheme(panel.sparkline.fillColor, config.theme),
zero: false, zero: false,
}, },
}, },
@ -564,7 +564,7 @@ class SingleStatCtrl extends MetricsPanelCtrl {
const plotSeries = { const plotSeries = {
data: data.sparkline, data: data.sparkline,
color: getColorFromHexRgbOrName(panel.sparkline.lineColor, config.theme.type), color: getColorForTheme(panel.sparkline.lineColor, config.theme),
}; };
$.plot(plotCanvas, [plotSeries], options); $.plot(plotCanvas, [plotSeries], options);
@ -585,7 +585,7 @@ class SingleStatCtrl extends MetricsPanelCtrl {
// Map panel colors to hex or rgb/a values // Map panel colors to hex or rgb/a values
if (panel.colors) { if (panel.colors) {
data.colorMap = panel.colors.map((color: string) => getColorFromHexRgbOrName(color, config.theme.type)); data.colorMap = panel.colors.map((color: string) => getColorForTheme(color, config.theme));
} }
const body = panel.gauge.show ? '' : getBigValueHtml(); const body = panel.gauge.show ? '' : getBigValueHtml();

View File

@ -129,7 +129,7 @@ export class TablePanelCtrl extends MetricsPanelCtrl {
this.dashboard.getTimezone(), this.dashboard.getTimezone(),
this.$sanitize, this.$sanitize,
this.templateSrv, this.templateSrv,
config.theme.type config.theme
); );
return super.render(this.table); return super.render(this.table);

View File

@ -2,9 +2,7 @@ import _ from 'lodash';
import { import {
escapeStringForRegex, escapeStringForRegex,
formattedValueToString, formattedValueToString,
getColorFromHexRgbOrName,
getValueFormat, getValueFormat,
GrafanaThemeType,
ScopedVars, ScopedVars,
stringStartsAsRegEx, stringStartsAsRegEx,
stringToJsRegex, stringToJsRegex,
@ -13,6 +11,8 @@ import {
TimeZone, TimeZone,
dateTimeFormatISO, dateTimeFormatISO,
dateTimeFormat, dateTimeFormat,
getColorForTheme,
GrafanaTheme,
} from '@grafana/data'; } from '@grafana/data';
import { getTemplateSrv, TemplateSrv } from '@grafana/runtime'; import { getTemplateSrv, TemplateSrv } from '@grafana/runtime';
import { ColumnRender, TableRenderModel, ColumnStyle } from './types'; import { ColumnRender, TableRenderModel, ColumnStyle } from './types';
@ -28,7 +28,7 @@ export class TableRenderer {
private timeZone: TimeZone, private timeZone: TimeZone,
private sanitize: (v: any) => any, private sanitize: (v: any) => any,
private templateSrv: TemplateSrv = getTemplateSrv(), private templateSrv: TemplateSrv = getTemplateSrv(),
private theme?: GrafanaThemeType private theme: GrafanaTheme
) { ) {
this.initColumns(); this.initColumns();
} }
@ -75,10 +75,10 @@ export class TableRenderer {
} }
for (let i = style.thresholds.length; i > 0; i--) { for (let i = style.thresholds.length; i > 0; i--) {
if (value >= style.thresholds[i - 1]) { if (value >= style.thresholds[i - 1]) {
return getColorFromHexRgbOrName(style.colors[i], this.theme); return getColorForTheme(style.colors[i], this.theme);
} }
} }
return getColorFromHexRgbOrName(_.first(style.colors), this.theme); return getColorForTheme(_.first(style.colors), this.theme);
} }
defaultCellFormatter(v: any, style: ColumnStyle) { defaultCellFormatter(v: any, style: ColumnStyle) {

View File

@ -1,8 +1,9 @@
import _ from 'lodash'; import _ from 'lodash';
import TableModel from 'app/core/table_model'; import TableModel from 'app/core/table_model';
import { TableRenderer } from '../renderer'; import { TableRenderer } from '../renderer';
import { getColorDefinitionByName, ScopedVars, TimeZone } from '@grafana/data'; import { ScopedVars, TimeZone } from '@grafana/data';
import { ColumnRender } from '../types'; import { ColumnRender } from '../types';
import { config } from 'app/core/config';
const utc: TimeZone = 'utc'; const utc: TimeZone = 'utc';
@ -23,8 +24,6 @@ const templateSrv = {
}; };
describe('when rendering table', () => { describe('when rendering table', () => {
const SemiDarkOrange = getColorDefinitionByName('semi-dark-orange');
describe('given 13 columns', () => { describe('given 13 columns', () => {
const table = new TableModel(); const table = new TableModel();
table.columns = [ table.columns = [
@ -87,7 +86,7 @@ describe('when rendering table', () => {
decimals: 1, decimals: 1,
colorMode: 'value', colorMode: 'value',
thresholds: [50, 80], thresholds: [50, 80],
colors: ['#00ff00', SemiDarkOrange.name, 'rgb(1,0,0)'], colors: ['#00ff00', 'semi-dark-orange', 'rgb(1,0,0)'],
}, },
{ {
pattern: 'String', pattern: 'String',
@ -178,7 +177,7 @@ describe('when rendering table', () => {
], ],
colorMode: 'value', colorMode: 'value',
thresholds: [1, 2], thresholds: [1, 2],
colors: ['#00ff00', SemiDarkOrange.name, 'rgb(1,0,0)'], colors: ['#00ff00', 'semi-dark-orange', 'rgb(1,0,0)'],
}, },
{ {
pattern: 'RangeMappingColored', pattern: 'RangeMappingColored',
@ -198,7 +197,7 @@ describe('when rendering table', () => {
], ],
colorMode: 'value', colorMode: 'value',
thresholds: [2, 5], thresholds: [2, 5],
colors: ['#00ff00', SemiDarkOrange.name, 'rgb(1,0,0)'], colors: ['#00ff00', 'semi-dark-orange', 'rgb(1,0,0)'],
}, },
{ {
pattern: 'HiddenType', pattern: 'HiddenType',
@ -212,7 +211,7 @@ describe('when rendering table', () => {
}; };
//@ts-ignore //@ts-ignore
const renderer = new TableRenderer(panel, table, utc, sanitize, templateSrv); const renderer = new TableRenderer(panel, table, utc, sanitize, templateSrv, config.theme);
it('time column should be formatted', () => { it('time column should be formatted', () => {
const html = renderer.renderCell(0, 0, 1388556366666); const html = renderer.renderCell(0, 0, 1388556366666);
@ -271,7 +270,7 @@ describe('when rendering table', () => {
it('colored cell should have style (handles named color values', () => { it('colored cell should have style (handles named color values', () => {
const html = renderer.renderCell(2, 0, 55); const html = renderer.renderCell(2, 0, 55);
expect(html).toBe(`<td style="color:${SemiDarkOrange.variants.dark}">55.0</td>`); expect(html).toBe(`<td style="color:${'#FF780A'}">55.0</td>`);
}); });
it('colored cell should have style handles(rgb color values)', () => { it('colored cell should have style handles(rgb color values)', () => {
@ -368,12 +367,12 @@ describe('when rendering table', () => {
it('value should be mapped to text and colored cell should have style', () => { it('value should be mapped to text and colored cell should have style', () => {
const html = renderer.renderCell(11, 0, 1); const html = renderer.renderCell(11, 0, 1);
expect(html).toBe(`<td style="color:${SemiDarkOrange.variants.dark}">on</td>`); expect(html).toBe(`<td style="color:${'#FF780A'}">on</td>`);
}); });
it('value should be mapped to text and colored cell should have style', () => { it('value should be mapped to text and colored cell should have style', () => {
const html = renderer.renderCell(11, 0, '1'); const html = renderer.renderCell(11, 0, '1');
expect(html).toBe(`<td style="color:${SemiDarkOrange.variants.dark}">on</td>`); expect(html).toBe(`<td style="color:${'#FF780A'}">on</td>`);
}); });
it('value should be mapped to text and colored cell should have style', () => { it('value should be mapped to text and colored cell should have style', () => {
@ -403,7 +402,7 @@ describe('when rendering table', () => {
it('value should be mapped to text (range) and colored cell should have style', () => { it('value should be mapped to text (range) and colored cell should have style', () => {
const html = renderer.renderCell(12, 0, 4); const html = renderer.renderCell(12, 0, 4);
expect(html).toBe(`<td style="color:${SemiDarkOrange.variants.dark}">off</td>`); expect(html).toBe(`<td style="color:${'#FF780A'}">off</td>`);
}); });
it('value should be mapped to text (range) and colored cell should have style', () => { it('value should be mapped to text (range) and colored cell should have style', () => {