Details.tsx 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. import React from 'react';
  2. import { ClusterName, TopicName } from 'redux/interfaces';
  3. import { Topic, TopicDetails } from 'generated-sources';
  4. import { NavLink, Switch, Route, useHistory } from 'react-router-dom';
  5. import {
  6. clusterTopicSettingsPath,
  7. clusterTopicPath,
  8. clusterTopicMessagesPath,
  9. clusterTopicsPath,
  10. clusterTopicConsumerGroupsPath,
  11. clusterTopicEditPath,
  12. clusterTopicSendMessagePath,
  13. } from 'lib/paths';
  14. import ClusterContext from 'components/contexts/ClusterContext';
  15. import ConfirmationModal from 'components/common/ConfirmationModal/ConfirmationModal';
  16. import { useDispatch } from 'react-redux';
  17. import { deleteTopicAction } from 'redux/actions';
  18. import PageHeading from 'components/common/PageHeading/PageHeading';
  19. import { Button } from 'components/common/Button/Button';
  20. import Dropdown from 'components/common/Dropdown/Dropdown';
  21. import VerticalElipsisIcon from 'components/common/Icons/VerticalElipsisIcon';
  22. import DropdownItem from 'components/common/Dropdown/DropdownItem';
  23. import styled from 'styled-components';
  24. import Navbar from 'components/common/Navigation/Navbar.styled';
  25. import OverviewContainer from './Overview/OverviewContainer';
  26. import TopicConsumerGroupsContainer from './ConsumerGroups/TopicConsumerGroupsContainer';
  27. import SettingsContainer from './Settings/SettingsContainer';
  28. import Messages from './Messages/Messages';
  29. interface Props extends Topic, TopicDetails {
  30. clusterName: ClusterName;
  31. topicName: TopicName;
  32. isInternal: boolean;
  33. isDeleted: boolean;
  34. isDeletePolicy: boolean;
  35. deleteTopic: (clusterName: ClusterName, topicName: TopicName) => void;
  36. clearTopicMessages(clusterName: ClusterName, topicName: TopicName): void;
  37. }
  38. const HeaderControlsWrapper = styled.div`
  39. display: flex;
  40. justify-content: flex-end;
  41. align-self: center;
  42. gap: 26px;
  43. `;
  44. const Details: React.FC<Props> = ({
  45. clusterName,
  46. topicName,
  47. isInternal,
  48. isDeleted,
  49. isDeletePolicy,
  50. deleteTopic,
  51. clearTopicMessages,
  52. }) => {
  53. const history = useHistory();
  54. const dispatch = useDispatch();
  55. const { isReadOnly, isTopicDeletionAllowed } =
  56. React.useContext(ClusterContext);
  57. const [isDeleteTopicConfirmationVisible, setDeleteTopicConfirmationVisible] =
  58. React.useState(false);
  59. const [isClearTopicConfirmationVisible, setClearTopicConfirmationVisible] =
  60. React.useState(false);
  61. const deleteTopicHandler = React.useCallback(() => {
  62. deleteTopic(clusterName, topicName);
  63. }, [clusterName, deleteTopic, topicName]);
  64. React.useEffect(() => {
  65. if (isDeleted) {
  66. dispatch(deleteTopicAction.cancel());
  67. history.push(clusterTopicsPath(clusterName));
  68. }
  69. }, [clusterName, dispatch, history, isDeleted]);
  70. const clearTopicMessagesHandler = React.useCallback(() => {
  71. clearTopicMessages(clusterName, topicName);
  72. setClearTopicConfirmationVisible(false);
  73. }, [clearTopicMessages, clusterName, topicName]);
  74. return (
  75. <div>
  76. <PageHeading text={topicName}>
  77. <HeaderControlsWrapper>
  78. <Route exact path="/clusters/:clusterName/topics/:topicName/messages">
  79. <Button
  80. buttonSize="M"
  81. buttonType="primary"
  82. isLink
  83. to={clusterTopicSendMessagePath(clusterName, topicName)}
  84. >
  85. Produce Message
  86. </Button>
  87. </Route>
  88. {!isReadOnly && !isInternal && (
  89. <Route path="/clusters/:clusterName/topics/:topicName">
  90. <Dropdown label={<VerticalElipsisIcon />} right>
  91. <DropdownItem
  92. onClick={() =>
  93. history.push(clusterTopicEditPath(clusterName, topicName))
  94. }
  95. >
  96. Edit settings
  97. </DropdownItem>
  98. {isDeletePolicy && (
  99. <DropdownItem
  100. onClick={() => setClearTopicConfirmationVisible(true)}
  101. danger
  102. >
  103. Clear messages
  104. </DropdownItem>
  105. )}
  106. {isTopicDeletionAllowed && (
  107. <DropdownItem
  108. onClick={() => setDeleteTopicConfirmationVisible(true)}
  109. danger
  110. >
  111. Remove topic
  112. </DropdownItem>
  113. )}
  114. </Dropdown>
  115. </Route>
  116. )}
  117. </HeaderControlsWrapper>
  118. </PageHeading>
  119. <ConfirmationModal
  120. isOpen={isDeleteTopicConfirmationVisible}
  121. onCancel={() => setDeleteTopicConfirmationVisible(false)}
  122. onConfirm={deleteTopicHandler}
  123. >
  124. Are you sure want to remove <b>{topicName}</b> topic?
  125. </ConfirmationModal>
  126. <ConfirmationModal
  127. isOpen={isClearTopicConfirmationVisible}
  128. onCancel={() => setClearTopicConfirmationVisible(false)}
  129. onConfirm={clearTopicMessagesHandler}
  130. >
  131. Are you sure want to clear topic messages?
  132. </ConfirmationModal>
  133. <Navbar role="navigation">
  134. <NavLink
  135. exact
  136. to={clusterTopicPath(clusterName, topicName)}
  137. activeClassName="is-active is-primary"
  138. >
  139. Overview
  140. </NavLink>
  141. <NavLink
  142. exact
  143. to={clusterTopicMessagesPath(clusterName, topicName)}
  144. activeClassName="is-active"
  145. >
  146. Messages
  147. </NavLink>
  148. <NavLink
  149. exact
  150. to={clusterTopicConsumerGroupsPath(clusterName, topicName)}
  151. activeClassName="is-active"
  152. >
  153. Consumers
  154. </NavLink>
  155. <NavLink
  156. exact
  157. to={clusterTopicSettingsPath(clusterName, topicName)}
  158. activeClassName="is-active"
  159. >
  160. Settings
  161. </NavLink>
  162. </Navbar>
  163. <Switch>
  164. <Route
  165. exact
  166. path="/clusters/:clusterName/topics/:topicName/messages"
  167. component={Messages}
  168. />
  169. <Route
  170. exact
  171. path="/clusters/:clusterName/topics/:topicName/settings"
  172. component={SettingsContainer}
  173. />
  174. <Route
  175. exact
  176. path="/clusters/:clusterName/topics/:topicName"
  177. component={OverviewContainer}
  178. />
  179. <Route
  180. exact
  181. path="/clusters/:clusterName/topics/:topicName/consumer-groups"
  182. component={TopicConsumerGroupsContainer}
  183. />
  184. </Switch>
  185. </div>
  186. );
  187. };
  188. export default Details;