From 6ba1699955d7bc4ca2d5ed3cab0d879e7a159ece Mon Sep 17 00:00:00 2001 From: Sergej-Vlasov <37613182+Sergej-Vlasov@users.noreply.github.com> Date: Thu, 4 Sep 2025 09:58:52 +0300 Subject: [PATCH] TabItemEditor: Add tab title edit undo action (#110497) * add undo action for tab title change * add i18n --- .../scene/layout-tabs/TabItemEditor.tsx | 19 ++++++++++++++++++- public/locales/en-US/grafana.json | 3 ++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/public/app/features/dashboard-scene/scene/layout-tabs/TabItemEditor.tsx b/public/app/features/dashboard-scene/scene/layout-tabs/TabItemEditor.tsx index ba88110e4a2..4ec8545fd8f 100644 --- a/public/app/features/dashboard-scene/scene/layout-tabs/TabItemEditor.tsx +++ b/public/app/features/dashboard-scene/scene/layout-tabs/TabItemEditor.tsx @@ -1,4 +1,4 @@ -import { useMemo } from 'react'; +import { useMemo, useRef } from 'react'; import { selectors } from '@grafana/e2e-selectors'; import { Trans, t } from '@grafana/i18n'; @@ -10,6 +10,7 @@ import { SHARED_DASHBOARD_QUERY } from 'app/plugins/datasource/dashboard/constan import { MIXED_DATASOURCE_NAME } from 'app/plugins/datasource/mixed/MixedDataSource'; import { useConditionalRenderingEditor } from '../../conditional-rendering/ConditionalRenderingEditor'; +import { dashboardEditActions } from '../../edit-pane/shared'; import { getQueryRunnerFor, useDashboard } from '../../utils/utils'; import { useLayoutCategory } from '../layouts-shared/DashboardLayoutSelector'; import { useEditPaneInputAutoFocus } from '../layouts-shared/utils'; @@ -69,6 +70,7 @@ export function useEditOptions(model: TabItem, isNewElement: boolean): OptionsPa function TabTitleInput({ tab, isNewElement, id }: { tab: TabItem; isNewElement: boolean; id?: string }) { const { title } = tab.useState(); + const prevTitle = useRef(''); const ref = useEditPaneInputAutoFocus({ autoFocus: isNewElement }); const hasUniqueTitle = tab.hasUniqueTitle(); @@ -85,6 +87,8 @@ function TabTitleInput({ tab, isNewElement, id }: { tab: TabItem; isNewElement: ref={ref} title={t('dashboard.tabs-layout.tab-options.title-option', 'Title')} value={title} + onFocus={() => (prevTitle.current = title || '')} + onBlur={() => editTabTitleAction(tab, title || '', prevTitle.current || '')} onChange={(e) => tab.onChangeTitle(e.currentTarget.value)} /> @@ -139,3 +143,16 @@ function TabRepeatSelect({ tab, id }: { tab: TabItem; id?: string }) { ); } + +function editTabTitleAction(tab: TabItem, title: string, prevTitle: string) { + if (title === prevTitle) { + return; + } + + dashboardEditActions.edit({ + description: t('dashboard.edit-actions.tab-title', 'Change tab title'), + source: tab, + perform: () => tab.onChangeTitle(title), + undo: () => tab.onChangeTitle(prevTitle), + }); +} diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json index 1c55d2791eb..34e8e2709d3 100644 --- a/public/locales/en-US/grafana.json +++ b/public/locales/en-US/grafana.json @@ -4695,7 +4695,8 @@ "paste-panel": "Paste panel", "remove": "Remove {{typeName}}", "row-title": "Change row title", - "switch-layout": "Switch layout" + "switch-layout": "Switch layout", + "tab-title": "Change tab title" }, "edit-pane": { "elements": {