implement onCancelEditingQuery library

This commit is contained in:
alexandra vargas
2025-07-18 14:52:12 +02:00
parent 128481735c
commit 3a33297885
6 changed files with 62 additions and 26 deletions
@@ -46,7 +46,7 @@ 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, queryRef?: string) => ReactNode;
queryLibraryEnabled: boolean;
};
@@ -11,6 +11,7 @@ import { QueryEditorRows } from '../query/components/QueryEditorRows';
import { ContentOutlineItem } from './ContentOutline/ContentOutlineItem';
import { changeDatasource } from './state/datasource';
import { updateQueryRefAction } from './state/explorePane';
import { changeQueries, runQueries } from './state/query';
import { getExploreItemSelector } from './state/selectors';
@@ -86,6 +87,10 @@ export const QueryRows = ({ exploreId }: Props) => {
reportInteraction('grafana_query_row_toggle', queryStatus === undefined ? {} : { queryEnabled: queryStatus });
};
const onCancelQueryLibraryEdit = useCallback(() => {
dispatch(updateQueryRefAction({ exploreId, queryRef: undefined }));
}, [dispatch, exploreId]);
return (
<QueryEditorRows
dsSettings={dsSettings}
@@ -103,6 +108,7 @@ export const QueryRows = ({ exploreId }: Props) => {
history={history}
eventBus={eventBridge}
queryRef={queryRef}
onCancelQueryLibraryEdit={onCancelQueryLibraryEdit}
queryRowWrapper={(children, refId) => (
<ContentOutlineItem
title={refId}
@@ -13,7 +13,8 @@ export function getUrlStateFromPaneState(pane: ExploreItemState): ExploreUrlStat
range: toURLRange(pane.range.raw),
// don't include panelsState in the url unless a piece of state is actually set
panelsState: pruneObject(pane.panelsState),
queryRef: pane.queryRef || undefined,
// don't include queryRef in the url unless it's actually set
...(pane.queryRef && { queryRef: pane.queryRef }),
};
}
@@ -5,7 +5,7 @@ import { MutableRefObject } from 'react';
import { UrlQueryMap } from '@grafana/data';
import { LocationService } from '@grafana/runtime';
import { changeDatasource } from 'app/features/explore/state/datasource';
import { changePanelsStateAction } from 'app/features/explore/state/explorePane';
import { changePanelsStateAction, updateQueryRefAction } from 'app/features/explore/state/explorePane';
import { splitClose, splitOpen } from 'app/features/explore/state/main';
import { runQueries } from 'app/features/explore/state/query';
import { changeRangeAction } from 'app/features/explore/state/time';
@@ -37,6 +37,7 @@ export function syncToURLPredicate(paused: MutableRefObject<boolean>, action: Ac
changeRangeAction.type,
changePanelsStateAction.type,
changeDatasource.fulfilled.type,
updateQueryRefAction.type,
].includes(action.type) && !paused.current
);
}
@@ -22,7 +22,7 @@ import { selectors } from '@grafana/e2e-selectors';
import { Trans, t } from '@grafana/i18n';
import { getDataSourceSrv, renderLimitedComponents, reportInteraction, usePluginComponents } from '@grafana/runtime';
import { DataQuery } from '@grafana/schema';
import { Badge, ErrorBoundaryAlert, List } from '@grafana/ui';
import { Badge, Divider, ErrorBoundaryAlert, List } from '@grafana/ui';
import { OperationRowHelp } from 'app/core/components/QueryOperationRow/OperationRowHelp';
import {
QueryOperationAction,
@@ -68,6 +68,7 @@ export interface Props<TQuery extends DataQuery> {
collapsable?: boolean;
hideRefId?: boolean;
queryRef?: string;
onCancelQueryLibraryEdit?: () => void;
}
interface State<TQuery extends DataQuery> {
@@ -232,6 +233,13 @@ export class QueryEditorRow<TQuery extends DataQuery> extends PureComponent<Prop
}
};
onCancelQueryLibraryEdit = () => {
const { onCancelQueryLibraryEdit } = this.props;
if (onCancelQueryLibraryEdit) {
onCancelQueryLibraryEdit();
}
};
onCopyQuery = () => {
const { query, onAddQuery, onQueryCopied } = this.props;
const copy = cloneDeep(query);
@@ -327,7 +335,7 @@ export class QueryEditorRow<TQuery extends DataQuery> extends PureComponent<Prop
renderQueryLibraryBadge = () => {
const { queryRef } = this.props;
return <QueryLibraryBadgeWrapper queryRef={queryRef} />;
return <QueryLibraryBadgeWrapper key="query-library-badge-wrapper" queryRef={queryRef} />;
};
renderExtraActions = () => {
@@ -368,11 +376,13 @@ export class QueryEditorRow<TQuery extends DataQuery> extends PureComponent<Prop
hideHideQueryButton: hideHideQueryButton = false,
onReplace,
onQueryReplacedFromLibrary,
queryRef,
} = this.props;
const { datasource, showingHelp } = this.state;
const isHidden = !!query.hide;
const hasEditorHelp = datasource?.components?.QueryEditorHelp;
const isEditingQueryLibraryRef = queryRef !== undefined;
return (
<>
@@ -385,19 +395,33 @@ export class QueryEditorRow<TQuery extends DataQuery> extends PureComponent<Prop
/>
)}
{this.renderExtraActions()}
<MaybeQueryLibrarySaveButton query={query} />
<QueryOperationAction
title={t('query-operation.header.duplicate-query', 'Duplicate query')}
icon="copy"
onClick={this.onCopyQuery}
/>
<ReplaceQueryFromLibrary
datasourceFilters={datasource?.name ? [datasource.name] : []}
onSelectQuery={(query) => {
onQueryReplacedFromLibrary?.();
onReplace?.(query);
}}
/>
<MaybeQueryLibrarySaveButton query={query} queryRef={queryRef} />
{isEditingQueryLibraryRef && (
<>
<QueryOperationAction
title={t('query-operation.header.cancel-query-library-edit', 'Cancel editing from library')}
icon="times"
onClick={this.onCancelQueryLibraryEdit}
/>
<Divider direction="vertical" spacing={0} />
</>
)}
{!isEditingQueryLibraryRef && (
<QueryOperationAction
title={t('query-operation.header.duplicate-query', 'Duplicate query')}
icon="copy"
onClick={this.onCopyQuery}
/>
)}
{!isEditingQueryLibraryRef && (
<ReplaceQueryFromLibrary
datasourceFilters={datasource?.name ? [datasource.name] : []}
onSelectQuery={(query) => {
onQueryReplacedFromLibrary?.();
onReplace?.(query);
}}
/>
)}
{!hideHideQueryButton ? (
<QueryOperationToggleAction
dataTestId={selectors.components.QueryEditorRow.actionButton('Hide response')}
@@ -411,11 +435,13 @@ export class QueryEditorRow<TQuery extends DataQuery> extends PureComponent<Prop
onClick={this.onHideQuery}
/>
) : null}
<QueryOperationAction
title={t('query-operation.header.remove-query', 'Remove query')}
icon="trash-alt"
onClick={this.onRemoveQuery}
/>
{!isEditingQueryLibraryRef && (
<QueryOperationAction
title={t('query-operation.header.remove-query', 'Remove query')}
icon="trash-alt"
onClick={this.onRemoveQuery}
/>
)}
</>
);
};
@@ -499,7 +525,6 @@ export function QueryLibraryBadgeWrapper(props: { queryRef?: string }) {
return (
<Badge
key="query-library-badge"
color="blue"
icon="book"
text={t('query-operation.query-library.from-library', 'Editing From Query Library')}
@@ -552,9 +577,9 @@ 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; queryRef?: string }) {
const { renderSaveQueryButton } = useQueryLibraryContext();
return renderSaveQueryButton(props.query);
return renderSaveQueryButton(props.query, props.queryRef);
}
interface ReplaceQueryFromLibraryProps<TQuery extends DataQuery> {
@@ -41,6 +41,7 @@ export interface Props {
onQueryReplacedFromLibrary?: () => void;
queryRowWrapper?: (children: ReactNode, refId: string) => ReactNode;
queryRef?: string;
onCancelQueryLibraryEdit?: () => void;
}
export class QueryEditorRows extends PureComponent<Props> {
@@ -177,6 +178,7 @@ export class QueryEditorRows extends PureComponent<Props> {
onQueryReplacedFromLibrary,
queryRowWrapper,
queryRef,
onCancelQueryLibraryEdit,
} = this.props;
return (
@@ -215,6 +217,7 @@ export class QueryEditorRows extends PureComponent<Props> {
history={history}
eventBus={eventBus}
queryRef={queryRef}
onCancelQueryLibraryEdit={onCancelQueryLibraryEdit}
/>
);