mirror of
https://github.com/grafana/grafana.git
synced 2025-02-10 23:55:47 -06:00
Rendering arrows for color picker, applying color changes to time series
This commit is contained in:
parent
e35e266c81
commit
c8ac23f3c1
@ -2,9 +2,9 @@ import React, { Component, createRef } from 'react';
|
||||
import PopperController from '../Tooltip/PopperController';
|
||||
import Popper from '../Tooltip/Popper';
|
||||
import { ColorPickerPopover } from './ColorPickerPopover';
|
||||
import { Themeable } from '../../types';
|
||||
import { Themeable, GrafanaTheme } from '../../types';
|
||||
|
||||
export interface ColorPickerProps {
|
||||
export interface ColorPickerProps extends Themeable {
|
||||
color: string;
|
||||
onChange: (color: string) => void;
|
||||
}
|
||||
@ -13,13 +13,29 @@ export class ColorPicker extends Component<ColorPickerProps & Themeable, any> {
|
||||
private pickerTriggerRef = createRef<HTMLDivElement>();
|
||||
|
||||
render() {
|
||||
const { theme } = this.props;
|
||||
return (
|
||||
<PopperController content={<ColorPickerPopover {...this.props} />}>
|
||||
<PopperController placement="bottom-start" content={<ColorPickerPopover {...this.props} />}>
|
||||
{(showPopper, hidePopper, popperProps) => {
|
||||
return (
|
||||
<>
|
||||
{this.pickerTriggerRef.current && (
|
||||
<Popper {...popperProps} referenceElement={this.pickerTriggerRef.current} className="ColorPicker" />
|
||||
<Popper
|
||||
{...popperProps}
|
||||
referenceElement={this.pickerTriggerRef.current}
|
||||
className="ColorPicker"
|
||||
renderArrow={({ arrowProps, placement }) => {
|
||||
return (
|
||||
<div
|
||||
{...arrowProps}
|
||||
data-placement={placement}
|
||||
className={`ColorPicker__arrow ColorPicker__arrow--${
|
||||
theme === GrafanaTheme.Light ? 'light' : 'dark'
|
||||
}`}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<div ref={this.pickerTriggerRef} onClick={showPopper} className="sp-replacer sp-light">
|
||||
<div className="sp-preview">
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import NamedColorsPicker from './NamedColorsPicker';
|
||||
import NamedColorsPicker from './NamedColorsPalette';
|
||||
import { getColorName } from '../..//utils/colorsPalette';
|
||||
import { SpectrumPicker } from './SpectrumPicker';
|
||||
import { SpectrumPalette } from './SpectrumPalette';
|
||||
import { ColorPickerProps } from './ColorPicker';
|
||||
import { GrafanaTheme, Themeable } from '../../types';
|
||||
|
||||
@ -32,7 +32,7 @@ export class ColorPickerPopover extends React.Component<Props, State> {
|
||||
const { color, onChange, theme } = this.props;
|
||||
|
||||
return activePicker === 'spectrum' ? (
|
||||
<SpectrumPicker color={color} onColorSelect={this.handleSpectrumColorSelect} options={{}} />
|
||||
<SpectrumPalette color={color} onColorSelect={this.handleSpectrumColorSelect} options={{}} />
|
||||
) : (
|
||||
<NamedColorsPicker color={getColorName(color)} onChange={onChange} theme={theme} />
|
||||
);
|
||||
|
@ -1,11 +1,12 @@
|
||||
import React, { FunctionComponent } from 'react';
|
||||
import { find, upperFirst } from 'lodash';
|
||||
import { Color, ColorsPalete, ColorDefinition, getColorForTheme } from '../../utils/colorsPalette';
|
||||
import { Themeable } from '../../types';
|
||||
import { ColorDefinition, getColorForTheme } from '../../utils/colorsPalette';
|
||||
import { Color } from 'csstype';
|
||||
import { find, upperFirst } from 'lodash';
|
||||
|
||||
type ColorChangeHandler = (color: ColorDefinition) => void;
|
||||
|
||||
enum ColorSwatchVariant {
|
||||
export enum ColorSwatchVariant {
|
||||
Small = 'small',
|
||||
Large = 'large',
|
||||
}
|
||||
@ -50,14 +51,14 @@ const ColorSwatch: FunctionComponent<ColorSwatchProps> = ({
|
||||
);
|
||||
};
|
||||
|
||||
interface ColorsGroupProps extends Themeable {
|
||||
interface NamedColorsGroupProps extends Themeable {
|
||||
colors: ColorDefinition[];
|
||||
selectedColor?: Color;
|
||||
onColorSelect: ColorChangeHandler;
|
||||
key?: string;
|
||||
}
|
||||
|
||||
const ColorsGroup: FunctionComponent<ColorsGroupProps> = ({
|
||||
const NamedColorsGroup: FunctionComponent<NamedColorsGroupProps> = ({
|
||||
colors,
|
||||
selectedColor,
|
||||
onColorSelect,
|
||||
@ -100,37 +101,4 @@ const ColorsGroup: FunctionComponent<ColorsGroupProps> = ({
|
||||
);
|
||||
};
|
||||
|
||||
interface NamedColorsPickerProps extends Themeable {
|
||||
color?: Color;
|
||||
onChange: (colorName: string) => void;
|
||||
}
|
||||
|
||||
const NamedColorsPicker = ({ color, onChange, theme }: NamedColorsPickerProps) => {
|
||||
const swatches: JSX.Element[] = [];
|
||||
ColorsPalete.forEach((colors, hue) => {
|
||||
swatches.push(
|
||||
<ColorsGroup
|
||||
key={hue}
|
||||
theme={theme}
|
||||
selectedColor={color}
|
||||
colors={colors}
|
||||
onColorSelect={color => onChange(color.name)}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
display: 'grid',
|
||||
gridTemplateColumns: 'repeat(3, 1fr)',
|
||||
gridRowGap: '32px',
|
||||
gridColumnGap: '32px',
|
||||
}}
|
||||
>
|
||||
{swatches}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default NamedColorsPicker;
|
||||
export default NamedColorsGroup;
|
@ -0,0 +1,42 @@
|
||||
import React from 'react';
|
||||
import { Color, ColorsPalette } from '../../utils/colorsPalette';
|
||||
import { Themeable } from '../../types/index';
|
||||
import NamedColorsGroup from './NamedColorsGroup';
|
||||
|
||||
interface NamedColorsPaletteProps extends Themeable {
|
||||
color?: Color;
|
||||
onChange: (colorName: string) => void;
|
||||
}
|
||||
|
||||
const NamedColorsPalette = ({ color, onChange, theme }: NamedColorsPaletteProps) => {
|
||||
const swatches: JSX.Element[] = [];
|
||||
|
||||
ColorsPalette.forEach((colors, hue) => {
|
||||
swatches.push(
|
||||
<NamedColorsGroup
|
||||
key={hue}
|
||||
theme={theme}
|
||||
selectedColor={color}
|
||||
colors={colors}
|
||||
onColorSelect={color => {
|
||||
onChange(color.name)
|
||||
}}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
display: 'grid',
|
||||
gridTemplateColumns: 'repeat(3, 1fr)',
|
||||
gridRowGap: '32px',
|
||||
gridColumnGap: '32px',
|
||||
}}
|
||||
>
|
||||
{swatches}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default NamedColorsPalette;
|
@ -3,7 +3,7 @@ import * as PopperJS from 'popper.js';
|
||||
import { SeriesColorPickerPopover } from './SeriesColorPickerPopover';
|
||||
import PopperController from '../Tooltip/PopperController';
|
||||
import Popper from '../Tooltip/Popper';
|
||||
import { Themeable } from '../../types';
|
||||
import { Themeable, GrafanaTheme } from '../../types';
|
||||
import { ColorPickerProps } from './ColorPicker';
|
||||
|
||||
export interface SeriesColorPickerProps extends ColorPickerProps, Themeable {
|
||||
@ -37,7 +37,7 @@ export class SeriesColorPicker extends React.Component<SeriesColorPickerProps> {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { children } = this.props;
|
||||
const { children, theme } = this.props;
|
||||
return (
|
||||
<PopperController placement="bottom-start" content={this.renderPickerTabs()}>
|
||||
{(showPopper, hidePopper, popperProps) => {
|
||||
@ -49,10 +49,21 @@ export class SeriesColorPicker extends React.Component<SeriesColorPickerProps> {
|
||||
onMouseEnter={showPopper}
|
||||
onMouseLeave={hidePopper}
|
||||
referenceElement={this.pickerTriggerRef.current}
|
||||
className="ColorPicker"
|
||||
arrowClassName="popper__arrow"
|
||||
wrapperClassName="ColorPicker"
|
||||
renderArrow={({ arrowProps, placement }) => {
|
||||
return (
|
||||
<div
|
||||
{...arrowProps}
|
||||
data-placement={placement}
|
||||
className={`ColorPicker__arrow ColorPicker__arrow--${
|
||||
theme === GrafanaTheme.Light ? 'light' : 'dark'
|
||||
}`}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{React.cloneElement(children, {
|
||||
ref: this.pickerTriggerRef,
|
||||
onClick: showPopper,
|
||||
|
@ -9,7 +9,7 @@ export interface Props {
|
||||
onColorSelect: (color: string) => void;
|
||||
}
|
||||
|
||||
export class SpectrumPicker extends React.Component<Props, any> {
|
||||
export class SpectrumPalette extends React.Component<Props, any> {
|
||||
elem: any;
|
||||
isMoving: boolean;
|
||||
|
@ -1,12 +1,107 @@
|
||||
$arrowSize: 10px;
|
||||
.ColorPicker {
|
||||
.popper__arrow {
|
||||
border-color: #f7f8fa;
|
||||
}
|
||||
@extend .popper;
|
||||
}
|
||||
|
||||
.ColorPicker__arrow {
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-style: solid;
|
||||
position: absolute;
|
||||
margin: 0px;
|
||||
|
||||
&[data-placement^='top'] {
|
||||
border-width: $arrowSize $arrowSize 0 $arrowSize;
|
||||
border-left-color: transparent;
|
||||
border-right-color: transparent;
|
||||
border-bottom-color: transparent;
|
||||
bottom: -$arrowSize;
|
||||
left: calc(50% - $arrowSize);
|
||||
padding-top: $arrowSize;
|
||||
}
|
||||
|
||||
&[data-placement^='bottom'] {
|
||||
border-width: 0 $arrowSize $arrowSize $arrowSize;
|
||||
border-left-color: transparent;
|
||||
border-right-color: transparent;
|
||||
border-top-color: transparent;
|
||||
top: 0;
|
||||
left: calc(50% - $arrowSize);
|
||||
}
|
||||
|
||||
&[data-placement^='bottom-start'] {
|
||||
border-width: 0 $arrowSize $arrowSize $arrowSize;
|
||||
border-left-color: transparent;
|
||||
border-right-color: transparent;
|
||||
border-top-color: transparent;
|
||||
top: 0;
|
||||
left: $arrowSize;
|
||||
}
|
||||
|
||||
&[data-placement^='bottom-end'] & {
|
||||
border-width: 0 $arrowSize $arrowSize $arrowSize;
|
||||
border-left-color: transparent;
|
||||
border-right-color: transparent;
|
||||
border-top-color: transparent;
|
||||
top: 0;
|
||||
left: calc(100% - $arrowSize);
|
||||
}
|
||||
|
||||
&[data-placement^='right'] {
|
||||
border-width: $arrowSize $arrowSize $arrowSize 0;
|
||||
border-left-color: transparent;
|
||||
border-top-color: transparent;
|
||||
border-bottom-color: transparent;
|
||||
left: 0;
|
||||
top: calc(50% - $arrowSize);
|
||||
}
|
||||
|
||||
&[data-placement^='left'] {
|
||||
border-width: $arrowSize 0 $arrowSize $arrowSize;
|
||||
border-top-color: transparent;
|
||||
border-right-color: transparent;
|
||||
border-bottom-color: transparent;
|
||||
right: -$arrowSize;
|
||||
top: calc(50% - $arrowSize);
|
||||
}
|
||||
}
|
||||
|
||||
.ColorPicker__arrow--light {
|
||||
border-color: #ffffff;
|
||||
}
|
||||
|
||||
.ColorPicker__arrow--dark {
|
||||
border-color: #1e2028;
|
||||
}
|
||||
|
||||
// Top
|
||||
.ColorPicker[data-placement^='top'] {
|
||||
padding-bottom: $arrowSize;
|
||||
}
|
||||
|
||||
// Bottom
|
||||
.ColorPicker[data-placement^='bottom'] {
|
||||
padding-top: $arrowSize;
|
||||
}
|
||||
|
||||
.ColorPicker[data-placement^='bottom-start'] {
|
||||
padding-top: $arrowSize;
|
||||
}
|
||||
|
||||
.ColorPicker[data-placement^='bottom-end'] {
|
||||
padding-top: $arrowSize;
|
||||
}
|
||||
|
||||
// Right
|
||||
.ColorPicker[data-placement^='right'] {
|
||||
padding-left: $arrowSize;
|
||||
}
|
||||
|
||||
// Left
|
||||
.ColorPicker[data-placement^='left'] {
|
||||
padding-right: $arrowSize;
|
||||
}
|
||||
|
||||
.ColorPickerPopover {
|
||||
border-radius: 3px;
|
||||
}
|
||||
@ -93,7 +188,7 @@
|
||||
}
|
||||
|
||||
.gf-color-picker__body {
|
||||
padding-bottom: 10px;
|
||||
padding-bottom: $arrowSize;
|
||||
padding-left: 6px;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import * as PopperJS from 'popper.js';
|
||||
import { Manager, Popper as ReactPopper } from 'react-popper';
|
||||
import { Manager, Popper as ReactPopper, PopperArrowProps } from 'react-popper';
|
||||
import { Portal } from '@grafana/ui';
|
||||
import Transition from 'react-transition-group/Transition';
|
||||
import { PopperContent } from './PopperController';
|
||||
@ -22,12 +22,18 @@ interface Props extends React.HTMLAttributes<HTMLDivElement> {
|
||||
placement?: PopperJS.Placement;
|
||||
content: PopperContent;
|
||||
referenceElement: PopperJS.ReferenceObject;
|
||||
arrowClassName?: string;
|
||||
wrapperClassName?: string;
|
||||
renderArrow?: (
|
||||
props: {
|
||||
arrowProps: PopperArrowProps;
|
||||
placement: string;
|
||||
}
|
||||
) => JSX.Element;
|
||||
}
|
||||
|
||||
class Popper extends PureComponent<Props> {
|
||||
render() {
|
||||
const { show, placement, onMouseEnter, onMouseLeave, className, arrowClassName } = this.props;
|
||||
const { show, placement, onMouseEnter, onMouseLeave, className, wrapperClassName, renderArrow } = this.props;
|
||||
const { content } = this.props;
|
||||
|
||||
return (
|
||||
@ -53,16 +59,15 @@ class Popper extends PureComponent<Props> {
|
||||
...transitionStyles[transitionState],
|
||||
}}
|
||||
data-placement={placement}
|
||||
className={`popper`}
|
||||
className={`${wrapperClassName}`}
|
||||
>
|
||||
<div className={className}>
|
||||
{content}
|
||||
<div
|
||||
ref={arrowProps.ref}
|
||||
style={{ ...arrowProps.style }}
|
||||
data-placement={placement}
|
||||
className={arrowClassName}
|
||||
/>
|
||||
{renderArrow &&
|
||||
renderArrow({
|
||||
arrowProps,
|
||||
placement,
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -27,8 +27,11 @@ export const Tooltip = ({ children, theme, ...controllerProps }: TooltipProps) =
|
||||
onMouseEnter={showPopper}
|
||||
onMouseLeave={hidePopper}
|
||||
referenceElement={tooltipTriggerRef.current}
|
||||
wrapperClassName='popper'
|
||||
className={popperBackgroundClassName}
|
||||
arrowClassName={'popper__arrow'}
|
||||
renderArrow={({ arrowProps, placement }) => (
|
||||
<div className="popper__arrow" data-placement={placement} {...arrowProps} />
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
{React.cloneElement(children, {
|
||||
|
@ -44,7 +44,6 @@ $popper-margin-from-ref: 5px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
|
||||
// Top
|
||||
.popper[data-placement^='top'] {
|
||||
padding-bottom: $popper-margin-from-ref;
|
||||
|
@ -1,11 +1,7 @@
|
||||
import { getColorName, getColorDefinition, ColorsPalete, buildColorDefinition } from './colorsPalette';
|
||||
import { getColorName, getColorDefinition, getColorByName, SemiDarkBlue, getColorFromHexRgbOrName } from './colorsPalette';
|
||||
import { GrafanaTheme } from '../types';
|
||||
|
||||
describe('colors', () => {
|
||||
const FakeBlue = buildColorDefinition('blue', 'blue', ['#0000ff', '#00000ee']);
|
||||
|
||||
beforeAll(() => {
|
||||
ColorsPalete.set('blue', [FakeBlue]);
|
||||
});
|
||||
|
||||
describe('getColorDefinition', () => {
|
||||
it('returns undefined for unknown hex', () => {
|
||||
@ -13,8 +9,8 @@ describe('colors', () => {
|
||||
});
|
||||
|
||||
it('returns definition for known hex', () => {
|
||||
expect(getColorDefinition(FakeBlue.variants.light)).toEqual(FakeBlue);
|
||||
expect(getColorDefinition(FakeBlue.variants.dark)).toEqual(FakeBlue);
|
||||
expect(getColorDefinition(SemiDarkBlue.variants.light)).toEqual(SemiDarkBlue);
|
||||
expect(getColorDefinition(SemiDarkBlue.variants.dark)).toEqual(SemiDarkBlue);
|
||||
});
|
||||
});
|
||||
|
||||
@ -24,8 +20,39 @@ describe('colors', () => {
|
||||
});
|
||||
|
||||
it('returns name for known hex', () => {
|
||||
expect(getColorName(FakeBlue.variants.light)).toEqual(FakeBlue.name);
|
||||
expect(getColorName(FakeBlue.variants.dark)).toEqual(FakeBlue.name);
|
||||
expect(getColorName(SemiDarkBlue.variants.light)).toEqual(SemiDarkBlue.name);
|
||||
expect(getColorName(SemiDarkBlue.variants.dark)).toEqual(SemiDarkBlue.name);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getColorByName', () => {
|
||||
it('returns undefined for unknown color', () => {
|
||||
expect(getColorByName('aruba-sunshine')).toBeUndefined();
|
||||
});
|
||||
|
||||
it('returns color definiton for known color', () => {
|
||||
expect(getColorByName(SemiDarkBlue.name)).toBe(SemiDarkBlue);
|
||||
});
|
||||
|
||||
});
|
||||
describe('getColorFromHexRgbOrName', () => {
|
||||
it('returns undefined for unknown color', () => {
|
||||
expect(() => getColorFromHexRgbOrName('aruba-sunshine')).toThrow();
|
||||
});
|
||||
|
||||
it('returns dark hex variant for known color if theme not specified', () => {
|
||||
expect(getColorFromHexRgbOrName(SemiDarkBlue.name)).toBe(SemiDarkBlue.variants.dark);
|
||||
});
|
||||
|
||||
it('returns correct variant\'s hex for known color if theme specified', () => {
|
||||
expect(getColorFromHexRgbOrName(SemiDarkBlue.name, GrafanaTheme.Light)).toBe(SemiDarkBlue.variants.light);
|
||||
});
|
||||
|
||||
it('returns color if specified as hex or rgb/a', () => {
|
||||
expect(getColorFromHexRgbOrName('ff0000')).toBe('ff0000');
|
||||
expect(getColorFromHexRgbOrName('#ff0000')).toBe('#ff0000');
|
||||
expect(getColorFromHexRgbOrName('rgb(0,0,0)')).toBe('rgb(0,0,0)');
|
||||
expect(getColorFromHexRgbOrName('rgba(0,0,0,1)')).toBe('rgba(0,0,0,1)');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -47,7 +47,7 @@ export type ColorDefinition = {
|
||||
variants: ThemeVariants;
|
||||
};
|
||||
|
||||
export const ColorsPalete = new Map<Hue, ColorDefinition[]>();
|
||||
export const ColorsPalette = new Map<Hue, ColorDefinition[]>();
|
||||
|
||||
export const buildColorDefinition = (
|
||||
hue: Hue,
|
||||
@ -107,15 +107,15 @@ const blues = [BasicBlue, DarkBlue, SemiDarkBlue, LightBlue, SuperLightBlue];
|
||||
const oranges = [BasicOrange, DarkOrange, SemiDarkOrange, LightOrange, SuperLightOrange];
|
||||
const purples = [BasicPurple, DarkPurple, SemiDarkPurple, LightPurple, SuperLightPurple];
|
||||
|
||||
ColorsPalete.set('green', greens);
|
||||
ColorsPalete.set('yellow', yellows);
|
||||
ColorsPalete.set('red', reds);
|
||||
ColorsPalete.set('blue', blues);
|
||||
ColorsPalete.set('orange', oranges);
|
||||
ColorsPalete.set('purple', purples);
|
||||
ColorsPalette.set('green', greens);
|
||||
ColorsPalette.set('yellow', yellows);
|
||||
ColorsPalette.set('red', reds);
|
||||
ColorsPalette.set('blue', blues);
|
||||
ColorsPalette.set('orange', oranges);
|
||||
ColorsPalette.set('purple', purples);
|
||||
|
||||
export const getColorDefinition = (hex: string): ColorDefinition | undefined => {
|
||||
return flatten(Array.from(ColorsPalete.values())).filter(definition =>
|
||||
return flatten(Array.from(ColorsPalette.values())).filter(definition =>
|
||||
some(values(definition.variants), color => color === hex)
|
||||
)[0];
|
||||
};
|
||||
@ -137,6 +137,25 @@ export const getColorName = (color: string): Color | undefined => {
|
||||
return color as Color;
|
||||
};
|
||||
|
||||
export const getColorByName = (colorName: string) => {
|
||||
const definition = flatten(Array.from(ColorsPalette.values())).filter(definition => definition.name === colorName);
|
||||
return definition.length > 0 ? definition[0] : undefined;
|
||||
};
|
||||
|
||||
export const getColorFromHexRgbOrName = (color: string, theme?: GrafanaTheme): string => {
|
||||
if (color.indexOf('rgb') > -1 || isHex(color)) {
|
||||
return color;
|
||||
}
|
||||
|
||||
const colorDefinition = getColorByName(color);
|
||||
|
||||
if (!colorDefinition) {
|
||||
throw new Error('Unknown color');
|
||||
}
|
||||
|
||||
return theme ? colorDefinition.variants[theme] : colorDefinition.variants.dark;
|
||||
};
|
||||
|
||||
export const getColorForTheme = (color: ColorDefinition, theme?: GrafanaTheme) => {
|
||||
return theme ? color.variants[theme] : color.variants.dark;
|
||||
};
|
||||
|
@ -1,7 +1,6 @@
|
||||
import kbn from 'app/core/utils/kbn';
|
||||
import { getFlotTickDecimals } from 'app/core/utils/ticks';
|
||||
import _ from 'lodash';
|
||||
import { ColorDefinition } from '@grafana/ui/src/utils/colorsPalette';
|
||||
|
||||
function matchSeriesOverride(aliasOrRegex, seriesAlias) {
|
||||
if (!aliasOrRegex) {
|
||||
@ -357,13 +356,8 @@ export default class TimeSeries {
|
||||
return false;
|
||||
}
|
||||
|
||||
setColor(color: string | ColorDefinition) {
|
||||
if (typeof color === 'string') {
|
||||
this.color = color;
|
||||
this.bars.fillColor = color;
|
||||
} else {
|
||||
this.color = color.variants.dark;
|
||||
this.bars.fillColor = color.variants.dark;
|
||||
}
|
||||
setColor(color: string) {
|
||||
this.color = color;
|
||||
this.bars.fillColor = color;
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,9 @@
|
||||
import _ from 'lodash';
|
||||
import { colors } from '@grafana/ui';
|
||||
import { colors, GrafanaTheme } from '@grafana/ui';
|
||||
|
||||
import TimeSeries from 'app/core/time_series2';
|
||||
import { getColorFromHexRgbOrName } from '@grafana/ui/src/utils/colorsPalette';
|
||||
import config from 'app/core/config';
|
||||
|
||||
export class DataProcessor {
|
||||
constructor(private panel) {}
|
||||
@ -107,12 +109,13 @@ export class DataProcessor {
|
||||
const alias = seriesData.target;
|
||||
|
||||
const colorIndex = index % colors.length;
|
||||
|
||||
const color = this.panel.aliasColors[alias] || colors[colorIndex];
|
||||
|
||||
const series = new TimeSeries({
|
||||
datapoints: datapoints,
|
||||
alias: alias,
|
||||
color: color,
|
||||
color: getColorFromHexRgbOrName(color, config.bootData.user.lightTheme ? GrafanaTheme.Light : GrafanaTheme.Dark),
|
||||
unit: seriesData.unit,
|
||||
});
|
||||
|
||||
|
@ -9,6 +9,9 @@ import _ from 'lodash';
|
||||
import { MetricsPanelCtrl } from 'app/plugins/sdk';
|
||||
import { DataProcessor } from './data_processor';
|
||||
import { axesEditorComponent } from './axes_editor';
|
||||
import { getColorFromHexRgbOrName } from '@grafana/ui/src/utils/colorsPalette';
|
||||
import config from 'app/core/config';
|
||||
import { GrafanaTheme } from '@grafana/ui';
|
||||
|
||||
class GraphCtrl extends MetricsPanelCtrl {
|
||||
static template = template;
|
||||
@ -242,8 +245,8 @@ class GraphCtrl extends MetricsPanelCtrl {
|
||||
}
|
||||
|
||||
onColorChange = (series, color) => {
|
||||
series.setColor(color);
|
||||
this.panel.aliasColors[series.alias] = series.color;
|
||||
series.setColor(getColorFromHexRgbOrName(color, config.bootData.user.lightTheme ? GrafanaTheme.Light : GrafanaTheme.Dark));
|
||||
this.panel.aliasColors[series.alias] = color;
|
||||
this.render();
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user