UI: Add support to duplicate query panel

Signed-off-by: anubhav21sharma <anubhav21sharma@gmail.com>
This commit is contained in:
anubhav21sharma 2025-12-18 11:54:27 +00:00
parent 45cf485168
commit 4f04aaccc3
3 changed files with 27 additions and 0 deletions

View file

@ -58,6 +58,7 @@ import { lintKeymap } from "@codemirror/lint";
import {
IconAlignJustified,
IconBinaryTree,
IconCopy,
IconDotsVertical,
IconSearch,
IconTerminal,
@ -121,6 +122,7 @@ interface ExpressionInputProps {
executeQuery: (expr: string) => void;
treeShown: boolean;
setShowTree: (showTree: boolean) => void;
duplicatePanel: (expr: string) => void;
removePanel: () => void;
}
@ -128,6 +130,7 @@ const ExpressionInput: FC<ExpressionInputProps> = ({
initialExpr,
metricNames,
executeQuery,
duplicatePanel,
removePanel,
treeShown,
setShowTree,
@ -250,6 +253,12 @@ const ExpressionInput: FC<ExpressionInputProps> = ({
>
{treeShown ? "Hide" : "Show"} tree view
</Menu.Item>
<Menu.Item
leftSection={<IconCopy style={menuIconStyle} />}
onClick={() => duplicatePanel(expr)}
>
Duplicate query
</Menu.Item>
<Menu.Item
color="red"
leftSection={<IconTrash style={menuIconStyle} />}

View file

@ -23,6 +23,7 @@ import { FC, Suspense, useCallback, useMemo, useState } from "react";
import { useAppDispatch, useAppSelector } from "../../state/hooks";
import {
addQueryToHistory,
duplicatePanel,
GraphDisplayMode,
GraphResolution,
removePanel,
@ -111,6 +112,9 @@ const QueryPanel: FC<PanelProps> = ({ idx, metricNames }) => {
setSelectedNode(null);
}
}}
duplicatePanel={(expr: string) => {
dispatch(duplicatePanel({ idx, expr }));
}}
removePanel={() => {
dispatch(removePanel(idx));
}}

View file

@ -115,6 +115,19 @@ export const queryPageSlice = createSlice({
state.panels.push(newDefaultPanel());
updateURL(state.panels);
},
duplicatePanel: (
state,
{ payload }: PayloadAction<{ idx: number; expr: string }>
) => {
const newPanel = {
...state.panels[payload.idx],
id: randomId(),
expr: payload.expr,
};
// Insert the duplicated panel just below the original panel.
state.panels.splice(payload.idx + 1, 0, newPanel);
updateURL(state.panels);
},
removePanel: (state, { payload }: PayloadAction<number>) => {
state.panels.splice(payload, 1);
updateURL(state.panels);
@ -153,6 +166,7 @@ export const {
setPanels,
addPanel,
removePanel,
duplicatePanel,
setExpr,
addQueryToHistory,
setShowTree,