Skip to content

Commit 5796354

Browse files
feat(pci-instances): improve region selection handling
ref: #TAPC-4573 Signed-off-by: Lauren Olivier <[email protected]>
1 parent 3bee8a3 commit 5796354

File tree

12 files changed

+220
-112
lines changed

12 files changed

+220
-112
lines changed

packages/manager/apps/pci-instances/src/__mocks__/instance/constants.ts

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,9 @@ export const mockedInstancesCatalogEntity: TInstancesCatalog = {
322322
export const mockedLocalizationsData: TRegionData[] = [
323323
{
324324
city: 'regions:manager_components_region_GRA',
325-
region: 'GRA',
325+
macroRegion: 'GRA',
326+
microRegion: 'GRA11',
327+
datacenterDetails: 'GRA',
326328
countryCode: 'fr',
327329
deploymentMode: 'region',
328330
microRegions: [
@@ -342,7 +344,9 @@ export const mockedLocalizationsData: TRegionData[] = [
342344
},
343345
{
344346
city: 'regions:manager_components_region_PAR',
345-
region: 'EU-WEST-PAR',
347+
macroRegion: 'PAR',
348+
microRegion: 'EU-WEST-PAR',
349+
datacenterDetails: 'EU-WEST-PAR',
346350
countryCode: 'fr',
347351
deploymentMode: 'region-3-az',
348352
microRegions: [
@@ -359,7 +363,9 @@ export const mockedLocalizationsData: TRegionData[] = [
359363
export const mockedLocalizationsDataForSelectedDeploymentZoneAndAllContinents: TRegionData[] = [
360364
{
361365
city: 'regions:manager_components_region_GRA',
362-
region: 'GRA',
366+
macroRegion: 'GRA',
367+
microRegion: 'GRA11',
368+
datacenterDetails: 'GRA',
363369
countryCode: 'fr',
364370
deploymentMode: 'region',
365371
microRegions: [
@@ -379,7 +385,9 @@ export const mockedLocalizationsDataForSelectedDeploymentZoneAndAllContinents: T
379385
},
380386
{
381387
city: 'regions:manager_components_region_BHS',
382-
region: 'BHS5',
388+
macroRegion: 'BHS',
389+
microRegion: 'BHS5',
390+
datacenterDetails: 'BHS5',
383391
countryCode: 'ca',
384392
deploymentMode: 'region',
385393
microRegions: [
@@ -393,7 +401,9 @@ export const mockedLocalizationsDataForSelectedDeploymentZoneAndAllContinents: T
393401
},
394402
{
395403
city: 'regions:manager_components_region_PAR',
396-
region: 'EU-WEST-PAR',
404+
macroRegion: 'PAR',
405+
microRegion: 'EU-WEST-PAR',
406+
datacenterDetails: 'EU-WEST-PAR',
397407
countryCode: 'fr',
398408
deploymentMode: 'region-3-az',
399409
microRegions: [
@@ -410,7 +420,9 @@ export const mockedLocalizationsDataForSelectedDeploymentZoneAndAllContinents: T
410420
export const mockedLocalizationsDataForNoneDeploymentZoneAndAllContinents: TRegionData[] = [
411421
{
412422
city: 'regions:manager_components_region_GRA',
413-
region: 'GRA',
423+
macroRegion: 'GRA',
424+
microRegion: 'GRA11',
425+
datacenterDetails: 'GRA',
414426
countryCode: 'fr',
415427
deploymentMode: 'region',
416428
microRegions: [
@@ -430,7 +442,9 @@ export const mockedLocalizationsDataForNoneDeploymentZoneAndAllContinents: TRegi
430442
},
431443
{
432444
city: 'regions:manager_components_region_BHS',
433-
region: 'BHS5',
445+
macroRegion: 'BHS',
446+
microRegion: 'BHS5',
447+
datacenterDetails: 'BHS5',
434448
countryCode: 'ca',
435449
deploymentMode: 'region',
436450
microRegions: [
@@ -444,7 +458,9 @@ export const mockedLocalizationsDataForNoneDeploymentZoneAndAllContinents: TRegi
444458
},
445459
{
446460
city: 'regions:manager_components_region_MIL',
447-
region: 'EU-SOUTH-LZ-MIL-A',
461+
macroRegion: 'EU-SOUTH-LZ-MIL',
462+
microRegion: 'EU-SOUTH-LZ-MIL-A',
463+
datacenterDetails: 'EU-SOUTH-LZ-MIL-A',
448464
countryCode: 'it',
449465
deploymentMode: 'localzone',
450466
microRegions: [
@@ -462,7 +478,9 @@ export const mockedLocalizationsDataForNoneDeploymentZoneAndAllContinents: TRegi
462478
},
463479
{
464480
city: 'regions:manager_components_region_PAR',
465-
region: 'EU-WEST-PAR',
481+
macroRegion: 'PAR',
482+
microRegion: 'EU-WEST-PAR',
483+
datacenterDetails: 'EU-WEST-PAR',
466484
countryCode: 'fr',
467485
deploymentMode: 'region-3-az',
468486
microRegions: [

packages/manager/apps/pci-instances/src/components/localizationCard/LocalizationCard.component.tsx

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,20 @@ import { TDeploymentMode } from '@/types/instance/common.type';
66
import { PciCard } from '@/components/pciCard/PciCard.component';
77

88
type TLocalizationCardProps = {
9-
title: string;
10-
region: string;
9+
city: string;
10+
datacenterDetails: string;
11+
macroRegion: string;
1112
countryCode: TCountryIsoCode | null;
1213
deploymentMode: TDeploymentMode;
1314
isSelected: boolean;
1415
disabled: boolean;
15-
onSelect: (region: string) => void;
16+
onSelect: () => void;
1617
};
1718

1819
export const LocalizationCard = ({
19-
title,
20-
region,
20+
city,
21+
datacenterDetails,
22+
macroRegion,
2123
countryCode,
2224
deploymentMode,
2325
isSelected,
@@ -28,19 +30,19 @@ export const LocalizationCard = ({
2830
selectable
2931
compact
3032
selected={isSelected}
31-
onClick={() => onSelect(region)}
33+
onClick={onSelect}
3234
disabled={disabled}
3335
>
3436
<PciCard.Header>
35-
<Radio value={region} disabled={disabled}>
37+
<Radio value={macroRegion} disabled={disabled}>
3638
<RadioControl />
3739
<RadioLabel className="font-bold text-lg text-[--ods-color-heading] gap-x-4 flex items-center">
3840
{countryCode && <Flag isoCode={countryCode} />}
39-
{title}
41+
{city}
4042
</RadioLabel>
4143
</Radio>
4244
<div className="flex items-center justify-between gap-4 w-full">
43-
<Text>{region}</Text>
45+
<Text>{datacenterDetails}</Text>
4446
<DeploymentModeBadge mode={deploymentMode} />
4547
</div>
4648
</PciCard.Header>

packages/manager/apps/pci-instances/src/pages/instances/create/components/CreationCart.component.tsx

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,42 @@ import {
88
TCartItem,
99
TCartItemDetail,
1010
} from '@/components/cart/Cart.component';
11+
import { deps } from '@/deps/deps';
12+
import { selectLocalisationDetails } from '../view-models/cartViewModel';
13+
import { useProjectId } from '@/hooks/project/useProjectId';
1114

1215
export const CreationCart = () => {
1316
const { t } = useTranslation('common');
17+
const projectId = useProjectId();
1418
const { control } = useFormContext<TInstanceCreationForm>();
15-
const [name, macroRegion, availabilityZone] = useWatch({
19+
const [name, macroRegion, microRegion, availabilityZone] = useWatch({
1620
control,
17-
name: ['name', 'macroRegion', 'availabilityZone'],
21+
name: ['name', 'macroRegion', 'microRegion', 'availabilityZone'],
1822
});
1923

24+
const localizationDetails = selectLocalisationDetails(deps)(
25+
projectId,
26+
macroRegion,
27+
microRegion,
28+
availabilityZone,
29+
);
30+
2031
const itemDetails: TCartItemDetail[] = useMemo(() => {
21-
const regionDetails = {
22-
name: t('localisation'),
23-
description: (
24-
<Text preset="heading-6" className="text-[--ods-color-heading]">
25-
{macroRegion} {availabilityZone && `(${availabilityZone})`}
26-
</Text>
27-
),
28-
};
32+
const regionDetails = localizationDetails
33+
? [
34+
{
35+
name: t('localisation'),
36+
description: (
37+
<Text preset="heading-6" className="text-[--ods-color-heading]">
38+
{`${localizationDetails.city} (${localizationDetails.datacenterDetails})`}
39+
</Text>
40+
),
41+
},
42+
]
43+
: [];
2944

30-
return [regionDetails];
31-
}, [macroRegion, availabilityZone, t]);
45+
return [...regionDetails];
46+
}, [t, localizationDetails]);
3247

3348
const cartItems: TCartItem[] = useMemo(
3449
() => [

packages/manager/apps/pci-instances/src/pages/instances/create/components/availabilityZoneSelection/AvailabilityZoneSelection.component.tsx

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,9 @@ export const AvailabilityZoneSelection = ({
3838

3939
const handleChoiceChange = (choice: RadioValueChangeDetail) => {
4040
if (choice.value) setChoice(choice.value as TChoice);
41+
if (choice.value === 'companyChoice') setValue('availabilityZone', null);
4142
};
4243

43-
useEffect(() => {
44-
if (choice === 'companyChoice')
45-
setValue('availabilityZone', 'companyChoice');
46-
}, [choice, setValue]);
47-
4844
useEffect(() => {
4945
if (!selectedAvailabilityZone) return;
5046

@@ -56,6 +52,8 @@ export const AvailabilityZoneSelection = ({
5652
setValue('availabilityZone', availabilityZones[0]);
5753
}, [availabilityZones, selectedAvailabilityZone, setValue]);
5854

55+
useEffect(() => setChoice('companyChoice'), [availabilityZones]);
56+
5957
return (
6058
<section className="pt-9 pb-5">
6159
<div className="flex flex-col gap-4">

packages/manager/apps/pci-instances/src/pages/instances/create/components/createInstanceForm/CreateInstanceForm.component.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export const CreateInstanceForm = () => {
3333
const microRegions = selectMicroRegions(deps)(projectId, macroRegion);
3434
const availabilityZones = selectAvailabilityZones(deps)(
3535
projectId,
36-
macroRegion,
36+
microRegions?.[0]?.value ?? null,
3737
);
3838

3939
const hasMultiMicroRegions = microRegions ? microRegions.length > 1 : false;

packages/manager/apps/pci-instances/src/pages/instances/create/components/localisationSelection/LocalizationSelection.component.tsx

Lines changed: 51 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ import { useProjectId } from '@/hooks/project/useProjectId';
1616
import { Controller, useFormContext, useWatch } from 'react-hook-form';
1717
import { TInstanceCreationForm } from '../../CreateInstance.page';
1818
import { useCallback, useEffect, useMemo, useState } from 'react';
19-
import { isMicroRegionAvailable } from '../../view-models/microRegionsViewModel';
19+
import {
20+
isMicroRegionAvailable,
21+
selectMicroRegions,
22+
} from '../../view-models/microRegionsViewModel';
2023
import clsx from 'clsx';
2124
import { useTranslation } from 'react-i18next';
2225
import { ContinentSelection } from '../continentSelection/ContinentSelection.component';
@@ -28,7 +31,7 @@ export const LocalizationSelection = () => {
2831
const { t } = useTranslation('creation');
2932

3033
const { control, setValue } = useFormContext<TInstanceCreationForm>();
31-
const [deploymentModes, selectedContinent, selectedRegion] = useWatch({
34+
const [deploymentModes, selectedContinent, selectedMacroRegion] = useWatch({
3235
control,
3336
name: ['deploymentModes', 'continent', 'macroRegion'],
3437
});
@@ -49,28 +52,41 @@ export const LocalizationSelection = () => {
4952
[projectId],
5053
);
5154

52-
const handleSelectRegion = (region: string | null) => {
53-
if (!region) return;
54-
setValue('macroRegion', region);
55+
const updateSelection = (macroRegion: string, microRegion: string) => {
56+
setValue('availabilityZone', null);
57+
setValue('macroRegion', macroRegion);
58+
setValue('microRegion', microRegion);
59+
5560
trackClick({
5661
location: PageLocation.funnel,
5762
buttonType: ButtonType.tile,
5863
actionType: 'action',
59-
actions: ['add_instance', 'select_localisation', region],
64+
actions: ['add_instance', 'select_localisation', microRegion],
6065
});
6166
};
6267

68+
const handleSelectRegion = (macroRegion: string | null) => {
69+
if (!macroRegion) return;
70+
const microRegions = selectMicroRegions(deps)(projectId, macroRegion);
71+
if (microRegions?.[0]) {
72+
updateSelection(macroRegion, microRegions[0].value);
73+
}
74+
};
75+
6376
const handleDisplayChange = () => setSeeAll(!seeAll);
6477

6578
useEffect(() => {
6679
const availablePreviousSelectedLocalization = localizations.find(
67-
(localization) => localization.region === selectedRegion,
80+
(localization) => localization.macroRegion === selectedMacroRegion,
6881
);
6982

70-
if (!availablePreviousSelectedLocalization && localizations[0]?.region) {
71-
setValue('macroRegion', localizations[0].region);
83+
if (
84+
!availablePreviousSelectedLocalization &&
85+
localizations[0]?.macroRegion
86+
) {
87+
setValue('macroRegion', localizations[0].macroRegion);
7288
}
73-
}, [localizations, selectedRegion, setValue]);
89+
}, [localizations, selectedMacroRegion, setValue]);
7490

7591
return (
7692
<section>
@@ -87,32 +103,46 @@ export const LocalizationSelection = () => {
87103
</CheckboxLabel>
88104
</Checkbox>
89105
</div>
90-
{selectedRegion && (
106+
{selectedMacroRegion && (
91107
<Controller
92108
name="macroRegion"
93109
control={control}
94110
render={() => (
95111
<div className="flex flex-col">
96112
<div className={clsx(seeAll && 'max-h-[450px] overflow-auto')}>
97113
<RadioGroup
98-
value={selectedRegion}
114+
value={selectedMacroRegion}
99115
onValueChange={({ value }) => handleSelectRegion(value)}
100116
>
101117
<div className="grid grid-cols-3 gap-6">
102118
{localizations.map(
103-
({ city, region, countryCode, deploymentMode }) =>
104-
region && (
119+
({
120+
city,
121+
datacenterDetails,
122+
macroRegion,
123+
microRegion,
124+
countryCode,
125+
deploymentMode,
126+
}) => {
127+
const displayCard =
128+
macroRegion && microRegion && datacenterDetails;
129+
130+
return displayCard ? (
105131
<LocalizationCard
106-
key={region}
107-
title={city}
108-
region={region}
132+
key={microRegion}
133+
city={city}
134+
datacenterDetails={datacenterDetails}
135+
macroRegion={macroRegion}
109136
countryCode={countryCode}
110137
deploymentMode={deploymentMode}
111-
onSelect={handleSelectRegion}
112-
isSelected={selectedRegion === region}
113-
disabled={!isRegionAvailable(region)}
138+
onSelect={() =>
139+
updateSelection(macroRegion, microRegion)
140+
}
141+
isSelected={selectedMacroRegion === macroRegion}
142+
disabled={!isRegionAvailable(macroRegion)}
114143
/>
115-
),
144+
) : null;
145+
},
116146
)}
117147
</div>
118148
</RadioGroup>

packages/manager/apps/pci-instances/src/pages/instances/create/hooks/useForm.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export const useForm = (projectId: string) => {
3030
'total',
3131
);
3232

33-
const macroRegionDefaultValue = localizations[0]!.region;
33+
const macroRegionDefaultValue = localizations[0]!.macroRegion;
3434

3535
const microRegionDefaultValue =
3636
localizations[0]!.microRegions[0]?.name ?? null;
@@ -42,8 +42,7 @@ export const useForm = (projectId: string) => {
4242
({ name }) => name === flavorCategoryDefaultValue,
4343
)?.type[0]?.name ?? '';
4444

45-
const availabilityZoneDefaultValue =
46-
localizations[0]!.microRegions[0]?.availabilityZones[0] ?? null;
45+
const availabilityZoneDefaultValue = null;
4746

4847
const formMethods = useReactHookForm({
4948
resolver: zodResolver(instanceCreationSchema),

0 commit comments

Comments
 (0)