Merge pull request #147 from PRO-Robotech/release/1.0.2

Release/1.0.2
This commit is contained in:
typescreep
2025-10-20 17:32:01 +03:00
committed by GitHub
35 changed files with 428 additions and 664 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.129",
"@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.129",
"resolved": "https://registry.npmjs.org/@prorobotech/openapi-k8s-toolkit/-/openapi-k8s-toolkit-0.0.1-alpha.129.tgz",
"integrity": "sha512-V5hrvOfbx7ZXCHu3sDYfvVKJPEbiymMk7Zb/1cQNfkyzjqvBB2JVRVEGVR9c6uyuWOHchBAMkiw2S5c5pm+yfQ==",
"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.129",
"@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

@@ -10,11 +10,12 @@ import {
usePermissions,
DeleteModal,
DeleteModalMany,
checkIfBuiltInInstanceNamespaceScoped,
checkIfApiInstanceNamespaceScoped,
// checkIfBuiltInInstanceNamespaceScoped,
// checkIfApiInstanceNamespaceScoped,
useBuiltinResources,
useApiResources,
Spacer,
getLinkToForm,
} from '@prorobotech/openapi-k8s-toolkit'
import { FlexGrow, PaddingContainer } from 'components'
import { TABLE_PROPS } from 'constants/tableProps'
@@ -27,13 +28,13 @@ import {
TABLE_ADD_BUTTON_HEIGHT,
} from 'constants/blocksSizes'
import { OverflowContainer } from './atoms'
import { getDataItems, getBackLinkToTable, getLinkToForm } from './utils'
import { getDataItems } from './utils'
type TTableApiBuiltinProps = {
namespace?: string
resourceType: 'builtin' | 'api'
apiGroup?: string // api
apiVersion?: string // api
apiVersion: string // api
typeName: string
labels?: string[]
fields?: string[]
@@ -71,7 +72,8 @@ export const TableApiBuiltin: FC<TTableApiBuiltinProps> = ({
)
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([])
const [selectedRowsData, setSelectedRowsData] = useState<{ name: string; endpoint: string }[]>([])
const [isNamespaced, setIsNamespaced] = useState<boolean>()
// const [isNamespaced, setIsNamespaced] = useState<boolean>()
// const [isNamespacedLoading, setIsNamespacedLoading] = useState<boolean>()
const [height, setHeight] = useState(0)
@@ -97,58 +99,49 @@ export const TableApiBuiltin: FC<TTableApiBuiltinProps> = ({
}
}, [])
useEffect(() => {
if (resourceType === 'builtin') {
checkIfBuiltInInstanceNamespaceScoped({
typeName,
clusterName: cluster,
}).then(({ isNamespaceScoped }) => {
if (isNamespaceScoped) {
setIsNamespaced(isNamespaceScoped)
}
})
}
if (resourceType === 'api' && apiGroup && apiVersion) {
checkIfApiInstanceNamespaceScoped({
apiGroup,
apiVersion,
typeName,
clusterName: cluster,
}).then(({ isNamespaceScoped }) => {
if (isNamespaceScoped) {
setIsNamespaced(true)
}
})
}
}, [resourceType, cluster, typeName, apiGroup, apiVersion])
// useEffect(() => {
// setIsNamespacedLoading(true)
// if (resourceType === 'builtin') {
// checkIfBuiltInInstanceNamespaceScoped({
// typeName,
// clusterName: cluster,
// })
// .then(({ isNamespaceScoped }) => {
// if (isNamespaceScoped) {
// setIsNamespaced(isNamespaceScoped)
// } else {
// setIsNamespaced(false)
// }
// })
// .finally(() => setIsNamespacedLoading(false))
// }
// if (resourceType === 'api' && apiGroup && apiVersion) {
// checkIfApiInstanceNamespaceScoped({
// apiGroup,
// apiVersion,
// typeName,
// clusterName: cluster,
// })
// .then(({ isNamespaceScoped }) => {
// if (isNamespaceScoped) {
// setIsNamespaced(true)
// } else {
// setIsNamespaced(false)
// }
// })
// .finally(() => setIsNamespacedLoading(false))
// }
// }, [resourceType, cluster, typeName, apiGroup, apiVersion])
const createPermission = usePermissions({
apiGroup: apiGroup || '',
typeName,
namespace: '',
group: apiGroup || undefined,
resource: typeName,
namespace: params.namespace,
clusterName: cluster,
verb: 'create',
refetchInterval: false,
})
const updatePermission = usePermissions({
apiGroup: apiGroup || '',
typeName,
namespace: '',
clusterName: cluster,
verb: 'update',
refetchInterval: false,
})
const deletePermission = usePermissions({
apiGroup: apiGroup || '',
typeName,
namespace: '',
clusterName: cluster,
verb: 'delete',
refetchInterval: false,
})
const {
isPending: isPendingBuiltin,
error: errorBuiltin,
@@ -233,35 +226,26 @@ export const TableApiBuiltin: FC<TTableApiBuiltinProps> = ({
...replaceValuesPartsOfUrls,
}}
cluster={cluster}
namespace={namespace}
theme={theme}
baseprefix={inside ? `${baseprefix}/inside` : baseprefix}
dataItems={getDataItems({ resourceType, dataBuiltin, dataApi })}
k8sResource={{
resource: typeName,
apiGroup,
apiVersion,
}}
// isNamespaced={isNamespaced}
// isNamespacedLoading={isNamespacedLoading}
dataForControls={{
cluster,
syntheticProject: params.syntheticProject,
pathPrefix: resourceType === 'builtin' ? 'forms/builtin' : 'forms/apis',
typeName,
apiVersion: resourceType === 'builtin' ? 'v1' : `${apiGroup}/${apiVersion}`,
backlink: getBackLinkToTable({
resourceType,
cluster,
baseprefix,
namespace,
syntheticProject: params.syntheticProject,
apiGroup,
apiVersion,
typeName,
inside,
fullPath,
searchMount,
}),
deletePathPrefix:
resourceType === 'builtin' ? `/api/clusters/${cluster}/k8s/api` : `/api/clusters/${cluster}/k8s/apis`,
resource: typeName,
apiGroup,
apiVersion,
}}
dataForControlsInternal={{
onDeleteHandle,
permissions: {
canUpdate: isNamespaced ? true : updatePermission.data?.status.allowed,
canDelete: isNamespaced ? true : deletePermission.data?.status.allowed,
},
}}
selectData={{
selectedRowKeys,
@@ -271,7 +255,6 @@ export const TableApiBuiltin: FC<TTableApiBuiltinProps> = ({
},
}}
tableProps={{ ...TABLE_PROPS, disablePagination: !searchMount }}
namespaceScopedWithoutNamespace={isNamespaced && !namespace}
// maxHeight={height - 65}
/>
)}
@@ -297,7 +280,6 @@ export const TableApiBuiltin: FC<TTableApiBuiltinProps> = ({
type="primary"
onClick={() => {
const url = getLinkToForm({
resourceType,
cluster,
baseprefix,
namespace,
@@ -311,8 +293,10 @@ export const TableApiBuiltin: FC<TTableApiBuiltinProps> = ({
})
navigate(url)
}}
loading={isNamespaced ? false : createPermission.isPending}
disabled={isNamespaced ? false : !createPermission.data?.status.allowed}
// loading={isNamespaced ? false : createPermission.isPending}
// disabled={isNamespaced ? false : !createPermission.data?.status.allowed}
loading={createPermission.isPending}
disabled={!createPermission.data?.status.allowed}
>
<PlusOutlined />
Add {kindName}

View File

@@ -11,178 +11,3 @@ export const getDataItems = ({
}): TJSON[] => {
return resourceType === 'builtin' ? dataBuiltin?.items || [] : dataApi?.items || []
}
export const getBackLinkToBuiltinTable = ({
cluster,
baseprefix,
namespace,
syntheticProject,
typeName,
inside,
fullPath,
searchMount,
}: {
cluster: string
baseprefix?: string
namespace?: string
syntheticProject?: string
typeName: string
inside?: boolean
fullPath: string
searchMount?: boolean
}): string => {
if (searchMount) {
return encodeURIComponent(fullPath)
}
const root = `${baseprefix}${inside ? '/inside' : ''}/${cluster}`
const mainRoute = `${root}${namespace ? `/${namespace}` : ''}${syntheticProject ? `/${syntheticProject}` : ''}`
return `${mainRoute}/builtin-table/${typeName}`
}
export const getBackLinkToApiTable = ({
cluster,
baseprefix,
namespace,
syntheticProject,
apiGroup,
apiVersion,
typeName,
inside,
fullPath,
searchMount,
}: {
cluster: string
baseprefix?: string
namespace?: string
syntheticProject?: string
apiGroup?: string // api
apiVersion?: string // api
typeName: string
inside?: boolean
fullPath: string
searchMount?: boolean
}): string => {
if (searchMount) {
return encodeURIComponent(fullPath)
}
const root = `${baseprefix}${inside ? '/inside' : ''}/${cluster}`
const mainRoute = `${root}${namespace ? `/${namespace}` : ''}${syntheticProject ? `/${syntheticProject}` : ''}`
return `${mainRoute}/api-table/${apiGroup}/${apiVersion}/${typeName}`
}
export const getBackLinkToTable = ({
resourceType,
...rest
}: {
resourceType: 'builtin' | 'api'
cluster: string
baseprefix?: string
namespace?: string
syntheticProject?: string
apiGroup?: string // api
apiVersion?: string // api
typeName: string
inside?: boolean
fullPath: string
searchMount?: boolean
}): string => {
return resourceType === 'builtin' ? getBackLinkToBuiltinTable({ ...rest }) : getBackLinkToApiTable({ ...rest })
}
export const getLinkToBuiltinForm = ({
cluster,
baseprefix,
namespace,
syntheticProject,
typeName,
inside,
fullPath,
searchMount,
}: {
cluster: string
baseprefix?: string
namespace?: string
syntheticProject?: string
typeName: string
inside?: boolean
fullPath: string
searchMount?: boolean
}): string => {
const root = `${baseprefix}${inside ? '/inside' : ''}/${cluster}`
const mainRoute = `${root}${namespace ? `/${namespace}` : ''}${syntheticProject ? `/${syntheticProject}` : ''}`
const backlink = getBackLinkToBuiltinTable({
cluster,
baseprefix,
namespace,
syntheticProject,
typeName,
inside,
fullPath,
searchMount,
})
return `${mainRoute}/forms/builtin/v1/${typeName}?backlink=${backlink}`
}
export const getLinkToApiForm = ({
cluster,
baseprefix,
namespace,
syntheticProject,
apiGroup,
apiVersion,
typeName,
inside,
fullPath,
searchMount,
}: {
cluster: string
baseprefix?: string
namespace?: string
syntheticProject?: string
apiGroup?: string // api
apiVersion?: string // api
typeName: string
inside?: boolean
fullPath: string
searchMount?: boolean
}): string => {
const root = `${baseprefix}${inside ? '/inside' : ''}/${cluster}`
const mainRoute = `${root}${namespace ? `/${namespace}` : ''}${syntheticProject ? `/${syntheticProject}` : ''}`
const backlink = getBackLinkToApiTable({
cluster,
baseprefix,
namespace,
syntheticProject,
apiGroup,
apiVersion,
typeName,
inside,
fullPath,
searchMount,
})
return `${mainRoute}/forms/apis/${apiGroup}/${apiVersion}/${typeName}?backlink=${backlink}`
}
export const getLinkToForm = ({
resourceType,
...rest
}: {
resourceType: 'builtin' | 'api'
cluster: string
baseprefix?: string
namespace?: string
syntheticProject?: string
apiGroup?: string // api
apiVersion?: string // api
typeName: string
inside?: boolean
fullPath: string
searchMount?: boolean
}): string => {
return resourceType === 'builtin' ? getLinkToBuiltinForm({ ...rest }) : getLinkToApiForm({ ...rest })
}

View File

@@ -50,8 +50,8 @@ export const TableCrdInfo: FC<TTableCrdInfoProps> = ({
}, [cluster, data, isPending, error, apiGroup, apiVersion])
const createPermission = usePermissions({
apiGroup,
typeName: data ? data.spec.names.singular : '',
group: apiGroup,
resource: data ? data.spec.names.singular : '',
namespace: '',
clusterName: cluster,
verb: 'create',
@@ -59,8 +59,8 @@ export const TableCrdInfo: FC<TTableCrdInfoProps> = ({
})
const updatePermission = usePermissions({
apiGroup,
typeName: data ? data.spec.names.singular : '',
group: apiGroup,
resource: data ? data.spec.names.singular : '',
namespace: '',
clusterName: cluster,
verb: 'update',
@@ -68,8 +68,8 @@ export const TableCrdInfo: FC<TTableCrdInfoProps> = ({
})
const deletePermission = usePermissions({
apiGroup,
typeName: data ? data.spec.names.singular : '',
group: apiGroup,
resource: data ? data.spec.names.singular : '',
namespace: '',
clusterName: cluster,
verb: 'delete',

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import React, { FC, useState, useEffect } from 'react'
import { useLocation, useNavigate, useParams } from 'react-router-dom'
import { Spin, Alert, Button, Flex } from 'antd'
@@ -130,133 +131,135 @@ export const ResourceInfo: FC<TResourceInfoProps> = ({
return acc
}, {})
return (
<>
{isPending && <Spin />}
{error && <Alert message={`An error has occurred: ${error?.message} `} type="error" />}
<OverflowMaxHeightContainer $maxHeight={height}>
{!error && data && (
<EnrichedTableProvider
key={`/${apiGroup}/${apiVersion}/${crdPluralName}`}
customizationId={`${customizationIdPrefix}/${apiGroup}/${apiVersion}/${crdPluralName}`}
tableMappingsReplaceValues={{
clusterName: params.clusterName,
projectName: params.projectName,
instanceName: params.instanceName,
namespace: params.namespace,
syntheticProject: params.syntheticProject,
entryType: params.entryType,
apiGroup: params.apiGroup,
apiVersion: params.apiVersion,
typeName: params.typeName,
entryName: params.entryName,
apiExtensionVersion: params.apiExtensionVersion,
crdName: params.crdName,
...replaceValuesPartsOfUrls,
}}
forceDefaultAdditionalPrinterColumns={crdAdditionalPrinterColumns}
cluster={cluster}
theme={theme}
baseprefix={inside ? `${baseprefix}/inside` : baseprefix}
dataItems={data.items}
resourceSchema={resourceSchema}
dataForControls={{
cluster,
syntheticProject: params.syntheticProject,
pathPrefix: 'forms/crds',
typeName: crdPluralName,
apiVersion: `${apiGroup}/${apiVersion}`,
backlink: `${baseprefix}${inside ? '/inside' : ''}/${cluster}${namespace ? `/${namespace}` : ''}${
params.syntheticProject ? `/${params.syntheticProject}` : ''
}/crd-table/${apiGroup}/${apiVersion}/${apiExtensionVersion}/${crdName}`,
deletePathPrefix: `/api/clusters/${clusterName}/k8s/apis`,
onDeleteHandle,
permissions: {
canUpdate: permissions.canUpdate,
canDelete: permissions.canDelete,
},
}}
selectData={{
selectedRowKeys,
onChange: (selectedRowKeys: React.Key[], selectedRowsData: { name: string; endpoint: string }[]) => {
setSelectedRowKeys(selectedRowKeys)
setSelectedRowsData(selectedRowsData)
},
}}
tableProps={{ ...TABLE_PROPS, disablePagination: true }}
// maxHeight={height - 65}
/>
)}
{/* {selectedRowKeys.length > 0 && (
<MarginTopContainer $top={-40}>
<Flex gap={16}>
<Button type="primary" onClick={clearSelected}>
<ClearOutlined />
Clear
</Button>
<Button type="primary" onClick={() => setIsDeleteModalManyOpen(selectedRowsData)}>
<MinusOutlined />
Delete
</Button>
</Flex>
</MarginTopContainer>
)} */}
</OverflowMaxHeightContainer>
<FlexGrow />
<PaddingContainer $padding="4px">
<Flex justify="space-between">
<Button
type="primary"
onClick={() =>
navigate(
`${baseprefix}${inside ? '/inside' : ''}/${cluster}${namespace ? `/${namespace}` : ''}${
params.syntheticProject ? `/${params.syntheticProject}` : ''
}/forms/crds/${apiGroup}/${apiVersion}/${crdPluralName}?backlink=${baseprefix}${
inside ? '/inside' : ''
}/${cluster}${namespace ? `/${namespace}` : ''}${
params.syntheticProject ? `/${params.syntheticProject}` : ''
}/crd-table/${apiGroup}/${apiVersion}/${apiExtensionVersion}/${crdName}`,
)
}
loading={permissions.canCreate === undefined}
disabled={permissions.canCreate === false}
>
<PlusOutlined />
Add
</Button>
{selectedRowKeys.length > 0 && (
<Flex gap={16}>
<Button type="primary" onClick={clearSelected}>
<ClearOutlined />
Clear
</Button>
<Button type="primary" onClick={() => setIsDeleteModalManyOpen(selectedRowsData)}>
<MinusOutlined />
Delete
</Button>
</Flex>
)}
</Flex>
</PaddingContainer>
{isDeleteModalOpen && (
<DeleteModal
name={isDeleteModalOpen.name}
onClose={() => {
setIsDeleteModalOpen(false)
clearSelected()
}}
endpoint={isDeleteModalOpen.endpoint}
/>
)}
{isDeleteModalManyOpen !== false && (
<DeleteModalMany
data={isDeleteModalManyOpen}
onClose={() => {
setIsDeleteModalManyOpen(false)
clearSelected()
}}
/>
)}
</>
)
return <div>Most likely deprecated</div>
// return (
// <>
// {isPending && <Spin />}
// {error && <Alert message={`An error has occurred: ${error?.message} `} type="error" />}
// <OverflowMaxHeightContainer $maxHeight={height}>
// {!error && data && (
// <EnrichedTableProvider
// key={`/${apiGroup}/${apiVersion}/${crdPluralName}`}
// customizationId={`${customizationIdPrefix}/${apiGroup}/${apiVersion}/${crdPluralName}`}
// tableMappingsReplaceValues={{
// clusterName: params.clusterName,
// projectName: params.projectName,
// instanceName: params.instanceName,
// namespace: params.namespace,
// syntheticProject: params.syntheticProject,
// entryType: params.entryType,
// apiGroup: params.apiGroup,
// apiVersion: params.apiVersion,
// typeName: params.typeName,
// entryName: params.entryName,
// apiExtensionVersion: params.apiExtensionVersion,
// crdName: params.crdName,
// ...replaceValuesPartsOfUrls,
// }}
// forceDefaultAdditionalPrinterColumns={crdAdditionalPrinterColumns}
// cluster={cluster}
// theme={theme}
// baseprefix={inside ? `${baseprefix}/inside` : baseprefix}
// dataItems={data.items}
// resourceSchema={resourceSchema}
// dataForControls={{
// cluster,
// syntheticProject: params.syntheticProject,
// pathPrefix: 'forms/crds',
// typeName: crdPluralName,
// apiVersion: `${apiGroup}/${apiVersion}`,
// backlink: `${baseprefix}${inside ? '/inside' : ''}/${cluster}${namespace ? `/${namespace}` : ''}${
// params.syntheticProject ? `/${params.syntheticProject}` : ''
// }/crd-table/${apiGroup}/${apiVersion}/${apiExtensionVersion}/${crdName}`,
// deletePathPrefix: `/api/clusters/${clusterName}/k8s/apis`,
// onDeleteHandle,
// permissions: {
// canUpdate: permissions.canUpdate,
// canDelete: permissions.canDelete,
// },
// }}
// selectData={{
// selectedRowKeys,
// onChange: (selectedRowKeys: React.Key[], selectedRowsData: { name: string; endpoint: string }[]) => {
// setSelectedRowKeys(selectedRowKeys)
// setSelectedRowsData(selectedRowsData)
// },
// }}
// tableProps={{ ...TABLE_PROPS, disablePagination: true }}
// // maxHeight={height - 65}
// />
// )}
// {/* {selectedRowKeys.length > 0 && (
// <MarginTopContainer $top={-40}>
// <Flex gap={16}>
// <Button type="primary" onClick={clearSelected}>
// <ClearOutlined />
// Clear
// </Button>
// <Button type="primary" onClick={() => setIsDeleteModalManyOpen(selectedRowsData)}>
// <MinusOutlined />
// Delete
// </Button>
// </Flex>
// </MarginTopContainer>
// )} */}
// </OverflowMaxHeightContainer>
// <FlexGrow />
// <PaddingContainer $padding="4px">
// <Flex justify="space-between">
// <Button
// type="primary"
// onClick={() =>
// navigate(
// `${baseprefix}${inside ? '/inside' : ''}/${cluster}${namespace ? `/${namespace}` : ''}${
// params.syntheticProject ? `/${params.syntheticProject}` : ''
// }/forms/crds/${apiGroup}/${apiVersion}/${crdPluralName}?backlink=${baseprefix}${
// inside ? '/inside' : ''
// }/${cluster}${namespace ? `/${namespace}` : ''}${
// params.syntheticProject ? `/${params.syntheticProject}` : ''
// }/crd-table/${apiGroup}/${apiVersion}/${apiExtensionVersion}/${crdName}`,
// )
// }
// loading={permissions.canCreate === undefined}
// disabled={permissions.canCreate === false}
// >
// <PlusOutlined />
// Add
// </Button>
// {selectedRowKeys.length > 0 && (
// <Flex gap={16}>
// <Button type="primary" onClick={clearSelected}>
// <ClearOutlined />
// Clear
// </Button>
// <Button type="primary" onClick={() => setIsDeleteModalManyOpen(selectedRowsData)}>
// <MinusOutlined />
// Delete
// </Button>
// </Flex>
// )}
// </Flex>
// </PaddingContainer>
// {isDeleteModalOpen && (
// <DeleteModal
// name={isDeleteModalOpen.name}
// onClose={() => {
// setIsDeleteModalOpen(false)
// clearSelected()
// }}
// endpoint={isDeleteModalOpen.endpoint}
// />
// )}
// {isDeleteModalManyOpen !== false && (
// <DeleteModalMany
// data={isDeleteModalManyOpen}
// onClose={() => {
// setIsDeleteModalManyOpen(false)
// clearSelected()
// }}
// />
// )}
// </>
// )
}

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

@@ -94,7 +94,7 @@ export const SearchEntry: FC<TSearchEntryProps> = ({ resource, labels, fields, f
resourceType={apiGroup.length > 0 ? 'api' : 'builtin'}
namespace={isNamespaceResource ? namespace : undefined}
apiGroup={apiGroup.length > 0 ? apiGroup : undefined}
apiVersion={apiGroup.length > 0 ? apiVersion : undefined}
apiVersion={apiVersion}
typeName={typeName}
labels={labels?.length ? labels : undefined}
fields={fields?.length ? fields : undefined}

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
@@ -85,6 +83,7 @@ export const TableApiPage: FC<TTableApiPageProps> = ({ forcedTheme, inside }) =>
apiGroup={apiGroup}
apiVersion={apiVersion}
typeName={typeName}
key={`${apiGroup}-${apiVersion}-${namespace}-${typeName}`}
limit={searchParams.get('limit')}
inside={inside}
customizationIdPrefix={tableCustomizationIdPrefix}

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
@@ -68,6 +66,8 @@ export const TableBuiltinPage: FC<TTableBuiltinPageProps> = ({ forcedTheme, insi
{typeName && (
<TableApiBuiltin
resourceType="builtin"
apiVersion="v1"
key={`${namespace}-${typeName}`}
namespace={namespace}
typeName={typeName}
limit={searchParams.get('limit')}

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'