mirror of
https://github.com/outbackdingo/openapi-ui.git
synced 2026-01-27 18:19:50 +00:00
use namespace nav & navigation resource
This commit is contained in:
11
.env
11
.env
@@ -1,11 +1,22 @@
|
||||
VITE_CUSTOMIZATION_API_GROUP=incloud.io
|
||||
VITE_CUSTOMIZATION_API_VERSION=v1alpha
|
||||
|
||||
VITE_CUSTOMIZATION_NAVIGATION_RESOURCE_NAME=navigations
|
||||
VITE_CUSTOMIZATION_NAVIGATION_RESOURCE=navigation
|
||||
|
||||
VITE_USE_NAMESPACE_NAV=true
|
||||
|
||||
VITE_NAVIGATE_FROM_CLUSTERLIST=/openapi-ui/clusters/~recordValue~
|
||||
|
||||
VITE_PROJECTS_API_GROUP=incloud.io
|
||||
VITE_PROJECTS_VERSION=v1alpha
|
||||
VITE_PROJECTS_RESOURCE_NAME=projects
|
||||
|
||||
VITE_MARKETPLACE_RESOURCE_NAME=marketplacepanels
|
||||
VITE_MARKETPLACE_KIND=MarketplacePanel
|
||||
|
||||
VITE_INSTANCES_API_GROUP=incloud.io
|
||||
VITE_INSTANCES_VERSION=v1alpha1
|
||||
VITE_INSTANCES_RESOURCE_NAME=v1alpha1
|
||||
|
||||
VITE_BFF_URL=
|
||||
|
||||
@@ -1,12 +1,24 @@
|
||||
KUBE_API_URL=
|
||||
|
||||
CUSTOMIZATION_API_GROUP=
|
||||
CUSTOMIZATION_API_VERSION=
|
||||
|
||||
CUSTOMIZATION_NAVIGATION_RESOURCE_NAME=
|
||||
CUSTOMIZATION_NAVIGATION_RESOURCE=
|
||||
|
||||
USE_NAMESPACE_NAV=
|
||||
|
||||
NAVIGATE_FROM_CLUSTERLIST=
|
||||
|
||||
PROJECTS_API_GROUP=
|
||||
PROJECTS_VERSION=
|
||||
PROJECTS_RESOURCE_NAME=
|
||||
|
||||
MARKETPLACE_RESOURCE_NAME=
|
||||
MARKETPLACE_KIND=
|
||||
|
||||
INSTANCES_API_GROUP=
|
||||
INSTANCES_VERSION=
|
||||
INSTANCES_RESOURCE_NAME=
|
||||
|
||||
BFF_URL=
|
||||
|
||||
@@ -17,22 +17,41 @@ if (process.env.LOCAL === 'true') {
|
||||
}
|
||||
|
||||
const KUBE_API_URL = process.env.LOCAL === 'true' ? options?.KUBE_API_URL : process.env.KUBE_API_URL
|
||||
|
||||
const CUSTOMIZATION_API_GROUP =
|
||||
process.env.LOCAL === 'true' ? options?.CUSTOMIZATION_API_GROUP : process.env.CUSTOMIZATION_API_GROUP
|
||||
const CUSTOMIZATION_API_VERSION =
|
||||
process.env.LOCAL === 'true' ? options?.CUSTOMIZATION_API_VERSION : process.env.CUSTOMIZATION_API_VERSION
|
||||
|
||||
const CUSTOMIZATION_NAVIGATION_RESOURCE_NAME =
|
||||
process.env.LOCAL === 'true'
|
||||
? options?.CUSTOMIZATION_NAVIGATION_RESOURCE_NAME
|
||||
: process.env.CUSTOMIZATION_NAVIGATION_RESOURCE_NAME
|
||||
const CUSTOMIZATION_NAVIGATION_RESOURCE =
|
||||
process.env.LOCAL === 'true'
|
||||
? options?.CUSTOMIZATION_NAVIGATION_RESOURCE
|
||||
: process.env.CUSTOMIZATION_NAVIGATION_RESOURCE
|
||||
|
||||
const USE_NAMESPACE_NAV = process.env.LOCAL === 'true' ? options?.USE_NAMESPACE_NAV : process.env.USE_NAMESPACE_NAV
|
||||
|
||||
const NAVIGATE_FROM_CLUSTERLIST =
|
||||
process.env.LOCAL === 'true' ? options?.NAVIGATE_FROM_CLUSTERLIST : process.env.NAVIGATE_FROM_CLUSTERLIST
|
||||
|
||||
const PROJECTS_API_GROUP = process.env.LOCAL === 'true' ? options?.PROJECTS_API_GROUP : process.env.PROJECTS_API_GROUP
|
||||
const PROJECTS_VERSION = process.env.LOCAL === 'true' ? options?.PROJECTS_VERSION : process.env.PROJECTS_VERSION
|
||||
const PROJECTS_RESOURCE_NAME =
|
||||
process.env.LOCAL === 'true' ? options?.PROJECTS_RESOURCE_NAME : process.env.PROJECTS_RESOURCE_NAME
|
||||
|
||||
const MARKETPLACE_RESOURCE_NAME =
|
||||
process.env.LOCAL === 'true' ? options?.MARKETPLACE_RESOURCE_NAME : process.env.MARKETPLACE_RESOURCE_NAME
|
||||
const MARKETPLACE_KIND = process.env.LOCAL === 'true' ? options?.MARKETPLACE_KIND : process.env.MARKETPLACE_KIND
|
||||
|
||||
const INSTANCES_API_GROUP =
|
||||
process.env.LOCAL === 'true' ? options?.INSTANCES_API_GROUP : process.env.INSTANCES_API_GROUP
|
||||
const INSTANCES_VERSION = process.env.LOCAL === 'true' ? options?.INSTANCES_VERSION : process.env.INSTANCES_VERSION
|
||||
const INSTANCES_RESOURCE_NAME =
|
||||
process.env.LOCAL === 'true' ? options?.INSTANCES_RESOURCE_NAME : process.env.INSTANCES_RESOURCE_NAME
|
||||
|
||||
const BFF_URL = process.env.LOCAL === 'true' ? options?.BFF_URL : process.env.BFF_URL
|
||||
|
||||
const healthcheck = require('express-healthcheck')
|
||||
@@ -140,6 +159,12 @@ app.get(`${basePrefix ? basePrefix : ''}/env.js`, (_, res) => {
|
||||
${basePrefix ? ` BASEPREFIX: "${basePrefix}",` : ''}
|
||||
CUSTOMIZATION_API_GROUP: ${JSON.stringify(CUSTOMIZATION_API_GROUP) || '"check envs"'},
|
||||
CUSTOMIZATION_API_VERSION: ${JSON.stringify(CUSTOMIZATION_API_VERSION) || '"check envs"'},
|
||||
CUSTOMIZATION_NAVIGATION_RESOURCE_NAME: ${
|
||||
JSON.stringify(CUSTOMIZATION_NAVIGATION_RESOURCE_NAME) || '"check envs"'
|
||||
},
|
||||
CUSTOMIZATION_NAVIGATION_RESOURCE: ${JSON.stringify(CUSTOMIZATION_NAVIGATION_RESOURCE) || '"check envs"'},
|
||||
USE_NAMESPACE_NAV: ${!!USE_NAMESPACE_NAV},
|
||||
NAVIGATE_FROM_CLUSTERLIST: ${JSON.stringify(NAVIGATE_FROM_CLUSTERLIST) || '"check envs"'},
|
||||
PROJECTS_API_GROUP: ${JSON.stringify(PROJECTS_API_GROUP) || '"check envs"'},
|
||||
PROJECTS_VERSION: ${JSON.stringify(PROJECTS_VERSION) || '"check envs"'},
|
||||
PROJECTS_RESOURCE_NAME: ${JSON.stringify(PROJECTS_RESOURCE_NAME) || '"check envs"'},
|
||||
|
||||
@@ -2,7 +2,8 @@ import React, { FC } from 'react'
|
||||
import { theme } from 'antd'
|
||||
import { useParams } from 'react-router-dom'
|
||||
import { HEAD_SECOND_ROW } from 'constants/blocksSizes'
|
||||
import { Selector, SelectorInside } from './organisms'
|
||||
import { BASE_USE_NAMESPACE_NAV } from 'constants/customizationApiGroupAndVersion'
|
||||
import { Selector, SelectorInside, SelectorNamespace } from './organisms'
|
||||
import { Styled } from './styled'
|
||||
|
||||
type THeaderProps = {
|
||||
@@ -20,15 +21,15 @@ export const HeaderSecond: FC<THeaderProps> = ({ inside }) => {
|
||||
return (
|
||||
<Styled.BackgroundContainer $bgColor={token.colorFillSecondary} $borderRadius={token.borderRadius}>
|
||||
<Styled.PaddingContainer $height={HEAD_SECOND_ROW}>
|
||||
{inside ? (
|
||||
<SelectorInside clusterName={clusterName} namespace={namespace} />
|
||||
) : (
|
||||
{inside && !BASE_USE_NAMESPACE_NAV && <SelectorInside clusterName={clusterName} namespace={namespace} />}
|
||||
{!inside && !BASE_USE_NAMESPACE_NAV && (
|
||||
<Selector
|
||||
clusterName={clusterName}
|
||||
projectName={projectName || possibleProject}
|
||||
instanceName={instanceName || possibleInstance}
|
||||
/>
|
||||
)}
|
||||
{BASE_USE_NAMESPACE_NAV && <SelectorNamespace clusterName={clusterName} namespace={namespace} />}
|
||||
</Styled.PaddingContainer>
|
||||
</Styled.BackgroundContainer>
|
||||
)
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import React, { FC, useState } from 'react'
|
||||
import { Flex } from 'antd'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import { useSelector } from 'react-redux'
|
||||
import { RootState } from 'store/store'
|
||||
import { useDirectUnknownResource } from '@prorobotech/openapi-k8s-toolkit'
|
||||
import { useNavSelector } from 'hooks/useNavSelector'
|
||||
import { useMountEffect } from 'hooks/useMountEffect'
|
||||
import { EntrySelect } from 'components/atoms'
|
||||
import {
|
||||
BASE_INSTANCES_API_GROUP,
|
||||
BASE_INSTANCES_VERSION,
|
||||
BASE_INSTANCES_RESOURCE_NAME,
|
||||
BASE_API_GROUP,
|
||||
BASE_API_VERSION,
|
||||
BASE_CUSTOMIZATION_NAVIGATION_RESOURCE_NAME,
|
||||
BASE_CUSTOMIZATION_NAVIGATION_RESOURCE,
|
||||
} from 'constants/customizationApiGroupAndVersion'
|
||||
|
||||
type TSelectorProps = {
|
||||
@@ -20,7 +20,6 @@ type TSelectorProps = {
|
||||
|
||||
export const Selector: FC<TSelectorProps> = ({ clusterName, projectName, instanceName }) => {
|
||||
const navigate = useNavigate()
|
||||
const baseprefix = useSelector((state: RootState) => state.baseprefix.baseprefix)
|
||||
|
||||
const [selectedClusterName, setSelectedClusterName] = useState(clusterName)
|
||||
const [selectedProjectName, setSelectedProjectName] = useState(projectName)
|
||||
@@ -32,6 +31,15 @@ export const Selector: FC<TSelectorProps> = ({ clusterName, projectName, instanc
|
||||
projectName,
|
||||
)
|
||||
|
||||
const { data: navigationData } = useDirectUnknownResource<{
|
||||
spec: { projects: { clear: string; change: string }; instances: { clear: string; change: string } }
|
||||
}>({
|
||||
uri: `/api/clusters/${clusterName}/k8s/apis/${BASE_API_GROUP}/${BASE_API_VERSION}/${BASE_CUSTOMIZATION_NAVIGATION_RESOURCE_NAME}/${BASE_CUSTOMIZATION_NAVIGATION_RESOURCE}`,
|
||||
refetchInterval: false,
|
||||
queryKey: ['navigation', clusterName || 'no-cluster'],
|
||||
isEnabled: clusterName !== undefined,
|
||||
})
|
||||
|
||||
// const handleClusterChange = (value: string) => {
|
||||
// setSelectedClusterName(value)
|
||||
// navigate(`${baseprefix}/clusters/${value}`)
|
||||
@@ -40,20 +48,34 @@ export const Selector: FC<TSelectorProps> = ({ clusterName, projectName, instanc
|
||||
const handleProjectChange = (value?: string) => {
|
||||
if (value) {
|
||||
setSelectedProjectName(value)
|
||||
navigate(`${baseprefix}/clusters/${selectedClusterName}/projects/${value}`)
|
||||
const changeUrl =
|
||||
navigationData?.spec.projects.change
|
||||
.replace('{selectedCluster}', selectedClusterName || 'no-cluster')
|
||||
.replace('{value}', value) || 'no navigation data'
|
||||
navigate(changeUrl)
|
||||
} else {
|
||||
navigate(`${baseprefix}/clusters/${selectedClusterName}/`)
|
||||
const clearUrl =
|
||||
navigationData?.spec.projects.clear.replace('{selectedCluster}', selectedClusterName || 'no-cluster') ||
|
||||
'no navigation data'
|
||||
navigate(clearUrl)
|
||||
}
|
||||
}
|
||||
|
||||
const handleInstanceChange = (value?: string) => {
|
||||
if (value) {
|
||||
setSelectedInstanceName(value)
|
||||
navigate(`${baseprefix}/${selectedClusterName}/${value}/${selectedProjectName}/api-table/apps/v1/deployments`)
|
||||
const changeUrl =
|
||||
navigationData?.spec.instances.change
|
||||
.replace('{selectedCluster}', selectedClusterName || 'no-cluster')
|
||||
.replace('{selectedProject}', selectedProjectName || 'no-project')
|
||||
.replace('{value}', value) || 'no navigation data'
|
||||
navigate(changeUrl)
|
||||
} else {
|
||||
navigate(
|
||||
`${baseprefix}/${selectedClusterName}/${selectedProjectName}/api-table/${BASE_INSTANCES_API_GROUP}/${BASE_INSTANCES_VERSION}/${BASE_INSTANCES_RESOURCE_NAME}`,
|
||||
)
|
||||
const clearUrl =
|
||||
navigationData?.spec.instances.clear
|
||||
.replace('{selectedCluster}', selectedClusterName || 'no-cluster')
|
||||
.replace('{selectedProject}', selectedProjectName || 'no-project') || 'no navigation data'
|
||||
navigate(clearUrl)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
import React, { FC, useState } from 'react'
|
||||
import { Flex } from 'antd'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import { useDirectUnknownResource } from '@prorobotech/openapi-k8s-toolkit'
|
||||
import { useNavSelectorInside } from 'hooks/useNavSelectorInside'
|
||||
import { useMountEffect } from 'hooks/useMountEffect'
|
||||
import { EntrySelect } from 'components/atoms'
|
||||
import {
|
||||
BASE_API_GROUP,
|
||||
BASE_API_VERSION,
|
||||
BASE_CUSTOMIZATION_NAVIGATION_RESOURCE_NAME,
|
||||
BASE_CUSTOMIZATION_NAVIGATION_RESOURCE,
|
||||
} from 'constants/customizationApiGroupAndVersion'
|
||||
|
||||
type TSelectorNamespaceProps = {
|
||||
clusterName?: string
|
||||
namespace?: string
|
||||
}
|
||||
|
||||
export const SelectorNamespace: FC<TSelectorNamespaceProps> = ({ clusterName, namespace }) => {
|
||||
const navigate = useNavigate()
|
||||
|
||||
const [selectedClusterName, setSelectedClusterName] = useState(clusterName)
|
||||
const [selectedNamespace, setSelectedNamespace] = useState(namespace)
|
||||
|
||||
const { namespacesInSidebar } = useNavSelectorInside(selectedClusterName)
|
||||
|
||||
const { data: navigationData } = useDirectUnknownResource<{
|
||||
spec: { namespaces: { clear: string; change: string } }
|
||||
}>({
|
||||
uri: `/api/clusters/${clusterName}/k8s/apis/${BASE_API_GROUP}/${BASE_API_VERSION}/${BASE_CUSTOMIZATION_NAVIGATION_RESOURCE_NAME}/${BASE_CUSTOMIZATION_NAVIGATION_RESOURCE}`,
|
||||
refetchInterval: false,
|
||||
queryKey: ['navigation', clusterName || 'no-cluster'],
|
||||
isEnabled: clusterName !== undefined,
|
||||
})
|
||||
|
||||
const handleNamepsaceChange = (value?: string) => {
|
||||
if (value) {
|
||||
setSelectedNamespace(value)
|
||||
const changeUrl =
|
||||
navigationData?.spec.namespaces.change
|
||||
.replace('{selectedCluster}', selectedClusterName || 'no-cluster')
|
||||
.replace('{value}', value) || 'no navigation data'
|
||||
navigate(changeUrl)
|
||||
} else {
|
||||
const clearUrl =
|
||||
navigationData?.spec.namespaces.clear.replace('{selectedCluster}', selectedClusterName || 'no-cluster') ||
|
||||
'no navigation data'
|
||||
navigate(clearUrl)
|
||||
}
|
||||
}
|
||||
|
||||
useMountEffect(() => {
|
||||
setSelectedClusterName(clusterName)
|
||||
setSelectedNamespace(namespace)
|
||||
}, [namespace, clusterName])
|
||||
|
||||
return (
|
||||
<Flex gap={18} justify="start">
|
||||
<EntrySelect
|
||||
placeholder="Namespace"
|
||||
options={namespacesInSidebar}
|
||||
value={selectedNamespace}
|
||||
onChange={handleNamepsaceChange}
|
||||
disabled={selectedClusterName === undefined || namespacesInSidebar.length === 0}
|
||||
/>
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export * from './SelectorNamespace'
|
||||
@@ -1,2 +1,3 @@
|
||||
export * from './Selector'
|
||||
export * from './SelectorInside'
|
||||
export * from './SelectorNamespace'
|
||||
|
||||
@@ -3,6 +3,7 @@ import { EnrichedTable } from '@prorobotech/openapi-k8s-toolkit'
|
||||
import { useSelector } from 'react-redux'
|
||||
import { RootState } from 'store/store'
|
||||
import { TABLE_PROPS } from 'constants/tableProps'
|
||||
import { BASE_NAVIGATE_FROM_CLUSTERLIST } from 'constants/customizationApiGroupAndVersion'
|
||||
|
||||
export const ListClusters: FC = () => {
|
||||
const theme = useSelector((state: RootState) => state.openapiTheme.theme)
|
||||
@@ -40,7 +41,7 @@ export const ListClusters: FC = () => {
|
||||
key: 'description',
|
||||
},
|
||||
]}
|
||||
pathToNavigate={`${baseprefix}/clusters/~recordValue~`}
|
||||
pathToNavigate={BASE_NAVIGATE_FROM_CLUSTERLIST}
|
||||
recordKeysForNavigation={['name']}
|
||||
withoutControls
|
||||
tableProps={TABLE_PROPS}
|
||||
|
||||
@@ -1,13 +1,26 @@
|
||||
/* eslint-disable no-underscore-dangle */
|
||||
export const BASE_API_GROUP = window._env_.CUSTOMIZATION_API_GROUP || import.meta.env.VITE_CUSTOMIZATION_API_GROUP
|
||||
export const BASE_API_VERSION = window._env_.CUSTOMIZATION_API_VERSION || import.meta.env.VITE_CUSTOMIZATION_API_VERSION
|
||||
|
||||
export const BASE_CUSTOMIZATION_NAVIGATION_RESOURCE_NAME =
|
||||
window._env_.CUSTOMIZATION_NAVIGATION_RESOURCE_NAME || import.meta.env.VITE_CUSTOMIZATION_NAVIGATION_RESOURCE_NAME
|
||||
export const BASE_CUSTOMIZATION_NAVIGATION_RESOURCE =
|
||||
window._env_.CUSTOMIZATION_NAVIGATION_RESOURCE || import.meta.env.VITE_CUSTOMIZATION_NAVIGATION_RESOURCE
|
||||
|
||||
export const BASE_USE_NAMESPACE_NAV = window._env_.USE_NAMESPACE_NAV || import.meta.env.VITE_USE_NAMESPACE_NAV
|
||||
|
||||
export const BASE_NAVIGATE_FROM_CLUSTERLIST =
|
||||
window._env_.NAVIGATE_FROM_CLUSTERLIST || import.meta.env.VITE_NAVIGATE_FROM_CLUSTERLIST
|
||||
|
||||
export const BASE_PROJECTS_API_GROUP = window._env_.PROJECTS_API_GROUP || import.meta.env.VITE_PROJECTS_API_GROUP
|
||||
export const BASE_PROJECTS_VERSION = window._env_.PROJECTS_VERSION || import.meta.env.VITE_PROJECTS_VERSION
|
||||
export const BASE_PROJECTS_RESOURCE_NAME =
|
||||
window._env_.PROJECTS_RESOURCE_NAME || import.meta.env.VITE_PROJECTS_RESOURCE_NAME
|
||||
|
||||
export const BASE_MARKETPLACE_RESOURCE_NAME =
|
||||
window._env_.MARKETPLACE_RESOURCE_NAME || import.meta.env.VITE_MARKETPLACE_RESOURCE_NAME
|
||||
export const BASE_MARKETPLACE_KIND = window._env_.MARKETPLACE_KIND || import.meta.env.VITE_MARKETPLACE_KIND
|
||||
|
||||
export const BASE_INSTANCES_API_GROUP = window._env_.INSTANCES_API_GROUP || import.meta.env.VITE_INSTANCES_API_GROUP
|
||||
export const BASE_INSTANCES_VERSION = window._env_.INSTANCES_VERSION || import.meta.env.VITE_INSTANCES_VERSION
|
||||
export const BASE_INSTANCES_RESOURCE_NAME =
|
||||
|
||||
Reference in New Issue
Block a user