From 63d2d977e456a927cb9ef1b8e5444703445998eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=B4=E6=99=96?= <2689991790@qq.com> Date: Mon, 1 Apr 2024 20:19:48 +0800 Subject: [PATCH 1/2] Fix resource pool related defects --- ui/src/components/TopoComponent/constants.ts | 29 +++++++-- ui/src/components/TopoComponent/index.tsx | 60 +++++++++++++------ .../customModal/ModifyUnitDetailModal.tsx | 19 ++++-- ui/src/hook/usePublicKey.ts | 29 +++++---- ui/src/pages/Tenant/Detail/Topo/index.tsx | 1 + ui/src/pages/Tenant/helper.ts | 4 +- 6 files changed, 101 insertions(+), 41 deletions(-) diff --git a/ui/src/components/TopoComponent/constants.ts b/ui/src/components/TopoComponent/constants.ts index e965487a1..9699b397c 100644 --- a/ui/src/components/TopoComponent/constants.ts +++ b/ui/src/components/TopoComponent/constants.ts @@ -1,4 +1,5 @@ import { intl } from '@/utils/intl'; +import { clone } from 'lodash'; import type { GraphNodeType } from './helper'; type OperateTypeLabel = { value: string; label: string; disabled?: boolean }[]; @@ -81,6 +82,8 @@ const clusterOperateOfTenant: OperateTypeLabel = [ const getZoneOperateOfTenant = ( haveResourcePool: boolean, tenantReplicas: API.ReplicaDetailType[], + tenantStatus?: string, + clusterStatus?: string, ): OperateTypeLabel => { return haveResourcePool ? [ @@ -90,7 +93,7 @@ const getZoneOperateOfTenant = ( id: 'Dashboard.components.TopoComponent.constants.EditResourcePool', defaultMessage: '编辑资源池', }), - disabled: false, + disabled: tenantStatus !== 'running' || clusterStatus !== 'running', }, { value: 'deleteResourcePool', @@ -98,7 +101,10 @@ const getZoneOperateOfTenant = ( id: 'Dashboard.components.TopoComponent.constants.DeleteAResourcePool', defaultMessage: '删除资源池', }), - disabled: tenantReplicas.length <= 2, + disabled: + tenantReplicas.length <= 2 || + tenantStatus !== 'running' || + clusterStatus !== 'running', }, ] : [ @@ -108,25 +114,40 @@ const getZoneOperateOfTenant = ( id: 'Dashboard.components.TopoComponent.constants.AddAResourcePool', defaultMessage: '新增资源池', }), - disabled: false, + disabled: tenantStatus !== 'running' || clusterStatus !== 'running', }, ]; }; const getZoneOperateOfCluster = ( topoData: GraphNodeType | undefined, + status: string, ): OperateTypeLabel => { if (!topoData) return []; - const isDisabled = topoData?.children?.length <= 2; + const isDisabled = topoData?.children?.length <= 2 || status !== 'running'; zoneOperate.forEach((operate) => { if (operate.value === 'deleteZone') operate.disabled = isDisabled; + if (operate.value === 'scaleServer') + operate.disabled = status !== 'running'; }); return zoneOperate; }; +const getClusterOperates = ( + clusterOperateList: OperateTypeLabel, + disabled: boolean, +): OperateTypeLabel => { + const res = clone(clusterOperateList); + res.forEach((item) => { + item.disabled = disabled; + }); + return res; +}; + export { clusterOperate, clusterOperateOfTenant, + getClusterOperates, getZoneOperateOfCluster, getZoneOperateOfTenant, serverOperate, diff --git a/ui/src/components/TopoComponent/index.tsx b/ui/src/components/TopoComponent/index.tsx index 357325096..3056967d8 100644 --- a/ui/src/components/TopoComponent/index.tsx +++ b/ui/src/components/TopoComponent/index.tsx @@ -6,15 +6,21 @@ import { useRequest,useUpdateEffect } from 'ahooks'; import { message } from 'antd'; import _ from 'lodash'; import { ReactElement,useEffect,useMemo,useRef,useState } from 'react'; -import { useModel } from '@umijs/max'; import showDeleteConfirm from '@/components/customModal/DeleteModal'; import OperateModal from '@/components/customModal/OperateModal'; import { RESULT_STATUS } from '@/constants'; import BasicInfo from '@/pages/Cluster/Detail/Overview/BasicInfo'; -import { getClusterFromTenant, getOriginResourceUsages, getZonesOptions } from '@/pages/Tenant/helper'; +import { +getClusterFromTenant, +getOriginResourceUsages, +getZonesOptions, +} from '@/pages/Tenant/helper'; import { getClusterDetailReq } from '@/services'; -import { deleteClusterReportWrap, deleteObzoneReportWrap } from '@/services/reportRequest/clusterReportReq'; +import { +deleteClusterReportWrap, +deleteObzoneReportWrap, +} from '@/services/reportRequest/clusterReportReq'; import { deleteObtenantPool } from '@/services/tenant'; import { getNSName } from '../../pages/Cluster/Detail/Overview/helper'; import { ReactNode,config } from './G6register'; @@ -22,11 +28,12 @@ import type { OperateTypeLabel } from './constants'; import { clusterOperate, clusterOperateOfTenant, -getZoneOperateOfTenant, +getClusterOperates, getZoneOperateOfCluster, +getZoneOperateOfTenant, serverOperate, } from './constants'; -import { appenAutoShapeListener,checkIsSame,getServerNumber,haveDisabledOperate } from './helper'; +import { appenAutoShapeListener,checkIsSame,getServerNumber } from './helper'; interface TopoProps { tenantReplicas?: API.ReplicaDetailType[]; @@ -36,6 +43,7 @@ interface TopoProps { resourcePoolDefaultValue?: any; refreshTenant?: () => void; defaultUnitCount?: number; + status?: string; } //Cluster topology diagram component @@ -47,17 +55,18 @@ export default function TopoComponent({ resourcePoolDefaultValue, refreshTenant, defaultUnitCount, + status, }: TopoProps) { const clusterOperateList = tenantReplicas ? clusterOperateOfTenant : clusterOperate; const modelRef = useRef(null); + const [visible, setVisible] = useState(false); const [operateList, setOprateList] = useState(clusterOperateList); const [inNode, setInNode] = useState(false); const [inModal, setInModal] = useState(false); - const [[ns, name]] = useState( namespace && clusterNameOfKubectl ? [namespace, clusterNameOfKubectl] @@ -87,13 +96,21 @@ export default function TopoComponent({ }, }, ); + const clusterStatus = useRef(originTopoData?.basicInfo?.status); + const tenantStatus = useRef(status); //Node more icon click event const handleClick = (evt: IG6GraphEvent) => { if (modelRef.current) { switch (evt.item?._cfg?.model?.type) { case 'cluster': - setOprateList(clusterOperateList); + let disabled = tenantReplicas + ? clusterStatus.current !== 'running' || + tenantStatus.current !== 'running' + : clusterStatus.current !== 'running'; + setOprateList( + getClusterOperates(clusterOperateList, disabled), + ); break; case 'zone': const zone = evt.item?._cfg?.model?.label as string; @@ -104,10 +121,20 @@ export default function TopoComponent({ (replica) => replica.zone === zone, ); setOprateList( - getZoneOperateOfTenant(haveResourcePool, tenantReplicas), + getZoneOperateOfTenant( + haveResourcePool, + tenantReplicas, + tenantStatus.current, + clusterStatus.current + ), ); } else { - setOprateList(getZoneOperateOfCluster(originTopoData?.topoData)); + setOprateList( + getZoneOperateOfCluster( + originTopoData?.topoData, + clusterStatus.current, + ), + ); } chooseZoneName.current = zone; break; @@ -287,19 +314,12 @@ export default function TopoComponent({ //Used to re-render the view after data update useUpdateEffect(() => { let checkStatusTimer: NodeJS.Timer; + clusterStatus.current = originTopoData?.basicInfo?.status; //polling if (!RESULT_STATUS.includes(originTopoData.topoData.status)) { - if (!haveDisabledOperate(operateList)) - setOprateList(operateList.map((item) => ({ ...item, disabled: true }))); - checkStatusTimer = setInterval(() => { getTopoData({ ns, name, useFor: 'topo', tenantReplicas }); }, 3000); - } else { - if (haveDisabledOperate(operateList)) - setOprateList( - operateList.map((item) => ({ ...item, disabled: false })), - ); } if (graph.current) { if (!checkIsSame(beforeTopoData.current, originTopoData.topoData)) { @@ -315,6 +335,10 @@ export default function TopoComponent({ }; }, [originTopoData]); + useUpdateEffect(() => { + tenantStatus.current = status; + }, [status]); + /** * Mouseleave will be triggered when the modal is opened, * so the modal cannot be closed in the callback function of mouseleave. @@ -373,7 +397,7 @@ export default function TopoComponent({ /> ), - [operateList, visible], + [operateList, visible, status], )} ( getMinResource({ minMemory: essentialParameter.minPoolMemory }), ); + const [selectZones, setSelectZones] = useState( editZone ? [editZone] : [], ); const selectZone = Form.useWatch('selectZone', form); const obtenantPoolReq = newResourcePool - ? createTenantReportWrap + ? createObtenantPoolReportWrap : patchObtenantPoolReportWrap; const handleSubmit = async () => { @@ -282,7 +283,12 @@ export default function ModifyUnitDetailModal({ style={{ marginRight: 24 }} > {/* */} - { + setSelectZones([val]); + }} + options={zonesOptions} + /> @@ -355,6 +361,7 @@ export default function ModifyUnitDetailModal({ { const [publicKey, setPublicKey] = React.useState(''); useEffect(() => { - getAppInfoFromStorage().then((appInfo) => { - setPublicKey(appInfo.publicKey); - }).catch((err) => { - console.log(err) - }); - }, []) + getAppInfo() + .then(({ data }) => { + setPublicKey(data.publicKey); + }) + .catch((err) => { + console.log(err); + }); + }, []); return publicKey; -} +}; -export const encryptText = (text: string, publicKey: string): string | false => { - const encrypt = new JSEncrypt(); +export const encryptText = ( + text: string, + publicKey: string, +): string | false => { + const encrypt = new JSEncrypt(); encrypt.setPublicKey(publicKey); return encrypt.encrypt(text); -} \ No newline at end of file +}; diff --git a/ui/src/pages/Tenant/Detail/Topo/index.tsx b/ui/src/pages/Tenant/Detail/Topo/index.tsx index 0dde2538b..a5a47c59e 100644 --- a/ui/src/pages/Tenant/Detail/Topo/index.tsx +++ b/ui/src/pages/Tenant/Detail/Topo/index.tsx @@ -86,6 +86,7 @@ export default function Topo() { replicaList: tenantTopoData?.replicas, editZone, }} + status={tenantTopoData?.info?.status} refreshTenant={reGetTenantDetail} header={ { if (resource.obZone === current.zone) { resource.availableCPU += Number(current.minCPU); - resource.availableLogDisk += Number(current.logDiskSize); - resource.availableMemory += Number(current.memorySize); + resource.availableLogDisk += Number(current.logDiskSize.split('Gi')[0]); + resource.availableMemory += Number(current.memorySize.split('Gi')[0]); originResourceUsages.obZoneResourceMap[current.zone].availableCPU += Number(current.minCPU); originResourceUsages.obZoneResourceMap[current.zone].availableLogDisk += From bcaba061c599aaf9c5c8282a831e073072d5cc3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=B4=E6=99=96?= <2689991790@qq.com> Date: Tue, 2 Apr 2024 11:03:56 +0800 Subject: [PATCH 2/2] fix:Avoid repeated requests for public keys --- ui/src/hook/usePublicKey.ts | 21 ++++++++++++--------- ui/src/models/global.ts | 3 +++ ui/src/utils/helper.ts | 4 +--- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/ui/src/hook/usePublicKey.ts b/ui/src/hook/usePublicKey.ts index d88f2a177..8e4b6db11 100644 --- a/ui/src/hook/usePublicKey.ts +++ b/ui/src/hook/usePublicKey.ts @@ -1,18 +1,21 @@ import { getAppInfo } from '@/services'; +import { useModel } from '@umijs/max'; import JSEncrypt from 'jsencrypt'; -import React, { useEffect } from 'react'; +import { useEffect } from 'react'; export const usePublicKey = () => { - const [publicKey, setPublicKey] = React.useState(''); + const { publicKey, setPublicKey } = useModel('global'); useEffect(() => { - getAppInfo() - .then(({ data }) => { - setPublicKey(data.publicKey); - }) - .catch((err) => { - console.log(err); - }); + if (!publicKey) { + getAppInfo() + .then(({ data }) => { + setPublicKey(data.publicKey); + }) + .catch((err) => { + console.log(err); + }); + } }, []); return publicKey; diff --git a/ui/src/models/global.ts b/ui/src/models/global.ts index 668be4713..e51c3842a 100644 --- a/ui/src/models/global.ts +++ b/ui/src/models/global.ts @@ -4,12 +4,15 @@ import { useRef, useState } from 'react'; export default () => { const [chooseClusterName, setChooseClusterName] = useState(''); const [userName, setUsername] = useState(); + const [publicKey, setPublicKey] = useState('') const reportDataInterval = useRef(); return { chooseClusterName, setChooseClusterName, userName, setUsername, + publicKey, + setPublicKey, reportDataInterval, }; }; diff --git a/ui/src/utils/helper.ts b/ui/src/utils/helper.ts index 049f938c8..b3a77cf80 100644 --- a/ui/src/utils/helper.ts +++ b/ui/src/utils/helper.ts @@ -113,7 +113,5 @@ export const reportPollData = async () => { data, }); localStorage.setItem('lastReportTime', Date.now().toString()); - } catch (err) { - throw new Error(err); - } + } catch (err) {} };