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 1172d8597 fix(studio): clear hidden resource selections (#4473)
1172d8597 is described below
commit 1172d859794e5b80011b25874029f988653c161c
Author: beautyarbutin <[email protected]>
AuthorDate: Mon Sep 21 12:04:48 2026 +0800
fix(studio): clear hidden resource selections (#4473)
Row selection survived filter and pagination changes on the consumer group
and
topic pages, so a batch delete could act on rows the operator can no longer
see.
Clear the selection in the search onChange/onSearch, the consumption-mode
filter
and the pagination handler, and add a regression test per page asserting the
batch-delete button disappears once the scope changes.
---
web/src/pages/instance/__tests__/ConsumerPage.test.tsx | 13 +++++++++++++
web/src/pages/instance/__tests__/TopicPage.test.tsx | 14 ++++++++++++++
web/src/pages/instance/consumer.tsx | 8 +++++++-
web/src/pages/instance/topic.tsx | 5 +++++
4 files changed, 39 insertions(+), 1 deletion(-)
diff --git a/web/src/pages/instance/__tests__/ConsumerPage.test.tsx
b/web/src/pages/instance/__tests__/ConsumerPage.test.tsx
index c05895135..7f6722d11 100644
--- a/web/src/pages/instance/__tests__/ConsumerPage.test.tsx
+++ b/web/src/pages/instance/__tests__/ConsumerPage.test.tsx
@@ -312,6 +312,19 @@ describe('Consumer page', () => {
});
});
+ it('clears selected consumer groups when the search scope changes', async ()
=> {
+ const user = userEvent.setup();
+ renderWithProviders(<ConsumerPage />);
+
+ const row = await screen.findByRole('row', { name: /remote-cg/ });
+ await user.click(within(row).getByRole('checkbox'));
+ expect(screen.getByRole('button', { name: /删除 \(1\)$/
})).toBeInTheDocument();
+
+ await user.type(screen.getByPlaceholderText('搜索 Group 名称或 Topic'),
'missing-group');
+
+ expect(screen.queryByRole('button', { name: /删除 \(1\)$/
})).not.toBeInTheDocument();
+ });
+
afterEach(() => {
cleanup();
Modal.destroyAll();
diff --git a/web/src/pages/instance/__tests__/TopicPage.test.tsx
b/web/src/pages/instance/__tests__/TopicPage.test.tsx
index 9b8b21f76..e7d4c27c3 100644
--- a/web/src/pages/instance/__tests__/TopicPage.test.tsx
+++ b/web/src/pages/instance/__tests__/TopicPage.test.tsx
@@ -730,6 +730,20 @@ describe('TopicPage', () => {
});
});
+ it('clears selected topics when the search scope changes', async () => {
+ const user = userEvent.setup();
+ renderWithProviders();
+
+ const row = await screen.findByRole('row', { name: /topic-01/ });
+ await user.click(within(row).getByRole('checkbox'));
+ expect(screen.getByRole('button', { name: /删除 \(1\)$/
})).toBeInTheDocument();
+
+ await user.type(screen.getByPlaceholderText('搜索 Topic 名称'),
'missing-topic');
+ await user.keyboard('{Enter}');
+
+ expect(screen.queryByRole('button', { name: /删除 \(1\)$/
})).not.toBeInTheDocument();
+ });
+
it('moves back from an emptied last topic page after batch deletion', async
() => {
const user = userEvent.setup();
const firstPage = buildTopics(20);
diff --git a/web/src/pages/instance/consumer.tsx
b/web/src/pages/instance/consumer.tsx
index f34471d1f..93abe2aad 100644
--- a/web/src/pages/instance/consumer.tsx
+++ b/web/src/pages/instance/consumer.tsx
@@ -1429,10 +1429,12 @@ const ConsumerPageContent = ({
allowClear
value={search}
onChange={(e) => {
+ setSelectedRowKeys([]);
setSearch(e.target.value);
setPage(1);
}}
onSearch={(value) => {
+ setSelectedRowKeys([]);
setSearch(value);
setPage(1);
}}
@@ -1441,7 +1443,10 @@ const ConsumerPageContent = ({
/>
<Select
value={modeFilter}
- onChange={setModeFilter}
+ onChange={(value) => {
+ setSelectedRowKeys([]);
+ setModeFilter(value);
+ }}
style={{ width: 140 }}
options={[
{ value: 'ALL', label: '全部模式' },
@@ -1551,6 +1556,7 @@ const ConsumerPageContent = ({
showTotal: (total) => `共 ${total} 个 Group`,
pageSizeOptions: [10, 20, 50, 100],
onChange: (nextPage, nextPageSize) => {
+ setSelectedRowKeys([]);
setPage(nextPage);
setPageSize(nextPageSize);
},
diff --git a/web/src/pages/instance/topic.tsx b/web/src/pages/instance/topic.tsx
index 831e4df9a..4252332cb 100644
--- a/web/src/pages/instance/topic.tsx
+++ b/web/src/pages/instance/topic.tsx
@@ -1496,6 +1496,7 @@ const TopicPage = () => {
<InstanceSelect
value={selectedInstanceId || undefined}
onChange={(value) => {
+ setSelectedRowKeys([]);
resetTablePage();
selectInstance(value);
}}
@@ -1509,11 +1510,13 @@ const TopicPage = () => {
onSearch={(value) => {
// Store the trimmed term so the client-side row filter matches
what the
// server query used; padded input would otherwise filter out
every row.
+ setSelectedRowKeys([]);
setSearchText(value.trim());
resetTablePage();
}}
onChange={(e) => {
if (!e.target.value) {
+ setSelectedRowKeys([]);
setSearchText('');
resetTablePage();
}
@@ -1523,6 +1526,7 @@ const TopicPage = () => {
placeholder="类型筛选"
value={typeFilter}
onChange={(value) => {
+ setSelectedRowKeys([]);
setTypeFilter(value);
resetTablePage();
}}
@@ -1641,6 +1645,7 @@ const TopicPage = () => {
showSizeChanger: true,
showTotal: (t) => `共 ${t} 条`,
onChange: (page, pageSize) => {
+ setSelectedRowKeys([]);
setTablePage(page);
setTablePageSize(pageSize);
},