This is an automated email from the ASF dual-hosted git repository.
lizhimins pushed a commit to branch rocketmq-studio
in repository https://gitbox.apache.org/repos/asf/rocketmq-dashboard.git
The following commit(s) were added to refs/heads/rocketmq-studio by this push:
new 00c5ce1b6 fix(ops): keep the unsaved NameServer selection when the
display language changes (#4818)
00c5ce1b6 is described below
commit 00c5ce1b6cd0b08eb625e15270f7225eb71ec1d0
Author: Apulupie <[email protected]>
AuthorDate: Thu Oct 1 17:24:45 2026 +0800
fix(ops): keep the unsaved NameServer selection when the display language
changes (#4818)
Co-authored-by: Frun1na <[email protected]>
---
web/src/pages/studio/Ops.tsx | 7 ++++-
web/src/pages/studio/__tests__/Ops.test.tsx | 47 +++++++++++++++++++++++++++--
2 files changed, 50 insertions(+), 4 deletions(-)
diff --git a/web/src/pages/studio/Ops.tsx b/web/src/pages/studio/Ops.tsx
index 667877554..5d84e12dc 100644
--- a/web/src/pages/studio/Ops.tsx
+++ b/web/src/pages/studio/Ops.tsx
@@ -82,7 +82,12 @@ const OpsPage: React.FC = () => {
setNamesrvAddrList(data.namesvrAddrList);
setUseVIPChannel(data.useVIPChannel);
setUseTLS(data.useTLS);
- setSelectedNamesrv(data.currentNamesrv);
+ // The effect re-runs when the display language changes (it feeds a
localized error
+ // message); an unsaved selection that is still in the freshly
loaded list must survive
+ // that re-run instead of snapping back to the stored current
NameServer.
+ setSelectedNamesrv((current) =>
+ current && data.namesvrAddrList.includes(current) ? current :
data.currentNamesrv,
+ );
setCurrentNamesrv(data.currentNamesrv);
setConfigurationAvailable(data.configurationAvailable);
setUnavailableReason(data.unavailableReason || '');
diff --git a/web/src/pages/studio/__tests__/Ops.test.tsx
b/web/src/pages/studio/__tests__/Ops.test.tsx
index a6efa1cfd..c0a11e2df 100644
--- a/web/src/pages/studio/__tests__/Ops.test.tsx
+++ b/web/src/pages/studio/__tests__/Ops.test.tsx
@@ -17,14 +17,28 @@
import type { ReactElement } from 'react';
import { beforeAll, beforeEach, describe, expect, it, vi } from 'vitest';
-import { fireEvent, render, screen, waitFor } from '@testing-library/react';
+import { act, fireEvent, render, screen, waitFor } from
'@testing-library/react';
import userEvent from '@testing-library/user-event';
import { App } from 'antd';
-import { LangProvider } from '../../../i18n/LangContext';
+import { LangProvider, useLang } from '../../../i18n/LangContext';
import OpsPage from '../Ops';
-import { addNameSvrAddr, deleteNameSvrAddr, queryOpsHomePage,
updateIsVIPChannel } from '../../../api/ops';
+import {
+ addNameSvrAddr,
+ deleteNameSvrAddr,
+ queryOpsHomePage,
+ updateIsVIPChannel,
+} from '../../../api/ops';
import useAuthStore from '../../../stores/authStore';
+const LanguageSwitch = () => {
+ const { setLang } = useLang();
+ return (
+ <button type="button" onClick={() => setLang('en')}>
+ switch-language
+ </button>
+ );
+};
+
vi.mock('../../../api/ops', () => ({
addNameSvrAddr: vi.fn(),
deleteNameSvrAddr: vi.fn(),
@@ -85,6 +99,33 @@ describe('OpsPage', () => {
expect(screen.getAllByRole('switch')[1]).not.toBeChecked();
});
+ it('keeps the unsaved NameServer selection when the display language
changes', async () => {
+ const user = userEvent.setup();
+ renderWithProviders(
+ <>
+ <LanguageSwitch />
+ <OpsPage />
+ </>,
+ );
+
+ expect(await screen.findByText('127.0.0.1:9876')).toBeInTheDocument();
+ await user.click(screen.getByRole('combobox'));
+ await user.click(
+ await screen.findByText('127.0.0.2:9876', { selector:
'.ant-select-item-option-content' }),
+ );
+
+ await user.click(screen.getByRole('button', { name: 'switch-language' }));
+ // Let every effect triggered by the language change settle before
asserting.
+ await act(async () => {
+ await Promise.resolve();
+ });
+
+ // The selection the user made but did not save must survive the refetch.
+ expect(
+ await screen.findByText('127.0.0.2:9876', { selector:
'.ant-select-selection-item' }),
+ ).toBeInTheDocument();
+ }, 20_000);
+
it('prevents overlapping NameServer mutations', async () => {
vi.mocked(addNameSvrAddr).mockImplementation(() => new Promise(() => {}));
renderWithProviders(<OpsPage />);