diff --git a/public/app/features/dashboard/components/Inspector/PanelInspector.tsx b/public/app/features/dashboard/components/Inspector/PanelInspector.tsx index 849a85b60f8..90e3c793520 100644 --- a/public/app/features/dashboard/components/Inspector/PanelInspector.tsx +++ b/public/app/features/dashboard/components/Inspector/PanelInspector.tsx @@ -29,7 +29,7 @@ const PanelInspectorUnconnected: React.FC = ({ panel, dashboard, plugin } }); const location = useLocation(); - const { data, isLoading, error } = usePanelLatestData(panel, dataOptions); + const { data, isLoading, error } = usePanelLatestData(panel, dataOptions, true); const metaDs = useDatasourceMetadata(data); const tabs = useInspectTabs(dashboard, plugin, error, metaDs); const defaultTab = new URLSearchParams(location.search).get('inspectTab') as InspectTab; diff --git a/public/app/features/dashboard/components/PanelEditor/OptionsPane.tsx b/public/app/features/dashboard/components/PanelEditor/OptionsPane.tsx index 0659a3a1b99..fba3cdb9ad4 100644 --- a/public/app/features/dashboard/components/PanelEditor/OptionsPane.tsx +++ b/public/app/features/dashboard/components/PanelEditor/OptionsPane.tsx @@ -32,7 +32,7 @@ export const OptionsPane: React.FC = ({ }: Props) => { const styles = useStyles(getStyles); const isVizPickerOpen = useSelector((state: StoreState) => state.panelEditor.isVizPickerOpen); - const { data } = usePanelLatestData(panel, { withTransforms: true, withFieldConfig: false }); + const { data } = usePanelLatestData(panel, { withTransforms: true, withFieldConfig: false }, true); return (
diff --git a/public/app/features/dashboard/components/PanelEditor/usePanelLatestData.ts b/public/app/features/dashboard/components/PanelEditor/usePanelLatestData.ts index ff8513dc5d0..7f738a4ca93 100644 --- a/public/app/features/dashboard/components/PanelEditor/usePanelLatestData.ts +++ b/public/app/features/dashboard/components/PanelEditor/usePanelLatestData.ts @@ -1,4 +1,11 @@ -import { DataQueryError, LoadingState, PanelData } from '@grafana/data'; +import { + compareArrayValues, + compareDataFrameStructures, + DataFrame, + DataQueryError, + LoadingState, + PanelData, +} from '@grafana/data'; import { useEffect, useRef, useState } from 'react'; import { PanelModel } from '../../state'; import { Unsubscribable } from 'rxjs'; @@ -14,16 +21,37 @@ interface UsePanelLatestData { /** * Subscribes and returns latest panel data from PanelQueryRunner */ -export const usePanelLatestData = (panel: PanelModel, options: GetDataOptions): UsePanelLatestData => { +export const usePanelLatestData = ( + panel: PanelModel, + options: GetDataOptions, + checkSchema?: boolean +): UsePanelLatestData => { const querySubscription = useRef(); const [latestData, setLatestData] = useState(); useEffect(() => { + let last: DataFrame[] = []; + let lastUpdate = 0; + querySubscription.current = panel .getQueryRunner() .getData(options) .subscribe({ - next: (data) => setLatestData(data), + next: (data) => { + if (checkSchema) { + const sameStructure = compareArrayValues(last, data.series, compareDataFrameStructures); + if (sameStructure) { + const now = Date.now(); + const elapsed = now - lastUpdate; + if (elapsed < 10000) { + return; // avoid updates if the schema has not changed for 10s + } + lastUpdate = now; + } + last = data.series; + } + setLatestData(data); + }, }); return () => {