Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

upcoming: [M3-7214 - M3-7216, M3-7219, M3-7221, M3-7222] - Add DC Get Well logic to various user flows pt1 #9943

Merged
merged 10 commits into from
Nov 30, 2023
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/manager": Upcoming Features
---

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))
Original file line number Diff line number Diff line change
Expand Up @@ -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',
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
13 changes: 9 additions & 4 deletions packages/manager/src/components/RegionSelect/RegionSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,12 +100,17 @@ export const RegionSelect = React.memo((props: RegionSelectProps) => {
Boolean(flags.dcGetWell) && Boolean(option.unavailable);
return (
<Tooltip
PopperProps={{
sx: { '& .MuiTooltip-tooltip': { minWidth: 215 } },
}}
title={
// TODO DC_GET_WELL: add proper link to status page when available
isDisabledMenuItem ? (
<>
For more information about regional availability, please see
our new <Link to="https://linode.com">status page</Link>.
There may be limited capacity in this region.{' '}
<Link to="https://www.linode.com/global-infrastructure/availability">
Learn more
</Link>
.
</>
) : (
''
Expand Down Expand Up @@ -133,7 +138,7 @@ export const RegionSelect = React.memo((props: RegionSelectProps) => {
<StyledFlagContainer>
<Flag country={option.data.country} />
</StyledFlagContainer>
{option.label} {isDisabledMenuItem && ' (Not available)'}
{option.label}
</Box>
{selected && <SelectedIcon visible={selected} />}
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,49 @@ 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[] = [];
Expand All @@ -53,33 +80,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);
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,13 @@ export const getRegionOptions = ({
currentCapability,
regions,
}: GetRegionOptions): RegionSelectOption[] => {
return regions
const filteredRegions = currentCapability
? regions.filter((region) =>
region.capabilities.includes(currentCapability)
)
: regions;

return filteredRegions
.map((region: Region) => {
const group = getRegionCountryGroup(region);

Expand Down
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -25,6 +25,7 @@ import { DynamicPriceNotice } from '../DynamicPriceNotice';
import { Link } from '../Link';

interface SelectRegionPanelProps {
currentCapability?: Capabilities | undefined;
disabled?: boolean;
error?: string;
handleSelection: (id: string) => void;
Expand All @@ -39,6 +40,7 @@ interface SelectRegionPanelProps {

export const SelectRegionPanel = (props: SelectRegionPanelProps) => {
const {
currentCapability,
disabled,
error,
handleSelection,
Expand Down Expand Up @@ -134,6 +136,7 @@ export const SelectRegionPanel = (props: SelectRegionPanelProps) => {
</Notice>
) : null}
<RegionSelect
currentCapability={currentCapability}
disabled={disabled}
errorText={error}
handleSelection={handleSelection}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ import {
useDatabaseTypesQuery,
} from 'src/queries/databases';
import { useRegionsQuery } from 'src/queries/regions';
import { regionsWithFeature } from 'src/utilities/doesRegionSupportFeature';
import { formatStorageUnits } from 'src/utilities/formatStorageUnits';
import { handleAPIErrors } from 'src/utilities/formikErrorUtils';
import { getSelectedOptionFromGroupedOptions } from 'src/utilities/getSelectedOptionFromGroupedOptions';
Expand Down Expand Up @@ -202,11 +201,6 @@ const DatabaseCreate = () => {
isLoading: regionsLoading,
} = useRegionsQuery();

const regionsThatSupportDbaas = regionsWithFeature(
regionsData ?? [],
'Managed Databases'
);

const {
data: engines,
error: enginesError,
Expand Down Expand Up @@ -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}
/>
<RegionHelperText mt={1} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,7 @@ export class LinodeCreate extends React.PureComponent<

{this.props.createType !== 'fromBackup' && (
<SelectRegionPanel
currentCapability="Linodes"
data-qa-select-region-panel
disabled={userCannotCreateLinode}
error={hasErrorFor.region}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ export const ConfigureForm = React.memo((props: Props) => {
textFieldProps={{
helperText,
}}
currentCapability="Linodes"
errorText={errorText}
handleSelection={handleSelectRegion}
label="New Region"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,7 @@ const NodeBalancerCreate = () => {
/>
</Paper>
<SelectRegionPanel
currentCapability="NodeBalancers"
disabled={disabled}
error={hasErrorFor('region')}
handleSelection={regionChange}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export const ClusterSelect: React.FC<Props> = (props) => {

return (
<RegionSelect
currentCapability="Object Storage"
data-qa-select-cluster
disabled={disabled}
errorText={errorText}
Expand Down
9 changes: 2 additions & 7 deletions packages/manager/src/features/Volumes/VolumeCreate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -297,18 +297,13 @@ export const VolumeCreate = () => {
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}
/>
Expand Down
4 changes: 2 additions & 2 deletions packages/manager/src/mocks/serverHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1020,11 +1020,11 @@ export const handlers = [
rest.get('*/account/availability', (req, res, ctx) => {
const newarkStorage = accountAvailabilityFactory.build({
id: 'us-east-0',
unavailable: ['Block Storage'],
unavailable: ['Object Storage'],
});
const atlanta = accountAvailabilityFactory.build({
id: 'us-southeast',
unavailable: ['Block Storage'],
unavailable: ['Block Storage', 'Managed Databases'],
});
const singapore = accountAvailabilityFactory.build({
id: 'ap-south',
Expand Down