From 8e502046c117b722ec301bc14f079d567bd25c48 Mon Sep 17 00:00:00 2001 From: Collin Fingar Date: Wed, 7 Jan 2026 15:18:48 -0500 Subject: [PATCH] SavedQueries: Added option to Panel configure to use SQ --- .../scene/UnconfiguredPanel.tsx | 90 ++++++++++++++++++- public/locales/en-US/grafana.json | 1 + 2 files changed, 88 insertions(+), 3 deletions(-) diff --git a/public/app/features/dashboard-scene/scene/UnconfiguredPanel.tsx b/public/app/features/dashboard-scene/scene/UnconfiguredPanel.tsx index 44a15a0d3e1..be54447486e 100644 --- a/public/app/features/dashboard-scene/scene/UnconfiguredPanel.tsx +++ b/public/app/features/dashboard-scene/scene/UnconfiguredPanel.tsx @@ -3,8 +3,9 @@ import { useCallback, useEffect, useState } from 'react'; import { CoreApp, GrafanaTheme2, PanelPlugin, PanelProps } from '@grafana/data'; import { Trans, t } from '@grafana/i18n'; -import { config, locationService } from '@grafana/runtime'; -import { sceneUtils } from '@grafana/scenes'; +import { config, getDataSourceSrv, locationService } from '@grafana/runtime'; +import { SceneDataTransformer, SceneQueryRunner, sceneUtils } from '@grafana/scenes'; +import { DataQuery } from '@grafana/schema'; import { Box, Button, @@ -18,10 +19,11 @@ import { usePanelContext, useStyles2, } from '@grafana/ui'; +import { useQueryLibraryContext } from 'app/features/explore/QueryLibrary/QueryLibraryContext'; import { NEW_PANEL_TITLE } from '../../dashboard/utils/dashboard'; import { DashboardInteractions } from '../utils/interactions'; -import { findVizPanelByKey, getVizPanelKeyForPanelId } from '../utils/utils'; +import { findVizPanelByKey, getVizPanelKeyForPanelId, getQueryRunnerFor } from '../utils/utils'; import { DashboardScene } from './DashboardScene'; @@ -32,6 +34,7 @@ function UnconfiguredPanelComp(props: PanelProps) { const [isOpen, setIsOpen] = useState(false); const panelContext = usePanelContext(); const styles = useStyles2(getStyles); + const { openDrawer: openQueryLibraryDrawer, queryLibraryEnabled } = useQueryLibraryContext(); const onMenuClick = useCallback((isOpen: boolean) => { setIsOpen(isOpen); @@ -58,6 +61,80 @@ function UnconfiguredPanelComp(props: PanelProps) { dashboard.onShowAddLibraryPanelDrawer(panel.getRef()); }; + const onUseSavedQuery = useCallback(async () => { + if (!dashboard || !(dashboard instanceof DashboardScene)) { + throw new Error('DashboardScene not found'); + } + + if (!panel) { + throw new Error('Panel not found'); + } + + if (!queryLibraryEnabled) { + return; + } + + openQueryLibraryDrawer({ + onSelectQuery: async (query: DataQuery) => { + try { + // Get or create the query runner for the panel BEFORE opening the editor + let queryRunner = getQueryRunnerFor(panel); + + // If panel doesn't have a query runner yet, create one + if (!queryRunner && !panel.state.$data) { + const defaultDatasource = config.defaultDatasource; + panel.setState({ + $data: new SceneDataTransformer({ + $data: new SceneQueryRunner({ + datasource: { + uid: defaultDatasource, + }, + queries: [], + }), + transformations: [], + }), + }); + queryRunner = getQueryRunnerFor(panel); + } + + if (!queryRunner) { + console.error('Failed to get or create query runner for panel'); + return; + } + + // Ensure query has datasource set + const enrichedQuery = query.datasource + ? query + : { + ...query, + datasource: queryRunner.state.datasource || { uid: config.defaultDatasource }, + }; + + // Set the query in the panel BEFORE opening the editor + // The editor will pick up this query when it initializes + queryRunner.setState({ queries: [enrichedQuery] }); + + // Update datasource if needed + if (enrichedQuery.datasource?.uid) { + const dsSettings = await getDataSourceSrv().get({ uid: enrichedQuery.datasource.uid }); + queryRunner.setState({ datasource: { uid: dsSettings.uid, type: dsSettings.type } }); + } + + // Now open the panel editor - it will pick up the query we just set + locationService.partial({ editPanel: props.id }); + + // Run the query after opening the editor + queryRunner.runQueries(); + } catch (error) { + console.error('Failed to set query from library:', error); + } + }, + options: { + context: CoreApp.Dashboard, + }, + }); + }, [dashboard, panel, props.id, openQueryLibraryDrawer, queryLibraryEnabled]); + useEffect(() => { if (!panel || !config.featureToggles.newVizSuggestions) { return; @@ -82,6 +159,13 @@ function UnconfiguredPanelComp(props: PanelProps) { label={t('dashboard.new-panel.menu-use-library-panel', 'Use library panel')} onClick={onUseLibraryPanel} > + {queryLibraryEnabled && ( + + )} ); diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json index baffdefbadf..862e30d4c1e 100644 --- a/public/locales/en-US/grafana.json +++ b/public/locales/en-US/grafana.json @@ -5187,6 +5187,7 @@ "empty-state-message": "Run a query to visualize it here or go to all visualizations to add other panel types", "menu-open-panel-editor": "Configure", "menu-use-library-panel": "Use library panel", + "menu-use-saved-query": "Use saved query", "missing-config": "Missing panel configuration", "suggestions": { "empty-state-message": "Run a query to start seeing suggested visualizations"