PieChart: move hiding series to PanelContext (#33756)

pull/32805/head^2
Oscar Kilhed 4 years ago committed by GitHub
parent 8333c55bee
commit 9e2e7b66a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      packages/grafana-ui/src/components/BarChart/utils.ts
  2. 0
      packages/grafana-ui/src/components/GraphNG/SeriesVisibilityChangeMode.ts
  3. 13
      packages/grafana-ui/src/components/GraphNG/types.ts
  4. 10
      packages/grafana-ui/src/components/GraphNG/utils.ts
  5. 3
      packages/grafana-ui/src/components/PanelChrome/PanelContext.ts
  6. 2
      packages/grafana-ui/src/components/PanelChrome/index.ts
  7. 10
      packages/grafana-ui/src/components/PanelChrome/types.ts
  8. 50
      packages/grafana-ui/src/components/PieChart/PieChart.tsx
  9. 2
      packages/grafana-ui/src/components/TimeSeries/utils.ts
  10. 12
      packages/grafana-ui/src/components/Timeline/utils.ts
  11. 31
      packages/grafana-ui/src/components/VizLegend/VizLegend.tsx
  12. 2
      packages/grafana-ui/src/components/VizLegend/VizLegendList.tsx
  13. 8
      packages/grafana-ui/src/components/VizLegend/types.ts
  14. 8
      packages/grafana-ui/src/components/VizLegend/utils.ts
  15. 3
      packages/grafana-ui/src/components/index.ts
  16. 2
      packages/grafana-ui/src/components/uPlot/PlotLegend.tsx
  17. 2
      packages/grafana-ui/src/components/uPlot/config.ts
  18. 8
      packages/grafana-ui/src/components/uPlot/utils.test.ts
  19. 2
      packages/grafana-ui/src/components/uPlot/utils.ts
  20. 10
      public/app/features/dashboard/dashgrid/PanelChrome.tsx
  21. 171
      public/app/features/dashboard/dashgrid/SeriesVisibilityConfigFactory.ts
  22. 1
      public/app/plugins/panel/piechart/PieChartPanel.tsx
  23. 4
      public/app/plugins/panel/piechart/module.tsx
  24. 15
      public/app/plugins/panel/timeseries/TimeSeriesPanel.tsx
  25. 22
      public/app/plugins/panel/timeseries/overrides/hideSeriesConfigFactory.test.ts
  26. 6
      public/app/plugins/panel/timeseries/overrides/hideSeriesConfigFactory.ts

@ -117,7 +117,7 @@ export function preparePlotConfigBuilder(
colorMode,
pathBuilder: config.drawBars,
pointsBuilder: config.drawPoints,
show: !customConfig.hideFrom?.graph,
show: !customConfig.hideFrom?.viz,
gradientMode: customConfig.gradientMode,
thresholds: field.config.thresholds,

@ -1,14 +1,5 @@
import { DataFrameFieldIndex, FieldMatcher } from '@grafana/data';
/**
* Mode to describe if a legend is isolated/selected or being appended to an existing
* series selection.
* @alpha
*/
export enum GraphNGLegendEventMode {
ToggleSelection = 'select',
AppendToSelection = 'append',
}
import { SeriesVisibilityChangeMode } from '..';
/**
* Event being triggered when the user interact with the Graph legend.
@ -16,7 +7,7 @@ export enum GraphNGLegendEventMode {
*/
export interface GraphNGLegendEvent {
fieldIndex: DataFrameFieldIndex;
mode: GraphNGLegendEventMode;
mode: SeriesVisibilityChangeMode;
}
/** @alpha */

@ -1,5 +1,4 @@
import React from 'react';
import { GraphNGLegendEventMode, XYFieldMatchers } from './types';
import { XYFieldMatchers } from './types';
import {
ArrayVector,
DataFrame,
@ -18,13 +17,6 @@ export interface PrepConfigOpts {
[prop: string]: any;
}
export function mapMouseEventToMode(event: React.MouseEvent): GraphNGLegendEventMode {
if (event.ctrlKey || event.metaKey || event.shiftKey) {
return GraphNGLegendEventMode.AppendToSelection;
}
return GraphNGLegendEventMode.ToggleSelection;
}
function applySpanNullsThresholds(frames: DataFrame[]) {
for (const frame of frames) {
let refField = frame.fields.find((field) => field.type === FieldType.time); // this doesnt need to be time, just any numeric/asc join field

@ -1,5 +1,6 @@
import { EventBusSrv, EventBus } from '@grafana/data';
import React from 'react';
import { SeriesVisibilityChangeMode } from '.';
/** @alpha */
export interface PanelContext {
@ -11,6 +12,8 @@ export interface PanelContext {
* @alpha -- experimental
*/
onSeriesColorChange?: (label: string, color: string) => void;
onToggleSeriesVisibility?: (label: string, mode: SeriesVisibilityChangeMode) => void;
}
const PanelContextRoot = React.createContext<PanelContext>({

@ -38,3 +38,5 @@ export {
} from './ErrorIndicator';
export { usePanelContext, PanelContextProvider, PanelContext } from './PanelContext';
export * from './types';

@ -0,0 +1,10 @@
/**
* Mode to describe if a legend is isolated/selected or being appended to an existing
* series selection.
* @alpha
*/
export enum SeriesVisibilityChangeMode {
ToggleSelection = 'select',
AppendToSelection = 'append',
}

@ -35,6 +35,7 @@ import { getTooltipContainerStyles } from '../../themes/mixins';
import { SeriesTable, SeriesTableRowProps, VizTooltipOptions } from '../VizTooltip';
import { usePanelContext } from '../PanelChrome';
import { Subscription } from 'rxjs';
import { SeriesVisibilityChangeBehavior } from '../VizLegend/types';
const defaultLegendOptions: PieChartLegendOptions = {
displayMode: LegendDisplayMode.List,
@ -94,31 +95,37 @@ function getLegend(props: PieChartProps, displayValues: FieldDisplay[]) {
if (legendOptions.displayMode === LegendDisplayMode.Hidden) {
return undefined;
}
const values = displayValues.map((v) => v.display);
const total = values.reduce((acc, item) => item.numeric + acc, 0);
const legendItems = values.map<VizLegendItem>((value, idx) => {
const total = displayValues
.filter((item) => {
return !item.field.custom.hideFrom.viz;
})
.reduce((acc, item) => item.display.numeric + acc, 0);
const legendItems = displayValues.map<VizLegendItem>((value, idx) => {
const hidden = value.field.custom.hideFrom.viz;
const display = value.display;
return {
label: value.title ?? '',
color: value.color ?? FALLBACK_COLOR,
label: display.title ?? '',
color: display.color ?? FALLBACK_COLOR,
yAxis: 1,
getItemKey: () => (value.title ?? '') + idx,
disabled: hidden,
getItemKey: () => (display.title ?? '') + idx,
getDisplayValues: () => {
const valuesToShow = legendOptions.values ?? [];
let displayValues = [];
if (valuesToShow.includes(PieChartLegendValues.Value)) {
displayValues.push({ numeric: value.numeric, text: formattedValueToString(value), title: 'Value' });
displayValues.push({ numeric: display.numeric, text: formattedValueToString(display), title: 'Value' });
}
if (valuesToShow.includes(PieChartLegendValues.Percent)) {
const fractionOfTotal = value.numeric / total;
const fractionOfTotal = hidden ? 0 : display.numeric / total;
const percentOfTotal = fractionOfTotal * 100;
displayValues.push({
numeric: fractionOfTotal,
percent: percentOfTotal,
text: percentOfTotal.toFixed(0) + '%',
text: hidden ? '-' : percentOfTotal.toFixed(0) + '%',
title: valuesToShow.length > 1 ? 'Percent' : undefined,
});
}
@ -128,7 +135,14 @@ function getLegend(props: PieChartProps, displayValues: FieldDisplay[]) {
};
});
return <VizLegend items={legendItems} placement={legendOptions.placement} displayMode={legendOptions.displayMode} />;
return (
<VizLegend
items={legendItems}
seriesVisibilityChangeBehavior={SeriesVisibilityChangeBehavior.Hide}
placement={legendOptions.placement}
displayMode={legendOptions.displayMode}
/>
);
}
function useSliceHighlightState() {
@ -174,7 +188,11 @@ export const PieChartSvg: FC<PieChartSvgProps> = ({
scroll: true,
});
if (fieldDisplayValues.length < 0) {
const filteredFieldDisplayValues = fieldDisplayValues.filter((dv) => {
return !dv.field.custom.hideFrom.viz;
});
if (filteredFieldDisplayValues.length < 0) {
return <div>No data</div>;
}
@ -186,10 +204,12 @@ export const PieChartSvg: FC<PieChartSvgProps> = ({
const showLabel = displayLabels.length > 0;
const showTooltip = tooltipOptions.mode !== 'none' && tooltip.tooltipOpen;
const total = fieldDisplayValues.reduce((acc, item) => item.display.numeric + acc, 0);
const total = filteredFieldDisplayValues.reduce((acc, item) => item.display.numeric + acc, 0);
const layout = getPieLayout(width, height, pieType);
const colors = [
...new Set(fieldDisplayValues.map((fieldDisplayValue) => fieldDisplayValue.display.color ?? FALLBACK_COLOR)),
...new Set(
filteredFieldDisplayValues.map((fieldDisplayValue) => fieldDisplayValue.display.color ?? FALLBACK_COLOR)
),
];
return (
@ -213,7 +233,7 @@ export const PieChartSvg: FC<PieChartSvgProps> = ({
);
})}
<Pie
data={fieldDisplayValues}
data={filteredFieldDisplayValues}
pieValue={getValue}
outerRadius={layout.outerRadius}
innerRadius={layout.innerRadius}

@ -161,7 +161,7 @@ export const preparePlotConfigBuilder: PrepConfig = ({ frame, theme, timeZone, g
pointSize: customConfig.pointSize,
pointColor: customConfig.pointColor ?? seriesColor,
spanNulls: customConfig.spanNulls || false,
show: !customConfig.hideFrom?.graph,
show: !customConfig.hideFrom?.viz,
gradientMode: customConfig.gradientMode,
thresholds: config.thresholds,

@ -1,5 +1,5 @@
import React from 'react';
import { GraphNGLegendEventMode, XYFieldMatchers } from '../GraphNG/types';
import { XYFieldMatchers } from '../GraphNG/types';
import {
DataFrame,
FieldColorModeId,
@ -17,7 +17,7 @@ import { AxisPlacement, GraphGradientMode, ScaleDirection, ScaleOrientation } fr
import { measureText } from '../../utils/measureText';
import { PrepConfigOpts } from '../GraphNG/utils';
import { TimelineFieldConfig } from '../..';
import { SeriesVisibilityChangeMode, TimelineFieldConfig } from '../..';
import { BarValueVisibility, TimelineMode } from './types';
const defaultConfig: TimelineFieldConfig = {
@ -26,11 +26,11 @@ const defaultConfig: TimelineFieldConfig = {
gradientMode: GraphGradientMode.None,
};
export function mapMouseEventToMode(event: React.MouseEvent): GraphNGLegendEventMode {
export function mapMouseEventToMode(event: React.MouseEvent): SeriesVisibilityChangeMode {
if (event.ctrlKey || event.metaKey || event.shiftKey) {
return GraphNGLegendEventMode.AppendToSelection;
return SeriesVisibilityChangeMode.AppendToSelection;
}
return GraphNGLegendEventMode.ToggleSelection;
return SeriesVisibilityChangeMode.ToggleSelection;
}
export function preparePlotFrame(data: DataFrame[], dimFields: XYFieldMatchers) {
@ -186,7 +186,7 @@ export const preparePlotConfigBuilder: PrepConfig = ({
//colorMode,
fillOpacity,
theme,
show: !customConfig.hideFrom?.graph,
show: !customConfig.hideFrom?.viz,
thresholds: config.thresholds,
// The following properties are not used in the uPlot config, but are utilized as transport for legend config

@ -1,10 +1,11 @@
import React, { useCallback } from 'react';
import { LegendProps, VizLegendItem } from './types';
import { LegendProps, SeriesVisibilityChangeBehavior, VizLegendItem } from './types';
import { LegendDisplayMode } from './models.gen';
import { VizLegendTable } from './VizLegendTable';
import { VizLegendList } from './VizLegendList';
import { DataHoverClearEvent, DataHoverEvent } from '@grafana/data';
import { usePanelContext } from '../PanelChrome';
import { SeriesVisibilityChangeMode, usePanelContext } from '../PanelChrome';
import { mapMouseEventToMode } from './utils';
/**
* @public
@ -13,13 +14,14 @@ export const VizLegend: React.FunctionComponent<LegendProps> = ({
items,
displayMode,
sortBy: sortKey,
seriesVisibilityChangeBehavior = SeriesVisibilityChangeBehavior.Isolate,
sortDesc,
onToggleSort,
onLabelClick,
onToggleSort,
placement,
className,
}) => {
const { eventBus } = usePanelContext();
const { eventBus, onToggleSeriesVisibility } = usePanelContext();
const onMouseEnter = useCallback(
(item: VizLegendItem, event: React.MouseEvent<HTMLElement, MouseEvent>) => {
@ -51,6 +53,23 @@ export const VizLegend: React.FunctionComponent<LegendProps> = ({
[eventBus]
);
const onLegendLabelClick = useCallback(
(item: VizLegendItem, event: React.MouseEvent<HTMLElement, MouseEvent>) => {
if (onLabelClick) {
onLabelClick(item, event);
}
if (onToggleSeriesVisibility) {
onToggleSeriesVisibility(
item.label,
seriesVisibilityChangeBehavior === SeriesVisibilityChangeBehavior.Hide
? SeriesVisibilityChangeMode.AppendToSelection
: mapMouseEventToMode(event)
);
}
},
[onToggleSeriesVisibility, onLabelClick, seriesVisibilityChangeBehavior]
);
switch (displayMode) {
case LegendDisplayMode.Table:
return (
@ -60,7 +79,7 @@ export const VizLegend: React.FunctionComponent<LegendProps> = ({
placement={placement}
sortBy={sortKey}
sortDesc={sortDesc}
onLabelClick={onLabelClick}
onLabelClick={onLegendLabelClick}
onToggleSort={onToggleSort}
onLabelMouseEnter={onMouseEnter}
onLabelMouseOut={onMouseOut}
@ -74,7 +93,7 @@ export const VizLegend: React.FunctionComponent<LegendProps> = ({
placement={placement}
onLabelMouseEnter={onMouseEnter}
onLabelMouseOut={onMouseOut}
onLabelClick={onLabelClick}
onLabelClick={onLegendLabelClick}
/>
);
default:

@ -15,9 +15,9 @@ export interface Props extends VizLegendBaseProps {}
export const VizLegendList: React.FunctionComponent<Props> = ({
items,
itemRenderer,
onLabelClick,
onLabelMouseEnter,
onLabelMouseOut,
onLabelClick,
placement,
className,
}) => {

@ -2,12 +2,18 @@ import { DataFrameFieldIndex, DisplayValue } from '@grafana/data';
import React from 'react';
import { LegendDisplayMode, LegendPlacement } from './models.gen';
export enum SeriesVisibilityChangeBehavior {
Isolate,
Hide,
}
export interface VizLegendBaseProps {
placement: LegendPlacement;
className?: string;
items: VizLegendItem[];
itemRenderer?: (item: VizLegendItem, index: number) => JSX.Element;
seriesVisibilityChangeBehavior?: SeriesVisibilityChangeBehavior;
onLabelClick?: (item: VizLegendItem, event: React.MouseEvent<HTMLElement>) => void;
itemRenderer?: (item: VizLegendItem, index: number) => JSX.Element;
onLabelMouseEnter?: (item: VizLegendItem, event: React.MouseEvent<HTMLElement>) => void;
onLabelMouseOut?: (item: VizLegendItem, event: React.MouseEvent<HTMLElement>) => void;
}

@ -0,0 +1,8 @@
import { SeriesVisibilityChangeMode } from '..';
export function mapMouseEventToMode(event: React.MouseEvent): SeriesVisibilityChangeMode {
if (event.ctrlKey || event.metaKey || event.shiftKey) {
return SeriesVisibilityChangeMode.AppendToSelection;
}
return SeriesVisibilityChangeMode.ToggleSelection;
}

@ -247,6 +247,7 @@ export { BarChart } from './BarChart/BarChart';
export { TimelineChart } from './Timeline/TimelineChart';
export { BarChartOptions, BarValueVisibility, BarChartFieldConfig } from './BarChart/types';
export { TimelineOptions, TimelineFieldConfig } from './Timeline/types';
export { GraphNGLegendEvent, GraphNGLegendEventMode } from './GraphNG/types';
export { GraphNGLegendEvent } from './GraphNG/types';
export * from './PanelChrome/types';
export * from './NodeGraph';
export { EmotionPerfTest } from './ThemeDemos/EmotionPerfTest';

@ -5,9 +5,9 @@ import { VizLegendItem } from '../VizLegend/types';
import { VizLegendOptions } from '../VizLegend/models.gen';
import { AxisPlacement } from './config';
import { VizLayout, VizLayoutLegendProps } from '../VizLayout/VizLayout';
import { mapMouseEventToMode } from '../GraphNG/utils';
import { VizLegend } from '../VizLegend/VizLegend';
import { GraphNGLegendEvent } from '..';
import { mapMouseEventToMode } from '../VizLegend/utils';
const defaultFormatter = (v: any) => (v == null ? '-' : v.toFixed(1));

@ -165,7 +165,7 @@ export interface AxisConfig {
export interface HideSeriesConfig {
tooltip: boolean;
legend: boolean;
graph: boolean;
viz: boolean;
}
/**

@ -233,10 +233,10 @@ describe('preparePlotData', () => {
{
name: 'a',
values: [-10, 20, 10],
config: { custom: { stacking: { mode: StackingMode.Normal, group: 'stackA' }, hideFrom: { graph: true } } },
config: { custom: { stacking: { mode: StackingMode.Normal, group: 'stackA' }, hideFrom: { viz: true } } },
},
{
// Will ignore a series as stacking base as it's hidden from graph
// Will ignore a series as stacking base as it's hidden from viz
name: 'b',
values: [10, 10, 10],
config: { custom: { stacking: { mode: StackingMode.Normal, group: 'stackA' } } },
@ -249,10 +249,10 @@ describe('preparePlotData', () => {
{
name: 'e',
values: [1, 2, 3],
config: { custom: { stacking: { mode: StackingMode.Normal, group: 'stackB' }, hideFrom: { graph: true } } },
config: { custom: { stacking: { mode: StackingMode.Normal, group: 'stackB' }, hideFrom: { viz: true } } },
},
{
// Will ignore e series as stacking base as it's hidden from graph
// Will ignore e series as stacking base as it's hidden from viz
name: 'f',
values: [1, 2, 3],
config: { custom: { stacking: { mode: StackingMode.Normal, group: 'stackB' } } },

@ -96,7 +96,7 @@ export function collectStackingGroups(f: Field, groups: Map<string, number[]>, s
if (
customConfig.stacking?.mode !== StackingMode.None &&
customConfig.stacking?.group &&
!customConfig.hideFrom?.graph
!customConfig.hideFrom?.viz
) {
if (!groups.has(customConfig.stacking.group)) {
groups.set(customConfig.stacking.group, [seriesIdx]);

@ -4,7 +4,7 @@ import classNames from 'classnames';
import { Subscription } from 'rxjs';
// Components
import { PanelHeader } from './PanelHeader/PanelHeader';
import { ErrorBoundary, PanelContextProvider, PanelContext } from '@grafana/ui';
import { ErrorBoundary, PanelContextProvider, PanelContext, SeriesVisibilityChangeMode } from '@grafana/ui';
// Utils & Services
import { getTimeSrv, TimeSrv } from '../services/TimeSrv';
import { applyPanelTimeOverrides } from 'app/features/dashboard/utils/panel';
@ -30,6 +30,7 @@ import { selectors } from '@grafana/e2e-selectors';
import { loadSnapshotData } from '../utils/loadSnapshotData';
import { RefreshEvent, RenderEvent } from 'app/types/events';
import { changeSeriesColorConfigFactory } from 'app/plugins/panel/timeseries/overrides/colorSeriesConfigFactory';
import { seriesVisibilityConfigFactory } from './SeriesVisibilityConfigFactory';
const DEFAULT_PLUGIN_ERROR = 'Error in plugin';
@ -77,6 +78,7 @@ export class PanelChrome extends Component<Props, State> {
context: {
eventBus,
onSeriesColorChange: this.onSeriesColorChange,
onToggleSeriesVisibility: this.onSeriesVisibilityChange,
},
data: this.getInitialPanelDataState(),
};
@ -86,6 +88,12 @@ export class PanelChrome extends Component<Props, State> {
this.onFieldConfigChange(changeSeriesColorConfigFactory(label, color, this.props.panel.fieldConfig));
};
onSeriesVisibilityChange = (label: string, mode: SeriesVisibilityChangeMode) => {
this.onFieldConfigChange(
seriesVisibilityConfigFactory(label, mode, this.props.panel.fieldConfig, this.state.data.series)
);
};
getInitialPanelDataState(): PanelData {
return {
state: LoadingState.NotStarted,

@ -0,0 +1,171 @@
import {
ByNamesMatcherMode,
DataFrame,
DynamicConfigValue,
FieldConfigSource,
FieldMatcherID,
FieldType,
getFieldDisplayName,
isSystemOverrideWithRef,
SystemConfigOverrideRule,
} from '@grafana/data';
import { SeriesVisibilityChangeMode } from '@grafana/ui';
const displayOverrideRef = 'hideSeriesFrom';
const isHideSeriesOverride = isSystemOverrideWithRef(displayOverrideRef);
export function seriesVisibilityConfigFactory(
label: string,
mode: SeriesVisibilityChangeMode,
fieldConfig: FieldConfigSource,
data: DataFrame[]
) {
const { overrides } = fieldConfig;
const displayName = label;
const currentIndex = overrides.findIndex(isHideSeriesOverride);
if (currentIndex < 0) {
if (mode === SeriesVisibilityChangeMode.ToggleSelection) {
const override = createOverride([displayName]);
return {
...fieldConfig,
overrides: [override, ...fieldConfig.overrides],
};
}
const displayNames = getDisplayNames(data, displayName);
const override = createOverride(displayNames);
return {
...fieldConfig,
overrides: [override, ...fieldConfig.overrides],
};
}
const overridesCopy = Array.from(overrides);
const [current] = overridesCopy.splice(currentIndex, 1) as SystemConfigOverrideRule[];
if (mode === SeriesVisibilityChangeMode.ToggleSelection) {
const existing = getExistingDisplayNames(current);
if (existing[0] === displayName && existing.length === 1) {
return {
...fieldConfig,
overrides: overridesCopy,
};
}
const override = createOverride([displayName]);
return {
...fieldConfig,
overrides: [override, ...overridesCopy],
};
}
const override = createExtendedOverride(current, displayName);
if (allFieldsAreExcluded(override, data)) {
return {
...fieldConfig,
overrides: overridesCopy,
};
}
return {
...fieldConfig,
overrides: [override, ...overridesCopy],
};
}
function createOverride(
names: string[],
mode = ByNamesMatcherMode.exclude,
property?: DynamicConfigValue
): SystemConfigOverrideRule {
property = property ?? {
id: 'custom.hideFrom',
value: {
viz: true,
legend: false,
tooltip: false,
},
};
return {
__systemRef: displayOverrideRef,
matcher: {
id: FieldMatcherID.byNames,
options: {
mode: mode,
names: names,
prefix: mode === ByNamesMatcherMode.exclude ? 'All except:' : undefined,
readOnly: true,
},
},
properties: [
{
...property,
value: {
viz: true,
legend: false,
tooltip: false,
},
},
],
};
}
const createExtendedOverride = (
current: SystemConfigOverrideRule,
displayName: string,
mode = ByNamesMatcherMode.exclude
): SystemConfigOverrideRule => {
const property = current.properties.find((p) => p.id === 'custom.hideFrom');
const existing = getExistingDisplayNames(current);
const index = existing.findIndex((name) => name === displayName);
if (index < 0) {
existing.push(displayName);
} else {
existing.splice(index, 1);
}
return createOverride(existing, mode, property);
};
const getExistingDisplayNames = (rule: SystemConfigOverrideRule): string[] => {
const names = rule.matcher.options?.names;
if (!Array.isArray(names)) {
return [];
}
return names;
};
const allFieldsAreExcluded = (override: SystemConfigOverrideRule, data: DataFrame[]): boolean => {
return getExistingDisplayNames(override).length === getDisplayNames(data).length;
};
const getDisplayNames = (data: DataFrame[], excludeName?: string): string[] => {
const unique = new Set<string>();
for (const frame of data) {
for (const field of frame.fields) {
if (field.type !== FieldType.number) {
continue;
}
const name = getFieldDisplayName(field, frame, data);
if (name === excludeName) {
continue;
}
unique.add(name);
}
}
return Array.from(unique);
};

@ -10,7 +10,6 @@ export const PieChartPanel: React.FC<Props> = ({
height,
options,
data,
onFieldConfigChange,
replaceVariables,
fieldConfig,
timeZone,

@ -3,6 +3,7 @@ import { PieChartPanel } from './PieChartPanel';
import { PieChartOptions } from './types';
import { LegendDisplayMode, PieChartType, PieChartLabels, PieChartLegendValues } from '@grafana/ui';
import { PieChartPanelChangedHandler } from './migrations';
import { addHideFrom } from '../timeseries/config';
export const plugin = new PanelPlugin<PieChartOptions>(PieChartPanel)
.setPanelChangeHandler(PieChartPanelChangedHandler)
@ -20,6 +21,9 @@ export const plugin = new PanelPlugin<PieChartOptions>(PieChartPanel)
},
},
},
useCustomConfig: (builder) => {
addHideFrom(builder);
},
})
.setPanelOptions((builder) => {
builder

@ -1,8 +1,7 @@
import { Field, PanelProps } from '@grafana/data';
import { TimeSeries, GraphNGLegendEvent, TooltipPlugin, ZoomPlugin } from '@grafana/ui';
import { TimeSeries, TooltipPlugin, ZoomPlugin } from '@grafana/ui';
import { getFieldLinksForExplore } from 'app/features/explore/utils/links';
import React, { useCallback } from 'react';
import { hideSeriesConfigFactory } from './overrides/hideSeriesConfigFactory';
import React from 'react';
import { AnnotationsPlugin } from './plugins/AnnotationsPlugin';
import { ContextMenuPlugin } from './plugins/ContextMenuPlugin';
import { ExemplarsPlugin } from './plugins/ExemplarsPlugin';
@ -17,18 +16,9 @@ export const TimeSeriesPanel: React.FC<TimeSeriesPanelProps> = ({
width,
height,
options,
fieldConfig,
onChangeTimeRange,
onFieldConfigChange,
replaceVariables,
}) => {
const onLegendClick = useCallback(
(event: GraphNGLegendEvent) => {
onFieldConfigChange(hideSeriesConfigFactory(event, fieldConfig, data.series));
},
[fieldConfig, onFieldConfigChange, data.series]
);
const getFieldLinks = (field: Field, rowIndex: number) => {
return getFieldLinksForExplore({ field, rowIndex, range: timeRange });
};
@ -50,7 +40,6 @@ export const TimeSeriesPanel: React.FC<TimeSeriesPanelProps> = ({
width={width}
height={height}
legend={options.legend}
onLegendClick={onLegendClick}
>
{(config, alignedDataFrame) => {
return (

@ -6,13 +6,13 @@ import {
FieldType,
toDataFrame,
} from '@grafana/data';
import { GraphNGLegendEvent, GraphNGLegendEventMode } from '@grafana/ui';
import { GraphNGLegendEvent, SeriesVisibilityChangeMode } from '@grafana/ui';
import { hideSeriesConfigFactory } from './hideSeriesConfigFactory';
describe('hideSeriesConfigFactory', () => {
it('should create config override matching one series', () => {
const event: GraphNGLegendEvent = {
mode: GraphNGLegendEventMode.ToggleSelection,
mode: SeriesVisibilityChangeMode.ToggleSelection,
fieldIndex: {
frameIndex: 0,
fieldIndex: 1,
@ -43,7 +43,7 @@ describe('hideSeriesConfigFactory', () => {
it('should create config override matching one series if selected with others', () => {
const event: GraphNGLegendEvent = {
mode: GraphNGLegendEventMode.ToggleSelection,
mode: SeriesVisibilityChangeMode.ToggleSelection,
fieldIndex: {
frameIndex: 0,
fieldIndex: 1,
@ -86,7 +86,7 @@ describe('hideSeriesConfigFactory', () => {
it('should create config override that append series to existing override', () => {
const event: GraphNGLegendEvent = {
mode: GraphNGLegendEventMode.AppendToSelection,
mode: SeriesVisibilityChangeMode.AppendToSelection,
fieldIndex: {
frameIndex: 1,
fieldIndex: 1,
@ -129,7 +129,7 @@ describe('hideSeriesConfigFactory', () => {
it('should create config override that hides all series if appending only existing series', () => {
const event: GraphNGLegendEvent = {
mode: GraphNGLegendEventMode.AppendToSelection,
mode: SeriesVisibilityChangeMode.AppendToSelection,
fieldIndex: {
frameIndex: 0,
fieldIndex: 1,
@ -166,7 +166,7 @@ describe('hideSeriesConfigFactory', () => {
it('should create config override that removes series if appending existing field', () => {
const event: GraphNGLegendEvent = {
mode: GraphNGLegendEventMode.AppendToSelection,
mode: SeriesVisibilityChangeMode.AppendToSelection,
fieldIndex: {
frameIndex: 0,
fieldIndex: 1,
@ -203,7 +203,7 @@ describe('hideSeriesConfigFactory', () => {
it('should create config override replacing existing series', () => {
const event: GraphNGLegendEvent = {
mode: GraphNGLegendEventMode.ToggleSelection,
mode: SeriesVisibilityChangeMode.ToggleSelection,
fieldIndex: {
frameIndex: 1,
fieldIndex: 1,
@ -240,7 +240,7 @@ describe('hideSeriesConfigFactory', () => {
it('should create config override removing existing series', () => {
const event: GraphNGLegendEvent = {
mode: GraphNGLegendEventMode.ToggleSelection,
mode: SeriesVisibilityChangeMode.ToggleSelection,
fieldIndex: {
frameIndex: 0,
fieldIndex: 1,
@ -277,7 +277,7 @@ describe('hideSeriesConfigFactory', () => {
it('should remove override if all fields are appended', () => {
const event: GraphNGLegendEvent = {
mode: GraphNGLegendEventMode.AppendToSelection,
mode: SeriesVisibilityChangeMode.AppendToSelection,
fieldIndex: {
frameIndex: 1,
fieldIndex: 1,
@ -314,7 +314,7 @@ describe('hideSeriesConfigFactory', () => {
it('should create config override hiding appended series if no previous override exists', () => {
const event: GraphNGLegendEvent = {
mode: GraphNGLegendEventMode.AppendToSelection,
mode: SeriesVisibilityChangeMode.AppendToSelection,
fieldIndex: {
frameIndex: 0,
fieldIndex: 1,
@ -357,7 +357,7 @@ describe('hideSeriesConfigFactory', () => {
it('should return existing override if invalid index is passed', () => {
const event: GraphNGLegendEvent = {
mode: GraphNGLegendEventMode.ToggleSelection,
mode: SeriesVisibilityChangeMode.ToggleSelection,
fieldIndex: {
frameIndex: 4,
fieldIndex: 1,

@ -9,7 +9,7 @@ import {
isSystemOverrideWithRef,
SystemConfigOverrideRule,
} from '@grafana/data';
import { GraphNGLegendEvent, GraphNGLegendEventMode } from '@grafana/ui';
import { GraphNGLegendEvent, SeriesVisibilityChangeMode } from '@grafana/ui';
const displayOverrideRef = 'hideSeriesFrom';
const isHideSeriesOverride = isSystemOverrideWithRef(displayOverrideRef);
@ -38,7 +38,7 @@ export const hideSeriesConfigFactory = (
const currentIndex = overrides.findIndex(isHideSeriesOverride);
if (currentIndex < 0) {
if (mode === GraphNGLegendEventMode.ToggleSelection) {
if (mode === SeriesVisibilityChangeMode.ToggleSelection) {
const override = createOverride([displayName]);
return {
@ -59,7 +59,7 @@ export const hideSeriesConfigFactory = (
const overridesCopy = Array.from(overrides);
const [current] = overridesCopy.splice(currentIndex, 1) as SystemConfigOverrideRule[];
if (mode === GraphNGLegendEventMode.ToggleSelection) {
if (mode === SeriesVisibilityChangeMode.ToggleSelection) {
const existing = getExistingDisplayNames(current);
if (existing[0] === displayName && existing.length === 1) {

Loading…
Cancel
Save