diff --git a/public/app/features/dashboard-scene/inspect/InspectJsonTab.tsx b/public/app/features/dashboard-scene/inspect/InspectJsonTab.tsx index 1e7cafed357..0b3d2ac23c2 100644 --- a/public/app/features/dashboard-scene/inspect/InspectJsonTab.tsx +++ b/public/app/features/dashboard-scene/inspect/InspectJsonTab.tsx @@ -125,7 +125,7 @@ export class InspectJsonTab extends SceneObjectBase { panel_type_changed: panel.state.pluginId !== panelModel.type, panel_id_changed: getPanelIdForVizPanel(panel) !== panelModel.id, panel_grid_pos_changed: hasGridPosChanged(panel.parent.state, newState), - panel_targets_changed: hasQueriesChanged(getQueryRunnerFor(panel), getQueryRunnerFor(gridItem.state.body)), + panel_targets_changed: hasQueriesChanged(getQueryRunnerFor(panel), getQueryRunnerFor(newState.$data)), }); }; @@ -218,7 +218,6 @@ function getJsonText(show: ShowContent, panel: VizPanel): string { case 'data-frames': { reportPanelInspectInteraction(InspectTab.JSON, 'dataFrame'); - const dataProvider = sceneGraph.getData(panel); if (dataProvider.state.data) { diff --git a/public/app/features/dashboard-scene/inspect/InspectQueryTab.tsx b/public/app/features/dashboard-scene/inspect/InspectQueryTab.tsx new file mode 100644 index 00000000000..2099a9ba9f6 --- /dev/null +++ b/public/app/features/dashboard-scene/inspect/InspectQueryTab.tsx @@ -0,0 +1,47 @@ +import React from 'react'; + +import { + SceneComponentProps, + sceneGraph, + SceneObjectBase, + SceneObjectState, + SceneObjectRef, + VizPanel, +} from '@grafana/scenes'; +import { t } from 'app/core/internationalization'; +import { QueryInspector } from 'app/features/inspector/QueryInspector'; +import { InspectTab } from 'app/features/inspector/types'; + +import { getQueryRunnerFor } from '../utils/utils'; + +export interface InspectQueryTabState extends SceneObjectState { + panelRef: SceneObjectRef; +} + +export class InspectQueryTab extends SceneObjectBase { + public getTabLabel() { + return t('dashboard.inspect.query-tab', 'Query'); + } + + public getTabValue() { + return InspectTab.Query; + } + + public onRefreshQuery = () => { + const queryRunner = getQueryRunnerFor(this.state.panelRef.resolve()); + + if (queryRunner) { + queryRunner.runQueries(); + } + }; + + static Component = ({ model }: SceneComponentProps) => { + const data = sceneGraph.getData(model.state.panelRef.resolve()).useState(); + + if (!data.data) { + return null; + } + + return ; + }; +} diff --git a/public/app/features/dashboard-scene/inspect/PanelInspectDrawer.tsx b/public/app/features/dashboard-scene/inspect/PanelInspectDrawer.tsx index 7eae1deb559..e3e5119254f 100644 --- a/public/app/features/dashboard-scene/inspect/PanelInspectDrawer.tsx +++ b/public/app/features/dashboard-scene/inspect/PanelInspectDrawer.tsx @@ -16,6 +16,7 @@ import { supportsDataQuery } from 'app/features/dashboard/components/PanelEditor import { InspectDataTab } from './InspectDataTab'; import { InspectJsonTab } from './InspectJsonTab'; +import { InspectQueryTab } from './InspectQueryTab'; import { InspectStatsTab } from './InspectStatsTab'; import { SceneInspectTab } from './types'; @@ -56,6 +57,7 @@ export class PanelInspectDrawer extends SceneObjectBase if (supportsDataQuery(plugin)) { tabs.push(new InspectDataTab({ panelRef })); tabs.push(new InspectStatsTab({ panelRef })); + tabs.push(new InspectQueryTab({ panelRef })); } tabs.push(new InspectJsonTab({ panelRef, onClose: this.onClose })); diff --git a/public/app/features/dashboard/components/Inspector/InspectContent.tsx b/public/app/features/dashboard/components/Inspector/InspectContent.tsx index b4ac829fce8..4bd881c62ad 100644 --- a/public/app/features/dashboard/components/Inspector/InspectContent.tsx +++ b/public/app/features/dashboard/components/Inspector/InspectContent.tsx @@ -109,9 +109,7 @@ export const InspectContent = ({ )} {activeTab === InspectTab.Error && } {data && activeTab === InspectTab.Stats && } - {data && activeTab === InspectTab.Query && ( - panel.refresh()} /> - )} + {data && activeTab === InspectTab.Query && panel.refresh()} />} ); }; diff --git a/public/app/features/dashboard/components/Inspector/PanelInspector.tsx b/public/app/features/dashboard/components/Inspector/PanelInspector.tsx index 92b23720cfb..9aa2309e02d 100644 --- a/public/app/features/dashboard/components/Inspector/PanelInspector.tsx +++ b/public/app/features/dashboard/components/Inspector/PanelInspector.tsx @@ -34,7 +34,7 @@ const PanelInspectorUnconnected = ({ panel, dashboard, plugin }: Props) => { }); const location = useLocation(); - const { data, isLoading, error } = usePanelLatestData(panel, dataOptions, true); + const { data, isLoading, error } = usePanelLatestData(panel, dataOptions, false); const metaDs = useDatasourceMetadata(data); const tabs = useInspectTabs(panel, dashboard, plugin, error, metaDs); const defaultTab = new URLSearchParams(location.search).get('inspectTab') as InspectTab; diff --git a/public/app/features/dashboard/components/PanelEditor/usePanelLatestData.ts b/public/app/features/dashboard/components/PanelEditor/usePanelLatestData.ts index e3d24cae356..5d2f455de61 100644 --- a/public/app/features/dashboard/components/PanelEditor/usePanelLatestData.ts +++ b/public/app/features/dashboard/components/PanelEditor/usePanelLatestData.ts @@ -64,7 +64,7 @@ export const usePanelLatestData = ( return { data: latestData, error: latestData && latestData.error, - isLoading: latestData ? latestData.state === LoadingState.Loading : true, + isLoading: latestData?.state === LoadingState.Loading, hasSeries: latestData ? !!latestData.series : false, }; }; diff --git a/public/app/features/explore/ExploreQueryInspector.test.tsx b/public/app/features/explore/ExploreQueryInspector.test.tsx index 950905a4d46..23f3f227c0a 100644 --- a/public/app/features/explore/ExploreQueryInspector.test.tsx +++ b/public/app/features/explore/ExploreQueryInspector.test.tsx @@ -35,7 +35,6 @@ jest.mock('@grafana/runtime', () => ({ const setup = (propOverrides = {}) => { const props: ExploreQueryInspectorProps = { - loading: false, width: 100, exploreId: 'left', onClose: jest.fn(), diff --git a/public/app/features/explore/ExploreQueryInspector.tsx b/public/app/features/explore/ExploreQueryInspector.tsx index 9b7e93f2870..83e0a8f257f 100644 --- a/public/app/features/explore/ExploreQueryInspector.tsx +++ b/public/app/features/explore/ExploreQueryInspector.tsx @@ -1,7 +1,7 @@ import React, { useEffect } from 'react'; import { connect, ConnectedProps } from 'react-redux'; -import { CoreApp, TimeZone } from '@grafana/data'; +import { CoreApp, LoadingState, TimeZone } from '@grafana/data'; import { reportInteraction } from '@grafana/runtime/src'; import { TabbedContainer, TabConfig } from '@grafana/ui'; import { ExploreDrawer } from 'app/features/explore/ExploreDrawer'; @@ -12,7 +12,7 @@ import { InspectStatsTab } from 'app/features/inspector/InspectStatsTab'; import { QueryInspector } from 'app/features/inspector/QueryInspector'; import { StoreState, ExploreItemState } from 'app/types'; -import { runQueries, selectIsWaitingForData } from './state/query'; +import { runQueries } from './state/query'; interface DispatchProps { width: number; @@ -24,7 +24,7 @@ interface DispatchProps { type Props = DispatchProps & ConnectedProps; export function ExploreQueryInspector(props: Props) { - const { loading, width, onClose, queryResponse, timeZone } = props; + const { width, onClose, queryResponse, timeZone } = props; const dataFrames = queryResponse?.series || []; let errors = queryResponse?.errors; if (!errors?.length && queryResponse?.error) { @@ -57,7 +57,7 @@ export function ExploreQueryInspector(props: Props) { props.runQueries({ exploreId: props.exploreId })} /> + props.runQueries({ exploreId: props.exploreId })} /> ), }; @@ -97,7 +97,6 @@ function mapStateToProps(state: StoreState, { exploreId }: { exploreId: string } const { queryResponse } = item; return { - loading: selectIsWaitingForData(exploreId)(state), queryResponse, }; } diff --git a/public/app/features/inspector/QueryInspector.tsx b/public/app/features/inspector/QueryInspector.tsx index 4d3981ce890..024b487d90e 100644 --- a/public/app/features/inspector/QueryInspector.tsx +++ b/public/app/features/inspector/QueryInspector.tsx @@ -2,22 +2,15 @@ import { css } from '@emotion/css'; import React, { PureComponent } from 'react'; import { Subscription } from 'rxjs'; -import { DataFrame } from '@grafana/data'; +import { LoadingState, PanelData } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; import { Stack } from '@grafana/experimental'; -import { config, RefreshEvent } from '@grafana/runtime'; +import { config } from '@grafana/runtime'; import { Button, ClipboardButton, JSONFormatter, LoadingPlaceholder } from '@grafana/ui'; import { backendSrv } from 'app/core/services/backend_srv'; -import { supportsDataQuery } from 'app/features/dashboard/components/PanelEditor/utils'; -import { PanelModel } from 'app/features/dashboard/state'; import { getPanelInspectorStyles } from './styles'; -interface DsQuery { - isLoading: boolean; - response: {}; -} - interface ExecutedQueryInfo { refId: string; query: string; @@ -26,16 +19,15 @@ interface ExecutedQueryInfo { } interface Props { - data: DataFrame[]; + data: PanelData; onRefreshQuery: () => void; - panel?: PanelModel; } interface State { allNodesExpanded: boolean | null; isMocking: boolean; mockedResponse: string; - dsQuery: DsQuery; + response: {}; executedQueries: ExecutedQueryInfo[]; } @@ -50,26 +42,16 @@ export class QueryInspector extends PureComponent { allNodesExpanded: null, isMocking: false, mockedResponse: '', - dsQuery: { - isLoading: false, - response: {}, - }, + response: {}, }; } componentDidMount() { - const { panel } = this.props; - this.subs.add( backendSrv.getInspectorStream().subscribe({ next: (response) => this.onDataSourceResponse(response), }) ); - - if (panel) { - this.subs.add(panel.events.subscribe(RefreshEvent, this.onPanelRefresh)); - this.updateQueryList(); - } } componentDidUpdate(oldProps: Props) { @@ -83,12 +65,13 @@ export class QueryInspector extends PureComponent { */ updateQueryList() { const { data } = this.props; + const frames = data.series; const executedQueries: ExecutedQueryInfo[] = []; - if (data?.length) { + if (frames?.length) { let last: ExecutedQueryInfo | undefined = undefined; - data.forEach((frame, idx) => { + frames.forEach((frame, idx) => { const query = frame.meta?.executedQueryString; if (query) { @@ -117,16 +100,6 @@ export class QueryInspector extends PureComponent { this.subs.unsubscribe(); } - onPanelRefresh = () => { - this.setState((prevState) => ({ - ...prevState, - dsQuery: { - isLoading: true, - response: {}, - }, - })); - }; - onDataSourceResponse(response: any) { // ignore silent requests if (response.config?.hideFromInspector) { @@ -168,13 +141,9 @@ export class QueryInspector extends PureComponent { delete response.$$config; } - this.setState((prevState) => ({ - ...prevState, - dsQuery: { - isLoading: false, - response: response, - }, - })); + this.setState({ + response: response, + }); } setFormattedJson = (formattedJson: any) => { @@ -240,16 +209,12 @@ export class QueryInspector extends PureComponent { } render() { - const { allNodesExpanded, executedQueries } = this.state; - const { panel, onRefreshQuery } = this.props; - const { response, isLoading } = this.state.dsQuery; + const { allNodesExpanded, executedQueries, response } = this.state; + const { onRefreshQuery, data } = this.props; const openNodes = this.getNrOfOpenNodes(); const styles = getPanelInspectorStyles(); const haveData = Object.keys(response).length > 0; - - if (panel && !supportsDataQuery(panel.plugin)) { - return null; - } + const isLoading = data.state === LoadingState.Loading; return (