Skip to content

Commit 7796df5

Browse files
authored
Reset wizard state when a different region is selected (#40)
* Extract wizard state init into a function * Init wizard state when changing region in wizard * Remove keypair initialization from Cluster section * Initialize keypair in HeadNode section
1 parent 56b3362 commit 7796df5

File tree

2 files changed

+81
-66
lines changed

2 files changed

+81
-66
lines changed

frontend/src/old-pages/Configure/Cluster.tsx

Lines changed: 61 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import {
2323
CheckboxProps,
2424
Container,
2525
FormField,
26-
Header,
2726
Select,
2827
SpaceBetween,
2928
} from '@cloudscape-design/components'
@@ -38,7 +37,10 @@ import {useFeatureFlag} from '../../feature-flags/useFeatureFlag'
3837
import {createComputeResource as singleCreate} from './Queues/SingleInstanceComputeResource'
3938
import {createComputeResource as multiCreate} from './Queues/MultiInstanceComputeResource'
4039
import {MultiUser, multiUserValidate} from './MultiUser'
41-
import {NonCancelableEventHandler} from '@cloudscape-design/components/internal/events'
40+
import {
41+
NonCancelableCustomEvent,
42+
NonCancelableEventHandler,
43+
} from '@cloudscape-design/components/internal/events'
4244
import TitleDescriptionHelpPanel from '../../components/help-panel/TitleDescriptionHelpPanel'
4345
import {useHelpPanel} from '../../components/help-panel/HelpPanel'
4446
import {useCallback, useMemo} from 'react'
@@ -47,6 +49,7 @@ import {SelectProps} from '@cloudscape-design/components/select/interfaces'
4749

4850
// Constants
4951
const errorsPath = ['app', 'wizard', 'errors', 'cluster']
52+
const configPath = ['app', 'wizard', 'config']
5053

5154
const selectQueues = (state: any) =>
5255
getState(state, ['app', 'wizard', 'config', 'Scheduling', 'SlurmQueues'])
@@ -112,23 +115,34 @@ function RegionSelect() {
112115
const {t} = useTranslation()
113116
const region =
114117
useState(['app', 'wizard', 'config', 'Region']) || 'Please select a region.'
115-
const queues = useSelector(selectQueues)
116118
const editing = useState(['app', 'wizard', 'editing'])
119+
const config = useState(configPath)
120+
const isMultipleInstanceTypesActive = useFeatureFlag(
121+
'queues_multiple_instance_types',
122+
)
117123

118-
const handleChange = ({detail}: any) => {
119-
const chosenRegion =
120-
detail.selectedOption.value === 'Default'
121-
? null
122-
: detail.selectedOption.value
123-
LoadAwsConfig(chosenRegion)
124-
setState(['app', 'wizard', 'vpc'], null)
125-
setState(['app', 'wizard', 'headNode', 'subnet'], null)
126-
if (queues)
127-
queues.forEach((_queue: any, i: any) => {
128-
clearState(['app', 'wizard', 'queues', i, 'subnet'])
129-
})
130-
setState(['app', 'wizard', 'config', 'Region'], chosenRegion)
131-
}
124+
const handleChange = useCallback(
125+
({detail}: NonCancelableCustomEvent<SelectProps.ChangeDetail>) => {
126+
const chosenRegion = detail.selectedOption.value
127+
128+
if (!chosenRegion) return
129+
130+
/**
131+
* Clear wizard state
132+
*
133+
* We keep the part of the state that is necessary
134+
* to continue with the experience
135+
*/
136+
const {page, source, clusterName, errors} =
137+
getState(['app', 'wizard']) || {}
138+
setState(['app', 'wizard'], {page, source, clusterName, errors})
139+
140+
initWizardState(config, chosenRegion, isMultipleInstanceTypesActive)
141+
142+
LoadAwsConfig(chosenRegion)
143+
},
144+
[config, isMultipleInstanceTypesActive],
145+
)
132146

133147
const supportedRegions = [
134148
'af-south-1',
@@ -181,6 +195,35 @@ function RegionSelect() {
181195
)
182196
}
183197

198+
function initWizardState(
199+
config: Record<string, unknown>,
200+
region: string,
201+
isMultipleInstanceTypesActive: boolean,
202+
) {
203+
const customAMIEnabled = getIn(config, ['Image', 'CustomAmi']) ? true : false
204+
setState(['app', 'wizard', 'customAMI', 'enabled'], customAMIEnabled)
205+
setState([...configPath, 'HeadNode', 'InstanceType'], 't2.micro')
206+
setState([...configPath, 'Scheduling', 'Scheduler'], 'slurm')
207+
setState([...configPath, 'Region'], region)
208+
setState([...configPath, 'Image', 'Os'], 'alinux2')
209+
setState(
210+
[...configPath, 'Scheduling', 'SlurmQueues'],
211+
[
212+
{
213+
Name: 'queue0',
214+
AllocationStrategy: isMultipleInstanceTypesActive
215+
? 'lowest-price'
216+
: undefined,
217+
ComputeResources: [
218+
isMultipleInstanceTypesActive
219+
? multiCreate(0, 0)
220+
: singleCreate(0, 0),
221+
],
222+
},
223+
],
224+
)
225+
}
226+
184227
function OsSelect() {
185228
const {t} = useTranslation()
186229
const oses: [string, string][] = [
@@ -341,7 +384,6 @@ function VpcSelect() {
341384
function Cluster() {
342385
const {t} = useTranslation()
343386
const editing = useState(['app', 'wizard', 'editing'])
344-
const configPath = ['app', 'wizard', 'config']
345387
let config = useState(configPath)
346388
let clusterConfig = useState(['app', 'wizard', 'clusterConfigYaml']) || ''
347389
let wizardLoaded = useState(['app', 'wizard', 'loaded'])
@@ -357,7 +399,6 @@ function Cluster() {
357399
useHelpPanel(<ClusterPropertiesHelpPanel />)
358400

359401
React.useEffect(() => {
360-
const configPath = ['app', 'wizard', 'config']
361402
// Don't overwrite the config if we go back, still gets overwritten
362403
// after going forward so need to consider better way of handling this
363404
if (clusterConfig) return
@@ -366,46 +407,12 @@ function Cluster() {
366407
if (!wizardLoaded) {
367408
setState(['app', 'wizard', 'loaded'], true)
368409
if (!config) {
369-
const customAMIEnabled = getIn(config, ['Image', 'CustomAmi'])
370-
? true
371-
: false
372-
setState(['app', 'wizard', 'customAMI', 'enabled'], customAMIEnabled)
373-
setState([...configPath, 'HeadNode', 'InstanceType'], 't2.micro')
374-
setState([...configPath, 'Scheduling', 'Scheduler'], 'slurm')
375-
setState([...configPath, 'Region'], region)
376-
setState([...configPath, 'Image', 'Os'], 'alinux2')
377-
setState(
378-
[...configPath, 'Scheduling', 'SlurmQueues'],
379-
[
380-
{
381-
Name: 'queue0',
382-
AllocationStrategy: isMultipleInstanceTypesActive
383-
? 'lowest-price'
384-
: undefined,
385-
ComputeResources: [
386-
isMultipleInstanceTypesActive
387-
? multiCreate(0, 0)
388-
: singleCreate(0, 0),
389-
],
390-
},
391-
],
392-
)
393-
}
394-
}
395-
396-
// Load these values when we get a new config as well (e.g. changing region)
397-
if (awsConfig && awsConfig.keypairs && awsConfig.keypairs.length > 0) {
398-
const keypairs = getState(['aws', 'keypairs']) || []
399-
const keypairNames = new Set(keypairs.map((kp: any) => kp.KeyName))
400-
const headNodeKPPath = [...configPath, 'HeadNode', 'Ssh', 'KeyName']
401-
if (keypairs.length > 0 && !keypairNames.has(getState(headNodeKPPath))) {
402-
setState(headNodeKPPath, awsConfig.keypairs[0].KeyName)
410+
initWizardState(config, region, isMultipleInstanceTypesActive)
403411
}
404412
}
405413
}, [
406414
region,
407415
config,
408-
awsConfig,
409416
clusterConfig,
410417
wizardLoaded,
411418
isMultipleInstanceTypesActive,

frontend/src/old-pages/Configure/HeadNode.tsx

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import i18next from 'i18next'
1515
import {Trans, useTranslation} from 'react-i18next'
1616
import {useSelector} from 'react-redux'
1717
import {findFirst, getIn} from '../../util'
18+
import safeGet from 'lodash/get'
1819

1920
// UI Elements
2021
import {
@@ -61,6 +62,7 @@ import {useHelpPanel} from '../../components/help-panel/HelpPanel'
6162
// Constants
6263
const headNodePath = ['app', 'wizard', 'config', 'HeadNode']
6364
const errorsPath = ['app', 'wizard', 'errors', 'headNode']
65+
const keypairPath = [...headNodePath, 'Ssh', 'KeyName']
6466

6567
function headNodeValidate() {
6668
const subnetPath = [...headNodePath, 'Networking', 'SubnetId']
@@ -210,28 +212,34 @@ function enableSsm(enable: any) {
210212
}
211213
}
212214
}
215+
const setKeyPair = (kpValue?: string) => {
216+
if (kpValue) setState(keypairPath, kpValue)
217+
else {
218+
clearState([...headNodePath, 'Ssh'])
219+
enableSsm(true)
220+
}
221+
}
213222

214223
function KeypairSelect() {
215224
const {t} = useTranslation()
216-
const keypairs = useState(['aws', 'keypairs']) || []
217-
const keypairPath = [...headNodePath, 'Ssh', 'KeyName']
218-
const keypair = useState(keypairPath) || ''
225+
const keypairsInAWSConfig = useState(['aws', 'keypairs'])
226+
const selectedKeypairName = useState(keypairPath)
219227
const editing = useState(['app', 'wizard', 'editing'])
220228
const keypairToOption = (kp: any) => {
221229
if (kp === 'None' || kp === null || kp === undefined)
222230
return {label: 'None', value: null}
223231
else return {label: kp.KeyName, value: kp.KeyName}
224232
}
225233

226-
const keypairsWithNone = ['None', ...keypairs]
234+
const keypairsWithNone = ['None', ...keypairsInAWSConfig]
227235

228-
const setKeyPair = (kpValue: any) => {
229-
if (kpValue) setState(keypairPath, kpValue)
230-
else {
231-
clearState([...headNodePath, 'Ssh'])
232-
enableSsm(true)
236+
React.useEffect(() => {
237+
const firstAvailableKeypair = safeGet(keypairsInAWSConfig, ['0', 'KeyName'])
238+
if (!selectedKeypairName && firstAvailableKeypair) {
239+
setKeyPair(firstAvailableKeypair)
233240
}
234-
}
241+
// eslint-disable-next-line react-hooks/exhaustive-deps
242+
}, [keypairsInAWSConfig])
235243

236244
return (
237245
<FormField
@@ -241,8 +249,8 @@ function KeypairSelect() {
241249
<Select
242250
disabled={editing}
243251
selectedOption={keypairToOption(
244-
findFirst(keypairs, (x: any) => {
245-
return x.KeyName === keypair
252+
findFirst(keypairsInAWSConfig, (x: any) => {
253+
return x.KeyName === selectedKeypairName
246254
}),
247255
)}
248256
onChange={({detail}) => {

0 commit comments

Comments
 (0)