mirror of
https://github.com/outbackdingo/openapi-ui.git
synced 2026-01-27 18:19:50 +00:00
only api and builtin cats | new selectors logic | new table controls design | new table container
This commit is contained in:
8
package-lock.json
generated
8
package-lock.json
generated
@@ -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.44",
|
||||
"@prorobotech/openapi-k8s-toolkit": "^0.0.1-alpha.45",
|
||||
"@readme/openapi-parser": "4.0.0",
|
||||
"@reduxjs/toolkit": "2.2.5",
|
||||
"@tanstack/react-query": "5.62.2",
|
||||
@@ -2807,9 +2807,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@prorobotech/openapi-k8s-toolkit": {
|
||||
"version": "0.0.1-alpha.44",
|
||||
"resolved": "https://registry.npmjs.org/@prorobotech/openapi-k8s-toolkit/-/openapi-k8s-toolkit-0.0.1-alpha.44.tgz",
|
||||
"integrity": "sha512-bw0vhZT5lQn6ci6Y3dVR0vBk8FdkOW+ZZzkMSi/JuexpVWm9x8O+PJmcSiXmoSnjwzPJtA/XUuqsxmDq1PODTw==",
|
||||
"version": "0.0.1-alpha.45",
|
||||
"resolved": "https://registry.npmjs.org/@prorobotech/openapi-k8s-toolkit/-/openapi-k8s-toolkit-0.0.1-alpha.45.tgz",
|
||||
"integrity": "sha512-+YltuzIeZDT/HAcLCyJzhBsq5a2Zz9ahZF0NYzaS/V6msZYjueoKbtl0OF4vGI8aUENuiEH1VfMY1i2w7vRp2A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@monaco-editor/react": "4.6.0",
|
||||
|
||||
@@ -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.44",
|
||||
"@prorobotech/openapi-k8s-toolkit": "0.0.1-alpha.45",
|
||||
"@readme/openapi-parser": "4.0.0",
|
||||
"@reduxjs/toolkit": "2.2.5",
|
||||
"@tanstack/react-query": "5.62.2",
|
||||
|
||||
@@ -8,7 +8,7 @@ type TEntrySelectProps = {
|
||||
value: string
|
||||
}[]
|
||||
value?: string
|
||||
onChange: (val: string) => void
|
||||
onChange: (val?: string) => void
|
||||
disabled?: boolean
|
||||
fullwidth?: boolean
|
||||
}
|
||||
@@ -19,9 +19,10 @@ export const EntrySelect: FC<TEntrySelectProps> = ({ placeholder, value, disable
|
||||
placeholder={placeholder}
|
||||
value={value}
|
||||
options={options.map(({ value, label }) => ({ label, value }))}
|
||||
onChange={(selectedValue: string) => onChange(selectedValue)}
|
||||
onChange={(selectedValue?: string) => onChange(selectedValue)}
|
||||
disabled={disabled}
|
||||
style={{ width: fullwidth ? '100%' : '200px' }}
|
||||
allowClear
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import styled from 'styled-components'
|
||||
|
||||
type TMarinTopContainerProps = {
|
||||
$top: number
|
||||
}
|
||||
|
||||
export const MarginTopContainer = styled.div<TMarinTopContainerProps>`
|
||||
margin-top: ${({ $top }) => $top}px;
|
||||
`
|
||||
1
src/components/atoms/MarginTopContainer/index.ts
Normal file
1
src/components/atoms/MarginTopContainer/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './MarginTopContainer'
|
||||
@@ -0,0 +1,11 @@
|
||||
import styled from 'styled-components'
|
||||
|
||||
type TOverflowMaxHeightContainerProps = {
|
||||
$maxHeight: number
|
||||
}
|
||||
|
||||
export const OverflowMaxHeightContainer = styled.div<TOverflowMaxHeightContainerProps>`
|
||||
overflow-x: auto;
|
||||
scrollbar-width: thin;
|
||||
height: ${({ $maxHeight }) => $maxHeight}px;
|
||||
`
|
||||
1
src/components/atoms/OverflowMaxHeightContainer/index.ts
Normal file
1
src/components/atoms/OverflowMaxHeightContainer/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './OverflowMaxHeightContainer'
|
||||
@@ -11,3 +11,5 @@ export * from './RowFlexGrow'
|
||||
export * from './FlexCol'
|
||||
export * from './NavigationContainer'
|
||||
export * from './EntrySelect'
|
||||
export * from './OverflowMaxHeightContainer'
|
||||
export * from './MarginTopContainer'
|
||||
|
||||
@@ -6,6 +6,11 @@ import { RootState } from 'store/store'
|
||||
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,
|
||||
} from 'constants/customizationApiGroupAndVersion'
|
||||
|
||||
type TSelectorProps = {
|
||||
clusterName?: string
|
||||
@@ -32,14 +37,24 @@ export const Selector: FC<TSelectorProps> = ({ clusterName, projectName, instanc
|
||||
// navigate(`${baseprefix}/clusters/${value}`)
|
||||
// }
|
||||
|
||||
const handleProjectChange = (value: string) => {
|
||||
setSelectedProjectName(value)
|
||||
navigate(`${baseprefix}/clusters/${selectedClusterName}/projects/${value}`)
|
||||
const handleProjectChange = (value?: string) => {
|
||||
if (value) {
|
||||
setSelectedProjectName(value)
|
||||
navigate(`${baseprefix}/clusters/${selectedClusterName}/projects/${value}`)
|
||||
} else {
|
||||
navigate(`${baseprefix}/clusters/${selectedClusterName}/`)
|
||||
}
|
||||
}
|
||||
|
||||
const handleInstanceChange = (value: string) => {
|
||||
setSelectedInstanceName(value)
|
||||
navigate(`${baseprefix}/${selectedClusterName}/${value}/${selectedProjectName}/api-table/apps/v1/deployments`)
|
||||
const handleInstanceChange = (value?: string) => {
|
||||
if (value) {
|
||||
setSelectedInstanceName(value)
|
||||
navigate(`${baseprefix}/${selectedClusterName}/${value}/${selectedProjectName}/api-table/apps/v1/deployments`)
|
||||
} else {
|
||||
navigate(
|
||||
`${baseprefix}/${selectedClusterName}/${selectedProjectName}/api-table/${BASE_INSTANCES_API_GROUP}/${BASE_INSTANCES_VERSION}/${BASE_INSTANCES_RESOURCE_NAME}`,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
useMountEffect(() => {
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
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 { useNavigate, useParams } from 'react-router-dom'
|
||||
import { useNavSelectorInside } from 'hooks/useNavSelectorInside'
|
||||
import { useMountEffect } from 'hooks/useMountEffect'
|
||||
import { EntrySelect } from 'components/atoms'
|
||||
@@ -14,7 +12,7 @@ type TSelectorInsideProps = {
|
||||
|
||||
export const SelectorInside: FC<TSelectorInsideProps> = ({ clusterName, namespace }) => {
|
||||
const navigate = useNavigate()
|
||||
const baseprefix = useSelector((state: RootState) => state.baseprefix.baseprefix)
|
||||
const params = useParams()
|
||||
|
||||
const [selectedClusterName, setSelectedClusterName] = useState(clusterName)
|
||||
const [selectedNamespace, setSelectedNamespace] = useState(namespace)
|
||||
@@ -27,9 +25,22 @@ export const SelectorInside: FC<TSelectorInsideProps> = ({ clusterName, namespac
|
||||
// navigate(`${baseprefix}/inside/${value}/apis`)
|
||||
// }
|
||||
|
||||
const handleNamepsaceChange = (value: string) => {
|
||||
setSelectedNamespace(value)
|
||||
navigate(`${baseprefix}/inside/${selectedClusterName}/${value}/apis`)
|
||||
const handleNamepsaceChange = (value?: string) => {
|
||||
if (value && params.namespace) {
|
||||
setSelectedNamespace(value)
|
||||
const pathnames = window.location.pathname.split('/')
|
||||
const newPathNames = [...pathnames.slice(0, 4), value, ...pathnames.slice(5)]
|
||||
navigate(newPathNames.join('/'))
|
||||
} else if (value && !params.namespace) {
|
||||
setSelectedNamespace(value)
|
||||
const pathnames = window.location.pathname.split('/')
|
||||
const newPathNames = [...pathnames.slice(0, 4), value, ...pathnames.slice(4)]
|
||||
navigate(newPathNames.join('/'))
|
||||
} else {
|
||||
const pathnames = window.location.pathname.split('/')
|
||||
const newPathnames = pathnames.filter((_, i) => i !== 4)
|
||||
navigate(newPathnames.join('/'))
|
||||
}
|
||||
}
|
||||
|
||||
useMountEffect(() => {
|
||||
|
||||
@@ -51,11 +51,12 @@ export const ListInsideAllResources: FC<TListInsideAllResourcesProps> = ({ names
|
||||
})
|
||||
}, [cluster, namespace, apiGroupList.data, builtInData.data])
|
||||
|
||||
const { crdGroups, nonCrdGroups, builtinGroups, apiExtensionVersion } = groupsByCategory || {}
|
||||
// const { crdGroups, nonCrdGroups, builtinGroups, apiExtensionVersion } = groupsByCategory || {}
|
||||
const { nonCrdGroups, builtinGroups } = groupsByCategory || {}
|
||||
|
||||
return (
|
||||
<Styled.Grid>
|
||||
<div>
|
||||
{/* <div>
|
||||
<Flex justify="center">
|
||||
<TitleWithNoTopMargin level={3}>CRD Groups</TitleWithNoTopMargin>
|
||||
</Flex>
|
||||
@@ -83,7 +84,7 @@ export const ListInsideAllResources: FC<TListInsideAllResourcesProps> = ({ names
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div> */}
|
||||
<div>
|
||||
<Flex justify="center">
|
||||
<TitleWithNoTopMargin level={3}>API Groups</TitleWithNoTopMargin>
|
||||
|
||||
@@ -3,7 +3,8 @@ import styled from 'styled-components'
|
||||
const Grid = styled.div`
|
||||
display: grid;
|
||||
grid-gap: 72px;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
/* grid-template-columns: repeat(3, 1fr); */
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
height: 100%;
|
||||
min-height: 80vh;
|
||||
`
|
||||
|
||||
@@ -19,9 +19,13 @@ export const Selector: FC<TSelectorProps> = ({ clusterName, projectName }) => {
|
||||
|
||||
const { clustersInSidebar } = useNavSelector(selectedClusterName, projectName)
|
||||
|
||||
const handleClusterChange = (value: string) => {
|
||||
setSelectedClusterName(value)
|
||||
navigate(`${baseprefix}/clusters/${value}`)
|
||||
const handleClusterChange = (value?: string) => {
|
||||
if (value) {
|
||||
setSelectedClusterName(value)
|
||||
navigate(`${baseprefix}/clusters/${value}`)
|
||||
} else {
|
||||
navigate(`${baseprefix}/clusters/`)
|
||||
}
|
||||
}
|
||||
|
||||
useMountEffect(() => {
|
||||
|
||||
@@ -18,9 +18,13 @@ export const SelectorInside: FC<TSelectorInsideProps> = ({ clusterName }) => {
|
||||
|
||||
const { clustersInSidebar } = useNavSelectorInside(selectedClusterName)
|
||||
|
||||
const handleClusterChange = (value: string) => {
|
||||
setSelectedClusterName(value)
|
||||
navigate(`${baseprefix}/inside/${value}/apis`)
|
||||
const handleClusterChange = (value?: string) => {
|
||||
if (value) {
|
||||
setSelectedClusterName(value)
|
||||
navigate(`${baseprefix}/inside/${value}/apis`)
|
||||
} else {
|
||||
navigate(`${baseprefix}/inside/`)
|
||||
}
|
||||
}
|
||||
|
||||
useMountEffect(() => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { FC, useState, useEffect } from 'react'
|
||||
import { useNavigate, useParams, useLocation } from 'react-router-dom'
|
||||
import { Spin, Alert, Button, Flex } from 'antd'
|
||||
import { PlusOutlined } from '@ant-design/icons'
|
||||
import { PlusOutlined, ClearOutlined, MinusOutlined } from '@ant-design/icons'
|
||||
import { useSelector } from 'react-redux'
|
||||
import { RootState } from 'store/store'
|
||||
import {
|
||||
@@ -19,8 +19,16 @@ import {
|
||||
useBuiltinResources,
|
||||
} from '@prorobotech/openapi-k8s-toolkit'
|
||||
import { BASE_API_GROUP, BASE_API_VERSION } from 'constants/customizationApiGroupAndVersion'
|
||||
import { FlexGrow } from 'components'
|
||||
import { FlexGrow, OverflowMaxHeightContainer, MarginTopContainer } from 'components'
|
||||
import { TABLE_PROPS } from 'constants/tableProps'
|
||||
import {
|
||||
HEAD_FIRST_ROW,
|
||||
HEAD_SECOND_ROW,
|
||||
FOOTER_HEIGHT,
|
||||
NAV_HEIGHT,
|
||||
CONTENT_CARD_PADDING,
|
||||
TABLE_ADD_BUTTON_HEIGHT,
|
||||
} from 'constants/blocksSizes'
|
||||
|
||||
type TTableBuiltinInfoProps = {
|
||||
namespace?: string
|
||||
@@ -46,6 +54,30 @@ export const TableBuiltinInfo: FC<TTableBuiltinInfoProps> = ({ namespace, typeNa
|
||||
const [selectedRowsData, setSelectedRowsData] = useState<{ name: string; endpoint: string }[]>([])
|
||||
const [isNamespaced, setIsNamespaced] = useState<boolean>()
|
||||
|
||||
const [height, setHeight] = useState(0)
|
||||
|
||||
useEffect(() => {
|
||||
const height =
|
||||
window.innerHeight -
|
||||
HEAD_FIRST_ROW -
|
||||
HEAD_SECOND_ROW -
|
||||
NAV_HEIGHT -
|
||||
CONTENT_CARD_PADDING * 2 -
|
||||
FOOTER_HEIGHT -
|
||||
TABLE_ADD_BUTTON_HEIGHT
|
||||
setHeight(height)
|
||||
|
||||
const handleResize = () => {
|
||||
setHeight(height)
|
||||
}
|
||||
|
||||
window.addEventListener('resize', handleResize)
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('resize', handleResize)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const createPermission = usePermissions({
|
||||
apiGroup: '',
|
||||
typeName,
|
||||
@@ -158,43 +190,59 @@ export const TableBuiltinInfo: FC<TTableBuiltinInfoProps> = ({ namespace, typeNa
|
||||
<>
|
||||
{isPending && <Spin />}
|
||||
{error && <Alert message={`An error has occurred: ${error?.message} `} type="error" />}
|
||||
{!error && data && (
|
||||
<EnrichedTableProvider
|
||||
theme={theme}
|
||||
baseprefix={inside ? `${baseprefix}/inside` : baseprefix}
|
||||
dataItems={data.items}
|
||||
additionalPrinterColumns={ensuredCustomOverrides || additionalPrinterColumns}
|
||||
additionalPrinterColumnsUndefinedValues={ensuredCustomOverridesUndefinedValues}
|
||||
additionalPrinterColumnsTrimLengths={ensuredCustomOverridesTrimLengths}
|
||||
additionalPrinterColumnsColWidths={ensuredCustomOverridesColWidths}
|
||||
dataForControls={{
|
||||
cluster,
|
||||
syntheticProject: params.syntheticProject,
|
||||
pathPrefix: 'forms/builtin',
|
||||
typeName,
|
||||
apiVersion: 'v1',
|
||||
backlink: `${baseprefix}${inside ? '/inside' : ''}/${cluster}${namespace ? `/${namespace}` : ''}${
|
||||
params.syntheticProject ? `/${params.syntheticProject}` : ''
|
||||
}/builtin-table/${typeName}`,
|
||||
deletePathPrefix: `/api/clusters/${cluster}/k8s/api`,
|
||||
onDeleteHandle,
|
||||
permissions: {
|
||||
canUpdate: isNamespaced ? true : updatePermission.data?.status.allowed,
|
||||
canDelete: isNamespaced ? true : deletePermission.data?.status.allowed,
|
||||
},
|
||||
}}
|
||||
pathToNavigate={tableMappingSpecific?.pathToNavigate}
|
||||
recordKeysForNavigation={tableMappingSpecific?.keysToParse}
|
||||
selectData={{
|
||||
selectedRowKeys,
|
||||
onChange: (selectedRowKeys: React.Key[], selectedRowsData: { name: string; endpoint: string }[]) => {
|
||||
setSelectedRowKeys(selectedRowKeys)
|
||||
setSelectedRowsData(selectedRowsData)
|
||||
},
|
||||
}}
|
||||
tableProps={TABLE_PROPS}
|
||||
/>
|
||||
)}
|
||||
<OverflowMaxHeightContainer $maxHeight={height}>
|
||||
{!error && data && (
|
||||
<EnrichedTableProvider
|
||||
theme={theme}
|
||||
baseprefix={inside ? `${baseprefix}/inside` : baseprefix}
|
||||
dataItems={data.items}
|
||||
additionalPrinterColumns={ensuredCustomOverrides || additionalPrinterColumns}
|
||||
additionalPrinterColumnsUndefinedValues={ensuredCustomOverridesUndefinedValues}
|
||||
additionalPrinterColumnsTrimLengths={ensuredCustomOverridesTrimLengths}
|
||||
additionalPrinterColumnsColWidths={ensuredCustomOverridesColWidths}
|
||||
dataForControls={{
|
||||
cluster,
|
||||
syntheticProject: params.syntheticProject,
|
||||
pathPrefix: 'forms/builtin',
|
||||
typeName,
|
||||
apiVersion: 'v1',
|
||||
backlink: `${baseprefix}${inside ? '/inside' : ''}/${cluster}${namespace ? `/${namespace}` : ''}${
|
||||
params.syntheticProject ? `/${params.syntheticProject}` : ''
|
||||
}/builtin-table/${typeName}`,
|
||||
deletePathPrefix: `/api/clusters/${cluster}/k8s/api`,
|
||||
onDeleteHandle,
|
||||
permissions: {
|
||||
canUpdate: isNamespaced ? true : updatePermission.data?.status.allowed,
|
||||
canDelete: isNamespaced ? true : deletePermission.data?.status.allowed,
|
||||
},
|
||||
}}
|
||||
pathToNavigate={tableMappingSpecific?.pathToNavigate}
|
||||
recordKeysForNavigation={tableMappingSpecific?.keysToParse}
|
||||
selectData={{
|
||||
selectedRowKeys,
|
||||
onChange: (selectedRowKeys: React.Key[], selectedRowsData: { name: string; endpoint: string }[]) => {
|
||||
setSelectedRowKeys(selectedRowKeys)
|
||||
setSelectedRowsData(selectedRowsData)
|
||||
},
|
||||
}}
|
||||
tableProps={TABLE_PROPS}
|
||||
/>
|
||||
)}
|
||||
{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 />
|
||||
<Flex justify="space-between">
|
||||
<Button
|
||||
@@ -214,14 +262,6 @@ export const TableBuiltinInfo: FC<TTableBuiltinInfoProps> = ({ namespace, typeNa
|
||||
<PlusOutlined />
|
||||
Add
|
||||
</Button>
|
||||
{selectedRowKeys.length > 0 && (
|
||||
<Flex gap={8}>
|
||||
<Button onClick={clearSelected}>Clear</Button>
|
||||
<Button onClick={() => setIsDeleteModalManyOpen(selectedRowsData)} danger>
|
||||
Delete
|
||||
</Button>
|
||||
</Flex>
|
||||
)}
|
||||
</Flex>
|
||||
{isDeleteModalOpen && (
|
||||
<DeleteModal
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { FC, useState } from 'react'
|
||||
import React, { FC, useState, useEffect } from 'react'
|
||||
import { useNavigate, useParams, useLocation } from 'react-router-dom'
|
||||
import { Spin, Alert, Button, Flex } from 'antd'
|
||||
import { PlusOutlined } from '@ant-design/icons'
|
||||
import { PlusOutlined, ClearOutlined, MinusOutlined } from '@ant-design/icons'
|
||||
import { useSelector } from 'react-redux'
|
||||
import { RootState } from 'store/store'
|
||||
import {
|
||||
@@ -16,8 +16,16 @@ import {
|
||||
parseCustomOverrides,
|
||||
} from '@prorobotech/openapi-k8s-toolkit'
|
||||
import { BASE_API_GROUP, BASE_API_VERSION } from 'constants/customizationApiGroupAndVersion'
|
||||
import { FlexGrow } from 'components'
|
||||
import { FlexGrow, OverflowMaxHeightContainer, MarginTopContainer } from 'components'
|
||||
import { TABLE_PROPS } from 'constants/tableProps'
|
||||
import {
|
||||
HEAD_FIRST_ROW,
|
||||
HEAD_SECOND_ROW,
|
||||
FOOTER_HEIGHT,
|
||||
NAV_HEIGHT,
|
||||
CONTENT_CARD_PADDING,
|
||||
TABLE_ADD_BUTTON_HEIGHT,
|
||||
} from 'constants/blocksSizes'
|
||||
|
||||
type TResourceInfoProps = {
|
||||
clusterName: string
|
||||
@@ -62,6 +70,30 @@ export const ResourceInfo: FC<TResourceInfoProps> = ({
|
||||
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([])
|
||||
const [selectedRowsData, setSelectedRowsData] = useState<{ name: string; endpoint: string }[]>([])
|
||||
|
||||
const [height, setHeight] = useState(0)
|
||||
|
||||
useEffect(() => {
|
||||
const height =
|
||||
window.innerHeight -
|
||||
HEAD_FIRST_ROW -
|
||||
HEAD_SECOND_ROW -
|
||||
NAV_HEIGHT -
|
||||
CONTENT_CARD_PADDING * 2 -
|
||||
FOOTER_HEIGHT -
|
||||
TABLE_ADD_BUTTON_HEIGHT
|
||||
setHeight(height)
|
||||
|
||||
const handleResize = () => {
|
||||
setHeight(height)
|
||||
}
|
||||
|
||||
window.addEventListener('resize', handleResize)
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('resize', handleResize)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const { isPending, error, data } = useCrdResources({
|
||||
clusterName,
|
||||
namespace,
|
||||
@@ -142,44 +174,60 @@ export const ResourceInfo: FC<TResourceInfoProps> = ({
|
||||
<>
|
||||
{isPending && <Spin />}
|
||||
{error && <Alert message={`An error has occurred: ${error?.message} `} type="error" />}
|
||||
{!error && data && (
|
||||
<EnrichedTableProvider
|
||||
theme={theme}
|
||||
baseprefix={inside ? `${baseprefix}/inside` : baseprefix}
|
||||
dataItems={data.items}
|
||||
resourceSchema={resourceSchema}
|
||||
additionalPrinterColumns={ensuredCustomOverrides || crdAdditionalPrinterColumns}
|
||||
additionalPrinterColumnsUndefinedValues={ensuredCustomOverridesUndefinedValues}
|
||||
additionalPrinterColumnsTrimLengths={ensuredCustomOverridesTrimLengths}
|
||||
additionalPrinterColumnsColWidths={ensuredCustomOverridesColWidths}
|
||||
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,
|
||||
},
|
||||
}}
|
||||
pathToNavigate={tableMappingSpecific?.pathToNavigate}
|
||||
recordKeysForNavigation={tableMappingSpecific?.keysToParse}
|
||||
selectData={{
|
||||
selectedRowKeys,
|
||||
onChange: (selectedRowKeys: React.Key[], selectedRowsData: { name: string; endpoint: string }[]) => {
|
||||
setSelectedRowKeys(selectedRowKeys)
|
||||
setSelectedRowsData(selectedRowsData)
|
||||
},
|
||||
}}
|
||||
tableProps={TABLE_PROPS}
|
||||
/>
|
||||
)}
|
||||
<OverflowMaxHeightContainer $maxHeight={height}>
|
||||
{!error && data && (
|
||||
<EnrichedTableProvider
|
||||
theme={theme}
|
||||
baseprefix={inside ? `${baseprefix}/inside` : baseprefix}
|
||||
dataItems={data.items}
|
||||
resourceSchema={resourceSchema}
|
||||
additionalPrinterColumns={ensuredCustomOverrides || crdAdditionalPrinterColumns}
|
||||
additionalPrinterColumnsUndefinedValues={ensuredCustomOverridesUndefinedValues}
|
||||
additionalPrinterColumnsTrimLengths={ensuredCustomOverridesTrimLengths}
|
||||
additionalPrinterColumnsColWidths={ensuredCustomOverridesColWidths}
|
||||
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,
|
||||
},
|
||||
}}
|
||||
pathToNavigate={tableMappingSpecific?.pathToNavigate}
|
||||
recordKeysForNavigation={tableMappingSpecific?.keysToParse}
|
||||
selectData={{
|
||||
selectedRowKeys,
|
||||
onChange: (selectedRowKeys: React.Key[], selectedRowsData: { name: string; endpoint: string }[]) => {
|
||||
setSelectedRowKeys(selectedRowKeys)
|
||||
setSelectedRowsData(selectedRowsData)
|
||||
},
|
||||
}}
|
||||
tableProps={TABLE_PROPS}
|
||||
/>
|
||||
)}
|
||||
{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 />
|
||||
<Flex justify="space-between">
|
||||
<Button
|
||||
@@ -201,14 +249,6 @@ export const ResourceInfo: FC<TResourceInfoProps> = ({
|
||||
<PlusOutlined />
|
||||
Add
|
||||
</Button>
|
||||
{selectedRowKeys.length > 0 && (
|
||||
<Flex gap={8}>
|
||||
<Button onClick={clearSelected}>Clear</Button>
|
||||
<Button onClick={() => setIsDeleteModalManyOpen(selectedRowsData)} danger>
|
||||
Delete
|
||||
</Button>
|
||||
</Flex>
|
||||
)}
|
||||
</Flex>
|
||||
{isDeleteModalOpen && (
|
||||
<DeleteModal
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/* eslint-disable max-lines-per-function */
|
||||
import React, { FC, useState, useEffect } from 'react'
|
||||
import { useNavigate, useParams, useLocation } from 'react-router-dom'
|
||||
import { Spin, Alert, Button, Flex } from 'antd'
|
||||
import { PlusOutlined } from '@ant-design/icons'
|
||||
import { PlusOutlined, ClearOutlined, MinusOutlined } from '@ant-design/icons'
|
||||
import { useSelector } from 'react-redux'
|
||||
import { RootState } from 'store/store'
|
||||
import {
|
||||
@@ -19,8 +20,16 @@ import {
|
||||
parseCustomOverrides,
|
||||
} from '@prorobotech/openapi-k8s-toolkit'
|
||||
import { BASE_API_GROUP, BASE_API_VERSION } from 'constants/customizationApiGroupAndVersion'
|
||||
import { FlexGrow } from 'components'
|
||||
import { FlexGrow, OverflowMaxHeightContainer, MarginTopContainer } from 'components'
|
||||
import { TABLE_PROPS } from 'constants/tableProps'
|
||||
import {
|
||||
HEAD_FIRST_ROW,
|
||||
HEAD_SECOND_ROW,
|
||||
FOOTER_HEIGHT,
|
||||
NAV_HEIGHT,
|
||||
CONTENT_CARD_PADDING,
|
||||
TABLE_ADD_BUTTON_HEIGHT,
|
||||
} from 'constants/blocksSizes'
|
||||
|
||||
type TTableNonCrdInfoProps = {
|
||||
namespace?: string
|
||||
@@ -54,6 +63,30 @@ export const TableNonCrdInfo: FC<TTableNonCrdInfoProps> = ({
|
||||
const [selectedRowsData, setSelectedRowsData] = useState<{ name: string; endpoint: string }[]>([])
|
||||
const [isNamespaced, setIsNamespaced] = useState<boolean>()
|
||||
|
||||
const [height, setHeight] = useState(0)
|
||||
|
||||
useEffect(() => {
|
||||
const height =
|
||||
window.innerHeight -
|
||||
HEAD_FIRST_ROW -
|
||||
HEAD_SECOND_ROW -
|
||||
NAV_HEIGHT -
|
||||
CONTENT_CARD_PADDING * 2 -
|
||||
FOOTER_HEIGHT -
|
||||
TABLE_ADD_BUTTON_HEIGHT
|
||||
setHeight(height)
|
||||
|
||||
const handleResize = () => {
|
||||
setHeight(height)
|
||||
}
|
||||
|
||||
window.addEventListener('resize', handleResize)
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('resize', handleResize)
|
||||
}
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
checkIfApiInstanceNamespaceScoped({
|
||||
apiGroup,
|
||||
@@ -173,43 +206,59 @@ export const TableNonCrdInfo: FC<TTableNonCrdInfoProps> = ({
|
||||
<>
|
||||
{isPending && <Spin />}
|
||||
{error && <Alert message={`An error has occurred: ${error?.message} `} type="error" />}
|
||||
{!error && data && (
|
||||
<EnrichedTableProvider
|
||||
theme={theme}
|
||||
baseprefix={inside ? `${baseprefix}/inside` : baseprefix}
|
||||
dataItems={data.items}
|
||||
additionalPrinterColumns={ensuredCustomOverrides || additionalPrinterColumns}
|
||||
additionalPrinterColumnsUndefinedValues={ensuredCustomOverridesUndefinedValues}
|
||||
additionalPrinterColumnsTrimLengths={ensuredCustomOverridesTrimLengths}
|
||||
additionalPrinterColumnsColWidths={ensuredCustomOverridesColWidths}
|
||||
dataForControls={{
|
||||
cluster,
|
||||
syntheticProject: params.syntheticProject,
|
||||
pathPrefix: 'forms/apis',
|
||||
typeName,
|
||||
apiVersion: `${apiGroup}/${apiVersion}`,
|
||||
backlink: `${baseprefix}${inside ? '/inside' : ''}/${cluster}${namespace ? `/${namespace}` : ''}${
|
||||
params.syntheticProject ? `/${params.syntheticProject}` : ''
|
||||
}/api-table/${apiGroup}/${apiVersion}/${typeName}`,
|
||||
deletePathPrefix: `/api/clusters/${cluster}/k8s/apis`,
|
||||
onDeleteHandle,
|
||||
permissions: {
|
||||
canUpdate: isNamespaced ? true : updatePermission.data?.status.allowed,
|
||||
canDelete: isNamespaced ? true : deletePermission.data?.status.allowed,
|
||||
},
|
||||
}}
|
||||
pathToNavigate={tableMappingSpecific?.pathToNavigate}
|
||||
recordKeysForNavigation={tableMappingSpecific?.keysToParse}
|
||||
selectData={{
|
||||
selectedRowKeys,
|
||||
onChange: (selectedRowKeys: React.Key[], selectedRowsData: { name: string; endpoint: string }[]) => {
|
||||
setSelectedRowKeys(selectedRowKeys)
|
||||
setSelectedRowsData(selectedRowsData)
|
||||
},
|
||||
}}
|
||||
tableProps={TABLE_PROPS}
|
||||
/>
|
||||
)}
|
||||
<OverflowMaxHeightContainer $maxHeight={height}>
|
||||
{!error && data && (
|
||||
<EnrichedTableProvider
|
||||
theme={theme}
|
||||
baseprefix={inside ? `${baseprefix}/inside` : baseprefix}
|
||||
dataItems={data.items}
|
||||
additionalPrinterColumns={ensuredCustomOverrides || additionalPrinterColumns}
|
||||
additionalPrinterColumnsUndefinedValues={ensuredCustomOverridesUndefinedValues}
|
||||
additionalPrinterColumnsTrimLengths={ensuredCustomOverridesTrimLengths}
|
||||
additionalPrinterColumnsColWidths={ensuredCustomOverridesColWidths}
|
||||
dataForControls={{
|
||||
cluster,
|
||||
syntheticProject: params.syntheticProject,
|
||||
pathPrefix: 'forms/apis',
|
||||
typeName,
|
||||
apiVersion: `${apiGroup}/${apiVersion}`,
|
||||
backlink: `${baseprefix}${inside ? '/inside' : ''}/${cluster}${namespace ? `/${namespace}` : ''}${
|
||||
params.syntheticProject ? `/${params.syntheticProject}` : ''
|
||||
}/api-table/${apiGroup}/${apiVersion}/${typeName}`,
|
||||
deletePathPrefix: `/api/clusters/${cluster}/k8s/apis`,
|
||||
onDeleteHandle,
|
||||
permissions: {
|
||||
canUpdate: isNamespaced ? true : updatePermission.data?.status.allowed,
|
||||
canDelete: isNamespaced ? true : deletePermission.data?.status.allowed,
|
||||
},
|
||||
}}
|
||||
pathToNavigate={tableMappingSpecific?.pathToNavigate}
|
||||
recordKeysForNavigation={tableMappingSpecific?.keysToParse}
|
||||
selectData={{
|
||||
selectedRowKeys,
|
||||
onChange: (selectedRowKeys: React.Key[], selectedRowsData: { name: string; endpoint: string }[]) => {
|
||||
setSelectedRowKeys(selectedRowKeys)
|
||||
setSelectedRowsData(selectedRowsData)
|
||||
},
|
||||
}}
|
||||
tableProps={TABLE_PROPS}
|
||||
/>
|
||||
)}
|
||||
{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 />
|
||||
<Flex justify="space-between">
|
||||
<Button
|
||||
@@ -231,14 +280,6 @@ export const TableNonCrdInfo: FC<TTableNonCrdInfoProps> = ({
|
||||
<PlusOutlined />
|
||||
Add
|
||||
</Button>
|
||||
{selectedRowKeys.length > 0 && (
|
||||
<Flex gap={8}>
|
||||
<Button onClick={clearSelected}>Clear</Button>
|
||||
<Button onClick={() => setIsDeleteModalManyOpen(selectedRowsData)} danger>
|
||||
Delete
|
||||
</Button>
|
||||
</Flex>
|
||||
)}
|
||||
</Flex>
|
||||
{isDeleteModalOpen && (
|
||||
<DeleteModal
|
||||
|
||||
@@ -11,3 +11,4 @@ export const BREADCRUMBS_HEIGHT = 26
|
||||
export const CONTENT_CARD_PADDING = 25
|
||||
export const BLACKHOLE_FORM_VIEW_SWITCH_HEIGHT = 42
|
||||
export const BLACKHOLE_FORM_SUBMIT_ROW_HEIGHT = 48
|
||||
export const TABLE_ADD_BUTTON_HEIGHT = 35
|
||||
|
||||
Reference in New Issue
Block a user