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 fd3776615 fix(topic): reload the paginated inventory after importing 
topics (#4602)
fd3776615 is described below

commit fd3776615644737a31833b3ebd67d04592b47ec0
Author: 烤化の初雪 <[email protected]>
AuthorDate: Mon Sep 21 21:04:24 2026 +0800

    fix(topic): reload the paginated inventory after importing topics (#4602)
    
    After a successful CSV import, `handleImportTopics` in 
`web/src/pages/instance/topic.tsx` prepended the created topics into the local 
`topics` array, deduplicating by name. The inventory is server-paginated, 
though: `totalTopics` is written only by `loadTopicPage`, the table renders a 
single server page, and the header shows that total. The prepend left three 
views of the same data disagreeing — new rows on screen, an unchanged header 
count, an unchanged pagination total — and importi [...]
    
    The success branch now awaits `reloadTopicPage()`, which is what every 
other mutation on the page already does for create, update and single or bulk 
delete. That removes the last place in this file that patched the list locally 
instead of reloading it.
    
    Fixes #4598
---
 .../pages/instance/__tests__/TopicPage.test.tsx    | 29 ++++++++++++++++++++++
 web/src/pages/instance/topic.tsx                   |  7 +++---
 2 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/web/src/pages/instance/__tests__/TopicPage.test.tsx 
b/web/src/pages/instance/__tests__/TopicPage.test.tsx
index 270371f62..f316dcfd9 100644
--- a/web/src/pages/instance/__tests__/TopicPage.test.tsx
+++ b/web/src/pages/instance/__tests__/TopicPage.test.tsx
@@ -930,6 +930,35 @@ describe('TopicPage', () => {
     expect(screen.getAllByText('imported-topic').length).toBeGreaterThan(0);
   });
 
+  it('reloads the paginated inventory after importing topics', async () => {
+    const user = userEvent.setup();
+    const imported: Topic = {
+      ...buildTopics(1)[0],
+      name: 'imported-topic',
+      instanceId: 'instance-proxy-1',
+    };
+    topicServiceMocks.listTopicsPage
+      .mockResolvedValueOnce({ items: [], total: 0, page: 1, size: 20 })
+      .mockResolvedValue({ items: [imported], total: 1, page: 1, size: 20 });
+    topicServiceMocks.importTopics.mockResolvedValue({ topics: [imported], 
failures: [] });
+    instanceServiceMocks.listInstances.mockResolvedValue([selectedInstance]);
+    renderWithProviders('/instance/instance-proxy-1/topic');
+
+    await screen.findByText(/共 0 个 Topic/);
+    const csv = [
+      '"Name","Namespace","Type","Cluster ID","Write Queues","Read 
Queues","Permission","Remark"',
+      
'"imported-topic","ignored","NORMAL","ignored-cluster","4","6","RW","orders"',
+    ].join('\n');
+    await user.upload(screen.getByTestId('topic-import-file'), new File([csv], 
'topics.csv'));
+    await screen.findByText('检测到 1 个 Topic,将通过后端批量导入');
+    await user.click(screen.getByRole('button', { name: '开始导入' }));
+
+    // The authoritative server page decides both the rows and the total: a 
local
+    // patch of the loaded page cannot keep the header and the pagination 
honest.
+    expect(await screen.findByText(/共 1 个 Topic/)).toBeInTheDocument();
+    expect(screen.getAllByText('imported-topic').length).toBeGreaterThan(0);
+  });
+
   it('does not call importTopics when imported topic CSV is invalid or 
duplicated', async () => {
     const user = userEvent.setup();
     instanceServiceMocks.listInstances.mockResolvedValue([selectedInstance]);
diff --git a/web/src/pages/instance/topic.tsx b/web/src/pages/instance/topic.tsx
index d9667e2a9..c883ebd18 100644
--- a/web/src/pages/instance/topic.tsx
+++ b/web/src/pages/instance/topic.tsx
@@ -1281,10 +1281,9 @@ const TopicPageContent = ({
     setImportRows([...nextRows]);
 
     if (createdTopics.length > 0) {
-      setTopics((previous) => {
-        const createdNames = new Set(createdTopics.map((topic) => topic.name));
-        return [...createdTopics, ...previous.filter((topic) => 
!createdNames.has(topic.name))];
-      });
+      // The inventory is server-paginated, so a local prepend leaves the rows,
+      // the header count and the pagination total disagreeing with the server.
+      await reloadTopicPage();
     }
 
     const failedCount = nextRows.filter((row) => row.status === 
'failed').length;

Reply via email to