From 3fee2214a03cd081917e641764d8acd27f103649 Mon Sep 17 00:00:00 2001 From: GneyHabub Date: Wed, 17 Mar 2021 15:00:03 +0300 Subject: [PATCH] Implement topic deletion --- .../src/components/Topics/List/List.tsx | 5 +-- .../src/components/Topics/List/ListItem.tsx | 25 ++++++++++++- .../Topics/List/ListItemContainer.ts | 35 +++++++++++++++++++ .../src/redux/actions/actions.ts | 6 ++++ .../src/redux/actions/thunks.ts | 16 +++++++++ .../src/redux/reducers/topics/reducer.ts | 9 +++++ 6 files changed, 93 insertions(+), 3 deletions(-) create mode 100644 kafka-ui-react-app/src/components/Topics/List/ListItemContainer.ts 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 879c08134a..c89c269923 100644 --- a/kafka-ui-react-app/src/components/Topics/List/List.tsx +++ b/kafka-ui-react-app/src/components/Topics/List/List.tsx @@ -4,7 +4,7 @@ import Breadcrumb from 'components/common/Breadcrumb/Breadcrumb'; import { NavLink } from 'react-router-dom'; import { clusterTopicNewPath } from 'lib/paths'; import ClusterContext from 'components/contexts/ClusterContext'; -import ListItem from './ListItem'; +import ListItemContainer from './ListItemContainer'; interface Props { clusterName: ClusterName; @@ -58,11 +58,12 @@ const List: React.FC = ({ clusterName, topics, externalTopics }) => { Total Partitions Out of sync replicas Type + {items.map((topic) => ( - + ))} 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 de2c2c78f2..0e69de45a4 100644 --- a/kafka-ui-react-app/src/components/Topics/List/ListItem.tsx +++ b/kafka-ui-react-app/src/components/Topics/List/ListItem.tsx @@ -1,14 +1,22 @@ import React from 'react'; import cx from 'classnames'; import { NavLink } from 'react-router-dom'; -import { TopicWithDetailedInfo } from 'redux/interfaces'; +import { + ClusterName, + TopicName, + TopicWithDetailedInfo, +} from 'redux/interfaces'; interface ListItemProps { topic: TopicWithDetailedInfo; + deleteTopic: (clusterName: ClusterName, topicName: TopicName) => void; + clusterName: ClusterName; } const ListItem: React.FC = ({ topic: { name, internal, partitions }, + deleteTopic, + clusterName, }) => { const outOfSyncReplicas = React.useMemo(() => { if (partitions === undefined || partitions.length === 0) { @@ -21,6 +29,10 @@ const ListItem: React.FC = ({ }, 0); }, [partitions]); + const deleteTopicHandler = () => { + deleteTopic(clusterName, name); + }; + return ( @@ -42,6 +54,17 @@ const ListItem: React.FC = ({ {internal ? 'Internal' : 'External'} + + + ); }; diff --git a/kafka-ui-react-app/src/components/Topics/List/ListItemContainer.ts b/kafka-ui-react-app/src/components/Topics/List/ListItemContainer.ts new file mode 100644 index 0000000000..618cad7b88 --- /dev/null +++ b/kafka-ui-react-app/src/components/Topics/List/ListItemContainer.ts @@ -0,0 +1,35 @@ +import { connect } from 'react-redux'; +import { RootState, ClusterName, TopicName, Action } from 'redux/interfaces'; +import { withRouter, RouteComponentProps } from 'react-router-dom'; +import { ThunkDispatch } from 'redux-thunk'; +import { deleteTopic } from 'redux/actions'; +import ListItem from './ListItem'; + +interface RouteProps { + clusterName: ClusterName; +} + +type OwnProps = RouteComponentProps; + +const mapStateToProps = ( + state: RootState, + { + match: { + params: { clusterName }, + }, + }: OwnProps +) => ({ + clusterName, +}); + +const mapDispatchToProps = ( + dispatch: ThunkDispatch +) => ({ + deleteTopic: (clusterName: ClusterName, topicName: TopicName) => { + dispatch(deleteTopic(clusterName, topicName)); + }, +}); + +export default withRouter( + connect(mapStateToProps, mapDispatchToProps)(ListItem) +); diff --git a/kafka-ui-react-app/src/redux/actions/actions.ts b/kafka-ui-react-app/src/redux/actions/actions.ts index 4fffc065a7..661865605c 100644 --- a/kafka-ui-react-app/src/redux/actions/actions.ts +++ b/kafka-ui-react-app/src/redux/actions/actions.ts @@ -82,6 +82,12 @@ export const updateTopicAction = createAsyncAction( 'PATCH_TOPIC__FAILURE' )(); +export const deleteTopicAction = createAsyncAction( + 'DELETE_TOPIC__REQUEST', + 'DELETE_TOPIC__SUCCESS', + 'DELETE_TOPIC__FAILURE' +)(); + export const fetchConsumerGroupsAction = createAsyncAction( 'GET_CONSUMER_GROUPS__REQUEST', 'GET_CONSUMER_GROUPS__SUCCESS', diff --git a/kafka-ui-react-app/src/redux/actions/thunks.ts b/kafka-ui-react-app/src/redux/actions/thunks.ts index 1c49beeb04..4b51dedb47 100644 --- a/kafka-ui-react-app/src/redux/actions/thunks.ts +++ b/kafka-ui-react-app/src/redux/actions/thunks.ts @@ -234,6 +234,22 @@ export const updateTopic = ( } }; +export const deleteTopic = ( + clusterName: ClusterName, + topicName: TopicName +): PromiseThunkResult => async (dispatch) => { + dispatch(actions.deleteTopicAction.request()); + try { + await topicsApiClient.deleteTopic({ + clusterName, + topicName, + }); + dispatch(actions.deleteTopicAction.success(topicName)); + } catch (e) { + dispatch(actions.deleteTopicAction.failure()); + } +}; + export const fetchConsumerGroupsList = ( clusterName: ClusterName ): PromiseThunkResult => async (dispatch) => { diff --git a/kafka-ui-react-app/src/redux/reducers/topics/reducer.ts b/kafka-ui-react-app/src/redux/reducers/topics/reducer.ts index 61e58772cc..ee3533f7dd 100644 --- a/kafka-ui-react-app/src/redux/reducers/topics/reducer.ts +++ b/kafka-ui-react-app/src/redux/reducers/topics/reducer.ts @@ -100,6 +100,15 @@ const reducer = (state = initialState, action: Action): TopicsState => { }; case getType(actions.createTopicAction.success): return addToTopicList(state, action.payload); + case getType(actions.deleteTopicAction.success): { + const newState: TopicsState = { ...state }; + delete newState.byName[action.payload]; + newState.allNames = newState.allNames.filter( + (name) => name !== action.payload + ); + return newState; + } + default: return state; }