Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add production/consumption to topic list and topic overview #2789

Draft
wants to merge 20 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import React from 'react';
import { CellContext } from '@tanstack/react-table';
import { Topic } from 'generated-sources';
import BytesFormatted from 'components/common/BytesFormatted/BytesFormatted';
import CircleArrowDownIcon from 'components/common/Icons/CircleArrowDownIcon';
import CircleArrowUpIcon from 'components/common/Icons/CircleArrowUpIcon';
import styled from 'styled-components';

const Wrapper = styled.div`
display: flex;
span {
display: flex;
align-items: center;
&:first-child {
margin-right: 10px;
}
& > svg {
margin-right: 5px;
}
}
`;
export const ThroughputCell: React.FC<CellContext<Topic, unknown>> = ({
row: { original },
}) => {
const production = original.bytesInPerSec;
const consumption = original.bytesOutPerSec;

if (production === undefined && consumption === undefined) {
return (
<Wrapper>
<span>
<CircleArrowDownIcon />
N/A
</span>
<span>
<CircleArrowUpIcon />
N/A
</span>
</Wrapper>
);
}
if (production === undefined) {
return (
<Wrapper>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can refactor this part in a tiny component. and use it in this conditions.

one question why are we checking if (production === undefined) instead of if(!production).

Copy link
Contributor

@David-DB88 David-DB88 May 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Mgrdich i just change conditions take a look please if its normal ?

<span>
<CircleArrowUpIcon /> <BytesFormatted value={consumption} />
</span>
</Wrapper>
);
}
if (consumption === undefined) {
return (
<Wrapper>
<span>
<CircleArrowDownIcon /> <BytesFormatted value={production} />
</span>
</Wrapper>
);
}

return (
<Wrapper>
<span>
<CircleArrowDownIcon /> <BytesFormatted value={production} />
</span>
<span>
<CircleArrowUpIcon /> <BytesFormatted value={consumption} />
</span>
</Wrapper>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { PER_PAGE } from 'lib/constants';
import { TopicTitleCell } from './TopicTitleCell';
import ActionsCell from './ActionsCell';
import BatchActionsbar from './BatchActionsBar';
import { ThroughputCell } from './ThroughputCell';

const TopicTable: React.FC = () => {
const { clusterName } = useAppParams<{ clusterName: ClusterName }>();
Expand Down Expand Up @@ -85,6 +86,11 @@ const TopicTable: React.FC = () => {
accessorKey: 'segmentSize',
cell: SizeCell,
},
{
header: 'Speed',
enableSorting: false,
cell: ThroughputCell,
},
{
id: 'actions',
header: '',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,21 +98,47 @@ describe('TopicTable Components', () => {
screen.getByRole('link', { name: '__internal.topic' })
).toBeInTheDocument();
expect(
screen.getByRole('row', { name: '__internal.topic 1 0 1 0 0 Bytes' })
screen.getByRole('row', {
name: /__internal.topic 1 0 1 0 0 Bytes* N\/A/,
})
).toBeInTheDocument();
expect(
screen.getByRole('link', { name: '__internal.topic2' })
).toBeInTheDocument();
expect(
screen.getByRole('row', {
name: /__internal.topic2 1 0 1 0* 0 Bytes* 0 Bytes/,
})
).toBeInTheDocument();
expect(
screen.getByRole('link', { name: '__internal.topic3' })
).toBeInTheDocument();
expect(
screen.getByRole('row', {
name: /__internal.topic3 1 0 1 0* 0 Bytes* 0 Bytes/,
})
).toBeInTheDocument();
expect(
screen.getByRole('link', { name: '__internal.topic4' })
).toBeInTheDocument();
expect(
screen.getByRole('row', {
name: /__internal.topic4 1 0 1 0 0 Bytes* 0 Bytes* 0 Bytes/,
})
).toBeInTheDocument();
expect(
screen.getByRole('link', { name: 'external.topic' })
).toBeInTheDocument();
expect(
screen.getByRole('row', { name: 'external.topic 1 0 1 0 1 KB' })
screen.getByRole('row', { name: /external.topic 1 0 1 0 1 KB* N\/A / })
).toBeInTheDocument();

expect(screen.getAllByRole('checkbox').length).toEqual(3);
expect(screen.getAllByRole('checkbox').length).toEqual(6);
});
describe('Selectable rows', () => {
it('renders selectable rows', () => {
renderComponent({ topics: topicsPayload, pageCount: 1 });
expect(screen.getAllByRole('checkbox').length).toEqual(3);
expect(screen.getAllByRole('checkbox').length).toEqual(6);
// Disable checkbox for internal topic
expect(screen.getAllByRole('checkbox')[1]).toBeDisabled();
// Disable checkbox for external topic
Expand Down Expand Up @@ -214,10 +240,10 @@ describe('TopicTable Components', () => {
await renderComponent({ topics: topicsPayload, pageCount: 1 });
expect(
screen.getAllByRole('button', { name: 'Dropdown Toggle' }).length
).toEqual(2);
).toEqual(5);
// Internal topic action buttons are disabled
const internalTopicRow = screen.getByRole('row', {
name: '__internal.topic 1 0 1 0 0 Bytes',
name: /__internal.topic 1 0 1 0 0 Bytes* N\/A/,
});
expect(internalTopicRow).toBeInTheDocument();
expect(
Expand All @@ -227,7 +253,7 @@ describe('TopicTable Components', () => {
).toBeDisabled();
// External topic action buttons are enabled
const externalTopicRow = screen.getByRole('row', {
name: 'external.topic 1 0 1 0 1 KB',
name: /external.topic 1 0 1 0 1 KB* N\/A/,
});
expect(externalTopicRow).toBeInTheDocument();
const extBtn = within(externalTopicRow).getByRole('button', {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,12 @@ const Overview: React.FC = () => {
<Metrics.Indicator label="Message Count">
{messageCount}
</Metrics.Indicator>
<Metrics.Indicator label="Production">
<BytesFormatted value={data?.bytesInPerSec} />
</Metrics.Indicator>
<Metrics.Indicator label="Consumption">
<BytesFormatted value={data?.bytesOutPerSec} />
</Metrics.Indicator>
</Metrics.Section>
</Metrics.Wrapper>
<Table
Expand Down
26 changes: 26 additions & 0 deletions kafka-ui-react-app/src/components/common/Icons/ArrowUpIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from 'react';

const ArrowUpIcon: React.FC = () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="8"
height="10"
viewBox="0 0 8 10"
>
{/* Font Awesome Pro 6.1.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. */}
<path
fillRule="evenodd"
clipRule="evenodd"
d="M4 10C3.44772 10 3 9.55228 3 9L3 1C3 0.447714 3.44772 -3.97973e-07 4 -3.49691e-07C4.55229 -3.01409e-07 5 0.447715 5 1L5 9C5 9.55228 4.55228 10 4 10Z"
fill="#73848C"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M7.70711 4.70711C7.31658 5.09763 6.68342 5.09763 6.29289 4.70711L4 2.41421L1.70711 4.70711C1.31658 5.09763 0.683418 5.09763 0.292893 4.70711C-0.097631 4.31658 -0.0976309 3.68342 0.292893 3.29289L3.29289 0.292893C3.68342 -0.0976318 4.31658 -0.0976318 4.70711 0.292893L7.70711 3.29289C8.09763 3.68342 8.09763 4.31658 7.70711 4.70711Z"
fill="#73848C"
/>
</svg>
);

export default ArrowUpIcon;
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from 'react';

const CircleArrowDownIcon: React.FC = () => {
return (
<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<circle cx="8" cy="8" r="8" fill="#E3E6E8" />
<path
fillRule="evenodd"
clipRule="evenodd"
d="M8 3C8.55228 3 9 3.44772 9 4L9 12C9 12.5523 8.55229 13 8 13C7.44772 13 7 12.5523 7 12L7 4C7 3.44772 7.44772 3 8 3Z"
fill="#73848C"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M4.29289 8.29289C4.68342 7.90237 5.31658 7.90237 5.70711 8.29289L8 10.5858L10.2929 8.29289C10.6834 7.90237 11.3166 7.90237 11.7071 8.29289C12.0976 8.68342 12.0976 9.31658 11.7071 9.70711L8.70711 12.7071C8.31658 13.0976 7.68342 13.0976 7.29289 12.7071L4.29289 9.70711C3.90237 9.31658 3.90237 8.68342 4.29289 8.29289Z"
fill="#73848C"
/>
</svg>
);
};
export default CircleArrowDownIcon;
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from 'react';

const CircleArrowUpIcon: React.FC = () => {
return (
<svg
width="16"
height="17"
viewBox="0 0 16 17"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<circle cx="8" cy="8.25781" r="8" fill="#E3E6E8" />
<path
fillRule="evenodd"
clipRule="evenodd"
d="M8 13.2578C7.44772 13.2578 7 12.8101 7 12.2578L7 4.25781C7 3.70553 7.44772 3.25781 8 3.25781C8.55229 3.25781 9 3.70553 9 4.25781L9 12.2578C9 12.8101 8.55228 13.2578 8 13.2578Z"
fill="#73848C"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M11.7071 7.96492C11.3166 8.35544 10.6834 8.35544 10.2929 7.96492L8 5.67203L5.70711 7.96492C5.31658 8.35544 4.68342 8.35544 4.29289 7.96492C3.90237 7.57439 3.90237 6.94123 4.29289 6.5507L7.29289 3.55071C7.68342 3.16018 8.31658 3.16018 8.70711 3.55071L11.7071 6.55071C12.0976 6.94123 12.0976 7.57439 11.7071 7.96492Z"
fill="#73848C"
/>
</svg>
);
};
export default CircleArrowUpIcon;
70 changes: 70 additions & 0 deletions kafka-ui-react-app/src/lib/fixtures/topics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,79 @@ export const externalTopicPayload = {
],
};

export const internalTopicBytesInPayload = {
name: '__internal.topic2',
internal: true,
partitionCount: 1,
replicationFactor: 1,
replicas: 1,
inSyncReplicas: 1,
segmentSize: 0,
segmentCount: 1,
underReplicatedPartitions: 0,
partitions: [
{
partition: 0,
leader: 1,
replicas: [{ broker: 1, leader: false, inSync: true }],
offsetMax: 0,
offsetMin: 0,
},
],
bytesInPerSec: 0,
};

export const internalTopicBytesOutPayload = {
name: '__internal.topic3',
internal: true,
partitionCount: 1,
replicationFactor: 1,
replicas: 1,
inSyncReplicas: 1,
segmentSize: 0,
segmentCount: 1,
underReplicatedPartitions: 0,
partitions: [
{
partition: 0,
leader: 1,
replicas: [{ broker: 1, leader: false, inSync: true }],
offsetMax: 0,
offsetMin: 0,
},
],
bytesOutPerSec: 0,
};

export const internalTopicThroughputPayload = {
name: '__internal.topic4',
internal: true,
partitionCount: 1,
replicationFactor: 1,
replicas: 1,
inSyncReplicas: 1,
segmentSize: 0,
segmentCount: 1,
underReplicatedPartitions: 0,
partitions: [
{
partition: 0,
leader: 1,
replicas: [{ broker: 1, leader: false, inSync: true }],
offsetMax: 0,
offsetMin: 0,
},
],
bytesInPerSec: 0,
bytesOutPerSec: 0,
};

export const topicsPayload: Topic[] = [
internalTopicPayload,
externalTopicPayload,
internalTopicBytesInPayload,
internalTopicBytesOutPayload,
internalTopicThroughputPayload,
];

export const topicConsumerGroups: ConsumerGroup[] = [
Expand Down