From 94f1173824e103a7946176474accf24cf4d2eca0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zolt=C3=A1n=20Bedi?= Date: Fri, 10 Sep 2021 18:18:22 +0200 Subject: [PATCH] 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 --- packages/grafana-data/src/types/explore.ts | 10 ++- .../components/PanelChrome/PanelContext.ts | 7 +- public/app/features/explore/Explore.tsx | 11 ++- ...ploreGraphNGPanel.tsx => ExploreGraph.tsx} | 79 +++++++------------ public/app/features/explore/Logs.tsx | 9 ++- public/app/features/explore/LogsContainer.tsx | 5 +- .../features/explore/TraceView/TraceView.tsx | 4 +- .../explore/TraceView/TraceViewContainer.tsx | 4 +- .../explore/TraceView/createSpanLink.tsx | 3 +- public/app/features/explore/utils/links.ts | 2 +- .../panel/timeseries/TimeSeriesPanel.tsx | 4 +- public/app/types/explore.ts | 4 - 12 files changed, 67 insertions(+), 75 deletions(-) rename public/app/features/explore/{ExploreGraphNGPanel.tsx => ExploreGraph.tsx} (74%) diff --git a/packages/grafana-data/src/types/explore.ts b/packages/grafana-data/src/types/explore.ts index 18abab2d122..d6bd1e899d8 100644 --- a/packages/grafana-data/src/types/explore.ts +++ b/packages/grafana-data/src/types/explore.ts @@ -1,4 +1,5 @@ -import { RawTimeRange } from './time'; +import { DataQuery } from './query'; +import { RawTimeRange, TimeRange } from './time'; /** @internal */ export interface ExploreUrlState { @@ -8,3 +9,10 @@ export interface ExploreUrlState { originPanelId?: number; context?: string; } + +/** + * SplitOpen type is used in Explore and related components. + */ +export type SplitOpen = ( + options?: { datasourceUid: string; query: T; range?: TimeRange } | undefined +) => void; diff --git a/packages/grafana-ui/src/components/PanelChrome/PanelContext.ts b/packages/grafana-ui/src/components/PanelChrome/PanelContext.ts index 8c10709b1e4..bfe31ef4ef4 100644 --- a/packages/grafana-ui/src/components/PanelChrome/PanelContext.ts +++ b/packages/grafana-ui/src/components/PanelChrome/PanelContext.ts @@ -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 { SeriesVisibilityChangeMode } from '.'; @@ -22,6 +22,11 @@ export interface PanelContext { onAnnotationCreate?: (annotation: AnnotationEventUIModel) => void; onAnnotationUpdate?: (annotation: AnnotationEventUIModel) => 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({ diff --git a/public/app/features/explore/Explore.tsx b/public/app/features/explore/Explore.tsx index 4f9e209c441..892322a6016 100644 --- a/public/app/features/explore/Explore.tsx +++ b/public/app/features/explore/Explore.tsx @@ -5,7 +5,6 @@ import { connect, ConnectedProps } from 'react-redux'; import AutoSizer from 'react-virtualized-auto-sizer'; import memoizeOne from 'memoize-one'; import { selectors } from '@grafana/e2e-selectors'; -import { TooltipDisplayMode } from '@grafana/schema'; import { ErrorBoundaryAlert, CustomScrollbar, Collapse, withTheme2, Themeable2 } from '@grafana/ui'; 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 { SecondaryActions } from './SecondaryActions'; import { FILTER_FOR_OPERATOR, FILTER_OUT_OPERATOR, FilterItem } from '@grafana/ui/src/components/Table/types'; -import { ExploreGraphNGPanel } from './ExploreGraphNGPanel'; import { NodeGraphContainer } from './NodeGraphContainer'; import { ResponseErrorContainer } from './ResponseErrorContainer'; import { TraceViewContainer } from './TraceView/TraceViewContainer'; +import { ExploreGraph } from './ExploreGraph'; const getStyles = (theme: GrafanaTheme2) => { return { @@ -191,16 +190,15 @@ export class Explore extends React.PureComponent { const spacing = parseInt(theme.spacing(2).slice(0, -2), 10); return ( - ); @@ -219,11 +217,12 @@ export class Explore extends React.PureComponent { } 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); return ( void; + loadingState: LoadingState; + annotations?: DataFrame[]; onHiddenSeriesChanged?: (hiddenSeries: string[]) => void; - tooltipDisplayMode: TooltipDisplayMode; + tooltipDisplayMode?: TooltipDisplayMode; splitOpenFn?: SplitOpen; } -export function ExploreGraphNGPanel({ +export function ExploreGraph({ data, height, width, timeZone, absoluteRange, - onUpdateTimeRange, + loadingState, annotations, - tooltipDisplayMode, - splitOpenFn, onHiddenSeriesChanged, + splitOpenFn, + tooltipDisplayMode = TooltipDisplayMode.Single, }: Props) { const theme = useTheme2(); 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 getFieldLinks = (field: Field, rowIndex: number) => { - return getFieldLinksForExplore({ field, rowIndex, splitOpenFn, range: timeRange }); - }; - const panelContext: PanelContext = { eventBus: appEvents, + onSplitOpen: splitOpenFn, onToggleSeriesVisibility(label: string, mode: SeriesVisibilityChangeMode) { setBaseStructureRev((r) => r + 1); setFieldConfig(seriesVisibilityConfigFactory(label, mode, fieldConfig, data)); @@ -155,33 +148,19 @@ export function ExploreGraphNGPanel({ >{`Show all ${dataWithConfig.length}`} )} - - {(config, alignedDataFrame) => { - return ( - <> - - - - {annotations && ( - - )} - - ); - }} - + options={ + { + tooltip: { mode: tooltipDisplayMode }, + legend: { displayMode: LegendDisplayMode.List, placement: 'bottom', calcs: [] }, + } as TimeSeriesOptions + } + /> ); } diff --git a/public/app/features/explore/Logs.tsx b/public/app/features/explore/Logs.tsx index bef95cd5183..e89239aef88 100644 --- a/public/app/features/explore/Logs.tsx +++ b/public/app/features/explore/Logs.tsx @@ -19,6 +19,7 @@ import { DataQuery, DataFrame, GrafanaTheme2, + LoadingState, } from '@grafana/data'; import { RadioButtonGroup, @@ -35,7 +36,7 @@ import { dedupLogRows, filterLogLevels } from 'app/core/logs_model'; import { LogsMetaRow } from './LogsMetaRow'; import LogsNavigation from './LogsNavigation'; import { RowContextOptions } from '@grafana/ui/src/components/Logs/LogRowContextProvider'; -import { ExploreGraphNGPanel } from './ExploreGraphNGPanel'; +import { ExploreGraph } from './ExploreGraph'; const SETTINGS_KEYS = { showLabels: 'grafana.explore.logs.showLabels', @@ -54,6 +55,7 @@ interface Props extends Themeable2 { theme: GrafanaTheme2; highlighterExpressions?: string[]; loading: boolean; + loadingState: LoadingState; absoluteRange: AbsoluteTimeRange; timeZone: TimeZone; scanning?: boolean; @@ -254,6 +256,7 @@ export class UnthemedLogs extends PureComponent { visibleRange, highlighterExpressions, loading = false, + loadingState, onClickFilterLabel, onClickFilterOutLabel, timeZone, @@ -297,14 +300,14 @@ export class UnthemedLogs extends PureComponent { This datasource does not support full-range histograms. The graph is based on the logs seen in the response. {logsSeries && logsSeries.length ? ( - ) : undefined} diff --git a/public/app/features/explore/LogsContainer.tsx b/public/app/features/explore/LogsContainer.tsx index 434a19d74d2..4c4f0864f71 100644 --- a/public/app/features/explore/LogsContainer.tsx +++ b/public/app/features/explore/LogsContainer.tsx @@ -2,7 +2,7 @@ import React, { PureComponent } from 'react'; import { connect, ConnectedProps } from 'react-redux'; import { css } from 'emotion'; 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 { StoreState } from 'app/types'; import { splitOpen } from './state/main'; @@ -20,6 +20,7 @@ interface LogsContainerProps extends PropsFromRedux { exploreId: ExploreId; scanRange?: RawTimeRange; syncedTimes: boolean; + loadingState: LoadingState; onClickFilterLabel?: (key: string, value: string) => void; onClickFilterOutLabel?: (key: string, value: string) => void; onStartScanning: () => void; @@ -60,6 +61,7 @@ export class LogsContainer extends PureComponent { render() { const { loading, + loadingState, logsHighlighterExpressions, logRows, logsMeta, @@ -123,6 +125,7 @@ export class LogsContainer extends PureComponent { width={width} highlighterExpressions={logsHighlighterExpressions} loading={loading} + loadingState={loadingState} onChangeTime={this.onChangeTime} onClickFilterLabel={onClickFilterLabel} onClickFilterOutLabel={onClickFilterOutLabel} diff --git a/public/app/features/explore/TraceView/TraceView.tsx b/public/app/features/explore/TraceView/TraceView.tsx index e97f4f29d8a..91483dffddd 100644 --- a/public/app/features/explore/TraceView/TraceView.tsx +++ b/public/app/features/explore/TraceView/TraceView.tsx @@ -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 { ThemeOptions, @@ -17,7 +17,7 @@ import { TraceToLogsData } from 'app/core/components/TraceToLogsSettings'; import { getDatasourceSrv } from 'app/features/plugins/datasource_srv'; import { getTimeZone } from 'app/features/profile/state/selectors'; 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 { useSelector } from 'react-redux'; import { createSpanLinkFactory } from './createSpanLink'; diff --git a/public/app/features/explore/TraceView/TraceViewContainer.tsx b/public/app/features/explore/TraceView/TraceViewContainer.tsx index d65cc042a71..c9f60b39f21 100644 --- a/public/app/features/explore/TraceView/TraceViewContainer.tsx +++ b/public/app/features/explore/TraceView/TraceViewContainer.tsx @@ -1,8 +1,8 @@ import React from 'react'; import { Collapse } from '@grafana/ui'; -import { DataFrame } from '@grafana/data'; +import { DataFrame, SplitOpen } from '@grafana/data'; import { TraceView } from './TraceView'; -import { ExploreId, SplitOpen } from '../../../types'; +import { ExploreId } from 'app/types/explore'; interface Props { dataFrames: DataFrame[]; diff --git a/public/app/features/explore/TraceView/createSpanLink.tsx b/public/app/features/explore/TraceView/createSpanLink.tsx index c2a5b7ee639..96a0099b5f3 100644 --- a/public/app/features/explore/TraceView/createSpanLink.tsx +++ b/public/app/features/explore/TraceView/createSpanLink.tsx @@ -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 { Icon } from '@grafana/ui'; import { TraceSpan } from '@jaegertracing/jaeger-ui-components'; import { TraceToLogsOptions } from 'app/core/components/TraceToLogsSettings'; import { getDatasourceSrv } from 'app/features/plugins/datasource_srv'; -import { SplitOpen } from 'app/types/explore'; import React from 'react'; import { LokiQuery } from '../../../plugins/datasource/loki/types'; diff --git a/public/app/features/explore/utils/links.ts b/public/app/features/explore/utils/links.ts index c672dc092b0..c3aabab2a51 100644 --- a/public/app/features/explore/utils/links.ts +++ b/public/app/features/explore/utils/links.ts @@ -8,9 +8,9 @@ import { ScopedVars, DataFrame, getFieldDisplayValuesProxy, + SplitOpen, } from '@grafana/data'; import { getTemplateSrv } from '@grafana/runtime'; -import { SplitOpen } from 'app/types/explore'; import { getLinkSrv } from '../../panel/panellinks/link_srv'; import { contextSrv } from 'app/core/services/context_srv'; diff --git a/public/app/plugins/panel/timeseries/TimeSeriesPanel.tsx b/public/app/plugins/panel/timeseries/TimeSeriesPanel.tsx index c873febd83b..ff3a91e582d 100644 --- a/public/app/plugins/panel/timeseries/TimeSeriesPanel.tsx +++ b/public/app/plugins/panel/timeseries/TimeSeriesPanel.tsx @@ -23,10 +23,10 @@ export const TimeSeriesPanel: React.FC = ({ onChangeTimeRange, replaceVariables, }) => { - const { sync, canAddAnnotations } = usePanelContext(); + const { sync, canAddAnnotations, onSplitOpen } = usePanelContext(); 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]); diff --git a/public/app/types/explore.ts b/public/app/types/explore.ts index 506ba3bcbe0..a4b6989b8f7 100644 --- a/public/app/types/explore.ts +++ b/public/app/types/explore.ts @@ -204,7 +204,3 @@ export interface ExplorePanelData extends PanelData { tableResult: DataFrame | null; logsResult: LogsModel | null; } - -export type SplitOpen = ( - options?: { datasourceUid: string; query: T; range?: TimeRange } | undefined -) => void;