mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
VizLegend: move onSeriesColorChanged to PanelContext (breaking change) (#33611)
This commit is contained in:
parent
578283078b
commit
6b0417207d
@ -22,7 +22,6 @@ export interface BarChartProps extends Themeable2, BarChartOptions {
|
|||||||
data: DataFrame[];
|
data: DataFrame[];
|
||||||
structureRev?: number; // a number that will change when the data[] structure changes
|
structureRev?: number; // a number that will change when the data[] structure changes
|
||||||
onLegendClick?: (event: GraphNGLegendEvent) => void;
|
onLegendClick?: (event: GraphNGLegendEvent) => void;
|
||||||
onSeriesColorChange?: (label: string, color: string) => void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface BarChartState {
|
interface BarChartState {
|
||||||
@ -87,7 +86,7 @@ class UnthemedBarChart extends React.Component<BarChartProps, BarChartState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderLegend() {
|
renderLegend() {
|
||||||
const { legend, onSeriesColorChange, onLegendClick, data } = this.props;
|
const { legend, onLegendClick, data } = this.props;
|
||||||
const { config } = this.state;
|
const { config } = this.state;
|
||||||
|
|
||||||
if (!config || legend.displayMode === LegendDisplayMode.Hidden) {
|
if (!config || legend.displayMode === LegendDisplayMode.Hidden) {
|
||||||
@ -97,7 +96,6 @@ class UnthemedBarChart extends React.Component<BarChartProps, BarChartState> {
|
|||||||
<PlotLegend
|
<PlotLegend
|
||||||
data={data}
|
data={data}
|
||||||
config={config}
|
config={config}
|
||||||
onSeriesColorChange={onSeriesColorChange}
|
|
||||||
onLegendClick={onLegendClick}
|
onLegendClick={onLegendClick}
|
||||||
maxHeight="35%"
|
maxHeight="35%"
|
||||||
maxWidth="60%"
|
maxWidth="60%"
|
||||||
|
@ -5,7 +5,7 @@ import { css } from '@emotion/css';
|
|||||||
import { GraphSeriesValue } from '@grafana/data';
|
import { GraphSeriesValue } from '@grafana/data';
|
||||||
|
|
||||||
import { Graph, GraphProps } from './Graph';
|
import { Graph, GraphProps } from './Graph';
|
||||||
import { VizLegendItem, SeriesColorChangeHandler } from '../VizLegend/types';
|
import { VizLegendItem } from '../VizLegend/types';
|
||||||
import { LegendDisplayMode, LegendPlacement } from '../VizLegend/models.gen';
|
import { LegendDisplayMode, LegendPlacement } from '../VizLegend/models.gen';
|
||||||
import { VizLegend } from '../VizLegend/VizLegend';
|
import { VizLegend } from '../VizLegend/VizLegend';
|
||||||
import { CustomScrollbar } from '../CustomScrollbar/CustomScrollbar';
|
import { CustomScrollbar } from '../CustomScrollbar/CustomScrollbar';
|
||||||
@ -18,7 +18,6 @@ export interface GraphWithLegendProps extends GraphProps {
|
|||||||
hideZero?: boolean;
|
hideZero?: boolean;
|
||||||
sortLegendBy?: string;
|
sortLegendBy?: string;
|
||||||
sortLegendDesc?: boolean;
|
sortLegendDesc?: boolean;
|
||||||
onSeriesColorChange?: SeriesColorChangeHandler;
|
|
||||||
onSeriesToggle?: (label: string, event: React.MouseEvent<HTMLElement>) => void;
|
onSeriesToggle?: (label: string, event: React.MouseEvent<HTMLElement>) => void;
|
||||||
onToggleSort: (sortBy: string) => void;
|
onToggleSort: (sortBy: string) => void;
|
||||||
}
|
}
|
||||||
@ -58,7 +57,6 @@ export const GraphWithLegend: React.FunctionComponent<GraphWithLegendProps> = (p
|
|||||||
sortLegendDesc,
|
sortLegendDesc,
|
||||||
legendDisplayMode,
|
legendDisplayMode,
|
||||||
placement,
|
placement,
|
||||||
onSeriesColorChange,
|
|
||||||
onSeriesToggle,
|
onSeriesToggle,
|
||||||
onToggleSort,
|
onToggleSort,
|
||||||
hideEmpty,
|
hideEmpty,
|
||||||
@ -120,7 +118,6 @@ export const GraphWithLegend: React.FunctionComponent<GraphWithLegendProps> = (p
|
|||||||
onSeriesToggle(item.label, event);
|
onSeriesToggle(item.label, event);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onSeriesColorChange={onSeriesColorChange}
|
|
||||||
onToggleSort={onToggleSort}
|
onToggleSort={onToggleSort}
|
||||||
/>
|
/>
|
||||||
</CustomScrollbar>
|
</CustomScrollbar>
|
||||||
|
@ -27,7 +27,6 @@ export interface GraphNGProps extends Themeable2 {
|
|||||||
timeZone: TimeZone;
|
timeZone: TimeZone;
|
||||||
fields?: XYFieldMatchers; // default will assume timeseries data
|
fields?: XYFieldMatchers; // default will assume timeseries data
|
||||||
onLegendClick?: (event: GraphNGLegendEvent) => void;
|
onLegendClick?: (event: GraphNGLegendEvent) => void;
|
||||||
onSeriesColorChange?: (label: string, color: string) => void;
|
|
||||||
children?: (builder: UPlotConfigBuilder, alignedDataFrame: DataFrame) => React.ReactNode;
|
children?: (builder: UPlotConfigBuilder, alignedDataFrame: DataFrame) => React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,7 +113,7 @@ class UnthemedGraphNG extends React.Component<GraphNGProps, GraphNGState> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
renderLegend() {
|
renderLegend() {
|
||||||
const { legend, onSeriesColorChange, onLegendClick, data } = this.props;
|
const { legend, onLegendClick, data } = this.props;
|
||||||
const { config } = this.state;
|
const { config } = this.state;
|
||||||
|
|
||||||
if (!config || (legend && legend.displayMode === LegendDisplayMode.Hidden)) {
|
if (!config || (legend && legend.displayMode === LegendDisplayMode.Hidden)) {
|
||||||
@ -125,7 +124,6 @@ class UnthemedGraphNG extends React.Component<GraphNGProps, GraphNGState> {
|
|||||||
<PlotLegend
|
<PlotLegend
|
||||||
data={data}
|
data={data}
|
||||||
config={config}
|
config={config}
|
||||||
onSeriesColorChange={onSeriesColorChange}
|
|
||||||
onLegendClick={onLegendClick}
|
onLegendClick={onLegendClick}
|
||||||
maxHeight="35%"
|
maxHeight="35%"
|
||||||
maxWidth="60%"
|
maxWidth="60%"
|
||||||
|
@ -4,6 +4,13 @@ import React from 'react';
|
|||||||
/** @alpha */
|
/** @alpha */
|
||||||
export interface PanelContext {
|
export interface PanelContext {
|
||||||
eventBus: EventBus;
|
eventBus: EventBus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a component wants to change the color for a series
|
||||||
|
*
|
||||||
|
* @alpha -- experimental
|
||||||
|
*/
|
||||||
|
onSeriesColorChange?: (label: string, color: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const PanelContextRoot = React.createContext<PanelContext>({
|
const PanelContextRoot = React.createContext<PanelContext>({
|
||||||
|
@ -53,7 +53,6 @@ export function PieChart(props: PieChartProps) {
|
|||||||
fieldConfig,
|
fieldConfig,
|
||||||
replaceVariables,
|
replaceVariables,
|
||||||
tooltipOptions,
|
tooltipOptions,
|
||||||
onSeriesColorChange,
|
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
...restProps
|
...restProps
|
||||||
@ -128,14 +127,7 @@ function getLegend(props: PieChartProps, displayValues: FieldDisplay[]) {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return <VizLegend items={legendItems} placement={legendOptions.placement} displayMode={legendOptions.displayMode} />;
|
||||||
<VizLegend
|
|
||||||
items={legendItems}
|
|
||||||
onSeriesColorChange={props.onSeriesColorChange}
|
|
||||||
placement={legendOptions.placement}
|
|
||||||
displayMode={legendOptions.displayMode}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function useSliceHighlightState() {
|
function useSliceHighlightState() {
|
||||||
|
@ -13,7 +13,6 @@ export interface PieChartSvgProps {
|
|||||||
highlightedTitle?: string;
|
highlightedTitle?: string;
|
||||||
displayLabels?: PieChartLabels[];
|
displayLabels?: PieChartLabels[];
|
||||||
useGradients?: boolean;
|
useGradients?: boolean;
|
||||||
onSeriesColorChange?: (label: string, color: string) => void;
|
|
||||||
tooltipOptions: VizTooltipOptions;
|
tooltipOptions: VizTooltipOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,7 +25,6 @@ export interface PieChartProps {
|
|||||||
pieType: PieChartType;
|
pieType: PieChartType;
|
||||||
displayLabels?: PieChartLabels[];
|
displayLabels?: PieChartLabels[];
|
||||||
useGradients?: boolean;
|
useGradients?: boolean;
|
||||||
onSeriesColorChange?: (label: string, color: string) => void;
|
|
||||||
legendOptions?: PieChartLegendOptions;
|
legendOptions?: PieChartLegendOptions;
|
||||||
tooltipOptions: VizTooltipOptions;
|
tooltipOptions: VizTooltipOptions;
|
||||||
reduceOptions: ReduceDataOptions;
|
reduceOptions: ReduceDataOptions;
|
||||||
|
@ -100,7 +100,7 @@ class UnthemedTimelineChart extends React.Component<TimelineProps, GraphNGState>
|
|||||||
};
|
};
|
||||||
|
|
||||||
renderLegend() {
|
renderLegend() {
|
||||||
const { legend, onSeriesColorChange, onLegendClick, data } = this.props;
|
const { legend, onLegendClick, data } = this.props;
|
||||||
const { config } = this.state;
|
const { config } = this.state;
|
||||||
|
|
||||||
if (!config || (legend && legend.displayMode === LegendDisplayMode.Hidden)) {
|
if (!config || (legend && legend.displayMode === LegendDisplayMode.Hidden)) {
|
||||||
@ -111,7 +111,6 @@ class UnthemedTimelineChart extends React.Component<TimelineProps, GraphNGState>
|
|||||||
<PlotLegend
|
<PlotLegend
|
||||||
data={data}
|
data={data}
|
||||||
config={config}
|
config={config}
|
||||||
onSeriesColorChange={onSeriesColorChange}
|
|
||||||
onLegendClick={onLegendClick}
|
onLegendClick={onLegendClick}
|
||||||
maxHeight="35%"
|
maxHeight="35%"
|
||||||
maxWidth="60%"
|
maxWidth="60%"
|
||||||
|
@ -53,21 +53,6 @@ const LegendStoryDemo: FC<LegendStoryDemoProps> = ({ displayMode, seriesCount, n
|
|||||||
setItems(generateLegendItems(seriesCount, theme, stats));
|
setItems(generateLegendItems(seriesCount, theme, stats));
|
||||||
}, [seriesCount, theme, stats]);
|
}, [seriesCount, theme, stats]);
|
||||||
|
|
||||||
const onSeriesColorChange = (label: string, color: string) => {
|
|
||||||
setItems(
|
|
||||||
items.map((item) => {
|
|
||||||
if (item.label === label) {
|
|
||||||
return {
|
|
||||||
...item,
|
|
||||||
color: color,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return item;
|
|
||||||
})
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const onLabelClick = (clickItem: VizLegendItem) => {
|
const onLabelClick = (clickItem: VizLegendItem) => {
|
||||||
setItems(
|
setItems(
|
||||||
items.map((item) => {
|
items.map((item) => {
|
||||||
@ -89,13 +74,7 @@ const LegendStoryDemo: FC<LegendStoryDemoProps> = ({ displayMode, seriesCount, n
|
|||||||
return (
|
return (
|
||||||
<p style={{ marginBottom: '32px' }}>
|
<p style={{ marginBottom: '32px' }}>
|
||||||
<h3 style={{ marginBottom: '32px' }}>{name}</h3>
|
<h3 style={{ marginBottom: '32px' }}>{name}</h3>
|
||||||
<VizLegend
|
<VizLegend displayMode={displayMode} items={items} placement={placement} onLabelClick={onLabelClick} />
|
||||||
displayMode={displayMode}
|
|
||||||
items={items}
|
|
||||||
placement={placement}
|
|
||||||
onSeriesColorChange={onSeriesColorChange}
|
|
||||||
onLabelClick={onLabelClick}
|
|
||||||
/>
|
|
||||||
</p>
|
</p>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -16,7 +16,6 @@ export const VizLegend: React.FunctionComponent<LegendProps> = ({
|
|||||||
sortDesc,
|
sortDesc,
|
||||||
onToggleSort,
|
onToggleSort,
|
||||||
onLabelClick,
|
onLabelClick,
|
||||||
onSeriesColorChange,
|
|
||||||
placement,
|
placement,
|
||||||
className,
|
className,
|
||||||
}) => {
|
}) => {
|
||||||
@ -65,7 +64,6 @@ export const VizLegend: React.FunctionComponent<LegendProps> = ({
|
|||||||
onToggleSort={onToggleSort}
|
onToggleSort={onToggleSort}
|
||||||
onLabelMouseEnter={onMouseEnter}
|
onLabelMouseEnter={onMouseEnter}
|
||||||
onLabelMouseOut={onMouseOut}
|
onLabelMouseOut={onMouseOut}
|
||||||
onSeriesColorChange={onSeriesColorChange}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
case LegendDisplayMode.List:
|
case LegendDisplayMode.List:
|
||||||
@ -77,7 +75,6 @@ export const VizLegend: React.FunctionComponent<LegendProps> = ({
|
|||||||
onLabelMouseEnter={onMouseEnter}
|
onLabelMouseEnter={onMouseEnter}
|
||||||
onLabelMouseOut={onMouseOut}
|
onLabelMouseOut={onMouseOut}
|
||||||
onLabelClick={onLabelClick}
|
onLabelClick={onLabelClick}
|
||||||
onSeriesColorChange={onSeriesColorChange}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
default:
|
default:
|
||||||
|
@ -15,7 +15,6 @@ export interface Props extends VizLegendBaseProps {}
|
|||||||
export const VizLegendList: React.FunctionComponent<Props> = ({
|
export const VizLegendList: React.FunctionComponent<Props> = ({
|
||||||
items,
|
items,
|
||||||
itemRenderer,
|
itemRenderer,
|
||||||
onSeriesColorChange,
|
|
||||||
onLabelClick,
|
onLabelClick,
|
||||||
onLabelMouseEnter,
|
onLabelMouseEnter,
|
||||||
onLabelMouseOut,
|
onLabelMouseOut,
|
||||||
@ -30,7 +29,6 @@ export const VizLegendList: React.FunctionComponent<Props> = ({
|
|||||||
<VizLegendListItem
|
<VizLegendListItem
|
||||||
item={item}
|
item={item}
|
||||||
onLabelClick={onLabelClick}
|
onLabelClick={onLabelClick}
|
||||||
onSeriesColorChange={onSeriesColorChange}
|
|
||||||
onLabelMouseEnter={onLabelMouseEnter}
|
onLabelMouseEnter={onLabelMouseEnter}
|
||||||
onLabelMouseOut={onLabelMouseOut}
|
onLabelMouseOut={onLabelMouseOut}
|
||||||
/>
|
/>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { useCallback } from 'react';
|
import React, { useCallback } from 'react';
|
||||||
import { css, cx } from '@emotion/css';
|
import { css, cx } from '@emotion/css';
|
||||||
import { VizLegendSeriesIcon } from './VizLegendSeriesIcon';
|
import { VizLegendSeriesIcon } from './VizLegendSeriesIcon';
|
||||||
import { VizLegendItem, SeriesColorChangeHandler } from './types';
|
import { VizLegendItem } from './types';
|
||||||
import { VizLegendStatsList } from './VizLegendStatsList';
|
import { VizLegendStatsList } from './VizLegendStatsList';
|
||||||
import { useStyles } from '../../themes';
|
import { useStyles } from '../../themes';
|
||||||
import { GrafanaTheme } from '@grafana/data';
|
import { GrafanaTheme } from '@grafana/data';
|
||||||
@ -10,7 +10,6 @@ export interface Props {
|
|||||||
item: VizLegendItem;
|
item: VizLegendItem;
|
||||||
className?: string;
|
className?: string;
|
||||||
onLabelClick?: (item: VizLegendItem, event: React.MouseEvent<HTMLDivElement>) => void;
|
onLabelClick?: (item: VizLegendItem, event: React.MouseEvent<HTMLDivElement>) => void;
|
||||||
onSeriesColorChange?: SeriesColorChangeHandler;
|
|
||||||
onLabelMouseEnter?: (item: VizLegendItem, event: React.MouseEvent<HTMLDivElement>) => void;
|
onLabelMouseEnter?: (item: VizLegendItem, event: React.MouseEvent<HTMLDivElement>) => void;
|
||||||
onLabelMouseOut?: (item: VizLegendItem, event: React.MouseEvent<HTMLDivElement>) => void;
|
onLabelMouseOut?: (item: VizLegendItem, event: React.MouseEvent<HTMLDivElement>) => void;
|
||||||
}
|
}
|
||||||
@ -20,7 +19,6 @@ export interface Props {
|
|||||||
*/
|
*/
|
||||||
export const VizLegendListItem: React.FunctionComponent<Props> = ({
|
export const VizLegendListItem: React.FunctionComponent<Props> = ({
|
||||||
item,
|
item,
|
||||||
onSeriesColorChange,
|
|
||||||
onLabelClick,
|
onLabelClick,
|
||||||
onLabelMouseEnter,
|
onLabelMouseEnter,
|
||||||
onLabelMouseOut,
|
onLabelMouseOut,
|
||||||
@ -54,18 +52,9 @@ export const VizLegendListItem: React.FunctionComponent<Props> = ({
|
|||||||
[item, onLabelClick]
|
[item, onLabelClick]
|
||||||
);
|
);
|
||||||
|
|
||||||
const onColorChange = useCallback(
|
|
||||||
(color: string) => {
|
|
||||||
if (onSeriesColorChange) {
|
|
||||||
onSeriesColorChange(item.label, color);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[item, onSeriesColorChange]
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.itemWrapper}>
|
<div className={styles.itemWrapper}>
|
||||||
<VizLegendSeriesIcon disabled={!onSeriesColorChange} color={item.color} onColorChange={onColorChange} />
|
<VizLegendSeriesIcon seriesName={item.label} color={item.color} />
|
||||||
<div
|
<div
|
||||||
onMouseEnter={onMouseEnter}
|
onMouseEnter={onMouseEnter}
|
||||||
onMouseOut={onMouseOut}
|
onMouseOut={onMouseOut}
|
||||||
|
@ -1,32 +1,41 @@
|
|||||||
import React from 'react';
|
import React, { useCallback } from 'react';
|
||||||
import { SeriesColorPicker } from '../ColorPicker/ColorPicker';
|
import { SeriesColorPicker } from '../ColorPicker/ColorPicker';
|
||||||
|
import { usePanelContext } from '../PanelChrome';
|
||||||
import { SeriesIcon } from './SeriesIcon';
|
import { SeriesIcon } from './SeriesIcon';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
disabled: boolean;
|
seriesName: string;
|
||||||
color: string;
|
color: string;
|
||||||
onColorChange: (color: string) => void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
export const VizLegendSeriesIcon: React.FunctionComponent<Props> = ({ disabled, color, onColorChange }) => {
|
export const VizLegendSeriesIcon: React.FunctionComponent<Props> = ({ seriesName, color }) => {
|
||||||
return disabled ? (
|
const { onSeriesColorChange } = usePanelContext();
|
||||||
<SeriesIcon color={color} />
|
const onChange = useCallback(
|
||||||
) : (
|
(color: string) => {
|
||||||
<SeriesColorPicker color={color} onChange={onColorChange} enableNamedColors>
|
return onSeriesColorChange!(seriesName, color);
|
||||||
{({ ref, showColorPicker, hideColorPicker }) => (
|
},
|
||||||
<SeriesIcon
|
[seriesName, onSeriesColorChange]
|
||||||
color={color}
|
|
||||||
className="pointer"
|
|
||||||
ref={ref}
|
|
||||||
onClick={showColorPicker}
|
|
||||||
onMouseLeave={hideColorPicker}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</SeriesColorPicker>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (seriesName && onSeriesColorChange) {
|
||||||
|
return (
|
||||||
|
<SeriesColorPicker color={color} onChange={onChange} enableNamedColors>
|
||||||
|
{({ ref, showColorPicker, hideColorPicker }) => (
|
||||||
|
<SeriesIcon
|
||||||
|
color={color}
|
||||||
|
className="pointer"
|
||||||
|
ref={ref}
|
||||||
|
onClick={showColorPicker}
|
||||||
|
onMouseLeave={hideColorPicker}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</SeriesColorPicker>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return <SeriesIcon color={color} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
VizLegendSeriesIcon.displayName = 'VizLegendSeriesIcon';
|
VizLegendSeriesIcon.displayName = 'VizLegendSeriesIcon';
|
||||||
|
@ -20,7 +20,6 @@ export const VizLegendTable: FC<VizLegendTableProps> = ({
|
|||||||
onLabelClick,
|
onLabelClick,
|
||||||
onLabelMouseEnter,
|
onLabelMouseEnter,
|
||||||
onLabelMouseOut,
|
onLabelMouseOut,
|
||||||
onSeriesColorChange,
|
|
||||||
}) => {
|
}) => {
|
||||||
const styles = useStyles(getStyles);
|
const styles = useStyles(getStyles);
|
||||||
|
|
||||||
@ -57,7 +56,6 @@ export const VizLegendTable: FC<VizLegendTableProps> = ({
|
|||||||
<LegendTableItem
|
<LegendTableItem
|
||||||
key={`${item.label}-${index}`}
|
key={`${item.label}-${index}`}
|
||||||
item={item}
|
item={item}
|
||||||
onSeriesColorChange={onSeriesColorChange}
|
|
||||||
onLabelClick={onLabelClick}
|
onLabelClick={onLabelClick}
|
||||||
onLabelMouseEnter={onLabelMouseEnter}
|
onLabelMouseEnter={onLabelMouseEnter}
|
||||||
onLabelMouseOut={onLabelMouseOut}
|
onLabelMouseOut={onLabelMouseOut}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { useCallback } from 'react';
|
import React, { useCallback } from 'react';
|
||||||
import { css, cx } from '@emotion/css';
|
import { css, cx } from '@emotion/css';
|
||||||
import { VizLegendSeriesIcon } from './VizLegendSeriesIcon';
|
import { VizLegendSeriesIcon } from './VizLegendSeriesIcon';
|
||||||
import { VizLegendItem, SeriesColorChangeHandler } from './types';
|
import { VizLegendItem } from './types';
|
||||||
import { useStyles } from '../../themes/ThemeContext';
|
import { useStyles } from '../../themes/ThemeContext';
|
||||||
import { styleMixins } from '../../themes';
|
import { styleMixins } from '../../themes';
|
||||||
import { GrafanaTheme, formattedValueToString } from '@grafana/data';
|
import { GrafanaTheme, formattedValueToString } from '@grafana/data';
|
||||||
@ -11,7 +11,6 @@ export interface Props {
|
|||||||
item: VizLegendItem;
|
item: VizLegendItem;
|
||||||
className?: string;
|
className?: string;
|
||||||
onLabelClick?: (item: VizLegendItem, event: React.MouseEvent<HTMLDivElement>) => void;
|
onLabelClick?: (item: VizLegendItem, event: React.MouseEvent<HTMLDivElement>) => void;
|
||||||
onSeriesColorChange?: SeriesColorChangeHandler;
|
|
||||||
onLabelMouseEnter?: (item: VizLegendItem, event: React.MouseEvent<HTMLDivElement>) => void;
|
onLabelMouseEnter?: (item: VizLegendItem, event: React.MouseEvent<HTMLDivElement>) => void;
|
||||||
onLabelMouseOut?: (item: VizLegendItem, event: React.MouseEvent<HTMLDivElement>) => void;
|
onLabelMouseOut?: (item: VizLegendItem, event: React.MouseEvent<HTMLDivElement>) => void;
|
||||||
}
|
}
|
||||||
@ -21,7 +20,6 @@ export interface Props {
|
|||||||
*/
|
*/
|
||||||
export const LegendTableItem: React.FunctionComponent<Props> = ({
|
export const LegendTableItem: React.FunctionComponent<Props> = ({
|
||||||
item,
|
item,
|
||||||
onSeriesColorChange,
|
|
||||||
onLabelClick,
|
onLabelClick,
|
||||||
onLabelMouseEnter,
|
onLabelMouseEnter,
|
||||||
onLabelMouseOut,
|
onLabelMouseOut,
|
||||||
@ -56,20 +54,11 @@ export const LegendTableItem: React.FunctionComponent<Props> = ({
|
|||||||
[item, onLabelClick]
|
[item, onLabelClick]
|
||||||
);
|
);
|
||||||
|
|
||||||
const onColorChange = useCallback(
|
|
||||||
(color: string) => {
|
|
||||||
if (onSeriesColorChange) {
|
|
||||||
onSeriesColorChange(item.label, color);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[item, onSeriesColorChange]
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<tr className={cx(styles.row, className)}>
|
<tr className={cx(styles.row, className)}>
|
||||||
<td>
|
<td>
|
||||||
<span className={styles.itemWrapper}>
|
<span className={styles.itemWrapper}>
|
||||||
<VizLegendSeriesIcon disabled={!onSeriesColorChange} color={item.color} onColorChange={onColorChange} />
|
<VizLegendSeriesIcon color={item.color} seriesName={item.label} />
|
||||||
<div
|
<div
|
||||||
onMouseEnter={onMouseEnter}
|
onMouseEnter={onMouseEnter}
|
||||||
onMouseOut={onMouseOut}
|
onMouseOut={onMouseOut}
|
||||||
|
@ -7,7 +7,6 @@ export interface VizLegendBaseProps {
|
|||||||
className?: string;
|
className?: string;
|
||||||
items: VizLegendItem[];
|
items: VizLegendItem[];
|
||||||
itemRenderer?: (item: VizLegendItem, index: number) => JSX.Element;
|
itemRenderer?: (item: VizLegendItem, index: number) => JSX.Element;
|
||||||
onSeriesColorChange?: SeriesColorChangeHandler;
|
|
||||||
onLabelClick?: (item: VizLegendItem, event: React.MouseEvent<HTMLElement>) => void;
|
onLabelClick?: (item: VizLegendItem, event: React.MouseEvent<HTMLElement>) => void;
|
||||||
onLabelMouseEnter?: (item: VizLegendItem, event: React.MouseEvent<HTMLElement>) => void;
|
onLabelMouseEnter?: (item: VizLegendItem, event: React.MouseEvent<HTMLElement>) => void;
|
||||||
onLabelMouseOut?: (item: VizLegendItem, event: React.MouseEvent<HTMLElement>) => void;
|
onLabelMouseOut?: (item: VizLegendItem, event: React.MouseEvent<HTMLElement>) => void;
|
||||||
@ -33,6 +32,3 @@ export interface VizLegendItem {
|
|||||||
getDisplayValues?: () => DisplayValue[];
|
getDisplayValues?: () => DisplayValue[];
|
||||||
fieldIndex?: DataFrameFieldIndex;
|
fieldIndex?: DataFrameFieldIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type SeriesOptionChangeHandler<TOption> = (label: string, option: TOption) => void;
|
|
||||||
export type SeriesColorChangeHandler = SeriesOptionChangeHandler<string>;
|
|
||||||
|
@ -14,14 +14,12 @@ const defaultFormatter = (v: any) => (v == null ? '-' : v.toFixed(1));
|
|||||||
interface PlotLegendProps extends VizLegendOptions, Omit<VizLayoutLegendProps, 'children'> {
|
interface PlotLegendProps extends VizLegendOptions, Omit<VizLayoutLegendProps, 'children'> {
|
||||||
data: DataFrame[];
|
data: DataFrame[];
|
||||||
config: UPlotConfigBuilder;
|
config: UPlotConfigBuilder;
|
||||||
onSeriesColorChange?: (label: string, color: string) => void;
|
|
||||||
onLegendClick?: (event: GraphNGLegendEvent) => void;
|
onLegendClick?: (event: GraphNGLegendEvent) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const PlotLegend: React.FC<PlotLegendProps> = ({
|
export const PlotLegend: React.FC<PlotLegendProps> = ({
|
||||||
data,
|
data,
|
||||||
config,
|
config,
|
||||||
onSeriesColorChange,
|
|
||||||
onLegendClick,
|
onLegendClick,
|
||||||
placement,
|
placement,
|
||||||
calcs,
|
calcs,
|
||||||
@ -99,7 +97,6 @@ export const PlotLegend: React.FC<PlotLegendProps> = ({
|
|||||||
placement={placement}
|
placement={placement}
|
||||||
items={legendItems}
|
items={legendItems}
|
||||||
displayMode={displayMode}
|
displayMode={displayMode}
|
||||||
onSeriesColorChange={onSeriesColorChange}
|
|
||||||
/>
|
/>
|
||||||
</VizLayout.Legend>
|
</VizLayout.Legend>
|
||||||
);
|
);
|
||||||
|
@ -29,6 +29,7 @@ import {
|
|||||||
import { selectors } from '@grafana/e2e-selectors';
|
import { selectors } from '@grafana/e2e-selectors';
|
||||||
import { loadSnapshotData } from '../utils/loadSnapshotData';
|
import { loadSnapshotData } from '../utils/loadSnapshotData';
|
||||||
import { RefreshEvent, RenderEvent } from 'app/types/events';
|
import { RefreshEvent, RenderEvent } from 'app/types/events';
|
||||||
|
import { changeSeriesColorConfigFactory } from 'app/plugins/panel/timeseries/overrides/colorSeriesConfigFactory';
|
||||||
|
|
||||||
const DEFAULT_PLUGIN_ERROR = 'Error in plugin';
|
const DEFAULT_PLUGIN_ERROR = 'Error in plugin';
|
||||||
|
|
||||||
@ -75,11 +76,16 @@ export class PanelChrome extends Component<Props, State> {
|
|||||||
refreshWhenInView: false,
|
refreshWhenInView: false,
|
||||||
context: {
|
context: {
|
||||||
eventBus,
|
eventBus,
|
||||||
|
onSeriesColorChange: this.onSeriesColorChange,
|
||||||
},
|
},
|
||||||
data: this.getInitialPanelDataState(),
|
data: this.getInitialPanelDataState(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onSeriesColorChange = (label: string, color: string) => {
|
||||||
|
this.onFieldConfigChange(changeSeriesColorConfigFactory(label, color, this.props.panel.fieldConfig));
|
||||||
|
};
|
||||||
|
|
||||||
getInitialPanelDataState(): PanelData {
|
getInitialPanelDataState(): PanelData {
|
||||||
return {
|
return {
|
||||||
state: LoadingState.NotStarted,
|
state: LoadingState.NotStarted,
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import React, { useCallback, useMemo } from 'react';
|
import React, { useCallback, useMemo } from 'react';
|
||||||
import { FieldType, PanelProps, VizOrientation } from '@grafana/data';
|
import { FieldType, PanelProps, VizOrientation } from '@grafana/data';
|
||||||
import { BarChart, BarChartOptions, GraphNGLegendEvent } from '@grafana/ui';
|
import { BarChart, BarChartOptions, GraphNGLegendEvent } from '@grafana/ui';
|
||||||
import { changeSeriesColorConfigFactory } from '../timeseries/overrides/colorSeriesConfigFactory';
|
|
||||||
import { hideSeriesConfigFactory } from '../timeseries/overrides/hideSeriesConfigFactory';
|
import { hideSeriesConfigFactory } from '../timeseries/overrides/hideSeriesConfigFactory';
|
||||||
|
|
||||||
interface Props extends PanelProps<BarChartOptions> {}
|
interface Props extends PanelProps<BarChartOptions> {}
|
||||||
@ -32,13 +31,6 @@ export const BarChartPanel: React.FunctionComponent<Props> = ({
|
|||||||
[fieldConfig, onFieldConfigChange, data.series]
|
[fieldConfig, onFieldConfigChange, data.series]
|
||||||
);
|
);
|
||||||
|
|
||||||
const onSeriesColorChange = useCallback(
|
|
||||||
(label: string, color: string) => {
|
|
||||||
onFieldConfigChange(changeSeriesColorConfigFactory(label, color, fieldConfig));
|
|
||||||
},
|
|
||||||
[fieldConfig, onFieldConfigChange]
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!data || !data.series?.length) {
|
if (!data || !data.series?.length) {
|
||||||
return (
|
return (
|
||||||
<div className="panel-empty">
|
<div className="panel-empty">
|
||||||
@ -70,7 +62,6 @@ export const BarChartPanel: React.FunctionComponent<Props> = ({
|
|||||||
width={width}
|
width={width}
|
||||||
height={height}
|
height={height}
|
||||||
onLegendClick={onLegendClick}
|
onLegendClick={onLegendClick}
|
||||||
onSeriesColorChange={onSeriesColorChange}
|
|
||||||
{...options}
|
{...options}
|
||||||
orientation={orientation}
|
orientation={orientation}
|
||||||
/>
|
/>
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import React, { useCallback } from 'react';
|
import React from 'react';
|
||||||
import { PieChart } from '@grafana/ui';
|
import { PieChart } from '@grafana/ui';
|
||||||
import { PieChartOptions } from './types';
|
import { PieChartOptions } from './types';
|
||||||
import { PanelProps } from '@grafana/data';
|
import { PanelProps } from '@grafana/data';
|
||||||
import { changeSeriesColorConfigFactory } from '../timeseries/overrides/colorSeriesConfigFactory';
|
|
||||||
|
|
||||||
interface Props extends PanelProps<PieChartOptions> {}
|
interface Props extends PanelProps<PieChartOptions> {}
|
||||||
|
|
||||||
@ -16,13 +15,6 @@ export const PieChartPanel: React.FC<Props> = ({
|
|||||||
fieldConfig,
|
fieldConfig,
|
||||||
timeZone,
|
timeZone,
|
||||||
}) => {
|
}) => {
|
||||||
const onSeriesColorChange = useCallback(
|
|
||||||
(label: string, color: string) => {
|
|
||||||
onFieldConfigChange(changeSeriesColorConfigFactory(label, color, fieldConfig));
|
|
||||||
},
|
|
||||||
[fieldConfig, onFieldConfigChange]
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PieChart
|
<PieChart
|
||||||
width={width}
|
width={width}
|
||||||
@ -32,7 +24,6 @@ export const PieChartPanel: React.FC<Props> = ({
|
|||||||
reduceOptions={options.reduceOptions}
|
reduceOptions={options.reduceOptions}
|
||||||
replaceVariables={replaceVariables}
|
replaceVariables={replaceVariables}
|
||||||
data={data.series}
|
data={data.series}
|
||||||
onSeriesColorChange={onSeriesColorChange}
|
|
||||||
pieType={options.pieType}
|
pieType={options.pieType}
|
||||||
displayLabels={options.displayLabels}
|
displayLabels={options.displayLabels}
|
||||||
legendOptions={options.legend}
|
legendOptions={options.legend}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import React, { useCallback } from 'react';
|
import React, { useCallback } from 'react';
|
||||||
import { PanelProps } from '@grafana/data';
|
import { PanelProps } from '@grafana/data';
|
||||||
import { GraphNGLegendEvent, TimelineChart, TimelineOptions } from '@grafana/ui';
|
import { GraphNGLegendEvent, TimelineChart, TimelineOptions } from '@grafana/ui';
|
||||||
import { changeSeriesColorConfigFactory } from '../timeseries/overrides/colorSeriesConfigFactory';
|
|
||||||
import { hideSeriesConfigFactory } from '../timeseries/overrides/hideSeriesConfigFactory';
|
import { hideSeriesConfigFactory } from '../timeseries/overrides/hideSeriesConfigFactory';
|
||||||
|
|
||||||
interface TimelinePanelProps extends PanelProps<TimelineOptions> {}
|
interface TimelinePanelProps extends PanelProps<TimelineOptions> {}
|
||||||
@ -26,13 +25,6 @@ export const TimelinePanel: React.FC<TimelinePanelProps> = ({
|
|||||||
[fieldConfig, onFieldConfigChange, data.series]
|
[fieldConfig, onFieldConfigChange, data.series]
|
||||||
);
|
);
|
||||||
|
|
||||||
const onSeriesColorChange = useCallback(
|
|
||||||
(label: string, color: string) => {
|
|
||||||
onFieldConfigChange(changeSeriesColorConfigFactory(label, color, fieldConfig));
|
|
||||||
},
|
|
||||||
[fieldConfig, onFieldConfigChange]
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!data || !data.series?.length) {
|
if (!data || !data.series?.length) {
|
||||||
return (
|
return (
|
||||||
<div className="panel-empty">
|
<div className="panel-empty">
|
||||||
@ -50,7 +42,6 @@ export const TimelinePanel: React.FC<TimelinePanelProps> = ({
|
|||||||
width={width}
|
width={width}
|
||||||
height={height}
|
height={height}
|
||||||
onLegendClick={onLegendClick}
|
onLegendClick={onLegendClick}
|
||||||
onSeriesColorChange={onSeriesColorChange}
|
|
||||||
{...options}
|
{...options}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -2,7 +2,6 @@ import { Field, PanelProps } from '@grafana/data';
|
|||||||
import { GraphNG, GraphNGLegendEvent, TooltipPlugin, ZoomPlugin } from '@grafana/ui';
|
import { GraphNG, GraphNGLegendEvent, TooltipPlugin, ZoomPlugin } from '@grafana/ui';
|
||||||
import { getFieldLinksForExplore } from 'app/features/explore/utils/links';
|
import { getFieldLinksForExplore } from 'app/features/explore/utils/links';
|
||||||
import React, { useCallback } from 'react';
|
import React, { useCallback } from 'react';
|
||||||
import { changeSeriesColorConfigFactory } from './overrides/colorSeriesConfigFactory';
|
|
||||||
import { hideSeriesConfigFactory } from './overrides/hideSeriesConfigFactory';
|
import { hideSeriesConfigFactory } from './overrides/hideSeriesConfigFactory';
|
||||||
import { AnnotationsPlugin } from './plugins/AnnotationsPlugin';
|
import { AnnotationsPlugin } from './plugins/AnnotationsPlugin';
|
||||||
import { ContextMenuPlugin } from './plugins/ContextMenuPlugin';
|
import { ContextMenuPlugin } from './plugins/ContextMenuPlugin';
|
||||||
@ -34,13 +33,6 @@ export const TimeSeriesPanel: React.FC<TimeSeriesPanelProps> = ({
|
|||||||
return getFieldLinksForExplore({ field, rowIndex, range: timeRange });
|
return getFieldLinksForExplore({ field, rowIndex, range: timeRange });
|
||||||
};
|
};
|
||||||
|
|
||||||
const onSeriesColorChange = useCallback(
|
|
||||||
(label: string, color: string) => {
|
|
||||||
onFieldConfigChange(changeSeriesColorConfigFactory(label, color, fieldConfig));
|
|
||||||
},
|
|
||||||
[fieldConfig, onFieldConfigChange]
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!data || !data.series?.length) {
|
if (!data || !data.series?.length) {
|
||||||
return (
|
return (
|
||||||
<div className="panel-empty">
|
<div className="panel-empty">
|
||||||
@ -59,7 +51,6 @@ export const TimeSeriesPanel: React.FC<TimeSeriesPanelProps> = ({
|
|||||||
height={height}
|
height={height}
|
||||||
legend={options.legend}
|
legend={options.legend}
|
||||||
onLegendClick={onLegendClick}
|
onLegendClick={onLegendClick}
|
||||||
onSeriesColorChange={onSeriesColorChange}
|
|
||||||
>
|
>
|
||||||
{(config, alignedDataFrame) => {
|
{(config, alignedDataFrame) => {
|
||||||
return (
|
return (
|
||||||
|
@ -4,7 +4,6 @@ import { PanelProps } from '@grafana/data';
|
|||||||
import { Options } from './types';
|
import { Options } from './types';
|
||||||
import { hideSeriesConfigFactory } from '../timeseries/overrides/hideSeriesConfigFactory';
|
import { hideSeriesConfigFactory } from '../timeseries/overrides/hideSeriesConfigFactory';
|
||||||
import { getXYDimensions } from './dims';
|
import { getXYDimensions } from './dims';
|
||||||
import { changeSeriesColorConfigFactory } from '../timeseries/overrides/colorSeriesConfigFactory';
|
|
||||||
|
|
||||||
interface XYChartPanelProps extends PanelProps<Options> {}
|
interface XYChartPanelProps extends PanelProps<Options> {}
|
||||||
|
|
||||||
@ -29,13 +28,6 @@ export const XYChartPanel: React.FC<XYChartPanelProps> = ({
|
|||||||
[fieldConfig, onFieldConfigChange, frames]
|
[fieldConfig, onFieldConfigChange, frames]
|
||||||
);
|
);
|
||||||
|
|
||||||
const onSeriesColorChange = useCallback(
|
|
||||||
(label: string, color: string) => {
|
|
||||||
onFieldConfigChange(changeSeriesColorConfigFactory(label, color, fieldConfig));
|
|
||||||
},
|
|
||||||
[fieldConfig, onFieldConfigChange]
|
|
||||||
);
|
|
||||||
|
|
||||||
if (dims.error) {
|
if (dims.error) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
@ -61,7 +53,6 @@ export const XYChartPanel: React.FC<XYChartPanelProps> = ({
|
|||||||
height={height}
|
height={height}
|
||||||
legend={options.legend}
|
legend={options.legend}
|
||||||
onLegendClick={onLegendClick}
|
onLegendClick={onLegendClick}
|
||||||
onSeriesColorChange={onSeriesColorChange}
|
|
||||||
>
|
>
|
||||||
{(config, alignedDataFrame) => {
|
{(config, alignedDataFrame) => {
|
||||||
return (
|
return (
|
||||||
|
Loading…
Reference in New Issue
Block a user