diff --git a/package-lock.json b/package-lock.json index be0226c..52bc419 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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", diff --git a/package.json b/package.json index 7df5ee3..8007af0 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/components/atoms/EntrySelect/EntrySelect.tsx b/src/components/atoms/EntrySelect/EntrySelect.tsx index 1098408..6a8d29b 100644 --- a/src/components/atoms/EntrySelect/EntrySelect.tsx +++ b/src/components/atoms/EntrySelect/EntrySelect.tsx @@ -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 = ({ 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 /> ) } diff --git a/src/components/atoms/MarginTopContainer/MarginTopContainer.ts b/src/components/atoms/MarginTopContainer/MarginTopContainer.ts new file mode 100644 index 0000000..5467252 --- /dev/null +++ b/src/components/atoms/MarginTopContainer/MarginTopContainer.ts @@ -0,0 +1,9 @@ +import styled from 'styled-components' + +type TMarinTopContainerProps = { + $top: number +} + +export const MarginTopContainer = styled.div` + margin-top: ${({ $top }) => $top}px; +` diff --git a/src/components/atoms/MarginTopContainer/index.ts b/src/components/atoms/MarginTopContainer/index.ts new file mode 100644 index 0000000..2d8ac3f --- /dev/null +++ b/src/components/atoms/MarginTopContainer/index.ts @@ -0,0 +1 @@ +export * from './MarginTopContainer' diff --git a/src/components/atoms/OverflowMaxHeightContainer/OverflowMaxHeightContainer.ts b/src/components/atoms/OverflowMaxHeightContainer/OverflowMaxHeightContainer.ts new file mode 100644 index 0000000..0ad28cf --- /dev/null +++ b/src/components/atoms/OverflowMaxHeightContainer/OverflowMaxHeightContainer.ts @@ -0,0 +1,11 @@ +import styled from 'styled-components' + +type TOverflowMaxHeightContainerProps = { + $maxHeight: number +} + +export const OverflowMaxHeightContainer = styled.div` + overflow-x: auto; + scrollbar-width: thin; + height: ${({ $maxHeight }) => $maxHeight}px; +` diff --git a/src/components/atoms/OverflowMaxHeightContainer/index.ts b/src/components/atoms/OverflowMaxHeightContainer/index.ts new file mode 100644 index 0000000..45fdf31 --- /dev/null +++ b/src/components/atoms/OverflowMaxHeightContainer/index.ts @@ -0,0 +1 @@ +export * from './OverflowMaxHeightContainer' diff --git a/src/components/atoms/index.ts b/src/components/atoms/index.ts index 43538ca..dacf67b 100644 --- a/src/components/atoms/index.ts +++ b/src/components/atoms/index.ts @@ -11,3 +11,5 @@ export * from './RowFlexGrow' export * from './FlexCol' export * from './NavigationContainer' export * from './EntrySelect' +export * from './OverflowMaxHeightContainer' +export * from './MarginTopContainer' diff --git a/src/components/organisms/HeaderSecond/organisms/Selector/Selector.tsx b/src/components/organisms/HeaderSecond/organisms/Selector/Selector.tsx index 3f0e7a7..8b8a594 100644 --- a/src/components/organisms/HeaderSecond/organisms/Selector/Selector.tsx +++ b/src/components/organisms/HeaderSecond/organisms/Selector/Selector.tsx @@ -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 = ({ 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(() => { diff --git a/src/components/organisms/HeaderSecond/organisms/SelectorInside/SelectorInside.tsx b/src/components/organisms/HeaderSecond/organisms/SelectorInside/SelectorInside.tsx index bdf757f..9376c73 100644 --- a/src/components/organisms/HeaderSecond/organisms/SelectorInside/SelectorInside.tsx +++ b/src/components/organisms/HeaderSecond/organisms/SelectorInside/SelectorInside.tsx @@ -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 = ({ 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 = ({ 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(() => { diff --git a/src/components/organisms/ListInsideAllResources/ListInsideAllResources.tsx b/src/components/organisms/ListInsideAllResources/ListInsideAllResources.tsx index 28ae77a..fc0bf15 100644 --- a/src/components/organisms/ListInsideAllResources/ListInsideAllResources.tsx +++ b/src/components/organisms/ListInsideAllResources/ListInsideAllResources.tsx @@ -51,11 +51,12 @@ export const ListInsideAllResources: FC = ({ names }) }, [cluster, namespace, apiGroupList.data, builtInData.data]) - const { crdGroups, nonCrdGroups, builtinGroups, apiExtensionVersion } = groupsByCategory || {} + // const { crdGroups, nonCrdGroups, builtinGroups, apiExtensionVersion } = groupsByCategory || {} + const { nonCrdGroups, builtinGroups } = groupsByCategory || {} return ( -
+ {/*
CRD Groups @@ -83,7 +84,7 @@ export const ListInsideAllResources: FC = ({ names }} /> )} -
+
*/}
API Groups diff --git a/src/components/organisms/ListInsideAllResources/styled.ts b/src/components/organisms/ListInsideAllResources/styled.ts index 6e83615..42363a0 100644 --- a/src/components/organisms/ListInsideAllResources/styled.ts +++ b/src/components/organisms/ListInsideAllResources/styled.ts @@ -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; ` diff --git a/src/components/organisms/Sidebar/organisms/Selector/Selector.tsx b/src/components/organisms/Sidebar/organisms/Selector/Selector.tsx index 9485e93..367c98d 100644 --- a/src/components/organisms/Sidebar/organisms/Selector/Selector.tsx +++ b/src/components/organisms/Sidebar/organisms/Selector/Selector.tsx @@ -19,9 +19,13 @@ export const Selector: FC = ({ 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(() => { diff --git a/src/components/organisms/Sidebar/organisms/SelectorInside/SelectorInside.tsx b/src/components/organisms/Sidebar/organisms/SelectorInside/SelectorInside.tsx index c85ab19..e77be9e 100644 --- a/src/components/organisms/Sidebar/organisms/SelectorInside/SelectorInside.tsx +++ b/src/components/organisms/Sidebar/organisms/SelectorInside/SelectorInside.tsx @@ -18,9 +18,13 @@ export const SelectorInside: FC = ({ 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(() => { diff --git a/src/components/organisms/TableBuiltinInfo/TableBuiltinInfo.tsx b/src/components/organisms/TableBuiltinInfo/TableBuiltinInfo.tsx index 972b8e3..573e7da 100644 --- a/src/components/organisms/TableBuiltinInfo/TableBuiltinInfo.tsx +++ b/src/components/organisms/TableBuiltinInfo/TableBuiltinInfo.tsx @@ -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 = ({ namespace, typeNa const [selectedRowsData, setSelectedRowsData] = useState<{ name: string; endpoint: string }[]>([]) const [isNamespaced, setIsNamespaced] = useState() + 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 = ({ namespace, typeNa <> {isPending && } {error && } - {!error && data && ( - { - setSelectedRowKeys(selectedRowKeys) - setSelectedRowsData(selectedRowsData) - }, - }} - tableProps={TABLE_PROPS} - /> - )} + + {!error && data && ( + { + setSelectedRowKeys(selectedRowKeys) + setSelectedRowsData(selectedRowsData) + }, + }} + tableProps={TABLE_PROPS} + /> + )} + {selectedRowKeys.length > 0 && ( + + + + + + + )} + - {selectedRowKeys.length > 0 && ( - - - - - )} {isDeleteModalOpen && ( = ({ const [selectedRowKeys, setSelectedRowKeys] = useState([]) 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 = ({ <> {isPending && } {error && } - {!error && data && ( - { - setSelectedRowKeys(selectedRowKeys) - setSelectedRowsData(selectedRowsData) - }, - }} - tableProps={TABLE_PROPS} - /> - )} + + {!error && data && ( + { + setSelectedRowKeys(selectedRowKeys) + setSelectedRowsData(selectedRowsData) + }, + }} + tableProps={TABLE_PROPS} + /> + )} + {selectedRowKeys.length > 0 && ( + + + + + + + )} + - {selectedRowKeys.length > 0 && ( - - - - - )} {isDeleteModalOpen && ( = ({ const [selectedRowsData, setSelectedRowsData] = useState<{ name: string; endpoint: string }[]>([]) const [isNamespaced, setIsNamespaced] = useState() + 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 = ({ <> {isPending && } {error && } - {!error && data && ( - { - setSelectedRowKeys(selectedRowKeys) - setSelectedRowsData(selectedRowsData) - }, - }} - tableProps={TABLE_PROPS} - /> - )} + + {!error && data && ( + { + setSelectedRowKeys(selectedRowKeys) + setSelectedRowsData(selectedRowsData) + }, + }} + tableProps={TABLE_PROPS} + /> + )} + {selectedRowKeys.length > 0 && ( + + + + + + + )} + - {selectedRowKeys.length > 0 && ( - - - - - )} {isDeleteModalOpen && (