mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
FieldConfig: Add support for Actions (#92874)
Co-authored-by: Leon Sorokin <leeoniya@gmail.com>
This commit is contained in:
parent
165ca3b4e8
commit
f9f85131a9
@ -1,3 +1,4 @@
|
||||
import { Action } from '../../types/action';
|
||||
import { Field } from '../../types/dataFrame';
|
||||
import { DataLink } from '../../types/dataLink';
|
||||
import { FieldOverrideContext } from '../../types/fieldOverrides';
|
||||
@ -59,6 +60,15 @@ export const dataLinksOverrideProcessor = (
|
||||
return value;
|
||||
};
|
||||
|
||||
export const actionsOverrideProcessor = (
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
value: any,
|
||||
_context: FieldOverrideContext,
|
||||
_settings?: DataLinksFieldConfigSettings
|
||||
): Action[] => {
|
||||
return value;
|
||||
};
|
||||
|
||||
export interface ValueMappingFieldConfigSettings {}
|
||||
|
||||
export const valueMappingsOverrideProcessor = (
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { HideSeriesConfig } from '@grafana/schema';
|
||||
|
||||
import { ScopedVars } from './ScopedVars';
|
||||
import { Action } from './action';
|
||||
import { QueryResultBase, Labels, NullValueMode } from './data';
|
||||
import { DataLink, LinkModel } from './dataLink';
|
||||
import { DecimalCount, DisplayProcessor, DisplayValue, DisplayValueAlignmentFactors } from './displayValue';
|
||||
@ -98,6 +99,8 @@ export interface FieldConfig<TOptions = any> {
|
||||
// The behavior when clicking on a result
|
||||
links?: DataLink[];
|
||||
|
||||
actions?: Action[];
|
||||
|
||||
// Alternative to empty string
|
||||
noValue?: string;
|
||||
|
||||
|
@ -31,7 +31,7 @@ func TestList(t *testing.T) {
|
||||
|
||||
res, err := List(ctx, "items", nil, Pagination{Limit: 2}, func(ctx context.Context, ns claims.NamespaceInfo, p Pagination) (*ListResponse[item], error) {
|
||||
return &ListResponse[item]{
|
||||
Items: []item{item{"1"}, item{"2"}},
|
||||
Items: []item{{"1"}, {"2"}},
|
||||
}, nil
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
@ -47,7 +47,7 @@ func TestList(t *testing.T) {
|
||||
})
|
||||
res, err := List(ctx, "items", a, Pagination{Limit: 2}, func(ctx context.Context, ns claims.NamespaceInfo, p Pagination) (*ListResponse[item], error) {
|
||||
return &ListResponse[item]{
|
||||
Items: []item{item{"1"}, item{"2"}},
|
||||
Items: []item{{"1"}, {"2"}},
|
||||
}, nil
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
@ -70,13 +70,13 @@ func TestList(t *testing.T) {
|
||||
res, err := List(ctx, "items", a, Pagination{Limit: 2}, func(ctx context.Context, ns claims.NamespaceInfo, p Pagination) (*ListResponse[item], error) {
|
||||
if called {
|
||||
return &ListResponse[item]{
|
||||
Items: []item{item{"3"}},
|
||||
Items: []item{{"3"}},
|
||||
}, nil
|
||||
}
|
||||
|
||||
called = true
|
||||
return &ListResponse[item]{
|
||||
Items: []item{item{"1"}, item{"2"}},
|
||||
Items: []item{{"1"}, {"2"}},
|
||||
Continue: 3,
|
||||
}, nil
|
||||
})
|
||||
|
15
public/app/core/components/OptionsUI/actions.tsx
Normal file
15
public/app/core/components/OptionsUI/actions.tsx
Normal file
@ -0,0 +1,15 @@
|
||||
import { Action, DataLinksFieldConfigSettings, StandardEditorProps, VariableSuggestionsScope } from '@grafana/data';
|
||||
import { ActionsInlineEditor } from 'app/features/actions/ActionsInlineEditor';
|
||||
|
||||
type Props = StandardEditorProps<Action[], DataLinksFieldConfigSettings>;
|
||||
|
||||
export const ActionsValueEditor = ({ value, onChange, context }: Props) => {
|
||||
return (
|
||||
<ActionsInlineEditor
|
||||
actions={value}
|
||||
onChange={onChange}
|
||||
data={context.data}
|
||||
getSuggestions={() => (context.getSuggestions ? context.getSuggestions(VariableSuggestionsScope.Values) : [])}
|
||||
/>
|
||||
);
|
||||
};
|
@ -26,7 +26,10 @@ import {
|
||||
displayNameOverrideProcessor,
|
||||
FieldNamePickerConfigSettings,
|
||||
booleanOverrideProcessor,
|
||||
Action,
|
||||
} from '@grafana/data';
|
||||
import { actionsOverrideProcessor } from '@grafana/data/src/field/overrides/processors';
|
||||
import { config } from '@grafana/runtime';
|
||||
import { FieldConfig } from '@grafana/schema';
|
||||
import { RadioButtonGroup, TimeZonePicker, Switch } from '@grafana/ui';
|
||||
import { FieldNamePicker } from '@grafana/ui/src/components/MatchersUI/FieldNamePicker';
|
||||
@ -34,6 +37,7 @@ import { ThresholdsValueEditor } from 'app/features/dimensions/editors/Threshold
|
||||
import { ValueMappingsEditor } from 'app/features/dimensions/editors/ValueMappingsEditor/ValueMappingsEditor';
|
||||
|
||||
import { DashboardPicker, DashboardPickerOptions } from './DashboardPicker';
|
||||
import { ActionsValueEditor } from './actions';
|
||||
import { ColorValueEditor, ColorValueEditorSettings } from './color';
|
||||
import { FieldColorEditor } from './fieldColor';
|
||||
import { DataLinksValueEditor } from './links';
|
||||
@ -143,6 +147,13 @@ export const getAllOptionEditors = () => {
|
||||
editor: DataLinksValueEditor,
|
||||
};
|
||||
|
||||
const actions: StandardEditorsRegistryItem<Action[]> = {
|
||||
id: 'actions',
|
||||
name: 'Actions',
|
||||
description: 'Allows defining actions',
|
||||
editor: ActionsValueEditor,
|
||||
};
|
||||
|
||||
const statsPicker: StandardEditorsRegistryItem<string[], StatsPickerConfigSettings> = {
|
||||
id: 'stats-picker',
|
||||
name: 'Stats Picker',
|
||||
@ -194,6 +205,7 @@ export const getAllOptionEditors = () => {
|
||||
select,
|
||||
unit,
|
||||
links,
|
||||
actions,
|
||||
statsPicker,
|
||||
strings,
|
||||
timeZone,
|
||||
@ -336,6 +348,8 @@ export const getAllStandardFieldConfigs = () => {
|
||||
category,
|
||||
};
|
||||
|
||||
const dataLinksCategory = config.featureToggles.vizActions ? 'Data links and actions' : 'Data links';
|
||||
|
||||
const links: FieldConfigPropertyItem<FieldConfig, DataLink[], StringFieldConfigSettings> = {
|
||||
id: 'links',
|
||||
path: 'links',
|
||||
@ -347,10 +361,26 @@ export const getAllStandardFieldConfigs = () => {
|
||||
placeholder: '-',
|
||||
},
|
||||
shouldApply: () => true,
|
||||
category: ['Data links'],
|
||||
category: [dataLinksCategory],
|
||||
getItemsCount: (value) => (value ? value.length : 0),
|
||||
};
|
||||
|
||||
const actions: FieldConfigPropertyItem<FieldConfig, Action[], StringFieldConfigSettings> = {
|
||||
id: 'actions',
|
||||
path: 'actions',
|
||||
name: 'Actions',
|
||||
editor: standardEditorsRegistry.get('actions').editor,
|
||||
override: standardEditorsRegistry.get('actions').editor,
|
||||
process: actionsOverrideProcessor,
|
||||
settings: {
|
||||
placeholder: '-',
|
||||
},
|
||||
shouldApply: () => true,
|
||||
category: [dataLinksCategory],
|
||||
getItemsCount: (value) => (value ? value.length : 0),
|
||||
showIf: () => config.featureToggles.vizActions,
|
||||
};
|
||||
|
||||
const color: FieldConfigPropertyItem<FieldConfig, FieldColor | undefined, FieldColorConfigSettings> = {
|
||||
id: 'color',
|
||||
path: 'color',
|
||||
@ -415,5 +445,19 @@ export const getAllStandardFieldConfigs = () => {
|
||||
category,
|
||||
};
|
||||
|
||||
return [unit, min, max, fieldMinMax, decimals, displayName, color, noValue, links, mappings, thresholds, filterable];
|
||||
return [
|
||||
unit,
|
||||
min,
|
||||
max,
|
||||
fieldMinMax,
|
||||
decimals,
|
||||
displayName,
|
||||
color,
|
||||
noValue,
|
||||
links,
|
||||
actions,
|
||||
mappings,
|
||||
thresholds,
|
||||
filterable,
|
||||
];
|
||||
};
|
||||
|
@ -221,6 +221,7 @@ export const SuggestionsInput = ({
|
||||
{...inputProps}
|
||||
ref={handleRef as unknown as React.RefObject<HTMLTextAreaElement>}
|
||||
autoFocus={autoFocus}
|
||||
rows={5}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
@ -24,16 +24,7 @@ const charWidth = measureText('M', UPLOT_AXIS_FONT_SIZE).width;
|
||||
const toRads = Math.PI / 180;
|
||||
|
||||
export const BarChartPanel = (props: PanelProps<Options>) => {
|
||||
const {
|
||||
data,
|
||||
options,
|
||||
fieldConfig,
|
||||
width,
|
||||
height,
|
||||
timeZone,
|
||||
id,
|
||||
// replaceVariables
|
||||
} = props;
|
||||
const { data, options, fieldConfig, width, height, timeZone, id, replaceVariables } = props;
|
||||
|
||||
// will need this if joining on time to re-create data links
|
||||
// const { dataLinkPostProcessor } = usePanelContext();
|
||||
@ -177,6 +168,7 @@ export const BarChartPanel = (props: PanelProps<Options>) => {
|
||||
sortOrder={options.tooltip.sort}
|
||||
isPinned={isPinned}
|
||||
maxHeight={options.tooltip.maxHeight}
|
||||
replaceVariables={replaceVariables}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
|
@ -306,6 +306,7 @@ export const CandlestickPanel = ({
|
||||
isPinned={isPinned}
|
||||
annotate={enableAnnotationCreation ? annotate : undefined}
|
||||
maxHeight={options.tooltip.maxHeight}
|
||||
replaceVariables={replaceVariables}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
|
@ -219,6 +219,7 @@ export const HeatmapPanel = ({
|
||||
annotate={enableAnnotationCreation ? annotate : undefined}
|
||||
maxHeight={options.tooltip.maxHeight}
|
||||
maxWidth={options.tooltip.maxWidth}
|
||||
replaceVariables={replaceVariables}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
|
@ -3,11 +3,13 @@ import * as React from 'react';
|
||||
import uPlot from 'uplot';
|
||||
|
||||
import {
|
||||
ActionModel,
|
||||
DataFrameType,
|
||||
Field,
|
||||
FieldType,
|
||||
formattedValueToString,
|
||||
getFieldDisplayName,
|
||||
InterpolateFunction,
|
||||
LinkModel,
|
||||
PanelData,
|
||||
} from '@grafana/data';
|
||||
@ -16,14 +18,14 @@ import { TooltipDisplayMode, useTheme2 } from '@grafana/ui';
|
||||
import { VizTooltipContent } from '@grafana/ui/src/components/VizTooltip/VizTooltipContent';
|
||||
import { VizTooltipFooter } from '@grafana/ui/src/components/VizTooltip/VizTooltipFooter';
|
||||
import { VizTooltipHeader } from '@grafana/ui/src/components/VizTooltip/VizTooltipHeader';
|
||||
import { VizTooltipWrapper } from '@grafana/ui/src/components/VizTooltip/VizTooltipWrapper';
|
||||
import { ColorIndicator, ColorPlacement, VizTooltipItem } from '@grafana/ui/src/components/VizTooltip/types';
|
||||
import { ColorScale } from 'app/core/components/ColorScale/ColorScale';
|
||||
import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
|
||||
import { isHeatmapCellsDense, readHeatmapRowsCustomMeta } from 'app/features/transformers/calculateHeatmap/heatmap';
|
||||
import { DataHoverView } from 'app/features/visualization/data-hover/DataHoverView';
|
||||
|
||||
import { VizTooltipWrapper } from '../../../../../packages/grafana-ui/src/components/VizTooltip/VizTooltipWrapper';
|
||||
import { getDataLinks } from '../status-history/utils';
|
||||
import { getDataLinks, getFieldActions } from '../status-history/utils';
|
||||
import { isTooltipScrollable } from '../timeseries/utils';
|
||||
|
||||
import { HeatmapData } from './fields';
|
||||
@ -43,6 +45,7 @@ interface HeatmapTooltipProps {
|
||||
annotate?: () => void;
|
||||
maxHeight?: number;
|
||||
maxWidth?: number;
|
||||
replaceVariables: InterpolateFunction;
|
||||
}
|
||||
|
||||
export const HeatmapTooltip = (props: HeatmapTooltipProps) => {
|
||||
@ -73,6 +76,7 @@ const HeatmapHoverCell = ({
|
||||
annotate,
|
||||
maxHeight,
|
||||
maxWidth,
|
||||
replaceVariables,
|
||||
}: HeatmapTooltipProps) => {
|
||||
const index = dataIdxs[1]!;
|
||||
const data = dataRef.current;
|
||||
@ -291,6 +295,7 @@ const HeatmapHoverCell = ({
|
||||
|
||||
if (isPinned) {
|
||||
let links: Array<LinkModel<Field>> = [];
|
||||
let actions: Array<ActionModel<Field>> = [];
|
||||
|
||||
const linksField = data.series?.fields[yValueIdx + 1];
|
||||
|
||||
@ -301,9 +306,11 @@ const HeatmapHoverCell = ({
|
||||
if (visible && hasLinks) {
|
||||
links = getDataLinks(linksField, xValueIdx);
|
||||
}
|
||||
|
||||
actions = getFieldActions(data.series!, linksField, replaceVariables);
|
||||
}
|
||||
|
||||
footer = <VizTooltipFooter dataLinks={links} annotate={annotate} />;
|
||||
footer = <VizTooltipFooter dataLinks={links} annotate={annotate} actions={actions} />;
|
||||
}
|
||||
|
||||
let can = useRef<HTMLCanvasElement>(null);
|
||||
|
@ -5,10 +5,10 @@ import { SortOrder, TooltipDisplayMode } from '@grafana/schema/dist/esm/common/c
|
||||
import { VizTooltipContent } from '@grafana/ui/src/components/VizTooltip/VizTooltipContent';
|
||||
import { VizTooltipFooter } from '@grafana/ui/src/components/VizTooltip/VizTooltipFooter';
|
||||
import { VizTooltipHeader } from '@grafana/ui/src/components/VizTooltip/VizTooltipHeader';
|
||||
import { VizTooltipWrapper } from '@grafana/ui/src/components/VizTooltip/VizTooltipWrapper';
|
||||
import { VizTooltipItem } from '@grafana/ui/src/components/VizTooltip/types';
|
||||
import { getContentItems } from '@grafana/ui/src/components/VizTooltip/utils';
|
||||
|
||||
import { VizTooltipWrapper } from '../../../../../packages/grafana-ui/src/components/VizTooltip/VizTooltipWrapper';
|
||||
import { getDataLinks } from '../status-history/utils';
|
||||
import { isTooltipScrollable } from '../timeseries/utils';
|
||||
|
||||
|
@ -198,6 +198,7 @@ export const StateTimelinePanel = ({
|
||||
annotate={enableAnnotationCreation ? annotate : undefined}
|
||||
withDuration={true}
|
||||
maxHeight={options.tooltip.maxHeight}
|
||||
replaceVariables={replaceVariables}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
|
@ -6,12 +6,12 @@ import { TooltipDisplayMode } from '@grafana/ui';
|
||||
import { VizTooltipContent } from '@grafana/ui/src/components/VizTooltip/VizTooltipContent';
|
||||
import { VizTooltipFooter } from '@grafana/ui/src/components/VizTooltip/VizTooltipFooter';
|
||||
import { VizTooltipHeader } from '@grafana/ui/src/components/VizTooltip/VizTooltipHeader';
|
||||
import { VizTooltipWrapper } from '@grafana/ui/src/components/VizTooltip/VizTooltipWrapper';
|
||||
import { VizTooltipItem } from '@grafana/ui/src/components/VizTooltip/types';
|
||||
import { getContentItems } from '@grafana/ui/src/components/VizTooltip/utils';
|
||||
import { findNextStateIndex, fmtDuration } from 'app/core/components/TimelineChart/utils';
|
||||
|
||||
import { VizTooltipWrapper } from '../../../../../packages/grafana-ui/src/components/VizTooltip/VizTooltipWrapper';
|
||||
import { getDataLinks } from '../status-history/utils';
|
||||
import { getDataLinks, getFieldActions } from '../status-history/utils';
|
||||
import { TimeSeriesTooltipProps } from '../timeseries/TimeSeriesTooltip';
|
||||
import { isTooltipScrollable } from '../timeseries/utils';
|
||||
|
||||
@ -31,6 +31,7 @@ export const StateTimelineTooltip2 = ({
|
||||
timeRange,
|
||||
withDuration,
|
||||
maxHeight,
|
||||
replaceVariables,
|
||||
}: StateTimelineTooltip2Props) => {
|
||||
const xField = series.fields[0];
|
||||
|
||||
@ -70,8 +71,9 @@ export const StateTimelineTooltip2 = ({
|
||||
const field = series.fields[seriesIdx];
|
||||
const dataIdx = dataIdxs[seriesIdx]!;
|
||||
const links = getDataLinks(field, dataIdx);
|
||||
const actions = getFieldActions(series, field, replaceVariables!);
|
||||
|
||||
footer = <VizTooltipFooter dataLinks={links} annotate={annotate} />;
|
||||
footer = <VizTooltipFooter dataLinks={links} annotate={annotate} actions={actions} />;
|
||||
}
|
||||
|
||||
const headerItem: VizTooltipItem = {
|
||||
|
@ -130,6 +130,7 @@ export const StatusHistoryPanel = ({
|
||||
annotate={enableAnnotationCreation ? annotate : undefined}
|
||||
withDuration={false}
|
||||
maxHeight={options.tooltip.maxHeight}
|
||||
replaceVariables={replaceVariables}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
|
@ -1,4 +1,7 @@
|
||||
import { Field, LinkModel } from '@grafana/data';
|
||||
import { ActionModel, Field, InterpolateFunction, LinkModel } from '@grafana/data';
|
||||
import { DataFrame } from '@grafana/data/';
|
||||
import { config } from '@grafana/runtime';
|
||||
import { getActions } from 'app/features/actions/utils';
|
||||
|
||||
export const getDataLinks = (field: Field, rowIdx: number) => {
|
||||
const links: Array<LinkModel<Field>> = [];
|
||||
@ -20,3 +23,31 @@ export const getDataLinks = (field: Field, rowIdx: number) => {
|
||||
|
||||
return links;
|
||||
};
|
||||
|
||||
export const getFieldActions = (dataFrame: DataFrame, field: Field, replaceVars: InterpolateFunction) => {
|
||||
if (!config.featureToggles?.vizActions) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const actions: Array<ActionModel<Field>> = [];
|
||||
const actionLookup = new Set<string>();
|
||||
|
||||
const actionsModel = getActions(
|
||||
dataFrame,
|
||||
field,
|
||||
field.state!.scopedVars!,
|
||||
replaceVars,
|
||||
field.config.actions ?? [],
|
||||
{}
|
||||
);
|
||||
|
||||
actionsModel.forEach((action) => {
|
||||
const key = `${action.title}`;
|
||||
if (!actionLookup.has(key)) {
|
||||
actions.push(action);
|
||||
actionLookup.add(key);
|
||||
}
|
||||
});
|
||||
|
||||
return actions;
|
||||
};
|
||||
|
@ -131,6 +131,7 @@ export const TimeSeriesPanel = ({
|
||||
isPinned={isPinned}
|
||||
annotate={enableAnnotationCreation ? annotate : undefined}
|
||||
maxHeight={options.tooltip.maxHeight}
|
||||
replaceVariables={replaceVariables}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
|
@ -1,16 +1,15 @@
|
||||
import { css } from '@emotion/css';
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
import { DataFrame, Field, FieldType, formattedValueToString } from '@grafana/data';
|
||||
import { DataFrame, Field, FieldType, formattedValueToString, InterpolateFunction } from '@grafana/data';
|
||||
import { SortOrder, TooltipDisplayMode } from '@grafana/schema/dist/esm/common/common.gen';
|
||||
import { VizTooltipContent } from '@grafana/ui/src/components/VizTooltip/VizTooltipContent';
|
||||
import { VizTooltipFooter } from '@grafana/ui/src/components/VizTooltip/VizTooltipFooter';
|
||||
import { VizTooltipHeader } from '@grafana/ui/src/components/VizTooltip/VizTooltipHeader';
|
||||
import { VizTooltipWrapper } from '@grafana/ui/src/components/VizTooltip/VizTooltipWrapper';
|
||||
import { VizTooltipItem } from '@grafana/ui/src/components/VizTooltip/types';
|
||||
import { getContentItems } from '@grafana/ui/src/components/VizTooltip/utils';
|
||||
|
||||
import { VizTooltipWrapper } from '../../../../../packages/grafana-ui/src/components/VizTooltip/VizTooltipWrapper';
|
||||
import { getDataLinks } from '../status-history/utils';
|
||||
import { getDataLinks, getFieldActions } from '../status-history/utils';
|
||||
import { fmt } from '../xychart/utils';
|
||||
|
||||
import { isTooltipScrollable } from './utils';
|
||||
@ -36,6 +35,8 @@ export interface TimeSeriesTooltipProps {
|
||||
|
||||
annotate?: () => void;
|
||||
maxHeight?: number;
|
||||
|
||||
replaceVariables?: InterpolateFunction;
|
||||
}
|
||||
|
||||
export const TimeSeriesTooltip = ({
|
||||
@ -48,6 +49,7 @@ export const TimeSeriesTooltip = ({
|
||||
isPinned,
|
||||
annotate,
|
||||
maxHeight,
|
||||
replaceVariables,
|
||||
}: TimeSeriesTooltipProps) => {
|
||||
const xField = series.fields[0];
|
||||
const xVal = formattedValueToString(xField.display!(xField.values[dataIdxs[0]!]));
|
||||
@ -77,8 +79,9 @@ export const TimeSeriesTooltip = ({
|
||||
const field = series.fields[seriesIdx];
|
||||
const dataIdx = dataIdxs[seriesIdx]!;
|
||||
const links = getDataLinks(field, dataIdx);
|
||||
const actions = getFieldActions(series, field, replaceVariables!);
|
||||
|
||||
footer = <VizTooltipFooter dataLinks={links} annotate={annotate} />;
|
||||
footer = <VizTooltipFooter dataLinks={links} actions={actions} annotate={annotate} />;
|
||||
}
|
||||
|
||||
const headerItem: VizTooltipItem | null = xField.config.custom?.hideFrom?.tooltip
|
||||
@ -101,10 +104,3 @@ export const TimeSeriesTooltip = ({
|
||||
</VizTooltipWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export const getStyles = () => ({
|
||||
wrapper: css({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
}),
|
||||
});
|
||||
|
@ -130,6 +130,7 @@ export const TrendPanel = ({
|
||||
sortOrder={options.tooltip.sort}
|
||||
isPinned={isPinned}
|
||||
maxHeight={options.tooltip.maxHeight}
|
||||
replaceVariables={replaceVariables}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
|
@ -5,9 +5,9 @@ import { alpha } from '@grafana/data/src/themes/colorManipulator';
|
||||
import { VizTooltipContent } from '@grafana/ui/src/components/VizTooltip/VizTooltipContent';
|
||||
import { VizTooltipFooter } from '@grafana/ui/src/components/VizTooltip/VizTooltipFooter';
|
||||
import { VizTooltipHeader } from '@grafana/ui/src/components/VizTooltip/VizTooltipHeader';
|
||||
import { VizTooltipWrapper } from '@grafana/ui/src/components/VizTooltip/VizTooltipWrapper';
|
||||
import { ColorIndicator, VizTooltipItem } from '@grafana/ui/src/components/VizTooltip/types';
|
||||
|
||||
import { VizTooltipWrapper } from '../../../../../packages/grafana-ui/src/components/VizTooltip/VizTooltipWrapper';
|
||||
import { getDataLinks } from '../status-history/utils';
|
||||
|
||||
import { Options } from './panelcfg.gen';
|
||||
|
@ -122,6 +122,7 @@ export const XYChartPanel2 = (props: Props2) => {
|
||||
dismiss={dismiss}
|
||||
isPinned={isPinned}
|
||||
seriesIdx={seriesIdx!}
|
||||
replaceVariables={props.replaceVariables}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
|
@ -1,14 +1,14 @@
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
import { DataFrame } from '@grafana/data';
|
||||
import { DataFrame, InterpolateFunction } from '@grafana/data';
|
||||
import { alpha } from '@grafana/data/src/themes/colorManipulator';
|
||||
import { VizTooltipContent } from '@grafana/ui/src/components/VizTooltip/VizTooltipContent';
|
||||
import { VizTooltipFooter } from '@grafana/ui/src/components/VizTooltip/VizTooltipFooter';
|
||||
import { VizTooltipHeader } from '@grafana/ui/src/components/VizTooltip/VizTooltipHeader';
|
||||
import { VizTooltipWrapper } from '@grafana/ui/src/components/VizTooltip/VizTooltipWrapper';
|
||||
import { ColorIndicator, VizTooltipItem } from '@grafana/ui/src/components/VizTooltip/types';
|
||||
|
||||
import { VizTooltipWrapper } from '../../../../../../packages/grafana-ui/src/components/VizTooltip/VizTooltipWrapper';
|
||||
import { getDataLinks } from '../../status-history/utils';
|
||||
import { getDataLinks, getFieldActions } from '../../status-history/utils';
|
||||
|
||||
import { XYSeries } from './types2';
|
||||
import { fmt } from './utils';
|
||||
@ -20,6 +20,7 @@ export interface Props {
|
||||
dismiss: () => void;
|
||||
data: DataFrame[];
|
||||
xySeries: XYSeries[];
|
||||
replaceVariables: InterpolateFunction;
|
||||
}
|
||||
|
||||
function stripSeriesName(fieldName: string, seriesName: string) {
|
||||
@ -30,7 +31,7 @@ function stripSeriesName(fieldName: string, seriesName: string) {
|
||||
return fieldName;
|
||||
}
|
||||
|
||||
export const XYChartTooltip = ({ dataIdxs, seriesIdx, data, xySeries, dismiss, isPinned }: Props) => {
|
||||
export const XYChartTooltip = ({ dataIdxs, seriesIdx, data, xySeries, dismiss, isPinned, replaceVariables }: Props) => {
|
||||
const rowIndex = dataIdxs.find((idx) => idx !== null)!;
|
||||
|
||||
const series = xySeries[seriesIdx! - 1];
|
||||
@ -94,8 +95,10 @@ export const XYChartTooltip = ({ dataIdxs, seriesIdx, data, xySeries, dismiss, i
|
||||
|
||||
if (isPinned && seriesIdx != null) {
|
||||
const links = getDataLinks(yField, rowIndex);
|
||||
const yFieldFrame = data.find((frame) => frame.fields.includes(yField))!;
|
||||
const actions = getFieldActions(yFieldFrame, yField, replaceVariables);
|
||||
|
||||
footer = <VizTooltipFooter dataLinks={links} />;
|
||||
footer = <VizTooltipFooter dataLinks={links} actions={actions} />;
|
||||
}
|
||||
|
||||
return (
|
||||
|
Loading…
Reference in New Issue
Block a user