diff --git a/public/app/features/alerting/unified/components/rule-editor/VizWrapper.tsx b/public/app/features/alerting/unified/components/rule-editor/VizWrapper.tsx index 22f31ccc3a0..12c76bb5b4d 100644 --- a/public/app/features/alerting/unified/components/rule-editor/VizWrapper.tsx +++ b/public/app/features/alerting/unified/components/rule-editor/VizWrapper.tsx @@ -3,7 +3,7 @@ import React from 'react'; import AutoSizer from 'react-virtualized-auto-sizer'; import { GrafanaTheme2, isTimeSeriesFrames, PanelData, ThresholdsConfig } from '@grafana/data'; -import { GraphTresholdsStyleMode, LoadingState } from '@grafana/schema'; +import { GraphTresholdsStyleMode } from '@grafana/schema'; import { useStyles2 } from '@grafana/ui'; import appEvents from 'app/core/app_events'; import { GraphContainer } from 'app/features/explore/Graph/GraphContainer'; @@ -37,7 +37,6 @@ export const VizWrapper = ({ data, thresholds, thresholdsType }: Props) => {
{isTimeSeriesData ? ( { } renderGraphPanel(width: number) { - const { graphResult, absoluteRange, timeZone, queryResponse, loading, showFlameGraph } = this.props; + const { graphResult, absoluteRange, timeZone, queryResponse, showFlameGraph } = this.props; return ( getTimeZone(state.user)); const fiscalYearStartMonth = useSelector((state: StoreState) => getFiscalYearStartMonth(state.user)); - const { refreshInterval, loading, datasourceInstance, range, isLive, isPaused, syncedTimes } = useSelector( + const { refreshInterval, datasourceInstance, range, isLive, isPaused, syncedTimes } = useSelector( (state: StoreState) => ({ - ...pick( - state.explore[exploreId]!, - 'refreshInterval', - 'loading', - 'datasourceInstance', - 'range', - 'isLive', - 'isPaused' - ), + ...pick(state.explore[exploreId]!, 'refreshInterval', 'datasourceInstance', 'range', 'isLive', 'isPaused'), syncedTimes: state.explore.syncedTimes, }), shallowEqual ); + const loading = useSelector(selectIsWaitingForData(exploreId)); const isLargerPane = useSelector((state: StoreState) => state.explore.largerExploreId === exploreId); const showSmallTimePicker = useSelector((state) => splitted || state.explore[exploreId]!.containerWidth < 1210); const showSmallDataSourcePicker = useSelector( diff --git a/public/app/features/explore/Graph/GraphContainer.tsx b/public/app/features/explore/Graph/GraphContainer.tsx index 2413636300d..56f0fd17b08 100644 --- a/public/app/features/explore/Graph/GraphContainer.tsx +++ b/public/app/features/explore/Graph/GraphContainer.tsx @@ -19,7 +19,6 @@ import { ExploreGraphLabel } from './ExploreGraphLabel'; import { loadGraphStyle } from './utils'; interface Props extends Pick { - loading: boolean; data: DataFrame[]; annotations?: DataFrame[]; eventBus: EventBus; diff --git a/public/app/features/explore/LogsContainer.tsx b/public/app/features/explore/LogsContainer.tsx index 67d89101449..9262e1ef6f1 100644 --- a/public/app/features/explore/LogsContainer.tsx +++ b/public/app/features/explore/LogsContainer.tsx @@ -27,7 +27,13 @@ import { getTimeZone } from '../profile/state/selectors'; import { LiveLogsWithTheme } from './LiveLogs'; import { Logs } from './Logs'; -import { addResultsToCache, clearCache, loadSupplementaryQueryData, setSupplementaryQueryEnabled } from './state/query'; +import { + addResultsToCache, + clearCache, + loadSupplementaryQueryData, + selectIsWaitingForData, + setSupplementaryQueryEnabled, +} from './state/query'; import { updateTimeRange } from './state/time'; import { LiveTailControls } from './useLiveTailControls'; import { LogsCrossFadeTransition } from './utils/LogsCrossFadeTransition'; @@ -208,13 +214,12 @@ class LogsContainer extends PureComponent { } } -function mapStateToProps(state: StoreState, { exploreId }: { exploreId: string }) { +function mapStateToProps(state: StoreState, { exploreId }: { exploreId: ExploreId }) { const explore = state.explore; // @ts-ignore const item: ExploreItemState = explore[exploreId]; const { logsResult, - loading, scanning, datasourceInstance, isLive, @@ -224,6 +229,7 @@ function mapStateToProps(state: StoreState, { exploreId }: { exploreId: string } absoluteRange, supplementaryQueries, } = item; + const loading = selectIsWaitingForData(exploreId)(state); const timeZone = getTimeZone(state.user); const logsVolume = supplementaryQueries[SupplementaryQueryType.LogsVolume]; diff --git a/public/app/features/explore/RawPrometheusContainer.tsx b/public/app/features/explore/RawPrometheusContainer.tsx index c37a9859852..b3ded8c5d58 100644 --- a/public/app/features/explore/RawPrometheusContainer.tsx +++ b/public/app/features/explore/RawPrometheusContainer.tsx @@ -12,6 +12,7 @@ import { ExploreId, ExploreItemState, TABLE_RESULTS_STYLES, TableResultsStyle } import { MetaInfoText } from './MetaInfoText'; import RawListContainer from './PrometheusListView/RawListContainer'; +import { selectIsWaitingForData } from './state/query'; import { getFieldLinksForExplore } from './utils/links'; interface RawPrometheusContainerProps { @@ -31,7 +32,8 @@ interface PrometheusContainerState { function mapStateToProps(state: StoreState, { exploreId }: RawPrometheusContainerProps) { const explore = state.explore; const item: ExploreItemState = explore[exploreId]!; - const { loading: loadingInState, tableResult, rawPrometheusResult, range } = item; + const { tableResult, rawPrometheusResult, range } = item; + const loadingInState = selectIsWaitingForData(exploreId)(state); const rawPrometheusFrame: DataFrame[] = rawPrometheusResult ? [rawPrometheusResult] : []; const result = (tableResult?.length ?? false) > 0 && rawPrometheusResult ? tableResult : rawPrometheusFrame; const loading = result && result.length > 0 ? false : loadingInState; diff --git a/public/app/features/explore/TableContainer.tsx b/public/app/features/explore/TableContainer.tsx index 600c4cdd7be..dc08655b100 100644 --- a/public/app/features/explore/TableContainer.tsx +++ b/public/app/features/explore/TableContainer.tsx @@ -8,6 +8,7 @@ import { StoreState } from 'app/types'; import { ExploreId, ExploreItemState } from 'app/types/explore'; import { MetaInfoText } from './MetaInfoText'; +import { selectIsWaitingForData } from './state/query'; import { getFieldLinksForExplore } from './utils/links'; interface TableContainerProps { @@ -23,7 +24,8 @@ function mapStateToProps(state: StoreState, { exploreId }: TableContainerProps) const explore = state.explore; // @ts-ignore const item: ExploreItemState = explore[exploreId]; - const { loading: loadingInState, tableResult, range } = item; + const { tableResult, range } = item; + const loadingInState = selectIsWaitingForData(exploreId); const loading = tableResult && tableResult.length > 0 ? false : loadingInState; return { loading, tableResult, range }; } diff --git a/public/app/features/explore/state/datasource.test.ts b/public/app/features/explore/state/datasource.test.ts index 606db7151f4..1218c074d67 100644 --- a/public/app/features/explore/state/datasource.test.ts +++ b/public/app/features/explore/state/datasource.test.ts @@ -37,7 +37,6 @@ describe('Datasource reducer', () => { graphResult: null, logsResult: null, tableResult: null, - loading: false, queryResponse: { // When creating an empty query response we also create a timeRange object with the current time. // Copying the range from the reducer here prevents intermittent failures when creating them at different times. diff --git a/public/app/features/explore/state/datasource.ts b/public/app/features/explore/state/datasource.ts index 5aed7e998ed..0d8062292f6 100644 --- a/public/app/features/explore/state/datasource.ts +++ b/public/app/features/explore/state/datasource.ts @@ -103,7 +103,6 @@ export const datasourceReducer = (state: ExploreItemState, action: AnyAction): E logsResult: null, supplementaryQueries: loadSupplementaryQueries(), queryResponse: createEmptyQueryResponse(), - loading: false, queryKeys: [], history, datasourceMissing: false, diff --git a/public/app/features/explore/state/query.ts b/public/app/features/explore/state/query.ts index 2ffa3d61318..c1af67c2d63 100644 --- a/public/app/features/explore/state/query.ts +++ b/public/app/features/explore/state/query.ts @@ -43,6 +43,7 @@ import { ExploreItemState, ExplorePanelData, QueryTransaction, + StoreState, ThunkDispatch, ThunkResult, } from 'app/types'; @@ -53,15 +54,31 @@ import { createErrorNotification } from '../../../core/copy/appNotification'; import { runRequest } from '../../query/state/runRequest'; import { decorateData } from '../utils/decorators'; import { + getSupplementaryQueryProvider, storeSupplementaryQueryEnabled, supplementaryQueryTypes, - getSupplementaryQueryProvider, } from '../utils/supplementaryQueries'; import { addHistoryItem, historyUpdatedAction, loadRichHistory } from './history'; import { stateSave } from './main'; import { updateTime } from './time'; -import { createCacheKey, getResultsFromCache, filterLogRowsByIndex } from './utils'; +import { createCacheKey, filterLogRowsByIndex, getResultsFromCache } from './utils'; + +/** + * Derives from explore state if a given Explore pane is waiting for more data to be received + */ +export const selectIsWaitingForData = (exploreId: ExploreId) => { + return (state: StoreState) => { + const panelState = state.explore[exploreId]; + if (!panelState) { + return false; + } + return panelState.queryResponse + ? panelState.queryResponse.state === LoadingState.Loading || + panelState.queryResponse.state === LoadingState.Streaming + : false; + }; +}; // // Actions and Payloads @@ -897,7 +914,10 @@ export const queryReducer = (state: ExploreItemState, action: AnyAction): Explor return { ...state, - loading: false, + queryResponse: { + ...state.queryResponse, + state: LoadingState.Done, + }, }; } @@ -1043,7 +1063,6 @@ export const queryReducer = (state: ExploreItemState, action: AnyAction): Explor ...state.queryResponse, state: loadingState, }, - loading: loadingState === LoadingState.Loading || loadingState === LoadingState.Streaming, }; } @@ -1159,7 +1178,6 @@ export const processQueryResponse = ( const { response } = action.payload; const { request, - state: loadingState, series, error, graphResult, @@ -1173,14 +1191,8 @@ export const processQueryResponse = ( } = response; if (error) { - if (error.type === DataQueryErrorType.Timeout) { - return { - ...state, - queryResponse: response, - loading: loadingState === LoadingState.Loading || loadingState === LoadingState.Streaming, - }; - } else if (error.type === DataQueryErrorType.Cancelled) { - return state; + if (error.type === DataQueryErrorType.Timeout || error.type === DataQueryErrorType.Cancelled) { + return { ...state }; } // Send error to Angular editors @@ -1211,7 +1223,6 @@ export const processQueryResponse = ( state.isLive && logsResult ? { ...logsResult, rows: filterLogRowsByIndex(state.clearedAtIndex, logsResult.rows) } : logsResult, - loading: loadingState === LoadingState.Loading || loadingState === LoadingState.Streaming, showLogs: !!logsResult, showMetrics: !!graphResult, showTable: !!tableResult?.length, diff --git a/public/app/features/explore/state/time.test.ts b/public/app/features/explore/state/time.test.ts index b32c38c6f8a..122b09eb49a 100644 --- a/public/app/features/explore/state/time.test.ts +++ b/public/app/features/explore/state/time.test.ts @@ -1,14 +1,13 @@ import { reducerTester } from 'test/core/redux/reducerTester'; -import { dateTime, LoadingState } from '@grafana/data'; +import { dateTime } from '@grafana/data'; import { configureStore } from 'app/store/configureStore'; import { ExploreId, ExploreItemState } from 'app/types/explore'; import { silenceConsoleOutput } from '../../../../test/core/utils/silenceConsoleOutput'; import { createDefaultInitialState } from './helpers'; -import { changeRangeAction, changeRefreshIntervalAction, timeReducer, updateTime } from './time'; -import { makeExplorePaneState } from './utils'; +import { changeRangeAction, timeReducer, updateTime } from './time'; const MOCK_TIME_RANGE = {}; @@ -43,50 +42,6 @@ describe('Explore item reducer', () => { }); }); - describe('changing refresh intervals', () => { - it("should result in 'streaming' state, when live-tailing is active", () => { - const initialState = makeExplorePaneState(); - const expectedState = { - ...initialState, - refreshInterval: 'LIVE', - isLive: true, - loading: true, - logsResult: { - hasUniqueLabels: false, - rows: [], - }, - queryResponse: { - ...initialState.queryResponse, - state: LoadingState.Streaming, - }, - }; - reducerTester() - .givenReducer(timeReducer, initialState) - .whenActionIsDispatched(changeRefreshIntervalAction({ exploreId: ExploreId.left, refreshInterval: 'LIVE' })) - .thenStateShouldEqual(expectedState); - }); - - it("should result in 'done' state, when live-tailing is stopped", () => { - const initialState = makeExplorePaneState(); - const expectedState = { - ...initialState, - refreshInterval: '', - logsResult: { - hasUniqueLabels: false, - rows: [], - }, - queryResponse: { - ...initialState.queryResponse, - state: LoadingState.Done, - }, - }; - reducerTester() - .givenReducer(timeReducer, initialState) - .whenActionIsDispatched(changeRefreshIntervalAction({ exploreId: ExploreId.left, refreshInterval: '' })) - .thenStateShouldEqual(expectedState); - }); - }); - describe('changing range', () => { describe('when changeRangeAction is dispatched', () => { it('then it should set correct state', () => { diff --git a/public/app/features/explore/state/time.ts b/public/app/features/explore/state/time.ts index ec96b5b5600..8c03ab554bf 100644 --- a/public/app/features/explore/state/time.ts +++ b/public/app/features/explore/state/time.ts @@ -182,7 +182,6 @@ export const timeReducer = (state: ExploreItemState, action: AnyAction): Explore }, isLive: live, isPaused: live ? false : state.isPaused, - loading: live, logsResult, }; } diff --git a/public/app/features/explore/state/utils.ts b/public/app/features/explore/state/utils.ts index 3dd4d90efbf..f4d8499a548 100644 --- a/public/app/features/explore/state/utils.ts +++ b/public/app/features/explore/state/utils.ts @@ -51,7 +51,6 @@ export const makeExplorePaneState = (): ExploreItemState => ({ to: null, } as any, scanning: false, - loading: false, queryKeys: [], isLive: false, isPaused: false, diff --git a/public/app/types/explore.ts b/public/app/types/explore.ts index 6c523946588..b8b6387445b 100644 --- a/public/app/types/explore.ts +++ b/public/app/types/explore.ts @@ -139,7 +139,6 @@ export interface ExploreItemState { */ scanRange?: RawTimeRange; - loading: boolean; /** * Table model that combines all query table results into a single table. */