custom navigation for search

This commit is contained in:
typescreep
2025-09-30 14:56:08 +03:00
parent 54c279b5f1
commit 96f85c9581
6 changed files with 70 additions and 6 deletions

View File

@@ -8,9 +8,10 @@ import { Styled } from './styled'
type THeaderProps = {
inside?: boolean
isSearch?: boolean
}
export const HeaderSecond: FC<THeaderProps> = ({ inside }) => {
export const HeaderSecond: FC<THeaderProps> = ({ inside, isSearch }) => {
// const { projectName, instanceName, clusterName, entryType, namespace, syntheticProject } = useParams()
const { projectName, instanceName, clusterName, namespace, syntheticProject } = useParams()
const { token } = theme.useToken()
@@ -24,14 +25,14 @@ export const HeaderSecond: FC<THeaderProps> = ({ inside }) => {
<Flex gap={18}>
{inside ? <SelectorClusterInside clusterName={clusterName} /> : <SelectorCluster clusterName={clusterName} />}
{inside && <SelectorInside clusterName={clusterName} namespace={namespace} />}
{!inside && BASE_USE_NAMESPACE_NAV !== 'true' && (
{!inside && !isSearch && BASE_USE_NAMESPACE_NAV !== 'true' && (
<Selector
clusterName={clusterName}
projectName={projectName || possibleProject}
instanceName={instanceName || possibleInstance}
/>
)}
{!inside && BASE_USE_NAMESPACE_NAV === 'true' && (
{!inside && (isSearch || BASE_USE_NAMESPACE_NAV === 'true') && (
<SelectorNamespace clusterName={clusterName} namespace={namespace} />
)}
</Flex>

View File

@@ -1,9 +1,12 @@
import React, { FC, useState } from 'react'
import { Flex, Typography } from 'antd'
import { useNavigate } from 'react-router-dom'
import { useLocation, useNavigate } from 'react-router-dom'
import { useDirectUnknownResource } from '@prorobotech/openapi-k8s-toolkit'
import { useSelector } from 'react-redux'
import type { RootState } from 'store/store'
import { useNavSelectorInside } from 'hooks/useNavSelectorInside'
import { useMountEffect } from 'hooks/useMountEffect'
import { useIsSearchPage } from 'hooks/useIsSearchPage'
import { EntrySelect } from 'components/atoms'
import {
BASE_API_GROUP,
@@ -19,6 +22,9 @@ type TSelectorNamespaceProps = {
export const SelectorNamespace: FC<TSelectorNamespaceProps> = ({ clusterName, namespace }) => {
const navigate = useNavigate()
const location = useLocation()
const baseprefix = useSelector((state: RootState) => state.baseprefix.baseprefix)
const [selectedClusterName, setSelectedClusterName] = useState(clusterName)
const [selectedNamespace, setSelectedNamespace] = useState(namespace)
@@ -34,7 +40,45 @@ export const SelectorNamespace: FC<TSelectorNamespaceProps> = ({ clusterName, na
isEnabled: clusterName !== undefined,
})
const isSearchPage = useIsSearchPage(baseprefix || '')
const handleNamepsaceChange = (value?: string) => {
if (isSearchPage) {
const { pathname, search, hash } = location
const segs = pathname.split('/')
// Assume pattern: /prefix/:clusterName/:namespace?/:syntheticProject?/search/*
// Find the "search" segment index
const searchIdx = segs.indexOf('search')
const clusterIdx = segs.indexOf(selectedClusterName || '')
if (clusterIdx === -1) {
return
} // bail if we can't find the cluster
const nsIdx = clusterIdx + 1 // where namespace would live if present
const spIdx = clusterIdx + 2 // where syntheticProject would live if present
const nsExists = nsIdx < searchIdx // true if something occupies ns slot
const spExists = spIdx < searchIdx // true if something occupies sp slot
if (value && value !== 'all') {
setSelectedNamespace(value)
if (nsExists) {
// replace namespace in place
segs[nsIdx] = value
} else {
// insert namespace before "search" (or before syntheticProject if present)
const insertAt = spExists ? spIdx : searchIdx
segs.splice(insertAt, 0, value)
}
} else if (nsExists) {
segs.splice(nsIdx, 1) // removes namespace; syntheticProject (if any) shifts left
}
// if ns didn't exist, nothing to clear
navigate(segs.join('/') + search + hash, { replace: true })
return
}
if (value && value !== 'all') {
setSelectedNamespace(value)
const changeUrl =

View File

@@ -0,0 +1 @@
export * from './useIsSearchPage'

View File

@@ -0,0 +1,9 @@
import { useLocation, matchPath } from 'react-router-dom'
export const useIsSearchPage = (prefix: string) => {
const { pathname } = useLocation()
const base = `/${prefix}`.replace(/\/{2,}/g, '/').replace(/\/$/, '')
const pattern = `${base}/:clusterName/:namespace?/:syntheticProject?/search/*`
return Boolean(matchPath({ path: pattern }, pathname))
}

View File

@@ -26,6 +26,7 @@ export const SearchPage: FC<TSearchPageProps> = ({ forcedTheme }) => {
<BaseTemplate
forcedTheme={forcedTheme}
inside={false}
isSearch
sidebar={
<ManageableSidebar
instanceName={possibleInstance}

View File

@@ -24,10 +24,18 @@ type TBaseTemplateProps = {
children?: ReactNode | undefined
forcedTheme?: 'dark' | 'light'
inside?: boolean
isSearch?: boolean
sidebar?: ReactNode
}
export const BaseTemplate: FC<TBaseTemplateProps> = ({ children, withNoCluster, forcedTheme, inside, sidebar }) => {
export const BaseTemplate: FC<TBaseTemplateProps> = ({
children,
withNoCluster,
forcedTheme,
inside,
isSearch,
sidebar,
}) => {
const navigate = useNavigate()
const { clusterName } = useParams()
const { useToken } = antdtheme
@@ -106,7 +114,7 @@ export const BaseTemplate: FC<TBaseTemplateProps> = ({ children, withNoCluster,
</Col>
<FlexCol flex="auto">
<DefaultLayout.ContentPadding $isFederation={isFederation}>
<HeaderSecond inside={inside} />
<HeaderSecond inside={inside} isSearch={isSearch} />
{clusterListQuery.error && (
<Alert message={`Cluster List Error: ${clusterListQuery.error?.message} `} type="error" />
)}