diff --git a/ui/src/components/ClassSelect/index.tsx b/ui/src/components/ClassSelect/index.tsx deleted file mode 100644 index 47b51c1bb..000000000 --- a/ui/src/components/ClassSelect/index.tsx +++ /dev/null @@ -1,104 +0,0 @@ -import { intl } from '@/utils/intl'; -import { Select, Tooltip } from 'antd'; - -interface ClassSelectProps { - selectList: { - value: string; - label: string; - toolTipData: any; - }[]; - form: any; - name: string | number | (string | number)[]; -} - -export default function ClassSelect({ - selectList, - form, - name, -}: ClassSelectProps) { - const filterOption = ( - input: string, - option: { label: string; value: string }, - ) =>{ - return (option?.value ?? '').toLowerCase().includes(input.toLowerCase()); - } - - const formatData = (list: any) => { - list.forEach((item: any) => { - item.label = ( - - {item.toolTipData.map((data: any) => { - let key = Object.keys(data)[0]; - if (typeof data[key] === 'string') { - return ( -
  • -
    -

    {key}:

    -

    {data[key]}

    -
    -
  • - ); - } else { - let value = JSON.stringify(data[key]) || String(data[key]); - return ( -
  • -
    -

    {key}:

    -

    {value}

    -
    -
  • - ); - } - })} - - } - > -
    {item.value}
    -
    - ); - }); - return list; - }; - - const selectChange = (val: string) => { - form.setFieldValue(name, val); - form.validateFields([name]); - }; - - return ( - + ); +} diff --git a/ui/src/components/customModal/AddZoneModal.tsx b/ui/src/components/customModal/AddZoneModal.tsx index 017d670de..8854ccff9 100644 --- a/ui/src/components/customModal/AddZoneModal.tsx +++ b/ui/src/components/customModal/AddZoneModal.tsx @@ -1,7 +1,7 @@ import { intl } from '@/utils/intl'; import { Form, Input, InputNumber, message } from 'antd'; -import { TZ_NAME_REG } from '@/constants'; +import { RULER_ZONE } from '@/constants/rules'; import { getNSName } from '@/pages/Cluster/Detail/Overview/helper'; import { addObzone } from '@/services'; import type { CommonModalType } from '.'; @@ -64,22 +64,7 @@ export default function AddZoneModal({ defaultMessage: 'zone名称', })} name="zone" - rules={[ - { - required: true, - message: intl.formatMessage({ - id: 'OBDashboard.components.customModal.AddZoneModal.EnterAZoneName', - defaultMessage: '请输入zone名称!', - }), - }, - { - pattern: TZ_NAME_REG, - message: intl.formatMessage({ - id: 'Dashboard.components.customModal.AddZoneModal.TheFirstCharacterMustBe', - defaultMessage: '首字符必须是字母或者下划线,不能包含 -', - }), - }, - ]} + rules={RULER_ZONE} > { + return replicaList.map((replica) => ({ + label: replica.zone, + value: replica.zone, + toolTipData: Object.keys(replica) + .filter((key) => key !== 'zone') + .map((key) => ({ [key]: replica[key] })), + })); +}; + type UnitConfigType = { clusterList?: API.SimpleClusterList; clusterResourceName?: string; essentialParameter?: API.EssentialParametersType; setClusterList: React.Dispatch>; + editZone?: string; + replicaList?: API.ReplicaDetailType[]; + newResourcePool?: boolean; + setEditZone?: React.Dispatch>; + zonesOptions?: API.OptionsType; }; export default function ModifyUnitDetailModal({ @@ -42,27 +65,58 @@ export default function ModifyUnitDetailModal({ setClusterList, essentialParameter = {}, clusterResourceName = '', + editZone, + replicaList, + newResourcePool = false, + setEditZone, + zonesOptions, }: CommonModalType & UnitConfigType) { - const [form] = Form.useForm(); + const [form] = Form.useForm(); const [minMemory, setMinMemory] = useState(2); const [maxResource, setMaxResource] = useState({}); - const [selectZones, setSelectZones] = useState([]); + const [selectZones, setSelectZones] = useState( + editZone ? [editZone] : [], + ); + const selectZone = Form.useWatch('selectZone', form); + const obtenantPoolReq = newResourcePool + ? createObtenantPool + : patchObtenantPool; + const handleSubmit = async () => { try { await form.validateFields(); form.submit(); } catch (err) {} }; - const handleCancel = () => setVisible(false); + const handleCancel = () => { + if (setEditZone) { + setEditZone(''); + setSelectZones([]); + } + form.resetFields(); + setVisible(false); + }; + const onFinish = async (values: any) => { const [ns, name] = getNSName(); - const res = await patchTenantConfiguration({ + const { zoneName, ...reqData } = formatPatchPoolData( + values, + newResourcePool ? 'create' : 'edit', + ); + const res = await obtenantPoolReq({ ns, name, - ...formatUnitDetailData(values), + zoneName, + ...reqData, }); if (res.successful) { - message.success(res.message); + message.success( + res.message || + intl.formatMessage({ + id: 'Dashboard.components.customModal.ModifyUnitDetailModal.ModifiedSuccessfully', + defaultMessage: '修改成功', + }), + ); successCallback(); form.resetFields(); setVisible(false); @@ -75,15 +129,48 @@ export default function ModifyUnitDetailModal({ } else { setSelectZones([...selectZones, name]); } + setClusterList( - getNewClusterList(clusterList, name, checked, { name: clusterResourceName }), + modifyZoneCheckedStatus(clusterList, name, checked, { + name: clusterResourceName, + }), ); }; - const targetZoneList = clusterList - .filter((cluster) => cluster.name === clusterResourceName)[0] - ?.topology.map((zone) => ({ zone: zone.zone, checked: zone.checked })); - + const getInitialValues = (editZone: string) => { + let result = {}; + const zone = replicaList?.find((replica) => replica.zone === editZone); + result.unitConfig = { + cpuCount: zone?.minCPU, + iopsWeight: zone?.iopsWeight, + logDiskSize: zone?.logDiskSize.split('Gi')[0], + maxIops: zone?.maxIops, + memorySize: zone?.memorySize.split('Gi')[0], + minIops: zone?.minIops, + }; + if (newResourcePool) { + result.priority = zone?.priority; + } else { + result[zone?.zone] = { + priority: zone?.priority, + }; + } + return result; + }; + let targetCluster = clusterList.find( + (cluster) => cluster.name === clusterResourceName, + ); + let targetZoneList = + targetCluster?.topology.map((zone) => ({ + zone: zone.zone, + checked: zone.checked, + })) || []; + + if (editZone) { + targetZoneList = targetZoneList.filter((zone) => zone.zone === editZone); + } + + const selectOptions = formatReplicaList(replicaList || []); useEffect(() => { if (essentialParameter) { setMinMemory(essentialParameter.minPoolMemory / (1 << 30)); @@ -98,15 +185,40 @@ export default function ModifyUnitDetailModal({ } setMaxResource(findMinParameter(selectZones, essentialParameter)); } - }, [selectZones]); + }, [selectZones, essentialParameter]); + + useEffect(() => { + if (selectZone && replicaList) { + form.setFieldsValue(getInitialValues(selectZone)); + } + }, [selectZone]); + + useEffect(() => { + if (editZone && clusterResourceName) { + setClusterList( + modifyZoneCheckedStatus(clusterList, editZone, true, { + name: clusterResourceName, + }), + ); + form.setFieldsValue(getInitialValues(editZone)); + setSelectZones([editZone]); + } + }, [editZone]); return ( - {targetZoneList && essentialParameter && ( + {newResourcePool && selectOptions.length ? ( -

    - {intl.formatMessage({ - id: 'Dashboard.Tenant.New.ResourcePools.ZonePriority', - defaultMessage: 'Zone优先级', + + + {/* */} + ({ - validator(_: any, value: string) { - if (checkName(value)) { - return Promise.resolve(); - } - return Promise.reject( - new Error( - intl.formatMessage({ - id: 'OBDashboard.Cluster.New.helper.TheResourceNameMayBe', - defaultMessage: '资源名可能拼接到域名中,需要符合域名格式', - }), - ), - ); - }, -}); -export { checkName, generateRandomPassword, passwordRules, resourceNameRule }; +export { generateRandomPassword, passwordRules}; diff --git a/ui/src/pages/Tenant/Detail/Backup/BackupConfiguration.tsx b/ui/src/pages/Tenant/Detail/Backup/BackupConfiguration.tsx index b934c1e82..76d455c8e 100644 --- a/ui/src/pages/Tenant/Detail/Backup/BackupConfiguration.tsx +++ b/ui/src/pages/Tenant/Detail/Backup/BackupConfiguration.tsx @@ -2,31 +2,31 @@ import { BACKUP_RESULT_STATUS } from '@/constants'; import { usePublicKey } from '@/hook/usePublicKey'; import { getNSName } from '@/pages/Cluster/Detail/Overview/helper'; import { -deletePolicyOfTenant, -updateBackupPolicyOfTenant, + deletePolicyOfTenant, + updateBackupPolicyOfTenant, } from '@/services/tenant'; import { intl } from '@/utils/intl'; import { useRequest } from 'ahooks'; import { -Button, -Card, -Col, -Descriptions, -Form, -InputNumber, -Popconfirm, -Row, -Select, -Space, -message + Button, + Card, + Col, + Descriptions, + Form, + InputNumber, + Popconfirm, + Row, + Select, + Space, + message, } from 'antd'; import dayjs from 'dayjs'; -import { useRef,useState } from 'react'; +import { useRef, useState } from 'react'; import { -checkIsSame, -checkScheduleDatesHaveFull, -formatBackupForm, -formatBackupPolicyData, + checkIsSame, + checkScheduleDatesHaveFull, + formatBackupForm, + formatBackupPolicyData, } from '../../helper'; import BakMethodsList from '../NewBackup/BakMethodsList'; import SchduleSelectFormItem from '../NewBackup/SchduleSelectFormItem'; @@ -248,8 +248,14 @@ export default function BackupConfiguration({ deleteBackupPolicyReq({ ns, name })} - title="删除备份" - description="确定要删除该备份策略吗?" + title={intl.formatMessage({ + id: 'Dashboard.Detail.Backup.BackupConfiguration.DeleteBackup', + defaultMessage: '删除备份', + })} + description={intl.formatMessage({ + id: 'Dashboard.Detail.Backup.BackupConfiguration.AreYouSureYouWant', + defaultMessage: '确定要删除该备份策略吗?', + })} >

    } + extra={ + + } collapsible={true} defaultExpand={true} > @@ -93,7 +129,10 @@ export default function Replicas({ )}
    -