refactor: create cluster by steps
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
import PageTools from '@/components/page-tools';
|
||||
import { PageActionType } from '@/config/types';
|
||||
import { forwardRef, useImperativeHandle, useRef } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import ClusterForm from '../components/cluster-form';
|
||||
import { ProviderType } from '../config';
|
||||
|
||||
const Title = styled.span`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
font-weight: 700;
|
||||
font-size: 16px;
|
||||
.text {
|
||||
font-size: 20px;
|
||||
}
|
||||
`;
|
||||
interface BasicFormProps {
|
||||
provider: ProviderType;
|
||||
action: PageActionType;
|
||||
credentialList: Global.BaseOption<number>[];
|
||||
currentData?: any;
|
||||
}
|
||||
|
||||
const BasicForm = forwardRef((props: BasicFormProps, ref) => {
|
||||
const { provider, credentialList, action, currentData } = props;
|
||||
const formRef = useRef<any>(null);
|
||||
|
||||
const handleOnFinish = (values: any) => {
|
||||
console.log(values);
|
||||
};
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
validateFields: formRef.current?.validateFields,
|
||||
getFieldsValue: formRef.current?.getFieldsValue,
|
||||
submit: formRef.current?.submit
|
||||
}));
|
||||
|
||||
return (
|
||||
<div>
|
||||
<PageTools
|
||||
marginBottom={26}
|
||||
left={<Title>Basic Configuration</Title>}
|
||||
marginTop={0}
|
||||
></PageTools>
|
||||
<ClusterForm
|
||||
provider={provider}
|
||||
action={action}
|
||||
ref={formRef}
|
||||
credentialList={credentialList}
|
||||
onFinish={handleOnFinish}
|
||||
currentData={currentData}
|
||||
></ClusterForm>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
export default BasicForm;
|
||||
@@ -0,0 +1,19 @@
|
||||
import React from 'react';
|
||||
import AddWorkerStep from '../components/add-worker-step';
|
||||
import ProviderCatalog from '../components/provider-catalog';
|
||||
import BasicForm from './basic-form';
|
||||
import WorkerPoolForm from './worker-pools-form';
|
||||
|
||||
export const moduleMap = {
|
||||
BasicForm: 'BasicForm',
|
||||
WorkerPoolForm: 'WorkerPoolForm',
|
||||
ProviderCatalog: 'ProviderCatalog',
|
||||
AddWorkerStep: 'AddWorkerStep'
|
||||
};
|
||||
|
||||
export const moduleRegistry: Record<string, React.ComponentType<any>> = {
|
||||
[moduleMap.BasicForm]: BasicForm,
|
||||
[moduleMap.WorkerPoolForm]: WorkerPoolForm,
|
||||
[moduleMap.ProviderCatalog]: ProviderCatalog,
|
||||
[moduleMap.AddWorkerStep]: AddWorkerStep
|
||||
};
|
||||
@@ -0,0 +1,100 @@
|
||||
import { useNavigate } from '@umijs/max';
|
||||
import { useMemoizedFn } from 'ahooks';
|
||||
import { useMemo } from 'react';
|
||||
import { ProviderType, ProviderValueMap } from '../config';
|
||||
import { moduleMap } from './module-registry';
|
||||
|
||||
export default function useStepList() {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const handleBack = useMemoizedFn(() => {
|
||||
navigate(-1);
|
||||
});
|
||||
|
||||
return useMemo(
|
||||
() => [
|
||||
{
|
||||
title: 'Select Cloud Provider',
|
||||
content: 'Choose the cloud provider for your cluster.',
|
||||
showButtons: (provider?: ProviderType) => {
|
||||
return {
|
||||
previous: false,
|
||||
next: true,
|
||||
save: false,
|
||||
skip: false
|
||||
};
|
||||
},
|
||||
defaultShow: true,
|
||||
showForms: [],
|
||||
showModules: [moduleMap.ProviderCatalog],
|
||||
providers: []
|
||||
},
|
||||
{
|
||||
title: 'Configure Cluster Settings',
|
||||
content: 'Set up the basic configuration for your cluster.',
|
||||
showButtons: (provider?: ProviderType) => {
|
||||
return {
|
||||
previous: true,
|
||||
next: provider === ProviderValueMap.DigitalOcean,
|
||||
save: provider !== ProviderValueMap.DigitalOcean,
|
||||
skip: false
|
||||
};
|
||||
},
|
||||
defaultShow: true,
|
||||
showForms: [moduleMap.BasicForm],
|
||||
showModules: [],
|
||||
providers: []
|
||||
},
|
||||
{
|
||||
title: 'Add Worker Pools',
|
||||
content: 'Define the worker pools for your cluster.',
|
||||
showButtons: (provider?: ProviderType) => {
|
||||
return {
|
||||
previous: true,
|
||||
next: false,
|
||||
save: true,
|
||||
skip: false
|
||||
};
|
||||
},
|
||||
defaultShow: false,
|
||||
showForms: [moduleMap.WorkerPoolForm],
|
||||
showModules: [],
|
||||
providers: [ProviderValueMap.DigitalOcean],
|
||||
beforeNext: handleBack
|
||||
},
|
||||
{
|
||||
title: 'Add Worker',
|
||||
content: 'Add a worker node to your cluster.',
|
||||
showButtons: (provider?: ProviderType) => {
|
||||
return {
|
||||
previous: false,
|
||||
next: false,
|
||||
save: false,
|
||||
skip: true
|
||||
};
|
||||
},
|
||||
defaultShow: false,
|
||||
showForms: [],
|
||||
showModules: [moduleMap.AddWorkerStep],
|
||||
providers: [ProviderValueMap.Custom]
|
||||
},
|
||||
{
|
||||
title: 'Register Cluster',
|
||||
content: 'Register your cluster with the chosen provider.',
|
||||
showButtons: (provider?: ProviderType) => {
|
||||
return {
|
||||
previous: false,
|
||||
next: false,
|
||||
save: false,
|
||||
skip: true
|
||||
};
|
||||
},
|
||||
defaultShow: false,
|
||||
showForms: [],
|
||||
showModules: [moduleMap.AddWorkerStep],
|
||||
providers: [ProviderValueMap.Kubernetes]
|
||||
}
|
||||
],
|
||||
[handleBack]
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
import PageTools from '@/components/page-tools';
|
||||
import { PageActionType } from '@/config/types';
|
||||
import { DeleteOutlined, PlusOutlined } from '@ant-design/icons';
|
||||
import { Button, Divider, FormInstance } from 'antd';
|
||||
import {
|
||||
forwardRef,
|
||||
useEffect,
|
||||
useImperativeHandle,
|
||||
useRef,
|
||||
useState
|
||||
} from 'react';
|
||||
import styled from 'styled-components';
|
||||
import WorkerPoolForm from '../components/pool-form';
|
||||
import { ProviderType } from '../config';
|
||||
import { NodePoolFormData } from '../config/types';
|
||||
|
||||
const PoolContainer = styled.div`
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 16px;
|
||||
`;
|
||||
|
||||
const PoolFormWrapper = styled.div`
|
||||
flex: 1;
|
||||
`;
|
||||
|
||||
const Title = styled.span`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
font-weight: 700;
|
||||
font-size: 16px;
|
||||
.text {
|
||||
font-size: 20px;
|
||||
}
|
||||
`;
|
||||
interface WorkerPoolsFormProps {
|
||||
provider: ProviderType;
|
||||
action: PageActionType;
|
||||
currentData?: any;
|
||||
}
|
||||
|
||||
const WorkerPoolsForm = forwardRef((props: WorkerPoolsFormProps, ref) => {
|
||||
const { provider, action, currentData } = props;
|
||||
const countRef = useRef(1);
|
||||
const formRefs = useRef<Record<number, FormInstance<any> | null>>({});
|
||||
const [workerPoolList, setWorkerPoolList] = useState<
|
||||
Map<number, NodePoolFormData>
|
||||
>(
|
||||
new Map([
|
||||
[
|
||||
1,
|
||||
{
|
||||
instance_type: 'Pool-1'
|
||||
}
|
||||
]
|
||||
]) as Map<number, NodePoolFormData>
|
||||
);
|
||||
|
||||
const handleOnFinish = (values: any) => {};
|
||||
|
||||
const updateCount = () => {
|
||||
countRef.current += 1;
|
||||
return countRef.current;
|
||||
};
|
||||
|
||||
const handleAddPool = () => {
|
||||
const newId = updateCount();
|
||||
setWorkerPoolList((prev) =>
|
||||
new Map(prev).set(newId, {
|
||||
instance_type: `Pool-${newId}`
|
||||
} as NodePoolFormData)
|
||||
);
|
||||
};
|
||||
|
||||
const handleRemovePool = (id: number) => {
|
||||
if (workerPoolList.size === 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
setWorkerPoolList((prev) => {
|
||||
const newList = new Map(prev);
|
||||
newList.delete(id);
|
||||
return newList;
|
||||
});
|
||||
formRefs.current[id] = null;
|
||||
};
|
||||
|
||||
const gatherFormValues = (results: PromiseSettledResult<any>[]) => {
|
||||
const resultList = results.map((result: PromiseSettledResult<any>) => {
|
||||
if (result.status === 'fulfilled') {
|
||||
return result.value;
|
||||
}
|
||||
if (result.status === 'rejected') {
|
||||
return result.reason?.values || {};
|
||||
}
|
||||
return {};
|
||||
});
|
||||
console.log('gatherFormValues========', resultList);
|
||||
return resultList;
|
||||
};
|
||||
|
||||
const validateFields = async () => {
|
||||
const promises = Array.from(Object.values(formRefs.current)).map((form) =>
|
||||
form?.validateFields()
|
||||
);
|
||||
const results = await Promise.allSettled(promises);
|
||||
console.log('results========0', promises, results);
|
||||
if (results.some((result) => result.status === 'rejected')) {
|
||||
return Promise.reject({
|
||||
values: {
|
||||
worker_pools: gatherFormValues(results)
|
||||
}
|
||||
});
|
||||
}
|
||||
return Promise.resolve({
|
||||
worker_pools: gatherFormValues(results)
|
||||
});
|
||||
};
|
||||
|
||||
const setFieldsValue = (data: any) => {
|
||||
const worker_pools = data.worker_pools || [];
|
||||
const newWorkerPools = worker_pools.map(
|
||||
(poolData: NodePoolFormData, index: number) => [index, poolData]
|
||||
);
|
||||
console.log('newWorkerPools========', newWorkerPools);
|
||||
setWorkerPoolList(new Map(newWorkerPools));
|
||||
};
|
||||
|
||||
const getFieldsValue = () => {
|
||||
const values = Object.values(formRefs.current).map((form) =>
|
||||
form?.getFieldsValue()
|
||||
);
|
||||
console.log('getFieldsValue========', values);
|
||||
return {
|
||||
worker_pools: values
|
||||
};
|
||||
};
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
submit: () => {},
|
||||
validateFields: validateFields,
|
||||
getFieldsValue: getFieldsValue
|
||||
}));
|
||||
|
||||
useEffect(() => {
|
||||
if (currentData) {
|
||||
console.log('currentData===========1=', currentData);
|
||||
setFieldsValue(currentData);
|
||||
}
|
||||
}, [currentData]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<PageTools
|
||||
marginBottom={22}
|
||||
marginTop={0}
|
||||
left={
|
||||
<span className="flex-center gap-16">
|
||||
<Title>Worker Pools Configuration</Title>
|
||||
</span>
|
||||
}
|
||||
right={
|
||||
<Button
|
||||
onClick={handleAddPool}
|
||||
variant="filled"
|
||||
color="default"
|
||||
icon={<PlusOutlined />}
|
||||
>
|
||||
Add Pool
|
||||
</Button>
|
||||
}
|
||||
></PageTools>
|
||||
{Array.from(workerPoolList.keys()).map((key, index) => (
|
||||
<div key={key}>
|
||||
<PoolContainer>
|
||||
<PoolFormWrapper>
|
||||
<WorkerPoolForm
|
||||
name={`workerPoolForm_${key}`}
|
||||
action={action}
|
||||
ref={(el: any) => {
|
||||
if (el) {
|
||||
formRefs.current[key] = el;
|
||||
}
|
||||
}}
|
||||
onFinish={handleOnFinish}
|
||||
provider={provider}
|
||||
currentData={workerPoolList.get(key)}
|
||||
></WorkerPoolForm>
|
||||
</PoolFormWrapper>
|
||||
</PoolContainer>
|
||||
{index !== Array.from(workerPoolList.keys()).length - 1 && (
|
||||
<Divider orientation="right">
|
||||
<Button
|
||||
variant="filled"
|
||||
color="default"
|
||||
onClick={() => handleRemovePool(key)}
|
||||
icon={<DeleteOutlined />}
|
||||
></Button>
|
||||
</Divider>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
<div className="flex-end">
|
||||
<Button
|
||||
onClick={handleAddPool}
|
||||
variant="filled"
|
||||
color="default"
|
||||
icon={<PlusOutlined />}
|
||||
>
|
||||
Add Pool
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
export default WorkerPoolsForm;
|
||||
Reference in New Issue
Block a user