List.tsx 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. import React from 'react';
  2. import { useHistory } from 'react-router';
  3. import {
  4. TopicWithDetailedInfo,
  5. ClusterName,
  6. TopicName,
  7. } from 'redux/interfaces';
  8. import Breadcrumb from 'components/common/Breadcrumb/Breadcrumb';
  9. import { Link, useParams } from 'react-router-dom';
  10. import { clusterTopicNewPath } from 'lib/paths';
  11. import usePagination from 'lib/hooks/usePagination';
  12. import ClusterContext from 'components/contexts/ClusterContext';
  13. import PageLoader from 'components/common/PageLoader/PageLoader';
  14. import Pagination from 'components/common/Pagination/Pagination';
  15. import { GetTopicsRequest, TopicColumnsToSort } from 'generated-sources';
  16. import SortableColumnHeader from 'components/common/table/SortableCulumnHeader/SortableColumnHeader';
  17. import Search from 'components/common/Search/Search';
  18. import { PER_PAGE } from 'lib/constants';
  19. import ListItem from './ListItem';
  20. export interface TopicsListProps {
  21. areTopicsFetching: boolean;
  22. topics: TopicWithDetailedInfo[];
  23. totalPages: number;
  24. fetchTopicsList(props: GetTopicsRequest): void;
  25. deleteTopic(topicName: TopicName, clusterName: ClusterName): void;
  26. clearTopicMessages(
  27. topicName: TopicName,
  28. clusterName: ClusterName,
  29. partitions?: number[]
  30. ): void;
  31. search: string;
  32. orderBy: TopicColumnsToSort | null;
  33. setTopicsSearch(search: string): void;
  34. setTopicsOrderBy(orderBy: TopicColumnsToSort | null): void;
  35. }
  36. const List: React.FC<TopicsListProps> = ({
  37. areTopicsFetching,
  38. topics,
  39. totalPages,
  40. fetchTopicsList,
  41. deleteTopic,
  42. clearTopicMessages,
  43. search,
  44. orderBy,
  45. setTopicsSearch,
  46. setTopicsOrderBy,
  47. }) => {
  48. const { isReadOnly } = React.useContext(ClusterContext);
  49. const { clusterName } = useParams<{ clusterName: ClusterName }>();
  50. const { page, perPage, pathname } = usePagination();
  51. const [showInternal, setShowInternal] = React.useState<boolean>(true);
  52. const history = useHistory();
  53. React.useEffect(() => {
  54. fetchTopicsList({
  55. clusterName,
  56. page,
  57. perPage,
  58. orderBy: orderBy || undefined,
  59. search,
  60. showInternal,
  61. });
  62. }, [
  63. fetchTopicsList,
  64. clusterName,
  65. page,
  66. perPage,
  67. orderBy,
  68. search,
  69. showInternal,
  70. ]);
  71. const handleSwitch = React.useCallback(() => {
  72. setShowInternal(!showInternal);
  73. history.push(`${pathname}?page=1&perPage=${perPage || PER_PAGE}`);
  74. }, [showInternal]);
  75. return (
  76. <div className="section">
  77. <Breadcrumb>{showInternal ? `All Topics` : `External Topics`}</Breadcrumb>
  78. <div className="box">
  79. <div className="columns">
  80. <div className="column is-one-quarter is-align-items-center is-flex">
  81. <div className="field">
  82. <input
  83. id="switchRoundedDefault"
  84. type="checkbox"
  85. name="switchRoundedDefault"
  86. className="switch is-rounded"
  87. checked={showInternal}
  88. onChange={handleSwitch}
  89. />
  90. <label htmlFor="switchRoundedDefault">Show Internal Topics</label>
  91. </div>
  92. </div>
  93. <div className="column">
  94. <Search
  95. handleSearch={setTopicsSearch}
  96. placeholder="Search by Topic Name"
  97. value={search}
  98. />
  99. </div>
  100. <div className="column is-2 is-justify-content-flex-end is-flex">
  101. {!isReadOnly && (
  102. <Link
  103. className="button is-primary"
  104. to={clusterTopicNewPath(clusterName)}
  105. >
  106. Add a Topic
  107. </Link>
  108. )}
  109. </div>
  110. </div>
  111. </div>
  112. {areTopicsFetching ? (
  113. <PageLoader />
  114. ) : (
  115. <div className="box">
  116. <table className="table is-fullwidth">
  117. <thead>
  118. <tr>
  119. <SortableColumnHeader
  120. value={TopicColumnsToSort.NAME}
  121. title="Topic Name"
  122. orderBy={orderBy}
  123. setOrderBy={setTopicsOrderBy}
  124. />
  125. <SortableColumnHeader
  126. value={TopicColumnsToSort.TOTAL_PARTITIONS}
  127. title="Total Partitions"
  128. orderBy={orderBy}
  129. setOrderBy={setTopicsOrderBy}
  130. />
  131. <SortableColumnHeader
  132. value={TopicColumnsToSort.OUT_OF_SYNC_REPLICAS}
  133. title="Out of sync replicas"
  134. orderBy={orderBy}
  135. setOrderBy={setTopicsOrderBy}
  136. />
  137. <th>Replication Factor</th>
  138. <th>Number of messages</th>
  139. <th>Size</th>
  140. <th>Type</th>
  141. <th>Clean Up Policy</th>
  142. <th> </th>
  143. </tr>
  144. </thead>
  145. <tbody>
  146. {topics.map((topic) => (
  147. <ListItem
  148. clusterName={clusterName}
  149. key={topic.name}
  150. topic={topic}
  151. deleteTopic={deleteTopic}
  152. clearTopicMessages={clearTopicMessages}
  153. />
  154. ))}
  155. {topics.length === 0 && (
  156. <tr>
  157. <td colSpan={10}>No topics found</td>
  158. </tr>
  159. )}
  160. </tbody>
  161. </table>
  162. <Pagination totalPages={totalPages} />
  163. </div>
  164. )}
  165. </div>
  166. );
  167. };
  168. export default List;