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-7724] - Linode plan table updates for Edge regions #10255

Merged
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/manager": Upcoming Features
---

Linode plan table updates for Edge regions ([#10255](https://github.com/linode/manager/pull/10255))
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,11 @@ export class LinodeCreate extends React.PureComponent<
});
}

const linodeIsInEdgeRegion = getIsEdgeRegion(
regionsData,
selectedRegionID ?? ''
);

if (typeDisplayInfo) {
const typeDisplayInfoCopy = cloneDeep(typeDisplayInfo);

Expand All @@ -392,7 +397,17 @@ export class LinodeCreate extends React.PureComponent<
)}/month $${hourlyPrice ?? UNKNOWN_PRICE}/hr`;
}

displaySections.push(typeDisplayInfoCopy);
// @TODO Gecko: Remove $0 hardcoding once plan data is returned from API
if (linodeIsInEdgeRegion) {
displaySections.push({
...typeDisplayInfoCopy,
details: '$0/month',
hourly: 0,
monthly: 0,
});
} else {
displaySections.push(typeDisplayInfoCopy);
}
}

const type = typesData.find(
Expand All @@ -406,7 +421,12 @@ export class LinodeCreate extends React.PureComponent<
type,
});

if (hasBackups && typeDisplayInfo && backupsMonthlyPrice) {
if (
hasBackups &&
typeDisplayInfo &&
backupsMonthlyPrice &&
!linodeIsInEdgeRegion
) {
displaySections.push(
renderBackupsDisplaySection(accountBackupsEnabled, backupsMonthlyPrice)
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { styled } from '@mui/material/styles';
import { SxProps } from '@mui/system';
import React from 'react';

import { Box } from 'src/components/Box';
import { Notice } from 'src/components/Notice/Notice';
import { Paper } from 'src/components/Paper';
import { Typography } from 'src/components/Typography';

interface EdgePlanTableProps {
copy?: string;
docsLink?: JSX.Element;
error?: JSX.Element | string;
header: string;
innerClass?: string;
renderTable: () => React.JSX.Element;
rootClass?: string;
sx?: SxProps;
}

export const EdgePlanTable = React.memo((props: EdgePlanTableProps) => {
const {
copy,
docsLink,
error,
header,
innerClass,
renderTable,
rootClass,
sx,
} = props;

return (
<Paper
className={rootClass}
data-qa-tp={header}
sx={{ flexGrow: 1, ...sx }}
>
<div className={innerClass}>
<Box sx={{ display: 'flex', justifyContent: 'space-between' }}>
{header && (
<Typography data-qa-tp-title variant="h2">
{header}
</Typography>
)}
{docsLink}
</Box>
{error && (
<Notice spacingBottom={0} spacingTop={12} variant="error">
{error}
</Notice>
)}
{copy && <StyledTypography data-qa-tp-copy>{copy}</StyledTypography>}
{renderTable()}
</div>
</Paper>
);
});

const StyledTypography = styled(Typography)(({ theme }) => ({
fontSize: '0.875rem',
marginTop: theme.spacing(1),
}));
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { StyledDisabledTableRow } from './PlansPanel.styles';

import type { PlanSelectionType } from './types';
import type { LinodeTypeClass, PriceObject, Region } from '@linode/api-v4';

export interface PlanSelectionProps {
currentPlanHeading?: string;
disabled?: boolean;
Expand Down Expand Up @@ -206,7 +207,7 @@ export const PlanSelection = (props: PlanSelectionProps) => {
{type.vcpus}
</TableCell>
<TableCell center data-qa-storage noWrap>
{convertMegabytesTo(type.disk, true)}
{type.disk === 0 ? 'N/A' : convertMegabytesTo(type.disk, true)}
</TableCell>
{shouldShowTransfer && type.transfer ? (
<TableCell center data-qa-transfer>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import { useTheme } from '@mui/material/styles';
import * as React from 'react';
import { useLocation } from 'react-router-dom';

import { Notice } from 'src/components/Notice/Notice';
import { getIsLinodeCreateTypeEdgeSupported } from 'src/components/RegionSelect/RegionSelect.utils';
import { getIsEdgeRegion } from 'src/components/RegionSelect/RegionSelect.utils';
import { TabbedPanel } from 'src/components/TabbedPanel/TabbedPanel';
import { useFlags } from 'src/hooks/useFlags';
import { plansNoticesUtils } from 'src/utilities/planNotices';
import { getQueryParamsFromQueryString } from 'src/utilities/queryParams';

import { EdgePlanTable } from './EdgePlanTable';
import { PlanContainer } from './PlanContainer';
import { PlanInformation } from './PlanInformation';
import {
Expand All @@ -14,6 +21,8 @@ import {

import type { PlanSelectionType } from './types';
import type { LinodeTypeClass, Region } from '@linode/api-v4';
import type { LinodeCreateType } from 'src/features/Linodes/LinodesCreate/types';

interface Props {
className?: string;
copy?: string;
Expand Down Expand Up @@ -56,9 +65,50 @@ export const PlansPanel = (props: Props) => {
types,
} = props;

const flags = useFlags();
const theme = useTheme();
const location = useLocation();
const params = getQueryParamsFromQueryString(location.search);

const hideEdgeRegions =
!flags.gecko ||
!getIsLinodeCreateTypeEdgeSupported(params.type as LinodeCreateType);

const showEdgePlanTable =
!hideEdgeRegions &&
getIsEdgeRegion(regionsData ?? [], selectedRegionID ?? '');

const planTypes = getPlanSelectionsByPlanType(types);

const getDedicatedEdgePlanType = () => {
// 256gb and 512gb plans will not be supported for Edge
const plansUpTo128GB = planTypes.dedicated.filter(
(planType) =>
!['Dedicated 256 GB', 'Dedicated 512 GB'].includes(
planType.formattedLabel
)
);

return plansUpTo128GB.map((plan) => {
delete plan.transfer;
return {
...plan,
disk: 0,
price: {
hourly: 0,
monthly: 0,
},
};
});
};

// @TODO Gecko: Get plan data from API when it's available instead of hardcoding
const plans = showEdgePlanTable
? {
dedicated: getDedicatedEdgePlanType(),
}
: planTypes;

const plans = getPlanSelectionsByPlanType(types);
const {
hasSelectedRegion,
isPlanPanelDisabled,
Expand All @@ -83,6 +133,12 @@ export const PlansPanel = (props: Props) => {
planType={plan}
regionsData={regionsData || []}
/>
{showEdgePlanTable && (
<Notice
text="Edge region pricing is temporarily $0 during the beta period, after which standard pricing will begin."
variant="warning"
/>
)}
<PlanContainer
currentPlanHeading={currentPlanHeading}
disabled={disabled || isPlanPanelDisabled(plan)}
Expand All @@ -109,6 +165,22 @@ export const PlansPanel = (props: Props) => {
currentPlanHeading
);

if (showEdgePlanTable) {
return (
<EdgePlanTable
copy={copy}
data-qa-select-plan
docsLink={docsLink}
error={error}
header={header || 'Linode Plan'}
innerClass={props.tabbedPanelInnerClass}
renderTable={tabs[0].render}
rootClass={`${className} tabbedPanel`}
sx={{ marginTop: theme.spacing(3), width: '100%' }}
/>
);
}

return (
<TabbedPanel
copy={copy}
Expand Down
Loading