Browse Source

Added replicas data to topic overview page (#1993)

* Added replicas data to topic overview page

* Added tests

* Tests improved

* Some logic moved to css plus some refactoring

* Index removed

* Tests improved
Kirill Morozov 3 years ago
parent
commit
d1c59dd74b

+ 10 - 0
kafka-ui-react-app/src/components/Topics/Topic/Details/Details.styled.ts

@@ -6,3 +6,13 @@ export const DropdownExtraMessage = styled.div`
   width: 100%;
   width: 100%;
   margin-top: 10px;
   margin-top: 10px;
 `;
 `;
+
+export const ReplicaCell = styled.span.attrs({ 'aria-label': 'replica-info' })<{
+  leader: boolean | undefined;
+}>`
+  ${this} ~ ${this}::before {
+    color: black;
+    content: ', ';
+  }
+  color: ${(props) => (props.leader ? 'orange' : null)};
+`;

+ 20 - 10
kafka-ui-react-app/src/components/Topics/Topic/Details/Overview/Overview.tsx

@@ -1,5 +1,5 @@
 import React from 'react';
 import React from 'react';
-import { Topic, TopicDetails } from 'generated-sources';
+import { Partition, Replica, Topic, TopicDetails } from 'generated-sources';
 import { ClusterName, TopicName } from 'redux/interfaces';
 import { ClusterName, TopicName } from 'redux/interfaces';
 import Dropdown from 'components/common/Dropdown/Dropdown';
 import Dropdown from 'components/common/Dropdown/Dropdown';
 import DropdownItem from 'components/common/Dropdown/DropdownItem';
 import DropdownItem from 'components/common/Dropdown/DropdownItem';
@@ -10,6 +10,7 @@ import TableHeaderCell from 'components/common/table/TableHeaderCell/TableHeader
 import VerticalElipsisIcon from 'components/common/Icons/VerticalElipsisIcon';
 import VerticalElipsisIcon from 'components/common/Icons/VerticalElipsisIcon';
 import * as Metrics from 'components/common/Metrics';
 import * as Metrics from 'components/common/Metrics';
 import { Tag } from 'components/common/Tag/Tag.styled';
 import { Tag } from 'components/common/Tag/Tag.styled';
+import { ReplicaCell } from 'components/Topics/Topic/Details/Details.styled';
 
 
 export interface Props extends Topic, TopicDetails {
 export interface Props extends Topic, TopicDetails {
   clusterName: ClusterName;
   clusterName: ClusterName;
@@ -100,7 +101,7 @@ const Overview: React.FC<Props> = ({
           <thead>
           <thead>
             <tr>
             <tr>
               <TableHeaderCell title="Partition ID" />
               <TableHeaderCell title="Partition ID" />
-              <TableHeaderCell title="Broker Leader" />
+              <TableHeaderCell title="Replicas" />
               <TableHeaderCell title="First Offset" />
               <TableHeaderCell title="First Offset" />
               <TableHeaderCell title="Next Offset" />
               <TableHeaderCell title="Next Offset" />
               <TableHeaderCell title="Message Count" />
               <TableHeaderCell title="Message Count" />
@@ -108,13 +109,22 @@ const Overview: React.FC<Props> = ({
             </tr>
             </tr>
           </thead>
           </thead>
           <tbody>
           <tbody>
-            {partitions?.map(({ partition, leader, offsetMin, offsetMax }) => (
-              <tr key={`partition-list-item-key-${partition}`}>
-                <td>{partition}</td>
-                <td>{leader}</td>
-                <td>{offsetMin}</td>
-                <td>{offsetMax}</td>
-                <td>{offsetMax - offsetMin}</td>
+            {partitions?.map((partition: Partition) => (
+              <tr key={`partition-list-item-key-${partition.partition}`}>
+                <td>{partition.partition}</td>
+                <td>
+                  {partition.replicas?.map((replica: Replica) => (
+                    <ReplicaCell
+                      leader={replica.leader}
+                      key={`replica-list-item-key-${replica.broker}`}
+                    >
+                      {replica.broker}
+                    </ReplicaCell>
+                  ))}
+                </td>
+                <td>{partition.offsetMin}</td>
+                <td>{partition.offsetMax}</td>
+                <td>{partition.offsetMax - partition.offsetMin}</td>
                 <td style={{ width: '5%' }}>
                 <td style={{ width: '5%' }}>
                   {!internal && !isReadOnly && cleanUpPolicy === 'DELETE' ? (
                   {!internal && !isReadOnly && cleanUpPolicy === 'DELETE' ? (
                     <Dropdown label={<VerticalElipsisIcon />} right>
                     <Dropdown label={<VerticalElipsisIcon />} right>
@@ -123,7 +133,7 @@ const Overview: React.FC<Props> = ({
                           clearTopicMessages({
                           clearTopicMessages({
                             clusterName,
                             clusterName,
                             topicName,
                             topicName,
-                            partitions: [partition],
+                            partitions: [partition.partition],
                           })
                           })
                         }
                         }
                         danger
                         danger

+ 19 - 1
kafka-ui-react-app/src/components/Topics/Topic/Details/Overview/__test__/Overview.spec.tsx

@@ -8,8 +8,10 @@ import theme from 'theme/theme';
 import { CleanUpPolicy } from 'generated-sources';
 import { CleanUpPolicy } from 'generated-sources';
 import ClusterContext from 'components/contexts/ClusterContext';
 import ClusterContext from 'components/contexts/ClusterContext';
 import userEvent from '@testing-library/user-event';
 import userEvent from '@testing-library/user-event';
+import { ReplicaCell } from 'components/Topics/Topic/Details/Details.styled';
 
 
 describe('Overview', () => {
 describe('Overview', () => {
+  const getReplicaCell = () => screen.getByLabelText('replica-info');
   const mockClusterName = 'local';
   const mockClusterName = 'local';
   const mockTopicName = 'topic';
   const mockTopicName = 'topic';
   const mockClearTopicMessages = jest.fn();
   const mockClearTopicMessages = jest.fn();
@@ -20,7 +22,7 @@ describe('Overview', () => {
       replicas: [
       replicas: [
         {
         {
           broker: 1,
           broker: 1,
-          leader: false,
+          leader: true,
           inSync: true,
           inSync: true,
         },
         },
       ],
       ],
@@ -66,6 +68,22 @@ describe('Overview', () => {
     mockClearTopicMessages.mockClear();
     mockClearTopicMessages.mockClear();
   });
   });
 
 
+  it('at least one replica was rendered', () => {
+    setupComponent({
+      ...defaultProps,
+      underReplicatedPartitions: 0,
+      inSyncReplicas: 1,
+      replicas: 1,
+    });
+    expect(getReplicaCell()).toBeInTheDocument();
+  });
+
+  it('renders replica cell with props', () => {
+    render(<ReplicaCell leader />);
+    expect(getReplicaCell()).toBeInTheDocument();
+    expect(getReplicaCell()).toHaveStyleRule('color', 'orange');
+  });
+
   describe('when it has internal flag', () => {
   describe('when it has internal flag', () => {
     it('does not render the Action button a Topic', () => {
     it('does not render the Action button a Topic', () => {
       setupComponent({
       setupComponent({