From 8bdc353aead327a8489542f4e88a98af377804ef Mon Sep 17 00:00:00 2001 From: Pavel Makarichev Date: Tue, 10 Jun 2025 20:32:36 +0300 Subject: [PATCH 1/7] fix: active broker --- .../src/components/Nav/ClusterMenu/ClusterMenu.tsx | 11 +++++++---- frontend/src/lib/paths.ts | 5 ++++- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/frontend/src/components/Nav/ClusterMenu/ClusterMenu.tsx b/frontend/src/components/Nav/ClusterMenu/ClusterMenu.tsx index 60f78a33f..03c1dd1f6 100644 --- a/frontend/src/components/Nav/ClusterMenu/ClusterMenu.tsx +++ b/frontend/src/components/Nav/ClusterMenu/ClusterMenu.tsx @@ -13,9 +13,11 @@ import { clusterSchemasPath, clusterTopicsPath, } from 'lib/paths'; -import { useLocation } from 'react-router-dom'; +import { useLocation, useParams } from 'react-router-dom'; import { useLocalStorage } from 'lib/hooks/useLocalStorage'; import { ClusterColorKey } from 'theme/theme'; +import useAppParams from 'lib/hooks/useAppParams'; +import type { ClusterName } from 'lib/interfaces/cluster'; interface ClusterMenuProps { name: Cluster['name']; @@ -39,8 +41,9 @@ const ClusterMenu: FC = ({ 'transparent' ); - const getIsMenuItemActive = (path: string) => - location.pathname.includes(path); + const getIsMenuItemActive = (path: string) => { + return location.pathname.includes(path); + }; return ( @@ -54,7 +57,7 @@ const ClusterMenu: FC = ({ {isOpen && ( diff --git a/frontend/src/lib/paths.ts b/frontend/src/lib/paths.ts index 9f961b261..3c25e26d1 100644 --- a/frontend/src/lib/paths.ts +++ b/frontend/src/lib/paths.ts @@ -47,7 +47,10 @@ export const clusterBrokersPath = ( export const clusterBrokerPath = ( clusterName: ClusterName = RouteParams.clusterName, brokerId: Broker['id'] | string = RouteParams.brokerId -) => `${clusterBrokersPath(clusterName)}/${brokerId}`; +) => { + return `${clusterBrokersPath(clusterName)}/${brokerId}`; +}; + export const clusterBrokerMetricsPath = ( clusterName: ClusterName = RouteParams.clusterName, brokerId: Broker['id'] | string = RouteParams.brokerId From 7132b6c224d9914d9600969bb0dd9260527d3ce5 Mon Sep 17 00:00:00 2001 From: Pavel Makarichev Date: Tue, 10 Jun 2025 20:56:44 +0300 Subject: [PATCH 2/7] enh: open active cluster by location --- .../components/Nav/ClusterMenu/ClusterMenu.tsx | 11 ++++------- .../ClusterMenu/__tests__/ClusterMenu.spec.tsx | 4 ++-- frontend/src/components/Nav/Nav.tsx | 6 ++++-- frontend/src/lib/hooks/useCurrentClusterName.ts | 15 +++++++++++++++ 4 files changed, 25 insertions(+), 11 deletions(-) create mode 100644 frontend/src/lib/hooks/useCurrentClusterName.ts diff --git a/frontend/src/components/Nav/ClusterMenu/ClusterMenu.tsx b/frontend/src/components/Nav/ClusterMenu/ClusterMenu.tsx index 03c1dd1f6..49a9cceeb 100644 --- a/frontend/src/components/Nav/ClusterMenu/ClusterMenu.tsx +++ b/frontend/src/components/Nav/ClusterMenu/ClusterMenu.tsx @@ -5,7 +5,6 @@ import MenuTab from 'components/Nav/Menu/MenuTab'; import MenuItem from 'components/Nav/Menu/MenuItem'; import { clusterACLPath, - clusterBrokerPath, clusterBrokersPath, clusterConnectorsPath, clusterConsumerGroupsPath, @@ -13,28 +12,26 @@ import { clusterSchemasPath, clusterTopicsPath, } from 'lib/paths'; -import { useLocation, useParams } from 'react-router-dom'; +import { useLocation } from 'react-router-dom'; import { useLocalStorage } from 'lib/hooks/useLocalStorage'; import { ClusterColorKey } from 'theme/theme'; -import useAppParams from 'lib/hooks/useAppParams'; -import type { ClusterName } from 'lib/interfaces/cluster'; interface ClusterMenuProps { name: Cluster['name']; status: Cluster['status']; features: Cluster['features']; - singleMode?: boolean; + opened?: boolean; } const ClusterMenu: FC = ({ name, status, features, - singleMode, + opened, }) => { const hasFeatureConfigured = (key: ClusterFeaturesEnum) => features?.includes(key); - const [isOpen, setIsOpen] = useState(!!singleMode); + const [isOpen, setIsOpen] = useState(!!opened); const location = useLocation(); const [colorKey, setColorKey] = useLocalStorage( `clusterColor-${name}`, diff --git a/frontend/src/components/Nav/ClusterMenu/__tests__/ClusterMenu.spec.tsx b/frontend/src/components/Nav/ClusterMenu/__tests__/ClusterMenu.spec.tsx index ce0bb9731..3593e88f5 100644 --- a/frontend/src/components/Nav/ClusterMenu/__tests__/ClusterMenu.spec.tsx +++ b/frontend/src/components/Nav/ClusterMenu/__tests__/ClusterMenu.spec.tsx @@ -8,12 +8,12 @@ import { render } from 'lib/testHelpers'; import { onlineClusterPayload } from 'lib/fixtures/clusters'; describe('ClusterMenu', () => { - const setupComponent = (cluster: Cluster, singleMode?: boolean) => ( + const setupComponent = (cluster: Cluster, opened?: boolean) => ( ); const getMenuItems = () => screen.getAllByRole('menuitem'); diff --git a/frontend/src/components/Nav/Nav.tsx b/frontend/src/components/Nav/Nav.tsx index 2741b4351..532f5e4dc 100644 --- a/frontend/src/components/Nav/Nav.tsx +++ b/frontend/src/components/Nav/Nav.tsx @@ -1,5 +1,6 @@ -import { useClusters } from 'lib/hooks/api/clusters'; import React, { type FC } from 'react'; +import { useClusters } from 'lib/hooks/api/clusters'; +import useCurrentClusterName from 'lib/hooks/useCurrentClusterName'; import * as S from './Nav.styled'; import MenuItem from './Menu/MenuItem'; @@ -7,6 +8,7 @@ import ClusterMenu from './ClusterMenu/ClusterMenu'; const Nav: FC = () => { const clusters = useClusters(); + const clusterName = useCurrentClusterName(); return ( diff --git a/frontend/src/lib/hooks/useCurrentClusterName.ts b/frontend/src/lib/hooks/useCurrentClusterName.ts new file mode 100644 index 000000000..69ab5a8b7 --- /dev/null +++ b/frontend/src/lib/hooks/useCurrentClusterName.ts @@ -0,0 +1,15 @@ +import { useLocation } from 'react-router-dom'; + +function useCurrentClusterName() { + const location = useLocation(); + const parts = location.pathname.split('/'); + const clusterPosition = parts.indexOf('clusters'); + + if (clusterPosition === undefined) { + return undefined; + } + + return parts[clusterPosition + 1]; +} + +export default useCurrentClusterName; From 4acf09a104d7a0c4cb64fe0b5fc4b95f3fdb6c3b Mon Sep 17 00:00:00 2001 From: Pavel Makarichev Date: Tue, 10 Jun 2025 21:33:07 +0300 Subject: [PATCH 3/7] enh: add resource page heading with cluster name --- frontend/src/components/ACLPage/List/List.tsx | 6 +++--- .../src/components/Brokers/Broker/Broker.tsx | 4 ++-- .../Brokers/BrokersList/BrokersList.tsx | 4 ++-- .../components/Connect/Details/DetailsPage.tsx | 6 +++--- .../src/components/Connect/List/ListPage.tsx | 6 +++--- frontend/src/components/Connect/New/New.tsx | 4 ++-- .../ConsumerGroups/Details/Details.tsx | 6 +++--- .../Details/ResetOffsets/ResetOffsets.tsx | 4 ++-- frontend/src/components/ConsumerGroups/List.tsx | 4 ++-- frontend/src/components/KsqlDb/KsqlDb.tsx | 6 +++--- .../src/components/Schemas/Details/Details.tsx | 6 +++--- frontend/src/components/Schemas/Diff/Diff.tsx | 4 ++-- frontend/src/components/Schemas/Edit/Form.tsx | 4 ++-- frontend/src/components/Schemas/List/List.tsx | 6 +++--- frontend/src/components/Schemas/New/New.tsx | 4 ++-- .../src/components/Topics/List/ListPage.tsx | 6 +++--- frontend/src/components/Topics/New/New.tsx | 4 ++-- frontend/src/components/Topics/Topic/Topic.tsx | 6 +++--- .../common/PageHeading/PageHeading.styled.ts | 9 ++++++++- .../common/PageHeading/PageHeading.tsx | 17 ++++++++++++----- .../ResourcePageHeading/ResourcePageHeading.tsx | 13 +++++++++++++ frontend/src/theme/theme.ts | 6 ++++++ 22 files changed, 84 insertions(+), 51 deletions(-) create mode 100644 frontend/src/components/common/ResourcePageHeading/ResourcePageHeading.tsx diff --git a/frontend/src/components/ACLPage/List/List.tsx b/frontend/src/components/ACLPage/List/List.tsx index 26155172b..07255011e 100644 --- a/frontend/src/components/ACLPage/List/List.tsx +++ b/frontend/src/components/ACLPage/List/List.tsx @@ -1,6 +1,5 @@ import React from 'react'; import { ColumnDef, Row } from '@tanstack/react-table'; -import PageHeading from 'components/common/PageHeading/PageHeading'; import Table from 'components/common/NewTable'; import { useConfirm } from 'lib/hooks/useConfirm'; import useAppParams from 'lib/hooks/useAppParams'; @@ -20,6 +19,7 @@ import { useTheme } from 'styled-components'; import ACLFormContext from 'components/ACLPage/Form/AclFormContext'; import PlusIcon from 'components/common/Icons/PlusIcon'; import ActionButton from 'components/common/ActionComponent/ActionButton/ActionButton'; +import ResourcePageHeading from 'components/common/ResourcePageHeading/ResourcePageHeading'; import * as S from './List.styled'; @@ -149,7 +149,7 @@ const ACList: React.FC = () => { return ( - + { > Create ACL - + { ); return ( <> - { return ( <> - + { return (
- - + { return ( <> - + {!isReadOnly && ( { placement="left" /> )} - + { return ( - { return (
- { )} - +
diff --git a/frontend/src/components/ConsumerGroups/Details/ResetOffsets/ResetOffsets.tsx b/frontend/src/components/ConsumerGroups/Details/ResetOffsets/ResetOffsets.tsx index 0b5864794..6edeff068 100644 --- a/frontend/src/components/ConsumerGroups/Details/ResetOffsets/ResetOffsets.tsx +++ b/frontend/src/components/ConsumerGroups/Details/ResetOffsets/ResetOffsets.tsx @@ -1,10 +1,10 @@ import React from 'react'; import { clusterConsumerGroupsPath, ClusterGroupParam } from 'lib/paths'; import 'react-datepicker/dist/react-datepicker.css'; -import PageHeading from 'components/common/PageHeading/PageHeading'; import useAppParams from 'lib/hooks/useAppParams'; import { useConsumerGroupDetails } from 'lib/hooks/api/consumers'; import PageLoader from 'components/common/PageLoader/PageLoader'; +import ResourcePageHeading from 'components/common/ResourcePageHeading/ResourcePageHeading'; import { ConsumerGroupOffsetsReset, ConsumerGroupOffsetsResetType, @@ -37,7 +37,7 @@ const ResetOffsets: React.FC = () => { return ( <> - { const { clusterName } = useAppParams(); @@ -92,7 +92,7 @@ const List = () => { return ( <> - + diff --git a/frontend/src/components/KsqlDb/KsqlDb.tsx b/frontend/src/components/KsqlDb/KsqlDb.tsx index d105720aa..12a2a8401 100644 --- a/frontend/src/components/KsqlDb/KsqlDb.tsx +++ b/frontend/src/components/KsqlDb/KsqlDb.tsx @@ -10,13 +10,13 @@ import { clusterKsqlDbTablesRelativePath, ClusterNameRoute, } from 'lib/paths'; -import PageHeading from 'components/common/PageHeading/PageHeading'; import { ActionButton } from 'components/common/ActionComponent'; import Navbar from 'components/common/Navigation/Navbar.styled'; import { Navigate, NavLink, Route, Routes } from 'react-router-dom'; import { Action, ResourceType } from 'generated-sources'; import { useKsqlkDb } from 'lib/hooks/api/ksqlDb'; import 'ace-builds/src-noconflict/ace'; +import ResourcePageHeading from 'components/common/ResourcePageHeading/ResourcePageHeading'; import TableView from './TableView'; @@ -29,7 +29,7 @@ const KsqlDb: React.FC = () => { return ( <> - + { > Execute KSQL Request - + { return ( <> - { )} - + {schema && } Old versions {areVersionsFetching ? ( diff --git a/frontend/src/components/Schemas/Diff/Diff.tsx b/frontend/src/components/Schemas/Diff/Diff.tsx index 43e31eddf..1bcafa774 100644 --- a/frontend/src/components/Schemas/Diff/Diff.tsx +++ b/frontend/src/components/Schemas/Diff/Diff.tsx @@ -11,8 +11,8 @@ import { useNavigate, useLocation } from 'react-router-dom'; import { useForm, Controller } from 'react-hook-form'; import Select from 'components/common/Select/Select'; import useAppParams from 'lib/hooks/useAppParams'; -import PageHeading from 'components/common/PageHeading/PageHeading'; import { useGetSchemasVersions } from 'lib/hooks/api/schemas'; +import ResourcePageHeading from 'components/common/ResourcePageHeading/ResourcePageHeading'; import * as S from './Diff.styled'; import { BackButton } from './Diff.styled'; @@ -57,7 +57,7 @@ const Diff: React.FC = () => { return ( <> - = ({ schema }) => { return ( - { return ( <> - + {!isReadOnly && ( <> @@ -77,7 +77,7 @@ const List: React.FC = () => { )} - + diff --git a/frontend/src/components/Schemas/New/New.tsx b/frontend/src/components/Schemas/New/New.tsx index 4bfcc4605..06809d984 100644 --- a/frontend/src/components/Schemas/New/New.tsx +++ b/frontend/src/components/Schemas/New/New.tsx @@ -16,11 +16,11 @@ import { FormError } from 'components/common/Input/Input.styled'; import Select from 'components/common/Select/Select'; import { Button } from 'components/common/Button/Button'; import { Textarea } from 'components/common/Textbox/Textarea.styled'; -import PageHeading from 'components/common/PageHeading/PageHeading'; import useAppParams from 'lib/hooks/useAppParams'; import yup from 'lib/yupExtended'; import { yupResolver } from '@hookform/resolvers/yup'; import { useCreateSchema } from 'lib/hooks/api/schemas'; +import ResourcePageHeading from 'components/common/ResourcePageHeading/ResourcePageHeading'; import * as S from './New.styled'; @@ -71,7 +71,7 @@ const New: React.FC = () => { return ( - { const { isReadOnly } = React.useContext(ClusterContext); @@ -46,7 +46,7 @@ const ListPage: React.FC = () => { return ( <> - + {!isReadOnly && ( { Add a Topic )} - +