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;