184 lines
6.0 KiB
TypeScript
184 lines
6.0 KiB
TypeScript
import useAddWorkerMessage from '@/pages/cluster-management/hooks/use-add-worker-message';
|
|
import { useIntl } from '@umijs/max';
|
|
import React, { useMemo } from 'react';
|
|
import styled from 'styled-components';
|
|
import { ProviderType, ProviderValueMap } from '../../config';
|
|
import { ClusterListItem } from '../../config/types';
|
|
import { AddWorkerContext } from './add-worker-context';
|
|
import AddedMessage from './added-message';
|
|
import CheckEnvironment from './check-environment';
|
|
import { StepName, StepNamesMap } from './config';
|
|
import DockerRunCommand from './docker-run-command';
|
|
import K8sRunCommand from './k8s-run-command';
|
|
import SelectCluster from './select-cluster';
|
|
import SelectVendor from './select-vendor';
|
|
import SpecifyArguments from './specify-arguments';
|
|
import useSummaryStatus from './use-summary-status';
|
|
|
|
const Container = styled.div`
|
|
margin: 0 auto;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 16px;
|
|
.command-info {
|
|
margin-bottom: 8px;
|
|
}
|
|
`;
|
|
/**
|
|
* clusterList and onClusterChange are only required when from worker page.
|
|
*/
|
|
type AddWorkerProps = {
|
|
actionSource?: 'modal' | 'page';
|
|
provider: ProviderType;
|
|
clusterList?: Global.BaseOption<number, ClusterListItem>[];
|
|
clusterLoading?: boolean;
|
|
stepList: StepName[];
|
|
onClusterChange?: (value: number, row?: any) => void;
|
|
onCancel?: () => void;
|
|
registrationInfo: {
|
|
token: string;
|
|
image: string;
|
|
server_url: string;
|
|
cluster_id: number | null;
|
|
[key: string]: any;
|
|
};
|
|
};
|
|
|
|
/**
|
|
* both add worker and register cluster use this component
|
|
* @param props
|
|
* @returns
|
|
*/
|
|
const AddWorkerSteps: React.FC<AddWorkerProps> = (props) => {
|
|
const {
|
|
actionSource,
|
|
registrationInfo,
|
|
provider,
|
|
clusterList,
|
|
clusterLoading,
|
|
stepList = [],
|
|
onCancel,
|
|
onClusterChange
|
|
} = props || {};
|
|
const intl = useIntl();
|
|
|
|
const [collapseKey, setCollapseKey] = React.useState<Set<string>>(
|
|
new Set([stepList[0]])
|
|
);
|
|
const { update, summary, register } = useSummaryStatus();
|
|
const { addedCount, createModelsChunkRequest } = useAddWorkerMessage();
|
|
|
|
const onToggle = (open: boolean, key: string) => {
|
|
setCollapseKey(open ? new Set([key]) : new Set());
|
|
};
|
|
|
|
const handleOnClusterChange = (value: number, row?: any) => {
|
|
onClusterChange?.(value, row);
|
|
};
|
|
|
|
React.useEffect(() => {
|
|
// reset collapseKey when stepList changes
|
|
setCollapseKey(new Set([stepList[0]]));
|
|
}, [stepList]);
|
|
|
|
React.useEffect(() => {
|
|
// this effect is only triggered when used in cluster create page inner
|
|
if (actionSource === 'page' && registrationInfo?.cluster_id) {
|
|
createModelsChunkRequest({
|
|
cluster_id: registrationInfo?.cluster_id
|
|
});
|
|
}
|
|
}, [actionSource, registrationInfo?.cluster_id]);
|
|
|
|
const disabled = useMemo(() => {
|
|
return (
|
|
stepList.includes(StepNamesMap.SelectCluster) && !clusterList?.length
|
|
);
|
|
}, [clusterList, stepList, StepNamesMap]);
|
|
|
|
// Downstream steps (check env, run command, ...) only make sense after a
|
|
// GPU vendor has been chosen. If the user toggled off every vendor in
|
|
// multi-select, gate them shut so the wrong panel can't be opened.
|
|
// Exception: for K8s clusters, Run Command is always accessible (CPU-only
|
|
// workers don't need a GPU vendor).
|
|
const selectedGPUs =
|
|
(summary.get('selectedGPUs') as string[] | undefined) || [];
|
|
const currentGPU = (summary.get('currentGPU') as string | undefined) || '';
|
|
const noVendorSelected = !currentGPU && selectedGPUs.length === 0;
|
|
const isK8s = provider === ProviderValueMap.Kubernetes;
|
|
// For non-K8s providers, all downstream steps are gated by vendor selection.
|
|
// For K8s, both CheckEnv and RunCommand are always accessible — CheckEnv
|
|
// shows a ready-nodes check when no vendor is selected (CPU-only workers).
|
|
const downstreamDisabled = disabled || (noVendorSelected && !isK8s);
|
|
|
|
React.useEffect(() => {
|
|
// If the user just deselected everything on a non-K8s provider, collapse
|
|
// any downstream panel back to the GPU step so they aren't left looking at
|
|
// a stale disabled-but-open command. For K8s, CheckEnv stays open with a
|
|
// ready-nodes check, so no collapsing needed.
|
|
if (!noVendorSelected || isK8s) return;
|
|
setCollapseKey((prev) =>
|
|
prev.has(StepNamesMap.SelectGPU)
|
|
? prev
|
|
: new Set([StepNamesMap.SelectGPU])
|
|
);
|
|
}, [noVendorSelected, isK8s]);
|
|
|
|
return (
|
|
<AddWorkerContext.Provider
|
|
value={{
|
|
clusterList,
|
|
clusterLoading,
|
|
provider,
|
|
stepList: stepList,
|
|
collapseKey,
|
|
actionSource,
|
|
onToggle,
|
|
onCancel,
|
|
onClusterChange: handleOnClusterChange,
|
|
registrationInfo,
|
|
summary,
|
|
registerField: register,
|
|
updateField: update
|
|
}}
|
|
>
|
|
<Container>
|
|
{stepList.includes(StepNamesMap.SelectCluster) && (
|
|
<SelectCluster disabled={disabled}></SelectCluster>
|
|
)}
|
|
{/* render the steps only when there is at least one cluster available or cluster selection is not required */}
|
|
{((clusterList && clusterList.length > 0) ||
|
|
!stepList.includes(StepNamesMap.SelectCluster)) && (
|
|
<>
|
|
<SelectVendor disabled={disabled}></SelectVendor>
|
|
{(isK8s || !noVendorSelected) && (
|
|
<CheckEnvironment disabled={disabled}></CheckEnvironment>
|
|
)}
|
|
|
|
{provider === ProviderValueMap.Kubernetes && (
|
|
<K8sRunCommand disabled={downstreamDisabled}></K8sRunCommand>
|
|
)}
|
|
|
|
{provider === ProviderValueMap.Docker && (
|
|
<>
|
|
<SpecifyArguments
|
|
disabled={downstreamDisabled}
|
|
></SpecifyArguments>
|
|
<DockerRunCommand
|
|
disabled={downstreamDisabled}
|
|
></DockerRunCommand>
|
|
</>
|
|
)}
|
|
</>
|
|
)}
|
|
{actionSource === 'modal' && (
|
|
// show in cluster create page inner
|
|
<AddedMessage addedCount={addedCount}></AddedMessage>
|
|
)}
|
|
</Container>
|
|
</AddWorkerContext.Provider>
|
|
);
|
|
};
|
|
|
|
export default AddWorkerSteps;
|