unbridled-41 opened a new pull request, #5070:
URL: https://github.com/apache/rocketmq-dashboard/pull/5070
## Problem
The AI history modal (会话历史) keeps its ticked rows when the operator changes
the page, the search or the active/archived scope, so the batch delete acts on
conversations that are no longer on screen.
`ConversationListPanel` owns `selectedRowKeys`
(`ConversationListModal.tsx:170`) and only ever prunes the keys whose delete
failed (`:224`). Nothing clears them on a scope change, and the toolbar's
destructive button is rendered on the selection alone (`:427`), confirming with
`remove(selectedRowKeys.map(Number))` (`:434`) — while antd renders the
checkbox column for the rows it is given (`rowSelection={{ selectedRowKeys,
onChange: setSelectedRowKeys }}`, `:483`).
Concretely: tick row A on page 1, click page 2. Page 2 shows nothing ticked,
but the toolbar still reads `删除 (1)`; confirming it issues `DELETE
/api/ai/conversations/{A}` for a row on another page. The delete is a hard
delete — it stops any active run, clears three tables and unlinks the agent
workspace.
The component's own comment two lines above that button states the property
the code was breaking: "the checkbox column antd renders selects the current
page only — so the two never disagree about what 'all' means" (`:424-426`).
## Evidence
Pre-fix, on base `a562601d`, with the three new tests in place and only
`ConversationListModal.tsx` at its base revision:
```
$ cd web && npx vitest run
src/pages/ai/components/__tests__/ConversationListModal.test.tsx
× dropsTheSelectionWhenThePageChangesTest
× dropsTheSelectionWhenTheSearchChangesTest
× dropsTheSelectionWhenTheScopeChangesTest
Test Files 1 failed (1)
Tests 3 failed | 19 passed (22)
FAIL … > dropsTheSelectionWhenThePageChangesTest
Error: expect(element).not.toBeInTheDocument()
expected document not to contain element, found <button
class="ant-btn … ant-btn-dangerous …"
data-testid="ai-conversation-selected-delete"
type="button"><span>删除 (1)
```
Reachability is a plain user path on `/ai` → 历史: tick a row, page (or type a
search, or switch to 已归档), press the red button.
## Root cause
The selection survived a change of query identity. The panel clears it after
a delete and for the conversation it knows left the list, but the three
handlers that move the window — `onSearch` (`:411`), the scope
`Segmented.onChange` (`:416`) and the pager's `onChange: list.setPage` (`:491`)
— did not.
## Fix
One `clearSelection` callback, called from those three handlers, mirroring
the merged fix for the same defect class on the topic and consumer group lists
(commit `1172d859`, "#4473 clear hidden resource selections", issue #4465). The
hook's setters are untouched: the selection is the modal's state, so the modal
is where the scope change is observable.
## Score
`PRIORITY = 72` (impact 30: a hard delete of conversations the operator
cannot see, irreversible and stopping a running agent run; scope 12: one page's
modal, but every user of the AI console; reproducibility 18: the three tests
decide it deterministically; maintenance value 12: the same defect class was
already fixed twice in this repository, and the file's own comment pins the
invariant).
`FIX_CONFIDENCE = 88`.
## Tests
```
$ cd web && npx vitest run
src/pages/ai/components/__tests__/ConversationListModal.test.tsx # post-fix
✓ src/pages/ai/components/__tests__/ConversationListModal.test.tsx (22
tests)
Test Files 1 passed (1)
Tests 22 passed (22)
$ cd web && npx tsc --noEmit -p tsconfig.json # no output, exit 0
$ cd web && npx eslint src/pages/ai/components/ConversationListModal.tsx \
src/pages/ai/components/__tests__/ConversationListModal.test.tsx
# exit 0
```
The pre-fix run of the same file (only the production file reverted to
`a562601d`, tests kept) is the failure quoted under Evidence. Each of the three
tests asserts both that the toolbar button is gone and that the new page's row
checkbox is unticked, so the fix is covered for all three setters rather than
for one representative.
## Risk
Low. The only behaviour change is that a selection does not survive a window
change, which is what the button's own copy ("删除本页全部 N 条会话?" / "删除 (N)")
already implies. The after-delete pruning is untouched, so the "keeps the rows
whose delete failed selected" behaviour still holds (its test passes
unchanged). No API, hook or payload change.
## Dedup
- `gh search issues --repo apache/rocketmq-dashboard "clear hidden resource
selections"` → #4465 (closed, Topic/Consumer), #2427/#2428 (closed, instance
list); `gh search prs` → #4473/#2433 (merged,
`pages/instance/{topic,consumer}.tsx` only), #4471 (closed).
- `gh search prs "conversation list selection"`, `"delete selected
conversations"` → no results.
- `grep -F ConversationListModal /tmp/open_pr_files.txt
/tmp/frun1na_files.txt /tmp/my_open_pr_files.txt` (the file lists of all 231
open PRs) → no match.
- `git log --oneline a562601d --
web/src/pages/ai/components/ConversationListModal.tsx` → `1ef5d860` (console
polish) and `5b761df8` (introduction); neither touches the selection.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]