From 8298929454dab156fffe6e5171e89a9c921bc7b4 Mon Sep 17 00:00:00 2001 From: Roman Zabaluev Date: Tue, 27 Feb 2024 16:30:14 +0700 Subject: [PATCH 1/3] Revert "Use a private actions runner for now" This reverts commit 03596865600d435616a3199b56d6c4d6dc6652fa. --- .github/workflows/aws_publisher.yml | 2 +- .github/workflows/backend_tests.yml | 2 +- .github/workflows/block_merge.yml | 2 +- .github/workflows/branch-deploy.yml | 4 ++-- .github/workflows/branch-remove.yml | 2 +- .github/workflows/build-public-image.yml | 2 +- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/cve.yml | 2 +- .github/workflows/delete-public-image.yml | 2 +- .github/workflows/e2e-automation.yml | 2 +- .github/workflows/e2e-manual.yml | 2 +- .github/workflows/e2e-tests.yml | 2 +- .github/workflows/e2e-weekly.yml | 2 +- .github/workflows/frontend_tests.yml | 2 +- .github/workflows/main.yml | 2 +- .github/workflows/md-links.yml | 2 +- .github/workflows/pr_linter.yml | 2 +- .github/workflows/release-serde-api.yml | 2 +- .github/workflows/release.yml | 4 ++-- .github/workflows/release_drafter.yml | 2 +- .github/workflows/separate_env_public_create.yml | 4 ++-- .github/workflows/separate_env_public_remove.yml | 2 +- .github/workflows/welcome-first-time-contributors.yml | 2 +- .github/workflows/workflow_linter.yml | 2 +- 24 files changed, 27 insertions(+), 27 deletions(-) diff --git a/.github/workflows/aws_publisher.yml b/.github/workflows/aws_publisher.yml index 9d74a2804..6aa70fa91 100644 --- a/.github/workflows/aws_publisher.yml +++ b/.github/workflows/aws_publisher.yml @@ -19,7 +19,7 @@ on: jobs: build-ami: name: Build AMI - runs-on: gha-private-runner + runs-on: ubuntu-latest steps: - name: Clone infra repo run: | diff --git a/.github/workflows/backend_tests.yml b/.github/workflows/backend_tests.yml index 06b9a6d1c..8a3ffe2d3 100644 --- a/.github/workflows/backend_tests.yml +++ b/.github/workflows/backend_tests.yml @@ -15,7 +15,7 @@ permissions: jobs: build-and-test: - runs-on: gha-private-runner + runs-on: ubuntu-latest steps: - name: Checkout diff --git a/.github/workflows/block_merge.yml b/.github/workflows/block_merge.yml index db26a946d..c689d45b0 100644 --- a/.github/workflows/block_merge.yml +++ b/.github/workflows/block_merge.yml @@ -4,7 +4,7 @@ on: types: [opened, labeled, unlabeled, synchronize] jobs: block_merge: - runs-on: gha-private-runner + runs-on: ubuntu-latest steps: - uses: mheap/github-action-required-labels@v5 with: diff --git a/.github/workflows/branch-deploy.yml b/.github/workflows/branch-deploy.yml index f073dff71..107a93116 100644 --- a/.github/workflows/branch-deploy.yml +++ b/.github/workflows/branch-deploy.yml @@ -12,7 +12,7 @@ permissions: jobs: build: if: ${{ github.event.label.name == 'status/feature_testing' || github.event.label.name == 'status/feature_testing_public' }} - runs-on: gha-private-runner + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: @@ -75,7 +75,7 @@ jobs: tag: ${{ steps.extract_branch.outputs.tag }} make-branch-env: needs: build - runs-on: gha-private-runner + runs-on: ubuntu-latest steps: - name: clone run: | diff --git a/.github/workflows/branch-remove.yml b/.github/workflows/branch-remove.yml index a3177011b..d700ea976 100644 --- a/.github/workflows/branch-remove.yml +++ b/.github/workflows/branch-remove.yml @@ -10,7 +10,7 @@ permissions: jobs: remove: - runs-on: gha-private-runner + runs-on: ubuntu-latest if: ${{ (github.event.label.name == 'status/feature_testing' || github.event.label.name == 'status/feature_testing_public') || (github.event.action == 'closed' && (contains(github.event.pull_request.labels.*.name, 'status/feature_testing') || contains(github.event.pull_request.labels.*.name, 'status/feature_testing_public'))) }} steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/build-public-image.yml b/.github/workflows/build-public-image.yml index de5e33b51..86f90ad9c 100644 --- a/.github/workflows/build-public-image.yml +++ b/.github/workflows/build-public-image.yml @@ -11,7 +11,7 @@ permissions: jobs: build: if: ${{ github.event.label.name == 'status/image_testing' }} - runs-on: gha-private-runner + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index a29477928..57f5a0251 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -23,7 +23,7 @@ permissions: jobs: analyze: name: Analyze - runs-on: gha-private-runner + runs-on: ubuntu-latest strategy: fail-fast: false matrix: diff --git a/.github/workflows/cve.yml b/.github/workflows/cve.yml index 13535c65c..d53913521 100644 --- a/.github/workflows/cve.yml +++ b/.github/workflows/cve.yml @@ -10,7 +10,7 @@ permissions: jobs: build-and-test: - runs-on: gha-private-runner + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/delete-public-image.yml b/.github/workflows/delete-public-image.yml index 5294307d8..8e3f2dd7c 100644 --- a/.github/workflows/delete-public-image.yml +++ b/.github/workflows/delete-public-image.yml @@ -6,7 +6,7 @@ on: jobs: remove: if: ${{ github.event.label.name == 'status/image_testing' || ( github.event.action == 'closed' && (contains(github.event.pull_request.labels, 'status/image_testing'))) }} - runs-on: gha-private-runner + runs-on: ubuntu-latest steps: - name: get branch name id: extract_branch diff --git a/.github/workflows/e2e-automation.yml b/.github/workflows/e2e-automation.yml index 0313784b7..6303001a3 100644 --- a/.github/workflows/e2e-automation.yml +++ b/.github/workflows/e2e-automation.yml @@ -21,7 +21,7 @@ permissions: jobs: build-and-test: - runs-on: gha-private-runner + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: diff --git a/.github/workflows/e2e-manual.yml b/.github/workflows/e2e-manual.yml index 2668897ae..d554bdaa2 100644 --- a/.github/workflows/e2e-manual.yml +++ b/.github/workflows/e2e-manual.yml @@ -20,7 +20,7 @@ permissions: jobs: build-and-test: - runs-on: gha-private-runner + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index f7509c1df..72e7c92e1 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -16,7 +16,7 @@ permissions: jobs: build-and-test: - runs-on: gha-private-runner + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: diff --git a/.github/workflows/e2e-weekly.yml b/.github/workflows/e2e-weekly.yml index 4e238ead9..d8275e473 100644 --- a/.github/workflows/e2e-weekly.yml +++ b/.github/workflows/e2e-weekly.yml @@ -8,7 +8,7 @@ permissions: jobs: build-and-test: - runs-on: gha-private-runner + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: diff --git a/.github/workflows/frontend_tests.yml b/.github/workflows/frontend_tests.yml index 9aa4a6110..4be3239d4 100644 --- a/.github/workflows/frontend_tests.yml +++ b/.github/workflows/frontend_tests.yml @@ -11,7 +11,7 @@ jobs: env: CI: true NODE_ENV: dev - runs-on: gha-private-runner + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 472dadbca..503656b2d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -10,7 +10,7 @@ permissions: jobs: build: - runs-on: gha-private-runner + runs-on: ubuntu-latest permissions: contents: read packages: write diff --git a/.github/workflows/md-links.yml b/.github/workflows/md-links.yml index ee3379558..b885e014d 100644 --- a/.github/workflows/md-links.yml +++ b/.github/workflows/md-links.yml @@ -14,7 +14,7 @@ permissions: jobs: build-and-test: - runs-on: gha-private-runner + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/pr_linter.yml b/.github/workflows/pr_linter.yml index ef5bd8b25..f4562345f 100644 --- a/.github/workflows/pr_linter.yml +++ b/.github/workflows/pr_linter.yml @@ -6,7 +6,7 @@ permissions: checks: write jobs: task-check: - runs-on: gha-private-runner + runs-on: ubuntu-latest steps: - uses: kentaro-m/task-completed-checker-action@v0.1.2 with: diff --git a/.github/workflows/release-serde-api.yml b/.github/workflows/release-serde-api.yml index 86aa61a75..af5b1db0d 100644 --- a/.github/workflows/release-serde-api.yml +++ b/.github/workflows/release-serde-api.yml @@ -7,7 +7,7 @@ permissions: jobs: release-serde-api: - runs-on: gha-private-runner + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index efa859a79..2ae221180 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -8,7 +8,7 @@ permissions: jobs: release: - runs-on: gha-private-runner + runs-on: ubuntu-latest permissions: contents: write packages: write @@ -95,7 +95,7 @@ jobs: cache-to: type=local,dest=/tmp/.buildx-cache charts: - runs-on: gha-private-runner + runs-on: ubuntu-latest needs: release steps: - name: Repository Dispatch diff --git a/.github/workflows/release_drafter.yml b/.github/workflows/release_drafter.yml index dc8f689ea..6614c88aa 100644 --- a/.github/workflows/release_drafter.yml +++ b/.github/workflows/release_drafter.yml @@ -18,7 +18,7 @@ permissions: jobs: update_release_draft: - runs-on: gha-private-runner + runs-on: ubuntu-latest permissions: contents: write pull-requests: write diff --git a/.github/workflows/separate_env_public_create.yml b/.github/workflows/separate_env_public_create.yml index 5449482db..b7bb630e1 100644 --- a/.github/workflows/separate_env_public_create.yml +++ b/.github/workflows/separate_env_public_create.yml @@ -12,7 +12,7 @@ permissions: jobs: build: - runs-on: gha-private-runner + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -76,7 +76,7 @@ jobs: tag: ${{ steps.extract_branch.outputs.tag }} separate-env-create: - runs-on: gha-private-runner + runs-on: ubuntu-latest needs: build steps: - name: clone diff --git a/.github/workflows/separate_env_public_remove.yml b/.github/workflows/separate_env_public_remove.yml index 2ada624e2..0eb48cd4a 100644 --- a/.github/workflows/separate_env_public_remove.yml +++ b/.github/workflows/separate_env_public_remove.yml @@ -9,7 +9,7 @@ on: jobs: separate-env-remove: - runs-on: gha-private-runner + runs-on: ubuntu-latest steps: - name: clone run: | diff --git a/.github/workflows/welcome-first-time-contributors.yml b/.github/workflows/welcome-first-time-contributors.yml index 3ec8e8a34..1ac861055 100644 --- a/.github/workflows/welcome-first-time-contributors.yml +++ b/.github/workflows/welcome-first-time-contributors.yml @@ -12,7 +12,7 @@ permissions: pull-requests: write jobs: welcome: - runs-on: gha-private-runner + runs-on: ubuntu-latest steps: - uses: actions/first-interaction@v1 with: diff --git a/.github/workflows/workflow_linter.yml b/.github/workflows/workflow_linter.yml index 47925a9cf..728aaa251 100644 --- a/.github/workflows/workflow_linter.yml +++ b/.github/workflows/workflow_linter.yml @@ -10,7 +10,7 @@ permissions: jobs: build-and-test: - runs-on: gha-private-runner + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 From 481df493f71bc7bfcc4fcfb2a591414a5bc5bb56 Mon Sep 17 00:00:00 2001 From: Aleksei Koziurov Date: Wed, 28 Feb 2024 12:38:41 +0800 Subject: [PATCH 2/3] FE: Online partition count is red fix (#137) Co-authored-by: Mgrdich --- .../Brokers/BrokersList/BrokersList.tsx | 235 +++--------------- .../BrokersMetrics/BrokersMetrics.styled.ts | 5 + .../BrokersMetrics/BrokersMetrics.tsx | 105 ++++++++ .../TableCells.styled.ts} | 4 - .../BrokersList/TableCells/TableCells.tsx | 97 ++++++++ .../BrokersList/__test__/BrokersList.spec.tsx | 71 +++--- .../Brokers/BrokersList/lib/constants.ts | 5 + .../Brokers/BrokersList/lib/index.ts | 3 + .../Brokers/BrokersList/lib/types.ts | 13 + .../Brokers/BrokersList/lib/utils.ts | 78 ++++++ .../NavBar/__tests__/NavBar.spec.tsx | 2 +- .../__tests__/PageContainer.spec.tsx | 4 +- .../Topics/Topic/Messages/Filters/Filters.tsx | 17 +- .../components/common/NewTable/SizeCell.tsx | 19 +- .../common/NewTable/SizeCellCount.tsx | 23 ++ .../src/components/common/NewTable/Table.tsx | 29 ++- .../lib/hooks/api/__tests__/topics.spec.ts | 1 - 17 files changed, 428 insertions(+), 283 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 create mode 100644 frontend/src/components/common/NewTable/SizeCellCount.tsx diff --git a/frontend/src/components/Brokers/BrokersList/BrokersList.tsx b/frontend/src/components/Brokers/BrokersList/BrokersList.tsx index f869269fa..bdc1f9c00 100644 --- a/frontend/src/components/Brokers/BrokersList/BrokersList.tsx +++ b/frontend/src/components/Brokers/BrokersList/BrokersList.tsx @@ -1,27 +1,15 @@ -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 Table from 'components/common/NewTable'; +import { clusterBrokerPath } from 'lib/paths'; 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 { clusterBrokerPath } from 'lib/paths'; -import { keyBy } from 'lib/functions/keyBy'; -import Tooltip from 'components/common/Tooltip/Tooltip'; -import ColoredCell from 'components/common/NewTable/ColoredCell'; - -import SkewHeader from './SkewHeader/SkewHeader'; -import * as S from './BrokersList.styled'; -const NA = 'N/A'; -const NA_DISK_USAGE = { - segmentCount: NA, - segmentSize: NA, -}; +import { BrokersMetrics } from './BrokersMetrics/BrokersMetrics'; +import { getBrokersTableColumns, getBrokersTableRows } from './lib'; const BrokersList: React.FC = () => { const navigate = useNavigate(); @@ -41,202 +29,35 @@ const BrokersList: React.FC = () => { version, } = clusterStats; - const rows = React.useMemo(() => { - if (!brokers || brokers.length === 0) { - return []; - } - - const diskUsageByBroker = keyBy(diskUsage, 'brokerId'); - - return brokers.map((broker) => { - const diskUse = diskUsageByBroker[broker.id] || NA_DISK_USAGE; - - return { - brokerId: broker.id, - size: diskUse.segmentSize, - count: diskUse.segmentCount, - port: broker.port, - host: broker.host, - partitionsLeader: broker.partitionsLeader, - partitionsSkew: broker.partitionsSkew, - leadersSkew: broker.leadersSkew, - inSyncPartitions: broker.inSyncPartitions, - }; - }); - }, [diskUsage, brokers]); - - const columns = React.useMemo[]>( - () => [ - { - header: 'Broker ID', - accessorKey: 'brokerId', - // eslint-disable-next-line react/no-unstable-nested-components - cell: ({ getValue }) => ( - - ()}`} - to={encodeURIComponent(`${getValue()}`)} - /> - {getValue() === activeControllers && ( - } - content="Active Controller" - placement="right" - /> - )} - - ), - }, - { - header: 'Disk usage', - accessorKey: 'size', - // eslint-disable-next-line react/no-unstable-nested-components - cell: ({ getValue, table, cell, column, renderValue, row }) => - getValue() === NA ? ( - NA - ) : ( - - ), - }, - { - // eslint-disable-next-line react/no-unstable-nested-components - header: () => , - accessorKey: 'partitionsSkew', - // eslint-disable-next-line react/no-unstable-nested-components - cell: ({ getValue }) => { - const value = getValue(); - return ( - = 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(); - return ( - = 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(); - return ( - - ); - }, - }, - { header: 'Port', accessorKey: 'port' }, - { - header: 'Host', - accessorKey: 'host', - }, - ], - [] + const rows = useMemo( + () => + getBrokersTableRows({ + brokers, + diskUsage, + activeControllers, + onlinePartitionCount, + offlinePartitionCount, + }), + [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 ( <> - - - - {brokerCount} - - - {isActiveControllerUnKnown ? ( - No Active Controller - ) : ( - activeControllers - )} - - {version} - - - - {partitionIsOffline ? ( - {onlinePartitionCount} - ) : ( - onlinePartitionCount - )} - - {` of ${ - (onlinePartitionCount || 0) + (offlinePartitionCount || 0) - } - `} - - - - {!underReplicatedPartitionCount ? ( - - {underReplicatedPartitionCount} - - ) : ( - {underReplicatedPartitionCount} - )} - - - {areAllInSync ? ( - replicas - ) : ( - {inSyncReplicasCount} - )} - of {replicas} - - - {outOfSyncReplicasCount} - - - + + + 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 ( + + + + {brokerCount} + + + + {isActiveControllerUnKnown ? ( + No Active Controller + ) : ( + activeControllers + )} + + + {version} + + + + + {partitionIsOffline ? ( + {onlinePartitionCount} + ) : ( + onlinePartitionCount + )} + + {` of ${(onlinePartitionCount || 0) + (offlinePartitionCount || 0)} + `} + + + + + {!underReplicatedPartitionCount ? ( + + {underReplicatedPartitionCount} + + ) : ( + {underReplicatedPartitionCount} + )} + + + + {areAllInSync ? ( + replicas + ) : ( + {inSyncReplicasCount} + )} + of {replicas} + + + + {outOfSyncReplicasCount} + + + + ); +}; 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..5d6039fbf --- /dev/null +++ b/frontend/src/components/Brokers/BrokersList/TableCells/TableCells.tsx @@ -0,0 +1,97 @@ +import React from 'react'; +import { BrokersTableRow } from 'components/Brokers/BrokersList/lib/types'; +import { CellContext } from '@tanstack/react-table'; +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'; + +type BrokerIdProps = CellContext; + +export const BrokerId = ({ getValue, row }: BrokerIdProps) => { + const { activeControllers } = row.original; + const brokerId = getValue(); + + return ( + + + {brokerId === activeControllers && ( + } + content="Active Controller" + placement="right" + /> + )} + + ); +}; + +type DiscUsageProps = CellContext; + +export const DiscUsage = ({ + getValue, + table, + cell, + column, + renderValue, + row, +}: DiscUsageProps) => { + if (getValue() === undefined) return NA; + + return ( + + ); +}; + +type ScewProps = CellContext< + BrokersTableRow, + BrokersTableRow['partitionsSkew'] | BrokersTableRow['leadersSkew'] +>; + +export const Skew = ({ getValue }: ScewProps) => { + const skew = getValue(); + const value = skew ? `${skew.toFixed(2)}%` : '-'; + + return ( + = 10 && skew < 20} + attention={skew !== undefined && skew >= 20} + /> + ); +}; + +type OnlinePartitionsProps = CellContext< + BrokersTableRow, + BrokersTableRow['onlinePartitionCount'] +>; + +export const OnlinePartitions = ({ row }: OnlinePartitionsProps) => { + const { onlinePartitionCount, offlinePartitionCount } = row.original; + + if ( + onlinePartitionCount === undefined || + offlinePartitionCount === undefined + ) { + return null; + } + + return ( + 0} + /> + ); +}; diff --git a/frontend/src/components/Brokers/BrokersList/__test__/BrokersList.spec.tsx b/frontend/src/components/Brokers/BrokersList/__test__/BrokersList.spec.tsx index e98f28e52..9dc40591e 100644 --- a/frontend/src/components/Brokers/BrokersList/__test__/BrokersList.spec.tsx +++ b/frontend/src/components/Brokers/BrokersList/__test__/BrokersList.spec.tsx @@ -72,11 +72,13 @@ describe('BrokersList Component', () => { }, })); renderComponent(); - const onlineWidget = screen.getByText( + const onlineWidgets = screen.getAllByText( clusterStatsPayload.onlinePartitionCount ); - expect(onlineWidget).toBeInTheDocument(); - expect(onlineWidget).toHaveStyle({ color: '#E51A1A' }); + onlineWidgets.forEach((widget) => { + expect(widget).toBeInTheDocument(); + expect(widget).toHaveStyle({ color: '#E51A1A' }); + }); }); it('shows right count when offlinePartitionCount > 0', async () => { (useClusterStats as jest.Mock).mockImplementation(() => ({ @@ -154,49 +156,24 @@ describe('BrokersList Component', () => { expect(screen.queryByRole('tooltip')).not.toBeInTheDocument() ); }); + }); + }); - describe('when diskUsage', () => { - describe('is empty', () => { - beforeEach(() => { - (useClusterStats as jest.Mock).mockImplementation(() => ({ - data: { ...clusterStatsPayload, diskUsage: undefined }, - })); - }); - - it('renders list of all brokers', async () => { - renderComponent(); - expect(screen.getByRole('table')).toBeInTheDocument(); - expect(screen.getAllByRole('row').length).toEqual(3); - }); - }); - - describe('was NOT set for second broker', () => { - beforeEach(() => { - (useClusterStats as jest.Mock).mockImplementation(() => ({ - data: { - ...clusterStatsPayload, - diskUsage: [clusterStatsPayload.diskUsage[0]], - }, - })); - }); - - it('renders list of all brokers', async () => { - renderComponent(); - expect(screen.getByRole('table')).toBeInTheDocument(); - expect(screen.getAllByRole('row').length).toEqual(3); - }); - }); - }); + describe('when diskUsage is empty', () => { + beforeEach(() => { + (useBrokers as jest.Mock).mockImplementation(() => ({ + data: brokersPayload, + })); + (useClusterStats as jest.Mock).mockImplementation(() => ({ + data: { ...clusterStatsPayload, diskUsage: undefined }, + })); }); - describe('when the brokers list is empty', () => { + describe('when it has no brokers', () => { beforeEach(() => { (useBrokers as jest.Mock).mockImplementation(() => ({ data: [], })); - (useClusterStats as jest.Mock).mockImplementation(() => ({ - data: clusterStatsPayload, - })); }); it('renders empty table', async () => { @@ -207,6 +184,22 @@ describe('BrokersList Component', () => { ).toBeInTheDocument(); }); }); + + it('renders list of all brokers', async () => { + renderComponent(); + expect(screen.getByRole('table')).toBeInTheDocument(); + expect(screen.getAllByRole('row').length).toEqual(3); + }); + it('opens broker when row clicked', async () => { + renderComponent(); + await userEvent.click(screen.getByRole('cell', { name: '100' })); + + await waitFor(() => + expect(mockedUsedNavigate).toBeCalledWith( + clusterBrokerPath(clusterName, '100') + ) + ); + }); }); }); }); 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..48e4e0cb4 --- /dev/null +++ b/frontend/src/components/Brokers/BrokersList/lib/constants.ts @@ -0,0 +1,5 @@ +export const NA = 'N/A'; +export const NA_DISK_USAGE = { + segmentCount: NA, + segmentSize: NA, +}; 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..7928862a1 --- /dev/null +++ b/frontend/src/components/Brokers/BrokersList/lib/types.ts @@ -0,0 +1,13 @@ +export type BrokersTableRow = { + brokerId: number; + size: number | undefined; + count: number | undefined; + port: number | undefined; + host: string | undefined; + partitionsLeader: number | undefined; + partitionsSkew: number | undefined; + leadersSkew: number | undefined; + onlinePartitionCount: number | undefined; + offlinePartitionCount: number | undefined; + 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..1eb6b2886 --- /dev/null +++ b/frontend/src/components/Brokers/BrokersList/lib/utils.ts @@ -0,0 +1,78 @@ +import { Broker, BrokerDiskUsage } from 'generated-sources'; +import * as Cell from 'components/Brokers/BrokersList/TableCells/TableCells'; +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'; + +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[] => { + if (!brokers || brokers.length === 0) { + return []; + } + + const diskUsageByBroker = keyBy(diskUsage, 'brokerId'); + + return brokers.map((broker) => { + const diskUse = diskUsageByBroker[broker.id] || NA_DISK_USAGE; + + return { + brokerId: broker.id, + size: diskUse.segmentSize, + count: diskUse.segmentCount, + port: broker.port, + host: broker.host, + partitionsLeader: broker.partitionsLeader, + partitionsSkew: broker.partitionsSkew, + leadersSkew: broker.leadersSkew, + onlinePartitionCount, + offlinePartitionCount, + activeControllers, + }; + }); +}; + +export const getBrokersTableColumns = () => { + const columnHelper = createColumnHelper(); + + 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('onlinePartitionCount', { + header: 'Online partitions', + cell: Cell.OnlinePartitions, + }), + columnHelper.accessor('port', { header: 'Port' }), + columnHelper.accessor('host', { header: 'Host' }), + ]; +}; 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(); + render(); }); 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', () => () =>
Version
); + 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( - +
child
, { 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 = ({ const [queryType, setQueryType] = React.useState( activeFilter.name - ? MessageFilterType.GROOVY_SCRIPT + ? MessageFilterType.CEL_SCRIPT : MessageFilterType.STRING_CONTAINS ); const [query, setQuery] = React.useState(searchParams.get('q') || ''); @@ -205,10 +211,7 @@ const Filters: React.FC = ({ 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 = ({ JSON.stringify({ index, ...newActiveFilter }) ); setActiveFilter({ index, ...newActiveFilter }); - setQueryType(MessageFilterType.GROOVY_SCRIPT); + setQueryType(MessageFilterType.CEL_SCRIPT); }; const composeMessageFilter = (filter: FilterEdit): ActiveMessageFilter => ({ diff --git a/frontend/src/components/common/NewTable/SizeCell.tsx b/frontend/src/components/common/NewTable/SizeCell.tsx index 7a230be81..4b472b5bd 100644 --- a/frontend/src/components/common/NewTable/SizeCell.tsx +++ b/frontend/src/components/common/NewTable/SizeCell.tsx @@ -2,16 +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: React.FC< - CellContext & { renderSegments?: boolean; precision?: number } -> = ({ getValue, row, renderSegments = false, precision = 0 }) => ( - <> +const SizeCell = ({ + getValue, + precision = 0, +}: CellContext & { + precision?: number; +}) => { + return ( ()} 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 = ({ + getValue, + row, + precision = 0, +}: CellContext & { + precision?: number; +}) => { + return ( + <> + ()} + 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 42d406b4f..df4421c98 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'; @@ -26,10 +26,13 @@ import ExpanderCell from './ExpanderCell'; import SelectRowCell from './SelectRowCell'; import SelectRowHeader from './SelectRowHeader'; -export interface TableProps { +export interface TableProps { data: TData[]; pageCount?: number; - columns: ColumnDef[]; + + // https://github.com/TanStack/table/issues/4382 + // eslint-disable-next-line @typescript-eslint/no-explicit-any + columns: ColumnDef[]; // 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({ +function Table({ data, pageCount, columns, @@ -134,7 +137,7 @@ function Table({ onRowHover, onMouseLeave, setRowId, -}: TableProps) { +}: TableProps) { const [searchParams, setSearchParams] = useSearchParams(); const location = useLocation(); const [rowSelection, setRowSelection] = React.useState({}); 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: [], }; From 3608b26ef3bdef85dc31bd7f7d1c71d7f8c7e433 Mon Sep 17 00:00:00 2001 From: Roman Zabaluev Date: Fri, 1 Mar 2024 22:27:08 +0700 Subject: [PATCH 3/3] FE: UX: Update color palette (#158) --- frontend/index.html | 3 +- frontend/public/favicon/favicon.ico | Bin 4286 -> 0 bytes .../public/favicon/{icon.svg => favicon.svg} | 10 ++-- frontend/src/components/App.tsx | 2 +- .../src/components/NavBar/NavBar.styled.ts | 6 ++- frontend/src/components/NavBar/NavBar.tsx | 2 +- .../NavBar/__tests__/NavBar.spec.tsx | 2 +- .../src/components/common/Logo/Logo.styled.ts | 5 ++ frontend/src/components/common/Logo/Logo.tsx | 11 ++--- .../common/PageLoader/PageLoader.styled.ts | 9 +++- .../common/PageLoader/PageLoader.tsx | 5 +- frontend/src/theme/theme.ts | 44 ++++++++++-------- 12 files changed, 59 insertions(+), 40 deletions(-) delete mode 100644 frontend/public/favicon/favicon.ico rename frontend/public/favicon/{icon.svg => favicon.svg} (77%) create mode 100644 frontend/src/components/common/Logo/Logo.styled.ts diff --git a/frontend/index.html b/frontend/index.html index 693664306..0041f6efa 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -5,8 +5,7 @@ - - + diff --git a/frontend/public/favicon/favicon.ico b/frontend/public/favicon/favicon.ico deleted file mode 100644 index 2774ebccf9b845f5d4202e5afe8677310e38b91b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4286 zcmc(jTT4|@5XX1lpr@XLUV7>?^Z_cnXIMx|7cbRAb}zb6LJ~>z(ghU+QzCj$ico|g zDd?qwzz{3K?xo!?cKdgJO@sUFv-UnmBN|z*wbxoR|Cw1cvzA8DwA|0knGwIEuIW)U zBZ{Kgxt5!X=H?pnzbUsiYmPOWh$2mvK7W>;J(KRB0re#gNaE`1lG8u;N6Xoj4Kpdt3(mD^^H%?o4oF%Z(dSU0rd0 zWT7WmU^?N;HEXhMcV6lYwJu4+!xm%3{D2KrRT7v^moA0RJZ`&>$;JMD=gjYk?|u7< z+kq@FA^g|eY<0~svU=*@$&uZNH)=AJwW z*ATZ0In*<-IZMtoOJDZW)~%Czd-G#w0yTeh@19g&AC5_|JdUV~S+PfcuU{{{n(h)(<5!)Zt;U`bfJ$opCiV|m+o$9 zbTlM!YIDRte+!;FCmlU%Ik;tuL?a)WV~st$EB+;M7jvG}KpNx8-p_yZ^Zx_ @media (prefers-color-scheme: dark) { #faviconCircle { - fill: white; + fill: #FDFDFD; } #faviconLogo { - fill: #4F4FFF; + fill: #171A1C; } } - -