Skip to content

Commit

Permalink
refactor: [M3-8080] - Linode Create Refactor - Add API/CLI Modal (#10442
Browse files Browse the repository at this point in the history
)

* initial work to add modal and button

* initial work to add modal and button

* add unit testing

* fix VPC issues

* fix console error

* fix form values being modified by resolvers

---------

Co-authored-by: Banks Nussman <banks@nussman.us>
  • Loading branch information
bnussman-akamai and bnussman committed May 14, 2024
1 parent e1e0bd8 commit 013dc2b
Show file tree
Hide file tree
Showing 8 changed files with 70 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ export const CopyTooltip = (props: CopyTooltipProps) => {

const StyledCopyButton = styled('button', {
label: 'StyledCopyButton',
shouldForwardProp: omittedProps(['copyableText', 'text']),
shouldForwardProp: omittedProps(['copyableText', 'text', 'onClickCallback']),
})<Omit<CopyTooltipProps, 'text'>>(({ theme, ...props }) => ({
'& svg': {
color: theme.color.grey1,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from 'react';

import { renderWithThemeAndHookFormContext } from 'src/utilities/testHelpers';

import { Actions } from './Actions';

describe('Actions', () => {
it('should render a create button', () => {
const { getByText } = renderWithThemeAndHookFormContext({
component: <Actions />,
});

const button = getByText('Create Linode').closest('button');

expect(button).toBeVisible();
expect(button).toHaveAttribute('type', 'submit');
expect(button).toBeEnabled();
});
it("should render a 'Create using command line' button", () => {
const { getByText } = renderWithThemeAndHookFormContext({
component: <Actions />,
});

const button = getByText('Create Using Command Line').closest('button');

expect(button).toBeVisible();
expect(button).toBeEnabled();
});
});
29 changes: 26 additions & 3 deletions packages/manager/src/features/Linodes/LinodeCreatev2/Actions.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,38 @@
import { CreateLinodeRequest } from '@linode/api-v4';
import React from 'react';
import React, { useState } from 'react';
import { useFormContext } from 'react-hook-form';

import { Box } from 'src/components/Box';
import { Button } from 'src/components/Button/Button';
import { useRestrictedGlobalGrantCheck } from 'src/hooks/useRestrictedGlobalGrantCheck';

import { ApiAwarenessModal } from '../LinodesCreate/ApiAwarenessModal/ApiAwarenessModal';
import { getLinodeCreatePayload } from './utilities';

export const Actions = () => {
const { formState } = useFormContext<CreateLinodeRequest>();
const [isAPIAwarenessModalOpen, setIsAPIAwarenessModalOpen] = useState(false);

const {
formState,
getValues,
trigger,
} = useFormContext<CreateLinodeRequest>();

const isLinodeCreateRestricted = useRestrictedGlobalGrantCheck({
globalGrantType: 'add_linodes',
});

const onOpenAPIAwareness = async () => {
if (await trigger(undefined, { shouldFocus: true })) {
setIsAPIAwarenessModalOpen(true);
}
};

return (
<Box sx={{ display: 'flex', justifyContent: 'flex-end' }}>
<Box sx={{ display: 'flex', gap: 1, justifyContent: 'flex-end' }}>
<Button buttonType="outlined" onClick={onOpenAPIAwareness}>
Create Using Command Line
</Button>
<Button
buttonType="primary"
disabled={isLinodeCreateRestricted}
Expand All @@ -23,6 +41,11 @@ export const Actions = () => {
>
Create Linode
</Button>
<ApiAwarenessModal
isOpen={isAPIAwarenessModalOpen}
onClose={() => setIsAPIAwarenessModalOpen(false)}
payLoad={getLinodeCreatePayload(structuredClone(getValues()))}
/>
</Box>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const Region = () => {
RegionSelectProps={{
textFieldProps: {
inputRef: field.ref,
onBlur: field.onBlur,
},
}}
currentCapability="Linodes"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const resolver: Resolver<LinodeCreateFormValues> = async (
context,
options
) => {
const transformedValues = getLinodeCreatePayload(values);
const transformedValues = getLinodeCreatePayload(structuredClone(values));

const { errors } = await yupResolver(
CreateLinodeSchema,
Expand All @@ -37,7 +37,7 @@ export const stackscriptResolver: Resolver<LinodeCreateFormValues> = async (
context,
options
) => {
const transformedValues = getLinodeCreatePayload(values);
const transformedValues = getLinodeCreatePayload(structuredClone(values));

const { errors } = await yupResolver(
CreateLinodeFromStackScriptSchema,
Expand All @@ -57,7 +57,7 @@ export const cloneResolver: Resolver<LinodeCreateFormValues> = async (
context,
options
) => {
const transformedValues = getLinodeCreatePayload(values);
const transformedValues = getLinodeCreatePayload(structuredClone(values));

const { errors } = await yupResolver(
CreateLinodeByCloningSchema,
Expand All @@ -84,7 +84,7 @@ export const backupResolver: Resolver<LinodeCreateFormValues> = async (
context,
options
) => {
const transformedValues = getLinodeCreatePayload(values);
const transformedValues = getLinodeCreatePayload(structuredClone(values));

const { errors } = await yupResolver(
CreateLinodeFromBackupSchema,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ const defaultProps: ApiAwarenessModalProps = {
isOpen: false,
onClose: vi.fn(),
payLoad: { region: '', type: '' },
route: '',
};

const renderComponent = (overrideProps?: Partial<ApiAwarenessModalProps>) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { CreateLinodeRequest } from '@linode/api-v4/lib/linodes';
import { useTheme } from '@mui/material/styles';
import { styled } from '@mui/material/styles';
import { useTheme } from '@mui/material/styles';
import React, { useEffect, useMemo } from 'react';
import { useHistory } from 'react-router-dom';

Expand All @@ -9,26 +9,26 @@ import { Dialog } from 'src/components/Dialog/Dialog';
import { Link } from 'src/components/Link';
import { Notice } from 'src/components/Notice/Notice';
import { SafeTabPanel } from 'src/components/Tabs/SafeTabPanel';
import { TabLinkList } from 'src/components/Tabs/TabLinkList';
import { Tab } from 'src/components/Tabs/Tab';
import { TabList } from 'src/components/Tabs/TabList';
import { TabPanels } from 'src/components/Tabs/TabPanels';
import { Tabs } from 'src/components/Tabs/Tabs';
import { Typography } from 'src/components/Typography';
import { useInProgressEvents } from 'src/queries/events/events';
import { sendApiAwarenessClickEvent } from 'src/utilities/analytics';
import { generateCurlCommand } from 'src/utilities/generate-cURL';
import { generateCLICommand } from 'src/utilities/generate-cli';
import { generateCurlCommand } from 'src/utilities/generate-cURL';

import { CodeBlock } from '../CodeBlock/CodeBlock';

export interface ApiAwarenessModalProps {
isOpen: boolean;
onClose: () => void;
payLoad: CreateLinodeRequest;
route: string;
}

export const ApiAwarenessModal = (props: ApiAwarenessModalProps) => {
const { isOpen, onClose, payLoad, route } = props;
const { isOpen, onClose, payLoad } = props;

const theme = useTheme();
const history = useHistory();
Expand All @@ -52,12 +52,10 @@ export const ApiAwarenessModal = (props: ApiAwarenessModalProps) => {

const tabs = [
{
routeName: route,
title: 'cURL',
type: 'API',
},
{
routeName: route,
title: 'Linode CLI',
type: 'CLI',
},
Expand Down Expand Up @@ -94,7 +92,10 @@ export const ApiAwarenessModal = (props: ApiAwarenessModalProps) => {
the Cloud Manager create form.
</Typography>
<StyledTabs defaultIndex={0} onChange={handleTabChange}>
<TabLinkList tabs={tabs} />
<TabList>
<Tab>cURL</Tab>
<Tab>Linode CLI</Tab>
</TabList>
<TabPanels>
<SafeTabPanel index={0}>
<Typography sx={{ marginTop: theme.spacing(2) }} variant="body1">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -806,7 +806,6 @@ export class LinodeCreate extends React.PureComponent<
isOpen={showApiAwarenessModal}
onClose={handleShowApiAwarenessModal}
payLoad={this.getPayload()}
route={this.props.match.url}
/>
</StyledButtonGroupBox>
</Grid>
Expand Down

0 comments on commit 013dc2b

Please sign in to comment.