QueryLibrary: Change context params (#109294)
This commit is contained in:
+6
-2
@@ -394,8 +394,12 @@ export function PanelDataQueriesTabRendered({ model }: SceneComponentProps<Panel
|
||||
<Button
|
||||
icon="plus"
|
||||
onClick={() =>
|
||||
openQueryLibraryDrawer(getDatasourceNames(datasource, queries), onSelectQueryFromLibrary, {
|
||||
context: CoreApp.PanelEditor,
|
||||
openQueryLibraryDrawer({
|
||||
datasourceFilters: getDatasourceNames(datasource, queries),
|
||||
onSelectQuery: onSelectQueryFromLibrary,
|
||||
options: {
|
||||
context: CoreApp.PanelEditor,
|
||||
},
|
||||
})
|
||||
}
|
||||
variant="secondary"
|
||||
|
||||
@@ -3,7 +3,14 @@ import { createContext, ReactNode, useContext } from 'react';
|
||||
import { CoreApp } from '@grafana/data';
|
||||
import { DataQuery } from '@grafana/schema';
|
||||
|
||||
import { OnSelectQueryType } from './types';
|
||||
import { OnSelectQueryType, QueryTemplate } from './types';
|
||||
|
||||
export type QueryLibraryDrawerOptions = {
|
||||
datasourceFilters?: string[];
|
||||
onSelectQuery?: OnSelectQueryType;
|
||||
options?: { isReplacingQuery?: boolean; onSave?: () => void; context?: string; highlightQuery?: string };
|
||||
query?: DataQuery;
|
||||
};
|
||||
|
||||
/**
|
||||
* Context with state and action to interact with Query Library. The Query Library feature consists of a drawer
|
||||
@@ -16,36 +23,15 @@ export type QueryLibraryContextType = {
|
||||
/**
|
||||
* Opens a drawer with query library.
|
||||
* @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 onSelectQuery Callback to be called when a query is selected from the library.
|
||||
* @param options.context Used for QueryEditor. Should identify the context this is called from, like 'explore' or
|
||||
* 'dashboard'.
|
||||
* @param newQuery New query to be added to the library.
|
||||
*/
|
||||
openDrawer: (
|
||||
datasourceFilters: string[],
|
||||
onSelectQuery: OnSelectQueryType,
|
||||
options?: {
|
||||
isReplacingQuery?: boolean;
|
||||
context?: string;
|
||||
highlightQuery?: string;
|
||||
}
|
||||
) => void;
|
||||
openDrawer: (options: QueryLibraryDrawerOptions) => void;
|
||||
closeDrawer: () => void;
|
||||
isDrawerOpen: boolean;
|
||||
|
||||
/**
|
||||
* 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 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.
|
||||
*/
|
||||
openAddQueryModal: (
|
||||
query: DataQuery,
|
||||
options?: { onSave?: () => void; context?: string; title?: string; isDuplicating?: boolean }
|
||||
) => void;
|
||||
closeAddQueryModal: () => void;
|
||||
onSave?: () => void;
|
||||
|
||||
/**
|
||||
* Returns a predefined small button that can be used to save a query to the library.
|
||||
@@ -55,10 +41,12 @@ export type QueryLibraryContextType = {
|
||||
query: DataQuery,
|
||||
app?: CoreApp,
|
||||
queryLibraryRef?: string,
|
||||
onUpdateSuccess?: () => void
|
||||
onUpdateSuccess?: () => void,
|
||||
onSelectQuery?: (query: DataQuery) => void
|
||||
) => ReactNode;
|
||||
queryLibraryEnabled: boolean;
|
||||
context: string;
|
||||
setNewQuery: (query?: QueryTemplate) => void;
|
||||
};
|
||||
|
||||
export const QueryLibraryContext = createContext<QueryLibraryContextType>({
|
||||
@@ -66,8 +54,8 @@ export const QueryLibraryContext = createContext<QueryLibraryContextType>({
|
||||
closeDrawer: () => {},
|
||||
isDrawerOpen: false,
|
||||
|
||||
openAddQueryModal: () => {},
|
||||
closeAddQueryModal: () => {},
|
||||
setNewQuery: () => {},
|
||||
onSave: () => {},
|
||||
|
||||
renderSaveQueryButton: () => {
|
||||
return null;
|
||||
|
||||
@@ -13,11 +13,10 @@ export function QueryLibraryContextProviderMock(props: PropsWithChildren<Props>)
|
||||
openDrawer: jest.fn(),
|
||||
closeDrawer: jest.fn(),
|
||||
isDrawerOpen: false,
|
||||
openAddQueryModal: jest.fn(),
|
||||
closeAddQueryModal: jest.fn(),
|
||||
renderSaveQueryButton: jest.fn(),
|
||||
queryLibraryEnabled: Boolean(props.queryLibraryEnabled),
|
||||
context: 'explore',
|
||||
setNewQuery: jest.fn(),
|
||||
}}
|
||||
>
|
||||
{props.children}
|
||||
|
||||
@@ -1,3 +1,25 @@
|
||||
import { DataQuery } from '@grafana/schema';
|
||||
import { DataQuery, DataSourceRef } from '@grafana/schema';
|
||||
|
||||
export type User = {
|
||||
uid: string;
|
||||
displayName?: string;
|
||||
avatarUrl?: string;
|
||||
};
|
||||
|
||||
export type OnSelectQueryType = (query: DataQuery) => void;
|
||||
|
||||
export type QueryTemplate = {
|
||||
query: DataQuery;
|
||||
datasourceName?: string;
|
||||
title?: string;
|
||||
description?: string;
|
||||
tags?: string[];
|
||||
isLocked?: boolean;
|
||||
isVisible?: boolean;
|
||||
queryText?: string;
|
||||
datasourceRef?: DataSourceRef | null;
|
||||
datasourceType?: string;
|
||||
createdAtTimestamp?: number;
|
||||
user?: User;
|
||||
uid?: string;
|
||||
};
|
||||
|
||||
@@ -107,9 +107,12 @@ export const QueryRows = ({ exploreId, isOpen, changeCompactMode }: Props) => {
|
||||
|
||||
// Open drawer with the original query highlighted
|
||||
if (originalQueryRef) {
|
||||
openDrawer([], () => {}, {
|
||||
context: 'explore',
|
||||
highlightQuery: originalQueryRef,
|
||||
openDrawer({
|
||||
datasourceFilters: [],
|
||||
options: {
|
||||
context: 'explore',
|
||||
highlightQuery: originalQueryRef,
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
import { useState } from 'react';
|
||||
|
||||
import { t } from '@grafana/i18n';
|
||||
import { reportInteraction } from '@grafana/runtime';
|
||||
import { DataQuery } from '@grafana/schema';
|
||||
import { Button } from '@grafana/ui';
|
||||
import { useDispatch, useSelector } from 'app/types/store';
|
||||
|
||||
import { useQueryLibraryContext } from '../QueryLibrary/QueryLibraryContext';
|
||||
import { changeQueries } from '../state/query';
|
||||
import { selectExploreDSMaps } from '../state/selectors';
|
||||
|
||||
type Props = {
|
||||
query: DataQuery;
|
||||
@@ -12,7 +16,17 @@ type Props = {
|
||||
|
||||
export const RichHistoryAddToLibrary = ({ query }: Props) => {
|
||||
const [hasBeenSaved, setHasBeenSaved] = useState(false);
|
||||
const { openAddQueryModal, queryLibraryEnabled } = useQueryLibraryContext();
|
||||
const { openDrawer, queryLibraryEnabled } = useQueryLibraryContext();
|
||||
const dispatch = useDispatch();
|
||||
const exploreActiveDS = useSelector(selectExploreDSMaps);
|
||||
const exploreId = exploreActiveDS.exploreToDS[0]?.exploreId;
|
||||
|
||||
const onSelectQuery = (newQuery: DataQuery) => {
|
||||
reportInteraction('grafana_explore_query_replaced_from_library');
|
||||
if (exploreId) {
|
||||
dispatch(changeQueries({ exploreId, queries: [newQuery] }));
|
||||
}
|
||||
};
|
||||
|
||||
const buttonLabel = t('explore.rich-history-card.add-to-library', 'Add to library');
|
||||
|
||||
@@ -22,7 +36,16 @@ export const RichHistoryAddToLibrary = ({ query }: Props) => {
|
||||
variant="secondary"
|
||||
aria-label={buttonLabel}
|
||||
onClick={() => {
|
||||
openAddQueryModal(query, { onSave: () => setHasBeenSaved(true), context: 'rich-history' });
|
||||
openDrawer({
|
||||
query,
|
||||
onSelectQuery,
|
||||
options: {
|
||||
onSave: () => {
|
||||
setHasBeenSaved(true);
|
||||
},
|
||||
context: 'rich-history',
|
||||
},
|
||||
});
|
||||
}}
|
||||
>
|
||||
{buttonLabel}
|
||||
|
||||
@@ -77,8 +77,10 @@ export function SecondaryActions({
|
||||
aria-label={t('explore.secondary-actions.add-from-query-library', 'Add query from library')}
|
||||
variant="canvas"
|
||||
onClick={() =>
|
||||
openQueryLibraryDrawer(activeDatasources, onSelectQueryFromLibrary, {
|
||||
context: CoreApp.Explore,
|
||||
openQueryLibraryDrawer({
|
||||
datasourceFilters: activeDatasources,
|
||||
onSelectQuery: onSelectQueryFromLibrary,
|
||||
options: { context: CoreApp.Explore },
|
||||
})
|
||||
}
|
||||
icon="plus"
|
||||
|
||||
@@ -56,7 +56,11 @@ export const addQueryHistoryToQueryLibrary = async () => {
|
||||
};
|
||||
|
||||
export const submitAddToQueryLibrary = async ({ title }: { title: string }) => {
|
||||
const input = within(screen.getByRole('dialog')).getByLabelText('Title');
|
||||
const container = screen.getByRole('dialog', {
|
||||
name: /Drawer title/i,
|
||||
});
|
||||
|
||||
const input = within(container).getByRole('textbox', { name: /title/i });
|
||||
await userEvent.type(input, title);
|
||||
const saveButton = screen.getByRole('button', {
|
||||
name: /^save$/i,
|
||||
|
||||
@@ -290,6 +290,11 @@ export class QueryEditorRow<TQuery extends DataQuery> extends PureComponent<Prop
|
||||
this.onToggleHelp();
|
||||
};
|
||||
|
||||
onSelectQueryFromLibrary = (query: DataQuery) => {
|
||||
this.props.onQueryReplacedFromLibrary?.();
|
||||
this.props.onReplace?.(query);
|
||||
};
|
||||
|
||||
renderCollapsedText(): string | null {
|
||||
const { datasource } = this.state;
|
||||
if (datasource?.getQueryDisplayText) {
|
||||
@@ -378,13 +383,7 @@ export class QueryEditorRow<TQuery extends DataQuery> extends PureComponent<Prop
|
||||
};
|
||||
|
||||
renderActions = (props: QueryOperationRowRenderProps) => {
|
||||
const {
|
||||
query,
|
||||
hideHideQueryButton: hideHideQueryButton = false,
|
||||
onReplace,
|
||||
onQueryReplacedFromLibrary,
|
||||
queryLibraryRef,
|
||||
} = this.props;
|
||||
const { query, hideHideQueryButton: hideHideQueryButton = false, queryLibraryRef } = this.props;
|
||||
const { datasource, showingHelp } = this.state;
|
||||
const isHidden = !!query.hide;
|
||||
|
||||
@@ -398,16 +397,14 @@ export class QueryEditorRow<TQuery extends DataQuery> extends PureComponent<Prop
|
||||
query={query}
|
||||
queryLibraryRef={queryLibraryRef}
|
||||
app={this.props.app}
|
||||
onSelectQuery={this.onSelectQueryFromLibrary}
|
||||
onUpdateSuccess={this.onExitQueryLibraryEditingMode}
|
||||
/>
|
||||
|
||||
{!isEditingQueryLibrary && (
|
||||
<ReplaceQueryFromLibrary
|
||||
datasourceFilters={datasource?.name ? [datasource.name] : []}
|
||||
onSelectQuery={(query) => {
|
||||
onQueryReplacedFromLibrary?.();
|
||||
onReplace?.(query);
|
||||
}}
|
||||
onSelectQuery={this.onSelectQueryFromLibrary}
|
||||
app={this.props.app}
|
||||
/>
|
||||
)}
|
||||
@@ -606,9 +603,16 @@ function MaybeQueryLibrarySaveButton(props: {
|
||||
app?: CoreApp;
|
||||
queryLibraryRef?: string;
|
||||
onUpdateSuccess?: () => void;
|
||||
onSelectQuery: (query: DataQuery) => void;
|
||||
}) {
|
||||
const { renderSaveQueryButton } = useQueryLibraryContext();
|
||||
return renderSaveQueryButton(props.query, props.app, props.queryLibraryRef, props.onUpdateSuccess);
|
||||
return renderSaveQueryButton(
|
||||
props.query,
|
||||
props.app,
|
||||
props.queryLibraryRef,
|
||||
props.onUpdateSuccess,
|
||||
props.onSelectQuery
|
||||
);
|
||||
}
|
||||
|
||||
interface ReplaceQueryFromLibraryProps<TQuery extends DataQuery> {
|
||||
@@ -625,7 +629,7 @@ function ReplaceQueryFromLibrary<TQuery extends DataQuery>({
|
||||
const { openDrawer, queryLibraryEnabled } = useQueryLibraryContext();
|
||||
|
||||
const onReplaceQueryFromLibrary = () => {
|
||||
openDrawer(datasourceFilters, onSelectQuery, { isReplacingQuery: true, context: app });
|
||||
openDrawer({ datasourceFilters, onSelectQuery, options: { isReplacingQuery: true, context: app } });
|
||||
};
|
||||
|
||||
return queryLibraryEnabled ? (
|
||||
|
||||
Reference in New Issue
Block a user