From c86c955ace0e741f8f1bdca956732d12910d81f2 Mon Sep 17 00:00:00 2001 From: TEDMykhailo <34422286+TEDMykhailo@users.noreply.github.com> Date: Thu, 22 Apr 2021 14:28:35 +0300 Subject: [PATCH] [issues-211] - Clearing up messages from a topic (#378) Co-authored-by: mbovtryuk --- .../src/components/Topics/List/List.tsx | 7 ++ .../components/Topics/List/ListContainer.ts | 7 +- .../src/components/Topics/List/ListItem.tsx | 9 +++ .../Topics/List/__tests__/List.spec.tsx | 2 + .../Topics/List/__tests__/ListItem.spec.tsx | 14 +++- .../Topics/Topic/Details/Details.tsx | 19 ++++- .../Topics/Topic/Details/DetailsContainer.ts | 4 +- .../Topic/Details/Overview/Overview.tsx | 75 +++++++++++++------ .../Details/Overview/OverviewContainer.ts | 13 +++- .../redux/actions/__test__/actions.spec.ts | 22 ++++++ .../actions/__test__/thunks/topics.spec.ts | 50 +++++++++++++ .../src/redux/actions/actions.ts | 6 ++ .../src/redux/actions/thunks/topics.ts | 24 ++++++ .../reducers/topics/__test__/reducer.spec.ts | 40 +++++----- .../src/redux/reducers/topics/reducer.ts | 6 ++ 15 files changed, 252 insertions(+), 46 deletions(-) diff --git a/kafka-ui-react-app/src/components/Topics/List/List.tsx b/kafka-ui-react-app/src/components/Topics/List/List.tsx index b7d0f30483..5f601d09e4 100644 --- a/kafka-ui-react-app/src/components/Topics/List/List.tsx +++ b/kafka-ui-react-app/src/components/Topics/List/List.tsx @@ -21,6 +21,11 @@ interface Props { totalPages: number; fetchTopicsList(props: FetchTopicsListParams): void; deleteTopic(topicName: TopicName, clusterName: ClusterName): void; + clearTopicMessages( + topicName: TopicName, + clusterName: ClusterName, + partitions?: number[] + ): void; } const List: React.FC = ({ @@ -30,6 +35,7 @@ const List: React.FC = ({ totalPages, fetchTopicsList, deleteTopic, + clearTopicMessages, }) => { const { isReadOnly } = React.useContext(ClusterContext); const { clusterName } = useParams<{ clusterName: ClusterName }>(); @@ -99,6 +105,7 @@ const List: React.FC = ({ key={topic.name} topic={topic} deleteTopic={deleteTopic} + clearTopicMessages={clearTopicMessages} /> ))} {items.length === 0 && ( diff --git a/kafka-ui-react-app/src/components/Topics/List/ListContainer.ts b/kafka-ui-react-app/src/components/Topics/List/ListContainer.ts index 18f1df98aa..2b3884cbc7 100644 --- a/kafka-ui-react-app/src/components/Topics/List/ListContainer.ts +++ b/kafka-ui-react-app/src/components/Topics/List/ListContainer.ts @@ -1,6 +1,10 @@ import { connect } from 'react-redux'; import { RootState } from 'redux/interfaces'; -import { fetchTopicsList, deleteTopic } from 'redux/actions'; +import { + fetchTopicsList, + deleteTopic, + clearTopicMessages, +} from 'redux/actions'; import { getTopicList, getExternalTopicList, @@ -19,6 +23,7 @@ const mapStateToProps = (state: RootState) => ({ const mapDispatchToProps = { fetchTopicsList, deleteTopic, + clearTopicMessages, }; export default connect(mapStateToProps, mapDispatchToProps)(List); diff --git a/kafka-ui-react-app/src/components/Topics/List/ListItem.tsx b/kafka-ui-react-app/src/components/Topics/List/ListItem.tsx index 77c1e985fa..fac54b8a94 100644 --- a/kafka-ui-react-app/src/components/Topics/List/ListItem.tsx +++ b/kafka-ui-react-app/src/components/Topics/List/ListItem.tsx @@ -14,12 +14,14 @@ export interface ListItemProps { topic: TopicWithDetailedInfo; deleteTopic: (clusterName: ClusterName, topicName: TopicName) => void; clusterName: ClusterName; + clearTopicMessages(topicName: TopicName, clusterName: ClusterName): void; } const ListItem: React.FC = ({ topic: { name, internal, partitions }, deleteTopic, clusterName, + clearTopicMessages, }) => { const [ isDeleteTopicConfirmationVisible, @@ -41,6 +43,10 @@ const ListItem: React.FC = ({ deleteTopic(clusterName, name); }, [clusterName, name]); + const clearTopicMessagesHandler = React.useCallback(() => { + clearTopicMessages(clusterName, name); + }, [clusterName, name]); + return ( @@ -70,6 +76,9 @@ const ListItem: React.FC = ({ } right > + + Clear Messages + setDeleteTopicConfirmationVisible(true)} > diff --git a/kafka-ui-react-app/src/components/Topics/List/__tests__/List.spec.tsx b/kafka-ui-react-app/src/components/Topics/List/__tests__/List.spec.tsx index faf33ddcd3..b09326d1a5 100644 --- a/kafka-ui-react-app/src/components/Topics/List/__tests__/List.spec.tsx +++ b/kafka-ui-react-app/src/components/Topics/List/__tests__/List.spec.tsx @@ -23,6 +23,7 @@ describe('List', () => { totalPages={1} fetchTopicsList={jest.fn()} deleteTopic={jest.fn()} + clearTopicMessages={jest.fn()} /> @@ -49,6 +50,7 @@ describe('List', () => { totalPages={1} fetchTopicsList={jest.fn()} deleteTopic={jest.fn()} + clearTopicMessages={jest.fn()} /> diff --git a/kafka-ui-react-app/src/components/Topics/List/__tests__/ListItem.spec.tsx b/kafka-ui-react-app/src/components/Topics/List/__tests__/ListItem.spec.tsx index 81e5335ef6..1d5986d18b 100644 --- a/kafka-ui-react-app/src/components/Topics/List/__tests__/ListItem.spec.tsx +++ b/kafka-ui-react-app/src/components/Topics/List/__tests__/ListItem.spec.tsx @@ -9,6 +9,7 @@ import ListItem, { ListItemProps } from '../ListItem'; const mockDelete = jest.fn(); const clusterName = 'local'; +const mockDeleteMessages = jest.fn(); jest.mock( 'components/common/ConfirmationModal/ConfirmationModal', @@ -21,14 +22,25 @@ describe('ListItem', () => { topic={internalTopicPayload} deleteTopic={mockDelete} clusterName={clusterName} + clearTopicMessages={mockDeleteMessages} {...props} /> ); + it('triggers the deleting messages when clicked on the delete messages button', () => { + const component = shallow(setupComponent()); + component.find('DropdownItem').at(0).simulate('click'); + expect(mockDeleteMessages).toBeCalledTimes(1); + expect(mockDeleteMessages).toBeCalledWith( + clusterName, + internalTopicPayload.name + ); + }); + it('triggers the deleteTopic when clicked on the delete button', () => { const wrapper = shallow(setupComponent()); expect(wrapper.find('mock-ConfirmationModal').prop('isOpen')).toBeFalsy(); - wrapper.find('DropdownItem').last().simulate('click'); + wrapper.find('DropdownItem').at(1).simulate('click'); const modal = wrapper.find('mock-ConfirmationModal'); expect(modal.prop('isOpen')).toBeTruthy(); modal.simulate('confirm'); diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Details/Details.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Details/Details.tsx index 6ee66383a2..0f52f9a22d 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Details/Details.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/Details/Details.tsx @@ -19,9 +19,15 @@ interface Props extends Topic, TopicDetails { clusterName: ClusterName; topicName: TopicName; deleteTopic: (clusterName: ClusterName, topicName: TopicName) => void; + clearTopicMessages(clusterName: ClusterName, topicName: TopicName): void; } -const Details: React.FC = ({ clusterName, topicName, deleteTopic }) => { +const Details: React.FC = ({ + clusterName, + topicName, + deleteTopic, + clearTopicMessages, +}) => { const history = useHistory(); const { isReadOnly } = React.useContext(ClusterContext); const [ @@ -33,6 +39,10 @@ const Details: React.FC = ({ clusterName, topicName, deleteTopic }) => { history.push(clusterTopicsPath(clusterName)); }, [clusterName, topicName]); + const clearTopicMessagesHandler = React.useCallback(() => { + clearTopicMessages(clusterName, topicName); + }, [clusterName, topicName]); + return (