Details.tsx 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. import React from 'react';
  2. import { ClusterName } from 'redux/interfaces';
  3. import {
  4. clusterConsumerGroupResetOffsetsPath,
  5. clusterConsumerGroupsPath,
  6. } from 'lib/paths';
  7. import { ConsumerGroupID } from 'redux/interfaces/consumerGroup';
  8. import PageLoader from 'components/common/PageLoader/PageLoader';
  9. import ConfirmationModal from 'components/common/ConfirmationModal/ConfirmationModal';
  10. import { useHistory, useParams } from 'react-router';
  11. import ClusterContext from 'components/contexts/ClusterContext';
  12. import PageHeading from 'components/common/PageHeading/PageHeading';
  13. import VerticalElipsisIcon from 'components/common/Icons/VerticalElipsisIcon';
  14. import * as Metrics from 'components/common/Metrics';
  15. import { Tag } from 'components/common/Tag/Tag.styled';
  16. import Dropdown from 'components/common/Dropdown/Dropdown';
  17. import DropdownItem from 'components/common/Dropdown/DropdownItem';
  18. import { groupBy } from 'lodash';
  19. import { Table } from 'components/common/table/Table/Table.styled';
  20. import TableHeaderCell from 'components/common/table/TableHeaderCell/TableHeaderCell';
  21. import { useAppDispatch, useAppSelector } from 'lib/hooks/redux';
  22. import {
  23. fetchConsumerGroupDetails,
  24. deleteConsumerGroup,
  25. selectById,
  26. getIsConsumerGroupDeleted,
  27. getAreConsumerGroupDetailsFulfilled,
  28. } from 'redux/reducers/consumerGroups/consumerGroupsSlice';
  29. import getTagColor from 'components/common/Tag/getTagColor';
  30. import ListItem from './ListItem';
  31. const Details: React.FC = () => {
  32. const history = useHistory();
  33. const { isReadOnly } = React.useContext(ClusterContext);
  34. const { consumerGroupID, clusterName } =
  35. useParams<{ consumerGroupID: ConsumerGroupID; clusterName: ClusterName }>();
  36. const dispatch = useAppDispatch();
  37. const consumerGroup = useAppSelector((state) =>
  38. selectById(state, consumerGroupID)
  39. );
  40. const isDeleted = useAppSelector(getIsConsumerGroupDeleted);
  41. const isFetched = useAppSelector(getAreConsumerGroupDetailsFulfilled);
  42. const [isConfirmationModalVisible, setIsConfirmationModalVisible] =
  43. React.useState<boolean>(false);
  44. React.useEffect(() => {
  45. dispatch(fetchConsumerGroupDetails({ clusterName, consumerGroupID }));
  46. }, [clusterName, consumerGroupID, dispatch]);
  47. const onDelete = () => {
  48. setIsConfirmationModalVisible(false);
  49. dispatch(deleteConsumerGroup({ clusterName, consumerGroupID }));
  50. };
  51. React.useEffect(() => {
  52. if (isDeleted) {
  53. history.push(clusterConsumerGroupsPath(clusterName));
  54. }
  55. }, [clusterName, history, isDeleted]);
  56. const onResetOffsets = () => {
  57. history.push(
  58. clusterConsumerGroupResetOffsetsPath(clusterName, consumerGroupID)
  59. );
  60. };
  61. if (!isFetched || !consumerGroup) {
  62. return <PageLoader />;
  63. }
  64. const partitionsByTopic = groupBy(consumerGroup.partitions, 'topic');
  65. return (
  66. <div>
  67. <div>
  68. <PageHeading text={consumerGroupID}>
  69. {!isReadOnly && (
  70. <Dropdown label={<VerticalElipsisIcon />} right>
  71. <DropdownItem onClick={onResetOffsets}>Reset offset</DropdownItem>
  72. <DropdownItem
  73. onClick={() => setIsConfirmationModalVisible(true)}
  74. danger
  75. >
  76. Delete consumer group
  77. </DropdownItem>
  78. </Dropdown>
  79. )}
  80. </PageHeading>
  81. </div>
  82. <Metrics.Wrapper>
  83. <Metrics.Section>
  84. <Metrics.Indicator label="State">
  85. <Tag color={getTagColor(consumerGroup)}>{consumerGroup.state}</Tag>
  86. </Metrics.Indicator>
  87. <Metrics.Indicator label="Members">
  88. {consumerGroup.members}
  89. </Metrics.Indicator>
  90. <Metrics.Indicator label="Assigned Topics">
  91. {consumerGroup.topics}
  92. </Metrics.Indicator>
  93. <Metrics.Indicator label="Assigned Partitions">
  94. {consumerGroup.partitions?.length}
  95. </Metrics.Indicator>
  96. <Metrics.Indicator label="Coordinator ID">
  97. {consumerGroup.coordinator?.id}
  98. </Metrics.Indicator>
  99. </Metrics.Section>
  100. </Metrics.Wrapper>
  101. <Table isFullwidth>
  102. <thead>
  103. <tr>
  104. <TableHeaderCell> </TableHeaderCell>
  105. <TableHeaderCell title="Topic" />
  106. </tr>
  107. </thead>
  108. <tbody>
  109. {Object.keys(partitionsByTopic).map((key) => (
  110. <ListItem
  111. clusterName={clusterName}
  112. consumers={partitionsByTopic[key]}
  113. name={key}
  114. key={key}
  115. />
  116. ))}
  117. </tbody>
  118. </Table>
  119. <ConfirmationModal
  120. isOpen={isConfirmationModalVisible}
  121. onCancel={() => setIsConfirmationModalVisible(false)}
  122. onConfirm={onDelete}
  123. >
  124. Are you sure you want to delete this consumer group?
  125. </ConfirmationModal>
  126. </div>
  127. );
  128. };
  129. export default Details;