List.tsx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. import React from 'react';
  2. import {
  3. TopicWithDetailedInfo,
  4. ClusterName,
  5. TopicName,
  6. } from 'redux/interfaces';
  7. import Breadcrumb from 'components/common/Breadcrumb/Breadcrumb';
  8. import { Link, useParams } from 'react-router-dom';
  9. import { clusterTopicNewPath } from 'lib/paths';
  10. import usePagination from 'lib/hooks/usePagination';
  11. import { FetchTopicsListParams } from 'redux/actions';
  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 ListItem from './ListItem';
  16. interface Props {
  17. areTopicsFetching: boolean;
  18. topics: TopicWithDetailedInfo[];
  19. externalTopics: TopicWithDetailedInfo[];
  20. totalPages: number;
  21. fetchTopicsList(props: FetchTopicsListParams): void;
  22. deleteTopic(topicName: TopicName, clusterName: ClusterName): void;
  23. clearTopicMessages(
  24. topicName: TopicName,
  25. clusterName: ClusterName,
  26. partitions?: number[]
  27. ): void;
  28. }
  29. const List: React.FC<Props> = ({
  30. areTopicsFetching,
  31. topics,
  32. externalTopics,
  33. totalPages,
  34. fetchTopicsList,
  35. deleteTopic,
  36. clearTopicMessages,
  37. }) => {
  38. const { isReadOnly } = React.useContext(ClusterContext);
  39. const { clusterName } = useParams<{ clusterName: ClusterName }>();
  40. const { page, perPage } = usePagination();
  41. React.useEffect(() => {
  42. fetchTopicsList({ clusterName, page, perPage });
  43. }, [fetchTopicsList, clusterName, page, perPage]);
  44. const [showInternal, setShowInternal] = React.useState<boolean>(true);
  45. const handleSwitch = React.useCallback(() => {
  46. setShowInternal(!showInternal);
  47. }, [showInternal]);
  48. const items = showInternal ? topics : externalTopics;
  49. return (
  50. <div className="section">
  51. <Breadcrumb>{showInternal ? `All Topics` : `External Topics`}</Breadcrumb>
  52. <div className="box">
  53. <div className="level">
  54. <div className="level-item level-left">
  55. <div className="field">
  56. <input
  57. id="switchRoundedDefault"
  58. type="checkbox"
  59. name="switchRoundedDefault"
  60. className="switch is-rounded"
  61. checked={showInternal}
  62. onChange={handleSwitch}
  63. />
  64. <label htmlFor="switchRoundedDefault">Show Internal Topics</label>
  65. </div>
  66. </div>
  67. <div className="level-item level-right">
  68. {!isReadOnly && (
  69. <Link
  70. className="button is-primary"
  71. to={clusterTopicNewPath(clusterName)}
  72. >
  73. Add a Topic
  74. </Link>
  75. )}
  76. </div>
  77. </div>
  78. </div>
  79. {areTopicsFetching ? (
  80. <PageLoader />
  81. ) : (
  82. <div className="box">
  83. <div className="table-container">
  84. <table className="table is-fullwidth">
  85. <thead>
  86. <tr>
  87. <th>Topic Name</th>
  88. <th>Total Partitions</th>
  89. <th>Out of sync replicas</th>
  90. <th>Type</th>
  91. <th> </th>
  92. </tr>
  93. </thead>
  94. <tbody>
  95. {items.map((topic) => (
  96. <ListItem
  97. clusterName={clusterName}
  98. key={topic.name}
  99. topic={topic}
  100. deleteTopic={deleteTopic}
  101. clearTopicMessages={clearTopicMessages}
  102. />
  103. ))}
  104. {items.length === 0 && (
  105. <tr>
  106. <td colSpan={10}>No topics found</td>
  107. </tr>
  108. )}
  109. </tbody>
  110. </table>
  111. <Pagination totalPages={totalPages} />
  112. </div>
  113. </div>
  114. )}
  115. </div>
  116. );
  117. };
  118. export default List;