QueryLibrary: Add CoreApp for QueryEditor rendering (#108867)

This commit is contained in:
Juan Cabanas
2025-07-30 15:12:35 -03:00
committed by GitHub
parent 60ce4ad1fa
commit 68ed7c129d
6 changed files with 25 additions and 11 deletions
@@ -376,6 +376,7 @@ export function PanelDataQueriesTabRendered({ model }: SceneComponentProps<Panel
onAddQuery={model.onAddQuery}
onQueriesChange={model.onQueriesChange}
onRunQueries={model.onRunQueries}
app={CoreApp.PanelEditor}
/>
<Stack gap={2}>
@@ -393,7 +394,9 @@ export function PanelDataQueriesTabRendered({ model }: SceneComponentProps<Panel
<Button
icon="plus"
onClick={() =>
openQueryLibraryDrawer(getDatasourceNames(datasource, queries), onSelectQueryFromLibrary)
openQueryLibraryDrawer(getDatasourceNames(datasource, queries), onSelectQueryFromLibrary, {
context: CoreApp.PanelEditor,
})
}
variant="secondary"
data-testid={selectors.components.QueryTab.addQueryFromLibrary}
@@ -1,5 +1,6 @@
import { createContext, ReactNode, useContext } from 'react';
import { CoreApp } from '@grafana/data';
import { DataQuery } from '@grafana/schema';
import { OnSelectQueryType } from './types';
@@ -17,7 +18,7 @@ export type QueryLibraryContextType = {
* @param datasourceFilters Data source names that will be used for initial filter in the library.
* @param queryActionButton Action button will be shown in the library next to the query and can implement context
* specific actions with the library, like running the query or updating some query in the current app.
* @param options.context Used for tracking. Should identify the context this is called from, like 'explore' or
* @param options.context Used for QueryEditor. Should identify the context this is called from, like 'explore' or
* 'dashboard'.
*/
openDrawer: (
@@ -32,7 +33,7 @@ export type QueryLibraryContextType = {
* Opens a modal for adding a query to the library.
* @param query Query to be saved
* @param options.onSave Callback that will be called after the query is saved.
* @param options.context Used for tracking. Should identify the context this is called from, like 'explore' or
* @param options.context Used for rendering QueryEditor. Should identify the context this is called from, like 'explore' or
* 'dashboard'.
* @param options.title Default title for the modal, can be overridden by the query title.
*/
@@ -46,8 +47,9 @@ export type QueryLibraryContextType = {
* Returns a predefined small button that can be used to save a query to the library.
* @param query
*/
renderSaveQueryButton: (query: DataQuery) => ReactNode;
renderSaveQueryButton: (query: DataQuery, app?: CoreApp) => ReactNode;
queryLibraryEnabled: boolean;
context: string;
};
export const QueryLibraryContext = createContext<QueryLibraryContextType>({
@@ -63,6 +65,7 @@ export const QueryLibraryContext = createContext<QueryLibraryContextType>({
},
queryLibraryEnabled: false,
context: 'unknown',
});
export function useQueryLibraryContext() {
@@ -17,6 +17,7 @@ export function QueryLibraryContextProviderMock(props: PropsWithChildren<Props>)
closeAddQueryModal: jest.fn(),
renderSaveQueryButton: jest.fn(),
queryLibraryEnabled: Boolean(props.queryLibraryEnabled),
context: 'explore',
}}
>
{props.children}
@@ -22,7 +22,7 @@ export const RichHistoryAddToLibrary = ({ query }: Props) => {
variant="secondary"
aria-label={buttonLabel}
onClick={() => {
openAddQueryModal(query, { onSave: () => setHasBeenSaved(true), context: 'richHistory' });
openAddQueryModal(query, { onSave: () => setHasBeenSaved(true), context: 'rich-history' });
}}
>
{buttonLabel}
@@ -1,6 +1,6 @@
import { css } from '@emotion/css';
import { GrafanaTheme2 } from '@grafana/data';
import { CoreApp, GrafanaTheme2 } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { Trans, t } from '@grafana/i18n';
import { ToolbarButton, useTheme2 } from '@grafana/ui';
@@ -76,7 +76,11 @@ export function SecondaryActions({
data-testid={selectors.pages.Explore.General.addFromQueryLibrary}
aria-label={t('explore.secondary-actions.add-from-query-library', 'Add query from library')}
variant="canvas"
onClick={() => openQueryLibraryDrawer(activeDatasources, onSelectQueryFromLibrary)}
onClick={() =>
openQueryLibraryDrawer(activeDatasources, onSelectQueryFromLibrary, {
context: CoreApp.Explore,
})
}
icon="plus"
>
<Trans i18nKey="explore.secondary-actions.add-from-query-library">Add query from library</Trans>
@@ -380,7 +380,7 @@ export class QueryEditorRow<TQuery extends DataQuery> extends PureComponent<Prop
/>
)}
{this.renderExtraActions()}
<MaybeQueryLibrarySaveButton query={query} />
<MaybeQueryLibrarySaveButton query={query} app={this.props.app} />
<QueryOperationAction
title={t('query-operation.header.duplicate-query', 'Duplicate query')}
icon="copy"
@@ -392,6 +392,7 @@ export class QueryEditorRow<TQuery extends DataQuery> extends PureComponent<Prop
onQueryReplacedFromLibrary?.();
onReplace?.(query);
}}
app={this.props.app}
/>
{!hideHideQueryButton ? (
<QueryOperationToggleAction
@@ -528,24 +529,26 @@ export function filterPanelDataToQuery(data: PanelData, refId: string): PanelDat
}
// Will render anything only if query library is enabled
function MaybeQueryLibrarySaveButton(props: { query: DataQuery }) {
function MaybeQueryLibrarySaveButton(props: { query: DataQuery; app?: CoreApp }) {
const { renderSaveQueryButton } = useQueryLibraryContext();
return renderSaveQueryButton(props.query);
return renderSaveQueryButton(props.query, props.app);
}
interface ReplaceQueryFromLibraryProps<TQuery extends DataQuery> {
datasourceFilters: string[];
onSelectQuery: (query: DataQuery) => void;
app?: CoreApp;
}
function ReplaceQueryFromLibrary<TQuery extends DataQuery>({
datasourceFilters,
onSelectQuery,
app,
}: ReplaceQueryFromLibraryProps<TQuery>) {
const { openDrawer, queryLibraryEnabled } = useQueryLibraryContext();
const onReplaceQueryFromLibrary = () => {
openDrawer(datasourceFilters, onSelectQuery, { isReplacingQuery: true });
openDrawer(datasourceFilters, onSelectQuery, { isReplacingQuery: true, context: app });
};
return queryLibraryEnabled ? (