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 4323fcabb fix(producer): keep the picked scope when the display 
language changes (#4890)
4323fcabb is described below

commit 4323fcabb678139cb8d2ea9840fc59efbe3cbda7
Author: 烤化の初雪 <[email protected]>
AuthorDate: Thu Oct 1 17:25:24 2026 +0800

    fix(producer): keep the picked scope when the display language changes 
(#4890)
    
    The topic-list effect in `Producer.tsx` depends on `fetchTopicFailedMessage`
    (`t('producer.fetchTopicFailed')`), a value of the current language, and 
its body
    started with an unconditional
    `form.setFieldsValue({ selectedTopic: undefined, producerGroup: undefined 
})`.
    Switching the display language therefore re-ran the effect and cleared the 
topic
    and producer-group the operator had just picked, leaving the page unable to
    query until both were selected again — the third occurrence of this pattern,
    after `BrokerCluster` (#4590) and `Ops` (#4818).
    
    The reset now happens only for the instance it was written for. A ref 
records the
    instance the form was cleared for, so the instance transition (initial
    auto-selection or a manual switch) still clears the scope, while the extra 
effect
    run that a language change causes leaves the selection untouched. The topic 
list
    itself is still reloaded, so the localized error message keeps following the
    language.
    
    Co-authored-by: unbridled-41 
<[email protected]>
---
 web/src/pages/studio/Producer.tsx                | 11 ++++-
 web/src/pages/studio/__tests__/Producer.test.tsx | 51 +++++++++++++++++++++++-
 2 files changed, 60 insertions(+), 2 deletions(-)

diff --git a/web/src/pages/studio/Producer.tsx 
b/web/src/pages/studio/Producer.tsx
index dc85973ce..6177d120c 100644
--- a/web/src/pages/studio/Producer.tsx
+++ b/web/src/pages/studio/Producer.tsx
@@ -94,6 +94,8 @@ const ProducerPage = () => {
 
   const producerGroupRequestIdRef = useRef(0);
   const selectedTopic = Form.useWatch('selectedTopic', form);
+  // Instance whose scope the form was last cleared for; see the topic-list 
effect below.
+  const lastResetInstanceRef = useRef<string | undefined>(undefined);
 
   useEffect(() => {
     let cancelled = false;
@@ -150,7 +152,14 @@ const ProducerPage = () => {
       };
     }
 
-    form.setFieldsValue({ selectedTopic: undefined, producerGroup: undefined 
});
+    // The topic list belongs to the instance, so the picked topic and 
producer group are
+    // dropped when the instance changes. The effect also re-runs when the 
display
+    // language changes (it feeds a localized error message), and clearing the 
form there
+    // too silently discarded the scope the operator had just selected.
+    if (lastResetInstanceRef.current !== selectedInstanceId) {
+      lastResetInstanceRef.current = selectedInstanceId;
+      form.setFieldsValue({ selectedTopic: undefined, producerGroup: undefined 
});
+    }
 
     void fetchTopicList(selectedInstanceId)
       .then((topics) => {
diff --git a/web/src/pages/studio/__tests__/Producer.test.tsx 
b/web/src/pages/studio/__tests__/Producer.test.tsx
index b54ddb2cf..b4b33736d 100644
--- a/web/src/pages/studio/__tests__/Producer.test.tsx
+++ b/web/src/pages/studio/__tests__/Producer.test.tsx
@@ -19,7 +19,7 @@ import { afterEach, beforeAll, beforeEach, describe, expect, 
it, vi } from 'vite
 import { fireEvent, render, screen, waitFor, within } 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 ProducerPage from '../Producer';
 import {
   type ProducerConnection,
@@ -64,6 +64,15 @@ const renderWithProviders = (ui: React.ReactElement) => {
   );
 };
 
+const LanguageSwitch = () => {
+  const { setLang } = useLang();
+  return (
+    <button type="button" onClick={() => setLang('en')}>
+      switch-language
+    </button>
+  );
+};
+
 const producerResult = (connectionSet: ProducerConnection[]): 
ProducerConnectionResult => ({
   connectionSet,
   complete: true,
@@ -638,4 +647,44 @@ describe('ProducerPage', () => {
 
     expect(fetchProducerGroups).not.toHaveBeenCalled();
   });
+
+  it('keeps the picked topic and producer group when the display language 
changes', async () => {
+    const user = userEvent.setup();
+    render(
+      <App>
+        <LangProvider>
+          <LanguageSwitch />
+          <ProducerPage />
+        </LangProvider>
+      </App>,
+    );
+
+    await waitFor(() => expect(fetchTopicList).toHaveBeenCalledTimes(1));
+    const [, topicSelect, groupInput] = screen.getAllByRole('combobox');
+    fireEvent.mouseDown(topicSelect.parentElement!);
+    await user.click(
+      await screen.findByText('order-events', { selector: 
'.ant-select-item-option-content' }),
+    );
+    await user.type(groupInput, 'order-producer');
+
+    // The topic-list effect re-runs on a language change (it feeds a 
localized error
+    // message) and it used to clear both inputs on every run, so picking a 
language
+    // silently discarded the operator's query scope.
+    await user.click(screen.getByRole('button', { name: 'switch-language' }));
+
+    expect(
+      screen.getByText('order-events', { selector: 
'.ant-select-selection-item' }),
+    ).toBeInTheDocument();
+    expect(screen.getAllByRole('combobox')[2]).toHaveValue('order-producer');
+
+    // The preserved scope is still the one the query runs with.
+    await user.click(screen.getByRole('button', { name: /Search/ }));
+    await waitFor(() => {
+      expect(queryProducerConnection).toHaveBeenCalledWith(
+        'instance-1',
+        'order-events',
+        'order-producer',
+      );
+    });
+  });
 });

Reply via email to