123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- import { Table } from 'components/common/table/Table/Table.styled';
- import TableHeaderCell from 'components/common/table/TableHeaderCell/TableHeaderCell';
- import { ConsumerGroupTopicPartition, SortOrder } from 'generated-sources';
- import React from 'react';
- import { ContentBox, TopicContentWrapper } from './TopicContent.styled';
- interface Props {
- consumers: ConsumerGroupTopicPartition[];
- }
- type OrderByKey = keyof ConsumerGroupTopicPartition;
- interface Headers {
- title: string;
- orderBy: OrderByKey | undefined;
- }
- const TABLE_HEADERS_MAP: Headers[] = [
- { title: 'Partition', orderBy: 'partition' },
- { title: 'Consumer ID', orderBy: 'consumerId' },
- { title: 'Host', orderBy: 'host' },
- { title: 'Messages Behind', orderBy: 'messagesBehind' },
- { title: 'Current Offset', orderBy: 'currentOffset' },
- { title: 'End offset', orderBy: 'endOffset' },
- ];
- const ipV4ToNum = (ip?: string) => {
- if (typeof ip === 'string' && ip.length !== 0) {
- const withoutSlash = ip.indexOf('/') !== -1 ? ip.slice(1) : ip;
- return Number(
- withoutSlash
- .split('.')
- .map((octet) => `000${octet}`.slice(-3))
- .join('')
- );
- }
- return 0;
- };
- type ComparatorFunction<T> = (
- valueA: T,
- valueB: T,
- order: SortOrder,
- property?: keyof T
- ) => number;
- const numberComparator: ComparatorFunction<ConsumerGroupTopicPartition> = (
- valueA,
- valueB,
- order,
- property
- ) => {
- if (property !== undefined) {
- return order === SortOrder.ASC
- ? Number(valueA[property]) - Number(valueB[property])
- : Number(valueB[property]) - Number(valueA[property]);
- }
- return 0;
- };
- const ipComparator: ComparatorFunction<ConsumerGroupTopicPartition> = (
- valueA,
- valueB,
- order
- ) =>
- order === SortOrder.ASC
- ? ipV4ToNum(valueA.host) - ipV4ToNum(valueB.host)
- : ipV4ToNum(valueB.host) - ipV4ToNum(valueA.host);
- const consumerIdComparator: ComparatorFunction<ConsumerGroupTopicPartition> = (
- valueA,
- valueB,
- order
- ) => {
- if (valueA.consumerId && valueB.consumerId) {
- if (order === SortOrder.ASC) {
- if (valueA.consumerId?.toLowerCase() > valueB.consumerId?.toLowerCase()) {
- return 1;
- }
- }
- if (order === SortOrder.DESC) {
- if (valueB.consumerId?.toLowerCase() > valueA.consumerId?.toLowerCase()) {
- return -1;
- }
- }
- }
- return 0;
- };
- const TopicContents: React.FC<Props> = ({ consumers }) => {
- const [orderBy, setOrderBy] = React.useState<OrderByKey>('partition');
- const [sortOrder, setSortOrder] = React.useState<SortOrder>(SortOrder.DESC);
- const handleOrder = React.useCallback((columnName: string | null) => {
- if (typeof columnName === 'string') {
- setOrderBy(columnName as OrderByKey);
- setSortOrder((prevOrder) =>
- prevOrder === SortOrder.DESC ? SortOrder.ASC : SortOrder.DESC
- );
- }
- }, []);
- const sortedConsumers = React.useMemo(() => {
- if (orderBy && sortOrder) {
- const isNumberProperty =
- orderBy === 'partition' ||
- orderBy === 'currentOffset' ||
- orderBy === 'endOffset' ||
- orderBy === 'messagesBehind';
- let comparator: ComparatorFunction<ConsumerGroupTopicPartition>;
- if (isNumberProperty) {
- comparator = numberComparator;
- }
- if (orderBy === 'host') {
- comparator = ipComparator;
- }
- if (orderBy === 'consumerId') {
- comparator = consumerIdComparator;
- }
- return consumers.sort((a, b) => comparator(a, b, sortOrder, orderBy));
- }
- return consumers;
- }, [orderBy, sortOrder, consumers]);
- return (
- <TopicContentWrapper>
- <td colSpan={3}>
- <ContentBox>
- <Table isFullwidth>
- <thead>
- <tr>
- {TABLE_HEADERS_MAP.map((header) => (
- <TableHeaderCell
- key={header.orderBy}
- title={header.title}
- orderBy={orderBy}
- sortOrder={sortOrder}
- orderValue={header.orderBy}
- handleOrderBy={handleOrder}
- />
- ))}
- </tr>
- </thead>
- <tbody>
- {sortedConsumers.map((consumer) => (
- <tr key={consumer.partition}>
- <td>{consumer.partition}</td>
- <td>{consumer.consumerId}</td>
- <td>{consumer.host}</td>
- <td>{consumer.messagesBehind}</td>
- <td>{consumer.currentOffset}</td>
- <td>{consumer.endOffset}</td>
- </tr>
- ))}
- </tbody>
- </Table>
- </ContentBox>
- </td>
- </TopicContentWrapper>
- );
- };
- export default TopicContents;
|