Skip to content
This repository was archived by the owner on Mar 13, 2023. It is now read-only.

Commit e6d4e82

Browse files
BarcoMasileMarco Basile
and
Marco Basile
authored
Fixed OS select dropdown + switched to FormField for consistency with the rest of wizard (#546)
* fixed rendering bug, improved `itemToOption` and added tests * removed useless semi-colon * moved dropdowns out of header actions and adopted a formfield for consistency with the rest of the wizard (fixes also layout issue) --------- Co-authored-by: Marco Basile <[email protected]>
1 parent 71e4902 commit e6d4e82

File tree

2 files changed

+107
-71
lines changed

2 files changed

+107
-71
lines changed

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

+72-71
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ import {MultiUser, multiUserValidate} from './MultiUser'
4141
import {NonCancelableEventHandler} from '@cloudscape-design/components/internal/events'
4242
import TitleDescriptionHelpPanel from '../../components/help-panel/TitleDescriptionHelpPanel'
4343
import {useHelpPanel} from '../../components/help-panel/HelpPanel'
44+
import {useCallback, useMemo} from 'react'
45+
import {OptionDefinition} from '@cloudscape-design/components/internal/components/option/interfaces'
46+
import {SelectProps} from '@cloudscape-design/components/select/interfaces'
4447

4548
// Constants
4649
const errorsPath = ['app', 'wizard', 'errors', 'cluster']
@@ -89,12 +92,20 @@ function clusterValidate() {
8992
return valid
9093
}
9194

92-
function itemToOption(item: string | null) {
93-
if (!item) return
94-
return {
95-
label: item,
96-
value: item,
95+
function itemToOption(
96+
item: string | [string, string] | null,
97+
): SelectProps.Option | null {
98+
if (!item) return null
99+
let label, value
100+
101+
if (typeof item == 'string') {
102+
label = item
103+
value = item
104+
} else {
105+
;[value, label] = item
97106
}
107+
108+
return {label, value}
98109
}
99110

100111
function RegionSelect() {
@@ -148,29 +159,24 @@ function RegionSelect() {
148159

149160
return (
150161
<>
151-
<Header
152-
// @ts-expect-error TS(2322) FIXME: Type '"h4"' is not assignable to type 'Variant | u... Remove this comment to see the full error message
153-
variant="h4"
162+
<FormField
163+
label={t('wizard.cluster.region.label')}
154164
description={t('wizard.cluster.region.description')}
155-
actions={
156-
<Select
157-
disabled={editing}
158-
// @ts-expect-error TS(2322) FIXME: Type '{ label: Element; value: string; } | undefin... Remove this comment to see the full error message
159-
selectedOption={itemToOption(
160-
// @ts-expect-error TS(2345) FIXME: Argument of type 'string[] | undefined' is not ass... Remove this comment to see the full error message
161-
findFirst(supportedRegions, (r: string) => {
162-
return r === region
163-
}),
164-
)}
165-
onChange={handleChange}
166-
// @ts-expect-error TS(2322) FIXME: Type '({ label: Element; value: string; } | undefi... Remove this comment to see the full error message
167-
options={supportedRegions.map(itemToOption)}
168-
selectedAriaLabel={t('wizard.cluster.region.selectedAriaLabel')}
169-
/>
170-
}
171165
>
172-
<Trans i18nKey="wizard.cluster.region.label" />
173-
</Header>
166+
<Select
167+
disabled={editing}
168+
selectedOption={itemToOption(
169+
// @ts-expect-error TS(2345) FIXME: Argument of type 'string[] | undefined' is not ass... Remove this comment to see the full error message
170+
findFirst(supportedRegions, (r: string) => {
171+
return r === region
172+
}),
173+
)}
174+
onChange={handleChange}
175+
// @ts-expect-error TS(2322) FIXME: Type '({ label: Element; value: string; } | undefi... Remove this comment to see the full error message
176+
options={supportedRegions.map(itemToOption)}
177+
selectedAriaLabel={t('wizard.cluster.region.selectedAriaLabel')}
178+
/>
179+
</FormField>
174180
</>
175181
)
176182
}
@@ -186,33 +192,33 @@ function OsSelect() {
186192
const osPath = ['app', 'wizard', 'config', 'Image', 'Os']
187193
const os = useState(osPath) || 'alinux2'
188194
const editing = useState(['app', 'wizard', 'editing'])
195+
196+
const osesOptions = useMemo(() => oses.map(itemToOption), [oses])
197+
198+
const selectedOs: OptionDefinition | null = useMemo(() => {
199+
const selectedOsTuple = findFirst(oses, (x: any) => x[0] === os) || null
200+
return itemToOption(selectedOsTuple)
201+
}, [os, oses])
202+
203+
const handleChange = useCallback(({detail}: any) => {
204+
setState(osPath, detail.selectedOption.value)
205+
}, [])
206+
189207
return (
190208
<>
191-
<Header
192-
// @ts-expect-error TS(2322) FIXME: Type '"h4"' is not assignable to type 'Variant | u... Remove this comment to see the full error message
193-
variant="h4"
209+
<FormField
210+
label={t('wizard.cluster.os.label')}
194211
description={t('wizard.cluster.os.description')}
195-
actions={
196-
<Select
197-
disabled={editing}
198-
// @ts-expect-error TS(2322) FIXME: Type '{ label: Element; value: string; } | undefin... Remove this comment to see the full error message
199-
selectedOption={itemToOption(
200-
// @ts-expect-error TS(2345) FIXME: Argument of type '[string, string] | undefined' is... Remove this comment to see the full error message
201-
findFirst(oses, (x: any) => {
202-
return x[0] === os
203-
}),
204-
)}
205-
onChange={({detail}) =>
206-
setState(osPath, detail.selectedOption.value)
207-
}
208-
// @ts-expect-error TS(2322) FIXME: Type '({ label: Element; value: string; } | undefi... Remove this comment to see the full error message
209-
options={oses.map(itemToOption)}
210-
selectedAriaLabel={t('wizard.cluster.os.selectedAriaLabel')}
211-
/>
212-
}
213212
>
214-
<Trans i18nKey="wizard.cluster.os.label" />
215-
</Header>
213+
<Select
214+
disabled={editing}
215+
selectedOption={selectedOs}
216+
onChange={handleChange}
217+
// @ts-expect-error TS(2322) FIXME: Type '({ label: Element; value: string; } | undefi... Remove this comment to see the full error message
218+
options={osesOptions}
219+
selectedAriaLabel={t('wizard.cluster.os.selectedAriaLabel')}
220+
/>
221+
</FormField>
216222
</>
217223
)
218224
}
@@ -311,29 +317,24 @@ function VpcSelect() {
311317
}
312318

313319
return (
314-
<Header
315-
// @ts-expect-error TS(2322) FIXME: Type '"h4"' is not assignable to type 'Variant | u... Remove this comment to see the full error message
316-
variant="h4"
320+
<FormField
321+
errorText={error}
317322
description={t('wizard.cluster.vpc.description')}
318-
actions={
319-
<FormField errorText={error}>
320-
<Select
321-
disabled={editing}
322-
// @ts-expect-error TS(2322) FIXME: Type '{ label: JSX.Element; value: any; }' is not ... Remove this comment to see the full error message
323-
selectedOption={vpcToDisplayOption(
324-
findFirst(vpcs, x => x.VpcId === vpc),
325-
)}
326-
onChange={({detail}) => {
327-
setVpc(detail.selectedOption.value)
328-
}}
329-
options={vpcs.map(vpcToOption)}
330-
selectedAriaLabel={t('wizard.cluster.vpc.selectedAriaLabel')}
331-
/>
332-
</FormField>
333-
}
323+
label={t('wizard.cluster.vpc.label')}
334324
>
335-
<Trans i18nKey="wizard.cluster.vpc.label" />
336-
</Header>
325+
<Select
326+
disabled={editing}
327+
// @ts-expect-error TS(2322) FIXME: Type '{ label: JSX.Element; value: any; }' is not ... Remove this comment to see the full error message
328+
selectedOption={vpcToDisplayOption(
329+
findFirst(vpcs, x => x.VpcId === vpc),
330+
)}
331+
onChange={({detail}) => {
332+
setVpc(detail.selectedOption.value)
333+
}}
334+
options={vpcs.map(vpcToOption)}
335+
selectedAriaLabel={t('wizard.cluster.vpc.selectedAriaLabel')}
336+
/>
337+
</FormField>
337338
)
338339
}
339340

@@ -483,4 +484,4 @@ const ClusterPropertiesHelpPanel = () => {
483484
)
484485
}
485486

486-
export {Cluster, clusterValidate, ClusterPropertiesHelpPanel}
487+
export {Cluster, clusterValidate, ClusterPropertiesHelpPanel, itemToOption}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import {describe} from '@jest/globals'
2+
import {itemToOption} from '../Cluster'
3+
4+
describe('Given a selection item', () => {
5+
describe('when the item is a string', () => {
6+
it('should return a valid SelectProps.Option', () => {
7+
const item = 'option-value'
8+
const expectedOption = {label: 'option-value', value: 'option-value'}
9+
10+
const option = itemToOption(item)
11+
12+
expect(option).toEqual(expectedOption)
13+
})
14+
})
15+
16+
describe('when the item is a tuple of 2 strings', () => {
17+
it('should return a valid SelectProps.Option', () => {
18+
const item = ['option-value', 'option-label'] as [string, string]
19+
const expectedOption = {label: 'option-label', value: 'option-value'}
20+
21+
const option = itemToOption(item)
22+
23+
expect(option).toEqual(expectedOption)
24+
})
25+
})
26+
27+
describe('when the item is null', () => {
28+
const item = null
29+
30+
it('should return null', () => {
31+
const option = itemToOption(item)
32+
expect(option).toBeNull()
33+
})
34+
})
35+
})

0 commit comments

Comments
 (0)