From f55faf4a14ef680a9868d8f2a54330eee0d246ce Mon Sep 17 00:00:00 2001 From: coliu-akamai Date: Tue, 28 Nov 2023 16:19:49 -0500 Subject: [PATCH 01/10] dc get well logic to various create flows --- .../components/SelectRegionPanel/SelectRegionPanel.tsx | 6 +++++- .../features/Databases/DatabaseCreate/DatabaseCreate.tsx | 9 ++------- .../src/features/Linodes/MigrateLinode/ConfigureForm.tsx | 1 + .../src/features/NodeBalancers/NodeBalancerCreate.tsx | 1 + .../ObjectStorage/BucketLanding/ClusterSelect.tsx | 1 + packages/manager/src/features/Volumes/VolumeCreate.tsx | 9 ++------- 6 files changed, 12 insertions(+), 15 deletions(-) diff --git a/packages/manager/src/components/SelectRegionPanel/SelectRegionPanel.tsx b/packages/manager/src/components/SelectRegionPanel/SelectRegionPanel.tsx index 1389eb7b750..057a807b5ee 100644 --- a/packages/manager/src/components/SelectRegionPanel/SelectRegionPanel.tsx +++ b/packages/manager/src/components/SelectRegionPanel/SelectRegionPanel.tsx @@ -1,4 +1,4 @@ -import { Region } from '@linode/api-v4/lib/regions'; +import { Capabilities, Region } from '@linode/api-v4/lib/regions'; import { useTheme } from '@mui/material'; import * as React from 'react'; import { useLocation } from 'react-router-dom'; @@ -25,6 +25,8 @@ import { DynamicPriceNotice } from '../DynamicPriceNotice'; import { Link } from '../Link'; interface SelectRegionPanelProps { + // TODO DC_GET_WELL: eventually we will make this prop required M3-7360 + currentCapability?: Capabilities | undefined; disabled?: boolean; error?: string; handleSelection: (id: string) => void; @@ -39,6 +41,7 @@ interface SelectRegionPanelProps { export const SelectRegionPanel = (props: SelectRegionPanelProps) => { const { + currentCapability, disabled, error, handleSelection, @@ -134,6 +137,7 @@ export const SelectRegionPanel = (props: SelectRegionPanelProps) => { ) : null} { isLoading: regionsLoading, } = useRegionsQuery(); - const regionsThatSupportDbaas = regionsWithFeature( - regionsData ?? [], - 'Managed Databases' - ); - const { data: engines, error: enginesError, @@ -507,8 +501,9 @@ const DatabaseCreate = () => { handleSelection={(selected: string) => setFieldValue('region', selected) } + currentCapability="Managed Databases" errorText={errors.region} - regions={regionsThatSupportDbaas} + regions={regionsData} selectedId={values.region} /> diff --git a/packages/manager/src/features/Linodes/MigrateLinode/ConfigureForm.tsx b/packages/manager/src/features/Linodes/MigrateLinode/ConfigureForm.tsx index d6065f47d0a..ed7b6bcc026 100644 --- a/packages/manager/src/features/Linodes/MigrateLinode/ConfigureForm.tsx +++ b/packages/manager/src/features/Linodes/MigrateLinode/ConfigureForm.tsx @@ -127,6 +127,7 @@ export const ConfigureForm = React.memo((props: Props) => { textFieldProps={{ helperText, }} + currentCapability="Linodes" errorText={errorText} handleSelection={handleSelectRegion} label="New Region" diff --git a/packages/manager/src/features/NodeBalancers/NodeBalancerCreate.tsx b/packages/manager/src/features/NodeBalancers/NodeBalancerCreate.tsx index d888fc149fa..d0b02bc6a13 100644 --- a/packages/manager/src/features/NodeBalancers/NodeBalancerCreate.tsx +++ b/packages/manager/src/features/NodeBalancers/NodeBalancerCreate.tsx @@ -479,6 +479,7 @@ const NodeBalancerCreate = () => { /> = (props) => { return ( { setFieldValue('region', value); setFieldValue('linode_id', null); }} - regions={ - regions?.filter((eachRegion) => - eachRegion.capabilities.some((eachCape) => - eachCape.match(/block/i) - ) - ) ?? [] - } + currentCapability="Block Storage" disabled={doesNotHavePermission} errorText={touched.region ? errors.region : undefined} isClearable label="Region" onBlur={handleBlur} + regions={regions ?? []} selectedId={values.region} width={400} /> From be6517fdc5edb24f91655ab4e75587c9c743b5d4 Mon Sep 17 00:00:00 2001 From: coliu-akamai Date: Tue, 28 Nov 2023 16:49:48 -0500 Subject: [PATCH 02/10] linode create flow dc get well --- .../manager/src/features/Linodes/LinodesCreate/LinodeCreate.tsx | 1 + packages/manager/src/mocks/serverHandlers.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/manager/src/features/Linodes/LinodesCreate/LinodeCreate.tsx b/packages/manager/src/features/Linodes/LinodesCreate/LinodeCreate.tsx index c91612a0180..78c62a58cfa 100644 --- a/packages/manager/src/features/Linodes/LinodesCreate/LinodeCreate.tsx +++ b/packages/manager/src/features/Linodes/LinodesCreate/LinodeCreate.tsx @@ -545,6 +545,7 @@ export class LinodeCreate extends React.PureComponent< {this.props.createType !== 'fromBackup' && ( { const newarkStorage = accountAvailabilityFactory.build({ id: 'us-east-0', - unavailable: ['Block Storage'], + unavailable: ['Object Storage'], }); const atlanta = accountAvailabilityFactory.build({ id: 'us-southeast', From f1583d12dd2fab291be1a19504131c7f9844c4a3 Mon Sep 17 00:00:00 2001 From: coliu-akamai Date: Tue, 28 Nov 2023 17:09:56 -0500 Subject: [PATCH 03/10] add logic to filter regions based on capability --- .../RegionSelect/RegionSelect.utils.test.tsx | 70 ++++++++++++------- .../RegionSelect/RegionSelect.utils.ts | 9 ++- 2 files changed, 54 insertions(+), 25 deletions(-) diff --git a/packages/manager/src/components/RegionSelect/RegionSelect.utils.test.tsx b/packages/manager/src/components/RegionSelect/RegionSelect.utils.test.tsx index 70f97abb9c4..df9f2ea51c4 100644 --- a/packages/manager/src/components/RegionSelect/RegionSelect.utils.test.tsx +++ b/packages/manager/src/components/RegionSelect/RegionSelect.utils.test.tsx @@ -18,22 +18,50 @@ const accountAvailabilityData = [ const regions: Region[] = [ regionFactory.build({ + capabilities: ['Linodes'], country: 'us', id: 'us-1', label: 'US Location', }), regionFactory.build({ + capabilities: ['Linodes'], country: 'ca', id: 'ca-1', label: 'CA Location', }), regionFactory.build({ + capabilities: ['Linodes'], country: 'jp', id: 'jp-1', label: 'JP Location', }), ]; +const expectedRegions: RegionSelectOption[] = [ + { + data: { country: 'ca', region: 'North America' }, + label: 'CA Location (ca-1)', + unavailable: false, + value: 'ca-1', + }, + { + data: { + country: 'us', + region: 'North America', + }, + label: 'US Location (us-1)', + unavailable: false, + value: 'us-1', + }, + + { + data: { country: 'jp', region: 'Asia' }, + label: 'JP Location (jp-1)', + unavailable: false, + value: 'jp-1', + }, +]; + describe('getRegionOptions', () => { it('should return an empty array if no regions are provided', () => { const regions: Region[] = []; @@ -53,33 +81,27 @@ describe('getRegionOptions', () => { regions, }); - // Expected result - const expected: RegionSelectOption[] = [ - { - data: { country: 'ca', region: 'North America' }, - label: 'CA Location (ca-1)', - unavailable: false, - value: 'ca-1', - }, - { - data: { - country: 'us', - region: 'North America', - }, - label: 'US Location (us-1)', - unavailable: false, - value: 'us-1', - }, + expect(result).toEqual(expectedRegions); + }); - { - data: { country: 'jp', region: 'Asia' }, - label: 'JP Location (jp-1)', - unavailable: false, - value: 'jp-1', - }, + it('should filter out regions that do not have the currentCapability if currentCapability is provided', () => { + const regionsToFilter: Region[] = [ + ...regions, + regionFactory.build({ + capabilities: ['Object Storage'], + country: 'pe', + id: 'peru-1', + label: 'Peru Location', + }), ]; - expect(result).toEqual(expected); + const result: RegionSelectOption[] = getRegionOptions({ + accountAvailabilityData, + currentCapability: 'Linodes', + regions: regionsToFilter, + }); + + expect(result).toEqual(expectedRegions); }); }); diff --git a/packages/manager/src/components/RegionSelect/RegionSelect.utils.ts b/packages/manager/src/components/RegionSelect/RegionSelect.utils.ts index 605213f1c22..7d88e613d1a 100644 --- a/packages/manager/src/components/RegionSelect/RegionSelect.utils.ts +++ b/packages/manager/src/components/RegionSelect/RegionSelect.utils.ts @@ -26,7 +26,14 @@ export const getRegionOptions = ({ currentCapability, regions, }: GetRegionOptions): RegionSelectOption[] => { - return regions + // TODO DC_GET_WELL - when currentCapability becomes a requiredProp, we can remove the extra `filteredRegions` constant and filter directly on `regions` + const filteredRegions = currentCapability + ? regions.filter((region) => + region.capabilities.includes(currentCapability) + ) + : regions; + + return filteredRegions .map((region: Region) => { const group = getRegionCountryGroup(region); From 443374b6ed2cfe8b5eb22a203fd16d32fcd6c179 Mon Sep 17 00:00:00 2001 From: coliu-akamai Date: Tue, 28 Nov 2023 17:13:36 -0500 Subject: [PATCH 04/10] changeset, update comment --- .../.changeset/pr-9943-upcoming-features-1701209599920.md | 5 +++++ .../src/components/SelectRegionPanel/SelectRegionPanel.tsx | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 packages/manager/.changeset/pr-9943-upcoming-features-1701209599920.md diff --git a/packages/manager/.changeset/pr-9943-upcoming-features-1701209599920.md b/packages/manager/.changeset/pr-9943-upcoming-features-1701209599920.md new file mode 100644 index 00000000000..95b840f72d0 --- /dev/null +++ b/packages/manager/.changeset/pr-9943-upcoming-features-1701209599920.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Upcoming Features +--- + +Add DC Get Well logic to various user flows pt1 ([#9943](https://github.com/linode/manager/pull/9943)) diff --git a/packages/manager/src/components/SelectRegionPanel/SelectRegionPanel.tsx b/packages/manager/src/components/SelectRegionPanel/SelectRegionPanel.tsx index 057a807b5ee..43e45685483 100644 --- a/packages/manager/src/components/SelectRegionPanel/SelectRegionPanel.tsx +++ b/packages/manager/src/components/SelectRegionPanel/SelectRegionPanel.tsx @@ -25,7 +25,7 @@ import { DynamicPriceNotice } from '../DynamicPriceNotice'; import { Link } from '../Link'; interface SelectRegionPanelProps { - // TODO DC_GET_WELL: eventually we will make this prop required M3-7360 + // TODO DC_GET_WELL: eventually we will make this prop required M3-7355 currentCapability?: Capabilities | undefined; disabled?: boolean; error?: string; From 5f21ca80c6f636198ad62e028b97c0a109c9ed52 Mon Sep 17 00:00:00 2001 From: coliu-akamai Date: Wed, 29 Nov 2023 09:18:14 -0500 Subject: [PATCH 05/10] slight cleanup --- .../.changeset/pr-9943-upcoming-features-1701209599920.md | 2 +- .../src/components/RegionSelect/RegionSelect.utils.test.tsx | 1 - .../manager/src/components/RegionSelect/RegionSelect.utils.ts | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/manager/.changeset/pr-9943-upcoming-features-1701209599920.md b/packages/manager/.changeset/pr-9943-upcoming-features-1701209599920.md index 95b840f72d0..20be155cf30 100644 --- a/packages/manager/.changeset/pr-9943-upcoming-features-1701209599920.md +++ b/packages/manager/.changeset/pr-9943-upcoming-features-1701209599920.md @@ -2,4 +2,4 @@ "@linode/manager": Upcoming Features --- -Add DC Get Well logic to various user flows pt1 ([#9943](https://github.com/linode/manager/pull/9943)) +Add logic to prevent new customers in regions to various user flows for DC Get Well initiative pt1 ([#9943](https://github.com/linode/manager/pull/9943)) diff --git a/packages/manager/src/components/RegionSelect/RegionSelect.utils.test.tsx b/packages/manager/src/components/RegionSelect/RegionSelect.utils.test.tsx index df9f2ea51c4..cf2e8fdefe6 100644 --- a/packages/manager/src/components/RegionSelect/RegionSelect.utils.test.tsx +++ b/packages/manager/src/components/RegionSelect/RegionSelect.utils.test.tsx @@ -53,7 +53,6 @@ const expectedRegions: RegionSelectOption[] = [ unavailable: false, value: 'us-1', }, - { data: { country: 'jp', region: 'Asia' }, label: 'JP Location (jp-1)', diff --git a/packages/manager/src/components/RegionSelect/RegionSelect.utils.ts b/packages/manager/src/components/RegionSelect/RegionSelect.utils.ts index 7d88e613d1a..a58fdb0a170 100644 --- a/packages/manager/src/components/RegionSelect/RegionSelect.utils.ts +++ b/packages/manager/src/components/RegionSelect/RegionSelect.utils.ts @@ -26,7 +26,7 @@ export const getRegionOptions = ({ currentCapability, regions, }: GetRegionOptions): RegionSelectOption[] => { - // TODO DC_GET_WELL - when currentCapability becomes a requiredProp, we can remove the extra `filteredRegions` constant and filter directly on `regions` + // TODO DC_GET_WELL - when currentCapability becomes a required prop (M3-7355), we can remove the extra `filteredRegions` constant and filter directly on `regions` const filteredRegions = currentCapability ? regions.filter((region) => region.capabilities.includes(currentCapability) From 96fc62d54657caf97f403a146a347d4e31ec3fb5 Mon Sep 17 00:00:00 2001 From: coliu-akamai Date: Wed, 29 Nov 2023 09:48:18 -0500 Subject: [PATCH 06/10] disable region for dbaas --- packages/manager/src/mocks/serverHandlers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/manager/src/mocks/serverHandlers.ts b/packages/manager/src/mocks/serverHandlers.ts index ad646789c7a..ef9ca6d7023 100644 --- a/packages/manager/src/mocks/serverHandlers.ts +++ b/packages/manager/src/mocks/serverHandlers.ts @@ -1024,7 +1024,7 @@ export const handlers = [ }); const atlanta = accountAvailabilityFactory.build({ id: 'us-southeast', - unavailable: ['Block Storage'], + unavailable: ['Block Storage', 'Managed Databases'], }); const singapore = accountAvailabilityFactory.build({ id: 'ap-south', From cd27c42bb92e69f0e0a7ab9e6a546b39b7ff58b2 Mon Sep 17 00:00:00 2001 From: coliu-akamai Date: Wed, 29 Nov 2023 12:04:16 -0500 Subject: [PATCH 07/10] fix e2e tests: specify capabilities --- .../e2e/core/linodes/create-linode.spec.ts | 4 ++++ .../enable-object-storage.spec.ts | 18 +++++++++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/packages/manager/cypress/e2e/core/linodes/create-linode.spec.ts b/packages/manager/cypress/e2e/core/linodes/create-linode.spec.ts index 6d037eb7bff..315e40a73e5 100644 --- a/packages/manager/cypress/e2e/core/linodes/create-linode.spec.ts +++ b/packages/manager/cypress/e2e/core/linodes/create-linode.spec.ts @@ -33,20 +33,24 @@ import { makeFeatureFlagData } from 'support/util/feature-flags'; const mockRegions: Region[] = [ regionFactory.build({ + capabilities: ['Linodes'], country: 'uk', id: 'eu-west', label: 'London, UK', }), regionFactory.build({ + capabilities: ['Linodes'], country: 'sg', id: 'ap-south', label: 'Singapore, SG', }), regionFactory.build({ + capabilities: ['Linodes'], id: 'us-east', label: 'Newark, NJ', }), regionFactory.build({ + capabilities: ['Linodes'], id: 'us-central', label: 'Dallas, TX', }), diff --git a/packages/manager/cypress/e2e/core/objectStorage/enable-object-storage.spec.ts b/packages/manager/cypress/e2e/core/objectStorage/enable-object-storage.spec.ts index e8de3c04f94..8787747900f 100644 --- a/packages/manager/cypress/e2e/core/objectStorage/enable-object-storage.spec.ts +++ b/packages/manager/cypress/e2e/core/objectStorage/enable-object-storage.spec.ts @@ -72,9 +72,21 @@ describe('Object Storage enrollment', () => { }; const mockRegions: Region[] = [ - regionFactory.build({ label: 'Newark, NJ', id: 'us-east' }), - regionFactory.build({ label: 'Sao Paulo, BR', id: 'br-gru' }), - regionFactory.build({ label: 'Jakarta, ID', id: 'id-cgk' }), + regionFactory.build({ + capabilities: ['Object Storage'], + label: 'Newark, NJ', + id: 'us-east', + }), + regionFactory.build({ + capabilities: ['Object Storage'], + label: 'Sao Paulo, BR', + id: 'br-gru', + }), + regionFactory.build({ + capabilities: ['Object Storage'], + label: 'Jakarta, ID', + id: 'id-cgk', + }), ]; // Clusters with special pricing are currently hardcoded rather than From 8b3dd0ad18e13b2a9da25844b66b5609a3ebb697 Mon Sep 17 00:00:00 2001 From: coliu-akamai Date: Wed, 29 Nov 2023 15:44:02 -0500 Subject: [PATCH 08/10] tooltip confirmed copy and link :D --- .../src/components/RegionSelect/RegionSelect.tsx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/manager/src/components/RegionSelect/RegionSelect.tsx b/packages/manager/src/components/RegionSelect/RegionSelect.tsx index ff7d01d38ad..f77aba8f2f2 100644 --- a/packages/manager/src/components/RegionSelect/RegionSelect.tsx +++ b/packages/manager/src/components/RegionSelect/RegionSelect.tsx @@ -101,11 +101,13 @@ export const RegionSelect = React.memo((props: RegionSelectProps) => { return ( - For more information about regional availability, please see - our new status page. + There may be limited capacity in this region.{' '} + + Learn more + + . ) : ( '' @@ -133,7 +135,7 @@ export const RegionSelect = React.memo((props: RegionSelectProps) => { - {option.label} {isDisabledMenuItem && ' (Not available)'} + {option.label} {selected && } From c808a5c1674db42d90221ab0a86a9499fbb2b3c0 Mon Sep 17 00:00:00 2001 From: coliu-akamai Date: Wed, 29 Nov 2023 16:31:41 -0500 Subject: [PATCH 09/10] update tooltip width --- packages/manager/src/components/RegionSelect/RegionSelect.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/manager/src/components/RegionSelect/RegionSelect.tsx b/packages/manager/src/components/RegionSelect/RegionSelect.tsx index f77aba8f2f2..ed2e3d01b24 100644 --- a/packages/manager/src/components/RegionSelect/RegionSelect.tsx +++ b/packages/manager/src/components/RegionSelect/RegionSelect.tsx @@ -100,6 +100,9 @@ export const RegionSelect = React.memo((props: RegionSelectProps) => { Boolean(flags.dcGetWell) && Boolean(option.unavailable); return ( From cab1a593466616c1af5c81c01cdf9e33bfd189ca Mon Sep 17 00:00:00 2001 From: coliu-akamai Date: Thu, 30 Nov 2023 10:28:23 -0500 Subject: [PATCH 10/10] remove comments I added in this PR - will remove rest of dc get well required prop comments in pt2 --- .../manager/src/components/RegionSelect/RegionSelect.utils.ts | 1 - .../src/components/SelectRegionPanel/SelectRegionPanel.tsx | 1 - 2 files changed, 2 deletions(-) diff --git a/packages/manager/src/components/RegionSelect/RegionSelect.utils.ts b/packages/manager/src/components/RegionSelect/RegionSelect.utils.ts index a58fdb0a170..a5fb1769f4a 100644 --- a/packages/manager/src/components/RegionSelect/RegionSelect.utils.ts +++ b/packages/manager/src/components/RegionSelect/RegionSelect.utils.ts @@ -26,7 +26,6 @@ export const getRegionOptions = ({ currentCapability, regions, }: GetRegionOptions): RegionSelectOption[] => { - // TODO DC_GET_WELL - when currentCapability becomes a required prop (M3-7355), we can remove the extra `filteredRegions` constant and filter directly on `regions` const filteredRegions = currentCapability ? regions.filter((region) => region.capabilities.includes(currentCapability) diff --git a/packages/manager/src/components/SelectRegionPanel/SelectRegionPanel.tsx b/packages/manager/src/components/SelectRegionPanel/SelectRegionPanel.tsx index 43e45685483..6e507165703 100644 --- a/packages/manager/src/components/SelectRegionPanel/SelectRegionPanel.tsx +++ b/packages/manager/src/components/SelectRegionPanel/SelectRegionPanel.tsx @@ -25,7 +25,6 @@ import { DynamicPriceNotice } from '../DynamicPriceNotice'; import { Link } from '../Link'; interface SelectRegionPanelProps { - // TODO DC_GET_WELL: eventually we will make this prop required M3-7355 currentCapability?: Capabilities | undefined; disabled?: boolean; error?: string;