diff --git a/public/app/features/dashboard-scene/panel-edit/PanelDataPane/AddDataItemMenu.tsx b/public/app/features/dashboard-scene/panel-edit/PanelDataPane/AddDataItemMenu.tsx
index b0d0d29e046..70680966f91 100644
--- a/public/app/features/dashboard-scene/panel-edit/PanelDataPane/AddDataItemMenu.tsx
+++ b/public/app/features/dashboard-scene/panel-edit/PanelDataPane/AddDataItemMenu.tsx
@@ -8,72 +8,80 @@ import { ExpressionQueryType } from 'app/features/expressions/types';
interface AddDataItemMenuProps {
onAddQuery: () => void;
+ onAddFromSavedQueries: () => void;
onAddTransform: () => void;
onAddExpression: (type: ExpressionQueryType) => void;
}
-export const AddDataItemMenu = memo(({ onAddQuery, onAddTransform, onAddExpression }: AddDataItemMenuProps) => {
- const expressionTypes = [
- { type: ExpressionQueryType.math, label: t('dashboard-scene.add-data-item-menu.expression-math', 'Math') },
- { type: ExpressionQueryType.reduce, label: t('dashboard-scene.add-data-item-menu.expression-reduce', 'Reduce') },
- {
- type: ExpressionQueryType.resample,
- label: t('dashboard-scene.add-data-item-menu.expression-resample', 'Resample'),
- },
- {
- type: ExpressionQueryType.classic,
- label: t('dashboard-scene.add-data-item-menu.expression-classic', 'Classic condition'),
- },
- {
- type: ExpressionQueryType.threshold,
- label: t('dashboard-scene.add-data-item-menu.expression-threshold', 'Threshold'),
- },
- ];
+export const AddDataItemMenu = memo(
+ ({ onAddQuery, onAddFromSavedQueries, onAddTransform, onAddExpression }: AddDataItemMenuProps) => {
+ const expressionTypes = [
+ { type: ExpressionQueryType.math, label: t('dashboard-scene.add-data-item-menu.expression-math', 'Math') },
+ { type: ExpressionQueryType.reduce, label: t('dashboard-scene.add-data-item-menu.expression-reduce', 'Reduce') },
+ {
+ type: ExpressionQueryType.resample,
+ label: t('dashboard-scene.add-data-item-menu.expression-resample', 'Resample'),
+ },
+ {
+ type: ExpressionQueryType.classic,
+ label: t('dashboard-scene.add-data-item-menu.expression-classic', 'Classic condition'),
+ },
+ {
+ type: ExpressionQueryType.threshold,
+ label: t('dashboard-scene.add-data-item-menu.expression-threshold', 'Threshold'),
+ },
+ ];
- // Add SQL if feature flag is enabled
- if (config.featureToggles.sqlExpressions) {
- expressionTypes.push({
- type: ExpressionQueryType.sql,
- label: t('dashboard-scene.add-data-item-menu.expression-sql', 'SQL'),
- });
- }
+ // Add SQL if feature flag is enabled
+ if (config.featureToggles.sqlExpressions) {
+ expressionTypes.push({
+ type: ExpressionQueryType.sql,
+ label: t('dashboard-scene.add-data-item-menu.expression-sql', 'SQL'),
+ });
+ }
- const expressionSubItems = expressionTypes.map(({ type, label }) => (
-
onAddExpression(type)} />
- ));
+ const expressionSubItems = expressionTypes.map(({ type, label }) => (
+ onAddExpression(type)} />
+ ));
- const menu = (
-
- );
-
- return (
-
-
-
+
-
-
- );
-});
+
+
+
+
+ );
+
+ return (
+
+
+
+
+
+ );
+ }
+);
AddDataItemMenu.displayName = 'AddDataItemMenu';
diff --git a/public/app/features/dashboard-scene/panel-edit/PanelDataPane/DetailViewHeader.tsx b/public/app/features/dashboard-scene/panel-edit/PanelDataPane/DetailViewHeader.tsx
index 58e09e1077c..9bfd02d0f87 100644
--- a/public/app/features/dashboard-scene/panel-edit/PanelDataPane/DetailViewHeader.tsx
+++ b/public/app/features/dashboard-scene/panel-edit/PanelDataPane/DetailViewHeader.tsx
@@ -28,6 +28,7 @@ import { DataSourcePicker } from 'app/features/datasources/components/picker/Dat
import { getQueryRunnerFor } from '../../utils/utils';
import { QueryTransformItem } from './QueryTransformList';
+import { SavedQueriesDrawer } from './SavedQueriesDrawer';
interface DetailViewHeaderProps {
selectedItem: QueryTransformItem;
@@ -63,6 +64,7 @@ export const DetailViewHeader = ({
const [isEditing, setIsEditing] = useState(false);
const [validationError, setValidationError] = useState(null);
+ const [isSavedQueriesDrawerOpen, setIsSavedQueriesDrawerOpen] = useState(false);
// Helper to update queries with consistent pattern
const updateQueries = useCallback(
@@ -265,6 +267,23 @@ export const DetailViewHeader = ({
onToggleTransformVisibility?.(selectedItem.index);
}, [selectedItem, onToggleTransformVisibility]);
+ // Handler for selecting a query from the library (replaces current query)
+ const onSelectQueryFromLibrary = useCallback(
+ (newQuery: DataQuery) => {
+ if (selectedItem.type !== 'query' || selectedItem.index === undefined) {
+ return;
+ }
+ updateQueries(
+ (queries) =>
+ queries.map((q, idx) =>
+ idx === selectedItem.index ? { ...newQuery, refId: q.refId, datasource: q.datasource } : q
+ ),
+ true
+ );
+ },
+ [selectedItem, updateQueries]
+ );
+
const refId = 'refId' in selectedItem.data ? selectedItem.data.refId : '';
const isHidden =
(selectedItem.type === 'query' || selectedItem.type === 'expression') &&
@@ -342,6 +361,19 @@ export const DetailViewHeader = ({
{/* Right side: Run Query + Actions Menu for queries/expressions */}
{(selectedItem.type === 'query' || selectedItem.type === 'expression') && (
+ {/* Save Query Button (only for queries, not expressions) */}
+ {selectedItem.type === 'query' && 'refId' in selectedItem.data && (
+
+ )}