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
This commit is contained in:
Kirill Morozov 2022-05-19 14:44:26 +03:00 committed by GitHub
parent ca545ddf36
commit d1c59dd74b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 49 additions and 11 deletions

View file

@ -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)};
`;

View file

@ -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 }) => ( {partitions?.map((partition: Partition) => (
<tr key={`partition-list-item-key-${partition}`}> <tr key={`partition-list-item-key-${partition.partition}`}>
<td>{partition}</td> <td>{partition.partition}</td>
<td>{leader}</td> <td>
<td>{offsetMin}</td> {partition.replicas?.map((replica: Replica) => (
<td>{offsetMax}</td> <ReplicaCell
<td>{offsetMax - offsetMin}</td> 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

View file

@ -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({