ListItem.tsx 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. import React from 'react';
  2. import {
  3. ClusterName,
  4. TopicName,
  5. TopicWithDetailedInfo,
  6. } from 'redux/interfaces';
  7. import DropdownItem from 'components/common/Dropdown/DropdownItem';
  8. import Dropdown from 'components/common/Dropdown/Dropdown';
  9. import ConfirmationModal from 'components/common/ConfirmationModal/ConfirmationModal';
  10. import ClusterContext from 'components/contexts/ClusterContext';
  11. import BytesFormatted from 'components/common/BytesFormatted/BytesFormatted';
  12. import { Tag } from 'components/common/Tag/Tag.styled';
  13. import VerticalElipsisIcon from 'components/common/Icons/VerticalElipsisIcon';
  14. import { TableKeyLink } from 'components/common/table/Table/TableKeyLink.styled';
  15. import * as S from './List.styled';
  16. export interface ListItemProps {
  17. topic: TopicWithDetailedInfo;
  18. selected: boolean;
  19. toggleTopicSelected(topicName: TopicName): void;
  20. deleteTopic: (clusterName: ClusterName, topicName: TopicName) => void;
  21. recreateTopic: (clusterName: ClusterName, topicName: TopicName) => void;
  22. clusterName: ClusterName;
  23. clearTopicMessages(topicName: TopicName, clusterName: ClusterName): void;
  24. }
  25. const ListItem: React.FC<ListItemProps> = ({
  26. topic: {
  27. name,
  28. internal,
  29. partitions,
  30. segmentSize,
  31. replicationFactor,
  32. cleanUpPolicy,
  33. },
  34. selected,
  35. toggleTopicSelected,
  36. deleteTopic,
  37. recreateTopic,
  38. clusterName,
  39. clearTopicMessages,
  40. }) => {
  41. const { isReadOnly, isTopicDeletionAllowed } =
  42. React.useContext(ClusterContext);
  43. const [isDeleteTopicConfirmationVisible, setDeleteTopicConfirmationVisible] =
  44. React.useState(false);
  45. const [
  46. isRecreateTopicConfirmationVisible,
  47. setRecreateTopicConfirmationVisible,
  48. ] = React.useState(false);
  49. const { outOfSyncReplicas, numberOfMessages } = React.useMemo(() => {
  50. if (partitions === undefined || partitions.length === 0) {
  51. return {
  52. outOfSyncReplicas: 0,
  53. numberOfMessages: 0,
  54. };
  55. }
  56. return partitions.reduce(
  57. (memo, { replicas, offsetMax, offsetMin }) => {
  58. const outOfSync = replicas?.filter(({ inSync }) => !inSync);
  59. return {
  60. outOfSyncReplicas: memo.outOfSyncReplicas + (outOfSync?.length || 0),
  61. numberOfMessages: memo.numberOfMessages + (offsetMax - offsetMin),
  62. };
  63. },
  64. {
  65. outOfSyncReplicas: 0,
  66. numberOfMessages: 0,
  67. }
  68. );
  69. }, [partitions]);
  70. const deleteTopicHandler = React.useCallback(() => {
  71. deleteTopic(clusterName, name);
  72. }, [clusterName, deleteTopic, name]);
  73. const recreateTopicHandler = React.useCallback(() => {
  74. recreateTopic(clusterName, name);
  75. setRecreateTopicConfirmationVisible(false);
  76. }, [recreateTopic, clusterName, name]);
  77. const clearTopicMessagesHandler = React.useCallback(() => {
  78. clearTopicMessages(clusterName, name);
  79. }, [clearTopicMessages, clusterName, name]);
  80. const [vElipsisVisble, setVElipsisVisble] = React.useState(false);
  81. return (
  82. <tr
  83. onMouseEnter={() => setVElipsisVisble(true)}
  84. onMouseLeave={() => setVElipsisVisble(false)}
  85. >
  86. {!isReadOnly && (
  87. <td>
  88. {!internal && (
  89. <input
  90. type="checkbox"
  91. checked={selected}
  92. onChange={() => {
  93. toggleTopicSelected(name);
  94. }}
  95. />
  96. )}
  97. </td>
  98. )}
  99. <TableKeyLink style={{ width: '44%' }}>
  100. {internal && <Tag color="gray">IN</Tag>}
  101. <S.Link exact to={`topics/${name}`} $isInternal={internal}>
  102. {name}
  103. </S.Link>
  104. </TableKeyLink>
  105. <td>{partitions?.length}</td>
  106. <td>{outOfSyncReplicas}</td>
  107. <td>{replicationFactor}</td>
  108. <td>{numberOfMessages}</td>
  109. <td>
  110. <BytesFormatted value={segmentSize} />
  111. </td>
  112. <td className="topic-action-block" style={{ width: '4%' }}>
  113. {!internal && !isReadOnly && vElipsisVisble ? (
  114. <div className="has-text-right">
  115. <Dropdown label={<VerticalElipsisIcon />} right>
  116. {cleanUpPolicy === 'DELETE' && (
  117. <DropdownItem onClick={clearTopicMessagesHandler} danger>
  118. Clear Messages
  119. </DropdownItem>
  120. )}
  121. {isTopicDeletionAllowed && (
  122. <DropdownItem
  123. onClick={() => setDeleteTopicConfirmationVisible(true)}
  124. danger
  125. >
  126. Remove Topic
  127. </DropdownItem>
  128. )}
  129. <DropdownItem
  130. onClick={() => setRecreateTopicConfirmationVisible(true)}
  131. danger
  132. >
  133. Recreate Topic
  134. </DropdownItem>
  135. </Dropdown>
  136. </div>
  137. ) : null}
  138. <ConfirmationModal
  139. isOpen={isDeleteTopicConfirmationVisible}
  140. onCancel={() => setDeleteTopicConfirmationVisible(false)}
  141. onConfirm={deleteTopicHandler}
  142. >
  143. Are you sure want to remove <b>{name}</b> topic?
  144. </ConfirmationModal>
  145. <ConfirmationModal
  146. isOpen={isRecreateTopicConfirmationVisible}
  147. onCancel={() => setRecreateTopicConfirmationVisible(false)}
  148. onConfirm={recreateTopicHandler}
  149. >
  150. Are you sure to recreate <b>{name}</b> topic?
  151. </ConfirmationModal>
  152. </td>
  153. </tr>
  154. );
  155. };
  156. export default ListItem;