Details.tsx 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. import React from 'react';
  2. import { ClusterName, TopicName } from 'redux/interfaces';
  3. import { NavLink, Route, Routes, useNavigate } from 'react-router-dom';
  4. import {
  5. RouteParamsClusterTopic,
  6. clusterTopicMessagesRelativePath,
  7. clusterTopicSettingsRelativePath,
  8. clusterTopicConsumerGroupsRelativePath,
  9. clusterTopicEditRelativePath,
  10. clusterTopicSendMessageRelativePath,
  11. } from 'lib/paths';
  12. import ClusterContext from 'components/contexts/ClusterContext';
  13. import ConfirmationModal from 'components/common/ConfirmationModal/ConfirmationModal';
  14. import { useDispatch } from 'react-redux';
  15. import PageHeading from 'components/common/PageHeading/PageHeading';
  16. import { Button } from 'components/common/Button/Button';
  17. import Dropdown from 'components/common/Dropdown/Dropdown';
  18. import VerticalElipsisIcon from 'components/common/Icons/VerticalElipsisIcon';
  19. import DropdownItem from 'components/common/Dropdown/DropdownItem';
  20. import styled from 'styled-components';
  21. import Navbar from 'components/common/Navigation/Navbar.styled';
  22. import * as S from 'components/Topics/Topic/Details/Details.styled';
  23. import { useAppSelector } from 'lib/hooks/redux';
  24. import {
  25. getIsTopicDeletePolicy,
  26. getIsTopicInternal,
  27. } from 'redux/reducers/topics/selectors';
  28. import useAppParams from 'lib/hooks/useAppParams';
  29. import OverviewContainer from './Overview/OverviewContainer';
  30. import TopicConsumerGroupsContainer from './ConsumerGroups/TopicConsumerGroupsContainer';
  31. import SettingsContainer from './Settings/SettingsContainer';
  32. import Messages from './Messages/Messages';
  33. interface Props {
  34. isDeleted: boolean;
  35. deleteTopic: (payload: {
  36. clusterName: ClusterName;
  37. topicName: TopicName;
  38. }) => void;
  39. recreateTopic: (payload: {
  40. clusterName: ClusterName;
  41. topicName: TopicName;
  42. }) => void;
  43. clearTopicMessages(params: {
  44. clusterName: ClusterName;
  45. topicName: TopicName;
  46. }): void;
  47. }
  48. const HeaderControlsWrapper = styled.div`
  49. display: flex;
  50. justify-content: flex-end;
  51. align-self: center;
  52. gap: 26px;
  53. `;
  54. const Details: React.FC<Props> = ({
  55. isDeleted,
  56. deleteTopic,
  57. recreateTopic,
  58. clearTopicMessages,
  59. }) => {
  60. const { clusterName, topicName } = useAppParams<RouteParamsClusterTopic>();
  61. const isInternal = useAppSelector((state) =>
  62. getIsTopicInternal(state, topicName)
  63. );
  64. const isDeletePolicy = useAppSelector((state) =>
  65. getIsTopicDeletePolicy(state, topicName)
  66. );
  67. const navigate = useNavigate();
  68. const dispatch = useDispatch();
  69. const { isReadOnly, isTopicDeletionAllowed } =
  70. React.useContext(ClusterContext);
  71. const [isDeleteTopicConfirmationVisible, setDeleteTopicConfirmationVisible] =
  72. React.useState(false);
  73. const [isClearTopicConfirmationVisible, setClearTopicConfirmationVisible] =
  74. React.useState(false);
  75. const [
  76. isRecreateTopicConfirmationVisible,
  77. setRecreateTopicConfirmationVisible,
  78. ] = React.useState(false);
  79. const deleteTopicHandler = () => deleteTopic({ clusterName, topicName });
  80. React.useEffect(() => {
  81. if (isDeleted) {
  82. navigate('../..');
  83. }
  84. }, [isDeleted, clusterName, dispatch, navigate]);
  85. const clearTopicMessagesHandler = () => {
  86. clearTopicMessages({ clusterName, topicName });
  87. setClearTopicConfirmationVisible(false);
  88. };
  89. const recreateTopicHandler = () => {
  90. recreateTopic({ clusterName, topicName });
  91. setRecreateTopicConfirmationVisible(false);
  92. };
  93. return (
  94. <div>
  95. <PageHeading text={topicName}>
  96. <HeaderControlsWrapper>
  97. <Routes>
  98. <Route
  99. path={clusterTopicMessagesRelativePath}
  100. element={
  101. <Button
  102. buttonSize="M"
  103. buttonType="primary"
  104. to={`../${clusterTopicSendMessageRelativePath}`}
  105. disabled={isReadOnly}
  106. >
  107. Produce Message
  108. </Button>
  109. }
  110. />
  111. </Routes>
  112. {!isReadOnly && !isInternal && (
  113. <Routes>
  114. <Route
  115. index
  116. element={
  117. <Dropdown label={<VerticalElipsisIcon />} right>
  118. <DropdownItem
  119. onClick={() => navigate(clusterTopicEditRelativePath)}
  120. >
  121. Edit settings
  122. <S.DropdownExtraMessage>
  123. Pay attention! This operation has
  124. <br />
  125. especially important consequences.
  126. </S.DropdownExtraMessage>
  127. </DropdownItem>
  128. {isDeletePolicy && (
  129. <DropdownItem
  130. onClick={() => setClearTopicConfirmationVisible(true)}
  131. danger
  132. >
  133. Clear messages
  134. </DropdownItem>
  135. )}
  136. <DropdownItem
  137. onClick={() => setRecreateTopicConfirmationVisible(true)}
  138. danger
  139. >
  140. Recreate Topic
  141. </DropdownItem>
  142. {isTopicDeletionAllowed && (
  143. <DropdownItem
  144. onClick={() => setDeleteTopicConfirmationVisible(true)}
  145. danger
  146. >
  147. Remove topic
  148. </DropdownItem>
  149. )}
  150. </Dropdown>
  151. }
  152. />
  153. </Routes>
  154. )}
  155. </HeaderControlsWrapper>
  156. </PageHeading>
  157. <ConfirmationModal
  158. isOpen={isDeleteTopicConfirmationVisible}
  159. onCancel={() => setDeleteTopicConfirmationVisible(false)}
  160. onConfirm={deleteTopicHandler}
  161. >
  162. Are you sure want to remove <b>{topicName}</b> topic?
  163. </ConfirmationModal>
  164. <ConfirmationModal
  165. isOpen={isClearTopicConfirmationVisible}
  166. onCancel={() => setClearTopicConfirmationVisible(false)}
  167. onConfirm={clearTopicMessagesHandler}
  168. >
  169. Are you sure want to clear topic messages?
  170. </ConfirmationModal>
  171. <ConfirmationModal
  172. isOpen={isRecreateTopicConfirmationVisible}
  173. onCancel={() => setRecreateTopicConfirmationVisible(false)}
  174. onConfirm={recreateTopicHandler}
  175. >
  176. Are you sure want to recreate <b>{topicName}</b> topic?
  177. </ConfirmationModal>
  178. <Navbar role="navigation">
  179. <NavLink
  180. to="."
  181. className={({ isActive }) => (isActive ? 'is-active is-primary' : '')}
  182. >
  183. Overview
  184. </NavLink>
  185. <NavLink
  186. to={clusterTopicMessagesRelativePath}
  187. className={({ isActive }) => (isActive ? 'is-active' : '')}
  188. >
  189. Messages
  190. </NavLink>
  191. <NavLink
  192. to={clusterTopicConsumerGroupsRelativePath}
  193. className={({ isActive }) => (isActive ? 'is-active' : '')}
  194. >
  195. Consumers
  196. </NavLink>
  197. <NavLink
  198. to={clusterTopicSettingsRelativePath}
  199. className={({ isActive }) => (isActive ? 'is-active' : '')}
  200. >
  201. Settings
  202. </NavLink>
  203. </Navbar>
  204. <Routes>
  205. <Route index element={<OverviewContainer />} />
  206. <Route path={clusterTopicMessagesRelativePath} element={<Messages />} />
  207. <Route
  208. path={clusterTopicSettingsRelativePath}
  209. element={<SettingsContainer />}
  210. />
  211. <Route
  212. path={clusterTopicConsumerGroupsRelativePath}
  213. element={<TopicConsumerGroupsContainer />}
  214. />
  215. </Routes>
  216. </div>
  217. );
  218. };
  219. export default Details;