fix(striker-ui): add confirm before provision server

main
Tsu-ba-me 3 years ago
parent 5856502c67
commit 3936060208
  1. 506
      striker-ui/components/ProvisionServerDialog.tsx

@ -8,6 +8,7 @@ import {
} from 'react'; } from 'react';
import { Box, Dialog, DialogProps, InputAdornment } from '@mui/material'; import { Box, Dialog, DialogProps, InputAdornment } from '@mui/material';
import { DataSizeUnit } from 'format-data-size'; import { DataSizeUnit } from 'format-data-size';
import { v4 as uuidv4 } from 'uuid';
import Autocomplete from './Autocomplete'; import Autocomplete from './Autocomplete';
import ContainedButton, { ContainedButtonProps } from './ContainedButton'; import ContainedButton, { ContainedButtonProps } from './ContainedButton';
@ -29,6 +30,7 @@ import {
} from '../types/TestInputFunction'; } from '../types/TestInputFunction';
import { BodyText, HeaderText } from './Text'; import { BodyText, HeaderText } from './Text';
import OutlinedLabeledInputWithSelect from './OutlinedLabeledInputWithSelect'; import OutlinedLabeledInputWithSelect from './OutlinedLabeledInputWithSelect';
import ConfirmDialog from './ConfirmDialog';
type InputMessage = Partial<Pick<MessageBoxProps, 'type' | 'text'>>; type InputMessage = Partial<Pick<MessageBoxProps, 'type' | 'text'>>;
@ -119,6 +121,10 @@ type AnvilUUIDMapToData = {
[uuid: string]: OrganizedAnvilDetailMetadataForProvisionServer; [uuid: string]: OrganizedAnvilDetailMetadataForProvisionServer;
}; };
type FileUUIDMapToData = {
[uuid: string]: FileMetadataForProvisionServer;
};
type StorageGroupUUIDMapToData = { type StorageGroupUUIDMapToData = {
[uuid: string]: OrganizedStorageGroupMetadataForProvisionServer; [uuid: string]: OrganizedStorageGroupMetadataForProvisionServer;
}; };
@ -149,13 +155,14 @@ type FilterAnvilsFunction = (
}; };
type VirtualDiskStates = { type VirtualDiskStates = {
maxes: bigint[]; stateIds: string[];
inputMaxes: string[]; inputMaxes: string[];
inputSizeMessages: Array<InputMessage | undefined>; inputSizeMessages: Array<InputMessage | undefined>;
inputSizes: string[]; inputSizes: string[];
inputStorageGroupUUIDMessages: Array<InputMessage | undefined>; inputStorageGroupUUIDMessages: Array<InputMessage | undefined>;
inputStorageGroupUUIDs: string[]; inputStorageGroupUUIDs: string[];
inputUnits: DataSizeUnit[]; inputUnits: DataSizeUnit[];
maxes: bigint[];
sizes: bigint[]; sizes: bigint[];
}; };
@ -428,13 +435,14 @@ const createSelectItemDisplay = ({
); );
const organizeAnvils = (data: AnvilDetailMetadataForProvisionServer[]) => { const organizeAnvils = (data: AnvilDetailMetadataForProvisionServer[]) => {
const anvilFiles: Record<string, FileMetadataForProvisionServer> = {}; const allFiles: Record<string, FileMetadataForProvisionServer> = {};
const result = data.reduce<{ const result = data.reduce<{
anvils: OrganizedAnvilDetailMetadataForProvisionServer[]; anvils: OrganizedAnvilDetailMetadataForProvisionServer[];
anvilSelectItems: SelectItem[]; anvilSelectItems: SelectItem[];
anvilUUIDMapToData: AnvilUUIDMapToData; anvilUUIDMapToData: AnvilUUIDMapToData;
files: FileMetadataForProvisionServer[]; files: FileMetadataForProvisionServer[];
fileSelectItems: SelectItem[]; fileSelectItems: SelectItem[];
fileUUIDMapToData: FileUUIDMapToData;
storageGroups: OrganizedStorageGroupMetadataForProvisionServer[]; storageGroups: OrganizedStorageGroupMetadataForProvisionServer[];
storageGroupSelectItems: SelectItem[]; storageGroupSelectItems: SelectItem[];
storageGroupUUIDMapToData: StorageGroupUUIDMapToData; storageGroupUUIDMapToData: StorageGroupUUIDMapToData;
@ -516,7 +524,7 @@ const organizeAnvils = (data: AnvilDetailMetadataForProvisionServer[]) => {
fileUUIDs.push(fileUUID); fileUUIDs.push(fileUUID);
anvilFiles[fileUUID] = file; allFiles[fileUUID] = file;
}); });
const resultAnvil = { const resultAnvil = {
@ -581,18 +589,20 @@ const organizeAnvils = (data: AnvilDetailMetadataForProvisionServer[]) => {
anvilUUIDMapToData: {}, anvilUUIDMapToData: {},
files: [], files: [],
fileSelectItems: [], fileSelectItems: [],
fileUUIDMapToData: {},
storageGroups: [], storageGroups: [],
storageGroupSelectItems: [], storageGroupSelectItems: [],
storageGroupUUIDMapToData: {}, storageGroupUUIDMapToData: {},
}, },
); );
Object.values(anvilFiles).forEach((distinctFile) => { Object.values(allFiles).forEach((distinctFile) => {
result.files.push(distinctFile); result.files.push(distinctFile);
result.fileSelectItems.push({ result.fileSelectItems.push({
displayValue: distinctFile.fileName, displayValue: distinctFile.fileName,
value: distinctFile.fileUUID, value: distinctFile.fileUUID,
}); });
result.fileUUIDMapToData[distinctFile.fileUUID] = distinctFile;
}); });
return result; return result;
@ -863,7 +873,7 @@ const createVirtualDiskForm = (
return ( return (
<Box <Box
key={`ps-virtual-disk-${vdIndex}`} key={`ps-virtual-disk-${get('stateIds')}`}
sx={{ sx={{
display: 'flex', display: 'flex',
flexDirection: 'column', flexDirection: 'column',
@ -952,54 +962,59 @@ const createVirtualDiskForm = (
const addVirtualDisk = ({ const addVirtualDisk = ({
existingVirtualDisks: virtualDisks = { existingVirtualDisks: virtualDisks = {
maxes: [], stateIds: [],
inputMaxes: [], inputMaxes: [],
inputSizeMessages: [], inputSizeMessages: [],
inputSizes: [], inputSizes: [],
inputStorageGroupUUIDMessages: [], inputStorageGroupUUIDMessages: [],
inputStorageGroupUUIDs: [], inputStorageGroupUUIDs: [],
inputUnits: [], inputUnits: [],
maxes: [],
sizes: [], sizes: [],
}, },
max = BIGINT_ZERO, stateId = uuidv4(),
inputMax = '0', inputMax = '0',
inputSize = '', inputSize = '',
inputSizeMessage = undefined, inputSizeMessage = undefined,
inputStorageGroupUUID = '', inputStorageGroupUUID = '',
inputStorageGroupUUIDMessage = undefined, inputStorageGroupUUIDMessage = undefined,
inputUnit = INITIAL_DATA_SIZE_UNIT, inputUnit = INITIAL_DATA_SIZE_UNIT,
max = BIGINT_ZERO,
setVirtualDisks, setVirtualDisks,
size = BIGINT_ZERO, size = BIGINT_ZERO,
}: { }: {
existingVirtualDisks?: VirtualDiskStates; existingVirtualDisks?: VirtualDiskStates;
max?: bigint; stateId?: string;
inputMax?: string; inputMax?: string;
inputSize?: string; inputSize?: string;
inputSizeMessage?: InputMessage | undefined; inputSizeMessage?: InputMessage | undefined;
inputStorageGroupUUID?: string; inputStorageGroupUUID?: string;
inputStorageGroupUUIDMessage?: InputMessage | undefined; inputStorageGroupUUIDMessage?: InputMessage | undefined;
inputUnit?: DataSizeUnit; inputUnit?: DataSizeUnit;
max?: bigint;
setVirtualDisks?: Dispatch<SetStateAction<VirtualDiskStates>>; setVirtualDisks?: Dispatch<SetStateAction<VirtualDiskStates>>;
size?: bigint; size?: bigint;
} = {}) => { } = {}) => {
const { const {
maxes, stateIds,
inputMaxes, inputMaxes,
inputSizeMessages, inputSizeMessages,
inputSizes, inputSizes,
inputStorageGroupUUIDMessages, inputStorageGroupUUIDMessages,
inputStorageGroupUUIDs, inputStorageGroupUUIDs,
inputUnits, inputUnits,
maxes,
sizes, sizes,
} = virtualDisks; } = virtualDisks;
maxes.push(max); stateIds.push(stateId);
inputMaxes.push(inputMax); inputMaxes.push(inputMax);
inputSizeMessages.push(inputSizeMessage); inputSizeMessages.push(inputSizeMessage);
inputSizes.push(inputSize); inputSizes.push(inputSize);
inputStorageGroupUUIDMessages.push(inputStorageGroupUUIDMessage); inputStorageGroupUUIDMessages.push(inputStorageGroupUUIDMessage);
inputStorageGroupUUIDs.push(inputStorageGroupUUID); inputStorageGroupUUIDs.push(inputStorageGroupUUID);
inputUnits.push(inputUnit); inputUnits.push(inputUnit);
maxes.push(max);
sizes.push(size); sizes.push(size);
setVirtualDisks?.call(null, { ...virtualDisks }); setVirtualDisks?.call(null, { ...virtualDisks });
@ -1020,6 +1035,9 @@ const ProvisionServerDialog = ({
>([]); >([]);
const [anvilUUIDMapToData, setAnvilUUIDMapToData] = const [anvilUUIDMapToData, setAnvilUUIDMapToData] =
useState<AnvilUUIDMapToData>({}); useState<AnvilUUIDMapToData>({});
const [fileUUIDMapToData, setFileUUIDMapToData] = useState<FileUUIDMapToData>(
{},
);
const [storageGroupUUIDMapToData, setStorageGroupUUIDMapToData] = const [storageGroupUUIDMapToData, setStorageGroupUUIDMapToData] =
useState<StorageGroupUUIDMapToData>({}); useState<StorageGroupUUIDMapToData>({});
@ -1084,6 +1102,9 @@ const ProvisionServerDialog = ({
string[] string[]
>([]); >([]);
const [isOpenProvisionConfirmDialog, setIsOpenProvisionConfirmDialog] =
useState<boolean>(false);
const inputTests: InputTestBatches = { const inputTests: InputTestBatches = {
serverName: { serverName: {
defaults: { defaults: {
@ -1433,12 +1454,14 @@ const ProvisionServerDialog = ({
anvilSelectItems: ueAnvilSelectItems, anvilSelectItems: ueAnvilSelectItems,
anvilUUIDMapToData: ueAnvilUUIDMapToData, anvilUUIDMapToData: ueAnvilUUIDMapToData,
fileSelectItems: ueFileSelectItems, fileSelectItems: ueFileSelectItems,
fileUUIDMapToData: ueFileUUIDMapToData,
storageGroupSelectItems: ueStorageGroupSelectItems, storageGroupSelectItems: ueStorageGroupSelectItems,
storageGroupUUIDMapToData: ueStorageGroupUUIDMapToData, storageGroupUUIDMapToData: ueStorageGroupUUIDMapToData,
} = organizeAnvils(data.anvils); } = organizeAnvils(data.anvils);
setAllAnvils(ueAllAnvils); setAllAnvils(ueAllAnvils);
setAnvilUUIDMapToData(ueAnvilUUIDMapToData); setAnvilUUIDMapToData(ueAnvilUUIDMapToData);
setFileUUIDMapToData(ueFileUUIDMapToData);
setStorageGroupUUIDMapToData(ueStorageGroupUUIDMapToData); setStorageGroupUUIDMapToData(ueStorageGroupUUIDMapToData);
setAnvilSelectItems(ueAnvilSelectItems); setAnvilSelectItems(ueAnvilSelectItems);
@ -1463,216 +1486,295 @@ const ProvisionServerDialog = ({
}, [initLimits]); }, [initLimits]);
return ( return (
<Dialog <>
{...{ <Dialog
fullWidth: true, {...{
maxWidth: 'sm', fullWidth: true,
open, maxWidth: 'sm',
PaperComponent: Panel, open,
PaperProps: { sx: { overflow: 'visible' } }, PaperComponent: Panel,
}} PaperProps: { sx: { overflow: 'visible' } },
>
<PanelHeader>
<HeaderText text="Provision a Server" />
</PanelHeader>
<Box
sx={{
display: 'flex',
flexDirection: 'column',
maxHeight: '50vh',
overflowY: 'scroll',
paddingBottom: '.6em',
paddingTop: '.6em',
'& > :not(:first-child)': {
marginTop: '1em',
},
}} }}
> >
<Box sx={{ display: 'flex', flexDirection: 'column' }}> <PanelHeader>
<OutlinedInputWithLabel <HeaderText text="Provision a Server" />
id="ps-server-name" </PanelHeader>
label="Server name" <Box
inputProps={{ sx={{
onChange: ({ target: { value } }) => { display: 'flex',
setInputServerNameValue(value); flexDirection: 'column',
maxHeight: '50vh',
overflowY: 'scroll',
paddingBottom: '.6em',
paddingTop: '.6em',
'& > :not(:first-child)': {
marginTop: '1em',
},
}}
>
<Box sx={{ display: 'flex', flexDirection: 'column' }}>
<OutlinedInputWithLabel
id="ps-server-name"
label="Server name"
inputProps={{
onChange: ({ target: { value } }) => {
setInputServerNameValue(value);
testInput({ inputs: { serverName: { value } } });
},
value: inputServerNameValue,
}}
inputLabelProps={{
isNotifyRequired: inputServerNameValue.length === 0,
}}
messageBoxProps={inputServerNameMessage}
/>
</Box>
{createOutlinedSlider(
'ps-cpu-cores',
'CPU cores',
inputCPUCoresValue,
{
messageBoxProps: inputCPUCoresMessage,
sliderProps: {
onChange: (value) => {
const newCPUCoresValue = value as number;
if (newCPUCoresValue !== inputCPUCoresValue) {
setInputCPUCoresValue(newCPUCoresValue);
const { maxCPUCores: newCPUCoresMax } = updateLimits({
cpuCores: newCPUCoresValue,
});
testInput({
inputs: {
cpuCores: {
max: newCPUCoresMax,
value: newCPUCoresValue,
},
},
});
}
},
max: inputCPUCoresMax,
min: inputCPUCoresMin,
},
},
)}
<OutlinedLabeledInputWithSelect
id="ps-memory"
label="Memory"
messageBoxProps={inputMemoryMessage}
inputWithLabelProps={{
inputProps: {
endAdornment: createMaxValueButton(
`${inputMemoryMax} ${inputMemoryUnit}`,
{
onButtonClick: () => {
setInputMemoryValue(inputMemoryMax);
changeMemory({ cmValue: memoryMax });
},
},
),
onChange: ({ target: { value } }) => {
handleInputMemoryValueChange({ value });
},
type: 'number',
value: inputMemoryValue,
},
inputLabelProps: {
isNotifyRequired: memory === BIGINT_ZERO,
},
}}
selectItems={DATA_SIZE_UNIT_SELECT_ITEMS}
selectWithLabelProps={{
selectProps: {
onChange: ({ target: { value } }) => {
const selectedUnit = value as DataSizeUnit;
testInput({ inputs: { serverName: { value } } }); handleInputMemoryValueChange({ unit: selectedUnit });
},
value: inputMemoryUnit,
}, },
value: inputServerNameValue,
}} }}
/>
{virtualDisks.stateIds.map((vdStateId, vdIndex) =>
createVirtualDiskForm(
virtualDisks,
vdIndex,
setVirtualDisks,
storageGroupSelectItems,
includeStorageGroupUUIDs,
updateLimits,
storageGroupUUIDMapToData,
testInput,
),
)}
<SelectWithLabel
disableItem={(value) => value === inputDriverISOFileUUID}
hideItem={(value) => !includeFileUUIDs.includes(value)}
id="ps-install-image"
inputLabelProps={{ inputLabelProps={{
isNotifyRequired: inputServerNameValue.length === 0, isNotifyRequired: inputInstallISOFileUUID.length === 0,
}} }}
messageBoxProps={inputServerNameMessage} label="Install ISO"
/> messageBoxProps={inputInstallISOMessage}
</Box> selectItems={fileSelectItems}
{createOutlinedSlider('ps-cpu-cores', 'CPU cores', inputCPUCoresValue, { selectProps={{
messageBoxProps: inputCPUCoresMessage,
sliderProps: {
onChange: (value) => {
const newCPUCoresValue = value as number;
if (newCPUCoresValue !== inputCPUCoresValue) {
setInputCPUCoresValue(newCPUCoresValue);
const { maxCPUCores: newCPUCoresMax } = updateLimits({
cpuCores: newCPUCoresValue,
});
testInput({
inputs: {
cpuCores: { max: newCPUCoresMax, value: newCPUCoresValue },
},
});
}
},
max: inputCPUCoresMax,
min: inputCPUCoresMin,
},
})}
<OutlinedLabeledInputWithSelect
id="ps-memory"
label="Memory"
messageBoxProps={inputMemoryMessage}
inputWithLabelProps={{
inputProps: {
endAdornment: createMaxValueButton(
`${inputMemoryMax} ${inputMemoryUnit}`,
{
onButtonClick: () => {
setInputMemoryValue(inputMemoryMax);
changeMemory({ cmValue: memoryMax });
},
},
),
onChange: ({ target: { value } }) => { onChange: ({ target: { value } }) => {
handleInputMemoryValueChange({ value }); const newInstallISOFileUUID = value as string;
handleInputInstallISOFileUUIDChange(newInstallISOFileUUID);
}, },
type: 'number', onClearIndicatorClick: () =>
value: inputMemoryValue, handleInputInstallISOFileUUIDChange(''),
}, value: inputInstallISOFileUUID,
inputLabelProps: { }}
isNotifyRequired: memory === BIGINT_ZERO, />
}, <SelectWithLabel
}} disableItem={(value) => value === inputInstallISOFileUUID}
selectItems={DATA_SIZE_UNIT_SELECT_ITEMS} hideItem={(value) => !includeFileUUIDs.includes(value)}
selectWithLabelProps={{ id="ps-driver-image"
selectProps: { label="Driver ISO"
messageBoxProps={inputDriverISOMessage}
selectItems={fileSelectItems}
selectProps={{
onChange: ({ target: { value } }) => { onChange: ({ target: { value } }) => {
const selectedUnit = value as DataSizeUnit; const newDriverISOFileUUID = value as string;
handleInputMemoryValueChange({ unit: selectedUnit }); handleInputDriverISOFileUUIDChange(newDriverISOFileUUID);
}, },
value: inputMemoryUnit, onClearIndicatorClick: () =>
}, handleInputDriverISOFileUUIDChange(''),
}} value: inputDriverISOFileUUID,
/> }}
{virtualDisks.maxes.map((max, vdIndex) => />
createVirtualDiskForm( <SelectWithLabel
virtualDisks, disableItem={(value) => !includeAnvilUUIDs.includes(value)}
vdIndex, id="ps-anvil"
setVirtualDisks, inputLabelProps={{
storageGroupSelectItems, isNotifyRequired: inputAnvilValue.length === 0,
includeStorageGroupUUIDs, }}
updateLimits, label="Anvil node pair"
storageGroupUUIDMapToData, messageBoxProps={inputAnvilMessage}
testInput, selectItems={anvilSelectItems}
), selectProps={{
)} onChange: ({ target: { value } }) => {
<SelectWithLabel const newAnvilUUID: string = value as string;
disableItem={(value) => value === inputDriverISOFileUUID}
hideItem={(value) => !includeFileUUIDs.includes(value)}
id="ps-install-image"
inputLabelProps={{
isNotifyRequired: inputInstallISOFileUUID.length === 0,
}}
label="Install ISO"
messageBoxProps={inputInstallISOMessage}
selectItems={fileSelectItems}
selectProps={{
onChange: ({ target: { value } }) => {
const newInstallISOFileUUID = value as string;
handleInputInstallISOFileUUIDChange(newInstallISOFileUUID);
},
onClearIndicatorClick: () =>
handleInputInstallISOFileUUIDChange(''),
value: inputInstallISOFileUUID,
}}
/>
<SelectWithLabel
disableItem={(value) => value === inputInstallISOFileUUID}
hideItem={(value) => !includeFileUUIDs.includes(value)}
id="ps-driver-image"
label="Driver ISO"
messageBoxProps={inputDriverISOMessage}
selectItems={fileSelectItems}
selectProps={{
onChange: ({ target: { value } }) => {
const newDriverISOFileUUID = value as string;
handleInputDriverISOFileUUIDChange(newDriverISOFileUUID);
},
onClearIndicatorClick: () => handleInputDriverISOFileUUIDChange(''),
value: inputDriverISOFileUUID,
}}
/>
<SelectWithLabel
disableItem={(value) => !includeAnvilUUIDs.includes(value)}
id="ps-anvil"
inputLabelProps={{
isNotifyRequired: inputAnvilValue.length === 0,
}}
label="Anvil node pair"
messageBoxProps={inputAnvilMessage}
selectItems={anvilSelectItems}
selectProps={{
onChange: ({ target: { value } }) => {
const newAnvilUUID: string = value as string;
handleInputAnvilValueChange(newAnvilUUID); handleInputAnvilValueChange(newAnvilUUID);
}, },
onClearIndicatorClick: () => handleInputAnvilValueChange(''), onClearIndicatorClick: () => handleInputAnvilValueChange(''),
renderValue: (value) => { renderValue: (value) => {
const { anvilName: rvAnvilName = `Unknown ${value}` } = const { anvilName: rvAnvilName = `Unknown ${value}` } =
anvilUUIDMapToData[value as string] ?? {}; anvilUUIDMapToData[value as string] ?? {};
return rvAnvilName; return rvAnvilName;
}, },
value: inputAnvilValue, value: inputAnvilValue,
}}
/>
<Autocomplete
id="ps-optimize-for-os"
extendRenderInput={({ inputLabelProps = {} }) => {
inputLabelProps.isNotifyRequired =
inputOptimizeForOSValue === null;
}}
isOptionEqualToValue={(option, value) => option.key === value.key}
label="Optimize for OS"
messageBoxProps={inputOptimizeForOSMessage}
noOptionsText="No matching OS"
onChange={(event, value) => {
setInputOptimizeForOSValue(value);
}}
openOnFocus
options={osAutocompleteOptions}
value={inputOptimizeForOSValue}
/>
</Box>
<Box
sx={{
display: 'flex',
flexDirection: 'row',
justifyContent: 'flex-end',
marginTop: '1em',
width: '100%',
}} }}
/> >
<Autocomplete <ContainedButton
id="ps-optimize-for-os" disabled={!testInput({ isIgnoreOnCallbacks: true })}
extendRenderInput={({ inputLabelProps = {} }) => { onClick={() => {
inputLabelProps.isNotifyRequired = inputOptimizeForOSValue === null; setIsOpenProvisionConfirmDialog(true);
}}
>
Provision
</ContainedButton>
</Box>
</Dialog>
{isOpenProvisionConfirmDialog && (
<ConfirmDialog
actionProceedText="Provision"
content={
<Box sx={{ display: 'flex', flexDirection: 'column' }}>
<BodyText
text={`Server ${inputServerNameValue} will be created on anvil node pair ${anvilUUIDMapToData[inputAnvilValue].anvilName} with the following properties:`}
/>
<BodyText text={`CPU: ${inputCPUCoresValue} core(s)`} />
<BodyText
text={`Memory: ${inputMemoryValue} ${inputMemoryUnit}`}
/>
{virtualDisks.stateIds.map((vdStateId, vdIndex) => (
<BodyText
key={`ps-virtual-disk-${vdStateId}-summary`}
text={`Virtual disk ${vdIndex}: ${
virtualDisks.inputSizes[vdIndex]
} ${virtualDisks.inputUnits[vdIndex]} on ${
storageGroupUUIDMapToData[
virtualDisks.inputStorageGroupUUIDs[vdIndex]
].storageGroupName
}`}
/>
))}
<BodyText
text={`Install ISO: ${fileUUIDMapToData[inputInstallISOFileUUID].fileName}`}
/>
<BodyText
text={`Driver ISO: ${
fileUUIDMapToData[inputDriverISOFileUUID]?.fileName ?? 'none'
}`}
/>
<BodyText
text={`Optimize for OS: ${inputOptimizeForOSValue?.label}`}
/>
</Box>
}
dialogProps={{ open: isOpenProvisionConfirmDialog }}
onCancel={() => {
setIsOpenProvisionConfirmDialog(false);
}} }}
label="Optimize for OS" onProceed={() => {
messageBoxProps={inputOptimizeForOSMessage} // const requestBody = {
noOptionsText="No matching OS" // serverName: inputServerNameValue,
onChange={(event, value) => { // cpuCores: inputCPUCoresValue,
setInputOptimizeForOSValue(value); // memory,
// virtualDisks: virtualDisks.stateIds.map((vdStateId, vdIndex) => ({
// size: virtualDisks.sizes[vdIndex],
// storageGroupUUID: virtualDisks.inputStorageGroupUUIDs[vdIndex],
// })),
// installISOFileUUID: inputInstallISOFileUUID,
// driverISOFileUUID: inputDriverISOFileUUID,
// anvilUUID: inputAnvilValue,
// optimizeForOS: inputOptimizeForOSValue?.key,
// };
setIsOpenProvisionConfirmDialog(false);
}} }}
openOnFocus titleText={`Provision ${inputServerNameValue}?`}
options={osAutocompleteOptions}
value={inputOptimizeForOSValue}
/> />
</Box> )}
<Box </>
sx={{
display: 'flex',
flexDirection: 'row',
justifyContent: 'flex-end',
marginTop: '1em',
width: '100%',
}}
>
<ContainedButton disabled={!testInput({ isIgnoreOnCallbacks: true })}>
Provision
</ContainedButton>
</Box>
</Dialog>
); );
}; };

Loading…
Cancel
Save