mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Explore: Refactor graph component to use PanelRenderer (#38914)
* Move SplitOpenFn type to grafana-data * Use panel renderer instead of Timeseries panel for graph in Explore * rename splitopen props on panel context
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import { RawTimeRange } from './time';
|
import { DataQuery } from './query';
|
||||||
|
import { RawTimeRange, TimeRange } from './time';
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
export interface ExploreUrlState {
|
export interface ExploreUrlState {
|
||||||
@@ -8,3 +9,10 @@ export interface ExploreUrlState {
|
|||||||
originPanelId?: number;
|
originPanelId?: number;
|
||||||
context?: string;
|
context?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SplitOpen type is used in Explore and related components.
|
||||||
|
*/
|
||||||
|
export type SplitOpen = <T extends DataQuery = any>(
|
||||||
|
options?: { datasourceUid: string; query: T; range?: TimeRange } | undefined
|
||||||
|
) => void;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { EventBusSrv, EventBus, DashboardCursorSync, AnnotationEventUIModel } from '@grafana/data';
|
import { AnnotationEventUIModel, DashboardCursorSync, EventBus, EventBusSrv, SplitOpen } from '@grafana/data';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { SeriesVisibilityChangeMode } from '.';
|
import { SeriesVisibilityChangeMode } from '.';
|
||||||
|
|
||||||
@@ -22,6 +22,11 @@ export interface PanelContext {
|
|||||||
onAnnotationCreate?: (annotation: AnnotationEventUIModel) => void;
|
onAnnotationCreate?: (annotation: AnnotationEventUIModel) => void;
|
||||||
onAnnotationUpdate?: (annotation: AnnotationEventUIModel) => void;
|
onAnnotationUpdate?: (annotation: AnnotationEventUIModel) => void;
|
||||||
onAnnotationDelete?: (id: string) => void;
|
onAnnotationDelete?: (id: string) => void;
|
||||||
|
/**
|
||||||
|
* onSplitOpen is used in Explore to open the split view. It can be used in panels which has intercations and used in Explore as well.
|
||||||
|
* For example TimeSeries panel.
|
||||||
|
*/
|
||||||
|
onSplitOpen?: SplitOpen;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const PanelContextRoot = React.createContext<PanelContext>({
|
export const PanelContextRoot = React.createContext<PanelContext>({
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import { connect, ConnectedProps } from 'react-redux';
|
|||||||
import AutoSizer from 'react-virtualized-auto-sizer';
|
import AutoSizer from 'react-virtualized-auto-sizer';
|
||||||
import memoizeOne from 'memoize-one';
|
import memoizeOne from 'memoize-one';
|
||||||
import { selectors } from '@grafana/e2e-selectors';
|
import { selectors } from '@grafana/e2e-selectors';
|
||||||
import { TooltipDisplayMode } from '@grafana/schema';
|
|
||||||
import { ErrorBoundaryAlert, CustomScrollbar, Collapse, withTheme2, Themeable2 } from '@grafana/ui';
|
import { ErrorBoundaryAlert, CustomScrollbar, Collapse, withTheme2, Themeable2 } from '@grafana/ui';
|
||||||
import { AbsoluteTimeRange, DataQuery, LoadingState, RawTimeRange, DataFrame, GrafanaTheme2 } from '@grafana/data';
|
import { AbsoluteTimeRange, DataQuery, LoadingState, RawTimeRange, DataFrame, GrafanaTheme2 } from '@grafana/data';
|
||||||
|
|
||||||
@@ -25,10 +24,10 @@ import { NoDataSourceCallToAction } from './NoDataSourceCallToAction';
|
|||||||
import { getTimeZone } from '../profile/state/selectors';
|
import { getTimeZone } from '../profile/state/selectors';
|
||||||
import { SecondaryActions } from './SecondaryActions';
|
import { SecondaryActions } from './SecondaryActions';
|
||||||
import { FILTER_FOR_OPERATOR, FILTER_OUT_OPERATOR, FilterItem } from '@grafana/ui/src/components/Table/types';
|
import { FILTER_FOR_OPERATOR, FILTER_OUT_OPERATOR, FilterItem } from '@grafana/ui/src/components/Table/types';
|
||||||
import { ExploreGraphNGPanel } from './ExploreGraphNGPanel';
|
|
||||||
import { NodeGraphContainer } from './NodeGraphContainer';
|
import { NodeGraphContainer } from './NodeGraphContainer';
|
||||||
import { ResponseErrorContainer } from './ResponseErrorContainer';
|
import { ResponseErrorContainer } from './ResponseErrorContainer';
|
||||||
import { TraceViewContainer } from './TraceView/TraceViewContainer';
|
import { TraceViewContainer } from './TraceView/TraceViewContainer';
|
||||||
|
import { ExploreGraph } from './ExploreGraph';
|
||||||
|
|
||||||
const getStyles = (theme: GrafanaTheme2) => {
|
const getStyles = (theme: GrafanaTheme2) => {
|
||||||
return {
|
return {
|
||||||
@@ -191,16 +190,15 @@ export class Explore extends React.PureComponent<Props, ExploreState> {
|
|||||||
const spacing = parseInt(theme.spacing(2).slice(0, -2), 10);
|
const spacing = parseInt(theme.spacing(2).slice(0, -2), 10);
|
||||||
return (
|
return (
|
||||||
<Collapse label="Graph" loading={loading} isOpen>
|
<Collapse label="Graph" loading={loading} isOpen>
|
||||||
<ExploreGraphNGPanel
|
<ExploreGraph
|
||||||
data={graphResult!}
|
data={graphResult!}
|
||||||
height={400}
|
height={400}
|
||||||
width={width - spacing}
|
width={width - spacing}
|
||||||
tooltipDisplayMode={TooltipDisplayMode.Single}
|
|
||||||
absoluteRange={absoluteRange}
|
absoluteRange={absoluteRange}
|
||||||
timeZone={timeZone}
|
timeZone={timeZone}
|
||||||
onUpdateTimeRange={this.onUpdateTimeRange}
|
|
||||||
annotations={queryResponse.annotations}
|
annotations={queryResponse.annotations}
|
||||||
splitOpenFn={splitOpen}
|
splitOpenFn={splitOpen}
|
||||||
|
loadingState={queryResponse.state}
|
||||||
/>
|
/>
|
||||||
</Collapse>
|
</Collapse>
|
||||||
);
|
);
|
||||||
@@ -219,11 +217,12 @@ export class Explore extends React.PureComponent<Props, ExploreState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderLogsPanel(width: number) {
|
renderLogsPanel(width: number) {
|
||||||
const { exploreId, syncedTimes, theme } = this.props;
|
const { exploreId, syncedTimes, theme, queryResponse } = this.props;
|
||||||
const spacing = parseInt(theme.spacing(2).slice(0, -2), 10);
|
const spacing = parseInt(theme.spacing(2).slice(0, -2), 10);
|
||||||
return (
|
return (
|
||||||
<LogsContainer
|
<LogsContainer
|
||||||
exploreId={exploreId}
|
exploreId={exploreId}
|
||||||
|
loadingState={queryResponse.state}
|
||||||
syncedTimes={syncedTimes}
|
syncedTimes={syncedTimes}
|
||||||
width={width - spacing}
|
width={width - spacing}
|
||||||
onClickFilterLabel={this.onClickFilterLabel}
|
onClickFilterLabel={this.onClickFilterLabel}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { css, cx } from '@emotion/css';
|
||||||
import {
|
import {
|
||||||
AbsoluteTimeRange,
|
AbsoluteTimeRange,
|
||||||
applyFieldOverrides,
|
applyFieldOverrides,
|
||||||
@@ -6,36 +7,31 @@ import {
|
|||||||
createFieldConfigRegistry,
|
createFieldConfigRegistry,
|
||||||
DataFrame,
|
DataFrame,
|
||||||
dateTime,
|
dateTime,
|
||||||
Field,
|
|
||||||
FieldColorModeId,
|
FieldColorModeId,
|
||||||
FieldConfigSource,
|
FieldConfigSource,
|
||||||
getFrameDisplayName,
|
getFrameDisplayName,
|
||||||
GrafanaTheme2,
|
GrafanaTheme2,
|
||||||
|
LoadingState,
|
||||||
|
SplitOpen,
|
||||||
TimeZone,
|
TimeZone,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
|
import { PanelRenderer } from '@grafana/runtime';
|
||||||
|
import { GraphDrawStyle, LegendDisplayMode, TooltipDisplayMode } from '@grafana/schema';
|
||||||
import {
|
import {
|
||||||
Icon,
|
Icon,
|
||||||
PanelContext,
|
PanelContext,
|
||||||
PanelContextProvider,
|
PanelContextProvider,
|
||||||
SeriesVisibilityChangeMode,
|
SeriesVisibilityChangeMode,
|
||||||
TimeSeries,
|
|
||||||
TooltipPlugin,
|
|
||||||
useStyles2,
|
useStyles2,
|
||||||
useTheme2,
|
useTheme2,
|
||||||
ZoomPlugin,
|
|
||||||
} from '@grafana/ui';
|
} from '@grafana/ui';
|
||||||
import { LegendDisplayMode, TooltipDisplayMode, GraphDrawStyle } from '@grafana/schema';
|
|
||||||
import { defaultGraphConfig, getGraphFieldConfig } from 'app/plugins/panel/timeseries/config';
|
|
||||||
import { ContextMenuPlugin } from 'app/plugins/panel/timeseries/plugins/ContextMenuPlugin';
|
|
||||||
import { ExemplarsPlugin } from 'app/plugins/panel/timeseries/plugins/ExemplarsPlugin';
|
|
||||||
import { css, cx } from '@emotion/css';
|
|
||||||
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
|
||||||
import { getFieldLinksForExplore } from './utils/links';
|
|
||||||
import { usePrevious } from 'react-use';
|
|
||||||
import appEvents from 'app/core/app_events';
|
import appEvents from 'app/core/app_events';
|
||||||
import { seriesVisibilityConfigFactory } from '../dashboard/dashgrid/SeriesVisibilityConfigFactory';
|
import { defaultGraphConfig, getGraphFieldConfig } from 'app/plugins/panel/timeseries/config';
|
||||||
|
import { TimeSeriesOptions } from 'app/plugins/panel/timeseries/types';
|
||||||
import { identity } from 'lodash';
|
import { identity } from 'lodash';
|
||||||
import { SplitOpen } from 'app/types/explore';
|
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||||
|
import { usePrevious } from 'react-use';
|
||||||
|
import { seriesVisibilityConfigFactory } from '../dashboard/dashgrid/SeriesVisibilityConfigFactory';
|
||||||
|
|
||||||
const MAX_NUMBER_OF_TIME_SERIES = 20;
|
const MAX_NUMBER_OF_TIME_SERIES = 20;
|
||||||
|
|
||||||
@@ -43,26 +39,26 @@ interface Props {
|
|||||||
data: DataFrame[];
|
data: DataFrame[];
|
||||||
height: number;
|
height: number;
|
||||||
width: number;
|
width: number;
|
||||||
annotations?: DataFrame[];
|
|
||||||
absoluteRange: AbsoluteTimeRange;
|
absoluteRange: AbsoluteTimeRange;
|
||||||
timeZone: TimeZone;
|
timeZone: TimeZone;
|
||||||
onUpdateTimeRange: (absoluteRange: AbsoluteTimeRange) => void;
|
loadingState: LoadingState;
|
||||||
|
annotations?: DataFrame[];
|
||||||
onHiddenSeriesChanged?: (hiddenSeries: string[]) => void;
|
onHiddenSeriesChanged?: (hiddenSeries: string[]) => void;
|
||||||
tooltipDisplayMode: TooltipDisplayMode;
|
tooltipDisplayMode?: TooltipDisplayMode;
|
||||||
splitOpenFn?: SplitOpen;
|
splitOpenFn?: SplitOpen;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ExploreGraphNGPanel({
|
export function ExploreGraph({
|
||||||
data,
|
data,
|
||||||
height,
|
height,
|
||||||
width,
|
width,
|
||||||
timeZone,
|
timeZone,
|
||||||
absoluteRange,
|
absoluteRange,
|
||||||
onUpdateTimeRange,
|
loadingState,
|
||||||
annotations,
|
annotations,
|
||||||
tooltipDisplayMode,
|
|
||||||
splitOpenFn,
|
|
||||||
onHiddenSeriesChanged,
|
onHiddenSeriesChanged,
|
||||||
|
splitOpenFn,
|
||||||
|
tooltipDisplayMode = TooltipDisplayMode.Single,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const theme = useTheme2();
|
const theme = useTheme2();
|
||||||
const [showAllTimeSeries, setShowAllTimeSeries] = useState(false);
|
const [showAllTimeSeries, setShowAllTimeSeries] = useState(false);
|
||||||
@@ -128,12 +124,9 @@ export function ExploreGraphNGPanel({
|
|||||||
|
|
||||||
const seriesToShow = showAllTimeSeries ? dataWithConfig : dataWithConfig.slice(0, MAX_NUMBER_OF_TIME_SERIES);
|
const seriesToShow = showAllTimeSeries ? dataWithConfig : dataWithConfig.slice(0, MAX_NUMBER_OF_TIME_SERIES);
|
||||||
|
|
||||||
const getFieldLinks = (field: Field, rowIndex: number) => {
|
|
||||||
return getFieldLinksForExplore({ field, rowIndex, splitOpenFn, range: timeRange });
|
|
||||||
};
|
|
||||||
|
|
||||||
const panelContext: PanelContext = {
|
const panelContext: PanelContext = {
|
||||||
eventBus: appEvents,
|
eventBus: appEvents,
|
||||||
|
onSplitOpen: splitOpenFn,
|
||||||
onToggleSeriesVisibility(label: string, mode: SeriesVisibilityChangeMode) {
|
onToggleSeriesVisibility(label: string, mode: SeriesVisibilityChangeMode) {
|
||||||
setBaseStructureRev((r) => r + 1);
|
setBaseStructureRev((r) => r + 1);
|
||||||
setFieldConfig(seriesVisibilityConfigFactory(label, mode, fieldConfig, data));
|
setFieldConfig(seriesVisibilityConfigFactory(label, mode, fieldConfig, data));
|
||||||
@@ -155,33 +148,19 @@ export function ExploreGraphNGPanel({
|
|||||||
>{`Show all ${dataWithConfig.length}`}</span>
|
>{`Show all ${dataWithConfig.length}`}</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<TimeSeries
|
<PanelRenderer
|
||||||
frames={seriesToShow}
|
data={{ series: seriesToShow, timeRange, structureRev, state: loadingState, annotations }}
|
||||||
structureRev={structureRev}
|
pluginId="timeseries"
|
||||||
|
title=""
|
||||||
width={width}
|
width={width}
|
||||||
height={height}
|
height={height}
|
||||||
timeRange={timeRange}
|
options={
|
||||||
legend={{ displayMode: LegendDisplayMode.List, placement: 'bottom', calcs: [] }}
|
{
|
||||||
timeZone={timeZone}
|
tooltip: { mode: tooltipDisplayMode },
|
||||||
>
|
legend: { displayMode: LegendDisplayMode.List, placement: 'bottom', calcs: [] },
|
||||||
{(config, alignedDataFrame) => {
|
} as TimeSeriesOptions
|
||||||
return (
|
}
|
||||||
<>
|
/>
|
||||||
<ZoomPlugin config={config} onZoom={onUpdateTimeRange} />
|
|
||||||
<TooltipPlugin config={config} data={alignedDataFrame} mode={tooltipDisplayMode} timeZone={timeZone} />
|
|
||||||
<ContextMenuPlugin config={config} data={alignedDataFrame} timeZone={timeZone} />
|
|
||||||
{annotations && (
|
|
||||||
<ExemplarsPlugin
|
|
||||||
config={config}
|
|
||||||
exemplars={annotations}
|
|
||||||
timeZone={timeZone}
|
|
||||||
getFieldLinks={getFieldLinks}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
</TimeSeries>
|
|
||||||
</PanelContextProvider>
|
</PanelContextProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -19,6 +19,7 @@ import {
|
|||||||
DataQuery,
|
DataQuery,
|
||||||
DataFrame,
|
DataFrame,
|
||||||
GrafanaTheme2,
|
GrafanaTheme2,
|
||||||
|
LoadingState,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import {
|
import {
|
||||||
RadioButtonGroup,
|
RadioButtonGroup,
|
||||||
@@ -35,7 +36,7 @@ import { dedupLogRows, filterLogLevels } from 'app/core/logs_model';
|
|||||||
import { LogsMetaRow } from './LogsMetaRow';
|
import { LogsMetaRow } from './LogsMetaRow';
|
||||||
import LogsNavigation from './LogsNavigation';
|
import LogsNavigation from './LogsNavigation';
|
||||||
import { RowContextOptions } from '@grafana/ui/src/components/Logs/LogRowContextProvider';
|
import { RowContextOptions } from '@grafana/ui/src/components/Logs/LogRowContextProvider';
|
||||||
import { ExploreGraphNGPanel } from './ExploreGraphNGPanel';
|
import { ExploreGraph } from './ExploreGraph';
|
||||||
|
|
||||||
const SETTINGS_KEYS = {
|
const SETTINGS_KEYS = {
|
||||||
showLabels: 'grafana.explore.logs.showLabels',
|
showLabels: 'grafana.explore.logs.showLabels',
|
||||||
@@ -54,6 +55,7 @@ interface Props extends Themeable2 {
|
|||||||
theme: GrafanaTheme2;
|
theme: GrafanaTheme2;
|
||||||
highlighterExpressions?: string[];
|
highlighterExpressions?: string[];
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
|
loadingState: LoadingState;
|
||||||
absoluteRange: AbsoluteTimeRange;
|
absoluteRange: AbsoluteTimeRange;
|
||||||
timeZone: TimeZone;
|
timeZone: TimeZone;
|
||||||
scanning?: boolean;
|
scanning?: boolean;
|
||||||
@@ -254,6 +256,7 @@ export class UnthemedLogs extends PureComponent<Props, State> {
|
|||||||
visibleRange,
|
visibleRange,
|
||||||
highlighterExpressions,
|
highlighterExpressions,
|
||||||
loading = false,
|
loading = false,
|
||||||
|
loadingState,
|
||||||
onClickFilterLabel,
|
onClickFilterLabel,
|
||||||
onClickFilterOutLabel,
|
onClickFilterOutLabel,
|
||||||
timeZone,
|
timeZone,
|
||||||
@@ -297,14 +300,14 @@ export class UnthemedLogs extends PureComponent<Props, State> {
|
|||||||
This datasource does not support full-range histograms. The graph is based on the logs seen in the response.
|
This datasource does not support full-range histograms. The graph is based on the logs seen in the response.
|
||||||
</div>
|
</div>
|
||||||
{logsSeries && logsSeries.length ? (
|
{logsSeries && logsSeries.length ? (
|
||||||
<ExploreGraphNGPanel
|
<ExploreGraph
|
||||||
data={logsSeries}
|
data={logsSeries}
|
||||||
height={150}
|
height={150}
|
||||||
width={width}
|
width={width}
|
||||||
tooltipDisplayMode={TooltipDisplayMode.Multi}
|
tooltipDisplayMode={TooltipDisplayMode.Multi}
|
||||||
absoluteRange={visibleRange || absoluteRange}
|
absoluteRange={visibleRange || absoluteRange}
|
||||||
timeZone={timeZone}
|
timeZone={timeZone}
|
||||||
onUpdateTimeRange={onChangeTime}
|
loadingState={loadingState}
|
||||||
onHiddenSeriesChanged={this.onToggleLogLevel}
|
onHiddenSeriesChanged={this.onToggleLogLevel}
|
||||||
/>
|
/>
|
||||||
) : undefined}
|
) : undefined}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React, { PureComponent } from 'react';
|
|||||||
import { connect, ConnectedProps } from 'react-redux';
|
import { connect, ConnectedProps } from 'react-redux';
|
||||||
import { css } from 'emotion';
|
import { css } from 'emotion';
|
||||||
import { Collapse } from '@grafana/ui';
|
import { Collapse } from '@grafana/ui';
|
||||||
import { AbsoluteTimeRange, Field, LogRowModel, RawTimeRange } from '@grafana/data';
|
import { AbsoluteTimeRange, Field, LoadingState, LogRowModel, RawTimeRange } from '@grafana/data';
|
||||||
import { ExploreId, ExploreItemState } from 'app/types/explore';
|
import { ExploreId, ExploreItemState } from 'app/types/explore';
|
||||||
import { StoreState } from 'app/types';
|
import { StoreState } from 'app/types';
|
||||||
import { splitOpen } from './state/main';
|
import { splitOpen } from './state/main';
|
||||||
@@ -20,6 +20,7 @@ interface LogsContainerProps extends PropsFromRedux {
|
|||||||
exploreId: ExploreId;
|
exploreId: ExploreId;
|
||||||
scanRange?: RawTimeRange;
|
scanRange?: RawTimeRange;
|
||||||
syncedTimes: boolean;
|
syncedTimes: boolean;
|
||||||
|
loadingState: LoadingState;
|
||||||
onClickFilterLabel?: (key: string, value: string) => void;
|
onClickFilterLabel?: (key: string, value: string) => void;
|
||||||
onClickFilterOutLabel?: (key: string, value: string) => void;
|
onClickFilterOutLabel?: (key: string, value: string) => void;
|
||||||
onStartScanning: () => void;
|
onStartScanning: () => void;
|
||||||
@@ -60,6 +61,7 @@ export class LogsContainer extends PureComponent<LogsContainerProps> {
|
|||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
loading,
|
loading,
|
||||||
|
loadingState,
|
||||||
logsHighlighterExpressions,
|
logsHighlighterExpressions,
|
||||||
logRows,
|
logRows,
|
||||||
logsMeta,
|
logsMeta,
|
||||||
@@ -123,6 +125,7 @@ export class LogsContainer extends PureComponent<LogsContainerProps> {
|
|||||||
width={width}
|
width={width}
|
||||||
highlighterExpressions={logsHighlighterExpressions}
|
highlighterExpressions={logsHighlighterExpressions}
|
||||||
loading={loading}
|
loading={loading}
|
||||||
|
loadingState={loadingState}
|
||||||
onChangeTime={this.onChangeTime}
|
onChangeTime={this.onChangeTime}
|
||||||
onClickFilterLabel={onClickFilterLabel}
|
onClickFilterLabel={onClickFilterLabel}
|
||||||
onClickFilterOutLabel={onClickFilterOutLabel}
|
onClickFilterOutLabel={onClickFilterOutLabel}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { DataFrame, DataFrameView, TraceSpanRow } from '@grafana/data';
|
import { DataFrame, DataFrameView, SplitOpen, TraceSpanRow } from '@grafana/data';
|
||||||
import { colors, useTheme } from '@grafana/ui';
|
import { colors, useTheme } from '@grafana/ui';
|
||||||
import {
|
import {
|
||||||
ThemeOptions,
|
ThemeOptions,
|
||||||
@@ -17,7 +17,7 @@ import { TraceToLogsData } from 'app/core/components/TraceToLogsSettings';
|
|||||||
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
|
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
|
||||||
import { getTimeZone } from 'app/features/profile/state/selectors';
|
import { getTimeZone } from 'app/features/profile/state/selectors';
|
||||||
import { StoreState } from 'app/types';
|
import { StoreState } from 'app/types';
|
||||||
import { ExploreId, SplitOpen } from 'app/types/explore';
|
import { ExploreId } from 'app/types/explore';
|
||||||
import React, { useCallback, useMemo, useState } from 'react';
|
import React, { useCallback, useMemo, useState } from 'react';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import { createSpanLinkFactory } from './createSpanLink';
|
import { createSpanLinkFactory } from './createSpanLink';
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Collapse } from '@grafana/ui';
|
import { Collapse } from '@grafana/ui';
|
||||||
import { DataFrame } from '@grafana/data';
|
import { DataFrame, SplitOpen } from '@grafana/data';
|
||||||
import { TraceView } from './TraceView';
|
import { TraceView } from './TraceView';
|
||||||
import { ExploreId, SplitOpen } from '../../../types';
|
import { ExploreId } from 'app/types/explore';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
dataFrames: DataFrame[];
|
dataFrames: DataFrame[];
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import { DataLink, dateTime, Field, mapInternalLinkToExplore, rangeUtil, TimeRange } from '@grafana/data';
|
import { DataLink, dateTime, Field, mapInternalLinkToExplore, rangeUtil, SplitOpen, TimeRange } from '@grafana/data';
|
||||||
import { getTemplateSrv } from '@grafana/runtime';
|
import { getTemplateSrv } from '@grafana/runtime';
|
||||||
import { Icon } from '@grafana/ui';
|
import { Icon } from '@grafana/ui';
|
||||||
import { TraceSpan } from '@jaegertracing/jaeger-ui-components';
|
import { TraceSpan } from '@jaegertracing/jaeger-ui-components';
|
||||||
import { TraceToLogsOptions } from 'app/core/components/TraceToLogsSettings';
|
import { TraceToLogsOptions } from 'app/core/components/TraceToLogsSettings';
|
||||||
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
|
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
|
||||||
import { SplitOpen } from 'app/types/explore';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { LokiQuery } from '../../../plugins/datasource/loki/types';
|
import { LokiQuery } from '../../../plugins/datasource/loki/types';
|
||||||
|
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ import {
|
|||||||
ScopedVars,
|
ScopedVars,
|
||||||
DataFrame,
|
DataFrame,
|
||||||
getFieldDisplayValuesProxy,
|
getFieldDisplayValuesProxy,
|
||||||
|
SplitOpen,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import { getTemplateSrv } from '@grafana/runtime';
|
import { getTemplateSrv } from '@grafana/runtime';
|
||||||
import { SplitOpen } from 'app/types/explore';
|
|
||||||
import { getLinkSrv } from '../../panel/panellinks/link_srv';
|
import { getLinkSrv } from '../../panel/panellinks/link_srv';
|
||||||
import { contextSrv } from 'app/core/services/context_srv';
|
import { contextSrv } from 'app/core/services/context_srv';
|
||||||
|
|
||||||
|
|||||||
@@ -23,10 +23,10 @@ export const TimeSeriesPanel: React.FC<TimeSeriesPanelProps> = ({
|
|||||||
onChangeTimeRange,
|
onChangeTimeRange,
|
||||||
replaceVariables,
|
replaceVariables,
|
||||||
}) => {
|
}) => {
|
||||||
const { sync, canAddAnnotations } = usePanelContext();
|
const { sync, canAddAnnotations, onSplitOpen } = usePanelContext();
|
||||||
|
|
||||||
const getFieldLinks = (field: Field, rowIndex: number) => {
|
const getFieldLinks = (field: Field, rowIndex: number) => {
|
||||||
return getFieldLinksForExplore({ field, rowIndex, range: timeRange });
|
return getFieldLinksForExplore({ field, rowIndex, splitOpenFn: onSplitOpen, range: timeRange });
|
||||||
};
|
};
|
||||||
|
|
||||||
const { frames, warn } = useMemo(() => prepareGraphableFields(data?.series, config.theme2), [data]);
|
const { frames, warn } = useMemo(() => prepareGraphableFields(data?.series, config.theme2), [data]);
|
||||||
|
|||||||
@@ -204,7 +204,3 @@ export interface ExplorePanelData extends PanelData {
|
|||||||
tableResult: DataFrame | null;
|
tableResult: DataFrame | null;
|
||||||
logsResult: LogsModel | null;
|
logsResult: LogsModel | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type SplitOpen = <T extends DataQuery = any>(
|
|
||||||
options?: { datasourceUid: string; query: T; range?: TimeRange } | undefined
|
|
||||||
) => void;
|
|
||||||
|
|||||||
Reference in New Issue
Block a user