Merge pull request #145 from PRO-Robotech/feature/dev

remove flickering | currenttags parser in sidebars
This commit is contained in:
typescreep
2025-10-20 11:30:44 +03:00
committed by GitHub
30 changed files with 226 additions and 277 deletions

8
package-lock.json generated
View File

@@ -11,7 +11,7 @@
"@ant-design/icons": "5.6.0",
"@monaco-editor/react": "4.6.0",
"@originjs/vite-plugin-federation": "1.3.6",
"@prorobotech/openapi-k8s-toolkit": "^0.0.1-alpha.136",
"@prorobotech/openapi-k8s-toolkit": "^0.0.1-alpha.137",
"@readme/openapi-parser": "4.0.0",
"@reduxjs/toolkit": "2.2.5",
"@tanstack/react-query": "5.62.2",
@@ -2804,9 +2804,9 @@
}
},
"node_modules/@prorobotech/openapi-k8s-toolkit": {
"version": "0.0.1-alpha.136",
"resolved": "https://registry.npmjs.org/@prorobotech/openapi-k8s-toolkit/-/openapi-k8s-toolkit-0.0.1-alpha.136.tgz",
"integrity": "sha512-Lwdifu6YwCYxg5uWR+oL52fDl7g5PU79kgg230y38nrfUqP7251H2amGSyg2QMmrYG3x31BwFM5iuWLPqDmqfA==",
"version": "0.0.1-alpha.137",
"resolved": "https://registry.npmjs.org/@prorobotech/openapi-k8s-toolkit/-/openapi-k8s-toolkit-0.0.1-alpha.137.tgz",
"integrity": "sha512-40wpiC8aRBmXZiNnkqYjqo15UEjF9mowoSGqe1/xzxFdjjeZtSBoDoGhLMFy/j6QBCvgaYnNH7mYqxZg5MS7rg==",
"license": "MIT",
"dependencies": {
"@monaco-editor/react": "4.6.0",

View File

@@ -20,7 +20,7 @@
"@ant-design/icons": "5.6.0",
"@monaco-editor/react": "4.6.0",
"@originjs/vite-plugin-federation": "1.3.6",
"@prorobotech/openapi-k8s-toolkit": "0.0.1-alpha.136",
"@prorobotech/openapi-k8s-toolkit": "0.0.1-alpha.137",
"@readme/openapi-parser": "4.0.0",
"@reduxjs/toolkit": "2.2.5",
"@tanstack/react-query": "5.62.2",

View File

@@ -30,6 +30,7 @@ import {
} from 'pages'
import { getBasePrefix } from 'utils/getBaseprefix'
import { colorsLight, colorsDark, sizes } from 'constants/colors'
import { MainLayout } from 'templates/MainLayout'
type TAppProps = {
isFederation?: boolean
@@ -54,87 +55,77 @@ export const App: FC<TAppProps> = ({ isFederation, forcedTheme }) => {
const renderRoutes = (prefix = '') => (
<Routes>
<Route path={`${prefix}/`} element={<MainPage forcedTheme={forcedTheme} />} />
<Route path={`${prefix}/clusters`} element={<ListClustersPage forcedTheme={forcedTheme} />} />
<Route path={`${prefix}/clusters/:clusterName`} element={<ListProjectsPage forcedTheme={forcedTheme} />} />
<Route path={`${prefix}/inside/`} element={<MainPage forcedTheme={forcedTheme} />} />
<Route
path={`${prefix}/clusters/:clusterName/projects/:namespace`}
element={<ProjectInfoPage forcedTheme={forcedTheme} />}
/>
<Route
path={`${prefix}/inside/clusters`}
element={<ListInsideClustersAndNsPage forcedTheme={forcedTheme} inside />}
/>
<Route
path={`${prefix}/inside/:clusterName/:namespace?/apis`}
element={<ListInsideApiPage forcedTheme={forcedTheme} inside />}
/>
<Route
path={`${prefix}/inside/:clusterName/:namespace?/crds-by-api/:apiGroup/:apiVersion/:apiExtensionVersion`}
element={<ListInsideCrdByApiGroupPage forcedTheme={forcedTheme} inside />}
/>
<Route
path={`${prefix}/inside/:clusterName/:namespace?/apis-by-api/:apiGroup/:apiVersion/`}
element={<ListInsideApiByApiGroupPage forcedTheme={forcedTheme} inside />}
/>
<Route
path={`${prefix}/:clusterName/:namespace?/:syntheticProject?/crd-table/:apiGroup/:apiVersion/:apiExtensionVersion/:crdName`}
element={<TableCrdPage forcedTheme={forcedTheme} />}
/>
<Route
path={`${prefix}/:clusterName/:namespace?/:syntheticProject?/api-table/:apiGroup/:apiVersion/:typeName`}
element={<TableApiPage forcedTheme={forcedTheme} />}
/>
<Route
path={`${prefix}/:clusterName/:namespace?/:syntheticProject?/builtin-table/:typeName`}
element={<TableBuiltinPage forcedTheme={forcedTheme} />}
/>
<Route
path={`${prefix}/:clusterName/:namespace?/:syntheticProject?/forms/builtin/:apiVersion/:typeName/:entryName?/`}
element={<FormBuiltinPage forcedTheme={forcedTheme} />}
/>
<Route
path={`${prefix}/:clusterName/:namespace?/:syntheticProject?/forms/apis/:apiGroup/:apiVersion/:typeName/:entryName?/`}
element={<FormApiPage forcedTheme={forcedTheme} />}
/>
<Route
path={`${prefix}/:clusterName/:namespace?/:syntheticProject?/forms/crds/:apiGroup/:apiVersion/:typeName/:entryName?/`}
element={<FormCrdPage forcedTheme={forcedTheme} />}
/>
<Route
path={`${prefix}/inside/:clusterName/:namespace?/:syntheticProject?/crd-table/:apiGroup/:apiVersion/:apiExtensionVersion/:crdName`}
element={<TableCrdPage forcedTheme={forcedTheme} inside />}
/>
<Route
path={`${prefix}/inside/:clusterName/:namespace?/:syntheticProject?/api-table/:apiGroup/:apiVersion/:typeName`}
element={<TableApiPage forcedTheme={forcedTheme} inside />}
/>
<Route
path={`${prefix}/inside/:clusterName/:namespace?/:syntheticProject?/builtin-table/:typeName`}
element={<TableBuiltinPage forcedTheme={forcedTheme} inside />}
/>
<Route
path={`${prefix}/inside/:clusterName/:namespace?/:syntheticProject?/forms/builtin/:apiVersion/:typeName/:entryName?/`}
element={<FormBuiltinPage forcedTheme={forcedTheme} inside />}
/>
<Route
path={`${prefix}/inside/:clusterName/:namespace?/:syntheticProject?/forms/apis/:apiGroup/:apiVersion/:typeName/:entryName?/`}
element={<FormApiPage forcedTheme={forcedTheme} inside />}
/>
<Route
path={`${prefix}/inside/:clusterName/:namespace?/:syntheticProject?/forms/crds/:apiGroup/:apiVersion/:typeName/:entryName?/`}
element={<FormCrdPage forcedTheme={forcedTheme} inside />}
/>
<Route
path={`${prefix}/:clusterName/:namespace?/:syntheticProject?/factory/:key/*`}
element={<FactoryPage forcedTheme={forcedTheme} />}
/>
<Route
path={`${prefix}/:clusterName/:namespace?/:syntheticProject?/search/*`}
element={<SearchPage forcedTheme={forcedTheme} />}
/>
<Route path={`${prefix}/factory-admin/*`} element={<FactoryAdminPage />} />
<Route element={<MainLayout forcedTheme={forcedTheme} />}>
<Route path={`${prefix}/`} element={<MainPage />} />
<Route path={`${prefix}/clusters`} element={<ListClustersPage />} />
<Route path={`${prefix}/clusters/:clusterName`} element={<ListProjectsPage />} />
<Route path={`${prefix}/inside/`} element={<MainPage />} />
<Route path={`${prefix}/clusters/:clusterName/projects/:namespace`} element={<ProjectInfoPage />} />
<Route path={`${prefix}/inside/clusters`} element={<ListInsideClustersAndNsPage inside />} />
<Route path={`${prefix}/inside/:clusterName/:namespace?/apis`} element={<ListInsideApiPage inside />} />
<Route
path={`${prefix}/inside/:clusterName/:namespace?/crds-by-api/:apiGroup/:apiVersion/:apiExtensionVersion`}
element={<ListInsideCrdByApiGroupPage inside />}
/>
<Route
path={`${prefix}/inside/:clusterName/:namespace?/apis-by-api/:apiGroup/:apiVersion/`}
element={<ListInsideApiByApiGroupPage inside />}
/>
<Route
path={`${prefix}/:clusterName/:namespace?/:syntheticProject?/crd-table/:apiGroup/:apiVersion/:apiExtensionVersion/:crdName`}
element={<TableCrdPage />}
/>
<Route
path={`${prefix}/:clusterName/:namespace?/:syntheticProject?/api-table/:apiGroup/:apiVersion/:typeName`}
element={<TableApiPage />}
/>
<Route
path={`${prefix}/:clusterName/:namespace?/:syntheticProject?/builtin-table/:typeName`}
element={<TableBuiltinPage />}
/>
<Route
path={`${prefix}/:clusterName/:namespace?/:syntheticProject?/forms/builtin/:apiVersion/:typeName/:entryName?/`}
element={<FormBuiltinPage />}
/>
<Route
path={`${prefix}/:clusterName/:namespace?/:syntheticProject?/forms/apis/:apiGroup/:apiVersion/:typeName/:entryName?/`}
element={<FormApiPage />}
/>
<Route
path={`${prefix}/:clusterName/:namespace?/:syntheticProject?/forms/crds/:apiGroup/:apiVersion/:typeName/:entryName?/`}
element={<FormCrdPage />}
/>
<Route
path={`${prefix}/inside/:clusterName/:namespace?/:syntheticProject?/crd-table/:apiGroup/:apiVersion/:apiExtensionVersion/:crdName`}
element={<TableCrdPage inside />}
/>
<Route
path={`${prefix}/inside/:clusterName/:namespace?/:syntheticProject?/api-table/:apiGroup/:apiVersion/:typeName`}
element={<TableApiPage inside />}
/>
<Route
path={`${prefix}/inside/:clusterName/:namespace?/:syntheticProject?/builtin-table/:typeName`}
element={<TableBuiltinPage inside />}
/>
<Route
path={`${prefix}/inside/:clusterName/:namespace?/:syntheticProject?/forms/builtin/:apiVersion/:typeName/:entryName?/`}
element={<FormBuiltinPage inside />}
/>
<Route
path={`${prefix}/inside/:clusterName/:namespace?/:syntheticProject?/forms/apis/:apiGroup/:apiVersion/:typeName/:entryName?/`}
element={<FormApiPage inside />}
/>
<Route
path={`${prefix}/inside/:clusterName/:namespace?/:syntheticProject?/forms/crds/:apiGroup/:apiVersion/:typeName/:entryName?/`}
element={<FormCrdPage inside />}
/>
<Route
path={`${prefix}/:clusterName/:namespace?/:syntheticProject?/factory/:key/*`}
element={<FactoryPage />}
/>
<Route path={`${prefix}/:clusterName/:namespace?/:syntheticProject?/search/*`} element={<SearchPage />} />
<Route path={`${prefix}/factory-admin/*`} element={<FactoryAdminPage />} />
</Route>
</Routes>
)

View File

@@ -25,7 +25,7 @@ export const User: FC = () => {
// },
{
key: '2',
label: <div onClick={() => navigate(`${baseprefix}/inside`)}>Inside</div>,
label: <div onClick={() => navigate(`${baseprefix}/inside/clusters`)}>Inside</div>,
},
{
key: '3',

View File

@@ -38,7 +38,7 @@ export const SelectorCluster: FC<TSelectorClusterProps> = ({ clusterName }) => {
<Flex gap={18} justify="start" align="center">
<Typography.Text>Cluster: </Typography.Text>
<EntrySelect
placeholder="Cluster"
placeholder="Select Cluster"
options={clustersInSidebar}
value={selectedClusterName}
onChange={handleClusterChange}

View File

@@ -36,7 +36,7 @@ export const SelectorClusterInside: FC<TSelectorClusterInsideProps> = ({ cluster
<Flex gap={18} justify="start" align="center">
<Typography.Text>Cluster: </Typography.Text>
<EntrySelect
placeholder="Cluster"
placeholder="Select Cluster"
options={clustersInSidebar}
value={selectedClusterName}
onChange={handleClusterChange}

View File

@@ -14,8 +14,8 @@ export const SelectorInside: FC<TSelectorInsideProps> = ({ clusterName, namespac
const navigate = useNavigate()
const params = useParams()
const [selectedClusterName, setSelectedClusterName] = useState(clusterName)
const [selectedNamespace, setSelectedNamespace] = useState(namespace)
const [selectedClusterName, setSelectedClusterName] = useState<string | undefined>(clusterName)
const [selectedNamespace, setSelectedNamespace] = useState<string | undefined>(namespace)
// const { namespacesInSidebar, clustersInSidebar } = useNavSelectorInside(selectedClusterName)
const { namespacesInSidebar } = useNavSelectorInside(selectedClusterName)

View File

@@ -18,9 +18,10 @@ export const ListInsideClusterAndNs: FC = () => {
const [selectedNamespace, setSelectedNamespace] = useState<string>()
const namespacesData = useBuiltinResources({
clusterName: cluster,
clusterName: selectedCluster || '',
typeName: 'namespaces',
limit: null,
isEnabled: selectedCluster !== undefined,
})
return (

View File

@@ -66,6 +66,7 @@ export const useNavSelector = (clusterName?: string, projectName?: string) => {
apiVersion: BASE_PROJECTS_VERSION,
typeName: BASE_PROJECTS_RESOURCE_NAME,
limit: null,
isEnabled: clusterName !== undefined,
})
const { data: instances, isSuccess: allInstancesLoadingSuccess } = useApiResources({
@@ -75,6 +76,7 @@ export const useNavSelector = (clusterName?: string, projectName?: string) => {
apiVersion: BASE_INSTANCES_VERSION,
typeName: BASE_INSTANCES_RESOURCE_NAME,
limit: null,
isEnabled: clusterName !== undefined,
})
const clustersInSidebar = clusterList ? clusterList.map(mappedClusterToOptionInSidebar) : []

View File

@@ -19,6 +19,7 @@ export const useNavSelectorInside = (clusterName?: string) => {
clusterName: clusterName || '',
typeName: 'namespaces',
limit: null,
isEnabled: Boolean(clusterName),
})
const clustersInSidebar = clusterList ? clusterList.map(mappedClusterToOptionInSidebar) : []

View File

@@ -5,11 +5,7 @@ import { getBreadcrumbsIdPrefix } from 'utils/getBreadcrumbsIdPrefix'
import { getSidebarIdPrefix } from 'utils/getSidebarIdPrefix'
import { BaseTemplate } from 'templates'
type TFactoryPageProps = {
forcedTheme?: 'light' | 'dark'
}
export const FactoryPage: FC<TFactoryPageProps> = ({ forcedTheme }) => {
export const FactoryPage: FC = () => {
const { namespace, syntheticProject, key } = useParams()
const [currentTags, setCurrentTags] = useState<string[]>()
@@ -29,7 +25,6 @@ export const FactoryPage: FC<TFactoryPageProps> = ({ forcedTheme }) => {
return (
<BaseTemplate
forcedTheme={forcedTheme}
sidebar={
<ManageableSidebar
instanceName={possibleInstance}
@@ -38,7 +33,7 @@ export const FactoryPage: FC<TFactoryPageProps> = ({ forcedTheme }) => {
currentTags={currentTags}
/>
}
withNoCluster
// withNoCluster
>
<NavigationContainer>
<ManageableBreadcrumbs idToCompare={breadcrumbsId} />

View File

@@ -18,11 +18,10 @@ import { BASE_USE_NAMESPACE_NAV } from 'constants/customizationApiGroupAndVersio
import { BaseTemplate } from 'templates'
type TFormApiPageProps = {
forcedTheme?: 'light' | 'dark'
inside?: boolean
}
export const FormApiPage: FC<TFormApiPageProps> = ({ forcedTheme, inside }) => {
export const FormApiPage: FC<TFormApiPageProps> = ({ inside }) => {
const { clusterName, syntheticProject, namespace, apiGroup, apiVersion, typeName, entryName } = useParams()
const [searchParams] = useSearchParams()
const baseprefix = useSelector((state: RootState) => state.baseprefix.baseprefix)
@@ -54,7 +53,6 @@ export const FormApiPage: FC<TFormApiPageProps> = ({ forcedTheme, inside }) => {
return (
<BaseTemplate
forcedTheme={forcedTheme}
inside={inside}
sidebar={
<ManageableSidebar

View File

@@ -18,11 +18,10 @@ import { BASE_USE_NAMESPACE_NAV } from 'constants/customizationApiGroupAndVersio
import { BaseTemplate } from 'templates'
type TFormBuiltinPageProps = {
forcedTheme?: 'light' | 'dark'
inside?: boolean
}
export const FormBuiltinPage: FC<TFormBuiltinPageProps> = ({ forcedTheme, inside }) => {
export const FormBuiltinPage: FC<TFormBuiltinPageProps> = ({ inside }) => {
const { clusterName, syntheticProject, namespace, typeName, entryName } = useParams()
const [searchParams] = useSearchParams()
const baseprefix = useSelector((state: RootState) => state.baseprefix.baseprefix)
@@ -54,7 +53,6 @@ export const FormBuiltinPage: FC<TFormBuiltinPageProps> = ({ forcedTheme, inside
return (
<BaseTemplate
forcedTheme={forcedTheme}
inside={inside}
sidebar={
<ManageableSidebar

View File

@@ -18,11 +18,10 @@ import { BASE_USE_NAMESPACE_NAV } from 'constants/customizationApiGroupAndVersio
import { BaseTemplate } from 'templates'
type TFormCrdPageProps = {
forcedTheme?: 'light' | 'dark'
inside?: boolean
}
export const FormCrdPage: FC<TFormCrdPageProps> = ({ forcedTheme, inside }) => {
export const FormCrdPage: FC<TFormCrdPageProps> = ({ inside }) => {
const { clusterName, syntheticProject, apiGroup, apiVersion, namespace, typeName, entryName } = useParams()
const [searchParams] = useSearchParams()
const baseprefix = useSelector((state: RootState) => state.baseprefix.baseprefix)
@@ -54,7 +53,6 @@ export const FormCrdPage: FC<TFormCrdPageProps> = ({ forcedTheme, inside }) => {
return (
<BaseTemplate
forcedTheme={forcedTheme}
inside={inside}
sidebar={
<ManageableSidebar

View File

@@ -7,11 +7,7 @@ import type { RootState } from 'store/store'
import { ListClusters, NavigationContainer } from 'components'
import { BaseTemplate } from 'templates'
type TListClustersPageProps = {
forcedTheme?: 'light' | 'dark'
}
export const ListClustersPage: FC<TListClustersPageProps> = ({ forcedTheme }) => {
export const ListClustersPage: FC = () => {
const baseprefix = useSelector((state: RootState) => state.baseprefix.baseprefix)
const breadcrumbItems = [
@@ -26,7 +22,7 @@ export const ListClustersPage: FC<TListClustersPageProps> = ({ forcedTheme }) =>
]
return (
<BaseTemplate withNoCluster forcedTheme={forcedTheme}>
<BaseTemplate>
<NavigationContainer>
<Breadcrumb items={breadcrumbItems} separator=">" />
</NavigationContainer>

View File

@@ -7,18 +7,17 @@ import { getBreadcrumbsIdPrefix } from 'utils/getBreadcrumbsIdPrefix'
import { BaseTemplate } from 'templates'
type TListInsideApiByApiGroupPageProps = {
forcedTheme?: 'light' | 'dark'
inside?: boolean
}
export const ListInsideApiByApiGroupPage: FC<TListInsideApiByApiGroupPageProps> = ({ forcedTheme, inside }) => {
export const ListInsideApiByApiGroupPage: FC<TListInsideApiByApiGroupPageProps> = ({ inside }) => {
const { namespace, apiGroup, apiVersion } = useParams()
const sidebarId = `${getSidebarIdPrefix({ namespace: !!namespace, inside })}api-by-api`
const breadcrumbsId = `${getBreadcrumbsIdPrefix({ namespace: !!namespace, inside })}api-by-api`
return (
<BaseTemplate forcedTheme={forcedTheme} inside={inside} sidebar={<ManageableSidebar idToCompare={sidebarId} />}>
<BaseTemplate inside={inside} sidebar={<ManageableSidebar idToCompare={sidebarId} />}>
<NavigationContainer>
<ManageableBreadcrumbs idToCompare={breadcrumbsId} inside />
</NavigationContainer>

View File

@@ -7,18 +7,17 @@ import { getBreadcrumbsIdPrefix } from 'utils/getBreadcrumbsIdPrefix'
import { BaseTemplate } from 'templates'
type TListInsideApiPageProps = {
forcedTheme?: 'light' | 'dark'
inside?: boolean
}
export const ListInsideApiPage: FC<TListInsideApiPageProps> = ({ forcedTheme, inside }) => {
export const ListInsideApiPage: FC<TListInsideApiPageProps> = ({ inside }) => {
const { namespace } = useParams()
const sidebarId = `${getSidebarIdPrefix({ namespace: !!namespace, inside })}apis`
const breadcrumbsId = `${getBreadcrumbsIdPrefix({ namespace: !!namespace, inside })}apis`
return (
<BaseTemplate forcedTheme={forcedTheme} inside={inside} sidebar={<ManageableSidebar idToCompare={sidebarId} />}>
<BaseTemplate inside={inside} sidebar={<ManageableSidebar idToCompare={sidebarId} />}>
<NavigationContainer>
<ManageableBreadcrumbs idToCompare={breadcrumbsId} inside />
</NavigationContainer>

View File

@@ -8,11 +8,10 @@ import { ListInsideClusterAndNs, NavigationContainer } from 'components'
import { BaseTemplate } from 'templates'
type TListInsideClustersAndNsPageProps = {
forcedTheme?: 'light' | 'dark'
inside?: boolean
}
export const ListInsideClustersAndNsPage: FC<TListInsideClustersAndNsPageProps> = ({ forcedTheme, inside }) => {
export const ListInsideClustersAndNsPage: FC<TListInsideClustersAndNsPageProps> = ({ inside }) => {
const baseprefix = useSelector((state: RootState) => state.baseprefix.baseprefix)
const breadcrumbItems = [
@@ -27,7 +26,7 @@ export const ListInsideClustersAndNsPage: FC<TListInsideClustersAndNsPageProps>
]
return (
<BaseTemplate withNoCluster forcedTheme={forcedTheme} inside={inside}>
<BaseTemplate inside={inside}>
<NavigationContainer>
<Breadcrumb items={breadcrumbItems} separator=">" />
</NavigationContainer>

View File

@@ -7,18 +7,17 @@ import { getBreadcrumbsIdPrefix } from 'utils/getBreadcrumbsIdPrefix'
import { BaseTemplate } from 'templates'
type TListInsideCrdByApiGroupPageProps = {
forcedTheme?: 'light' | 'dark'
inside?: boolean
}
export const ListInsideCrdByApiGroupPage: FC<TListInsideCrdByApiGroupPageProps> = ({ forcedTheme, inside }) => {
export const ListInsideCrdByApiGroupPage: FC<TListInsideCrdByApiGroupPageProps> = ({ inside }) => {
const { namespace, apiGroup, apiVersion, apiExtensionVersion } = useParams()
const sidebarId = `${getSidebarIdPrefix({ namespace: !!namespace, inside })}crd-by-api`
const breadcrumbsId = `${getBreadcrumbsIdPrefix({ namespace: !!namespace, inside })}crd-by-api`
return (
<BaseTemplate forcedTheme={forcedTheme} inside={inside} sidebar={<ManageableSidebar idToCompare={sidebarId} />}>
<BaseTemplate inside={inside} sidebar={<ManageableSidebar idToCompare={sidebarId} />}>
<NavigationContainer>
<ManageableBreadcrumbs idToCompare={breadcrumbsId} inside />
</NavigationContainer>

View File

@@ -2,13 +2,9 @@ import React, { FC } from 'react'
import { RedirectProjectList } from 'components'
import { BaseTemplate } from 'templates'
type TListProjectsPageProps = {
forcedTheme?: 'light' | 'dark'
}
export const ListProjectsPage: FC<TListProjectsPageProps> = ({ forcedTheme }) => {
export const ListProjectsPage: FC = () => {
return (
<BaseTemplate forcedTheme={forcedTheme}>
<BaseTemplate>
<RedirectProjectList />
</BaseTemplate>
)

View File

@@ -2,16 +2,12 @@ import React, { FC, useEffect } from 'react'
import { useNavigate } from 'react-router-dom'
import { BaseTemplate } from 'templates'
type TMainPageProps = {
forcedTheme?: 'light' | 'dark'
}
export const MainPage: FC<TMainPageProps> = ({ forcedTheme }) => {
export const MainPage: FC = () => {
const navigate = useNavigate()
useEffect(() => {
navigate('./clusters')
}, [navigate])
return <BaseTemplate withNoCluster forcedTheme={forcedTheme} />
return <BaseTemplate />
}

View File

@@ -2,13 +2,9 @@ import React, { FC } from 'react'
import { RedirectProjectInfo } from 'components'
import { BaseTemplate } from 'templates'
type TProjectInfoPageProps = {
forcedTheme?: 'light' | 'dark'
}
export const ProjectInfoPage: FC<TProjectInfoPageProps> = ({ forcedTheme }) => {
export const ProjectInfoPage: FC = () => {
return (
<BaseTemplate forcedTheme={forcedTheme}>
<BaseTemplate>
<RedirectProjectInfo />
</BaseTemplate>
)

View File

@@ -6,11 +6,7 @@ import { getSidebarIdPrefix } from 'utils/getSidebarIdPrefix'
import { getBreadcrumbsIdPrefix } from 'utils/getBreadcrumbsIdPrefix'
import { BaseTemplate } from 'templates'
type TSearchPageProps = {
forcedTheme?: 'light' | 'dark'
}
export const SearchPage: FC<TSearchPageProps> = ({ forcedTheme }) => {
export const SearchPage: FC = () => {
const { namespace, syntheticProject } = useParams()
const possibleProject = syntheticProject && namespace ? syntheticProject : namespace
@@ -28,7 +24,6 @@ export const SearchPage: FC<TSearchPageProps> = ({ forcedTheme }) => {
return (
<BaseTemplate
forcedTheme={forcedTheme}
inside={false}
isSearch
sidebar={

View File

@@ -17,11 +17,10 @@ import {
} from 'constants/customizationApiGroupAndVersion'
type TTableApiPageProps = {
forcedTheme?: 'light' | 'dark'
inside?: boolean
}
export const TableApiPage: FC<TTableApiPageProps> = ({ forcedTheme, inside }) => {
export const TableApiPage: FC<TTableApiPageProps> = ({ inside }) => {
const { clusterName, namespace, syntheticProject, apiGroup, apiVersion, typeName } = useParams()
const [searchParams] = useSearchParams()
const baseprefix = useSelector((state: RootState) => state.baseprefix.baseprefix)
@@ -62,7 +61,6 @@ export const TableApiPage: FC<TTableApiPageProps> = ({ forcedTheme, inside }) =>
return (
<BaseTemplate
forcedTheme={forcedTheme}
inside={inside}
sidebar={
<ManageableSidebar

View File

@@ -12,11 +12,10 @@ import { BaseTemplate } from 'templates'
import { BASE_USE_NAMESPACE_NAV } from 'constants/customizationApiGroupAndVersion'
type TTableBuiltinPageProps = {
forcedTheme?: 'light' | 'dark'
inside?: boolean
}
export const TableBuiltinPage: FC<TTableBuiltinPageProps> = ({ forcedTheme, inside }) => {
export const TableBuiltinPage: FC<TTableBuiltinPageProps> = ({ inside }) => {
const { clusterName, namespace, syntheticProject, typeName } = useParams()
const [searchParams] = useSearchParams()
const baseprefix = useSelector((state: RootState) => state.baseprefix.baseprefix)
@@ -49,7 +48,6 @@ export const TableBuiltinPage: FC<TTableBuiltinPageProps> = ({ forcedTheme, insi
return (
<BaseTemplate
forcedTheme={forcedTheme}
inside={inside}
sidebar={
<ManageableSidebar

View File

@@ -12,11 +12,10 @@ import { BaseTemplate } from 'templates'
import { BASE_USE_NAMESPACE_NAV } from 'constants/customizationApiGroupAndVersion'
type TTableCrdPageProps = {
forcedTheme?: 'light' | 'dark'
inside?: boolean
}
export const TableCrdPage: FC<TTableCrdPageProps> = ({ forcedTheme, inside }) => {
export const TableCrdPage: FC<TTableCrdPageProps> = ({ inside }) => {
const { clusterName, namespace, syntheticProject, apiGroup, apiVersion, apiExtensionVersion, crdName } = useParams()
const baseprefix = useSelector((state: RootState) => state.baseprefix.baseprefix)
@@ -48,7 +47,6 @@ export const TableCrdPage: FC<TTableCrdPageProps> = ({ forcedTheme, inside }) =>
return (
<BaseTemplate
forcedTheme={forcedTheme}
inside={inside}
sidebar={
<ManageableSidebar

View File

@@ -1,132 +1,32 @@
import React, { FC, ReactNode, useEffect, useCallback } from 'react'
import { Layout, theme as antdtheme, Alert, Col } from 'antd'
import { useClusterList } from '@prorobotech/openapi-k8s-toolkit'
import { useSelector, useDispatch } from 'react-redux'
import { useParams, useNavigate } from 'react-router-dom'
import React, { FC, ReactNode } from 'react'
import { Col } from 'antd'
import { useSelector } from 'react-redux'
import type { RootState } from 'store/store'
import { setTheme } from 'store/theme/theme/theme'
import { setCluster } from 'store/cluster/cluster/cluster'
import { setClusterList } from 'store/clusterList/clusterList/clusterList'
import {
DefaultLayout,
DefaultColorProvider,
Header,
HeaderSecond,
Footer,
Sidebar,
RowFlexGrow,
FlexCol,
} from 'components'
import { Styled } from './styled'
import { DefaultLayout, HeaderSecond, Footer, Sidebar, RowFlexGrow, FlexCol } from 'components'
type TBaseTemplateProps = {
withNoCluster?: boolean
// withNoCluster?: boolean
children?: ReactNode | undefined
forcedTheme?: 'dark' | 'light'
inside?: boolean
isSearch?: boolean
sidebar?: ReactNode
}
export const BaseTemplate: FC<TBaseTemplateProps> = ({
children,
withNoCluster,
forcedTheme,
inside,
isSearch,
sidebar,
}) => {
const navigate = useNavigate()
const { clusterName } = useParams()
const { useToken } = antdtheme
const { token } = useToken()
const dispatch = useDispatch()
const theme = useSelector((state: RootState) => state.openapiTheme.theme)
export const BaseTemplate: FC<TBaseTemplateProps> = ({ children, inside, isSearch, sidebar }) => {
const isFederation = useSelector((state: RootState) => state.federation.isFederation)
const baseprefix = useSelector((state: RootState) => state.baseprefix.baseprefix)
const clusterListQuery = useClusterList({ refetchInterval: false })
useEffect(() => {
if (forcedTheme) {
return
}
const localStorageTheme = localStorage.getItem('theme')
if (localStorageTheme && (localStorageTheme === 'dark' || localStorageTheme === 'light')) {
dispatch(setTheme(localStorageTheme))
} else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
localStorage.setItem('theme', 'dark')
dispatch(setTheme('dark'))
} else {
localStorage.setItem('theme', 'light')
dispatch(setTheme('light'))
}
}, [dispatch, forcedTheme])
useEffect(() => {
if (forcedTheme) {
dispatch(setTheme(forcedTheme))
}
}, [dispatch, forcedTheme])
const handleStorage = useCallback(() => {
const localStorageTheme = localStorage.getItem('theme')
if (localStorageTheme && (localStorageTheme === 'dark' || localStorageTheme === 'light')) {
dispatch(setTheme(localStorageTheme))
}
}, [dispatch])
useEffect(() => {
window.addEventListener('storage', handleStorage)
return () => {
window.removeEventListener('storage', handleStorage)
}
}, [handleStorage])
useEffect(() => {
if (clusterListQuery.data) {
dispatch(setClusterList(clusterListQuery.data))
}
}, [clusterListQuery, dispatch])
if (clusterName) {
dispatch(setCluster(clusterName))
}
if (clusterName === undefined) {
dispatch(setCluster(''))
}
if (!clusterName && !withNoCluster) {
navigate(`${baseprefix}/`)
}
return (
<DefaultColorProvider $color={token.colorText}>
<Styled.Container $isDark={theme === 'dark'}>
<Layout>
<DefaultLayout.Layout $bgColor={token.colorBgLayout}>
<DefaultLayout.ContentContainer>
<Header />
<RowFlexGrow wrap={false}>
<Col span="250px">
<Sidebar sidebar={sidebar} />
</Col>
<FlexCol flex="auto">
<DefaultLayout.ContentPadding $isFederation={isFederation}>
<HeaderSecond inside={inside} isSearch={isSearch} />
{clusterListQuery.error && (
<Alert message={`Cluster List Error: ${clusterListQuery.error?.message} `} type="error" />
)}
{children}
</DefaultLayout.ContentPadding>
<Footer />
</FlexCol>
</RowFlexGrow>
</DefaultLayout.ContentContainer>
</DefaultLayout.Layout>
</Layout>
</Styled.Container>
</DefaultColorProvider>
<RowFlexGrow wrap={false}>
<Col span="250px">
<Sidebar sidebar={sidebar} />
</Col>
<FlexCol flex="auto">
<DefaultLayout.ContentPadding $isFederation={isFederation}>
<HeaderSecond inside={inside} isSearch={isSearch} />
{children}
</DefaultLayout.ContentPadding>
<Footer />
</FlexCol>
</RowFlexGrow>
)
}

View File

@@ -0,0 +1,95 @@
import React, { FC, ReactNode, useEffect, useCallback } from 'react'
import { Layout, theme as antdtheme, Alert } from 'antd'
import { useClusterList } from '@prorobotech/openapi-k8s-toolkit'
import { useSelector, useDispatch } from 'react-redux'
import { useParams, Outlet } from 'react-router-dom'
import type { RootState } from 'store/store'
import { setTheme } from 'store/theme/theme/theme'
import { setCluster } from 'store/cluster/cluster/cluster'
import { setClusterList } from 'store/clusterList/clusterList/clusterList'
import { DefaultLayout, DefaultColorProvider, Header } from 'components'
import { Styled } from './styled'
type TMainLayoutProps = {
children?: ReactNode | undefined
forcedTheme?: 'dark' | 'light'
}
export const MainLayout: FC<TMainLayoutProps> = ({ children, forcedTheme }) => {
const { clusterName } = useParams()
const { useToken } = antdtheme
const { token } = useToken()
const dispatch = useDispatch()
const theme = useSelector((state: RootState) => state.openapiTheme.theme)
const clusterListQuery = useClusterList({ refetchInterval: false })
useEffect(() => {
if (forcedTheme) {
return
}
const localStorageTheme = localStorage.getItem('theme')
if (localStorageTheme && (localStorageTheme === 'dark' || localStorageTheme === 'light')) {
dispatch(setTheme(localStorageTheme))
} else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
localStorage.setItem('theme', 'dark')
dispatch(setTheme('dark'))
} else {
localStorage.setItem('theme', 'light')
dispatch(setTheme('light'))
}
}, [dispatch, forcedTheme])
useEffect(() => {
if (forcedTheme) {
dispatch(setTheme(forcedTheme))
}
}, [dispatch, forcedTheme])
const handleStorage = useCallback(() => {
const localStorageTheme = localStorage.getItem('theme')
if (localStorageTheme && (localStorageTheme === 'dark' || localStorageTheme === 'light')) {
dispatch(setTheme(localStorageTheme))
}
}, [dispatch])
useEffect(() => {
window.addEventListener('storage', handleStorage)
return () => {
window.removeEventListener('storage', handleStorage)
}
}, [handleStorage])
useEffect(() => {
if (clusterListQuery.data) {
dispatch(setClusterList(clusterListQuery.data))
}
}, [clusterListQuery, dispatch])
if (clusterName) {
dispatch(setCluster(clusterName))
}
if (clusterName === undefined) {
dispatch(setCluster(''))
}
return (
<DefaultColorProvider $color={token.colorText}>
<Styled.Container $isDark={theme === 'dark'}>
<Layout>
<DefaultLayout.Layout $bgColor={token.colorBgLayout}>
<DefaultLayout.ContentContainer>
<Header />
{clusterListQuery.error && (
<Alert message={`Cluster List Error: ${clusterListQuery.error?.message} `} type="error" />
)}
<Outlet />
{children}
</DefaultLayout.ContentContainer>
</DefaultLayout.Layout>
</Layout>
</Styled.Container>
</DefaultColorProvider>
)
}

View File

@@ -0,0 +1 @@
export { MainLayout } from './MainLayout'