diff --git a/packages/grafana-data/src/field/fieldOverrides.ts b/packages/grafana-data/src/field/fieldOverrides.ts
index 96d7d403644..c3a64d496ae 100644
--- a/packages/grafana-data/src/field/fieldOverrides.ts
+++ b/packages/grafana-data/src/field/fieldOverrides.ts
@@ -1,5 +1,5 @@
import { isNumber, set, unset, get, cloneDeep } from 'lodash';
-import { useMemo, useRef } from 'react';
+import { createContext, useContext, useMemo, useRef } from 'react';
import { usePrevious } from 'react-use';
import { ThresholdsMode, VariableFormatID } from '@grafana/schema';
@@ -583,13 +583,14 @@ export function useFieldOverrides(
data: PanelData | undefined,
timeZone: string,
theme: GrafanaTheme2,
- replace: InterpolateFunction,
- dataLinkPostProcessor?: DataLinkPostProcessor
+ replace: InterpolateFunction
): PanelData | undefined {
const fieldConfigRegistry = plugin?.fieldConfigRegistry;
const structureRev = useRef(0);
const prevSeries = usePrevious(data?.series);
+ const { dataLinkPostProcessor } = useDataLinksContext();
+
return useMemo(() => {
if (!fieldConfigRegistry || !fieldConfig || !data) {
return;
@@ -650,3 +651,15 @@ export function getFieldDataContextClone(frame: DataFrame, field: Field, fieldSc
return { value: { frame, field, data: [frame] } };
}
+
+/**
+ * @internal
+ */
+export const DataLinksContext = createContext<{
+ dataLinkPostProcessor: DataLinkPostProcessor;
+}>({ dataLinkPostProcessor: defaultInternalLinkPostProcessor });
+
+/**
+ * @internal
+ */
+export const useDataLinksContext = () => useContext(DataLinksContext);
diff --git a/packages/grafana-data/src/index.ts b/packages/grafana-data/src/index.ts
index 6dcc5a186e6..269dba30b62 100644
--- a/packages/grafana-data/src/index.ts
+++ b/packages/grafana-data/src/index.ts
@@ -150,6 +150,8 @@ export {
applyRawFieldOverrides,
useFieldOverrides,
getFieldDataContextClone,
+ DataLinksContext,
+ useDataLinksContext,
} from './field/fieldOverrides';
export { getFieldDisplayValuesProxy } from './field/getFieldDisplayValuesProxy';
export {
diff --git a/packages/grafana-ui/src/components/PanelChrome/PanelContext.ts b/packages/grafana-ui/src/components/PanelChrome/PanelContext.ts
index 97ddb007235..a9d5334925a 100644
--- a/packages/grafana-ui/src/components/PanelChrome/PanelContext.ts
+++ b/packages/grafana-ui/src/components/PanelChrome/PanelContext.ts
@@ -96,6 +96,7 @@ export interface PanelContext {
/**
* Optional supplier for internal data links. If not provided a link pointing to Explore will be generated.
* @internal
+ * @deprecated Please use DataLinksContext instead. This property will be removed in next major.
*/
dataLinkPostProcessor?: DataLinkPostProcessor;
}
diff --git a/public/app/features/explore/CustomContainer.tsx b/public/app/features/explore/CustomContainer.tsx
index 26cf7dd14f4..ab5bc4117d4 100644
--- a/public/app/features/explore/CustomContainer.tsx
+++ b/public/app/features/explore/CustomContainer.tsx
@@ -1,6 +1,6 @@
-import { DataFrame, EventBus, LoadingState, SplitOpen, TimeRange } from '@grafana/data';
+import { DataFrame, DataLinksContext, EventBus, LoadingState, SplitOpen, TimeRange } from '@grafana/data';
import { PanelRenderer } from '@grafana/runtime';
-import { PanelChrome, PanelContext, PanelContextProvider } from '@grafana/ui';
+import { PanelChrome } from '@grafana/ui';
import { getPanelPluginMeta } from '../plugins/importPanelPlugin';
@@ -18,29 +18,13 @@ export interface Props {
eventBus: EventBus;
}
-export function CustomContainer({
- width,
- height,
- timeZone,
- state,
- pluginId,
- frames,
- timeRange,
- splitOpenFn,
- eventBus,
-}: Props) {
+export function CustomContainer({ width, height, timeZone, state, pluginId, frames, timeRange, splitOpenFn }: Props) {
const plugin = getPanelPluginMeta(pluginId);
const dataLinkPostProcessor = useExploreDataLinkPostProcessor(splitOpenFn, timeRange);
- const panelContext: PanelContext = {
- dataLinkPostProcessor,
- eventBus,
- eventsScope: 'explore',
- };
-
return (
-
+
{(innerWidth, innerHeight) => (
)}
-
+
);
}
diff --git a/public/app/features/explore/Graph/ExploreGraph.tsx b/public/app/features/explore/Graph/ExploreGraph.tsx
index e4dedb3f76c..6c5ccbba57c 100644
--- a/public/app/features/explore/Graph/ExploreGraph.tsx
+++ b/public/app/features/explore/Graph/ExploreGraph.tsx
@@ -8,6 +8,7 @@ import {
createFieldConfigRegistry,
DashboardCursorSync,
DataFrame,
+ DataLinksContext,
EventBus,
FieldColorModeId,
FieldConfigSource,
@@ -121,9 +122,8 @@ export function ExploreGraph({
replaceVariables: (value) => value, // We don't need proper replace here as it is only used in getLinks and we use getFieldLinks
theme,
fieldConfigRegistry,
- dataLinkPostProcessor,
});
- }, [fieldConfigRegistry, data, timeZone, theme, styledFieldConfig, dataLinkPostProcessor]);
+ }, [fieldConfigRegistry, data, timeZone, theme, styledFieldConfig]);
const annotationsWithConfig = useMemo(() => {
return applyFieldOverrides({
@@ -171,7 +171,6 @@ export function ExploreGraph({
onToggleSeriesVisibility(label: string, mode: SeriesVisibilityChangeMode) {
setFieldConfig(seriesVisibilityConfigFactory(label, mode, fieldConfig, data));
},
- dataLinkPostProcessor,
};
function toggleLegend(name: string | undefined, mode: SeriesVisibilityChangeMode) {
@@ -204,23 +203,25 @@ export function ExploreGraph({
);
return (
-
-
-
+
+
+
+
+
);
}
diff --git a/public/app/features/panel/components/PanelRenderer.tsx b/public/app/features/panel/components/PanelRenderer.tsx
index 74b9b295be2..fb99e39041a 100644
--- a/public/app/features/panel/components/PanelRenderer.tsx
+++ b/public/app/features/panel/components/PanelRenderer.tsx
@@ -11,7 +11,7 @@ import {
} from '@grafana/data';
import { Trans } from '@grafana/i18n';
import { getTemplateSrv, PanelRendererProps } from '@grafana/runtime';
-import { ErrorBoundaryAlert, usePanelContext, useTheme2 } from '@grafana/ui';
+import { ErrorBoundaryAlert, useTheme2 } from '@grafana/ui';
import { appEvents } from 'app/core/core';
import { importPanelPlugin, syncGetPanelPlugin } from '../../plugins/importPanelPlugin';
@@ -39,16 +39,7 @@ export function PanelRenderer
(prop
const [plugin, setPlugin] = useState(syncGetPanelPlugin(pluginId));
const [error, setError] = useState();
const optionsWithDefaults = useOptionDefaults(plugin, options, fieldConfig);
- const { dataLinkPostProcessor } = usePanelContext();
- const dataWithOverrides = useFieldOverrides(
- plugin,
- optionsWithDefaults?.fieldConfig,
- data,
- timeZone,
- theme,
- replace,
- dataLinkPostProcessor
- );
+ const dataWithOverrides = useFieldOverrides(plugin, optionsWithDefaults?.fieldConfig, data, timeZone, theme, replace);
useEffect(() => {
// If we already have a plugin and it's correct one do nothing
diff --git a/public/app/plugins/panel/candlestick/CandlestickPanel.tsx b/public/app/plugins/panel/candlestick/CandlestickPanel.tsx
index 3f261b56876..cb17a7792fd 100644
--- a/public/app/plugins/panel/candlestick/CandlestickPanel.tsx
+++ b/public/app/plugins/panel/candlestick/CandlestickPanel.tsx
@@ -4,7 +4,7 @@
import { useMemo, useState } from 'react';
import uPlot from 'uplot';
-import { Field, getDisplayProcessor, PanelProps } from '@grafana/data';
+import { Field, getDisplayProcessor, PanelProps, useDataLinksContext } from '@grafana/data';
import { PanelDataErrorView } from '@grafana/runtime';
import { DashboardCursorSync, TooltipDisplayMode } from '@grafana/schema';
import {
@@ -50,11 +50,12 @@ export const CandlestickPanel = ({
onThresholdsChange,
canEditThresholds,
showThresholds,
- dataLinkPostProcessor,
eventBus,
canExecuteActions,
} = usePanelContext();
+ const { dataLinkPostProcessor } = useDataLinksContext();
+
const userCanExecuteActions = useMemo(() => canExecuteActions?.() ?? false, [canExecuteActions]);
const theme = useTheme2();
diff --git a/public/app/plugins/panel/state-timeline/StateTimelinePanel.tsx b/public/app/plugins/panel/state-timeline/StateTimelinePanel.tsx
index d1369a79508..30ed5965a63 100644
--- a/public/app/plugins/panel/state-timeline/StateTimelinePanel.tsx
+++ b/public/app/plugins/panel/state-timeline/StateTimelinePanel.tsx
@@ -1,6 +1,6 @@
import { useMemo, useState } from 'react';
-import { DashboardCursorSync, PanelProps } from '@grafana/data';
+import { DashboardCursorSync, PanelProps, useDataLinksContext } from '@grafana/data';
import { PanelDataErrorView } from '@grafana/runtime';
import {
AxisPlacement,
@@ -47,8 +47,9 @@ export const StateTimelinePanel = ({
// temp range set for adding new annotation set by TooltipPlugin2, consumed by AnnotationPlugin2
const [newAnnotationRange, setNewAnnotationRange] = useState(null);
- const { sync, eventsScope, canAddAnnotations, dataLinkPostProcessor, eventBus, canExecuteActions } =
- usePanelContext();
+ const { sync, eventsScope, canAddAnnotations, eventBus, canExecuteActions } = usePanelContext();
+
+ const { dataLinkPostProcessor } = useDataLinksContext();
const userCanExecuteActions = useMemo(() => canExecuteActions?.() ?? false, [canExecuteActions]);
const cursorSync = sync?.() ?? DashboardCursorSync.Off;
diff --git a/public/app/plugins/panel/status-history/StatusHistoryPanel.tsx b/public/app/plugins/panel/status-history/StatusHistoryPanel.tsx
index be38b2a81f1..bfa2dbdcf99 100644
--- a/public/app/plugins/panel/status-history/StatusHistoryPanel.tsx
+++ b/public/app/plugins/panel/status-history/StatusHistoryPanel.tsx
@@ -1,6 +1,6 @@
import { useMemo, useState } from 'react';
-import { DashboardCursorSync, PanelProps } from '@grafana/data';
+import { DashboardCursorSync, PanelProps, useDataLinksContext } from '@grafana/data';
import { Trans } from '@grafana/i18n';
import { PanelDataErrorView } from '@grafana/runtime';
import {
@@ -48,7 +48,8 @@ export const StatusHistoryPanel = ({
// temp range set for adding new annotation set by TooltipPlugin2, consumed by AnnotationPlugin2
const [newAnnotationRange, setNewAnnotationRange] = useState(null);
- const { sync, eventsScope, canAddAnnotations, dataLinkPostProcessor, eventBus } = usePanelContext();
+ const { sync, eventsScope, canAddAnnotations, eventBus } = usePanelContext();
+ const { dataLinkPostProcessor } = useDataLinksContext();
const cursorSync = sync?.() ?? DashboardCursorSync.Off;
const enableAnnotationCreation = Boolean(canAddAnnotations && canAddAnnotations());
diff --git a/public/app/plugins/panel/timeseries/TimeSeriesPanel.tsx b/public/app/plugins/panel/timeseries/TimeSeriesPanel.tsx
index 92ba4d3f97b..bc198392c05 100644
--- a/public/app/plugins/panel/timeseries/TimeSeriesPanel.tsx
+++ b/public/app/plugins/panel/timeseries/TimeSeriesPanel.tsx
@@ -7,6 +7,7 @@ import {
DataFrame,
alignTimeRangeCompareData,
shouldAlignTimeCompare,
+ useDataLinksContext,
FieldType,
} from '@grafana/data';
import { PanelDataErrorView } from '@grafana/runtime';
@@ -46,11 +47,12 @@ export const TimeSeriesPanel = ({
onThresholdsChange,
canEditThresholds,
showThresholds,
- dataLinkPostProcessor,
eventBus,
canExecuteActions,
} = usePanelContext();
+ const { dataLinkPostProcessor } = useDataLinksContext();
+
const userCanExecuteActions = useMemo(() => canExecuteActions?.() ?? false, [canExecuteActions]);
// Vertical orientation is not available for users through config.
// It is simplified version of horizontal time series panel and it does not support all plugins.
diff --git a/public/app/plugins/panel/trend/TrendPanel.tsx b/public/app/plugins/panel/trend/TrendPanel.tsx
index d5a7cff51d3..ecfaff896e0 100644
--- a/public/app/plugins/panel/trend/TrendPanel.tsx
+++ b/public/app/plugins/panel/trend/TrendPanel.tsx
@@ -8,9 +8,10 @@ import {
FieldType,
PanelProps,
TimeRange,
+ useDataLinksContext,
} from '@grafana/data';
import { config, PanelDataErrorView } from '@grafana/runtime';
-import { KeyboardPlugin, TooltipDisplayMode, usePanelContext, TooltipPlugin2 } from '@grafana/ui';
+import { KeyboardPlugin, TooltipDisplayMode, TooltipPlugin2 } from '@grafana/ui';
import { TooltipHoverMode } from '@grafana/ui/internal';
import { XYFieldMatchers } from 'app/core/components/GraphNG/types';
import { preparePlotFrame } from 'app/core/components/GraphNG/utils';
@@ -33,7 +34,7 @@ export const TrendPanel = ({
replaceVariables,
id,
}: PanelProps) => {
- const { dataLinkPostProcessor } = usePanelContext();
+ const { dataLinkPostProcessor } = useDataLinksContext();
// Need to fallback to first number field if no xField is set in options otherwise panel crashes 😬
const trendXFieldName =
options.xField ?? data.series[0]?.fields.find((field) => field.type === FieldType.number)?.name;