From 2f19a43d2d2b77e56f6e66dfbb34891a7e324ab4 Mon Sep 17 00:00:00 2001
From: alexeykozyurov <akozyurov@provectus.com>
Date: Mon, 12 Feb 2024 23:33:40 +0700
Subject: [PATCH 1/6] Brokers list refactoring.

---
 .../Brokers/BrokersList/BrokersList.tsx       | 353 +++++++-----------
 .../BrokersMetrics/BrokersMetrics.styled.ts   |   5 +
 .../BrokersMetrics/BrokersMetrics.tsx         | 105 ++++++
 .../TableCells.styled.ts}                     |   4 -
 .../BrokersList/TableCells/TableCells.tsx     |  86 +++++
 .../Brokers/BrokersList/lib/constants.ts      |   1 +
 .../Brokers/BrokersList/lib/index.ts          |   3 +
 .../Brokers/BrokersList/lib/types.ts          |  12 +
 .../Brokers/BrokersList/lib/utils.ts          |  76 ++++
 .../components/common/NewTable/SizeCell.tsx   |   2 +-
 .../src/components/common/NewTable/Table.tsx  |  21 +-
 11 files changed, 444 insertions(+), 224 deletions(-)
 create mode 100644 frontend/src/components/Brokers/BrokersList/BrokersMetrics/BrokersMetrics.styled.ts
 create mode 100644 frontend/src/components/Brokers/BrokersList/BrokersMetrics/BrokersMetrics.tsx
 rename frontend/src/components/Brokers/BrokersList/{BrokersList.styled.ts => TableCells/TableCells.styled.ts} (64%)
 create mode 100644 frontend/src/components/Brokers/BrokersList/TableCells/TableCells.tsx
 create mode 100644 frontend/src/components/Brokers/BrokersList/lib/constants.ts
 create mode 100644 frontend/src/components/Brokers/BrokersList/lib/index.ts
 create mode 100644 frontend/src/components/Brokers/BrokersList/lib/types.ts
 create mode 100644 frontend/src/components/Brokers/BrokersList/lib/utils.ts

diff --git a/frontend/src/components/Brokers/BrokersList/BrokersList.tsx b/frontend/src/components/Brokers/BrokersList/BrokersList.tsx
index ede570c65..1555d213a 100644
--- a/frontend/src/components/Brokers/BrokersList/BrokersList.tsx
+++ b/frontend/src/components/Brokers/BrokersList/BrokersList.tsx
@@ -1,22 +1,138 @@
-import React from 'react';
+import React, { useMemo } from 'react';
 import { ClusterName } from 'redux/interfaces';
 import { useNavigate } from 'react-router-dom';
 import PageHeading from 'components/common/PageHeading/PageHeading';
-import * as Metrics from 'components/common/Metrics';
 import useAppParams from 'lib/hooks/useAppParams';
-import { useBrokers } from 'lib/hooks/api/brokers';
-import { useClusterStats } from 'lib/hooks/api/clusters';
-import Table, { LinkCell, SizeCell } from 'components/common/NewTable';
-import CheckMarkRoundIcon from 'components/common/Icons/CheckMarkRoundIcon';
-import { ColumnDef } from '@tanstack/react-table';
+import Table from 'components/common/NewTable';
 import { clusterBrokerPath } from 'lib/paths';
-import Tooltip from 'components/common/Tooltip/Tooltip';
-import ColoredCell from 'components/common/NewTable/ColoredCell';
+import { useClusterStats } from 'lib/hooks/api/clusters';
+import { useBrokers } from 'lib/hooks/api/brokers';
 
-import SkewHeader from './SkewHeader/SkewHeader';
-import * as S from './BrokersList.styled';
+import { BrokersMetrics } from './BrokersMetrics/BrokersMetrics';
+import { getBrokersTableColumns, getBrokersTableRows } from './lib';
 
-const NA = 'N/A';
+// const brokers = JSON.parse(
+//   '[\n' +
+//     '    {\n' +
+//     '        "id": 1,\n' +
+//     '        "host": "test-region-1-broker-1.kafka",\n' +
+//     '        "port": 9092,\n' +
+//     '        "bytesInPerSec": null,\n' +
+//     '        "bytesOutPerSec": null,\n' +
+//     '        "partitionsLeader": 18,\n' +
+//     '        "partitions": 110,\n' +
+//     '        "inSyncPartitions": 110,\n' +
+//     '        "partitionsSkew": 0.0,\n' +
+//     '        "leadersSkew": -1.8\n' +
+//     '    },\n' +
+//     '    {\n' +
+//     '        "id": 2,\n' +
+//     '        "host": "test-region-1-broker-2.kafka",\n' +
+//     '        "port": 9092,\n' +
+//     '        "bytesInPerSec": null,\n' +
+//     '        "bytesOutPerSec": null,\n' +
+//     '        "partitionsLeader": 18,\n' +
+//     '        "partitions": 110,\n' +
+//     '        "inSyncPartitions": 110,\n' +
+//     '        "partitionsSkew": 0.0,\n' +
+//     '        "leadersSkew": -1.8\n' +
+//     '    },\n' +
+//     '    {\n' +
+//     '        "id": 3,\n' +
+//     '        "host": "test-region-1-broker-3.kafka",\n' +
+//     '        "port": 9092,\n' +
+//     '        "bytesInPerSec": null,\n' +
+//     '        "bytesOutPerSec": null,\n' +
+//     '        "partitionsLeader": 18,\n' +
+//     '        "partitions": 110,\n' +
+//     '        "inSyncPartitions": 110,\n' +
+//     '        "partitionsSkew": 0.0,\n' +
+//     '        "leadersSkew": -1.8\n' +
+//     '    },\n' +
+//     '    {\n' +
+//     '        "id": 4,\n' +
+//     '        "host": "test-region-2-broker-1.kafka",\n' +
+//     '        "port": 9092,\n' +
+//     '        "bytesInPerSec": null,\n' +
+//     '        "bytesOutPerSec": null,\n' +
+//     '        "partitionsLeader": 19,\n' +
+//     '        "partitions": 110,\n' +
+//     '        "inSyncPartitions": 110,\n' +
+//     '        "partitionsSkew": 0.0,\n' +
+//     '        "leadersSkew": 3.6\n' +
+//     '    },\n' +
+//     '    {\n' +
+//     '        "id": 5,\n' +
+//     '        "host": "test-region-2-broker-2.kafka",\n' +
+//     '        "port": 9092,\n' +
+//     '        "bytesInPerSec": null,\n' +
+//     '        "bytesOutPerSec": null,\n' +
+//     '        "partitionsLeader": 18,\n' +
+//     '        "partitions": 110,\n' +
+//     '        "inSyncPartitions": 110,\n' +
+//     '        "partitionsSkew": 0.0,\n' +
+//     '        "leadersSkew": -1.8\n' +
+//     '    },\n' +
+//     '    {\n' +
+//     '        "id": 6,\n' +
+//     '        "host": "test-region-2-broker-3.kafka",\n' +
+//     '        "port": 9092,\n' +
+//     '        "bytesInPerSec": null,\n' +
+//     '        "bytesOutPerSec": null,\n' +
+//     '        "partitionsLeader": 19,\n' +
+//     '        "partitions": 110,\n' +
+//     '        "inSyncPartitions": 110,\n' +
+//     '        "partitionsSkew": 0.0,\n' +
+//     '        "leadersSkew": 3.6\n' +
+//     '    }  \n' +
+//     ']'
+// ) as Broker[] | undefined;
+//
+// const clusterStats = JSON.parse(
+//   '{\n' +
+//     '    "brokerCount": 6,\n' +
+//     '    "zooKeeperStatus": null,\n' +
+//     '    "activeControllers": 3,\n' +
+//     '    "onlinePartitionCount": 110,\n' +
+//     '    "offlinePartitionCount": 0, \n' +
+//     '    "inSyncReplicasCount": 660,\n' +
+//     '    "outOfSyncReplicasCount": 0,\n' +
+//     '    "underReplicatedPartitionCount": 0,\n' +
+//     '    "diskUsage": [\n' +
+//     '        {\n' +
+//     '            "brokerId": 1, \n' +
+//     '            "segmentSize": 15296,\n' +
+//     '            "segmentCount": 110\n' +
+//     '        },\n' +
+//     '        {\n' +
+//     '            "brokerId": 2, \n' +
+//     '            "segmentSize": 15296,\n' +
+//     '            "segmentCount": 110\n' +
+//     '        },\n' +
+//     '        {\n' +
+//     '            "brokerId": 3, \n' +
+//     '            "segmentSize": 15296,\n' +
+//     '            "segmentCount": 110\n' +
+//     '        },\n' +
+//     '        {\n' +
+//     '            "brokerId": 4, \n' +
+//     '            "segmentSize": 15608,\n' +
+//     '            "segmentCount": 130\n' +
+//     '        },\n' +
+//     '        {\n' +
+//     '            "brokerId": 5, \n' +
+//     '            "segmentSize": 15892,\n' +
+//     '            "segmentCount": 131\n' +
+//     '        },\n' +
+//     '        {\n' +
+//     '            "brokerId": 6, \n' +
+//     '            "segmentSize": 15608,\n' +
+//     '            "segmentCount": 132\n' +
+//     '        }\n' +
+//     '    ],\n' +
+//     '    "version": "2.7-IV2"\n' +
+//     '}'
+// ) as ClusterStats;
 
 const BrokersList: React.FC = () => {
   const navigate = useNavigate();
@@ -36,209 +152,28 @@ const BrokersList: React.FC = () => {
     version,
   } = clusterStats;
 
-  const rows = React.useMemo(() => {
-    let brokersResource;
-    if (!diskUsage || !diskUsage?.length) {
-      brokersResource =
-        brokers?.map((broker) => {
-          return {
-            brokerId: broker.id,
-            segmentSize: NA,
-            segmentCount: NA,
-          };
-        }) || [];
-    } else {
-      brokersResource = diskUsage;
-    }
-
-    return brokersResource.map(({ brokerId, segmentSize, segmentCount }) => {
-      const broker = brokers?.find(({ id }) => id === brokerId);
-      return {
-        brokerId,
-        size: segmentSize || NA,
-        count: segmentCount || NA,
-        port: broker?.port,
-        host: broker?.host,
-        partitionsLeader: broker?.partitionsLeader,
-        partitionsSkew: broker?.partitionsSkew,
-        leadersSkew: broker?.leadersSkew,
-        inSyncPartitions: broker?.inSyncPartitions,
-      };
-    });
-  }, [diskUsage, brokers]);
-
-  const columns = React.useMemo<ColumnDef<(typeof rows)[number]>[]>(
-    () => [
-      {
-        header: 'Broker ID',
-        accessorKey: 'brokerId',
-        // eslint-disable-next-line react/no-unstable-nested-components
-        cell: ({ getValue }) => (
-          <S.RowCell>
-            <LinkCell
-              value={`${getValue<string | number>()}`}
-              to={encodeURIComponent(`${getValue<string | number>()}`)}
-            />
-            {getValue<string | number>() === activeControllers && (
-              <Tooltip
-                value={<CheckMarkRoundIcon />}
-                content="Active Controller"
-                placement="right"
-              />
-            )}
-          </S.RowCell>
-        ),
-      },
-      {
-        header: 'Disk usage',
-        accessorKey: 'size',
-        // eslint-disable-next-line react/no-unstable-nested-components
-        cell: ({ getValue, table, cell, column, renderValue, row }) =>
-          getValue() === NA ? (
-            NA
-          ) : (
-            <SizeCell
-              table={table}
-              column={column}
-              row={row}
-              cell={cell}
-              getValue={getValue}
-              renderValue={renderValue}
-              renderSegments
-              precision={2}
-            />
-          ),
-      },
-      {
-        // eslint-disable-next-line react/no-unstable-nested-components
-        header: () => <SkewHeader />,
-        accessorKey: 'partitionsSkew',
-        // eslint-disable-next-line react/no-unstable-nested-components
-        cell: ({ getValue }) => {
-          const value = getValue<number>();
-          return (
-            <ColoredCell
-              value={value ? `${value.toFixed(2)}%` : '-'}
-              warn={value >= 10 && value < 20}
-              attention={value >= 20}
-            />
-          );
-        },
-      },
-      { header: 'Leaders', accessorKey: 'partitionsLeader' },
-      {
-        header: 'Leader skew',
-        accessorKey: 'leadersSkew',
-        // eslint-disable-next-line react/no-unstable-nested-components
-        cell: ({ getValue }) => {
-          const value = getValue<number>();
-          return (
-            <ColoredCell
-              value={value ? `${value.toFixed(2)}%` : '-'}
-              warn={value >= 10 && value < 20}
-              attention={value >= 20}
-            />
-          );
-        },
-      },
-      {
-        header: 'Online partitions',
-        accessorKey: 'inSyncPartitions',
-        // eslint-disable-next-line react/no-unstable-nested-components
-        cell: ({ getValue, row }) => {
-          const value = getValue<number>();
-          return (
-            <ColoredCell
-              value={value}
-              attention={value !== row.original.count}
-            />
-          );
-        },
-      },
-      { header: 'Port', accessorKey: 'port' },
-      {
-        header: 'Host',
-        accessorKey: 'host',
-      },
-    ],
-    []
+  const rows = useMemo(
+    () => getBrokersTableRows({ brokers, diskUsage, activeControllers }),
+    [diskUsage, activeControllers, brokers]
   );
 
-  const replicas = (inSyncReplicasCount ?? 0) + (outOfSyncReplicasCount ?? 0);
-  const areAllInSync = inSyncReplicasCount && replicas === inSyncReplicasCount;
-  const partitionIsOffline = offlinePartitionCount && offlinePartitionCount > 0;
-
-  const isActiveControllerUnKnown = typeof activeControllers === 'undefined';
+  const columns = useMemo(() => getBrokersTableColumns(), []);
 
   return (
     <>
       <PageHeading text="Brokers" />
-      <Metrics.Wrapper>
-        <Metrics.Section title="Uptime">
-          <Metrics.Indicator label="Broker Count">
-            {brokerCount}
-          </Metrics.Indicator>
-          <Metrics.Indicator
-            label="Active Controller"
-            isAlert={isActiveControllerUnKnown}
-          >
-            {isActiveControllerUnKnown ? (
-              <S.DangerText>No Active Controller</S.DangerText>
-            ) : (
-              activeControllers
-            )}
-          </Metrics.Indicator>
-          <Metrics.Indicator label="Version">{version}</Metrics.Indicator>
-        </Metrics.Section>
-        <Metrics.Section title="Partitions">
-          <Metrics.Indicator
-            label="Online"
-            isAlert
-            alertType={partitionIsOffline ? 'error' : 'success'}
-          >
-            {partitionIsOffline ? (
-              <Metrics.RedText>{onlinePartitionCount}</Metrics.RedText>
-            ) : (
-              onlinePartitionCount
-            )}
-            <Metrics.LightText>
-              {` of ${
-                (onlinePartitionCount || 0) + (offlinePartitionCount || 0)
-              }
-              `}
-            </Metrics.LightText>
-          </Metrics.Indicator>
-          <Metrics.Indicator
-            label="URP"
-            title="Under replicated partitions"
-            isAlert
-            alertType={!underReplicatedPartitionCount ? 'success' : 'error'}
-          >
-            {!underReplicatedPartitionCount ? (
-              <Metrics.LightText>
-                {underReplicatedPartitionCount}
-              </Metrics.LightText>
-            ) : (
-              <Metrics.RedText>{underReplicatedPartitionCount}</Metrics.RedText>
-            )}
-          </Metrics.Indicator>
-          <Metrics.Indicator
-            label="In Sync Replicas"
-            isAlert
-            alertType={areAllInSync ? 'success' : 'error'}
-          >
-            {areAllInSync ? (
-              replicas
-            ) : (
-              <Metrics.RedText>{inSyncReplicasCount}</Metrics.RedText>
-            )}
-            <Metrics.LightText> of {replicas}</Metrics.LightText>
-          </Metrics.Indicator>
-          <Metrics.Indicator label="Out Of Sync Replicas">
-            {outOfSyncReplicasCount}
-          </Metrics.Indicator>
-        </Metrics.Section>
-      </Metrics.Wrapper>
+
+      <BrokersMetrics
+        brokerCount={brokerCount}
+        inSyncReplicasCount={inSyncReplicasCount}
+        outOfSyncReplicasCount={outOfSyncReplicasCount}
+        version={version}
+        activeControllers={activeControllers}
+        offlinePartitionCount={offlinePartitionCount}
+        onlinePartitionCount={onlinePartitionCount}
+        underReplicatedPartitionCount={underReplicatedPartitionCount}
+      />
+
       <Table
         columns={columns}
         data={rows}
diff --git a/frontend/src/components/Brokers/BrokersList/BrokersMetrics/BrokersMetrics.styled.ts b/frontend/src/components/Brokers/BrokersList/BrokersMetrics/BrokersMetrics.styled.ts
new file mode 100644
index 000000000..96aef8139
--- /dev/null
+++ b/frontend/src/components/Brokers/BrokersList/BrokersMetrics/BrokersMetrics.styled.ts
@@ -0,0 +1,5 @@
+import styled from 'styled-components';
+
+export const DangerText = styled.span`
+  color: ${({ theme }) => theme.circularAlert.color.error};
+`;
diff --git a/frontend/src/components/Brokers/BrokersList/BrokersMetrics/BrokersMetrics.tsx b/frontend/src/components/Brokers/BrokersList/BrokersMetrics/BrokersMetrics.tsx
new file mode 100644
index 000000000..5c1600806
--- /dev/null
+++ b/frontend/src/components/Brokers/BrokersList/BrokersMetrics/BrokersMetrics.tsx
@@ -0,0 +1,105 @@
+import React from 'react';
+import * as Metrics from 'components/common/Metrics';
+
+import * as S from './BrokersMetrics.styled';
+
+type BrokersMetricsProps = {
+  brokerCount: number | undefined;
+  inSyncReplicasCount: number | undefined;
+  outOfSyncReplicasCount: number | undefined;
+  offlinePartitionCount: number | undefined;
+  activeControllers: number | undefined;
+  onlinePartitionCount: number | undefined;
+  underReplicatedPartitionCount: number | undefined;
+  version: string | undefined;
+};
+
+export const BrokersMetrics = ({
+  brokerCount,
+  version,
+  activeControllers,
+  outOfSyncReplicasCount,
+  inSyncReplicasCount,
+  offlinePartitionCount,
+  underReplicatedPartitionCount,
+  onlinePartitionCount,
+}: BrokersMetricsProps) => {
+  const replicas = (inSyncReplicasCount ?? 0) + (outOfSyncReplicasCount ?? 0);
+  const areAllInSync = inSyncReplicasCount && replicas === inSyncReplicasCount;
+  const partitionIsOffline = offlinePartitionCount && offlinePartitionCount > 0;
+
+  const isActiveControllerUnKnown = typeof activeControllers === 'undefined';
+
+  return (
+    <Metrics.Wrapper>
+      <Metrics.Section title="Uptime">
+        <Metrics.Indicator label="Broker Count">
+          {brokerCount}
+        </Metrics.Indicator>
+
+        <Metrics.Indicator
+          label="Active Controller"
+          isAlert={isActiveControllerUnKnown}
+        >
+          {isActiveControllerUnKnown ? (
+            <S.DangerText>No Active Controller</S.DangerText>
+          ) : (
+            activeControllers
+          )}
+        </Metrics.Indicator>
+
+        <Metrics.Indicator label="Version">{version}</Metrics.Indicator>
+      </Metrics.Section>
+
+      <Metrics.Section title="Partitions">
+        <Metrics.Indicator
+          label="Online"
+          isAlert
+          alertType={partitionIsOffline ? 'error' : 'success'}
+        >
+          {partitionIsOffline ? (
+            <Metrics.RedText>{onlinePartitionCount}</Metrics.RedText>
+          ) : (
+            onlinePartitionCount
+          )}
+          <Metrics.LightText>
+            {` of ${(onlinePartitionCount || 0) + (offlinePartitionCount || 0)}
+              `}
+          </Metrics.LightText>
+        </Metrics.Indicator>
+
+        <Metrics.Indicator
+          label="URP"
+          title="Under replicated partitions"
+          isAlert
+          alertType={!underReplicatedPartitionCount ? 'success' : 'error'}
+        >
+          {!underReplicatedPartitionCount ? (
+            <Metrics.LightText>
+              {underReplicatedPartitionCount}
+            </Metrics.LightText>
+          ) : (
+            <Metrics.RedText>{underReplicatedPartitionCount}</Metrics.RedText>
+          )}
+        </Metrics.Indicator>
+
+        <Metrics.Indicator
+          label="In Sync Replicas"
+          isAlert
+          alertType={areAllInSync ? 'success' : 'error'}
+        >
+          {areAllInSync ? (
+            replicas
+          ) : (
+            <Metrics.RedText>{inSyncReplicasCount}</Metrics.RedText>
+          )}
+          <Metrics.LightText> of {replicas}</Metrics.LightText>
+        </Metrics.Indicator>
+
+        <Metrics.Indicator label="Out Of Sync Replicas">
+          {outOfSyncReplicasCount}
+        </Metrics.Indicator>
+      </Metrics.Section>
+    </Metrics.Wrapper>
+  );
+};
diff --git a/frontend/src/components/Brokers/BrokersList/BrokersList.styled.ts b/frontend/src/components/Brokers/BrokersList/TableCells/TableCells.styled.ts
similarity index 64%
rename from frontend/src/components/Brokers/BrokersList/BrokersList.styled.ts
rename to frontend/src/components/Brokers/BrokersList/TableCells/TableCells.styled.ts
index 964e64368..718f952eb 100644
--- a/frontend/src/components/Brokers/BrokersList/BrokersList.styled.ts
+++ b/frontend/src/components/Brokers/BrokersList/TableCells/TableCells.styled.ts
@@ -10,7 +10,3 @@ export const RowCell = styled.div`
     padding-left: 6px;
   }
 `;
-
-export const DangerText = styled.span`
-  color: ${({ theme }) => theme.circularAlert.color.error};
-`;
diff --git a/frontend/src/components/Brokers/BrokersList/TableCells/TableCells.tsx b/frontend/src/components/Brokers/BrokersList/TableCells/TableCells.tsx
new file mode 100644
index 000000000..0cb201cc8
--- /dev/null
+++ b/frontend/src/components/Brokers/BrokersList/TableCells/TableCells.tsx
@@ -0,0 +1,86 @@
+import React from 'react';
+import { BrokersTableRow } from 'components/Brokers/BrokersList/lib/types';
+import { CellContext } from '@tanstack/react-table';
+import { LinkCell, SizeCell } from 'components/common/NewTable';
+import Tooltip from 'components/common/Tooltip/Tooltip';
+import CheckMarkRoundIcon from 'components/common/Icons/CheckMarkRoundIcon';
+import { NA } from 'components/Brokers/BrokersList/lib';
+import ColoredCell from 'components/common/NewTable/ColoredCell';
+
+import * as S from './TableCells.styled';
+
+type BrokerIdProps = CellContext<BrokersTableRow, BrokersTableRow['brokerId']>;
+
+export const BrokerId = ({ getValue, row }: BrokerIdProps) => {
+  const { activeControllers } = row.original;
+  const brokerId = getValue();
+
+  return (
+    <S.RowCell>
+      <LinkCell value={`${brokerId}`} to={encodeURIComponent(`${brokerId}`)} />
+      {brokerId === activeControllers && (
+        <Tooltip
+          value={<CheckMarkRoundIcon />}
+          content="Active Controller"
+          placement="right"
+        />
+      )}
+    </S.RowCell>
+  );
+};
+
+type DiscUsageProps = CellContext<BrokersTableRow, BrokersTableRow['size']>;
+
+export const DiscUsage = ({
+  getValue,
+  table,
+  cell,
+  column,
+  renderValue,
+  row,
+}: DiscUsageProps) => {
+  if (getValue() === NA) return NA;
+
+  return (
+    <SizeCell
+      table={table}
+      column={column}
+      row={row}
+      cell={cell}
+      getValue={getValue}
+      renderValue={renderValue}
+      renderSegments
+      precision={2}
+    />
+  );
+};
+
+type ScewProps = CellContext<
+  BrokersTableRow,
+  BrokersTableRow['partitionsSkew'] | BrokersTableRow['leadersSkew']
+>;
+
+export const Skew = ({ getValue }: ScewProps) => {
+  const skew = getValue();
+  const value = skew ? `${skew.toFixed(2)}%` : '-';
+
+  return (
+    <ColoredCell
+      value={value}
+      warn={skew !== undefined && skew >= 10 && skew < 20}
+      attention={skew !== undefined && skew >= 20}
+    />
+  );
+};
+
+type OnlinePartitionsProps = CellContext<
+  BrokersTableRow,
+  BrokersTableRow['inSyncPartitions']
+>;
+
+export const OnlinePartitions = ({ getValue, row }: OnlinePartitionsProps) => {
+  const value = getValue();
+  const { count } = row.original;
+
+  return <ColoredCell value={value} attention={value !== count} />;
+};
diff --git a/frontend/src/components/Brokers/BrokersList/lib/constants.ts b/frontend/src/components/Brokers/BrokersList/lib/constants.ts
new file mode 100644
index 000000000..140fb6d52
--- /dev/null
+++ b/frontend/src/components/Brokers/BrokersList/lib/constants.ts
@@ -0,0 +1 @@
+export const NA = 'N/A';
diff --git a/frontend/src/components/Brokers/BrokersList/lib/index.ts b/frontend/src/components/Brokers/BrokersList/lib/index.ts
new file mode 100644
index 000000000..7a616f8d2
--- /dev/null
+++ b/frontend/src/components/Brokers/BrokersList/lib/index.ts
@@ -0,0 +1,3 @@
+export * from './utils';
+export * from './constants';
+export * from './types';
diff --git a/frontend/src/components/Brokers/BrokersList/lib/types.ts b/frontend/src/components/Brokers/BrokersList/lib/types.ts
new file mode 100644
index 000000000..7e30589cd
--- /dev/null
+++ b/frontend/src/components/Brokers/BrokersList/lib/types.ts
@@ -0,0 +1,12 @@
+export type BrokersTableRow = {
+  brokerId: number;
+  size: string | number;
+  count: string | number;
+  port: number | undefined;
+  host: string | undefined;
+  partitionsLeader: number | undefined;
+  partitionsSkew: number | undefined;
+  leadersSkew: number | undefined;
+  inSyncPartitions: number;
+  activeControllers: number | undefined;
+};
diff --git a/frontend/src/components/Brokers/BrokersList/lib/utils.ts b/frontend/src/components/Brokers/BrokersList/lib/utils.ts
new file mode 100644
index 000000000..b4b0a4cf9
--- /dev/null
+++ b/frontend/src/components/Brokers/BrokersList/lib/utils.ts
@@ -0,0 +1,76 @@
+import { Broker, BrokerDiskUsage } from 'generated-sources';
+import * as Cell from 'components/Brokers/BrokersList/TableCells/TableCells';
+import SkewHeader from 'components/Brokers/BrokersList/SkewHeader/SkewHeader';
+import { createColumnHelper } from '@tanstack/react-table';
+
+import { BrokersTableRow } from './types';
+import { NA } from './constants';
+
+const brokerResourceMapper = (broker: Broker) => ({
+  brokerId: broker.id,
+  segmentSize: NA,
+  segmentCount: NA,
+});
+
+type GetBrokersTableRowsParams = {
+  brokers: Broker[] | undefined;
+  diskUsage: BrokerDiskUsage[] | undefined;
+  activeControllers: number | undefined;
+};
+
+export const getBrokersTableRows = ({
+  brokers = [],
+  diskUsage = [],
+  activeControllers,
+}: GetBrokersTableRowsParams): BrokersTableRow[] => {
+  const brokersResource = diskUsage.length
+    ? diskUsage
+    : brokers.map(brokerResourceMapper);
+
+  return brokersResource.map(({ brokerId, segmentSize, segmentCount }) => {
+    const broker = brokers?.find(({ id }) => id === brokerId);
+
+    return {
+      brokerId,
+      size: segmentSize || NA,
+      count: segmentCount || NA,
+      port: broker?.port,
+      host: broker?.host,
+      partitionsLeader: broker?.partitionsLeader,
+      partitionsSkew: broker?.partitionsSkew,
+      leadersSkew: broker?.leadersSkew,
+      inSyncPartitions: broker?.inSyncPartitions ?? 0,
+      activeControllers,
+    };
+  });
+};
+
+export const getBrokersTableColumns = () => {
+  const columnHelper = createColumnHelper<BrokersTableRow>();
+
+  return [
+    columnHelper.accessor('brokerId', {
+      header: 'Broker ID',
+      cell: Cell.BrokerId,
+    }),
+    columnHelper.accessor('size', {
+      header: 'Disk usage',
+      cell: Cell.DiscUsage,
+    }),
+    columnHelper.accessor('partitionsSkew', {
+      header: SkewHeader,
+      cell: Cell.Skew,
+    }),
+    columnHelper.accessor('partitionsLeader', { header: 'Leaders' }),
+    columnHelper.accessor('leadersSkew', {
+      header: 'Leader skew',
+      cell: Cell.Skew,
+    }),
+    columnHelper.accessor('inSyncPartitions', {
+      header: 'Online partitions',
+      cell: Cell.OnlinePartitions,
+    }),
+    columnHelper.accessor('port', { header: 'Port' }),
+    columnHelper.accessor('host', { header: 'Host' }),
+  ];
+};
diff --git a/frontend/src/components/common/NewTable/SizeCell.tsx b/frontend/src/components/common/NewTable/SizeCell.tsx
index 7a230be81..118132065 100644
--- a/frontend/src/components/common/NewTable/SizeCell.tsx
+++ b/frontend/src/components/common/NewTable/SizeCell.tsx
@@ -6,7 +6,7 @@ import BytesFormatted from 'components/common/BytesFormatted/BytesFormatted';
 type AsAny = any;
 
 const SizeCell: React.FC<
-  CellContext<AsAny, unknown> & { renderSegments?: boolean; precision?: number }
+  CellContext<AsAny, AsAny> & { renderSegments?: boolean; precision?: number }
 > = ({ getValue, row, renderSegments = false, precision = 0 }) => (
   <>
     <BytesFormatted value={getValue<string | number>()} precision={precision} />
diff --git a/frontend/src/components/common/NewTable/Table.tsx b/frontend/src/components/common/NewTable/Table.tsx
index 4a3bf3030..7177072ba 100644
--- a/frontend/src/components/common/NewTable/Table.tsx
+++ b/frontend/src/components/common/NewTable/Table.tsx
@@ -1,20 +1,20 @@
 import React from 'react';
+import type {
+  ColumnDef,
+  OnChangeFn,
+  PaginationState,
+  Row,
+  SortingState,
+} from '@tanstack/react-table';
 import {
   flexRender,
   getCoreRowModel,
   getExpandedRowModel,
+  getPaginationRowModel,
   getSortedRowModel,
   useReactTable,
-  getPaginationRowModel,
-} from '@tanstack/react-table';
-import type {
-  Row,
-  SortingState,
-  OnChangeFn,
-  PaginationState,
-  ColumnDef,
 } from '@tanstack/react-table';
-import { useSearchParams, useLocation } from 'react-router-dom';
+import { useLocation, useSearchParams } from 'react-router-dom';
 import { PER_PAGE } from 'lib/constants';
 import { Button } from 'components/common/Button/Button';
 import Input from 'components/common/Input/Input';
@@ -29,7 +29,8 @@ import SelectRowHeader from './SelectRowHeader';
 export interface TableProps<TData> {
   data: TData[];
   pageCount?: number;
-  columns: ColumnDef<TData>[];
+  // eslint-disable-next-line @typescript-eslint/no-explicit-any
+  columns: ColumnDef<TData, any>[];
 
   // Server-side processing: sorting, pagination
   serverSideProcessing?: boolean;

From d38e33f3de48bde6a0e7e736d1ab042a55b71b49 Mon Sep 17 00:00:00 2001
From: alexeykozyurov <akozyurov@provectus.com>
Date: Tue, 13 Feb 2024 14:28:45 +0700
Subject: [PATCH 2/6] Bugfix.

---
 .../Brokers/BrokersList/BrokersList.tsx       | 134 ++----------------
 .../BrokersList/TableCells/TableCells.tsx     |  14 +-
 .../Brokers/BrokersList/lib/types.ts          |   3 +-
 .../Brokers/BrokersList/lib/utils.ts          |   9 +-
 4 files changed, 27 insertions(+), 133 deletions(-)

diff --git a/frontend/src/components/Brokers/BrokersList/BrokersList.tsx b/frontend/src/components/Brokers/BrokersList/BrokersList.tsx
index 1555d213a..bdc1f9c00 100644
--- a/frontend/src/components/Brokers/BrokersList/BrokersList.tsx
+++ b/frontend/src/components/Brokers/BrokersList/BrokersList.tsx
@@ -5,135 +5,12 @@ import PageHeading from 'components/common/PageHeading/PageHeading';
 import useAppParams from 'lib/hooks/useAppParams';
 import Table from 'components/common/NewTable';
 import { clusterBrokerPath } from 'lib/paths';
-import { useClusterStats } from 'lib/hooks/api/clusters';
 import { useBrokers } from 'lib/hooks/api/brokers';
+import { useClusterStats } from 'lib/hooks/api/clusters';
 
 import { BrokersMetrics } from './BrokersMetrics/BrokersMetrics';
 import { getBrokersTableColumns, getBrokersTableRows } from './lib';
 
-// const brokers = JSON.parse(
-//   '[\n' +
-//     '    {\n' +
-//     '        "id": 1,\n' +
-//     '        "host": "test-region-1-broker-1.kafka",\n' +
-//     '        "port": 9092,\n' +
-//     '        "bytesInPerSec": null,\n' +
-//     '        "bytesOutPerSec": null,\n' +
-//     '        "partitionsLeader": 18,\n' +
-//     '        "partitions": 110,\n' +
-//     '        "inSyncPartitions": 110,\n' +
-//     '        "partitionsSkew": 0.0,\n' +
-//     '        "leadersSkew": -1.8\n' +
-//     '    },\n' +
-//     '    {\n' +
-//     '        "id": 2,\n' +
-//     '        "host": "test-region-1-broker-2.kafka",\n' +
-//     '        "port": 9092,\n' +
-//     '        "bytesInPerSec": null,\n' +
-//     '        "bytesOutPerSec": null,\n' +
-//     '        "partitionsLeader": 18,\n' +
-//     '        "partitions": 110,\n' +
-//     '        "inSyncPartitions": 110,\n' +
-//     '        "partitionsSkew": 0.0,\n' +
-//     '        "leadersSkew": -1.8\n' +
-//     '    },\n' +
-//     '    {\n' +
-//     '        "id": 3,\n' +
-//     '        "host": "test-region-1-broker-3.kafka",\n' +
-//     '        "port": 9092,\n' +
-//     '        "bytesInPerSec": null,\n' +
-//     '        "bytesOutPerSec": null,\n' +
-//     '        "partitionsLeader": 18,\n' +
-//     '        "partitions": 110,\n' +
-//     '        "inSyncPartitions": 110,\n' +
-//     '        "partitionsSkew": 0.0,\n' +
-//     '        "leadersSkew": -1.8\n' +
-//     '    },\n' +
-//     '    {\n' +
-//     '        "id": 4,\n' +
-//     '        "host": "test-region-2-broker-1.kafka",\n' +
-//     '        "port": 9092,\n' +
-//     '        "bytesInPerSec": null,\n' +
-//     '        "bytesOutPerSec": null,\n' +
-//     '        "partitionsLeader": 19,\n' +
-//     '        "partitions": 110,\n' +
-//     '        "inSyncPartitions": 110,\n' +
-//     '        "partitionsSkew": 0.0,\n' +
-//     '        "leadersSkew": 3.6\n' +
-//     '    },\n' +
-//     '    {\n' +
-//     '        "id": 5,\n' +
-//     '        "host": "test-region-2-broker-2.kafka",\n' +
-//     '        "port": 9092,\n' +
-//     '        "bytesInPerSec": null,\n' +
-//     '        "bytesOutPerSec": null,\n' +
-//     '        "partitionsLeader": 18,\n' +
-//     '        "partitions": 110,\n' +
-//     '        "inSyncPartitions": 110,\n' +
-//     '        "partitionsSkew": 0.0,\n' +
-//     '        "leadersSkew": -1.8\n' +
-//     '    },\n' +
-//     '    {\n' +
-//     '        "id": 6,\n' +
-//     '        "host": "test-region-2-broker-3.kafka",\n' +
-//     '        "port": 9092,\n' +
-//     '        "bytesInPerSec": null,\n' +
-//     '        "bytesOutPerSec": null,\n' +
-//     '        "partitionsLeader": 19,\n' +
-//     '        "partitions": 110,\n' +
-//     '        "inSyncPartitions": 110,\n' +
-//     '        "partitionsSkew": 0.0,\n' +
-//     '        "leadersSkew": 3.6\n' +
-//     '    }  \n' +
-//     ']'
-// ) as Broker[] | undefined;
-//
-// const clusterStats = JSON.parse(
-//   '{\n' +
-//     '    "brokerCount": 6,\n' +
-//     '    "zooKeeperStatus": null,\n' +
-//     '    "activeControllers": 3,\n' +
-//     '    "onlinePartitionCount": 110,\n' +
-//     '    "offlinePartitionCount": 0, \n' +
-//     '    "inSyncReplicasCount": 660,\n' +
-//     '    "outOfSyncReplicasCount": 0,\n' +
-//     '    "underReplicatedPartitionCount": 0,\n' +
-//     '    "diskUsage": [\n' +
-//     '        {\n' +
-//     '            "brokerId": 1, \n' +
-//     '            "segmentSize": 15296,\n' +
-//     '            "segmentCount": 110\n' +
-//     '        },\n' +
-//     '        {\n' +
-//     '            "brokerId": 2, \n' +
-//     '            "segmentSize": 15296,\n' +
-//     '            "segmentCount": 110\n' +
-//     '        },\n' +
-//     '        {\n' +
-//     '            "brokerId": 3, \n' +
-//     '            "segmentSize": 15296,\n' +
-//     '            "segmentCount": 110\n' +
-//     '        },\n' +
-//     '        {\n' +
-//     '            "brokerId": 4, \n' +
-//     '            "segmentSize": 15608,\n' +
-//     '            "segmentCount": 130\n' +
-//     '        },\n' +
-//     '        {\n' +
-//     '            "brokerId": 5, \n' +
-//     '            "segmentSize": 15892,\n' +
-//     '            "segmentCount": 131\n' +
-//     '        },\n' +
-//     '        {\n' +
-//     '            "brokerId": 6, \n' +
-//     '            "segmentSize": 15608,\n' +
-//     '            "segmentCount": 132\n' +
-//     '        }\n' +
-//     '    ],\n' +
-//     '    "version": "2.7-IV2"\n' +
-//     '}'
-// ) as ClusterStats;
-
 const BrokersList: React.FC = () => {
   const navigate = useNavigate();
   const { clusterName } = useAppParams<{ clusterName: ClusterName }>();
@@ -153,7 +30,14 @@ const BrokersList: React.FC = () => {
   } = clusterStats;
 
   const rows = useMemo(
-    () => getBrokersTableRows({ brokers, diskUsage, activeControllers }),
+    () =>
+      getBrokersTableRows({
+        brokers,
+        diskUsage,
+        activeControllers,
+        onlinePartitionCount,
+        offlinePartitionCount,
+      }),
     [diskUsage, activeControllers, brokers]
   );
 
diff --git a/frontend/src/components/Brokers/BrokersList/TableCells/TableCells.tsx b/frontend/src/components/Brokers/BrokersList/TableCells/TableCells.tsx
index 0cb201cc8..0e6ada0a0 100644
--- a/frontend/src/components/Brokers/BrokersList/TableCells/TableCells.tsx
+++ b/frontend/src/components/Brokers/BrokersList/TableCells/TableCells.tsx
@@ -75,12 +75,16 @@ export const Skew = ({ getValue }: ScewProps) => {
 
 type OnlinePartitionsProps = CellContext<
   BrokersTableRow,
-  BrokersTableRow['inSyncPartitions']
+  BrokersTableRow['onlinePartitionCount']
 >;
 
-export const OnlinePartitions = ({ getValue, row }: OnlinePartitionsProps) => {
-  const value = getValue();
-  const { count } = row.original;
+export const OnlinePartitions = ({ row }: OnlinePartitionsProps) => {
+  const { onlinePartitionCount, offlinePartitionCount } = row.original;
 
-  return <ColoredCell value={value} attention={value !== count} />;
+  return (
+    <ColoredCell
+      value={onlinePartitionCount}
+      attention={offlinePartitionCount > 0}
+    />
+  );
 };
diff --git a/frontend/src/components/Brokers/BrokersList/lib/types.ts b/frontend/src/components/Brokers/BrokersList/lib/types.ts
index 7e30589cd..4138dff7d 100644
--- a/frontend/src/components/Brokers/BrokersList/lib/types.ts
+++ b/frontend/src/components/Brokers/BrokersList/lib/types.ts
@@ -7,6 +7,7 @@ export type BrokersTableRow = {
   partitionsLeader: number | undefined;
   partitionsSkew: number | undefined;
   leadersSkew: number | undefined;
-  inSyncPartitions: number;
+  onlinePartitionCount: number;
+  offlinePartitionCount: number;
   activeControllers: number | undefined;
 };
diff --git a/frontend/src/components/Brokers/BrokersList/lib/utils.ts b/frontend/src/components/Brokers/BrokersList/lib/utils.ts
index b4b0a4cf9..e13dd6d8b 100644
--- a/frontend/src/components/Brokers/BrokersList/lib/utils.ts
+++ b/frontend/src/components/Brokers/BrokersList/lib/utils.ts
@@ -16,12 +16,16 @@ type GetBrokersTableRowsParams = {
   brokers: Broker[] | undefined;
   diskUsage: BrokerDiskUsage[] | undefined;
   activeControllers: number | undefined;
+  onlinePartitionCount: number | undefined;
+  offlinePartitionCount: number | undefined;
 };
 
 export const getBrokersTableRows = ({
   brokers = [],
   diskUsage = [],
   activeControllers,
+  onlinePartitionCount,
+  offlinePartitionCount,
 }: GetBrokersTableRowsParams): BrokersTableRow[] => {
   const brokersResource = diskUsage.length
     ? diskUsage
@@ -39,7 +43,8 @@ export const getBrokersTableRows = ({
       partitionsLeader: broker?.partitionsLeader,
       partitionsSkew: broker?.partitionsSkew,
       leadersSkew: broker?.leadersSkew,
-      inSyncPartitions: broker?.inSyncPartitions ?? 0,
+      onlinePartitionCount: onlinePartitionCount ?? 0,
+      offlinePartitionCount: offlinePartitionCount ?? 0,
       activeControllers,
     };
   });
@@ -66,7 +71,7 @@ export const getBrokersTableColumns = () => {
       header: 'Leader skew',
       cell: Cell.Skew,
     }),
-    columnHelper.accessor('inSyncPartitions', {
+    columnHelper.accessor('onlinePartitionCount', {
       header: 'Online partitions',
       cell: Cell.OnlinePartitions,
     }),

From a78639e6564217f239edb281421dacd25de81e4e Mon Sep 17 00:00:00 2001
From: alexeykozyurov <akozyurov@provectus.com>
Date: Sun, 25 Feb 2024 17:33:20 +0800
Subject: [PATCH 3/6] SizeCell unknown rollback.

---
 .../Brokers/BrokersList/TableCells/TableCells.tsx    |  9 ++++++++-
 .../src/components/Brokers/BrokersList/lib/utils.ts  |  3 +--
 frontend/src/components/common/NewTable/SizeCell.tsx | 12 +++++++++---
 3 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/frontend/src/components/Brokers/BrokersList/TableCells/TableCells.tsx b/frontend/src/components/Brokers/BrokersList/TableCells/TableCells.tsx
index 0e6ada0a0..60d5920e9 100644
--- a/frontend/src/components/Brokers/BrokersList/TableCells/TableCells.tsx
+++ b/frontend/src/components/Brokers/BrokersList/TableCells/TableCells.tsx
@@ -39,7 +39,7 @@ export const DiscUsage = ({
   renderValue,
   row,
 }: DiscUsageProps) => {
-  if (getValue() === NA) return NA;
+  if (getValue() === undefined) return NA;
 
   return (
     <SizeCell
@@ -81,6 +81,13 @@ type OnlinePartitionsProps = CellContext<
 export const OnlinePartitions = ({ row }: OnlinePartitionsProps) => {
   const { onlinePartitionCount, offlinePartitionCount } = row.original;
 
+  if (
+    onlinePartitionCount === undefined ||
+    offlinePartitionCount === undefined
+  ) {
+    return null;
+  }
+
   return (
     <ColoredCell
       value={onlinePartitionCount}
diff --git a/frontend/src/components/Brokers/BrokersList/lib/utils.ts b/frontend/src/components/Brokers/BrokersList/lib/utils.ts
index 64576e270..1eb6b2886 100644
--- a/frontend/src/components/Brokers/BrokersList/lib/utils.ts
+++ b/frontend/src/components/Brokers/BrokersList/lib/utils.ts
@@ -1,8 +1,8 @@
 import { Broker, BrokerDiskUsage } from 'generated-sources';
 import * as Cell from 'components/Brokers/BrokersList/TableCells/TableCells';
-import SkewHeader from 'components/Brokers/BrokersList/SkewHeader/SkewHeader';
 import { createColumnHelper } from '@tanstack/react-table';
 import { keyBy } from 'lib/functions/keyBy';
+import SkewHeader from 'components/Brokers/BrokersList/SkewHeader/SkewHeader';
 
 import { BrokersTableRow } from './types';
 import { NA_DISK_USAGE } from './constants';
@@ -40,7 +40,6 @@ export const getBrokersTableRows = ({
       partitionsLeader: broker.partitionsLeader,
       partitionsSkew: broker.partitionsSkew,
       leadersSkew: broker.leadersSkew,
-      inSyncPartitions: broker.inSyncPartitions,
       onlinePartitionCount,
       offlinePartitionCount,
       activeControllers,
diff --git a/frontend/src/components/common/NewTable/SizeCell.tsx b/frontend/src/components/common/NewTable/SizeCell.tsx
index 118132065..03279b60d 100644
--- a/frontend/src/components/common/NewTable/SizeCell.tsx
+++ b/frontend/src/components/common/NewTable/SizeCell.tsx
@@ -5,9 +5,15 @@ import BytesFormatted from 'components/common/BytesFormatted/BytesFormatted';
 // eslint-disable-next-line @typescript-eslint/no-explicit-any
 type AsAny = any;
 
-const SizeCell: React.FC<
-  CellContext<AsAny, AsAny> & { renderSegments?: boolean; precision?: number }
-> = ({ getValue, row, renderSegments = false, precision = 0 }) => (
+const SizeCell = <TValue = unknown,>({
+  getValue,
+  row,
+  renderSegments = false,
+  precision = 0,
+}: CellContext<AsAny, TValue> & {
+  renderSegments?: boolean;
+  precision?: number;
+}) => (
   <>
     <BytesFormatted value={getValue<string | number>()} precision={precision} />
     {renderSegments ? `, ${row?.original.count} segment(s)` : null}

From 6b40452cacbed3c1fd3083e59b7ea9bbf45a24a1 Mon Sep 17 00:00:00 2001
From: Mgrdich <mgotm13@gmail.com>
Date: Sun, 25 Feb 2024 17:06:44 +0400
Subject: [PATCH 4/6] Minor code modifications in the SizeCellCount

---
 .../BrokersList/TableCells/TableCells.tsx     |  6 ++---
 .../components/common/NewTable/SizeCell.tsx   | 19 +++++----------
 .../common/NewTable/SizeCellCount.tsx         | 23 +++++++++++++++++++
 .../src/components/common/NewTable/Table.tsx  | 11 +++++----
 4 files changed, 39 insertions(+), 20 deletions(-)
 create mode 100644 frontend/src/components/common/NewTable/SizeCellCount.tsx

diff --git a/frontend/src/components/Brokers/BrokersList/TableCells/TableCells.tsx b/frontend/src/components/Brokers/BrokersList/TableCells/TableCells.tsx
index 60d5920e9..5d6039fbf 100644
--- a/frontend/src/components/Brokers/BrokersList/TableCells/TableCells.tsx
+++ b/frontend/src/components/Brokers/BrokersList/TableCells/TableCells.tsx
@@ -1,11 +1,12 @@
 import React from 'react';
 import { BrokersTableRow } from 'components/Brokers/BrokersList/lib/types';
 import { CellContext } from '@tanstack/react-table';
-import { LinkCell, SizeCell } from 'components/common/NewTable';
+import { LinkCell } from 'components/common/NewTable';
 import Tooltip from 'components/common/Tooltip/Tooltip';
 import CheckMarkRoundIcon from 'components/common/Icons/CheckMarkRoundIcon';
 import { NA } from 'components/Brokers/BrokersList/lib';
 import ColoredCell from 'components/common/NewTable/ColoredCell';
+import SizeCellCount from 'components/common/NewTable/SizeCellCount';
 
 import * as S from './TableCells.styled';
 
@@ -42,14 +43,13 @@ export const DiscUsage = ({
   if (getValue() === undefined) return NA;
 
   return (
-    <SizeCell
+    <SizeCellCount
       table={table}
       column={column}
       row={row}
       cell={cell}
       getValue={getValue}
       renderValue={renderValue}
-      renderSegments
       precision={2}
     />
   );
diff --git a/frontend/src/components/common/NewTable/SizeCell.tsx b/frontend/src/components/common/NewTable/SizeCell.tsx
index 03279b60d..4b472b5bd 100644
--- a/frontend/src/components/common/NewTable/SizeCell.tsx
+++ b/frontend/src/components/common/NewTable/SizeCell.tsx
@@ -2,22 +2,15 @@ import React from 'react';
 import { CellContext } from '@tanstack/react-table';
 import BytesFormatted from 'components/common/BytesFormatted/BytesFormatted';
 
-// eslint-disable-next-line @typescript-eslint/no-explicit-any
-type AsAny = any;
-
-const SizeCell = <TValue = unknown,>({
+const SizeCell = <TData, TValue>({
   getValue,
-  row,
-  renderSegments = false,
   precision = 0,
-}: CellContext<AsAny, TValue> & {
-  renderSegments?: boolean;
+}: CellContext<TData, TValue> & {
   precision?: number;
-}) => (
-  <>
+}) => {
+  return (
     <BytesFormatted value={getValue<string | number>()} precision={precision} />
-    {renderSegments ? `, ${row?.original.count} segment(s)` : null}
-  </>
-);
+  );
+};
 
 export default SizeCell;
diff --git a/frontend/src/components/common/NewTable/SizeCellCount.tsx b/frontend/src/components/common/NewTable/SizeCellCount.tsx
new file mode 100644
index 000000000..80df59b9f
--- /dev/null
+++ b/frontend/src/components/common/NewTable/SizeCellCount.tsx
@@ -0,0 +1,23 @@
+import React from 'react';
+import { CellContext } from '@tanstack/react-table';
+import BytesFormatted from 'components/common/BytesFormatted/BytesFormatted';
+
+const SizeCellCount = <TData extends { count?: number | undefined }, TValue>({
+  getValue,
+  row,
+  precision = 0,
+}: CellContext<TData, TValue> & {
+  precision?: number;
+}) => {
+  return (
+    <>
+      <BytesFormatted
+        value={getValue<string | number>()}
+        precision={precision}
+      />
+      {`, ${row.original.count} segment(s)`}
+    </>
+  );
+};
+
+export default SizeCellCount;
diff --git a/frontend/src/components/common/NewTable/Table.tsx b/frontend/src/components/common/NewTable/Table.tsx
index a614dae95..df4421c98 100644
--- a/frontend/src/components/common/NewTable/Table.tsx
+++ b/frontend/src/components/common/NewTable/Table.tsx
@@ -26,10 +26,13 @@ import ExpanderCell from './ExpanderCell';
 import SelectRowCell from './SelectRowCell';
 import SelectRowHeader from './SelectRowHeader';
 
-export interface TableProps<TData, TValue> {
+export interface TableProps<TData> {
   data: TData[];
   pageCount?: number;
-  columns: ColumnDef<TData, TValue>[];
+
+  // https://github.com/TanStack/table/issues/4382
+  // eslint-disable-next-line @typescript-eslint/no-explicit-any
+  columns: ColumnDef<TData, any>[];
 
   // Server-side processing: sorting, pagination
   serverSideProcessing?: boolean;
@@ -118,7 +121,7 @@ const getSortingFromSearchParams = (searchParams: URLSearchParams) => {
  *    - use URLSearchParams to get the pagination and sorting state from the url for your server side processing.
  */
 
-function Table<TData, TValue = unknown>({
+function Table<TData>({
   data,
   pageCount,
   columns,
@@ -134,7 +137,7 @@ function Table<TData, TValue = unknown>({
   onRowHover,
   onMouseLeave,
   setRowId,
-}: TableProps<TData, TValue>) {
+}: TableProps<TData>) {
   const [searchParams, setSearchParams] = useSearchParams();
   const location = useLocation();
   const [rowSelection, setRowSelection] = React.useState({});

From 490271ef3559531beabd7c80f8b71717cd7589ea Mon Sep 17 00:00:00 2001
From: alexeykozyurov <akozyurov@provectus.com>
Date: Sun, 25 Feb 2024 21:22:01 +0800
Subject: [PATCH 5/6] GROOVY_SCRIPT -> CEL_SCRIPT

---
 .../Topics/Topic/Messages/Filters/Filters.tsx   | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/frontend/src/components/Topics/Topic/Messages/Filters/Filters.tsx b/frontend/src/components/Topics/Topic/Messages/Filters/Filters.tsx
index 347623d22..99eb6bac4 100644
--- a/frontend/src/components/Topics/Topic/Messages/Filters/Filters.tsx
+++ b/frontend/src/components/Topics/Topic/Messages/Filters/Filters.tsx
@@ -13,7 +13,7 @@ import {
 } from 'generated-sources';
 import React, { useContext } from 'react';
 import omitBy from 'lodash/omitBy';
-import { useNavigate, useLocation, useSearchParams } from 'react-router-dom';
+import { useLocation, useNavigate, useSearchParams } from 'react-router-dom';
 import MultiSelect from 'components/common/MultiSelect/MultiSelect.styled';
 import { Option } from 'react-multi-select-component';
 import BytesFormatted from 'components/common/BytesFormatted/BytesFormatted';
@@ -55,11 +55,17 @@ export interface FiltersProps {
   meta: TopicMessageConsuming;
   isFetching: boolean;
   messageEventType?: string;
+
   addMessage(content: { message: TopicMessage; prepend: boolean }): void;
+
   resetMessages(): void;
+
   updatePhase(phase: string): void;
+
   updateMeta(meta: TopicMessageConsuming): void;
+
   setIsFetching(status: boolean): void;
+
   setMessageType(messageType: string): void;
 }
 
@@ -152,7 +158,7 @@ const Filters: React.FC<FiltersProps> = ({
 
   const [queryType, setQueryType] = React.useState<MessageFilterType>(
     activeFilter.name
-      ? MessageFilterType.GROOVY_SCRIPT
+      ? MessageFilterType.CEL_SCRIPT
       : MessageFilterType.STRING_CONTAINS
   );
   const [query, setQuery] = React.useState<string>(searchParams.get('q') || '');
@@ -205,10 +211,7 @@ const Filters: React.FC<FiltersProps> = ({
   const handleFiltersSubmit = (currentOffset: string) => {
     const nextAttempt = Number(searchParams.get('attempt') || 0) + 1;
     const props: Query = {
-      q:
-        queryType === MessageFilterType.GROOVY_SCRIPT
-          ? activeFilter.code
-          : query,
+      q: queryType === MessageFilterType.CEL_SCRIPT ? activeFilter.code : query,
       filterQueryType: queryType,
       attempt: nextAttempt,
       limit: PER_PAGE,
@@ -309,7 +312,7 @@ const Filters: React.FC<FiltersProps> = ({
       JSON.stringify({ index, ...newActiveFilter })
     );
     setActiveFilter({ index, ...newActiveFilter });
-    setQueryType(MessageFilterType.GROOVY_SCRIPT);
+    setQueryType(MessageFilterType.CEL_SCRIPT);
   };
 
   const composeMessageFilter = (filter: FilterEdit): ActiveMessageFilter => ({

From 8b9579f5988b7b9bde7ae8081d65a3c9fffb602c Mon Sep 17 00:00:00 2001
From: alexeykozyurov <akozyurov@provectus.com>
Date: Wed, 28 Feb 2024 12:38:01 +0800
Subject: [PATCH 6/6] TS errors fix in tests

---
 frontend/src/components/NavBar/__tests__/NavBar.spec.tsx      | 2 +-
 .../components/PageContainer/__tests__/PageContainer.spec.tsx | 4 +++-
 frontend/src/lib/hooks/api/__tests__/topics.spec.ts           | 1 -
 3 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/frontend/src/components/NavBar/__tests__/NavBar.spec.tsx b/frontend/src/components/NavBar/__tests__/NavBar.spec.tsx
index 2e37613ba..9b3e4528f 100644
--- a/frontend/src/components/NavBar/__tests__/NavBar.spec.tsx
+++ b/frontend/src/components/NavBar/__tests__/NavBar.spec.tsx
@@ -20,7 +20,7 @@ describe('NavBar', () => {
       })),
     });
 
-    render(<NavBar onBurgerClick={jest.fn()} setDarkMode={jest.fn()} />);
+    render(<NavBar onBurgerClick={jest.fn()} />);
   });
 
   it('correctly renders header', () => {
diff --git a/frontend/src/components/PageContainer/__tests__/PageContainer.spec.tsx b/frontend/src/components/PageContainer/__tests__/PageContainer.spec.tsx
index ca91cd207..b6d654ea5 100644
--- a/frontend/src/components/PageContainer/__tests__/PageContainer.spec.tsx
+++ b/frontend/src/components/PageContainer/__tests__/PageContainer.spec.tsx
@@ -9,9 +9,11 @@ import { Cluster, ServerStatus } from 'generated-sources';
 const burgerButtonOptions = { name: 'burger' };
 
 jest.mock('components/Version/Version', () => () => <div>Version</div>);
+
 interface DataType {
   data: Cluster[] | undefined;
 }
+
 jest.mock('lib/hooks/api/clusters');
 const mockedNavigate = jest.fn();
 jest.mock('react-router-dom', () => ({
@@ -30,7 +32,7 @@ describe('Page Container', () => {
       })),
     });
     render(
-      <PageContainer setDarkMode={jest.fn()}>
+      <PageContainer>
         <div>child</div>
       </PageContainer>,
       {
diff --git a/frontend/src/lib/hooks/api/__tests__/topics.spec.ts b/frontend/src/lib/hooks/api/__tests__/topics.spec.ts
index 34b864fd4..802368495 100644
--- a/frontend/src/lib/hooks/api/__tests__/topics.spec.ts
+++ b/frontend/src/lib/hooks/api/__tests__/topics.spec.ts
@@ -77,7 +77,6 @@ describe('Topics hooks', () => {
         minInSyncReplicas: 0,
         cleanupPolicy: '',
         retentionMs: 0,
-        retentionBytes: 0,
         maxMessageBytes: 0,
         customParams: [],
       };