Skip to content

Commit 5cdd44d

Browse files
David-DB88davitbejanyan
andauthored
[FE] Fix updating message count upon clearing messages (#3080)
* in a function clearTopicMessagesHandler added invalidateQueries * changed redux Topic messages clear with react query call * changed redux Topic messages clear with react query call on Overview/ActionCell.tsx * show on alert deleted item * added s on variable clearMessage * removed clearTopicMessages action from redux and replace functionality with hook useClearTopicMessages --------- Co-authored-by: davitbejanyan <[email protected]>
1 parent b890dc3 commit 5cdd44d

File tree

10 files changed

+78
-114
lines changed

10 files changed

+78
-114
lines changed

kafka-ui-react-app/src/components/Topics/List/ActionsCell.tsx

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
11
import React from 'react';
22
import { Action, CleanUpPolicy, Topic, ResourceType } from 'generated-sources';
33
import { CellContext } from '@tanstack/react-table';
4-
import { useAppDispatch } from 'lib/hooks/redux';
54
import ClusterContext from 'components/contexts/ClusterContext';
65
import { ClusterNameRoute } from 'lib/paths';
76
import useAppParams from 'lib/hooks/useAppParams';
8-
import { clearTopicMessages } from 'redux/reducers/topicMessages/topicMessagesSlice';
97
import {
108
Dropdown,
119
DropdownItem,
1210
DropdownItemHint,
1311
} from 'components/common/Dropdown';
14-
import { useQueryClient } from '@tanstack/react-query';
1512
import {
16-
topicKeys,
1713
useDeleteTopic,
14+
useClearTopicMessages,
1815
useRecreateTopic,
1916
} from 'lib/hooks/api/topics';
2017
import { ActionDropdownItem } from 'components/common/ActionComponent';
@@ -24,20 +21,16 @@ const ActionsCell: React.FC<CellContext<Topic, unknown>> = ({ row }) => {
2421

2522
const { isReadOnly, isTopicDeletionAllowed } =
2623
React.useContext(ClusterContext);
27-
const dispatch = useAppDispatch();
2824
const { clusterName } = useAppParams<ClusterNameRoute>();
29-
const queryClient = useQueryClient();
3025

26+
const clearMessages = useClearTopicMessages(clusterName);
3127
const deleteTopic = useDeleteTopic(clusterName);
3228
const recreateTopic = useRecreateTopic({ clusterName, topicName: name });
3329

3430
const disabled = internal || isReadOnly;
3531

3632
const clearTopicMessagesHandler = async () => {
37-
await dispatch(
38-
clearTopicMessages({ clusterName, topicName: name })
39-
).unwrap();
40-
return queryClient.invalidateQueries(topicKeys.all(clusterName));
33+
await clearMessages.mutateAsync(name);
4134
};
4235

4336
const isCleanupDisabled = cleanUpPolicy !== CleanUpPolicy.DELETE;

kafka-ui-react-app/src/components/Topics/List/BatchActionsBar.tsx

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@ import { Row } from '@tanstack/react-table';
33
import { Action, Topic, ResourceType } from 'generated-sources';
44
import useAppParams from 'lib/hooks/useAppParams';
55
import { ClusterName } from 'redux/interfaces';
6-
import { topicKeys, useDeleteTopic } from 'lib/hooks/api/topics';
6+
import {
7+
topicKeys,
8+
useClearTopicMessages,
9+
useDeleteTopic,
10+
} from 'lib/hooks/api/topics';
711
import { useConfirm } from 'lib/hooks/useConfirm';
812
import { Button } from 'components/common/Button/Button';
9-
import { useAppDispatch } from 'lib/hooks/redux';
10-
import { clearTopicMessages } from 'redux/reducers/topicMessages/topicMessagesSlice';
1113
import { clusterTopicCopyRelativePath } from 'lib/paths';
1214
import { useQueryClient } from '@tanstack/react-query';
1315
import { ActionCanButton } from 'components/common/ActionComponent';
@@ -25,11 +27,14 @@ const BatchActionsbar: React.FC<BatchActionsbarProps> = ({
2527
}) => {
2628
const { clusterName } = useAppParams<{ clusterName: ClusterName }>();
2729
const confirm = useConfirm();
28-
const dispatch = useAppDispatch();
2930
const deleteTopic = useDeleteTopic(clusterName);
3031
const selectedTopics = rows.map(({ original }) => original.name);
3132
const client = useQueryClient();
3233

34+
const clearMessages = useClearTopicMessages(clusterName);
35+
const clearTopicMessagesHandler = async (topicName: Topic['name']) => {
36+
await clearMessages.mutateAsync(topicName);
37+
};
3338
const deleteTopicsHandler = () => {
3439
confirm('Are you sure you want to remove selected topics?', async () => {
3540
try {
@@ -50,7 +55,7 @@ const BatchActionsbar: React.FC<BatchActionsbarProps> = ({
5055
try {
5156
await Promise.all(
5257
selectedTopics.map((topicName) =>
53-
dispatch(clearTopicMessages({ clusterName, topicName })).unwrap()
58+
clearTopicMessagesHandler(topicName)
5459
)
5560
);
5661
resetRowSelection();

kafka-ui-react-app/src/components/Topics/List/__tests__/TopicTable.spec.tsx

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,15 @@ import { externalTopicPayload, topicsPayload } from 'lib/fixtures/topics';
66
import ClusterContext from 'components/contexts/ClusterContext';
77
import userEvent from '@testing-library/user-event';
88
import {
9+
useClearTopicMessages,
910
useDeleteTopic,
1011
useRecreateTopic,
1112
useTopics,
1213
} from 'lib/hooks/api/topics';
1314
import TopicTable from 'components/Topics/List/TopicTable';
1415
import { clusterTopicsPath } from 'lib/paths';
15-
import { useAppDispatch } from 'lib/hooks/redux';
1616

1717
const clusterName = 'test-cluster';
18-
const unwrapMock = jest.fn();
1918

2019
jest.mock('lib/hooks/redux', () => ({
2120
...jest.requireActual('lib/hooks/redux'),
@@ -29,22 +28,24 @@ jest.mock('lib/hooks/api/topics', () => ({
2928
useDeleteTopic: jest.fn(),
3029
useRecreateTopic: jest.fn(),
3130
useTopics: jest.fn(),
31+
useClearTopicMessages: jest.fn(),
3232
}));
3333

3434
const deleteTopicMock = jest.fn();
3535
const recreateTopicMock = jest.fn();
36+
const clearTopicMessages = jest.fn();
3637

3738
describe('TopicTable Components', () => {
3839
beforeEach(() => {
3940
(useDeleteTopic as jest.Mock).mockImplementation(() => ({
4041
mutateAsync: deleteTopicMock,
4142
}));
43+
(useClearTopicMessages as jest.Mock).mockImplementation(() => ({
44+
mutateAsync: clearTopicMessages,
45+
}));
4246
(useRecreateTopic as jest.Mock).mockImplementation(() => ({
4347
mutateAsync: recreateTopicMock,
4448
}));
45-
(useAppDispatch as jest.Mock).mockImplementation(() => () => ({
46-
unwrap: unwrapMock,
47-
}));
4849
});
4950

5051
const renderComponent = (
@@ -185,9 +186,9 @@ describe('TopicTable Components', () => {
185186
).toBeInTheDocument();
186187
const confirmBtn = getButtonByName('Confirm');
187188
expect(confirmBtn).toBeInTheDocument();
188-
expect(unwrapMock).not.toHaveBeenCalled();
189+
expect(clearTopicMessages).not.toHaveBeenCalled();
189190
await userEvent.click(confirmBtn);
190-
expect(unwrapMock).toHaveBeenCalledTimes(2);
191+
expect(clearTopicMessages).toHaveBeenCalledTimes(2);
191192
expect(screen.getAllByRole('checkbox')[1]).not.toBeChecked();
192193
expect(screen.getAllByRole('checkbox')[2]).not.toBeChecked();
193194
});
@@ -282,7 +283,7 @@ describe('TopicTable Components', () => {
282283
await userEvent.click(
283284
screen.getByRole('button', { name: 'Confirm' })
284285
);
285-
expect(unwrapMock).toHaveBeenCalled();
286+
expect(clearTopicMessages).toHaveBeenCalled();
286287
});
287288
});
288289

kafka-ui-react-app/src/components/Topics/Topic/Overview/ActionsCell.tsx

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,23 @@
11
import React from 'react';
22
import { Action, Partition, ResourceType } from 'generated-sources';
33
import { CellContext } from '@tanstack/react-table';
4-
import { useAppDispatch } from 'lib/hooks/redux';
54
import ClusterContext from 'components/contexts/ClusterContext';
65
import { RouteParamsClusterTopic } from 'lib/paths';
76
import useAppParams from 'lib/hooks/useAppParams';
8-
import { clearTopicMessages } from 'redux/reducers/topicMessages/topicMessagesSlice';
97
import { Dropdown } from 'components/common/Dropdown';
10-
import { useTopicDetails } from 'lib/hooks/api/topics';
8+
import { useClearTopicMessages, useTopicDetails } from 'lib/hooks/api/topics';
119
import { ActionDropdownItem } from 'components/common/ActionComponent';
1210

1311
const ActionsCell: React.FC<CellContext<Partition, unknown>> = ({ row }) => {
1412
const { clusterName, topicName } = useAppParams<RouteParamsClusterTopic>();
1513
const { data } = useTopicDetails({ clusterName, topicName });
1614
const { isReadOnly } = React.useContext(ClusterContext);
1715
const { partition } = row.original;
18-
const dispatch = useAppDispatch();
16+
17+
const clearMessages = useClearTopicMessages(clusterName, [partition]);
1918

2019
const clearTopicMessagesHandler = async () => {
21-
await dispatch(
22-
clearTopicMessages({ clusterName, topicName, partitions: [partition] })
23-
).unwrap();
20+
await clearMessages.mutateAsync(topicName);
2421
};
2522
const disabled =
2623
data?.internal || isReadOnly || data?.cleanUpPolicy !== 'DELETE';

kafka-ui-react-app/src/components/Topics/Topic/Overview/__test__/Overview.spec.tsx

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ import ClusterContext from 'components/contexts/ClusterContext';
88
import userEvent from '@testing-library/user-event';
99
import { clusterTopicPath } from 'lib/paths';
1010
import { Replica } from 'components/Topics/Topic/Overview/Overview.styled';
11-
import { useTopicDetails } from 'lib/hooks/api/topics';
12-
import { useAppDispatch } from 'lib/hooks/redux';
11+
import { useClearTopicMessages, useTopicDetails } from 'lib/hooks/api/topics';
1312
import {
1413
externalTopicPayload,
1514
internalTopicPayload,
@@ -26,14 +25,10 @@ const defaultContextValues = {
2625

2726
jest.mock('lib/hooks/api/topics', () => ({
2827
useTopicDetails: jest.fn(),
28+
useClearTopicMessages: jest.fn(),
2929
}));
3030

31-
const unwrapMock = jest.fn();
32-
33-
jest.mock('lib/hooks/redux', () => ({
34-
...jest.requireActual('lib/hooks/redux'),
35-
useAppDispatch: jest.fn(),
36-
}));
31+
const clearTopicMessage = jest.fn();
3732

3833
describe('Overview', () => {
3934
const renderComponent = (
@@ -43,6 +38,9 @@ describe('Overview', () => {
4338
(useTopicDetails as jest.Mock).mockImplementation(() => ({
4439
data: topic,
4540
}));
41+
(useClearTopicMessages as jest.Mock).mockImplementation(() => ({
42+
mutateAsync: clearTopicMessage,
43+
}));
4644
const path = clusterTopicPath(clusterName, topicName);
4745
return render(
4846
<WithRoute path={clusterTopicPath()}>
@@ -54,12 +52,6 @@ describe('Overview', () => {
5452
);
5553
};
5654

57-
beforeEach(() => {
58-
(useAppDispatch as jest.Mock).mockImplementation(() => () => ({
59-
unwrap: unwrapMock,
60-
}));
61-
});
62-
6355
it('at least one replica was rendered', () => {
6456
renderComponent();
6557
expect(screen.getByLabelText('replica-info')).toBeInTheDocument();
@@ -136,7 +128,7 @@ describe('Overview', () => {
136128

137129
const clearMessagesButton = screen.getByText('Clear Messages');
138130
await userEvent.click(clearMessagesButton);
139-
expect(unwrapMock).toHaveBeenCalledTimes(1);
131+
expect(clearTopicMessage).toHaveBeenCalledTimes(1);
140132
});
141133
});
142134

kafka-ui-react-app/src/components/Topics/Topic/Topic.tsx

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,12 @@ import { useAppDispatch } from 'lib/hooks/redux';
2121
import useAppParams from 'lib/hooks/useAppParams';
2222
import { Dropdown, DropdownItemHint } from 'components/common/Dropdown';
2323
import {
24+
useClearTopicMessages,
2425
useDeleteTopic,
2526
useRecreateTopic,
2627
useTopicDetails,
2728
} from 'lib/hooks/api/topics';
28-
import {
29-
clearTopicMessages,
30-
resetTopicMessages,
31-
} from 'redux/reducers/topicMessages/topicMessagesSlice';
29+
import { resetTopicMessages } from 'redux/reducers/topicMessages/topicMessagesSlice';
3230
import { Action, CleanUpPolicy, ResourceType } from 'generated-sources';
3331
import PageLoader from 'components/common/PageLoader/PageLoader';
3432
import SlidingSidebar from 'components/common/SlidingSidebar';
@@ -69,9 +67,11 @@ const Topic: React.FC = () => {
6967
dispatch(resetTopicMessages());
7068
};
7169
}, []);
72-
70+
const clearMessages = useClearTopicMessages(clusterName);
71+
const clearTopicMessagesHandler = async () => {
72+
await clearMessages.mutateAsync(topicName);
73+
};
7374
const canCleanup = data?.cleanUpPolicy === CleanUpPolicy.DELETE;
74-
7575
return (
7676
<>
7777
<PageHeading
@@ -110,9 +110,7 @@ const Topic: React.FC = () => {
110110
</ActionDropdownItem>
111111

112112
<ActionDropdownItem
113-
onClick={() =>
114-
dispatch(clearTopicMessages({ clusterName, topicName })).unwrap()
115-
}
113+
onClick={clearTopicMessagesHandler}
116114
confirm="Are you sure want to clear topic messages?"
117115
disabled={!canCleanup}
118116
danger

kafka-ui-react-app/src/components/Topics/Topic/__test__/Topic.spec.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
import { CleanUpPolicy, Topic } from 'generated-sources';
1717
import { externalTopicPayload } from 'lib/fixtures/topics';
1818
import {
19+
useClearTopicMessages,
1920
useDeleteTopic,
2021
useRecreateTopic,
2122
useTopicDetails,
@@ -31,9 +32,11 @@ jest.mock('lib/hooks/api/topics', () => ({
3132
useTopicDetails: jest.fn(),
3233
useDeleteTopic: jest.fn(),
3334
useRecreateTopic: jest.fn(),
35+
useClearTopicMessages: jest.fn(),
3436
}));
3537

3638
const unwrapMock = jest.fn();
39+
const clearTopicMessages = jest.fn();
3740

3841
jest.mock('lib/hooks/redux', () => ({
3942
...jest.requireActual('lib/hooks/redux'),
@@ -98,6 +101,9 @@ describe('Details', () => {
98101
(useRecreateTopic as jest.Mock).mockImplementation(() => ({
99102
mutateAsync: mockRecreate,
100103
}));
104+
(useClearTopicMessages as jest.Mock).mockImplementation(() => ({
105+
mutateAsync: clearTopicMessages,
106+
}));
101107
(useAppDispatch as jest.Mock).mockImplementation(() => () => ({
102108
unwrap: unwrapMock,
103109
}));
@@ -145,7 +151,7 @@ describe('Details', () => {
145151
name: 'Confirm',
146152
})[0];
147153
await waitFor(() => userEvent.click(submitButton));
148-
expect(unwrapMock).toHaveBeenCalledTimes(1);
154+
expect(clearTopicMessages).toHaveBeenCalledTimes(1);
149155
});
150156

151157
it('closes the modal when cancel button is clicked', async () => {

kafka-ui-react-app/src/lib/hooks/api/topics.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {
22
topicsApiClient as api,
33
messagesApiClient as messagesApi,
44
consumerGroupsApiClient,
5+
messagesApiClient,
56
} from 'lib/api';
67
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
78
import {
@@ -233,6 +234,34 @@ export function useDeleteTopic(clusterName: ClusterName) {
233234
}
234235
);
235236
}
237+
238+
export function useClearTopicMessages(
239+
clusterName: ClusterName,
240+
partitions?: number[]
241+
) {
242+
const client = useQueryClient();
243+
return useMutation(
244+
async (topicName: Topic['name']) => {
245+
await messagesApiClient.deleteTopicMessages({
246+
clusterName,
247+
partitions,
248+
topicName,
249+
});
250+
return topicName;
251+
},
252+
253+
{
254+
onSuccess: (topicName) => {
255+
showSuccessAlert({
256+
id: `message-${topicName}-${clusterName}-${partitions}`,
257+
message: `${topicName} messages have been successfully cleared!`,
258+
});
259+
client.invalidateQueries(topicKeys.all(clusterName));
260+
},
261+
}
262+
);
263+
}
264+
236265
export function useRecreateTopic(props: GetTopicDetailsRequest) {
237266
const client = useQueryClient();
238267
return useMutation(() => api.recreateTopic(props), {

0 commit comments

Comments
 (0)